From b14f5cba19f71eb351476242509425183135f771 Mon Sep 17 00:00:00 2001 From: KV Date: Sun, 13 Sep 2020 06:09:32 +0200 Subject: [PATCH 01/10] Add -b BRANCH argument to the compare and restore commands Adding an optional -b BRANCH argument to build_examples.py to enable comparing to and restoring from any branch or commit. That will help when e.g. reversing an unfortunate commit of generated files. This solves part 2 of issue #167. --- src/wireviz/build_examples.py | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/wireviz/build_examples.py b/src/wireviz/build_examples.py index 10a4b1bf..095cc0a7 100755 --- a/src/wireviz/build_examples.py +++ b/src/wireviz/build_examples.py @@ -13,22 +13,23 @@ from wv_helper import open_file_write, open_file_read, open_file_append +dir = script_path.parent.parent.parent readme = 'readme.md' groups = { 'examples': { - 'path': Path(script_path).parent.parent.parent / 'examples', + 'path': dir / 'examples', 'prefix': 'ex', readme: [], # Include no files 'title': 'Example Gallery', }, 'tutorial' : { - 'path': Path(script_path).parent.parent.parent / 'tutorial', + 'path': dir / 'tutorial', 'prefix': 'tutorial', readme: ['md', 'yml'], # Include .md and .yml files 'title': 'WireViz Tutorial', }, 'demos' : { - 'path': Path(script_path).parent.parent.parent / 'examples', + 'path': dir / 'examples', 'prefix': 'demo', }, } @@ -96,17 +97,21 @@ def clean_generated(groupkeys): os.remove(filename) -def compare_generated(groupkeys, include_graphviz_output = False): +def compare_generated(groupkeys, branch = '', include_graphviz_output = False): + if branch: + branch = f' {branch.strip()}' compare_extensions = generated_extensions if include_graphviz_output else extensions_not_containing_graphviz_output for key in groupkeys: # collect and compare files for filename in collect_filenames('Comparing', key, compare_extensions): - cmd = f'git --no-pager diff "{filename}"' + cmd = f'git --no-pager diff{branch} -- "{filename}"' print(f' {cmd}') os.system(cmd) -def restore_generated(groupkeys): +def restore_generated(groupkeys, branch = ''): + if branch: + branch = f' {branch.strip()}' for key in groupkeys: # collect input YAML files filename_list = collect_filenames('Restoring', key, input_extensions) @@ -116,7 +121,7 @@ def restore_generated(groupkeys): filename_list.append(groups[key]['path'] / readme) # restore files for filename in filename_list: - cmd = f'git checkout -- "{filename}"' + cmd = f'git checkout{branch} -- "{filename}"' print(f' {cmd}') os.system(cmd) @@ -128,6 +133,8 @@ def parse_args(): help='what to do with the generated files (default: build)') parser.add_argument('-c', '--compare-graphviz-output', action='store_true', help='the Graphviz output is also compared (default: False)') + parser.add_argument('-b', '--branch', action='store', default='', + help='branch or commit to compare with or restore from') parser.add_argument('-g', '--groups', nargs='+', choices=groups.keys(), default=groups.keys(), help='the groups of generated files (default: all)') @@ -141,9 +148,9 @@ def main(): elif args.action == 'clean': clean_generated(args.groups) elif args.action == 'compare': - compare_generated(args.groups, args.compare_graphviz_output) + compare_generated(args.groups, args.branch, args.compare_graphviz_output) elif args.action == 'restore': - restore_generated(args.groups) + restore_generated(args.groups, args.branch) if __name__ == '__main__': From 83a467a4aa19f4d15f91f7deaa3016c00e7b87db Mon Sep 17 00:00:00 2001 From: KV Date: Sun, 13 Sep 2020 17:47:04 +0200 Subject: [PATCH 02/10] Add diff as an alias to the compare command When used to "git diff", it is easy to write "build_examples.py diff" instead of "build_examples.py compare" by a mistake. Therefore, "diff" is now an alias to "compare" so both commands will work. This solves part 3 of issue #167. --- src/wireviz/build_examples.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wireviz/build_examples.py b/src/wireviz/build_examples.py index 095cc0a7..942fd807 100755 --- a/src/wireviz/build_examples.py +++ b/src/wireviz/build_examples.py @@ -129,7 +129,7 @@ def restore_generated(groupkeys, branch = ''): def parse_args(): parser = argparse.ArgumentParser(description='Wireviz Example Manager',) parser.add_argument('action', nargs='?', action='store', - choices=['build','clean','compare','restore'], default='build', + choices=['build','clean','compare','diff','restore'], default='build', help='what to do with the generated files (default: build)') parser.add_argument('-c', '--compare-graphviz-output', action='store_true', help='the Graphviz output is also compared (default: False)') @@ -147,7 +147,7 @@ def main(): build_generated(args.groups) elif args.action == 'clean': clean_generated(args.groups) - elif args.action == 'compare': + elif args.action == 'compare' or args.action == 'diff': compare_generated(args.groups, args.branch, args.compare_graphviz_output) elif args.action == 'restore': restore_generated(args.groups, args.branch) From c4957f147510fef65135b64207d9c5407df32bf7 Mon Sep 17 00:00:00 2001 From: KV Date: Sat, 10 Oct 2020 18:44:37 +0200 Subject: [PATCH 03/10] Comment out unimplemented command line option It seems, that the current implementation ignores --generate-bom, and that parser.add_argument() code line is therefore commented out until it gets implemented to avoid any confusion. This solves part 1 of issue #167. --- src/wireviz/wireviz.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wireviz/wireviz.py b/src/wireviz/wireviz.py index 3adc0782..0bee9385 100755 --- a/src/wireviz/wireviz.py +++ b/src/wireviz/wireviz.py @@ -213,7 +213,7 @@ def parse_cmdline(): ) parser.add_argument('input_file', action='store', type=str, metavar='YAML_FILE') parser.add_argument('-o', '--output_file', action='store', type=str, metavar='OUTPUT') - parser.add_argument('--generate-bom', action='store_true', default=True) + # Not implemented: parser.add_argument('--generate-bom', action='store_true', default=True) parser.add_argument('--prepend-file', action='store', type=str, metavar='YAML_FILE') return parser.parse_args() From 7df8a4b7cfe322f62dbf55a1d6c7f506a5743e60 Mon Sep 17 00:00:00 2001 From: KV Date: Sat, 10 Oct 2020 20:35:20 +0200 Subject: [PATCH 04/10] Add command line options to show version number Add -V command line option (and --version as an alias) to both wireviz.py and build_examples.py that show version number. Move the version number from setup.py into __init__.py to access the same version number specification from all files needing it. This solves part 4 of issue #167. --- setup.py | 4 +++- src/wireviz/__init__.py | 3 +++ src/wireviz/build_examples.py | 3 ++- src/wireviz/wireviz.py | 3 ++- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 09621bb7..1a49016c 100644 --- a/setup.py +++ b/setup.py @@ -4,6 +4,8 @@ import os from setuptools import setup, find_packages +from src.wireviz import __version__ + project_name = 'wireviz' # Utility function to read the README file. @@ -15,7 +17,7 @@ def read(fname): setup( name=project_name, - version='0.1', + version=__version__, author='Daniel Rojas', #author_email='', description='Easily document cables and wiring harnesses', diff --git a/src/wireviz/__init__.py b/src/wireviz/__init__.py index e69de29b..c8f5000d 100644 --- a/src/wireviz/__init__.py +++ b/src/wireviz/__init__.py @@ -0,0 +1,3 @@ +# Please don't import anything in this file to avoid issues when it is imported in setup.py + +__version__ = '0.1.1' diff --git a/src/wireviz/build_examples.py b/src/wireviz/build_examples.py index 942fd807..5e594dae 100755 --- a/src/wireviz/build_examples.py +++ b/src/wireviz/build_examples.py @@ -9,7 +9,7 @@ script_path = Path(__file__).absolute() sys.path.insert(0, str(script_path.parent.parent)) # to find wireviz module -from wireviz import wireviz +from wireviz import wireviz, __version__ from wv_helper import open_file_write, open_file_read, open_file_append @@ -128,6 +128,7 @@ def restore_generated(groupkeys, branch = ''): def parse_args(): parser = argparse.ArgumentParser(description='Wireviz Example Manager',) + parser.add_argument('-V', '--version', action='version', version='%(prog)s - wireviz ' + __version__) parser.add_argument('action', nargs='?', action='store', choices=['build','clean','compare','diff','restore'], default='build', help='what to do with the generated files (default: build)') diff --git a/src/wireviz/wireviz.py b/src/wireviz/wireviz.py index 0bee9385..cac6aa0b 100755 --- a/src/wireviz/wireviz.py +++ b/src/wireviz/wireviz.py @@ -12,7 +12,7 @@ if __name__ == '__main__': sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) - +from wireviz import __version__ from wireviz.Harness import Harness from wireviz.wv_helper import expand, open_file_read @@ -211,6 +211,7 @@ def parse_cmdline(): parser = argparse.ArgumentParser( description='Generate cable and wiring harness documentation from YAML descriptions', ) + parser.add_argument('-V', '--version', action='version', version='%(prog)s ' + __version__) parser.add_argument('input_file', action='store', type=str, metavar='YAML_FILE') parser.add_argument('-o', '--output_file', action='store', type=str, metavar='OUTPUT') # Not implemented: parser.add_argument('--generate-bom', action='store_true', default=True) From 4782da47c9060304d61c947a1a6b6ab27aa53bb8 Mon Sep 17 00:00:00 2001 From: kvid Date: Wed, 14 Oct 2020 16:08:16 +0200 Subject: [PATCH 05/10] Add optional image to connectors and cables (#153) This image, with an optional caption below, is displayed in the lower section of the connector/cable node in the diagram - just above the notes if present. This solves the basic part of issue #27, and is a continuation of PR #137 that was closed due to changes in the base branch. --- docs/advanced_image_usage.md | 61 +++++++++++++++++++ examples/ex08.yml | 11 +++- examples/resources/cable-WH+BN+GN+shield.png | Bin 0 -> 4449 bytes examples/resources/stereo-phone-plug-TRS.png | Bin 0 -> 1933 bytes requirements.txt | 1 + setup.py | 1 + src/wireviz/DataClasses.py | 50 ++++++++++++++- src/wireviz/Harness.py | 6 +- src/wireviz/wireviz.py | 5 ++ src/wireviz/wv_helper.py | 42 ++++++++++++- 10 files changed, 172 insertions(+), 5 deletions(-) create mode 100644 docs/advanced_image_usage.md create mode 100644 examples/resources/cable-WH+BN+GN+shield.png create mode 100644 examples/resources/stereo-phone-plug-TRS.png diff --git a/docs/advanced_image_usage.md b/docs/advanced_image_usage.md new file mode 100644 index 00000000..5fd4288f --- /dev/null +++ b/docs/advanced_image_usage.md @@ -0,0 +1,61 @@ +# Advanced Image Usage + +In rare cases when the [ordinary image scaling functionality](syntax.md#images) is insufficient, a couple of extra optional image attributes can be set to offer extra image cell space and scaling functionality when combined with the image dimension attributes `width` and `height`, but in most cases their default values below are sufficient: +- `scale: ` (how an image will use the available cell space) is default `false` if no dimension is set, or `true` if only one dimension is set, or `both` if both dimensions are set. +- `fixedsize: ` (scale to fixed size or expand to minimum size) is default `false` when no dimension is set or if a `scale` value is set, and `true` otherwise. +- When `fixedsize` is true and only one dimension is set, then the other dimension is calculated using the image aspect ratio. If reading the aspect ratio fails, then 1:1 ratio is assumed. + +See explanations of all supported values for these attributes in subsections below. + +## The effect of `fixedsize` boolean values + +- When `false`, any `width` or `height` values are _minimum_ values used to expand the image cell size for more available space, but cell contents or other size demands in the table might expand this cell even more than specified by `width` or `height`. +- When `true`, both `width` and `height` values are required by Graphwiz and specify the fixed size of the image cell, distorting any image inside if it don't fit. Any borders are normally drawn around the fixed size, and therefore, WireViz enclose the image cell in an extra table without borders when `fixedsize` is true to keep the borders around the outer non-fixed cell. + +## The effect of `scale` string values: + +- When `false`, the image is not scaled. +- When `true`, the image is scaled proportionally to fit within the available image cell space. +- When `width`, the image width is expanded (height is normally unchanged) to fill the available image cell space width. +- When `height`, the image height is expanded (width is normally unchanged) to fill the available image cell space height. +- When `both`, both image width and height are expanded independently to fill the available image cell space. + +In all cases (except `true`) the image might get distorted when a specified fixed image cell size limits the available space to less than what an unscaled image needs. + +In the WireViz diagrams there are no other space demanding cells in the same row, and hence, there are never extra available image cell space height unless a greater image cell `height` also is set. + +## Usage examples + +All examples of `image` attribute combinations below also require the mandatory `src` attribute to be set. + +- Expand the image proportionally to fit within a minimum height and the node width: +```yaml + height: 100 # Expand image cell to this minimum height + fixedsize: false # Avoid scaling to a fixed size + # scale default value is true in this case +``` + +- Increase the space around the image by expanding the image cell space (width and/or height) to a larger value without scaling the image: +```yaml + width: 200 # Expand image cell to this minimum width + height: 100 # Expand image cell to this minimum height + scale: false # Avoid scaling the image + # fixedsize default value is false in this case +``` + +- Stretch the image width to fill the available space in the node: +```yaml + scale: width # Expand image width to fill the available image cell space + # fixedsize default value is false in this case +``` + +- Stretch the image height to a minimum value: +```yaml + height: 100 # Expand image cell to this minimum height + scale: height # Expand image height to fill the available image cell space + # fixedsize default value is false in this case +``` + +## How Graphviz support this image scaling + +The connector and cable nodes are rendered using a HTML `` containing an image cell `') elif row is not None: @@ -53,6 +55,30 @@ def nested_html_table(rows): html.append('
` with `width`, `height`, and `fixedsize` attributes containing an image `` with `src` and `scale` attributes. See also the [Graphviz doc](https://graphviz.org/doc/info/shapes.html#html), but note that WireViz uses default values as described above. diff --git a/examples/ex08.yml b/examples/ex08.yml index 2195c4a0..eea3976a 100644 --- a/examples/ex08.yml +++ b/examples/ex08.yml @@ -1,4 +1,5 @@ # contributed by @cocide +# and later extended to include images connectors: Key: @@ -7,14 +8,22 @@ connectors: pins: [T, R, S] pinlabels: [Dot, Dash, Ground] show_pincount: false + image: + src: resources/stereo-phone-plug-TRS.png + caption: Tip, Ring, and Sleeve cables: W1: gauge: 24 AWG length: 0.2 + color: BK # Cable jacket color color_code: DIN wirecount: 3 - shield: true + shield: SN # Matching the shield color in the image + image: + src: resources/cable-WH+BN+GN+shield.png + height: 70 # Scale the image size slightly down + caption: Cross-section connections: - diff --git a/examples/resources/cable-WH+BN+GN+shield.png b/examples/resources/cable-WH+BN+GN+shield.png new file mode 100644 index 0000000000000000000000000000000000000000..f854aeae4b491bc08185e34cd84f1084450c10d6 GIT binary patch literal 4449 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 literal 0 HcmV?d00001 diff --git a/requirements.txt b/requirements.txt index 93394812..92620aea 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,5 @@ . graphviz +pillow pyyaml setuptools \ No newline at end of file diff --git a/setup.py b/setup.py index 1a49016c..cd289742 100644 --- a/setup.py +++ b/setup.py @@ -25,6 +25,7 @@ def read(fname): long_description_content_type='text/markdown', install_requires=[ 'pyyaml', + 'pillow', 'graphviz', ], license='GPLv3', diff --git a/src/wireviz/DataClasses.py b/src/wireviz/DataClasses.py index 6b3b1e36..3ad84d21 100644 --- a/src/wireviz/DataClasses.py +++ b/src/wireviz/DataClasses.py @@ -2,11 +2,48 @@ # -*- coding: utf-8 -*- from typing import Optional, List, Any, Union -from dataclasses import dataclass, field -from wireviz.wv_helper import int2tuple +from dataclasses import dataclass, field, InitVar +from pathlib import Path +from wireviz.wv_helper import int2tuple, aspect_ratio from wireviz import wv_colors +@dataclass +class Image: + gv_dir: InitVar[Path] # Directory of .gv file injected as context during parsing + # Attributes of the image object : + src: str + scale: Optional[str] = None # false | true | width | height | both + # Attributes of the image cell containing the image: + width: Optional[int] = None + height: Optional[int] = None + fixedsize: Optional[bool] = None + # Contents of the text cell just below the image cell: + caption: Optional[str] = None + # See also HTML doc at https://graphviz.org/doc/info/shapes.html#html + + def __post_init__(self, gv_dir): + + if self.fixedsize is None: + # Default True if any dimension specified unless self.scale also is specified. + self.fixedsize = (self.width or self.height) and self.scale is None + + if self.scale is None: + self.scale = "false" if not self.width and not self.height \ + else "both" if self.width and self.height \ + else "true" # When only one dimension is specified. + + if self.fixedsize: + # If only one dimension is specified, compute the other + # because Graphviz requires both when fixedsize=True. + if self.height: + if not self.width: + self.width = self.height * aspect_ratio(gv_dir.joinpath(self.src)) + else: + if self.width: + self.height = self.width / aspect_ratio(gv_dir.joinpath(self.src)) + + @dataclass class Connector: name: str @@ -18,6 +55,7 @@ class Connector: type: Optional[str] = None subtype: Optional[str] = None pincount: Optional[int] = None + image: Optional[Image] = None notes: Optional[str] = None pinlabels: List[Any] = field(default_factory=list) pins: List[Any] = field(default_factory=list) @@ -29,6 +67,10 @@ class Connector: loops: List[Any] = field(default_factory=list) def __post_init__(self): + + if isinstance(self.image, dict): + self.image = Image(**self.image) + self.ports_left = False self.ports_right = False self.visible_pins = {} @@ -91,6 +133,7 @@ class Cable: color: Optional[str] = None wirecount: Optional[int] = None shield: bool = False + image: Optional[Image] = None notes: Optional[str] = None colors: List[Any] = field(default_factory=list) color_code: Optional[str] = None @@ -99,6 +142,9 @@ class Cable: def __post_init__(self): + if isinstance(self.image, dict): + self.image = Image(**self.image) + if isinstance(self.gauge, str): # gauge and unit specified try: g, u = self.gauge.split(' ') diff --git a/src/wireviz/Harness.py b/src/wireviz/Harness.py index af7946e3..e701425a 100644 --- a/src/wireviz/Harness.py +++ b/src/wireviz/Harness.py @@ -8,7 +8,7 @@ from wireviz.wv_helper import awg_equiv, mm2_equiv, tuplelist2tsv, \ nested_html_table, flatten2d, index_if_list, html_line_breaks, \ graphviz_line_breaks, remove_line_breaks, open_file_read, open_file_write, \ - manufacturer_info_field + html_image, html_caption, manufacturer_info_field from collections import Counter from typing import List from pathlib import Path @@ -98,6 +98,8 @@ def create_graph(self) -> Graph: f'{connector.pincount}-pin' if connector.show_pincount else None, connector.color, '' if connector.color else None], '' if connector.style != 'simple' else None, + [html_image(connector.image)], + [html_caption(connector.image)], [html_line_breaks(connector.notes)]] html.extend(nested_html_table(rows)) @@ -173,6 +175,8 @@ def create_graph(self) -> Graph: f'{cable.length} m' if cable.length > 0 else None, cable.color, '' if cable.color else None], '', + [html_image(cable.image)], + [html_caption(cable.image)], [html_line_breaks(cable.notes)]] html.extend(nested_html_table(rows)) diff --git a/src/wireviz/wireviz.py b/src/wireviz/wireviz.py index cac6aa0b..9ecef5a0 100755 --- a/src/wireviz/wireviz.py +++ b/src/wireviz/wireviz.py @@ -44,6 +44,11 @@ def parse(yaml_input: str, file_out: (str, Path) = None, return_types: (None, st if len(yaml_data[sec]) > 0: if ty == dict: for key, attribs in yaml_data[sec].items(): + # The Image dataclass might need to open an image file with a relative path. + image = attribs.get('image') + if isinstance(image, dict): + image['gv_dir'] = Path(file_out if file_out else '').parent # Inject context + if sec == 'connectors': if not attribs.get('autogenerate', False): harness.add_connector(name=key, **attribs) diff --git a/src/wireviz/wv_helper.py b/src/wireviz/wv_helper.py index 418060d2..32b8fb6b 100644 --- a/src/wireviz/wv_helper.py +++ b/src/wireviz/wv_helper.py @@ -34,6 +34,7 @@ def nested_html_table(rows): # input: list, each item may be scalar or list # output: a parent table with one child table per parent item that is list, and one cell per parent item that is scalar # purpose: create the appearance of one table, where cell widths are independent between rows + # attributes in any leading inside a list are injected into to the preceeding tag html = [] html.append('') for row in rows: @@ -43,7 +44,8 @@ def nested_html_table(rows): html.append('
') for cell in row: if cell is not None: - html.append(f' ') + # Inject attributes to the preceeding '.replace('>
{cell} tag where needed + html.append(f' {cell}
') html.append('
') return html +def html_image(image): + if not image: + return None + # The leading attributes belong to the preceeding tag. See where used below. + html = f'{html_size_attr(image)}>' + if image.fixedsize: + # Close the preceeding tag and enclose the image cell in a table without + # borders to avoid narrow borders when the fixed width < the node width. + html = f'''> + + +
+ ''' + return f'''{html_line_breaks(image.caption)}' if image and image.caption else None + +def html_size_attr(image): + # Return Graphviz HTML attributes to specify minimum or fixed size of a TABLE or TD object + return ((f' width="{image.width}"' if image.width else '') + + (f' height="{image.height}"' if image.height else '') + + ( ' fixedsize="true"' if image.fixedsize else '')) if image else '' + def expand(yaml_data): # yaml_data can be: @@ -132,6 +158,20 @@ def open_file_write(filename): def open_file_append(filename): return open(filename, 'a', encoding='UTF-8') + +def aspect_ratio(image_src): + try: + from PIL import Image + image = Image.open(image_src) + if image.width > 0 and image.height > 0: + return image.width / image.height + print(f'aspect_ratio(): Invalid image size {image.width} x {image.height}') + # ModuleNotFoundError and FileNotFoundError are the most expected, but all are handled equally. + except Exception as error: + print(f'aspect_ratio(): {type(error).__name__}: {error}') + return 1 # Assume 1:1 when unable to read actual image size + + def manufacturer_info_field(manufacturer, mpn): if manufacturer or mpn: return f'{manufacturer if manufacturer else "MPN"}{": " + str(mpn) if mpn else ""}' From 1809f73d58945231bd2e20a9cdf9902a6966ccf2 Mon Sep 17 00:00:00 2001 From: KV Date: Wed, 12 Aug 2020 18:15:04 +0200 Subject: [PATCH 06/10] Simplify colorbar using the same technique as html_image() Moving common code into html_colorbar() helper function. --- src/wireviz/Harness.py | 14 +++----------- src/wireviz/wv_helper.py | 4 ++++ 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/wireviz/Harness.py b/src/wireviz/Harness.py index e701425a..a29ce35b 100644 --- a/src/wireviz/Harness.py +++ b/src/wireviz/Harness.py @@ -8,7 +8,7 @@ from wireviz.wv_helper import awg_equiv, mm2_equiv, tuplelist2tsv, \ nested_html_table, flatten2d, index_if_list, html_line_breaks, \ graphviz_line_breaks, remove_line_breaks, open_file_read, open_file_write, \ - html_image, html_caption, manufacturer_info_field + html_colorbar, html_image, html_caption, manufacturer_info_field from collections import Counter from typing import List from pathlib import Path @@ -96,17 +96,13 @@ def create_graph(self) -> Graph: [html_line_breaks(connector.type), html_line_breaks(connector.subtype), f'{connector.pincount}-pin' if connector.show_pincount else None, - connector.color, '' if connector.color else None], + connector.color, html_colorbar(connector.color)], '' if connector.style != 'simple' else None, [html_image(connector.image)], [html_caption(connector.image)], [html_line_breaks(connector.notes)]] html.extend(nested_html_table(rows)) - if connector.color: # add color bar next to color info, if present - colorbar = f' bgcolor="{wv_colors.translate_color(connector.color, "HEX")}" width="4">' # leave out ' tag - html = [row.replace('>', colorbar) for row in html] - if connector.style != 'simple': pinhtml = [] pinhtml.append('') @@ -173,17 +169,13 @@ def create_graph(self) -> Graph: f'{cable.gauge} {cable.gauge_unit}{awg_fmt}' if cable.gauge else None, '+ S' if cable.shield else None, f'{cable.length} m' if cable.length > 0 else None, - cable.color, '' if cable.color else None], + cable.color, html_colorbar(cable.color)], '', [html_image(cable.image)], [html_caption(cable.image)], [html_line_breaks(cable.notes)]] html.extend(nested_html_table(rows)) - if cable.color: # add color bar next to color info, if present - colorbar = f' bgcolor="{wv_colors.translate_color(cable.color, "HEX")}" width="4">' # leave out ' tag - html = [row.replace('>', colorbar) for row in html] - wirehtml = [] wirehtml.append('
') # conductor table wirehtml.append(' ') diff --git a/src/wireviz/wv_helper.py b/src/wireviz/wv_helper.py index 32b8fb6b..8385f7e9 100644 --- a/src/wireviz/wv_helper.py +++ b/src/wireviz/wv_helper.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +from wireviz import wv_colors from typing import List awg_equiv_table = { @@ -55,6 +56,9 @@ def nested_html_table(rows): html.append('
 
') return html +def html_colorbar(color): + return f'' if color else None + def html_image(image): if not image: return None From b00040cdd93ddd1b8bfe21a1030118cc1cf5b7c7 Mon Sep 17 00:00:00 2001 From: KV Date: Sat, 10 Oct 2020 21:43:27 +0200 Subject: [PATCH 07/10] Add version number to output files with meta info Tag the .gv and .html output files with generator and version number. --- src/wireviz/Harness.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/wireviz/Harness.py b/src/wireviz/Harness.py index a29ce35b..f5ef5e54 100644 --- a/src/wireviz/Harness.py +++ b/src/wireviz/Harness.py @@ -3,7 +3,7 @@ from wireviz.DataClasses import Connector, Cable from graphviz import Graph -from wireviz import wv_colors, wv_helper +from wireviz import wv_colors, wv_helper, __version__ from wireviz.wv_colors import get_color_hex from wireviz.wv_helper import awg_equiv, mm2_equiv, tuplelist2tsv, \ nested_html_table, flatten2d, index_if_list, html_line_breaks, \ @@ -63,7 +63,7 @@ def connect(self, from_name: str, from_pin: (int, str), via_name: str, via_pin: def create_graph(self) -> Graph: dot = Graph() - dot.body.append('// Graph generated by WireViz') + dot.body.append('// Graph generated by WireViz ' + __version__) dot.body.append('// https://github.com/formatc1702/WireViz') font = 'arial' dot.attr('graph', rankdir='LR', @@ -296,7 +296,12 @@ def output(self, filename: (str, Path), view: bool = False, cleanup: bool = True # HTML output with open_file_write(f'{filename}.html') as file: file.write('\n') - file.write('') + file.write('\n') + file.write(' \n') + file.write(f' \n') + file.write(' Wireviz Diagram and BOM\n') + file.write('\n') file.write('

Diagram

') with open_file_read(f'{filename}.svg') as svg: From 7dcd1a7eebb5cb8ad14518d28f267e30b470111c Mon Sep 17 00:00:00 2001 From: KV Date: Thu, 15 Oct 2020 20:42:34 +0200 Subject: [PATCH 08/10] Define application name and URL only once The application name and URL was defined several places in the code, and the name was not written exactly the same everywhere. By using the same constants everywhere, consistency is obtained. --- setup.py | 8 +++----- src/wireviz/Harness.py | 11 +++++------ src/wireviz/__init__.py | 4 ++++ src/wireviz/build_examples.py | 8 ++++---- 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/setup.py b/setup.py index cd289742..af1b715f 100644 --- a/setup.py +++ b/setup.py @@ -4,9 +4,7 @@ import os from setuptools import setup, find_packages -from src.wireviz import __version__ - -project_name = 'wireviz' +from src.wireviz import __version__, CMD_NAME, APP_URL # Utility function to read the README file. # Used for the long_description. It's nice, because now 1) we have a top level @@ -16,7 +14,7 @@ def read(fname): return open(os.path.join(os.path.dirname(__file__), fname)).read() setup( - name=project_name, + name=CMD_NAME, version=__version__, author='Daniel Rojas', #author_email='', @@ -30,7 +28,7 @@ def read(fname): ], license='GPLv3', keywords='cable connector hardware harness wiring wiring-diagram wiring-harness', - url='https://github.com/formatc1702/WireViz', + url=APP_URL, package_dir={'': 'src'}, packages=find_packages('src'), entry_points={ diff --git a/src/wireviz/Harness.py b/src/wireviz/Harness.py index f5ef5e54..e597a153 100644 --- a/src/wireviz/Harness.py +++ b/src/wireviz/Harness.py @@ -3,7 +3,7 @@ from wireviz.DataClasses import Connector, Cable from graphviz import Graph -from wireviz import wv_colors, wv_helper, __version__ +from wireviz import wv_colors, wv_helper, __version__, APP_NAME, APP_URL from wireviz.wv_colors import get_color_hex from wireviz.wv_helper import awg_equiv, mm2_equiv, tuplelist2tsv, \ nested_html_table, flatten2d, index_if_list, html_line_breaks, \ @@ -63,8 +63,8 @@ def connect(self, from_name: str, from_pin: (int, str), via_name: str, via_pin: def create_graph(self) -> Graph: dot = Graph() - dot.body.append('// Graph generated by WireViz ' + __version__) - dot.body.append('// https://github.com/formatc1702/WireViz') + dot.body.append(f'// Graph generated by {APP_NAME} {__version__}') + dot.body.append(f'// {APP_URL}') font = 'arial' dot.attr('graph', rankdir='LR', ranksep='2', @@ -298,9 +298,8 @@ def output(self, filename: (str, Path), view: bool = False, cleanup: bool = True file.write('\n') file.write('\n') file.write(' \n') - file.write(f' \n') - file.write(' Wireviz Diagram and BOM\n') + file.write(f' \n') + file.write(f' {APP_NAME} Diagram and BOM\n') file.write('\n') file.write('

Diagram

') diff --git a/src/wireviz/__init__.py b/src/wireviz/__init__.py index c8f5000d..3f3bcf3c 100644 --- a/src/wireviz/__init__.py +++ b/src/wireviz/__init__.py @@ -1,3 +1,7 @@ # Please don't import anything in this file to avoid issues when it is imported in setup.py __version__ = '0.1.1' + +CMD_NAME = 'wireviz' # Lower case command and module name +APP_NAME = 'WireViz' # Application name in texts meant to be human readable +APP_URL = 'https://github.com/formatc1702/WireViz' diff --git a/src/wireviz/build_examples.py b/src/wireviz/build_examples.py index 5e594dae..4195b121 100755 --- a/src/wireviz/build_examples.py +++ b/src/wireviz/build_examples.py @@ -9,7 +9,7 @@ script_path = Path(__file__).absolute() sys.path.insert(0, str(script_path.parent.parent)) # to find wireviz module -from wireviz import wireviz, __version__ +from wireviz import wireviz, __version__, APP_NAME from wv_helper import open_file_write, open_file_read, open_file_append @@ -26,7 +26,7 @@ 'path': dir / 'tutorial', 'prefix': 'tutorial', readme: ['md', 'yml'], # Include .md and .yml files - 'title': 'WireViz Tutorial', + 'title': f'{APP_NAME} Tutorial', }, 'demos' : { 'path': dir / 'examples', @@ -127,8 +127,8 @@ def restore_generated(groupkeys, branch = ''): def parse_args(): - parser = argparse.ArgumentParser(description='Wireviz Example Manager',) - parser.add_argument('-V', '--version', action='version', version='%(prog)s - wireviz ' + __version__) + parser = argparse.ArgumentParser(description=f'{APP_NAME} Example Manager',) + parser.add_argument('-V', '--version', action='version', version=f'%(prog)s - {APP_NAME} {__version__}') parser.add_argument('action', nargs='?', action='store', choices=['build','clean','compare','diff','restore'], default='build', help='what to do with the generated files (default: build)') From fb17eae7a677c72f9f855b478eb5def0d4b9974b Mon Sep 17 00:00:00 2001 From: KV Date: Thu, 15 Oct 2020 20:56:05 +0200 Subject: [PATCH 09/10] Avoid errors from HTML validator The https://validator.w3.org/ reported Errors: The align attribute on the th/td element is obsolete. Use CSS instead. By replacing align="X" attributes with text-align:X; CSS equivalent, the validator now completes without any errors or warnings. This solves the remaining issues from #97. --- src/wireviz/Harness.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/wireviz/Harness.py b/src/wireviz/Harness.py index e597a153..8b401c21 100644 --- a/src/wireviz/Harness.py +++ b/src/wireviz/Harness.py @@ -316,14 +316,14 @@ def output(self, filename: (str, Path), view: bool = False, cleanup: bool = True file.write('') file.write('') for item in listy[0]: - file.write(f'') + file.write(f'') file.write('') for row in listy[1:]: file.write('') for i, item in enumerate(row): item_str = item.replace('\u00b2', '²') - align = 'align="right"' if listy[0][i] == 'Qty' else '' - file.write(f'') + align = 'text-align:right; ' if listy[0][i] == 'Qty' else '' + file.write(f'') file.write('') file.write('
{item}{item}
{item_str}{item_str}
') From c9cc94d6806b225bbf57f1e25cc381828e0c178e Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Mon, 20 Jul 2020 14:14:22 +0200 Subject: [PATCH 10/10] Improve documentation - Create `docs/` directory - Add syntax description (`syntax.md`) - Track changes since first release (`CHANGELOG.md`) - Expand contribution guidelines (`CONTRIBUTING.md`) - Improve main readme (`README.md`) - Add documentation for build script (`buildscript.md`) --- CHANGELOG.md | 29 --- CONTRIBUTING.md | 18 -- docs/CHANGELOG.md | 45 +++++ docs/CONTRIBUTING.md | 43 +++++ README.md => docs/README.md | 98 ++++++---- docs/buildscript.md | 36 ++++ docs/syntax.md | 344 ++++++++++++++++++++++++++++++++++++ setup.py | 2 +- 8 files changed, 534 insertions(+), 81 deletions(-) delete mode 100644 CHANGELOG.md delete mode 100644 CONTRIBUTING.md create mode 100644 docs/CHANGELOG.md create mode 100644 docs/CONTRIBUTING.md rename README.md => docs/README.md (50%) create mode 100644 docs/buildscript.md create mode 100644 docs/syntax.md diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 5192789a..00000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,29 +0,0 @@ -# Change Log - -## [0.2](https://github.com/formatc1702/WireViz/tree/v0.2) (2020-XX-XX) - -### Backward incompatible changes - -- Change names of connector attributes ([#77](https://github.com/formatc1702/WireViz/issues/77)) -- Remove ferrules as a separate connector type ([#78](https://github.com/formatc1702/WireViz/issues/78)) -- Change the way loops are defined ([#79](https://github.com/formatc1702/WireViz/issues/79)) - -### New features -- Add bidirectional AWG/mm2 conversion ([#41](https://github.com/formatc1702/WireViz/pull/41)) -- Add support for part numbers ([#11](https://github.com/formatc1702/WireViz/pull/11)) -- Add support for multicolored wires ([#17](https://github.com/formatc1702/WireViz/pull/17), [#96](https://github.com/formatc1702/WireViz/pull/96)) -- Add ability to export data directly to other programs ([#55](https://github.com/formatc1702/WireViz/pull/55)) -- Add support for line breaks in various fields ([#63](https://github.com/formatc1702/WireViz/issues/63)) -- Allow using connector pin names to define connections ([#72](https://github.com/formatc1702/WireViz/issues/72)) -- Make defining connection sets easier and more flexible ([#67](https://github.com/formatc1702/WireViz/issues/67)) - -### Misc. fixes - -- Improve BOM generation -- Add various input sanity checks - -### - -## [0.1](https://github.com/formatc1702/WireViz/tree/v0.1) (2020-06-29) - -- Initial release diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 7a94ac7e..00000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,18 +0,0 @@ -# Contribution Guidelines - -When contributing to this repository, please first discuss the change you -wish to make via issue, email, or any other method with the owners of this -repository before making a change. - -## Pull Requests - -1. Fork this repository to your repository -1. Clone the repository to your local machine -1. Checkout the `dev` branch -1. Make any changes to the code on the `dev` branch -1. Push your changes to your fork -1. Create new pull request - -## Documentation Strings - -Documentation strings are to follow the Google Style ([examples](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html)). diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md new file mode 100644 index 00000000..d97a40c9 --- /dev/null +++ b/docs/CHANGELOG.md @@ -0,0 +1,45 @@ +# Change Log + +## [0.2](https://github.com/formatc1702/WireViz/tree/v0.2) (2020-XX-XX) + +### Backward incompatible changes + +- Change names of connector attributes ([#77](https://github.com/formatc1702/WireViz/issues/77), [#105](https://github.com/formatc1702/WireViz/pull/105)) + - `pinnumbers` is now `pins` + - `pinout` is now `pinlabels` +- Remove ferrules as a separate connector type ([#78](https://github.com/formatc1702/WireViz/issues/78), [#102](https://github.com/formatc1702/WireViz/pull/102)) + - Simple connectors like ferrules are now defined using the `style: simple` attribute +- Change the way loops are defined ([#79](https://github.com/formatc1702/WireViz/issues/79), [#75](https://github.com/formatc1702/WireViz/pull/75)) + - Wires looping between two pins of the same connector are now handled via the connector's `loops` attribute. + +See the [syntax description](syntax.md) for details. + + +### New features +- Add bidirectional AWG/mm2 conversion ([#40](https://github.com/formatc1702/WireViz/issues/40), [#41](https://github.com/formatc1702/WireViz/pull/41)) +- Add support for part numbers ([#11](https://github.com/formatc1702/WireViz/pull/11), [#114](https://github.com/formatc1702/WireViz/issues/114), [#121](https://github.com/formatc1702/WireViz/pull/121)) +- Add support for multicolored wires ([#12](https://github.com/formatc1702/WireViz/issues/12), [#17](https://github.com/formatc1702/WireViz/pull/17), [#96](https://github.com/formatc1702/WireViz/pull/96), [#131](https://github.com/formatc1702/WireViz/issues/131), [#132](https://github.com/formatc1702/WireViz/pull/132)) +- Add support for images ([#27](https://github.com/formatc1702/WireViz/issues/27), [#153](https://github.com/formatc1702/WireViz/pull/153)) +- Add ability to export data directly to other programs ([#55](https://github.com/formatc1702/WireViz/pull/55)) +- Add support for line breaks in various fields ([#49](https://github.com/formatc1702/WireViz/issues/49), [#64](https://github.com/formatc1702/WireViz/pull/64)) +- Allow using connector pin names to define connections ([#72](https://github.com/formatc1702/WireViz/issues/72), [#139](https://github.com/formatc1702/WireViz/issues/139), [#140](https://github.com/formatc1702/WireViz/pull/140)) +- Make defining connection sets easier and more flexible ([#67](https://github.com/formatc1702/WireViz/issues/67), [#75](https://github.com/formatc1702/WireViz/pull/75)) +- Add new command line options ([#167](https://github.com/formatc1702/WireViz/issues/167), [#173](https://github.com/formatc1702/WireViz/pull/173)) +- Add new features to `build_examples.py` ([#118](https://github.com/formatc1702/WireViz/pull/118)) +- Add new colors ([#103](https://github.com/formatc1702/WireViz/pull/103), [#113](https://github.com/formatc1702/WireViz/pull/113), [#144](https://github.com/formatc1702/WireViz/issues/144), [#145](https://github.com/formatc1702/WireViz/pull/145)) +- Improve documentation ([#107](https://github.com/formatc1702/WireViz/issues/107), [#111](https://github.com/formatc1702/WireViz/pull/111)) + + +### Misc. fixes + +- Improve BOM generation +- Add various input sanity checks +- Improve HTML output ([#66](https://github.com/formatc1702/WireViz/issues/66), [#136](https://github.com/formatc1702/WireViz/pull/136), [#95](https://github.com/formatc1702/WireViz/pull/95)) +- Fix node rendering bug ([#69](https://github.com/formatc1702/WireViz/issues/69), [#104](https://github.com/formatc1702/WireViz/pull/104)) +- Improve shield rendering ([#125](https://github.com/formatc1702/WireViz/issues/125), [#126](https://github.com/formatc1702/WireViz/pull/126)) +- Add GitHub Linguist overrides ([#146](https://github.com/formatc1702/WireViz/issues/146), [#154](https://github.com/formatc1702/WireViz/pull/154)) + + +## [0.1](https://github.com/formatc1702/WireViz/tree/v0.1) (2020-06-29) + +- Initial release diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md new file mode 100644 index 00000000..b11c0696 --- /dev/null +++ b/docs/CONTRIBUTING.md @@ -0,0 +1,43 @@ +# Contribution Guidelines + +When contributing to this repository, please [submit a new issue](https://github.com/formatc1702/WireViz/issues) first to discuss the proposed change, before submitting a pull request. + +## Submitting a new Issue + +- First, search existing (open and closed) issues for any related issues. + - You might then find an existing answer or suggested solution to your issue, possibly also an existing PR you can test. + - When finding existing issues that seem related to your issue, please include references (# followed by issue number) to related issues in your new issue description, or if a very similar issue is still open, consider adding a comment in that issue instead of creating a new one. +- When appropriate, please prefix your issue title with one of these category prefixes followed by a space: + - **[bug]** When the issue seems to be caused by a bug. + - **[feature]** When requesting a feature change or new feature. + - **[internal]** When suggesting code improvements that doesn't change any output. + - **[doc]** For documentation issues. + - **[meta]** For issues about the development or contribution process. +- Please include enough information in the description to enable another user to reproduce any error state described in your issue: + - The versions of your WireViz, Graphviz (`dot -V`), Python (`python -V`), and operating system. + - The relevant input files unless (preferably) you can demonstrate the same issue using one of the example files. If your input file is large or complex, please try to find a smaller/simplified input that still can reproduce the same issue. + - Any warnings or error messages you get. +- See also [How We Write Github Issues](https://wiredcraft.com/blog/how-we-write-our-github-issues/) in general. + +## Submitting a new Pull Request + +1. Fork this repository and clone it on your local machine. +1. Create a new feature branch on top of the `dev` branch. +1. Commit your code changes to this feature branch. +1. Push the changes to your fork. +1. Submit a new pull request, using `dev` as the base branch. +1. Please include in the PR description (and optionally also in the commit message body) a reference (# followed by issue number) to the issue where the suggested changes are discussed. + +### Hints + +- Make sure to [write good commit messages](https://chris.beams.io/posts/git-commit/). +- Always consider `git rebase` before `git merge` when joining commits from different branches, to keep the commit history simple and easier to read. +- If the `dev` branch has advanced since your fork, consider rebasing onto the current state to avoid merge conflicts. +- Avoid committing changes to generated files in PRs (examples, tutorials, etc.) to reduce merging conflicts. The owner will rebuild them. +- For complex PRs, consider [interactively rebasing](https://thoughtbot.com/blog/git-interactive-rebase-squash-amend-rewriting-history) your contribution to remove intermediate commits and clean up the commit history. +- Feel free to submit a [draft PR](https://github.blog/2019-02-14-introducing-draft-pull-requests/) for your work-in-progress. This lets other contributors comment on and review your code, while clearly marking it as not ready for merging. + + +## Documentation Strings + +Documentation strings are to follow the Google Style ([examples](https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html)). diff --git a/README.md b/docs/README.md similarity index 50% rename from README.md rename to docs/README.md index e973b634..ad2e4aa3 100644 --- a/README.md +++ b/docs/README.md @@ -1,9 +1,15 @@ # WireViz + +[![PyPI - Version](https://img.shields.io/pypi/v/wireviz.svg?colorB=blue)](https://pypi.org/project/wireviz/) +[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/wireviz.svg?)](https://pypi.org/project/wireviz/) +[![PyPI - Downloads](https://img.shields.io/pypi/dm/wireviz)](https://pypi.org/project/wireviz/) + ## Summary WireViz is a tool for easily documenting cables, wiring harnesses and connector pinouts. It takes plain text, YAML-formatted files as input and produces beautiful graphical output (SVG, PNG, ...) thanks to [GraphViz](https://www.graphviz.org/). It handles automatic BOM (Bill of Materials) creation and has a lot of extra features. + ## Features * WireViz input files are fully text based @@ -13,37 +19,26 @@ WireViz is a tool for easily documenting cables, wiring harnesses and connector * YAML syntax * UTF-8 input and output files for special character support * Understands and uses color abbreviations as per [IEC 60757](https://en.wikipedia.org/wiki/Electronic_color_code#Color_band_system) (black=BK, red=RD, ...) - * Optionally outputs colors as abbreviation (e.g. 'YE'), full name (e.g. 'yellow') or hex value (e.g. '#ffff00'), with choice of UPPER or lower case + * Auto-generates standard wire color schemes and allows custom ones if needed * [DIN 47100](https://en.wikipedia.org/wiki/DIN_47100) (WT/BN/GN/YE/GY/PK/BU/RD/BK/VT/...) - * [IEC 62](https://en.wikipedia.org/wiki/Electronic_color_code#Color_band_system) (BN/RD/OR/YE/GN/BU/VT/GY/WT/BK/...) + * [IEC 60757](https://en.wikipedia.org/wiki/Electronic_color_code#Color_band_system) (BN/RD/OR/YE/GN/BU/VT/GY/WT/BK/...) * [25 Pair Color Code](https://en.wikipedia.org/wiki/25-pair_color_code#Color_coding) (BUWH/WHBU/OGWH/WHOG/GNWH/WHGN/BNWH/...) * [TIA/EIA 568 A/B](https://en.wikipedia.org/wiki/TIA/EIA-568#Wiring) (Subset of 25-Pair, used in CAT-5/6/...) * Understands wire gauge in mm² or AWG * Optionally auto-calculates equivalent gauge between mm² and AWG -* Allows more than one connector per side, as well as loopbacks +* Is suitable for both very simple cables, and more complex harnesses. * Allows for easy-autorouting for 1-to-1 wiring * Generates BOM (Bill of Materials) _Note_: WireViz is not designed to represent the complete wiring of a system. Its main aim is to document the construction of individual wires and harnesses. -## Installation - -WireWiz requires GraphViz to be installed in order to work. See the [GraphViz download page](https://graphviz.org/download/) for OS-specific instructions. - -Installation of the WireWiz package and its Python dependencies can be done using pip after cloning the repository: - -``` -git clone -cd -pip3 install -e . -``` ## Examples ### Demo 01 -[WireViz input file](examples/demo01.yml): +[WireViz input file](../examples/demo01.yml): ```yaml connectors: @@ -76,23 +71,56 @@ connections: Output file: -![Sample output diagram](examples/demo01.png) +![Sample output diagram](../examples/demo01.png) -[Bill of Materials](examples/demo01.bom.tsv) (auto-generated) +[Bill of Materials](../examples/demo01.bom.tsv) (auto-generated) ### Demo 02 -![](examples/demo02.png) +![](../examples/demo02.png) -[Source](examples/demo02.yml) - [Bill of Materials](examples/demo02.bom.tsv) +[Source](../examples/demo02.yml) - [Bill of Materials](../examples/demo02.bom.tsv) ### Tutorial and example gallery -See the [tutorial page](tutorial/readme.md) for sample code, -as well as the [example gallery](examples/readme.md) to see more of what WireViz can do. +See the [tutorial page](../tutorial/readme.md) for sample code, +as well as the [example gallery](../examples/readme.md) to see more of what WireViz can do. + ## Usage +### Installation + +#### Requirements + +WireViz requires Python 3.7 or later. + +WireWiz requires GraphViz to be installed in order to work. See the [GraphViz download page](https://graphviz.org/download/) for OS-specific instructions. + +_Note_: Ubuntu 18.04 LTS users in particular may need to separately install Python 3.7 or above, as that comes with Python 3.6 as the included system Python install. + +#### Installing the latest release + +The latest WireViz release can be downloaded from [PyPI](https://pypi.org/project/wireviz/) with the following command: +``` +pip3 install wireviz +``` + +#### Installing the development version + +Access to the current state of the development branch can be gained by cloning the repo and installing manually: + +``` +git clone +cd +git checkout dev +pip3 install -e . +``` + +If you would like to contribute to this project, make sure you read the [contribution guidelines](CONTRIBUTING.md)! + +### How to run + ``` $ wireviz ~/path/to/file/mywire.yml ``` @@ -107,29 +135,33 @@ mywire.bom.tsv BOM (bill of materials) as tab-separated text file mywire.html HTML page with wiring diagram and BOM embedded ``` -### (Re-)Building the example projects +#### Command line options -If you would like to rebuild all of the included demos, examples and tutorials, use the ```build_examples.py``` script: +- `--prepend-file ` to prepend an additional YAML file. Useful for part libraries and templates shared among multiple cables/harnesses. +- `-o ` or `--output_file ` to generate output files with a name different from the input file. +- `-V` or `--version` to display the WireViz version. +- `-h` or `--help` to see a summary of the usage help text. -```cd src/wireviz -./build_examples.py -``` +### Syntax description + +A description of the WireViz YAML input syntax can be found [here](syntax.md). + + +### (Re-)Building the example projects + +Please see the [documentation](buildscript.md) of the `build_examples.py` script for info on building the demos, examples and tutorial. ## Changelog See [CHANGELOG.md](CHANGELOG.md) -## Status -This is very much a [work in progress](https://github.com/formatc1702/WireViz/projects/1). Source code, API, syntax and functionality may change wildly at any time. - -## Requirements +## Status -Developed and tested using Python 3.7; might not work with older Python versions. +This is very much a work in progress. Source code, API, syntax and functionality may change wildly at any time. -Ubuntu 18.04 LTS users in particular may need to separately install Python 3.7 or above, as that comes with Python 3.6 as the included system Python install. ## License -[GPL-3.0](LICENSE) +[GPL-3.0](../LICENSE) diff --git a/docs/buildscript.md b/docs/buildscript.md new file mode 100644 index 00000000..2655770e --- /dev/null +++ b/docs/buildscript.md @@ -0,0 +1,36 @@ +# (Re-)Building the example projects + + + +## Commands + +- `python build_examples.py` to build generated files in all groups. +- `python build_examples.py compare` to compare generated files in all groups against the last commit. +- `python build_examples.py clean` to delete generated files in all groups. +- `python build_examples.py restore` to restore generated files in all groups from the last commit. +- `python build_examples.py -V` or `--version` to display the WireViz version. +- `python build_examples.py -h` or `--help` to see a summary of the usage help text. + + +## Options + +- Append `-b` or `--branch` followed by a specified branch or commit to compare with or restore from (default: The last commit in the current branch). +- Append `-c` or `--compare-graphviz-output` to the `compare` command above to also compare the Graphviz output (default: False). +- Append `-g` or `--groups` followed by space separated group names to any command above, and the set of generated files affected by the command will be limited to the selected groups. +Possible group names: + - `examples` to process `examples/{readme.md,ex*.*}` + - `tutorial` to process`tutorial/{readme.md,tutorial*.*}` + - `demos` to process`examples/demo*.*` + + Affected filetypes: `.gv`, `.bom.tsv`, `.png`, `.svg`, `.html` + + +## Usage hints + +- Run `python build_examples.py` after any code changes to verify that it still is possible to process YAML-input from all groups without errors. +- Run `python build_examples.py compare` after the rebuilding above to verify that the output differences are as expected after a code change. +- Run `python build_examples.py restore` before adding and committing to avoid including changes to generated files after the rebuilding above. diff --git a/docs/syntax.md b/docs/syntax.md new file mode 100644 index 00000000..a0a30c27 --- /dev/null +++ b/docs/syntax.md @@ -0,0 +1,344 @@ +# WireViz Syntax + +## Main sections + +```yaml +connectors: # dictionary of all used connectors + : # unique connector designator/name + ... # connector attributes (see below) + : + ... + ... + +cables: # dictionary of all used cables and wires + : # unique cable designator/name + ... # cable attributes (see below) + : + ... + ... + +connections: # list of all connections to be made + # between cables and connectors + - + ... # connection set (see below) + - + ... + ... + +additional_bom_items: # custom items to add to BOM + - # BOM item (see below) + ... + +``` + +## Connector attributes + +```yaml + : # unique connector designator/name + # general information about a connector (all optional) + type: + subtype: + color: # see below + image: # see below + notes: + + # product information (all optional) + pn: # [internal] part number + mpn: # manufacturer part number + manufacturer: # manufacturer name + + # pinout information + # at least one of the following must be specified + pincount: # if omitted, is set to length of specified list(s) + pins: # if omitted, is autofilled with [1, 2, ..., pincount] + pinlabels: # if omitted, is autofilled with blanks + + # rendering information (all optional) + style: