From 2dfdbd577a83e6f0a4c87a922b597cb1d02a8e1d Mon Sep 17 00:00:00 2001 From: Manuel Scholz Date: Tue, 23 Jun 2020 11:49:53 +0200 Subject: [PATCH 01/35] Update wv_helper.py Added bigger AWG sizes --- src/wv_helper.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/wv_helper.py b/src/wv_helper.py index 49b9c3d..1c803fd 100644 --- a/src/wv_helper.py +++ b/src/wv_helper.py @@ -16,6 +16,8 @@ def awg_equiv(mm2): '10': 8, '16': 6, '25': 4, + '35': 2, + '50': 1, } k = str(mm2) if k in awg_equiv_table: From c3621498a7cf3bac4d77aca5ae22a2bfa0620ade Mon Sep 17 00:00:00 2001 From: "Morrison-Reed Elliot (BEG/EVS1-NA)" Date: Wed, 24 Jun 2020 11:45:05 -0400 Subject: [PATCH 02/35] implemented functionality to hide pins that are not connected --- examples/ex07.bom.tsv | 4 ++ examples/ex07.gv | 16 +++++++ examples/ex07.html | 101 ++++++++++++++++++++++++++++++++++++++++++ examples/ex07.png | Bin 0 -> 25066 bytes examples/ex07.svg | 100 +++++++++++++++++++++++++++++++++++++++++ examples/ex07.yml | 25 +++++++++++ examples/readme.md | 6 +++ src/batch.py | 2 +- src/wireviz.py | 16 ++++++- 9 files changed, 268 insertions(+), 2 deletions(-) create mode 100644 examples/ex07.bom.tsv create mode 100644 examples/ex07.gv create mode 100644 examples/ex07.html create mode 100644 examples/ex07.png create mode 100644 examples/ex07.svg create mode 100644 examples/ex07.yml diff --git a/examples/ex07.bom.tsv b/examples/ex07.bom.tsv new file mode 100644 index 0000000..ff4b2d7 --- /dev/null +++ b/examples/ex07.bom.tsv @@ -0,0 +1,4 @@ +Item Qty Unit Designators +Connector, D-Sub, female, 9 pins 1 X2 +Connector, TE 776164-1, female, 35 pins 1 X1 +Cable, 2 x 20 AWG 1 m C1 diff --git a/examples/ex07.gv b/examples/ex07.gv new file mode 100644 index 0000000..80d892d --- /dev/null +++ b/examples/ex07.gv @@ -0,0 +1,16 @@ +graph { +// Graph generated by WireViz +// https://github.com/formatc1702/WireViz + graph [bgcolor=white fontname=arial nodesep=0.33 rankdir=LR ranksep=2] + node [fillcolor=white fontname=arial shape=record style=filled] + edge [fontname=arial style=bold] + X1 [label="X1|{TE 776164-1|female|35-pin}|{{5|6}}"] + X2 [label="X2|{D-Sub|female|9-pin}|{{2|7}}"] + edge [color="#000000:#ffff00:#000000"] + X1:p5r:e -- C1:w1:w + C1:w1:e -- X2:p7l:w + edge [color="#000000:#00ff00:#000000"] + X1:p6r:e -- C1:w2:w + C1:w2:e -- X2:p2l:w + C1 [label=<
C1
2x20 AWG1 m
 
X1:5YEX2:7
X1:6GNX2:2
 
> fillcolor=white margin=0 shape=box style=""] +} diff --git a/examples/ex07.html b/examples/ex07.html new file mode 100644 index 0000000..6544c47 --- /dev/null +++ b/examples/ex07.html @@ -0,0 +1,101 @@ +

Diagram

+ + + + + +%3 + + + +X1 + +X1 + +TE 776164-1 + +female + +35-pin + +5 + +6 + + + +C1 + + +C1 + +2x + +20 AWG + +1 m +  +X1:5 +YE +X2:7 + + + +X1:6 +GN +X2:2 + + + +  + + + +X1:e--C1:w + + + + + + +X1:e--C1:w + + + + + + +X2 + +X2 + +D-Sub + +female + +9-pin + +2 + +7 + + + +C1:e--X2:w + + + + + + +C1:e--X2:w + + + + + + +

Bill of Materials

ItemQtyUnitDesignators
Connector, D-Sub, female, 9 pins1X2
Connector, TE 776164-1, female, 35 pins1X1
Cable, 2 x 20 AWG1mC1
\ No newline at end of file diff --git a/examples/ex07.png b/examples/ex07.png new file mode 100644 index 0000000000000000000000000000000000000000..4d7cb787290da00605acdecad24fc8bcdfb85152 GIT binary patch literal 25066 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 + + + + + +%3 + + + +X1 + +X1 + +TE 776164-1 + +female + +35-pin + +5 + +6 + + + +C1 + + +C1 + +2x + +20 AWG + +1 m +  +X1:5 +YE +X2:7 + + + +X1:6 +GN +X2:2 + + + +  + + + +X1:e--C1:w + + + + + + +X1:e--C1:w + + + + + + +X2 + +X2 + +D-Sub + +female + +9-pin + +2 + +7 + + + +C1:e--X2:w + + + + + + +C1:e--X2:w + + + + + + diff --git a/examples/ex07.yml b/examples/ex07.yml new file mode 100644 index 0000000..064122d --- /dev/null +++ b/examples/ex07.yml @@ -0,0 +1,25 @@ +connectors: + X1: + type: TE 776164-1 + subtype: female + hide_disconnected_pins: True + pincount: 35 + + X2: + type: D-Sub + subtype: female + pincount: 9 + hide_disconnected_pins: True + +cables: + C1: + wirecount: 2 + gauge: 20 AWG + colors: [YE, GN] + length: 1 + +connections: + - + - X1: [5,6] + - C1: [1,2] + - X2: [7,2] \ No newline at end of file diff --git a/examples/readme.md b/examples/readme.md index 5330f73..6ddef6f 100644 --- a/examples/readme.md +++ b/examples/readme.md @@ -35,3 +35,9 @@ [Source](ex06.yml) - [Bill of Materials](ex06.bom.tsv) +## Example 07 +![](ex07.png) + +[Source](ex07.yml) - [Bill of Materials](ex07.bom.tsv) + + diff --git a/src/batch.py b/src/batch.py index 300cd84..56e752c 100644 --- a/src/batch.py +++ b/src/batch.py @@ -2,7 +2,7 @@ import wireviz import os demos = 0 # 2 -examples = 0 # 6 +examples = 0 # 7 tutorials = 7 # 7 if demos: diff --git a/src/wireviz.py b/src/wireviz.py index afe825d..7ae27c9 100755 --- a/src/wireviz.py +++ b/src/wireviz.py @@ -27,6 +27,10 @@ class Harness: def connect(self, from_name, from_pin, via_name, via_pin, to_name, to_pin): self.cables[via_name].connect(from_name, from_pin, via_pin, to_name, to_pin) + if from_name in self.connectors: + self.connectors[from_name].activate_pin(from_pin) + if to_name in self.connectors: + self.connectors[to_name].activate_pin(to_pin) def create_graph(self): dot = Graph() @@ -85,8 +89,10 @@ class Harness: '{}-pin'.format(len(n.pinout)) if n.show_pincount else ''] # p = pinout p = [[],[],[]] - p[1] = list(n.pinout) for i, x in enumerate(n.pinout, 1): + if n.hide_disconnected_pins and not n.visible_pins.get(i, False): + continue + p[1].append(x) if n.ports_left: p[0].append('{portno}'.format(portno=i)) if n.ports_right: @@ -321,11 +327,13 @@ class Connector: color: str = None show_name: bool = True show_pincount: bool = True + hide_disconnected_pins: bool = False def __post_init__(self): self.ports_left = False self.ports_right = False self.loops = [] + self.visible_pins = {} if self.pinout: if self.pincount is not None: @@ -339,6 +347,12 @@ class Connector: def loop(self, from_pin, to_pin): self.loops.append((from_pin, to_pin)) + if self.hide_disconnected_pins: + self.visible_pins[from_pin] = True + self.visible_pins[to_pin] = True + + def activate_pin(self, pin): + self.visible_pins[pin] = True @dataclass class Cable: From 955cf83cfb368e12ce454940c7673444a30f7f71 Mon Sep 17 00:00:00 2001 From: Kimmo Lindholm Date: Wed, 24 Jun 2020 16:46:08 +0300 Subject: [PATCH 03/35] Add optional custom pinnumbers to connector --- src/wireviz.py | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/src/wireviz.py b/src/wireviz.py index afe825d..cb7e615 100755 --- a/src/wireviz.py +++ b/src/wireviz.py @@ -82,16 +82,23 @@ class Harness: # a = attributes a = [n.type, n.subtype, - '{}-pin'.format(len(n.pinout)) if n.show_pincount else ''] + '{}-pin'.format(n.pincount) if n.show_pincount else ''] # p = pinout p = [[],[],[]] p[1] = list(n.pinout) - for i, x in enumerate(n.pinout, 1): - if n.ports_left: - p[0].append('{portno}'.format(portno=i)) - if n.ports_right: - p[2].append('{portno}'.format(portno=i)) - # l = label + if (n.pinnumbers): + for i in n.pinnumbers: + if n.ports_left: + p[0].append('{portno}'.format(portno=i)) + if n.ports_right: + p[2].append('{portno}'.format(portno=i)) + else: + for i, x in enumerate(n.pinout, 1): + if n.ports_left: + p[0].append('{portno}'.format(portno=i)) + if n.ports_right: + p[2].append('{portno}'.format(portno=i)) + # l = label l = [n.name if n.show_name else '', a, p, n.notes] dot.node(k, label=nested(l)) @@ -318,6 +325,7 @@ class Connector: pincount: int = None notes: str = None pinout: List[Any] = field(default_factory=list) + pinnumbers: List[Any] = field(default_factory=list) color: str = None show_name: bool = True show_pincount: bool = True @@ -327,15 +335,17 @@ class Connector: self.ports_right = False self.loops = [] - if self.pinout: - if self.pincount is not None: - raise Exception('You cannot specify both pinout and pincount') - else: + if self.pincount is None: + if self.pinout: self.pincount = len(self.pinout) - else: - if not self.pincount: - self.pincount = 1 - self.pinout = ['',] * self.pincount + elif self.pinnumbers: + self.pincount = len(self.pinnumbers) + else: + raise Exception('You need to specify at least one, pincount, pinout or pinnumbers') + + if self.pinout and self.pinnumbers: + if len(self.pinout) != len(self.pinnumbers): + raise Exception('Given pinout and pinnumbers size mismatch') def loop(self, from_pin, to_pin): self.loops.append((from_pin, to_pin)) From 8bf296b18607a47d761db81de7adcd1fa68df160 Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Sat, 27 Jun 2020 11:13:16 +0200 Subject: [PATCH 04/35] Auto-generate pin numbers if only pincount is specified --- src/wireviz.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/wireviz.py b/src/wireviz.py index cb7e615..284d310 100755 --- a/src/wireviz.py +++ b/src/wireviz.py @@ -347,6 +347,9 @@ class Connector: if len(self.pinout) != len(self.pinnumbers): raise Exception('Given pinout and pinnumbers size mismatch') + if not self.pinout and not self.pinnumbers: + self.pinnumbers = list(range(1,self.pincount + 1)) + def loop(self, from_pin, to_pin): self.loops.append((from_pin, to_pin)) From d0023c1d41a1f896ce56c266ded36a232c868140 Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Sat, 27 Jun 2020 23:31:58 +0200 Subject: [PATCH 05/35] Make custom pin numbers and hidden unused pins work nicely together --- src/wireviz.py | 31 +++++++++---------------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/src/wireviz.py b/src/wireviz.py index 0f7459a..650acf2 100755 --- a/src/wireviz.py +++ b/src/wireviz.py @@ -89,30 +89,14 @@ class Harness: '{}-pin'.format(n.pincount) if n.show_pincount else ''] # p = pinout p = [[],[],[]] - # from dev branch - p[1] = list(n.pinout) - if (n.pinnumbers): - for i in n.pinnumbers: - if n.ports_left: - p[0].append('{portno}'.format(portno=i)) - if n.ports_right: - p[2].append('{portno}'.format(portno=i)) - else: - for i, x in enumerate(n.pinout, 1): - if n.ports_left: - p[0].append('{portno}'.format(portno=i)) - if n.ports_right: - p[2].append('{portno}'.format(portno=i)) - # l = label - # from hide_unconnected branch - for i, x in enumerate(n.pinout, 1): - if n.hide_disconnected_pins and not n.visible_pins.get(i, False): + for pinnumber, pinname in zip(n.pinnumbers, n.pinout): + if n.hide_disconnected_pins and not n.visible_pins.get(pinnumber, False): continue - p[1].append(x) + p[1].append(pinname) if n.ports_left: - p[0].append('{portno}'.format(portno=i)) + p[0].append('{portno}'.format(portno=pinnumber)) if n.ports_right: - p[2].append('{portno}'.format(portno=i)) + p[2].append('{portno}'.format(portno=pinnumber)) # l = label l = [n.name if n.show_name else '', a, p, n.notes] dot.node(k, label=nested(l)) @@ -364,8 +348,11 @@ class Connector: if len(self.pinout) != len(self.pinnumbers): raise Exception('Given pinout and pinnumbers size mismatch') - if not self.pinout and not self.pinnumbers: + # create default lists for pinnumbers (sequential) and pinouts (blank) if not specified + if not self.pinnumbers: self.pinnumbers = list(range(1,self.pincount + 1)) + if not self.pinout: + self.pinout = [''] * self.pincount def loop(self, from_pin, to_pin): self.loops.append((from_pin, to_pin)) From da80d4ba8506922a2da7e9f0fcb155ba709ddf05 Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Sat, 27 Jun 2020 23:37:37 +0200 Subject: [PATCH 06/35] Auto-assign pincount = 1 for ferrules at initialization --- src/wireviz.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/wireviz.py b/src/wireviz.py index 650acf2..551c388 100755 --- a/src/wireviz.py +++ b/src/wireviz.py @@ -341,6 +341,8 @@ class Connector: self.pincount = len(self.pinout) elif self.pinnumbers: self.pincount = len(self.pinnumbers) + elif self.category == 'ferrule': + self.pincount = 1 else: raise Exception('You need to specify at least one, pincount, pinout or pinnumbers') From 790e9c93c4fd46f2f48c7de22e1b33fc42351a16 Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Sat, 27 Jun 2020 23:46:22 +0200 Subject: [PATCH 07/35] Update demos and examples --- examples/demo01.bom.tsv | 6 +- examples/demo01.html | 2 +- examples/demo02.bom.tsv | 24 +-- examples/demo02.gv | 8 +- examples/demo02.html | 18 +- examples/demo02.svg | 16 +- examples/ex01.bom.tsv | 4 +- examples/ex01.html | 2 +- examples/ex02.bom.tsv | 6 +- examples/ex02.html | 2 +- examples/ex03.bom.tsv | 8 +- examples/ex03.html | 2 +- examples/ex04.bom.tsv | 14 +- examples/ex04.gv | 48 ++--- examples/ex04.html | 98 ++++----- examples/ex04.svg | 96 ++++----- examples/ex05.bom.tsv | 10 +- examples/ex05.html | 2 +- examples/ex06.bom.tsv | 10 +- examples/ex06.html | 2 +- examples/ex07.gv | 4 +- examples/ex07.html | 135 ++++++------ examples/ex07.png | Bin 25066 -> 26580 bytes examples/ex07.svg | 135 ++++++------ examples/ex07.yml | 6 +- examples/ex08.bom.tsv | 3 + examples/ex08.gv | 17 ++ examples/ex08.html | 99 +++++++++ examples/ex08.png | Bin 0 -> 32765 bytes examples/ex08.svg | 98 +++++++++ examples/ex08.yml | 24 +++ examples/ex09.bom.tsv | 4 + examples/ex09.gv | 48 +++++ examples/ex09.html | 451 ++++++++++++++++++++++++++++++++++++++++ examples/ex09.png | Bin 0 -> 208186 bytes examples/ex09.svg | 450 +++++++++++++++++++++++++++++++++++++++ examples/ex09.yml | 31 +++ examples/readme.md | 12 ++ src/batch.py | 4 +- 39 files changed, 1573 insertions(+), 326 deletions(-) create mode 100644 examples/ex08.bom.tsv create mode 100644 examples/ex08.gv create mode 100644 examples/ex08.html create mode 100644 examples/ex08.png create mode 100644 examples/ex08.svg create mode 100644 examples/ex08.yml create mode 100644 examples/ex09.bom.tsv create mode 100644 examples/ex09.gv create mode 100644 examples/ex09.html create mode 100644 examples/ex09.png create mode 100644 examples/ex09.svg create mode 100644 examples/ex09.yml diff --git a/examples/demo01.bom.tsv b/examples/demo01.bom.tsv index 43f2d71..d753410 100644 --- a/examples/demo01.bom.tsv +++ b/examples/demo01.bom.tsv @@ -1,4 +1,4 @@ Item Qty Unit Designators -D-Sub, female, 9 pins 1 X1 -Molex KK 254, female, 3 pins 1 X2 -Cable 3 x 0.25 mm² shielded 0.2 m W1 +Connector, D-Sub, female, 9 pins 1 X1 +Connector, Molex KK 254, female, 3 pins 1 X2 +Cable, 3 x 0.25 mm² shielded 0.2 m W1 diff --git a/examples/demo01.html b/examples/demo01.html index f490520..cfedd06 100644 --- a/examples/demo01.html +++ b/examples/demo01.html @@ -168,4 +168,4 @@ -

Bill of Materials

ItemQtyUnitDesignators
D-Sub, female, 9 pins1X1
Molex KK 254, female, 3 pins1X2
Cable 3 x 0.25 mm² shielded0.2mW1
\ No newline at end of file +

Bill of Materials

ItemQtyUnitDesignators
Connector, D-Sub, female, 9 pins1X1
Connector, Molex KK 254, female, 3 pins1X2
Cable, 3 x 0.25 mm² shielded0.2mW1
\ No newline at end of file diff --git a/examples/demo02.bom.tsv b/examples/demo02.bom.tsv index 5fe7ab1..bbaf4a1 100644 --- a/examples/demo02.bom.tsv +++ b/examples/demo02.bom.tsv @@ -1,13 +1,13 @@ Item Qty Unit Designators -Crimp ferrule, 0.25 mm² 2 -Molex KK 254, female, 4 pins 2 X2, X3 -Molex KK 254, female, 5 pins 1 X4 -Molex KK 254, female, 8 pins 1 X1 -Cable 2 x 0.25 mm² 0.3 m W4 -Wire 0.14 mm² BK 0.9 m W1, W2, W3 -Wire 0.14 mm² BU 0.3 m W3 -Wire 0.14 mm² GN 0.6 m W1, W2 -Wire 0.14 mm² OG 0.3 m W3 -Wire 0.14 mm² RD 0.6 m W1, W2 -Wire 0.14 mm² VT 0.3 m W3 -Wire 0.14 mm² YE 0.6 m W1, W2 +Connector, Crimp ferrule, 0.25 mm² 2 +Connector, Molex KK 254, female, 4 pins 2 X2, X3 +Connector, Molex KK 254, female, 5 pins 1 X4 +Connector, Molex KK 254, female, 8 pins 1 X1 +Cable, 2 x 0.25 mm² 0.3 m W4 +Wire, 0.14 mm², BK 0.9 m W1, W2, W3 +Wire, 0.14 mm², BU 0.3 m W3 +Wire, 0.14 mm², GN 0.6 m W1, W2 +Wire, 0.14 mm², OG 0.3 m W3 +Wire, 0.14 mm², RD 0.6 m W1, W2 +Wire, 0.14 mm², VT 0.3 m W3 +Wire, 0.14 mm², YE 0.6 m W1, W2 diff --git a/examples/demo02.gv b/examples/demo02.gv index fa19809..3e8f42d 100644 --- a/examples/demo02.gv +++ b/examples/demo02.gv @@ -8,7 +8,7 @@ graph { X2 [label="X2|{Molex KK 254|female|4-pin}|{{1|2|3|4}|{GND|+5V|SCL|SDA}}"] X3 [label="X3|{Molex KK 254|female|4-pin}|{{1|2|3|4}|{GND|+5V|SCL|SDA}}"] X4 [label="X4|{Molex KK 254|female|5-pin}|{{1|2|3|4|5}|{GND|+12V|MISO|MOSI|SCK}}"] - F1 [label=< + _F1 [label=< @@ -18,7 +18,7 @@ graph { > margin=0 orientation=180 shape=none style=filled] - F2 [label=< + _F2 [label=<
Crimp ferrule, 0.25 mm²
@@ -68,9 +68,9 @@ graph { W3:w4:e -- X4:p5l:w W3 [label=<
Crimp ferrule, 0.25 mm²
W3
4x0.14 mm² (26 AWG)0.3 m
 
X1:1BKX4:1
X1:5BUX4:3
X1:6OGX4:4
X1:7VTX4:5
 
> fillcolor=white margin=0 shape=box style="filled,dashed"] edge [color="#000000:#000000:#000000"] - F1:e -- W4:w1:w + _F1:e -- W4:w1:w edge [color="#000000:#ff0000:#000000"] - F2:e -- W4:w2:w + _F2:e -- W4:w2:w edge [color="#000000:#000000:#000000"] W4:w1:e -- X4:p1l:w edge [color="#000000:#ff0000:#000000"] diff --git a/examples/demo02.html b/examples/demo02.html index 25797b0..a63a0c6 100644 --- a/examples/demo02.html +++ b/examples/demo02.html @@ -341,9 +341,9 @@ SCK - + -F1 +_F1 Crimp ferrule, 0.25 mm²     @@ -374,24 +374,24 @@   - + -F1:e--W4:w +_F1:e--W4:w - + -F2 +_F2 Crimp ferrule, 0.25 mm²     - + -F2:e--W4:w +_F2:e--W4:w @@ -496,4 +496,4 @@ -

Bill of Materials

ItemQtyUnitDesignators
Crimp ferrule, 0.25 mm²2
Molex KK 254, female, 4 pins2X2, X3
Molex KK 254, female, 5 pins1X4
Molex KK 254, female, 8 pins1X1
Cable 2 x 0.25 mm²0.3mW4
Wire 0.14 mm² BK0.9mW1, W2, W3
Wire 0.14 mm² BU0.3mW3
Wire 0.14 mm² GN0.6mW1, W2
Wire 0.14 mm² OG0.3mW3
Wire 0.14 mm² RD0.6mW1, W2
Wire 0.14 mm² VT0.3mW3
Wire 0.14 mm² YE0.6mW1, W2
\ No newline at end of file +

Bill of Materials

ItemQtyUnitDesignators
Connector, Crimp ferrule, 0.25 mm²2
Connector, Molex KK 254, female, 4 pins2X2, X3
Connector, Molex KK 254, female, 5 pins1X4
Connector, Molex KK 254, female, 8 pins1X1
Cable, 2 x 0.25 mm²0.3mW4
Wire, 0.14 mm², BK0.9mW1, W2, W3
Wire, 0.14 mm², BU0.3mW3
Wire, 0.14 mm², GN0.6mW1, W2
Wire, 0.14 mm², OG0.3mW3
Wire, 0.14 mm², RD0.6mW1, W2
Wire, 0.14 mm², VT0.3mW3
Wire, 0.14 mm², YE0.6mW1, W2
\ No newline at end of file diff --git a/examples/demo02.svg b/examples/demo02.svg index 60a0a9e..3b8a93e 100644 --- a/examples/demo02.svg +++ b/examples/demo02.svg @@ -341,9 +341,9 @@ SCK - + -F1 +_F1 Crimp ferrule, 0.25 mm²     @@ -374,24 +374,24 @@   - + -F1:e--W4:w +_F1:e--W4:w - + -F2 +_F2 Crimp ferrule, 0.25 mm²     - + -F2:e--W4:w +_F2:e--W4:w diff --git a/examples/ex01.bom.tsv b/examples/ex01.bom.tsv index f1a36cd..6eeb436 100644 --- a/examples/ex01.bom.tsv +++ b/examples/ex01.bom.tsv @@ -1,3 +1,3 @@ Item Qty Unit Designators -Molex KK 254, female, 4 pins 2 X1, X2 -Cable 4 x 0.25 mm² shielded 0.2 m W1 +Connector, Molex KK 254, female, 4 pins 2 X1, X2 +Cable, 4 x 0.25 mm² shielded 0.2 m W1 diff --git a/examples/ex01.html b/examples/ex01.html index 22856aa..5c03d91 100644 --- a/examples/ex01.html +++ b/examples/ex01.html @@ -172,4 +172,4 @@ -

Bill of Materials

ItemQtyUnitDesignators
Molex KK 254, female, 4 pins2X1, X2
Cable 4 x 0.25 mm² shielded0.2mW1
\ No newline at end of file +

Bill of Materials

ItemQtyUnitDesignators
Connector, Molex KK 254, female, 4 pins2X1, X2
Cable, 4 x 0.25 mm² shielded0.2mW1
\ No newline at end of file diff --git a/examples/ex02.bom.tsv b/examples/ex02.bom.tsv index 61e34ab..4c8d11e 100644 --- a/examples/ex02.bom.tsv +++ b/examples/ex02.bom.tsv @@ -1,4 +1,4 @@ Item Qty Unit Designators -Molex Micro-Fit, female, 2 pins 3 X2, X3, X4 -Molex Micro-Fit, male, 2 pins 1 X1 -Cable 2 x 0.25 mm² 0.6 m W1, W2, W3 +Connector, Molex Micro-Fit, female, 2 pins 3 X2, X3, X4 +Connector, Molex Micro-Fit, male, 2 pins 1 X1 +Cable, 2 x 0.25 mm² 0.6 m W1, W2, W3 diff --git a/examples/ex02.html b/examples/ex02.html index 152b7a2..148fa57 100644 --- a/examples/ex02.html +++ b/examples/ex02.html @@ -255,4 +255,4 @@ -

Bill of Materials

ItemQtyUnitDesignators
Molex Micro-Fit, female, 2 pins3X2, X3, X4
Molex Micro-Fit, male, 2 pins1X1
Cable 2 x 0.25 mm²0.6mW1, W2, W3
\ No newline at end of file +

Bill of Materials

ItemQtyUnitDesignators
Connector, Molex Micro-Fit, female, 2 pins3X2, X3, X4
Connector, Molex Micro-Fit, male, 2 pins1X1
Cable, 2 x 0.25 mm²0.6mW1, W2, W3
\ No newline at end of file diff --git a/examples/ex03.bom.tsv b/examples/ex03.bom.tsv index bb66fbc..98d3491 100644 --- a/examples/ex03.bom.tsv +++ b/examples/ex03.bom.tsv @@ -1,5 +1,5 @@ Item Qty Unit Designators -Molex Micro-Fit, female, 2 pins 3 X2, X3, X4 -Molex Micro-Fit, male, 2 pins 1 X1 -Wire 0.25 mm² BK 0.6 m W1 -Wire 0.25 mm² RD 0.6 m W1 +Connector, Molex Micro-Fit, female, 2 pins 3 X2, X3, X4 +Connector, Molex Micro-Fit, male, 2 pins 1 X1 +Wire, 0.25 mm², BK 0.6 m W1 +Wire, 0.25 mm², RD 0.6 m W1 diff --git a/examples/ex03.html b/examples/ex03.html index fa7fe59..9490593 100644 --- a/examples/ex03.html +++ b/examples/ex03.html @@ -225,4 +225,4 @@ -

Bill of Materials

ItemQtyUnitDesignators
Molex Micro-Fit, female, 2 pins3X2, X3, X4
Molex Micro-Fit, male, 2 pins1X1
Wire 0.25 mm² BK0.6mW1
Wire 0.25 mm² RD0.6mW1
\ No newline at end of file +

Bill of Materials

ItemQtyUnitDesignators
Connector, Molex Micro-Fit, female, 2 pins3X2, X3, X4
Connector, Molex Micro-Fit, male, 2 pins1X1
Wire, 0.25 mm², BK0.6mW1
Wire, 0.25 mm², RD0.6mW1
\ No newline at end of file diff --git a/examples/ex04.bom.tsv b/examples/ex04.bom.tsv index cfa8f84..edee58d 100644 --- a/examples/ex04.bom.tsv +++ b/examples/ex04.bom.tsv @@ -1,8 +1,8 @@ Item Qty Unit Designators -Crimp ferrule 12 -Wire 0.25 mm² BN 0.2 m W1 -Wire 0.25 mm² BU 0.2 m W1 -Wire 0.25 mm² GN 0.2 m W1 -Wire 0.25 mm² OG 0.2 m W1 -Wire 0.25 mm² RD 0.2 m W1 -Wire 0.25 mm² YE 0.2 m W1 +Connector, Crimp ferrule 12 +Wire, 0.25 mm², BN 0.2 m W1 +Wire, 0.25 mm², BU 0.2 m W1 +Wire, 0.25 mm², GN 0.2 m W1 +Wire, 0.25 mm², OG 0.2 m W1 +Wire, 0.25 mm², RD 0.2 m W1 +Wire, 0.25 mm², YE 0.2 m W1 diff --git a/examples/ex04.gv b/examples/ex04.gv index 5715530..7d4428b 100644 --- a/examples/ex04.gv +++ b/examples/ex04.gv @@ -4,7 +4,7 @@ graph { graph [bgcolor=white fontname=arial nodesep=0.33 rankdir=LR ranksep=2] node [fillcolor=white fontname=arial shape=record style=filled] edge [fontname=arial style=bold] - F1 [label=< + _F1 [label=< @@ -14,7 +14,7 @@ graph { > margin=0 orientation=180 shape=none style=filled] - F2 [label=< + _F2 [label=<
Crimp ferrule
@@ -24,7 +24,7 @@ graph { > margin=0 orientation=180 shape=none style=filled] - F3 [label=< + _F3 [label=<
Crimp ferrule
@@ -34,7 +34,7 @@ graph { > margin=0 orientation=180 shape=none style=filled] - F4 [label=< + _F4 [label=<
Crimp ferrule
@@ -44,7 +44,7 @@ graph { > margin=0 orientation=180 shape=none style=filled] - F5 [label=< + _F5 [label=<
Crimp ferrule
@@ -54,7 +54,7 @@ graph { > margin=0 orientation=180 shape=none style=filled] - F6 [label=< + _F6 [label=<
Crimp ferrule
@@ -64,7 +64,7 @@ graph { > margin=0 orientation=180 shape=none style=filled] - F7 [label=< + _F7 [label=<
Crimp ferrule
@@ -74,7 +74,7 @@ graph { > margin=0 orientation=0 shape=none style=filled] - F8 [label=< + _F8 [label=<
@@ -84,7 +84,7 @@ graph { > margin=0 orientation=0 shape=none style=filled] - F9 [label=< + _F9 [label=<
@@ -94,7 +94,7 @@ graph { > margin=0 orientation=0 shape=none style=filled] - F10 [label=< + _F10 [label=<
@@ -104,7 +104,7 @@ graph { > margin=0 orientation=0 shape=none style=filled] - F11 [label=< + _F11 [label=<
@@ -114,7 +114,7 @@ graph { > margin=0 orientation=0 shape=none style=filled] - F12 [label=< + _F12 [label=<
@@ -125,28 +125,28 @@ graph { > margin=0 orientation=0 shape=none style=filled] edge [color="#000000:#666600:#000000"] - F1:e -- W1:w1:w + _F1:e -- W1:w1:w edge [color="#000000:#ff0000:#000000"] - F2:e -- W1:w2:w + _F2:e -- W1:w2:w edge [color="#000000:#ff8000:#000000"] - F3:e -- W1:w3:w + _F3:e -- W1:w3:w edge [color="#000000:#ffff00:#000000"] - F4:e -- W1:w4:w + _F4:e -- W1:w4:w edge [color="#000000:#00ff00:#000000"] - F5:e -- W1:w5:w + _F5:e -- W1:w5:w edge [color="#000000:#0066ff:#000000"] - F6:e -- W1:w6:w + _F6:e -- W1:w6:w edge [color="#000000:#0066ff:#000000"] - W1:w6:e -- F7:w + W1:w6:e -- _F7:w edge [color="#000000:#00ff00:#000000"] - W1:w5:e -- F8:w + W1:w5:e -- _F8:w edge [color="#000000:#ffff00:#000000"] - W1:w4:e -- F9:w + W1:w4:e -- _F9:w edge [color="#000000:#ff8000:#000000"] - W1:w3:e -- F10:w + W1:w3:e -- _F10:w edge [color="#000000:#ff0000:#000000"] - W1:w2:e -- F11:w + W1:w2:e -- _F11:w edge [color="#000000:#666600:#000000"] - W1:w1:e -- F12:w + W1:w1:e -- _F12:w W1 [label=<
W1
6x0.25 mm² (24 AWG)0.2 m
 
BN
RD
OG
YE
GN
BU
 
> fillcolor=white margin=0 shape=box style="filled,dashed"] } diff --git a/examples/ex04.html b/examples/ex04.html index 807969f..4c44171 100644 --- a/examples/ex04.html +++ b/examples/ex04.html @@ -8,9 +8,9 @@ viewBox="0.00 0.00 712.00 344.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> - + -F1 +_F1 Crimp ferrule     @@ -55,178 +55,178 @@   - + -F1:e--W1:w +_F1:e--W1:w - + -F2 +_F2 Crimp ferrule     - + -F2:e--W1:w +_F2:e--W1:w - + -F3 +_F3 Crimp ferrule     - + -F3:e--W1:w +_F3:e--W1:w - + -F4 +_F4 Crimp ferrule     - + -F4:e--W1:w +_F4:e--W1:w - + -F5 +_F5 Crimp ferrule     - + -F5:e--W1:w +_F5:e--W1:w - + -F6 +_F6 Crimp ferrule     - + -F6:e--W1:w +_F6:e--W1:w - + -F7 +_F7   Crimp ferrule   - + -F8 +_F8   Crimp ferrule   - + -F9 +_F9   Crimp ferrule   - + -F10 +_F10   Crimp ferrule   - + -F11 +_F11   Crimp ferrule   - + -F12 +_F12   Crimp ferrule   - + -W1:e--F7:w +W1:e--_F7:w - + -W1:e--F8:w +W1:e--_F8:w - + -W1:e--F9:w +W1:e--_F9:w - + -W1:e--F10:w +W1:e--_F10:w - + -W1:e--F11:w +W1:e--_F11:w - + -W1:e--F12:w +W1:e--_F12:w -

Bill of Materials

ItemQtyUnitDesignators
Crimp ferrule12
Wire 0.25 mm² BN0.2mW1
Wire 0.25 mm² BU0.2mW1
Wire 0.25 mm² GN0.2mW1
Wire 0.25 mm² OG0.2mW1
Wire 0.25 mm² RD0.2mW1
Wire 0.25 mm² YE0.2mW1
\ No newline at end of file +

Bill of Materials

ItemQtyUnitDesignators
Connector, Crimp ferrule12
Wire, 0.25 mm², BN0.2mW1
Wire, 0.25 mm², BU0.2mW1
Wire, 0.25 mm², GN0.2mW1
Wire, 0.25 mm², OG0.2mW1
Wire, 0.25 mm², RD0.2mW1
Wire, 0.25 mm², YE0.2mW1
\ No newline at end of file diff --git a/examples/ex04.svg b/examples/ex04.svg index 8272dec..ecf2e71 100644 --- a/examples/ex04.svg +++ b/examples/ex04.svg @@ -8,9 +8,9 @@ viewBox="0.00 0.00 712.00 344.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> - + -F1 +_F1 Crimp ferrule     @@ -55,174 +55,174 @@   - + -F1:e--W1:w +_F1:e--W1:w - + -F2 +_F2 Crimp ferrule     - + -F2:e--W1:w +_F2:e--W1:w - + -F3 +_F3 Crimp ferrule     - + -F3:e--W1:w +_F3:e--W1:w - + -F4 +_F4 Crimp ferrule     - + -F4:e--W1:w +_F4:e--W1:w - + -F5 +_F5 Crimp ferrule     - + -F5:e--W1:w +_F5:e--W1:w - + -F6 +_F6 Crimp ferrule     - + -F6:e--W1:w +_F6:e--W1:w - + -F7 +_F7   Crimp ferrule   - + -F8 +_F8   Crimp ferrule   - + -F9 +_F9   Crimp ferrule   - + -F10 +_F10   Crimp ferrule   - + -F11 +_F11   Crimp ferrule   - + -F12 +_F12   Crimp ferrule   - + -W1:e--F7:w +W1:e--_F7:w - + -W1:e--F8:w +W1:e--_F8:w - + -W1:e--F9:w +W1:e--_F9:w - + -W1:e--F10:w +W1:e--_F10:w - + -W1:e--F11:w +W1:e--_F11:w - + -W1:e--F12:w +W1:e--_F12:w diff --git a/examples/ex05.bom.tsv b/examples/ex05.bom.tsv index 3314de6..d80fedd 100644 --- a/examples/ex05.bom.tsv +++ b/examples/ex05.bom.tsv @@ -1,6 +1,6 @@ Item Qty Unit Designators -Molex KK 254, female, 4 pins 3 X1, X2, X3 -Wire 0.25 mm² PK 0.4 m W1, W2 -Wire 0.25 mm² TQ 0.4 m W1, W2 -Wire 0.25 mm² VT 0.4 m W1, W2 -Wire 0.25 mm² YE 0.4 m W1, W2 +Connector, Molex KK 254, female, 4 pins 3 X1, X2, X3 +Wire, 0.25 mm², PK 0.4 m W1, W2 +Wire, 0.25 mm², TQ 0.4 m W1, W2 +Wire, 0.25 mm², VT 0.4 m W1, W2 +Wire, 0.25 mm², YE 0.4 m W1, W2 diff --git a/examples/ex05.html b/examples/ex05.html index dc6d5dd..f8fc416 100644 --- a/examples/ex05.html +++ b/examples/ex05.html @@ -292,4 +292,4 @@ -

Bill of Materials

ItemQtyUnitDesignators
Molex KK 254, female, 4 pins3X1, X2, X3
Wire 0.25 mm² PK0.4mW1, W2
Wire 0.25 mm² TQ0.4mW1, W2
Wire 0.25 mm² VT0.4mW1, W2
Wire 0.25 mm² YE0.4mW1, W2
\ No newline at end of file +

Bill of Materials

ItemQtyUnitDesignators
Connector, Molex KK 254, female, 4 pins3X1, X2, X3
Wire, 0.25 mm², PK0.4mW1, W2
Wire, 0.25 mm², TQ0.4mW1, W2
Wire, 0.25 mm², VT0.4mW1, W2
Wire, 0.25 mm², YE0.4mW1, W2
\ No newline at end of file diff --git a/examples/ex06.bom.tsv b/examples/ex06.bom.tsv index d4bb657..7885f32 100644 --- a/examples/ex06.bom.tsv +++ b/examples/ex06.bom.tsv @@ -1,6 +1,6 @@ Item Qty Unit Designators -Molex KK 254, female, 4 pins 6 X1, X2, X3, X4, X5, X6 -Wire 0.25 mm² PK 1.0 m W1, W2, W3, W4, W5 -Wire 0.25 mm² TQ 1.0 m W1, W2, W3, W4, W5 -Wire 0.25 mm² VT 1.0 m W1, W2, W3, W4, W5 -Wire 0.25 mm² YE 1.0 m W1, W2, W3, W4, W5 +Connector, Molex KK 254, female, 4 pins 6 X1, X2, X3, X4, X5, X6 +Wire, 0.25 mm², PK 1.0 m W1, W2, W3, W4, W5 +Wire, 0.25 mm², TQ 1.0 m W1, W2, W3, W4, W5 +Wire, 0.25 mm², VT 1.0 m W1, W2, W3, W4, W5 +Wire, 0.25 mm², YE 1.0 m W1, W2, W3, W4, W5 diff --git a/examples/ex06.html b/examples/ex06.html index 1700d54..ea542d0 100644 --- a/examples/ex06.html +++ b/examples/ex06.html @@ -653,4 +653,4 @@ -

Bill of Materials

ItemQtyUnitDesignators
Molex KK 254, female, 4 pins6X1, X2, X3, X4, X5, X6
Wire 0.25 mm² PK1.0mW1, W2, W3, W4, W5
Wire 0.25 mm² TQ1.0mW1, W2, W3, W4, W5
Wire 0.25 mm² VT1.0mW1, W2, W3, W4, W5
Wire 0.25 mm² YE1.0mW1, W2, W3, W4, W5
\ No newline at end of file +

Bill of Materials

ItemQtyUnitDesignators
Connector, Molex KK 254, female, 4 pins6X1, X2, X3, X4, X5, X6
Wire, 0.25 mm², PK1.0mW1, W2, W3, W4, W5
Wire, 0.25 mm², TQ1.0mW1, W2, W3, W4, W5
Wire, 0.25 mm², VT1.0mW1, W2, W3, W4, W5
Wire, 0.25 mm², YE1.0mW1, W2, W3, W4, W5
\ No newline at end of file diff --git a/examples/ex07.gv b/examples/ex07.gv index 80d892d..2a10a84 100644 --- a/examples/ex07.gv +++ b/examples/ex07.gv @@ -4,8 +4,8 @@ graph { graph [bgcolor=white fontname=arial nodesep=0.33 rankdir=LR ranksep=2] node [fillcolor=white fontname=arial shape=record style=filled] edge [fontname=arial style=bold] - X1 [label="X1|{TE 776164-1|female|35-pin}|{{5|6}}"] - X2 [label="X2|{D-Sub|female|9-pin}|{{2|7}}"] + X1 [label="X1|{TE 776164-1|female|35-pin}|{{5|6}}|Unconnected pins are not shown"] + X2 [label="X2|{D-Sub|female|9-pin}|{{2|7}}|Unconnected pins are not shown"] edge [color="#000000:#ffff00:#000000"] X1:p5r:e -- C1:w1:w C1:w1:e -- X2:p7l:w diff --git a/examples/ex07.html b/examples/ex07.html index 6544c47..c206174 100644 --- a/examples/ex07.html +++ b/examples/ex07.html @@ -1,100 +1,103 @@

Diagram

- - - - -%3 - + + + + X1 - -X1 - -TE 776164-1 - -female - -35-pin - -5 - -6 + +X1 + +TE 776164-1 + +female + +35-pin + +5 + +6 + +Unconnected pins are not shown C1 - - -C1 - -2x - -20 AWG - -1 m -  -X1:5 -YE -X2:7 - - - -X1:6 -GN -X2:2 - - - -  + + +C1 + +2x + +20 AWG + +1 m +  +X1:5 +YE +X2:7 + + + +X1:6 +GN +X2:2 + + + +  X1:e--C1:w - - - + + + X1:e--C1:w - - - + + + X2 - -X2 - -D-Sub - -female - -9-pin - -2 - -7 + +X2 + +D-Sub + +female + +9-pin + +2 + +7 + +Unconnected pins are not shown C1:e--X2:w - - - + + + C1:e--X2:w - - - + + + diff --git a/examples/ex07.png b/examples/ex07.png index 4d7cb787290da00605acdecad24fc8bcdfb85152..2fc2ce6ad96b9d9a8486b684968e0ae3cf575e62 100644 GIT binary patch literal 26580 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 - - - - -%3 - + + + + X1 - -X1 - -TE 776164-1 - -female - -35-pin - -5 - -6 + +X1 + +TE 776164-1 + +female + +35-pin + +5 + +6 + +Unconnected pins are not shown C1 - - -C1 - -2x - -20 AWG - -1 m -  -X1:5 -YE -X2:7 - - - -X1:6 -GN -X2:2 - - - -  + + +C1 + +2x + +20 AWG + +1 m +  +X1:5 +YE +X2:7 + + + +X1:6 +GN +X2:2 + + + +  X1:e--C1:w - - - + + + X1:e--C1:w - - - + + + X2 - -X2 - -D-Sub - -female - -9-pin - -2 - -7 + +X2 + +D-Sub + +female + +9-pin + +2 + +7 + +Unconnected pins are not shown C1:e--X2:w - - - + + + C1:e--X2:w - - - + + + diff --git a/examples/ex07.yml b/examples/ex07.yml index 064122d..9ba9477 100644 --- a/examples/ex07.yml +++ b/examples/ex07.yml @@ -1,15 +1,19 @@ +# contributed by @elliotmr + connectors: X1: type: TE 776164-1 subtype: female hide_disconnected_pins: True pincount: 35 + notes: Unconnected pins are not shown X2: type: D-Sub subtype: female pincount: 9 hide_disconnected_pins: True + notes: Unconnected pins are not shown cables: C1: @@ -22,4 +26,4 @@ connections: - - X1: [5,6] - C1: [1,2] - - X2: [7,2] \ No newline at end of file + - X2: [7,2] diff --git a/examples/ex08.bom.tsv b/examples/ex08.bom.tsv new file mode 100644 index 0000000..3457bbb --- /dev/null +++ b/examples/ex08.bom.tsv @@ -0,0 +1,3 @@ +Item Qty Unit Designators +Connector, Phone Connector, male 3.5, 3 pins 1 Key +Cable, 3 x 24 AWG shielded 0.2 m W1 diff --git a/examples/ex08.gv b/examples/ex08.gv new file mode 100644 index 0000000..a949333 --- /dev/null +++ b/examples/ex08.gv @@ -0,0 +1,17 @@ +graph { +// Graph generated by WireViz +// https://github.com/formatc1702/WireViz + graph [bgcolor=white fontname=arial nodesep=0.33 rankdir=LR ranksep=2] + node [fillcolor=white fontname=arial shape=record style=filled] + edge [fontname=arial style=bold] + Key [label="Key|{Phone Connector|male 3.5|3-pin}|{{Dot|Dash|Ground}|{T|R|S}}"] + edge [color="#000000:#ffffff:#000000"] + Key:pSr:e -- W1:w1:w + edge [color="#000000:#666600:#000000"] + Key:pRr:e -- W1:w2:w + edge [color="#000000:#00ff00:#000000"] + Key:pTr:e -- W1:w3:w + edge [color="#000000"] + Key:pSr:e -- W1:ws:w + W1 [label=<
W1
3x24 AWG+ S0.2 m
 
Key:SWH
Key:RBN
Key:TGN
 
Key:SShield
 
> fillcolor=white margin=0 shape=box style=""] +} diff --git a/examples/ex08.html b/examples/ex08.html new file mode 100644 index 0000000..c290a0f --- /dev/null +++ b/examples/ex08.html @@ -0,0 +1,99 @@ +

Diagram

+ + + + + + + + +Key + +Key + +Phone Connector + +male 3.5 + +3-pin + +Dot + +Dash + +Ground + +T + +R + +S + + + +W1 + + +W1 + +3x + +24 AWG + ++ S + +0.2 m +  +Key:S +WH + + + +Key:R +BN + + + +Key:T +GN + + + +  +Key:S +Shield + +  + + + +Key:e--W1:w + + + + + + +Key:e--W1:w + + + + + + +Key:e--W1:w + + + + + + +Key:e--W1:w + + + + +

Bill of Materials

ItemQtyUnitDesignators
Connector, Phone Connector, male 3.5, 3 pins1Key
Cable, 3 x 24 AWG shielded0.2mW1
\ No newline at end of file diff --git a/examples/ex08.png b/examples/ex08.png new file mode 100644 index 0000000000000000000000000000000000000000..a0270f7852119679d541317f85eddb1891db9896 GIT binary patch literal 32765 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 C7gcQl literal 0 HcmV?d00001 diff --git a/examples/ex08.svg b/examples/ex08.svg new file mode 100644 index 0000000..0599c11 --- /dev/null +++ b/examples/ex08.svg @@ -0,0 +1,98 @@ + + + + + + + + + +Key + +Key + +Phone Connector + +male 3.5 + +3-pin + +Dot + +Dash + +Ground + +T + +R + +S + + + +W1 + + +W1 + +3x + +24 AWG + ++ S + +0.2 m +  +Key:S +WH + + + +Key:R +BN + + + +Key:T +GN + + + +  +Key:S +Shield + +  + + + +Key:e--W1:w + + + + + + +Key:e--W1:w + + + + + + +Key:e--W1:w + + + + + + +Key:e--W1:w + + + + diff --git a/examples/ex08.yml b/examples/ex08.yml new file mode 100644 index 0000000..0d42be5 --- /dev/null +++ b/examples/ex08.yml @@ -0,0 +1,24 @@ +# contributed by @cocide + +connectors: + Key: + type: Phone Connector + subtype: male 3.5 + pinnumbers: [T, R, S] + pinout: [Dot, Dash, Ground] + +cables: + W1: + gauge: 24 AWG + length: 0.2 + color_code: DIN + wirecount: 3 + shield: true + +connections: + - + - Key: [S,R,T] + - W1: [1,2,3] + - + - Key: S + - W1: s diff --git a/examples/ex09.bom.tsv b/examples/ex09.bom.tsv new file mode 100644 index 0000000..b07a154 --- /dev/null +++ b/examples/ex09.bom.tsv @@ -0,0 +1,4 @@ +Item Qty Unit Designators +Connector, D-Sub, male, 25 pins 1 X1 +Connector, F48, female, 48 pins 1 X2 +Cable, 12 x 0.25 mm² shielded 0.2 m W1 diff --git a/examples/ex09.gv b/examples/ex09.gv new file mode 100644 index 0000000..52df78a --- /dev/null +++ b/examples/ex09.gv @@ -0,0 +1,48 @@ +graph { +// Graph generated by WireViz +// https://github.com/formatc1702/WireViz + graph [bgcolor=white fontname=arial nodesep=0.33 rankdir=LR ranksep=2] + node [fillcolor=white fontname=arial shape=record style=filled] + edge [fontname=arial style=bold] + X1 [label="X1|{D-Sub|male|25-pin}|{{SENSE_P_1|SENSE_N_1|SENSE_P_2|SENSE_N_2|SENSE_P_3|SENSE_N_3|SENSE_P_4|SENSE_N_4|SENSE_P_5|SENSE_N_5|SENSE_P_6|SENSE_N_6|GND}|{1|14|3|16|5|18|7|20|9|22|11|24|13}}"] + X2 [label="X2|{F48|female|48-pin}|{{z2|b2|d2|z4|b4|d4|z6|b6|d6|z8|b8|d8|z10|b10|d10|z12|b12|d12|z14|b14|d14|z16|b16|d16|z18|b18|d18|z20|b20|d20|z22|b22|d22|z24|b24|d24|z26|b26|d26|z28|b28|d28|z30|b30|d30|z32|b32|d32}}"] + edge [color="#000000:#666600:#000000"] + X1:p1r:e -- W1:w2:w + W1:w2:e -- X2:pd4l:w + edge [color="#000000:#ffffff:#000000"] + X1:p14r:e -- W1:w1:w + W1:w1:e -- X2:pz2l:w + edge [color="#000000:#ffff00:#000000"] + X1:p3r:e -- W1:w4:w + W1:w4:e -- X2:pd10l:w + edge [color="#000000:#00ff00:#000000"] + X1:p16r:e -- W1:w3:w + W1:w3:e -- X2:pz8l:w + edge [color="#000000:#ff66cc:#000000"] + X1:p5r:e -- W1:w6:w + W1:w6:e -- X2:pd16l:w + edge [color="#000000:#999999:#000000"] + X1:p18r:e -- W1:w5:w + W1:w5:e -- X2:pz14l:w + edge [color="#000000:#ff0000:#000000"] + X1:p7r:e -- W1:w8:w + W1:w8:e -- X2:pd20l:w + edge [color="#000000:#0066ff:#000000"] + X1:p20r:e -- W1:w7:w + W1:w7:e -- X2:pz18l:w + edge [color="#000000:#8000ff:#000000"] + X1:p9r:e -- W1:w10:w + W1:w10:e -- X2:pd26l:w + edge [color="#000000:#000000:#000000"] + X1:p22r:e -- W1:w9:w + W1:w9:e -- X2:pz24l:w + edge [color="#000000:#666600:#000000"] + X1:p11r:e -- W1:w12:w + W1:w12:e -- X2:pd32l:w + edge [color="#000000:#ffffff:#000000"] + X1:p24r:e -- W1:w11:w + W1:w11:e -- X2:pz30l:w + edge [color="#000000"] + X1:p13r:e -- W1:ws:w + W1 [label=<
W1
12x0.25 mm²+ S0.2 m
 
X1:14WHX2:z2
X1:1BNX2:d4
X1:16GNX2:z8
X1:3YEX2:d10
X1:18GYX2:z14
X1:5PKX2:d16
X1:20BUX2:z18
X1:7RDX2:d20
X1:22BKX2:z24
X1:9VTX2:d26
X1:24WHX2:z30
X1:11BNX2:d32
 
X1:13Shield
 
> fillcolor=white margin=0 shape=box style=""] +} diff --git a/examples/ex09.html b/examples/ex09.html new file mode 100644 index 0000000..ccce9d5 --- /dev/null +++ b/examples/ex09.html @@ -0,0 +1,451 @@ +

Diagram

+ + + + + + + + +X1 + +X1 + +D-Sub + +male + +25-pin + +SENSE_P_1 + +SENSE_N_1 + +SENSE_P_2 + +SENSE_N_2 + +SENSE_P_3 + +SENSE_N_3 + +SENSE_P_4 + +SENSE_N_4 + +SENSE_P_5 + +SENSE_N_5 + +SENSE_P_6 + +SENSE_N_6 + +GND + +1 + +14 + +3 + +16 + +5 + +18 + +7 + +20 + +9 + +22 + +11 + +24 + +13 + + + +W1 + + +W1 + +12x + +0.25 mm² + ++ S + +0.2 m +  +X1:14 +WH +X2:z2 + + + +X1:1 +BN +X2:d4 + + + +X1:16 +GN +X2:z8 + + + +X1:3 +YE +X2:d10 + + + +X1:18 +GY +X2:z14 + + + +X1:5 +PK +X2:d16 + + + +X1:20 +BU +X2:z18 + + + +X1:7 +RD +X2:d20 + + + +X1:22 +BK +X2:z24 + + + +X1:9 +VT +X2:d26 + + + +X1:24 +WH +X2:z30 + + + +X1:11 +BN +X2:d32 + + + +  +X1:13 +Shield + +  + + + +X1:e--W1:w + + + + + + +X1:e--W1:w + + + + + + +X1:e--W1:w + + + + + + +X1:e--W1:w + + + + + + +X1:e--W1:w + + + + + + +X1:e--W1:w + + + + + + +X1:e--W1:w + + + + + + +X1:e--W1:w + + + + + + +X1:e--W1:w + + + + + + +X1:e--W1:w + + + + + + +X1:e--W1:w + + + + + + +X1:e--W1:w + + + + + + +X1:e--W1:w + + + + +X2 + +X2 + +F48 + +female + +48-pin + +z2 + +b2 + +d2 + +z4 + +b4 + +d4 + +z6 + +b6 + +d6 + +z8 + +b8 + +d8 + +z10 + +b10 + +d10 + +z12 + +b12 + +d12 + +z14 + +b14 + +d14 + +z16 + +b16 + +d16 + +z18 + +b18 + +d18 + +z20 + +b20 + +d20 + +z22 + +b22 + +d22 + +z24 + +b24 + +d24 + +z26 + +b26 + +d26 + +z28 + +b28 + +d28 + +z30 + +b30 + +d30 + +z32 + +b32 + +d32 + + + +W1:e--X2:w + + + + + + +W1:e--X2:w + + + + + + +W1:e--X2:w + + + + + + +W1:e--X2:w + + + + + + +W1:e--X2:w + + + + + + +W1:e--X2:w + + + + + + +W1:e--X2:w + + + + + + +W1:e--X2:w + + + + + + +W1:e--X2:w + + + + + + +W1:e--X2:w + + + + + + +W1:e--X2:w + + + + + + +W1:e--X2:w + + + + + + +

Bill of Materials

ItemQtyUnitDesignators
Connector, D-Sub, male, 25 pins1X1
Connector, F48, female, 48 pins1X2
Cable, 12 x 0.25 mm² shielded0.2mW1
\ No newline at end of file diff --git a/examples/ex09.png b/examples/ex09.png new file mode 100644 index 0000000000000000000000000000000000000000..80c7662f47577d0003c7ee357d2d3b6083e2e15a GIT binary patch literal 208186 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 literal 0 HcmV?d00001 diff --git a/examples/ex09.svg b/examples/ex09.svg new file mode 100644 index 0000000..29ba2bb --- /dev/null +++ b/examples/ex09.svg @@ -0,0 +1,450 @@ + + + + + + + + + +X1 + +X1 + +D-Sub + +male + +25-pin + +SENSE_P_1 + +SENSE_N_1 + +SENSE_P_2 + +SENSE_N_2 + +SENSE_P_3 + +SENSE_N_3 + +SENSE_P_4 + +SENSE_N_4 + +SENSE_P_5 + +SENSE_N_5 + +SENSE_P_6 + +SENSE_N_6 + +GND + +1 + +14 + +3 + +16 + +5 + +18 + +7 + +20 + +9 + +22 + +11 + +24 + +13 + + + +W1 + + +W1 + +12x + +0.25 mm² + ++ S + +0.2 m +  +X1:14 +WH +X2:z2 + + + +X1:1 +BN +X2:d4 + + + +X1:16 +GN +X2:z8 + + + +X1:3 +YE +X2:d10 + + + +X1:18 +GY +X2:z14 + + + +X1:5 +PK +X2:d16 + + + +X1:20 +BU +X2:z18 + + + +X1:7 +RD +X2:d20 + + + +X1:22 +BK +X2:z24 + + + +X1:9 +VT +X2:d26 + + + +X1:24 +WH +X2:z30 + + + +X1:11 +BN +X2:d32 + + + +  +X1:13 +Shield + +  + + + +X1:e--W1:w + + + + + + +X1:e--W1:w + + + + + + +X1:e--W1:w + + + + + + +X1:e--W1:w + + + + + + +X1:e--W1:w + + + + + + +X1:e--W1:w + + + + + + +X1:e--W1:w + + + + + + +X1:e--W1:w + + + + + + +X1:e--W1:w + + + + + + +X1:e--W1:w + + + + + + +X1:e--W1:w + + + + + + +X1:e--W1:w + + + + + + +X1:e--W1:w + + + + +X2 + +X2 + +F48 + +female + +48-pin + +z2 + +b2 + +d2 + +z4 + +b4 + +d4 + +z6 + +b6 + +d6 + +z8 + +b8 + +d8 + +z10 + +b10 + +d10 + +z12 + +b12 + +d12 + +z14 + +b14 + +d14 + +z16 + +b16 + +d16 + +z18 + +b18 + +d18 + +z20 + +b20 + +d20 + +z22 + +b22 + +d22 + +z24 + +b24 + +d24 + +z26 + +b26 + +d26 + +z28 + +b28 + +d28 + +z30 + +b30 + +d30 + +z32 + +b32 + +d32 + + + +W1:e--X2:w + + + + + + +W1:e--X2:w + + + + + + +W1:e--X2:w + + + + + + +W1:e--X2:w + + + + + + +W1:e--X2:w + + + + + + +W1:e--X2:w + + + + + + +W1:e--X2:w + + + + + + +W1:e--X2:w + + + + + + +W1:e--X2:w + + + + + + +W1:e--X2:w + + + + + + +W1:e--X2:w + + + + + + +W1:e--X2:w + + + + + + diff --git a/examples/ex09.yml b/examples/ex09.yml new file mode 100644 index 0000000..baef3ab --- /dev/null +++ b/examples/ex09.yml @@ -0,0 +1,31 @@ +# contributed by @kimmoli + +connectors: + X1: + type: D-Sub + subtype: male + pincount: 25 + pinnumbers: [1,14,3,16,5,18,7,20,9,22,11,24,13] + pinout: [ SENSE_P_1, SENSE_N_1, SENSE_P_2, SENSE_N_2, SENSE_P_3, SENSE_N_3, SENSE_P_4,SENSE_N_4, SENSE_P_5, SENSE_N_5, SENSE_P_6, SENSE_N_6, GND ] + X2: + type: F48 + subtype: female + pincount: 48 + pinnumbers: [ z2,b2,d2,z4,b4,d4,z6,b6,d6,z8,b8,d8,z10,b10,d10,z12,b12,d12,z14,b14,d14,z16,b16,d16,z18,b18,d18,z20,b20,d20,z22,b22,d22,z24,b24,d24,z26,b26,d26,z28,b28,d28,z30,b30,d30,z32,b32,d32 ] + +cables: + W1: + gauge: 0.25 mm2 + length: 0.2 + color_code: DIN + wirecount: 12 + shield: true + +connections: + - + - X1: [1,14,3,16,5,18,7,20,9,22,11,24] + - W1: [2,1,4,3,6,5,8,7,10,9,12,11] + - X2: [d4,z2,d10,z8,d16,z14,d20,z18,d26,z24,d32,z30] + - + - X1: 13 + - W1: s diff --git a/examples/readme.md b/examples/readme.md index 6ddef6f..e90e593 100644 --- a/examples/readme.md +++ b/examples/readme.md @@ -41,3 +41,15 @@ [Source](ex07.yml) - [Bill of Materials](ex07.bom.tsv) +## Example 08 +![](ex08.png) + +[Source](ex08.yml) - [Bill of Materials](ex08.bom.tsv) + + +## Example 09 +![](ex09.png) + +[Source](ex09.yml) - [Bill of Materials](ex09.bom.tsv) + + diff --git a/src/batch.py b/src/batch.py index 56e752c..6add6a9 100644 --- a/src/batch.py +++ b/src/batch.py @@ -1,8 +1,8 @@ import wireviz import os -demos = 0 # 2 -examples = 0 # 7 +demos = 2 # 2 +examples = 9 # 9 tutorials = 7 # 7 if demos: From 466199215170f1451b1199fed1726d5e8a2c7d2a Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Sat, 27 Jun 2020 23:54:55 +0200 Subject: [PATCH 08/35] Fine-tune wire BOM output if no gauge is specified --- src/wireviz.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wireviz.py b/src/wireviz.py index 551c388..2be00a2 100755 --- a/src/wireviz.py +++ b/src/wireviz.py @@ -294,7 +294,7 @@ class Harness: designators = list(dict.fromkeys(designators)) designators.sort() total_length = sum(i['length'] for i in items) - name = 'Wire, {gauge}{color}'.format(gauge='{} {}'.format(shared['gauge'], shared['gauge_unit']) if shared['gauge'] else '', + name = 'Wire{gauge}{color}'.format(gauge=', {} {}'.format(shared['gauge'], shared['gauge_unit']) if shared['gauge'] else '', color=', {}'.format(shared['color']) if shared['color'] != '' else '') item = {'item': name, 'qty': round(total_length, 3), 'unit': 'm', 'designators': designators} bom_cables.append(item) From dfb184c1a41c8294048db88dd8c8b378aaaee561 Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Sun, 28 Jun 2020 10:39:11 +0200 Subject: [PATCH 09/35] Move source from src/ to src/wireviz/ in preparation for merge of refactor brancb --- src/{ => wireviz}/.gitignore | 0 src/{ => wireviz}/batch.py | 0 src/{ => wireviz}/wireviz.py | 0 src/{ => wireviz}/wv_colors.py | 0 src/{ => wireviz}/wv_helper.py | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename src/{ => wireviz}/.gitignore (100%) rename src/{ => wireviz}/batch.py (100%) rename src/{ => wireviz}/wireviz.py (100%) rename src/{ => wireviz}/wv_colors.py (100%) rename src/{ => wireviz}/wv_helper.py (100%) diff --git a/src/.gitignore b/src/wireviz/.gitignore similarity index 100% rename from src/.gitignore rename to src/wireviz/.gitignore diff --git a/src/batch.py b/src/wireviz/batch.py similarity index 100% rename from src/batch.py rename to src/wireviz/batch.py diff --git a/src/wireviz.py b/src/wireviz/wireviz.py similarity index 100% rename from src/wireviz.py rename to src/wireviz/wireviz.py diff --git a/src/wv_colors.py b/src/wireviz/wv_colors.py similarity index 100% rename from src/wv_colors.py rename to src/wireviz/wv_colors.py diff --git a/src/wv_helper.py b/src/wireviz/wv_helper.py similarity index 100% rename from src/wv_helper.py rename to src/wireviz/wv_helper.py From 5514fd424420e170986e225b27ebcbde20fc06eb Mon Sep 17 00:00:00 2001 From: Andreas Nordin Date: Wed, 24 Jun 2020 18:59:42 +0200 Subject: [PATCH 10/35] refactor dependencies and installation There are hard copies of the graphviz and pyyaml dependencies included in the repo. Remove these. Sort out installation and dependency handling by writing a functional setup.py script. Rename top level documentation. Refactor wireviz.py slightly to allow it to run as an installed script. # Conflicts: # src/batch.py # src/wireviz/batch.py # src/wireviz/build_examples.py --- .gitignore | 9 +- LICENSE.txt => LICENSE | 0 readme.md => README.md | 2 +- todo.md => TODO | 0 requirements.txt | 1 + setup.py | 45 ++ src/graphviz/__init__.py | 63 -- src/graphviz/_compat.py | 69 -- src/graphviz/backend.py | 312 ------- src/graphviz/dot.py | 287 ------- src/graphviz/files.py | 311 ------- src/graphviz/lang.py | 195 ----- src/graphviz/tools.py | 47 -- src/wireviz/__init__.py | 0 src/wireviz/build_examples.py | 54 ++ src/wireviz/wireviz.py | 12 +- src/yaml/__init__.py | 427 ---------- src/yaml/composer.py | 139 ---- src/yaml/constructor.py | 748 ----------------- src/yaml/cyaml.py | 101 --- src/yaml/dumper.py | 62 -- src/yaml/emitter.py | 1137 -------------------------- src/yaml/error.py | 75 -- src/yaml/events.py | 86 -- src/yaml/loader.py | 63 -- src/yaml/nodes.py | 49 -- src/yaml/parser.py | 589 -------------- src/yaml/reader.py | 185 ----- src/yaml/representer.py | 389 --------- src/yaml/resolver.py | 227 ------ src/yaml/scanner.py | 1435 --------------------------------- src/yaml/serializer.py | 111 --- src/yaml/tokens.py | 104 --- 33 files changed, 117 insertions(+), 7217 deletions(-) rename LICENSE.txt => LICENSE (100%) rename readme.md => README.md (95%) rename todo.md => TODO (100%) create mode 100644 requirements.txt create mode 100644 setup.py delete mode 100644 src/graphviz/__init__.py delete mode 100644 src/graphviz/_compat.py delete mode 100644 src/graphviz/backend.py delete mode 100644 src/graphviz/dot.py delete mode 100644 src/graphviz/files.py delete mode 100644 src/graphviz/lang.py delete mode 100644 src/graphviz/tools.py create mode 100644 src/wireviz/__init__.py create mode 100644 src/wireviz/build_examples.py delete mode 100644 src/yaml/__init__.py delete mode 100644 src/yaml/composer.py delete mode 100644 src/yaml/constructor.py delete mode 100644 src/yaml/cyaml.py delete mode 100644 src/yaml/dumper.py delete mode 100644 src/yaml/emitter.py delete mode 100644 src/yaml/error.py delete mode 100644 src/yaml/events.py delete mode 100644 src/yaml/loader.py delete mode 100644 src/yaml/nodes.py delete mode 100644 src/yaml/parser.py delete mode 100644 src/yaml/reader.py delete mode 100644 src/yaml/representer.py delete mode 100644 src/yaml/resolver.py delete mode 100644 src/yaml/scanner.py delete mode 100644 src/yaml/serializer.py delete mode 100644 src/yaml/tokens.py diff --git a/.gitignore b/.gitignore index 79b2f55..c121d2f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,9 @@ .DS_Store -temp/ +.eggs +__pycache__ +.*.swp +*.egg-info +*.pyc +build +data +dist diff --git a/LICENSE.txt b/LICENSE similarity index 100% rename from LICENSE.txt rename to LICENSE diff --git a/readme.md b/README.md similarity index 95% rename from readme.md rename to README.md index bca9684..df7092a 100644 --- a/readme.md +++ b/README.md @@ -94,7 +94,7 @@ mywire.html HTML page with wiring diagram and BOM embedded ## Status -This is very much a [work in progress](todo.md). Source code, API, syntax and functionality may change wildly at any time. +This is very much a [work in progress](TODO). Source code, API, syntax and functionality may change wildly at any time. ## Requirements diff --git a/todo.md b/TODO similarity index 100% rename from todo.md rename to TODO diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..9c558e3 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +. diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..83dbc55 --- /dev/null +++ b/setup.py @@ -0,0 +1,45 @@ +#!/usr/bin/python3 + +import os +from setuptools import setup, find_packages + +project_name = 'wireviz' + +# Utility function to read the README file. +# Used for the long_description. It's nice, because now 1) we have a top level +# README file and 2) it's easier to type in the README file than to put a raw +# string in below ... +def read(fname): + return open(os.path.join(os.path.dirname(__file__), fname)).read() + +setup( + name=project_name, + version='0.1', + author='Daniel Rojas', + #author_email='', + description='Easily document cables and wiring harnesses', + long_description=read(os.path.join(os.path.dirname(__file__), 'README.md')), + long_description_content_type='text/markdown', + install_requires=[ + 'pyyaml', + 'graphviz', + ], + license='GPLv3', + keywords='cable connector hardware harness wiring wiring-diagram wiring-harness', + url='https://github.com/n42/WireViz', + package_dir={'': 'src'}, + packages=find_packages('src'), + entry_points={ + 'console_scripts': ['wireviz=wireviz.wireviz:main'], + }, + classifiers=[ + 'Development Status :: 4 - Beta', + 'Environment :: Console', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + 'Topic :: Utilities', + 'License :: OSI Approved :: GNU General Public License v3 (GPLv3)', + ], + +) diff --git a/src/graphviz/__init__.py b/src/graphviz/__init__.py deleted file mode 100644 index 66760eb..0000000 --- a/src/graphviz/__init__.py +++ /dev/null @@ -1,63 +0,0 @@ -# graphviz - create dot, save, render, view - -"""Assemble DOT source code and render it with Graphviz. - ->>> dot = Digraph(comment='The Round Table') - ->>> dot.node('A', 'King Arthur') ->>> dot.node('B', 'Sir Bedevere the Wise') ->>> dot.node('L', 'Sir Lancelot the Brave') - ->>> dot.edges(['AB', 'AL']) - ->>> dot.edge('B', 'L', constraint='false') - ->>> print(dot) #doctest: +NORMALIZE_WHITESPACE -// The Round Table -digraph { - A [label="King Arthur"] - B [label="Sir Bedevere the Wise"] - L [label="Sir Lancelot the Brave"] - A -> B - A -> L - B -> L [constraint=false] -} -""" - -from .dot import Graph, Digraph -from .files import Source -from .lang import escape, nohtml -from .backend import (render, pipe, version, view, - ENGINES, FORMATS, RENDERERS, FORMATTERS, - ExecutableNotFound, RequiredArgumentError) - -__all__ = [ - 'Graph', 'Digraph', - 'Source', - 'escape', 'nohtml', - 'render', 'pipe', 'version', 'view', - 'ENGINES', 'FORMATS', 'RENDERERS', 'FORMATTERS', - 'ExecutableNotFound', 'RequiredArgumentError', -] - -__title__ = 'graphviz' -__version__ = '0.14.1.dev0' -__author__ = 'Sebastian Bank ' -__license__ = 'MIT, see LICENSE.txt' -__copyright__ = 'Copyright (c) 2013-2020 Sebastian Bank' - -#: Set of known layout commands used for rendering (``'dot'``, ``'neato'``, ...) -ENGINES = ENGINES - -#: Set of known output formats for rendering (``'pdf'``, ``'png'``, ...) -FORMATS = FORMATS - -#: Set of known output formatters for rendering (``'cairo'``, ``'gd'``, ...) -FORMATTERS = FORMATTERS - -#: Set of known output renderers for rendering (``'cairo'``, ``'gd'``, ...) -RENDERERS = RENDERERS - -ExecutableNotFound = ExecutableNotFound - -RequiredArgumentError = RequiredArgumentError diff --git a/src/graphviz/_compat.py b/src/graphviz/_compat.py deleted file mode 100644 index 7d6fc7b..0000000 --- a/src/graphviz/_compat.py +++ /dev/null @@ -1,69 +0,0 @@ -# _compat.py - Python 2/3 compatibility - -import os -import sys -import operator -import subprocess - -PY2 = (sys.version_info.major == 2) - - -if PY2: - string_classes = (str, unicode) # needed individually for sublassing - text_type = unicode - - iteritems = operator.methodcaller('iteritems') - - def makedirs(name, mode=0o777, exist_ok=False): - try: - os.makedirs(name, mode) - except OSError: - if not exist_ok or not os.path.isdir(name): - raise - - def stderr_write_bytes(data, flush=False): - """Write data str to sys.stderr (flush if requested).""" - sys.stderr.write(data) - if flush: - sys.stderr.flush() - - def Popen_stderr_devnull(*args, **kwargs): # noqa: N802 - with open(os.devnull, 'w') as f: - return subprocess.Popen(*args, stderr=f, **kwargs) - - class CalledProcessError(subprocess.CalledProcessError): - - def __init__(self, returncode, cmd, output=None, stderr=None): - super(CalledProcessError, self).__init__(returncode, cmd, output) - self.stderr = stderr - - @property # pragma: no cover - def stdout(self): - return self.output - - @stdout.setter # pragma: no cover - def stdout(self, value): - self.output = value - - -else: - string_classes = (str,) - text_type = str - - def iteritems(d): - return iter(d.items()) - - def makedirs(name, mode=0o777, exist_ok=False): # allow os.makedirs mocking - return os.makedirs(name, mode, exist_ok=exist_ok) - - def stderr_write_bytes(data, flush=False): - """Encode data str and write to sys.stderr (flush if requested).""" - encoding = sys.stderr.encoding or sys.getdefaultencoding() - sys.stderr.write(data.decode(encoding)) - if flush: - sys.stderr.flush() - - def Popen_stderr_devnull(*args, **kwargs): # noqa: N802 - return subprocess.Popen(*args, stderr=subprocess.DEVNULL, **kwargs) - - CalledProcessError = subprocess.CalledProcessError diff --git a/src/graphviz/backend.py b/src/graphviz/backend.py deleted file mode 100644 index 6f4cc0c..0000000 --- a/src/graphviz/backend.py +++ /dev/null @@ -1,312 +0,0 @@ -# backend.py - execute rendering, open files in viewer - -import os -import re -import errno -import logging -import platform -import subprocess - -from . import _compat - -from . import tools - -__all__ = [ - 'render', 'pipe', 'version', 'view', - 'ENGINES', 'FORMATS', 'RENDERERS', 'FORMATTERS', - 'ExecutableNotFound', 'RequiredArgumentError', -] - -ENGINES = { # http://www.graphviz.org/pdf/dot.1.pdf - 'dot', 'neato', 'twopi', 'circo', 'fdp', 'sfdp', 'patchwork', 'osage', -} - -FORMATS = { # http://www.graphviz.org/doc/info/output.html - 'bmp', - 'canon', 'dot', 'gv', 'xdot', 'xdot1.2', 'xdot1.4', - 'cgimage', - 'cmap', - 'eps', - 'exr', - 'fig', - 'gd', 'gd2', - 'gif', - 'gtk', - 'ico', - 'imap', 'cmapx', - 'imap_np', 'cmapx_np', - 'ismap', - 'jp2', - 'jpg', 'jpeg', 'jpe', - 'json', 'json0', 'dot_json', 'xdot_json', # Graphviz 2.40 - 'pct', 'pict', - 'pdf', - 'pic', - 'plain', 'plain-ext', - 'png', - 'pov', - 'ps', - 'ps2', - 'psd', - 'sgi', - 'svg', 'svgz', - 'tga', - 'tif', 'tiff', - 'tk', - 'vml', 'vmlz', - 'vrml', - 'wbmp', - 'webp', - 'xlib', - 'x11', -} - -RENDERERS = { # $ dot -T: - 'cairo', - 'dot', - 'fig', - 'gd', - 'gdiplus', - 'map', - 'pic', - 'pov', - 'ps', - 'svg', - 'tk', - 'vml', - 'vrml', - 'xdot', -} - -FORMATTERS = {'cairo', 'core', 'gd', 'gdiplus', 'gdwbmp', 'xlib'} - -PLATFORM = platform.system().lower() - - -log = logging.getLogger(__name__) - - -class ExecutableNotFound(RuntimeError): - """Exception raised if the Graphviz executable is not found.""" - - _msg = ('failed to execute %r, ' - 'make sure the Graphviz executables are on your systems\' PATH') - - def __init__(self, args): - super(ExecutableNotFound, self).__init__(self._msg % args) - - -class RequiredArgumentError(Exception): - """Exception raised if a required argument is missing.""" - - -class CalledProcessError(_compat.CalledProcessError): - - def __str__(self): - s = super(CalledProcessError, self).__str__() - return '%s [stderr: %r]' % (s, self.stderr) - - -def command(engine, format_, filepath=None, renderer=None, formatter=None): - """Return args list for ``subprocess.Popen`` and name of the rendered file.""" - if formatter is not None and renderer is None: - raise RequiredArgumentError('formatter given without renderer') - - if engine not in ENGINES: - raise ValueError('unknown engine: %r' % engine) - if format_ not in FORMATS: - raise ValueError('unknown format: %r' % format_) - if renderer is not None and renderer not in RENDERERS: - raise ValueError('unknown renderer: %r' % renderer) - if formatter is not None and formatter not in FORMATTERS: - raise ValueError('unknown formatter: %r' % formatter) - - output_format = [f for f in (format_, renderer, formatter) if f is not None] - cmd = [engine, '-T%s' % ':'.join(output_format)] - - if filepath is None: - rendered = None - else: - cmd.extend(['-O', filepath]) - suffix = '.'.join(reversed(output_format)) - rendered = '%s.%s' % (filepath, suffix) - - return cmd, rendered - - -if PLATFORM == 'windows': # pragma: no cover - def get_startupinfo(): - """Return subprocess.STARTUPINFO instance hiding the console window.""" - startupinfo = subprocess.STARTUPINFO() - startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW - startupinfo.wShowWindow = subprocess.SW_HIDE - return startupinfo -else: - def get_startupinfo(): - """Return None for startupinfo argument of ``subprocess.Popen``.""" - return None - - -def run(cmd, input=None, capture_output=False, check=False, encoding=None, - quiet=False, **kwargs): - """Run the command described by cmd and return its (stdout, stderr) tuple.""" - log.debug('run %r', cmd) - - if input is not None: - kwargs['stdin'] = subprocess.PIPE - if encoding is not None: - input = input.encode(encoding) - - if capture_output: - kwargs['stdout'] = kwargs['stderr'] = subprocess.PIPE - - try: - proc = subprocess.Popen(cmd, startupinfo=get_startupinfo(), **kwargs) - except OSError as e: - if e.errno == errno.ENOENT: - raise ExecutableNotFound(cmd) - else: - raise - - out, err = proc.communicate(input) - - if not quiet and err: - _compat.stderr_write_bytes(err, flush=True) - - if encoding is not None: - if out is not None: - out = out.decode(encoding) - if err is not None: - err = err.decode(encoding) - - if check and proc.returncode: - raise CalledProcessError(proc.returncode, cmd, - output=out, stderr=err) - - return out, err - - -def render(engine, format, filepath, renderer=None, formatter=None, quiet=False): - """Render file with Graphviz ``engine`` into ``format``, return result filename. - - Args: - engine: The layout commmand used for rendering (``'dot'``, ``'neato'``, ...). - format: The output format used for rendering (``'pdf'``, ``'png'``, ...). - filepath: Path to the DOT source file to render. - renderer: The output renderer used for rendering (``'cairo'``, ``'gd'``, ...). - formatter: The output formatter used for rendering (``'cairo'``, ``'gd'``, ...). - quiet (bool): Suppress ``stderr`` output from the layout subprocess. - Returns: - The (possibly relative) path of the rendered file. - Raises: - ValueError: If ``engine``, ``format``, ``renderer``, or ``formatter`` are not known. - graphviz.RequiredArgumentError: If ``formatter`` is given but ``renderer`` is None. - graphviz.ExecutableNotFound: If the Graphviz executable is not found. - subprocess.CalledProcessError: If the exit status is non-zero. - - The layout command is started from the directory of ``filepath``, so that - references to external files (e.g. ``[image=...]``) can be given as paths - relative to the DOT source file. - """ - dirname, filename = os.path.split(filepath) - del filepath - - cmd, rendered = command(engine, format, filename, renderer, formatter) - if dirname: - cwd = dirname - rendered = os.path.join(dirname, rendered) - else: - cwd = None - - run(cmd, capture_output=True, cwd=cwd, check=True, quiet=quiet) - return rendered - - -def pipe(engine, format, data, renderer=None, formatter=None, quiet=False): - """Return ``data`` piped through Graphviz ``engine`` into ``format``. - - Args: - engine: The layout commmand used for rendering (``'dot'``, ``'neato'``, ...). - format: The output format used for rendering (``'pdf'``, ``'png'``, ...). - data: The binary (encoded) DOT source string to render. - renderer: The output renderer used for rendering (``'cairo'``, ``'gd'``, ...). - formatter: The output formatter used for rendering (``'cairo'``, ``'gd'``, ...). - quiet (bool): Suppress ``stderr`` output from the layout subprocess. - Returns: - Binary (encoded) stdout of the layout command. - Raises: - ValueError: If ``engine``, ``format``, ``renderer``, or ``formatter`` are not known. - graphviz.RequiredArgumentError: If ``formatter`` is given but ``renderer`` is None. - graphviz.ExecutableNotFound: If the Graphviz executable is not found. - subprocess.CalledProcessError: If the exit status is non-zero. - """ - cmd, _ = command(engine, format, None, renderer, formatter) - out, _ = run(cmd, input=data, capture_output=True, check=True, quiet=quiet) - return out - - -def version(): - """Return the version number tuple from the ``stderr`` output of ``dot -V``. - - Returns: - Two, three, or four ``int`` version ``tuple``. - Raises: - graphviz.ExecutableNotFound: If the Graphviz executable is not found. - subprocess.CalledProcessError: If the exit status is non-zero. - RuntimmeError: If the output cannot be parsed into a version number. - """ - cmd = ['dot', '-V'] - out, _ = run(cmd, check=True, encoding='ascii', - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - - ma = re.search(r'graphviz version (\d+\.\d+(?:\.\d+){,2}) ', out) - if ma is None: - raise RuntimeError('cannot parse %r output: %r' % (cmd, out)) - - return tuple(int(d) for d in ma.group(1).split('.')) - - -def view(filepath, quiet=False): - """Open filepath with its default viewing application (platform-specific). - - Args: - filepath: Path to the file to open in viewer. - quiet (bool): Suppress ``stderr`` output from the viewer process - (ineffective on Windows). - Raises: - RuntimeError: If the current platform is not supported. - """ - try: - view_func = getattr(view, PLATFORM) - except AttributeError: - raise RuntimeError('platform %r not supported' % PLATFORM) - view_func(filepath, quiet) - - -@tools.attach(view, 'darwin') -def view_darwin(filepath, quiet): - """Open filepath with its default application (mac).""" - cmd = ['open', filepath] - log.debug('view: %r', cmd) - popen_func = _compat.Popen_stderr_devnull if quiet else subprocess.Popen - popen_func(cmd) - - -@tools.attach(view, 'linux') -@tools.attach(view, 'freebsd') -def view_unixoid(filepath, quiet): - """Open filepath in the user's preferred application (linux, freebsd).""" - cmd = ['xdg-open', filepath] - log.debug('view: %r', cmd) - popen_func = _compat.Popen_stderr_devnull if quiet else subprocess.Popen - popen_func(cmd) - - -@tools.attach(view, 'windows') -def view_windows(filepath, quiet): - """Start filepath with its associated application (windows).""" - # TODO: implement quiet=True - filepath = os.path.normpath(filepath) - log.debug('view: %r', filepath) - os.startfile(filepath) diff --git a/src/graphviz/dot.py b/src/graphviz/dot.py deleted file mode 100644 index 40cf1ae..0000000 --- a/src/graphviz/dot.py +++ /dev/null @@ -1,287 +0,0 @@ -# dot.py - create dot code - -r"""Assemble DOT source code objects. - ->>> dot = Graph(comment=u'M\xf8nti Pyth\xf8n ik den H\xf8lie Grailen') - ->>> dot.node(u'M\xf8\xf8se') ->>> dot.node('trained_by', u'trained by') ->>> dot.node('tutte', u'TUTTE HERMSGERVORDENBROTBORDA') - ->>> dot.edge(u'M\xf8\xf8se', 'trained_by') ->>> dot.edge('trained_by', 'tutte') - ->>> dot.node_attr['shape'] = 'rectangle' - ->>> print(dot.source.replace(u'\xf8', '0')) #doctest: +NORMALIZE_WHITESPACE -// M0nti Pyth0n ik den H0lie Grailen -graph { - node [shape=rectangle] - "M00se" - trained_by [label="trained by"] - tutte [label="TUTTE HERMSGERVORDENBROTBORDA"] - "M00se" -- trained_by - trained_by -- tutte -} - ->>> dot.view('test-output/m00se.gv') # doctest: +SKIP -'test-output/m00se.gv.pdf' -""" - -from . import lang -from . import files - -__all__ = ['Graph', 'Digraph'] - - -class Dot(files.File): - """Assemble, save, and render DOT source code, open result in viewer.""" - - _comment = '// %s' - _subgraph = 'subgraph %s{' - _subgraph_plain = '%s{' - _node = _attr = '\t%s%s' - _attr_plain = _attr % ('%s', '') - _tail = '}' - - _quote = staticmethod(lang.quote) - _quote_edge = staticmethod(lang.quote_edge) - - _a_list = staticmethod(lang.a_list) - _attr_list = staticmethod(lang.attr_list) - - def __init__(self, name=None, comment=None, - filename=None, directory=None, - format=None, engine=None, encoding=files.ENCODING, - graph_attr=None, node_attr=None, edge_attr=None, body=None, - strict=False): - self.name = name - self.comment = comment - - super(Dot, self).__init__(filename, directory, format, engine, encoding) - - self.graph_attr = dict(graph_attr) if graph_attr is not None else {} - self.node_attr = dict(node_attr) if node_attr is not None else {} - self.edge_attr = dict(edge_attr) if edge_attr is not None else {} - - self.body = list(body) if body is not None else [] - - self.strict = strict - - def _kwargs(self): - result = super(Dot, self)._kwargs() - result.update(name=self.name, - comment=self.comment, - graph_attr=dict(self.graph_attr), - node_attr=dict(self.node_attr), - edge_attr=dict(self.edge_attr), - body=list(self.body), - strict=self.strict) - return result - - def clear(self, keep_attrs=False): - """Reset content to an empty body, clear graph/node/egde_attr mappings. - - Args: - keep_attrs (bool): preserve graph/node/egde_attr mappings - """ - if not keep_attrs: - for a in (self.graph_attr, self.node_attr, self.edge_attr): - a.clear() - del self.body[:] - - def __iter__(self, subgraph=False): - """Yield the DOT source code line by line (as graph or subgraph).""" - if self.comment: - yield self._comment % self.comment - - if subgraph: - if self.strict: - raise ValueError('subgraphs cannot be strict') - head = self._subgraph if self.name else self._subgraph_plain - else: - head = self._head_strict if self.strict else self._head - yield head % (self._quote(self.name) + ' ' if self.name else '') - - for kw in ('graph', 'node', 'edge'): - attrs = getattr(self, '%s_attr' % kw) - if attrs: - yield self._attr % (kw, self._attr_list(None, attrs)) - - for line in self.body: - yield line - - yield self._tail - - def __str__(self): - """The DOT source code as string.""" - return '\n'.join(self) - - source = property(__str__, doc=__str__.__doc__) - - def node(self, name, label=None, _attributes=None, **attrs): - """Create a node. - - Args: - name: Unique identifier for the node inside the source. - label: Caption to be displayed (defaults to the node ``name``). - attrs: Any additional node attributes (must be strings). - """ - name = self._quote(name) - attr_list = self._attr_list(label, attrs, _attributes) - line = self._node % (name, attr_list) - self.body.append(line) - - def edge(self, tail_name, head_name, label=None, _attributes=None, **attrs): - """Create an edge between two nodes. - - Args: - tail_name: Start node identifier. - head_name: End node identifier. - label: Caption to be displayed near the edge. - attrs: Any additional edge attributes (must be strings). - """ - tail_name = self._quote_edge(tail_name) - head_name = self._quote_edge(head_name) - attr_list = self._attr_list(label, attrs, _attributes) - line = self._edge % (tail_name, head_name, attr_list) - self.body.append(line) - - def edges(self, tail_head_iter): - """Create a bunch of edges. - - Args: - tail_head_iter: Iterable of ``(tail_name, head_name)`` pairs. - """ - edge = self._edge_plain - quote = self._quote_edge - lines = (edge % (quote(t), quote(h)) for t, h in tail_head_iter) - self.body.extend(lines) - - def attr(self, kw=None, _attributes=None, **attrs): - """Add a general or graph/node/edge attribute statement. - - Args: - kw: Attributes target (``None`` or ``'graph'``, ``'node'``, ``'edge'``). - attrs: Attributes to be set (must be strings, may be empty). - - See the :ref:`usage examples in the User Guide `. - """ - if kw is not None and kw.lower() not in ('graph', 'node', 'edge'): - raise ValueError('attr statement must target graph, node, or edge: ' - '%r' % kw) - if attrs or _attributes: - if kw is None: - a_list = self._a_list(None, attrs, _attributes) - line = self._attr_plain % a_list - else: - attr_list = self._attr_list(None, attrs, _attributes) - line = self._attr % (kw, attr_list) - self.body.append(line) - - def subgraph(self, graph=None, name=None, comment=None, - graph_attr=None, node_attr=None, edge_attr=None, body=None): - """Add the current content of the given sole ``graph`` argument as subgraph \ - or return a context manager returning a new graph instance created \ - with the given (``name``, ``comment``, etc.) arguments whose content is \ - added as subgraph when leaving the context manager's ``with``-block. - - Args: - graph: An instance of the same kind (:class:`.Graph`, :class:`.Digraph`) - as the current graph (sole argument in non-with-block use). - name: Subgraph name (``with``-block use). - comment: Subgraph comment (``with``-block use). - graph_attr: Subgraph-level attribute-value mapping (``with``-block use). - node_attr: Node-level attribute-value mapping (``with``-block use). - edge_attr: Edge-level attribute-value mapping (``with``-block use). - body: Verbatim lines to add to the subgraph ``body`` (``with``-block use). - - See the :ref:`usage examples in the User Guide `. - - .. note:: - If the ``name`` of the subgraph begins with ``'cluster'`` (all lowercase) - the layout engine will treat it as a special cluster subgraph. - """ - if graph is None: - return SubgraphContext(self, {'name': name, - 'comment': comment, - 'graph_attr': graph_attr, - 'node_attr': node_attr, - 'edge_attr': edge_attr, - 'body': body}) - - args = [name, comment, graph_attr, node_attr, edge_attr, body] - if not all(a is None for a in args): - raise ValueError('graph must be sole argument of subgraph()') - - if graph.directed != self.directed: - raise ValueError('%r cannot add subgraph of different kind:' - ' %r' % (self, graph)) - - lines = ['\t' + line for line in graph.__iter__(subgraph=True)] - self.body.extend(lines) - - -class SubgraphContext(object): - """Return a blank instance of the parent and add as subgraph on exit.""" - - def __init__(self, parent, kwargs): - self.parent = parent - self.graph = parent.__class__(**kwargs) - - def __enter__(self): - return self.graph - - def __exit__(self, type_, value, traceback): - if type_ is None: - self.parent.subgraph(self.graph) - - -class Graph(Dot): - """Graph source code in the DOT language. - - Args: - name: Graph name used in the source code. - comment: Comment added to the first line of the source. - filename: Filename for saving the source (defaults to ``name`` + ``'.gv'``). - directory: (Sub)directory for source saving and rendering. - format: Rendering output format (``'pdf'``, ``'png'``, ...). - engine: Layout command used (``'dot'``, ``'neato'``, ...). - encoding: Encoding for saving the source. - graph_attr: Mapping of ``(attribute, value)`` pairs for the graph. - node_attr: Mapping of ``(attribute, value)`` pairs set for all nodes. - edge_attr: Mapping of ``(attribute, value)`` pairs set for all edges. - body: Iterable of verbatim lines to add to the graph ``body``. - strict (bool): Rendering should merge multi-edges. - - Note: - All parameters are optional and can be changed under their - corresponding attribute name after instance creation. - """ - - _head = 'graph %s{' - _head_strict = 'strict %s' % _head - _edge = '\t%s -- %s%s' - _edge_plain = _edge % ('%s', '%s', '') - - @property - def directed(self): - """``False``""" - return False - - -class Digraph(Dot): - """Directed graph source code in the DOT language.""" - - if Graph.__doc__ is not None: - __doc__ += Graph.__doc__.partition('.')[2] - - _head = 'digraph %s{' - _head_strict = 'strict %s' % _head - _edge = '\t%s -> %s%s' - _edge_plain = _edge % ('%s', '%s', '') - - @property - def directed(self): - """``True``""" - return True diff --git a/src/graphviz/files.py b/src/graphviz/files.py deleted file mode 100644 index bf1585f..0000000 --- a/src/graphviz/files.py +++ /dev/null @@ -1,311 +0,0 @@ -# files.py - save, render, view - -"""Save DOT code objects, render with Graphviz dot, and open in viewer.""" - -import os -import io -import codecs -import locale -import logging - -from ._compat import text_type - -from . import backend -from . import tools - -__all__ = ['File', 'Source'] - -ENCODING = 'utf-8' - - -log = logging.getLogger(__name__) - - -class Base(object): - - _format = 'pdf' - _engine = 'dot' - _encoding = ENCODING - - @property - def format(self): - """The output format used for rendering (``'pdf'``, ``'png'``, ...).""" - return self._format - - @format.setter - def format(self, format): - format = format.lower() - if format not in backend.FORMATS: - raise ValueError('unknown format: %r' % format) - self._format = format - - @property - def engine(self): - """The layout commmand used for rendering (``'dot'``, ``'neato'``, ...).""" - return self._engine - - @engine.setter - def engine(self, engine): - engine = engine.lower() - if engine not in backend.ENGINES: - raise ValueError('unknown engine: %r' % engine) - self._engine = engine - - @property - def encoding(self): - """The encoding for the saved source file.""" - return self._encoding - - @encoding.setter - def encoding(self, encoding): - if encoding is None: - encoding = locale.getpreferredencoding() - codecs.lookup(encoding) # raise early - self._encoding = encoding - - def copy(self): - """Return a copied instance of the object. - - Returns: - An independent copy of the current object. - """ - kwargs = self._kwargs() - return self.__class__(**kwargs) - - def _kwargs(self): - ns = self.__dict__ - return {a[1:]: ns[a] for a in ('_format', '_engine', '_encoding') - if a in ns} - - -class File(Base): - - directory = '' - - _default_extension = 'gv' - - def __init__(self, filename=None, directory=None, - format=None, engine=None, encoding=ENCODING): - if filename is None: - name = getattr(self, 'name', None) or self.__class__.__name__ - filename = '%s.%s' % (name, self._default_extension) - self.filename = filename - - if directory is not None: - self.directory = directory - - if format is not None: - self.format = format - - if engine is not None: - self.engine = engine - - self.encoding = encoding - - def _kwargs(self): - result = super(File, self)._kwargs() - result['filename'] = self.filename - if 'directory' in self.__dict__: - result['directory'] = self.directory - return result - - def _repr_svg_(self): - return self.pipe(format='svg').decode(self._encoding) - - def pipe(self, format=None, renderer=None, formatter=None, quiet=False): - """Return the source piped through the Graphviz layout command. - - Args: - format: The output format used for rendering (``'pdf'``, ``'png'``, etc.). - renderer: The output renderer used for rendering (``'cairo'``, ``'gd'``, ...). - formatter: The output formatter used for rendering (``'cairo'``, ``'gd'``, ...). - quiet (bool): Suppress ``stderr`` output from the layout subprocess. - Returns: - Binary (encoded) stdout of the layout command. - Raises: - ValueError: If ``format``, ``renderer``, or ``formatter`` are not known. - graphviz.RequiredArgumentError: If ``formatter`` is given but ``renderer`` is None. - graphviz.ExecutableNotFound: If the Graphviz executable is not found. - subprocess.CalledProcessError: If the exit status is non-zero. - """ - if format is None: - format = self._format - - data = text_type(self.source).encode(self._encoding) - - out = backend.pipe(self._engine, format, data, - renderer=renderer, formatter=formatter, - quiet=quiet) - - return out - - @property - def filepath(self): - return os.path.join(self.directory, self.filename) - - def save(self, filename=None, directory=None): - """Save the DOT source to file. Ensure the file ends with a newline. - - Args: - filename: Filename for saving the source (defaults to ``name`` + ``'.gv'``) - directory: (Sub)directory for source saving and rendering. - Returns: - The (possibly relative) path of the saved source file. - """ - if filename is not None: - self.filename = filename - if directory is not None: - self.directory = directory - - filepath = self.filepath - tools.mkdirs(filepath) - - data = text_type(self.source) - - log.debug('write %d bytes to %r', len(data), filepath) - with io.open(filepath, 'w', encoding=self.encoding) as fd: - fd.write(data) - if not data.endswith(u'\n'): - fd.write(u'\n') - - return filepath - - def render(self, filename=None, directory=None, view=False, cleanup=False, - format=None, renderer=None, formatter=None, - quiet=False, quiet_view=False): - """Save the source to file and render with the Graphviz engine. - - Args: - filename: Filename for saving the source (defaults to ``name`` + ``'.gv'``) - directory: (Sub)directory for source saving and rendering. - view (bool): Open the rendered result with the default application. - cleanup (bool): Delete the source file after rendering. - format: The output format used for rendering (``'pdf'``, ``'png'``, etc.). - renderer: The output renderer used for rendering (``'cairo'``, ``'gd'``, ...). - formatter: The output formatter used for rendering (``'cairo'``, ``'gd'``, ...). - quiet (bool): Suppress ``stderr`` output from the layout subprocess. - quiet_view (bool): Suppress ``stderr`` output from the viewer process - (implies ``view=True``, ineffective on Windows). - Returns: - The (possibly relative) path of the rendered file. - Raises: - ValueError: If ``format``, ``renderer``, or ``formatter`` are not known. - graphviz.RequiredArgumentError: If ``formatter`` is given but ``renderer`` is None. - graphviz.ExecutableNotFound: If the Graphviz executable is not found. - subprocess.CalledProcessError: If the exit status is non-zero. - RuntimeError: If viewer opening is requested but not supported. - - The layout command is started from the directory of ``filepath``, so that - references to external files (e.g. ``[image=...]``) can be given as paths - relative to the DOT source file. - """ - filepath = self.save(filename, directory) - - if format is None: - format = self._format - - rendered = backend.render(self._engine, format, filepath, - renderer=renderer, formatter=formatter, - quiet=quiet) - - if cleanup: - log.debug('delete %r', filepath) - os.remove(filepath) - - if quiet_view or view: - self._view(rendered, self._format, quiet_view) - - return rendered - - def view(self, filename=None, directory=None, cleanup=False, - quiet=False, quiet_view=False): - """Save the source to file, open the rendered result in a viewer. - - Args: - filename: Filename for saving the source (defaults to ``name`` + ``'.gv'``) - directory: (Sub)directory for source saving and rendering. - cleanup (bool): Delete the source file after rendering. - quiet (bool): Suppress ``stderr`` output from the layout subprocess. - quiet_view (bool): Suppress ``stderr`` output from the viewer process - (ineffective on Windows). - Returns: - The (possibly relative) path of the rendered file. - Raises: - graphviz.ExecutableNotFound: If the Graphviz executable is not found. - subprocess.CalledProcessError: If the exit status is non-zero. - RuntimeError: If opening the viewer is not supported. - - Short-cut method for calling :meth:`.render` with ``view=True``. - """ - return self.render(filename=filename, directory=directory, - view=True, cleanup=cleanup, - quiet=quiet, quiet_view=quiet_view) - - def _view(self, filepath, format, quiet): - """Start the right viewer based on file format and platform.""" - methodnames = [ - '_view_%s_%s' % (format, backend.PLATFORM), - '_view_%s' % backend.PLATFORM, - ] - for name in methodnames: - view_method = getattr(self, name, None) - if view_method is not None: - break - else: - raise RuntimeError('%r has no built-in viewer support for %r' - ' on %r platform' % (self.__class__, format, - backend.PLATFORM)) - view_method(filepath, quiet) - - _view_darwin = staticmethod(backend.view.darwin) - _view_freebsd = staticmethod(backend.view.freebsd) - _view_linux = staticmethod(backend.view.linux) - _view_windows = staticmethod(backend.view.windows) - - -class Source(File): - """Verbatim DOT source code string to be rendered by Graphviz. - - Args: - source: The verbatim DOT source code string. - filename: Filename for saving the source (defaults to ``'Source.gv'``). - directory: (Sub)directory for source saving and rendering. - format: Rendering output format (``'pdf'``, ``'png'``, ...). - engine: Layout command used (``'dot'``, ``'neato'``, ...). - encoding: Encoding for saving the source. - - Note: - All parameters except ``source`` are optional. All of them can be changed - under their corresponding attribute name after instance creation. - """ - - @classmethod - def from_file(cls, filename, directory=None, - format=None, engine=None, encoding=ENCODING): - """Return an instance with the source string read from the given file. - - Args: - filename: Filename for loading/saving the source. - directory: (Sub)directory for source loading/saving and rendering. - format: Rendering output format (``'pdf'``, ``'png'``, ...). - engine: Layout command used (``'dot'``, ``'neato'``, ...). - encoding: Encoding for loading/saving the source. - """ - filepath = os.path.join(directory or '', filename) - if encoding is None: - encoding = locale.getpreferredencoding() - log.debug('read %r with encoding %r', filepath, encoding) - with io.open(filepath, encoding=encoding) as fd: - source = fd.read() - return cls(source, filename, directory, format, engine, encoding) - - def __init__(self, source, filename=None, directory=None, - format=None, engine=None, encoding=ENCODING): - super(Source, self).__init__(filename, directory, - format, engine, encoding) - self.source = source #: The verbatim DOT source code string. - - def _kwargs(self): - result = super(Source, self)._kwargs() - result['source'] = self.source - return result diff --git a/src/graphviz/lang.py b/src/graphviz/lang.py deleted file mode 100644 index 8969700..0000000 --- a/src/graphviz/lang.py +++ /dev/null @@ -1,195 +0,0 @@ -# lang.py - dot language creation helpers - -"""Quote strings to be valid DOT identifiers, assemble attribute lists.""" - -import re -import collections -import functools - -from . import _compat - -from . import tools - -__all__ = ['quote', 'quote_edge', 'a_list', 'attr_list', 'escape', 'nohtml'] - -# https://www.graphviz.org/doc/info/lang.html -# https://www.graphviz.org/doc/info/attrs.html#k:escString - -HTML_STRING = re.compile(r'<.*>$', re.DOTALL) - -ID = re.compile(r'([a-zA-Z_][a-zA-Z0-9_]*|-?(\.[0-9]+|[0-9]+(\.[0-9]*)?))$') - -KEYWORDS = {'node', 'edge', 'graph', 'digraph', 'subgraph', 'strict'} - -COMPASS = {'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw', 'c', '_'} # TODO - -QUOTE_OPTIONAL_BACKSLASHES = re.compile(r'(?P(?:\\\\)*)' - r'\\?(?P")') - -ESCAPE_UNESCAPED_QUOTES = functools.partial(QUOTE_OPTIONAL_BACKSLASHES.sub, - r'\g\\\g') - - -def quote(identifier, - is_html_string=HTML_STRING.match, - is_valid_id=ID.match, dot_keywords=KEYWORDS, - escape_unescaped_quotes=ESCAPE_UNESCAPED_QUOTES): - r"""Return DOT identifier from string, quote if needed. - - >>> quote('') - '""' - - >>> quote('spam') - 'spam' - - >>> quote('spam spam') - '"spam spam"' - - >>> quote('-4.2') - '-4.2' - - >>> quote('.42') - '.42' - - >>> quote('<spam>') - '<spam>' - - >>> quote(nohtml('<>')) - '"<>"' - - >>> print(quote('"')) - "\"" - - >>> print(quote('\\"')) - "\"" - - >>> print(quote('\\\\"')) - "\\\"" - - >>> print(quote('\\\\\\"')) - "\\\"" - """ - if is_html_string(identifier) and not isinstance(identifier, NoHtml): - pass - elif not is_valid_id(identifier) or identifier.lower() in dot_keywords: - return '"%s"' % escape_unescaped_quotes(identifier) - return identifier - - -def quote_edge(identifier): - """Return DOT edge statement node_id from string, quote if needed. - - >>> quote_edge('spam') - 'spam' - - >>> quote_edge('spam spam:eggs eggs') - '"spam spam":"eggs eggs"' - - >>> quote_edge('spam:eggs:s') - 'spam:eggs:s' - """ - node, _, rest = identifier.partition(':') - parts = [quote(node)] - if rest: - port, _, compass = rest.partition(':') - parts.append(quote(port)) - if compass: - parts.append(compass) - return ':'.join(parts) - - -def a_list(label=None, kwargs=None, attributes=None): - """Return assembled DOT a_list string. - - >>> a_list('spam', {'spam': None, 'ham': 'ham ham', 'eggs': ''}) - 'label=spam eggs="" ham="ham ham"' - """ - result = ['label=%s' % quote(label)] if label is not None else [] - if kwargs: - items = ['%s=%s' % (quote(k), quote(v)) - for k, v in tools.mapping_items(kwargs) if v is not None] - result.extend(items) - if attributes: - if hasattr(attributes, 'items'): - attributes = tools.mapping_items(attributes) - items = ['%s=%s' % (quote(k), quote(v)) - for k, v in attributes if v is not None] - result.extend(items) - return ' '.join(result) - - -def attr_list(label=None, kwargs=None, attributes=None): - """Return assembled DOT attribute list string. - - Sorts ``kwargs`` and ``attributes`` if they are plain dicts (to avoid - unpredictable order from hash randomization in Python 3 versions). - - >>> attr_list() - '' - - >>> attr_list('spam spam', kwargs={'eggs': 'eggs', 'ham': 'ham ham'}) - ' [label="spam spam" eggs=eggs ham="ham ham"]' - - >>> attr_list(kwargs={'spam': None, 'eggs': ''}) - ' [eggs=""]' - """ - content = a_list(label, kwargs, attributes) - if not content: - return '' - return ' [%s]' % content - - -def escape(s): - r"""Return ``s`` as literal disabling special meaning of backslashes and ``'<...>'``. - - see also https://www.graphviz.org/doc/info/attrs.html#k:escString - - Args: - s: String in which backslashes and ``'<...>'`` should be treated as literal. - Raises: - TypeError: If ``s`` is not a ``str`` on Python 3, or a ``str``/``unicode`` on Python 2. - - >>> print(escape(r'\l')) - \\l - """ - return nohtml(s.replace('\\', '\\\\')) - - -class NoHtml(object): - """Mixin for string subclasses disabling fall-through of ``'<...>'``.""" - - __slots__ = () - - _doc = "%s subclass that does not treat ``'<...>'`` as DOT HTML string." - - @classmethod - def _subcls(cls, other): - name = '%s_%s' % (cls.__name__, other.__name__) - bases = (other, cls) - ns = {'__doc__': cls._doc % other.__name__} - return type(name, bases, ns) - - -NOHTML = collections.OrderedDict((c, NoHtml._subcls(c)) for c in _compat.string_classes) - - -def nohtml(s): - """Return copy of ``s`` that will not treat ``'<...>'`` as DOT HTML string in quoting. - - Args: - s: String in which leading ``'<'`` and trailing ``'>'`` should be treated as literal. - Raises: - TypeError: If ``s`` is not a ``str`` on Python 3, or a ``str``/``unicode`` on Python 2. - - >>> quote('<>-*-<>') - '<>-*-<>' - - >>> quote(nohtml('<>-*-<>')) - '"<>-*-<>"' - """ - try: - subcls = NOHTML[type(s)] - except KeyError: - raise TypeError('%r does not have one of the required types:' - ' %r' % (s, list(NOHTML))) - return subcls(s) diff --git a/src/graphviz/tools.py b/src/graphviz/tools.py deleted file mode 100644 index ef435b7..0000000 --- a/src/graphviz/tools.py +++ /dev/null @@ -1,47 +0,0 @@ -# tools.py - generic helpers - -import os - -from . import _compat - -__all__ = ['attach', 'mkdirs', 'mapping_items'] - - -def attach(object, name): - """Return a decorator doing ``setattr(object, name)`` with its argument. - - >>> spam = type('Spam', (object,), {})() - >>> @attach(spam, 'eggs') - ... def func(): - ... pass - >>> spam.eggs # doctest: +ELLIPSIS - - """ - def decorator(func): - setattr(object, name, func) - return func - return decorator - - -def mkdirs(filename, mode=0o777): - """Recursively create directories up to the path of ``filename`` as needed.""" - dirname = os.path.dirname(filename) - if not dirname: - return - _compat.makedirs(dirname, mode=mode, exist_ok=True) - - -def mapping_items(mapping): - """Return an iterator over the ``mapping`` items, sort if it's a plain dict. - - >>> list(mapping_items({'spam': 0, 'ham': 1, 'eggs': 2})) - [('eggs', 2), ('ham', 1), ('spam', 0)] - - >>> from collections import OrderedDict - >>> list(mapping_items(OrderedDict(enumerate(['spam', 'ham', 'eggs'])))) - [(0, 'spam'), (1, 'ham'), (2, 'eggs')] - """ - result = _compat.iteritems(mapping) - if type(mapping) is dict: - result = iter(sorted(result)) - return result diff --git a/src/wireviz/__init__.py b/src/wireviz/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/wireviz/build_examples.py b/src/wireviz/build_examples.py new file mode 100644 index 0000000..d989ae1 --- /dev/null +++ b/src/wireviz/build_examples.py @@ -0,0 +1,54 @@ +import wireviz +import os + +demos = 2 # 2 +<<<<<<< HEAD:src/wireviz/batch.py +examples = 9 # 9 +======= +examples = 6 # 6 +>>>>>>> 2d428e8... refactor dependencies and installation:src/wireviz/build_examples.py +tutorials = 7 # 7 + +if demos: + for i in range(1,demos+1): + fn = '../examples/demo{:02d}.yml'.format(i) + print(fn) + wireviz.parse(fn, gen_bom=True) + +if examples: + with open(os.path.abspath('../examples/readme.md'), 'w') as file: + file.write('# Example gallery\n') + for i in range(1,examples+1): + fn = '../examples/ex{:02d}.yml'.format(i) + print(fn) + wireviz.parse(fn, gen_bom=True) + + file.write('## Example {:02d}\n'.format(i)) + file.write('![](ex{:02d}.png)\n\n'.format(i)) + file.write('[Source](ex{:02d}.yml) - [Bill of Materials](ex{:02d}.bom.tsv)\n\n\n'.format(i,i)) + +if tutorials: + with open(os.path.abspath('../tutorial/readme.md'), 'w') as file: + file.write('# WireViz Tutorial\n') + for i in range(1,tutorials+1): + fn = '../tutorial/tutorial{:02d}.yml'.format(i) + print(fn) + wireviz.parse(fn, gen_bom=True) + + with open(os.path.abspath('../tutorial/tutorial{:02d}.md'.format(i)), 'r') as info: + for line in info: + file.write(line.replace('## ', '## {} - '.format(i))) + file.write('\n[Source](tutorial{:02d}.yml):\n\n'.format(i)) + + with open(os.path.abspath('../tutorial/tutorial{:02d}.yml'.format(i)), 'r') as src: + file.write('```yaml\n') + for line in src: + file.write(line) + file.write('```\n') + file.write('\n') + + file.write('\nOutput:\n\n'.format(i)) + + file.write('![](tutorial{:02d}.png)\n\n'.format(i)) + + file.write('[Bill of Materials](tutorial{:02d}.bom.tsv)\n\n\n'.format(i)) diff --git a/src/wireviz/wireviz.py b/src/wireviz/wireviz.py index 2be00a2..ceb350a 100755 --- a/src/wireviz/wireviz.py +++ b/src/wireviz/wireviz.py @@ -1,4 +1,6 @@ #!/usr/bin/env python3 + +import argparse import os from dataclasses import dataclass, field from typing import Any, List @@ -6,8 +8,8 @@ from collections import Counter import yaml from graphviz import Graph -import wv_colors -from wv_helper import nested, int2tuple, awg_equiv, flatten2d, tuplelist2tsv +from wireviz import wv_colors +from wireviz.wv_helper import nested, int2tuple, awg_equiv, flatten2d, tuplelist2tsv class Harness: @@ -620,8 +622,7 @@ def parse(file_in, file_out=None, gen_bom=False): h.output(filename=file_out, format=('png','svg'), gen_bom=gen_bom, view=False) -if __name__ == '__main__': - import argparse +def main(): ap = argparse.ArgumentParser() ap.add_argument('file_input', nargs='?', default='_test/test.yml') ap.add_argument('file_output', nargs='?', default=None) @@ -629,3 +630,6 @@ if __name__ == '__main__': args = ap.parse_args() parse(args.file_input, file_out=args.file_output, gen_bom=args.bom) + +if __name__ == '__main__': + main() diff --git a/src/yaml/__init__.py b/src/yaml/__init__.py deleted file mode 100644 index 13d687c..0000000 --- a/src/yaml/__init__.py +++ /dev/null @@ -1,427 +0,0 @@ - -from .error import * - -from .tokens import * -from .events import * -from .nodes import * - -from .loader import * -from .dumper import * - -__version__ = '5.3.1' -try: - from .cyaml import * - __with_libyaml__ = True -except ImportError: - __with_libyaml__ = False - -import io - -#------------------------------------------------------------------------------ -# Warnings control -#------------------------------------------------------------------------------ - -# 'Global' warnings state: -_warnings_enabled = { - 'YAMLLoadWarning': True, -} - -# Get or set global warnings' state -def warnings(settings=None): - if settings is None: - return _warnings_enabled - - if type(settings) is dict: - for key in settings: - if key in _warnings_enabled: - _warnings_enabled[key] = settings[key] - -# Warn when load() is called without Loader=... -class YAMLLoadWarning(RuntimeWarning): - pass - -def load_warning(method): - if _warnings_enabled['YAMLLoadWarning'] is False: - return - - import warnings - - message = ( - "calling yaml.%s() without Loader=... is deprecated, as the " - "default Loader is unsafe. Please read " - "https://msg.pyyaml.org/load for full details." - ) % method - - warnings.warn(message, YAMLLoadWarning, stacklevel=3) - -#------------------------------------------------------------------------------ -def scan(stream, Loader=Loader): - """ - Scan a YAML stream and produce scanning tokens. - """ - loader = Loader(stream) - try: - while loader.check_token(): - yield loader.get_token() - finally: - loader.dispose() - -def parse(stream, Loader=Loader): - """ - Parse a YAML stream and produce parsing events. - """ - loader = Loader(stream) - try: - while loader.check_event(): - yield loader.get_event() - finally: - loader.dispose() - -def compose(stream, Loader=Loader): - """ - Parse the first YAML document in a stream - and produce the corresponding representation tree. - """ - loader = Loader(stream) - try: - return loader.get_single_node() - finally: - loader.dispose() - -def compose_all(stream, Loader=Loader): - """ - Parse all YAML documents in a stream - and produce corresponding representation trees. - """ - loader = Loader(stream) - try: - while loader.check_node(): - yield loader.get_node() - finally: - loader.dispose() - -def load(stream, Loader=None): - """ - Parse the first YAML document in a stream - and produce the corresponding Python object. - """ - if Loader is None: - load_warning('load') - Loader = FullLoader - - loader = Loader(stream) - try: - return loader.get_single_data() - finally: - loader.dispose() - -def load_all(stream, Loader=None): - """ - Parse all YAML documents in a stream - and produce corresponding Python objects. - """ - if Loader is None: - load_warning('load_all') - Loader = FullLoader - - loader = Loader(stream) - try: - while loader.check_data(): - yield loader.get_data() - finally: - loader.dispose() - -def full_load(stream): - """ - Parse the first YAML document in a stream - and produce the corresponding Python object. - - Resolve all tags except those known to be - unsafe on untrusted input. - """ - return load(stream, FullLoader) - -def full_load_all(stream): - """ - Parse all YAML documents in a stream - and produce corresponding Python objects. - - Resolve all tags except those known to be - unsafe on untrusted input. - """ - return load_all(stream, FullLoader) - -def safe_load(stream): - """ - Parse the first YAML document in a stream - and produce the corresponding Python object. - - Resolve only basic YAML tags. This is known - to be safe for untrusted input. - """ - return load(stream, SafeLoader) - -def safe_load_all(stream): - """ - Parse all YAML documents in a stream - and produce corresponding Python objects. - - Resolve only basic YAML tags. This is known - to be safe for untrusted input. - """ - return load_all(stream, SafeLoader) - -def unsafe_load(stream): - """ - Parse the first YAML document in a stream - and produce the corresponding Python object. - - Resolve all tags, even those known to be - unsafe on untrusted input. - """ - return load(stream, UnsafeLoader) - -def unsafe_load_all(stream): - """ - Parse all YAML documents in a stream - and produce corresponding Python objects. - - Resolve all tags, even those known to be - unsafe on untrusted input. - """ - return load_all(stream, UnsafeLoader) - -def emit(events, stream=None, Dumper=Dumper, - canonical=None, indent=None, width=None, - allow_unicode=None, line_break=None): - """ - Emit YAML parsing events into a stream. - If stream is None, return the produced string instead. - """ - getvalue = None - if stream is None: - stream = io.StringIO() - getvalue = stream.getvalue - dumper = Dumper(stream, canonical=canonical, indent=indent, width=width, - allow_unicode=allow_unicode, line_break=line_break) - try: - for event in events: - dumper.emit(event) - finally: - dumper.dispose() - if getvalue: - return getvalue() - -def serialize_all(nodes, stream=None, Dumper=Dumper, - canonical=None, indent=None, width=None, - allow_unicode=None, line_break=None, - encoding=None, explicit_start=None, explicit_end=None, - version=None, tags=None): - """ - Serialize a sequence of representation trees into a YAML stream. - If stream is None, return the produced string instead. - """ - getvalue = None - if stream is None: - if encoding is None: - stream = io.StringIO() - else: - stream = io.BytesIO() - getvalue = stream.getvalue - dumper = Dumper(stream, canonical=canonical, indent=indent, width=width, - allow_unicode=allow_unicode, line_break=line_break, - encoding=encoding, version=version, tags=tags, - explicit_start=explicit_start, explicit_end=explicit_end) - try: - dumper.open() - for node in nodes: - dumper.serialize(node) - dumper.close() - finally: - dumper.dispose() - if getvalue: - return getvalue() - -def serialize(node, stream=None, Dumper=Dumper, **kwds): - """ - Serialize a representation tree into a YAML stream. - If stream is None, return the produced string instead. - """ - return serialize_all([node], stream, Dumper=Dumper, **kwds) - -def dump_all(documents, stream=None, Dumper=Dumper, - default_style=None, default_flow_style=False, - canonical=None, indent=None, width=None, - allow_unicode=None, line_break=None, - encoding=None, explicit_start=None, explicit_end=None, - version=None, tags=None, sort_keys=True): - """ - Serialize a sequence of Python objects into a YAML stream. - If stream is None, return the produced string instead. - """ - getvalue = None - if stream is None: - if encoding is None: - stream = io.StringIO() - else: - stream = io.BytesIO() - getvalue = stream.getvalue - dumper = Dumper(stream, default_style=default_style, - default_flow_style=default_flow_style, - canonical=canonical, indent=indent, width=width, - allow_unicode=allow_unicode, line_break=line_break, - encoding=encoding, version=version, tags=tags, - explicit_start=explicit_start, explicit_end=explicit_end, sort_keys=sort_keys) - try: - dumper.open() - for data in documents: - dumper.represent(data) - dumper.close() - finally: - dumper.dispose() - if getvalue: - return getvalue() - -def dump(data, stream=None, Dumper=Dumper, **kwds): - """ - Serialize a Python object into a YAML stream. - If stream is None, return the produced string instead. - """ - return dump_all([data], stream, Dumper=Dumper, **kwds) - -def safe_dump_all(documents, stream=None, **kwds): - """ - Serialize a sequence of Python objects into a YAML stream. - Produce only basic YAML tags. - If stream is None, return the produced string instead. - """ - return dump_all(documents, stream, Dumper=SafeDumper, **kwds) - -def safe_dump(data, stream=None, **kwds): - """ - Serialize a Python object into a YAML stream. - Produce only basic YAML tags. - If stream is None, return the produced string instead. - """ - return dump_all([data], stream, Dumper=SafeDumper, **kwds) - -def add_implicit_resolver(tag, regexp, first=None, - Loader=None, Dumper=Dumper): - """ - Add an implicit scalar detector. - If an implicit scalar value matches the given regexp, - the corresponding tag is assigned to the scalar. - first is a sequence of possible initial characters or None. - """ - if Loader is None: - loader.Loader.add_implicit_resolver(tag, regexp, first) - loader.FullLoader.add_implicit_resolver(tag, regexp, first) - loader.UnsafeLoader.add_implicit_resolver(tag, regexp, first) - else: - Loader.add_implicit_resolver(tag, regexp, first) - Dumper.add_implicit_resolver(tag, regexp, first) - -def add_path_resolver(tag, path, kind=None, Loader=None, Dumper=Dumper): - """ - Add a path based resolver for the given tag. - A path is a list of keys that forms a path - to a node in the representation tree. - Keys can be string values, integers, or None. - """ - if Loader is None: - loader.Loader.add_path_resolver(tag, path, kind) - loader.FullLoader.add_path_resolver(tag, path, kind) - loader.UnsafeLoader.add_path_resolver(tag, path, kind) - else: - Loader.add_path_resolver(tag, path, kind) - Dumper.add_path_resolver(tag, path, kind) - -def add_constructor(tag, constructor, Loader=None): - """ - Add a constructor for the given tag. - Constructor is a function that accepts a Loader instance - and a node object and produces the corresponding Python object. - """ - if Loader is None: - loader.Loader.add_constructor(tag, constructor) - loader.FullLoader.add_constructor(tag, constructor) - loader.UnsafeLoader.add_constructor(tag, constructor) - else: - Loader.add_constructor(tag, constructor) - -def add_multi_constructor(tag_prefix, multi_constructor, Loader=None): - """ - Add a multi-constructor for the given tag prefix. - Multi-constructor is called for a node if its tag starts with tag_prefix. - Multi-constructor accepts a Loader instance, a tag suffix, - and a node object and produces the corresponding Python object. - """ - if Loader is None: - loader.Loader.add_multi_constructor(tag_prefix, multi_constructor) - loader.FullLoader.add_multi_constructor(tag_prefix, multi_constructor) - loader.UnsafeLoader.add_multi_constructor(tag_prefix, multi_constructor) - else: - Loader.add_multi_constructor(tag_prefix, multi_constructor) - -def add_representer(data_type, representer, Dumper=Dumper): - """ - Add a representer for the given type. - Representer is a function accepting a Dumper instance - and an instance of the given data type - and producing the corresponding representation node. - """ - Dumper.add_representer(data_type, representer) - -def add_multi_representer(data_type, multi_representer, Dumper=Dumper): - """ - Add a representer for the given type. - Multi-representer is a function accepting a Dumper instance - and an instance of the given data type or subtype - and producing the corresponding representation node. - """ - Dumper.add_multi_representer(data_type, multi_representer) - -class YAMLObjectMetaclass(type): - """ - The metaclass for YAMLObject. - """ - def __init__(cls, name, bases, kwds): - super(YAMLObjectMetaclass, cls).__init__(name, bases, kwds) - if 'yaml_tag' in kwds and kwds['yaml_tag'] is not None: - if isinstance(cls.yaml_loader, list): - for loader in cls.yaml_loader: - loader.add_constructor(cls.yaml_tag, cls.from_yaml) - else: - cls.yaml_loader.add_constructor(cls.yaml_tag, cls.from_yaml) - - cls.yaml_dumper.add_representer(cls, cls.to_yaml) - -class YAMLObject(metaclass=YAMLObjectMetaclass): - """ - An object that can dump itself to a YAML stream - and load itself from a YAML stream. - """ - - __slots__ = () # no direct instantiation, so allow immutable subclasses - - yaml_loader = [Loader, FullLoader, UnsafeLoader] - yaml_dumper = Dumper - - yaml_tag = None - yaml_flow_style = None - - @classmethod - def from_yaml(cls, loader, node): - """ - Convert a representation node to a Python object. - """ - return loader.construct_yaml_object(node, cls) - - @classmethod - def to_yaml(cls, dumper, data): - """ - Convert a Python object to a representation node. - """ - return dumper.represent_yaml_object(cls.yaml_tag, data, cls, - flow_style=cls.yaml_flow_style) - diff --git a/src/yaml/composer.py b/src/yaml/composer.py deleted file mode 100644 index 6d15cb4..0000000 --- a/src/yaml/composer.py +++ /dev/null @@ -1,139 +0,0 @@ - -__all__ = ['Composer', 'ComposerError'] - -from .error import MarkedYAMLError -from .events import * -from .nodes import * - -class ComposerError(MarkedYAMLError): - pass - -class Composer: - - def __init__(self): - self.anchors = {} - - def check_node(self): - # Drop the STREAM-START event. - if self.check_event(StreamStartEvent): - self.get_event() - - # If there are more documents available? - return not self.check_event(StreamEndEvent) - - def get_node(self): - # Get the root node of the next document. - if not self.check_event(StreamEndEvent): - return self.compose_document() - - def get_single_node(self): - # Drop the STREAM-START event. - self.get_event() - - # Compose a document if the stream is not empty. - document = None - if not self.check_event(StreamEndEvent): - document = self.compose_document() - - # Ensure that the stream contains no more documents. - if not self.check_event(StreamEndEvent): - event = self.get_event() - raise ComposerError("expected a single document in the stream", - document.start_mark, "but found another document", - event.start_mark) - - # Drop the STREAM-END event. - self.get_event() - - return document - - def compose_document(self): - # Drop the DOCUMENT-START event. - self.get_event() - - # Compose the root node. - node = self.compose_node(None, None) - - # Drop the DOCUMENT-END event. - self.get_event() - - self.anchors = {} - return node - - def compose_node(self, parent, index): - if self.check_event(AliasEvent): - event = self.get_event() - anchor = event.anchor - if anchor not in self.anchors: - raise ComposerError(None, None, "found undefined alias %r" - % anchor, event.start_mark) - return self.anchors[anchor] - event = self.peek_event() - anchor = event.anchor - if anchor is not None: - if anchor in self.anchors: - raise ComposerError("found duplicate anchor %r; first occurrence" - % anchor, self.anchors[anchor].start_mark, - "second occurrence", event.start_mark) - self.descend_resolver(parent, index) - if self.check_event(ScalarEvent): - node = self.compose_scalar_node(anchor) - elif self.check_event(SequenceStartEvent): - node = self.compose_sequence_node(anchor) - elif self.check_event(MappingStartEvent): - node = self.compose_mapping_node(anchor) - self.ascend_resolver() - return node - - def compose_scalar_node(self, anchor): - event = self.get_event() - tag = event.tag - if tag is None or tag == '!': - tag = self.resolve(ScalarNode, event.value, event.implicit) - node = ScalarNode(tag, event.value, - event.start_mark, event.end_mark, style=event.style) - if anchor is not None: - self.anchors[anchor] = node - return node - - def compose_sequence_node(self, anchor): - start_event = self.get_event() - tag = start_event.tag - if tag is None or tag == '!': - tag = self.resolve(SequenceNode, None, start_event.implicit) - node = SequenceNode(tag, [], - start_event.start_mark, None, - flow_style=start_event.flow_style) - if anchor is not None: - self.anchors[anchor] = node - index = 0 - while not self.check_event(SequenceEndEvent): - node.value.append(self.compose_node(node, index)) - index += 1 - end_event = self.get_event() - node.end_mark = end_event.end_mark - return node - - def compose_mapping_node(self, anchor): - start_event = self.get_event() - tag = start_event.tag - if tag is None or tag == '!': - tag = self.resolve(MappingNode, None, start_event.implicit) - node = MappingNode(tag, [], - start_event.start_mark, None, - flow_style=start_event.flow_style) - if anchor is not None: - self.anchors[anchor] = node - while not self.check_event(MappingEndEvent): - #key_event = self.peek_event() - item_key = self.compose_node(node, None) - #if item_key in node.value: - # raise ComposerError("while composing a mapping", start_event.start_mark, - # "found duplicate key", key_event.start_mark) - item_value = self.compose_node(node, item_key) - #node.value[item_key] = item_value - node.value.append((item_key, item_value)) - end_event = self.get_event() - node.end_mark = end_event.end_mark - return node - diff --git a/src/yaml/constructor.py b/src/yaml/constructor.py deleted file mode 100644 index 1948b12..0000000 --- a/src/yaml/constructor.py +++ /dev/null @@ -1,748 +0,0 @@ - -__all__ = [ - 'BaseConstructor', - 'SafeConstructor', - 'FullConstructor', - 'UnsafeConstructor', - 'Constructor', - 'ConstructorError' -] - -from .error import * -from .nodes import * - -import collections.abc, datetime, base64, binascii, re, sys, types - -class ConstructorError(MarkedYAMLError): - pass - -class BaseConstructor: - - yaml_constructors = {} - yaml_multi_constructors = {} - - def __init__(self): - self.constructed_objects = {} - self.recursive_objects = {} - self.state_generators = [] - self.deep_construct = False - - def check_data(self): - # If there are more documents available? - return self.check_node() - - def check_state_key(self, key): - """Block special attributes/methods from being set in a newly created - object, to prevent user-controlled methods from being called during - deserialization""" - if self.get_state_keys_blacklist_regexp().match(key): - raise ConstructorError(None, None, - "blacklisted key '%s' in instance state found" % (key,), None) - - def get_data(self): - # Construct and return the next document. - if self.check_node(): - return self.construct_document(self.get_node()) - - def get_single_data(self): - # Ensure that the stream contains a single document and construct it. - node = self.get_single_node() - if node is not None: - return self.construct_document(node) - return None - - def construct_document(self, node): - data = self.construct_object(node) - while self.state_generators: - state_generators = self.state_generators - self.state_generators = [] - for generator in state_generators: - for dummy in generator: - pass - self.constructed_objects = {} - self.recursive_objects = {} - self.deep_construct = False - return data - - def construct_object(self, node, deep=False): - if node in self.constructed_objects: - return self.constructed_objects[node] - if deep: - old_deep = self.deep_construct - self.deep_construct = True - if node in self.recursive_objects: - raise ConstructorError(None, None, - "found unconstructable recursive node", node.start_mark) - self.recursive_objects[node] = None - constructor = None - tag_suffix = None - if node.tag in self.yaml_constructors: - constructor = self.yaml_constructors[node.tag] - else: - for tag_prefix in self.yaml_multi_constructors: - if tag_prefix is not None and node.tag.startswith(tag_prefix): - tag_suffix = node.tag[len(tag_prefix):] - constructor = self.yaml_multi_constructors[tag_prefix] - break - else: - if None in self.yaml_multi_constructors: - tag_suffix = node.tag - constructor = self.yaml_multi_constructors[None] - elif None in self.yaml_constructors: - constructor = self.yaml_constructors[None] - elif isinstance(node, ScalarNode): - constructor = self.__class__.construct_scalar - elif isinstance(node, SequenceNode): - constructor = self.__class__.construct_sequence - elif isinstance(node, MappingNode): - constructor = self.__class__.construct_mapping - if tag_suffix is None: - data = constructor(self, node) - else: - data = constructor(self, tag_suffix, node) - if isinstance(data, types.GeneratorType): - generator = data - data = next(generator) - if self.deep_construct: - for dummy in generator: - pass - else: - self.state_generators.append(generator) - self.constructed_objects[node] = data - del self.recursive_objects[node] - if deep: - self.deep_construct = old_deep - return data - - def construct_scalar(self, node): - if not isinstance(node, ScalarNode): - raise ConstructorError(None, None, - "expected a scalar node, but found %s" % node.id, - node.start_mark) - return node.value - - def construct_sequence(self, node, deep=False): - if not isinstance(node, SequenceNode): - raise ConstructorError(None, None, - "expected a sequence node, but found %s" % node.id, - node.start_mark) - return [self.construct_object(child, deep=deep) - for child in node.value] - - def construct_mapping(self, node, deep=False): - if not isinstance(node, MappingNode): - raise ConstructorError(None, None, - "expected a mapping node, but found %s" % node.id, - node.start_mark) - mapping = {} - for key_node, value_node in node.value: - key = self.construct_object(key_node, deep=deep) - if not isinstance(key, collections.abc.Hashable): - raise ConstructorError("while constructing a mapping", node.start_mark, - "found unhashable key", key_node.start_mark) - value = self.construct_object(value_node, deep=deep) - mapping[key] = value - return mapping - - def construct_pairs(self, node, deep=False): - if not isinstance(node, MappingNode): - raise ConstructorError(None, None, - "expected a mapping node, but found %s" % node.id, - node.start_mark) - pairs = [] - for key_node, value_node in node.value: - key = self.construct_object(key_node, deep=deep) - value = self.construct_object(value_node, deep=deep) - pairs.append((key, value)) - return pairs - - @classmethod - def add_constructor(cls, tag, constructor): - if not 'yaml_constructors' in cls.__dict__: - cls.yaml_constructors = cls.yaml_constructors.copy() - cls.yaml_constructors[tag] = constructor - - @classmethod - def add_multi_constructor(cls, tag_prefix, multi_constructor): - if not 'yaml_multi_constructors' in cls.__dict__: - cls.yaml_multi_constructors = cls.yaml_multi_constructors.copy() - cls.yaml_multi_constructors[tag_prefix] = multi_constructor - -class SafeConstructor(BaseConstructor): - - def construct_scalar(self, node): - if isinstance(node, MappingNode): - for key_node, value_node in node.value: - if key_node.tag == 'tag:yaml.org,2002:value': - return self.construct_scalar(value_node) - return super().construct_scalar(node) - - def flatten_mapping(self, node): - merge = [] - index = 0 - while index < len(node.value): - key_node, value_node = node.value[index] - if key_node.tag == 'tag:yaml.org,2002:merge': - del node.value[index] - if isinstance(value_node, MappingNode): - self.flatten_mapping(value_node) - merge.extend(value_node.value) - elif isinstance(value_node, SequenceNode): - submerge = [] - for subnode in value_node.value: - if not isinstance(subnode, MappingNode): - raise ConstructorError("while constructing a mapping", - node.start_mark, - "expected a mapping for merging, but found %s" - % subnode.id, subnode.start_mark) - self.flatten_mapping(subnode) - submerge.append(subnode.value) - submerge.reverse() - for value in submerge: - merge.extend(value) - else: - raise ConstructorError("while constructing a mapping", node.start_mark, - "expected a mapping or list of mappings for merging, but found %s" - % value_node.id, value_node.start_mark) - elif key_node.tag == 'tag:yaml.org,2002:value': - key_node.tag = 'tag:yaml.org,2002:str' - index += 1 - else: - index += 1 - if merge: - node.value = merge + node.value - - def construct_mapping(self, node, deep=False): - if isinstance(node, MappingNode): - self.flatten_mapping(node) - return super().construct_mapping(node, deep=deep) - - def construct_yaml_null(self, node): - self.construct_scalar(node) - return None - - bool_values = { - 'yes': True, - 'no': False, - 'true': True, - 'false': False, - 'on': True, - 'off': False, - } - - def construct_yaml_bool(self, node): - value = self.construct_scalar(node) - return self.bool_values[value.lower()] - - def construct_yaml_int(self, node): - value = self.construct_scalar(node) - value = value.replace('_', '') - sign = +1 - if value[0] == '-': - sign = -1 - if value[0] in '+-': - value = value[1:] - if value == '0': - return 0 - elif value.startswith('0b'): - return sign*int(value[2:], 2) - elif value.startswith('0x'): - return sign*int(value[2:], 16) - elif value[0] == '0': - return sign*int(value, 8) - elif ':' in value: - digits = [int(part) for part in value.split(':')] - digits.reverse() - base = 1 - value = 0 - for digit in digits: - value += digit*base - base *= 60 - return sign*value - else: - return sign*int(value) - - inf_value = 1e300 - while inf_value != inf_value*inf_value: - inf_value *= inf_value - nan_value = -inf_value/inf_value # Trying to make a quiet NaN (like C99). - - def construct_yaml_float(self, node): - value = self.construct_scalar(node) - value = value.replace('_', '').lower() - sign = +1 - if value[0] == '-': - sign = -1 - if value[0] in '+-': - value = value[1:] - if value == '.inf': - return sign*self.inf_value - elif value == '.nan': - return self.nan_value - elif ':' in value: - digits = [float(part) for part in value.split(':')] - digits.reverse() - base = 1 - value = 0.0 - for digit in digits: - value += digit*base - base *= 60 - return sign*value - else: - return sign*float(value) - - def construct_yaml_binary(self, node): - try: - value = self.construct_scalar(node).encode('ascii') - except UnicodeEncodeError as exc: - raise ConstructorError(None, None, - "failed to convert base64 data into ascii: %s" % exc, - node.start_mark) - try: - if hasattr(base64, 'decodebytes'): - return base64.decodebytes(value) - else: - return base64.decodestring(value) - except binascii.Error as exc: - raise ConstructorError(None, None, - "failed to decode base64 data: %s" % exc, node.start_mark) - - timestamp_regexp = re.compile( - r'''^(?P[0-9][0-9][0-9][0-9]) - -(?P[0-9][0-9]?) - -(?P[0-9][0-9]?) - (?:(?:[Tt]|[ \t]+) - (?P[0-9][0-9]?) - :(?P[0-9][0-9]) - :(?P[0-9][0-9]) - (?:\.(?P[0-9]*))? - (?:[ \t]*(?PZ|(?P[-+])(?P[0-9][0-9]?) - (?::(?P[0-9][0-9]))?))?)?$''', re.X) - - def construct_yaml_timestamp(self, node): - value = self.construct_scalar(node) - match = self.timestamp_regexp.match(node.value) - values = match.groupdict() - year = int(values['year']) - month = int(values['month']) - day = int(values['day']) - if not values['hour']: - return datetime.date(year, month, day) - hour = int(values['hour']) - minute = int(values['minute']) - second = int(values['second']) - fraction = 0 - tzinfo = None - if values['fraction']: - fraction = values['fraction'][:6] - while len(fraction) < 6: - fraction += '0' - fraction = int(fraction) - if values['tz_sign']: - tz_hour = int(values['tz_hour']) - tz_minute = int(values['tz_minute'] or 0) - delta = datetime.timedelta(hours=tz_hour, minutes=tz_minute) - if values['tz_sign'] == '-': - delta = -delta - tzinfo = datetime.timezone(delta) - elif values['tz']: - tzinfo = datetime.timezone.utc - return datetime.datetime(year, month, day, hour, minute, second, fraction, - tzinfo=tzinfo) - - def construct_yaml_omap(self, node): - # Note: we do not check for duplicate keys, because it's too - # CPU-expensive. - omap = [] - yield omap - if not isinstance(node, SequenceNode): - raise ConstructorError("while constructing an ordered map", node.start_mark, - "expected a sequence, but found %s" % node.id, node.start_mark) - for subnode in node.value: - if not isinstance(subnode, MappingNode): - raise ConstructorError("while constructing an ordered map", node.start_mark, - "expected a mapping of length 1, but found %s" % subnode.id, - subnode.start_mark) - if len(subnode.value) != 1: - raise ConstructorError("while constructing an ordered map", node.start_mark, - "expected a single mapping item, but found %d items" % len(subnode.value), - subnode.start_mark) - key_node, value_node = subnode.value[0] - key = self.construct_object(key_node) - value = self.construct_object(value_node) - omap.append((key, value)) - - def construct_yaml_pairs(self, node): - # Note: the same code as `construct_yaml_omap`. - pairs = [] - yield pairs - if not isinstance(node, SequenceNode): - raise ConstructorError("while constructing pairs", node.start_mark, - "expected a sequence, but found %s" % node.id, node.start_mark) - for subnode in node.value: - if not isinstance(subnode, MappingNode): - raise ConstructorError("while constructing pairs", node.start_mark, - "expected a mapping of length 1, but found %s" % subnode.id, - subnode.start_mark) - if len(subnode.value) != 1: - raise ConstructorError("while constructing pairs", node.start_mark, - "expected a single mapping item, but found %d items" % len(subnode.value), - subnode.start_mark) - key_node, value_node = subnode.value[0] - key = self.construct_object(key_node) - value = self.construct_object(value_node) - pairs.append((key, value)) - - def construct_yaml_set(self, node): - data = set() - yield data - value = self.construct_mapping(node) - data.update(value) - - def construct_yaml_str(self, node): - return self.construct_scalar(node) - - def construct_yaml_seq(self, node): - data = [] - yield data - data.extend(self.construct_sequence(node)) - - def construct_yaml_map(self, node): - data = {} - yield data - value = self.construct_mapping(node) - data.update(value) - - def construct_yaml_object(self, node, cls): - data = cls.__new__(cls) - yield data - if hasattr(data, '__setstate__'): - state = self.construct_mapping(node, deep=True) - data.__setstate__(state) - else: - state = self.construct_mapping(node) - data.__dict__.update(state) - - def construct_undefined(self, node): - raise ConstructorError(None, None, - "could not determine a constructor for the tag %r" % node.tag, - node.start_mark) - -SafeConstructor.add_constructor( - 'tag:yaml.org,2002:null', - SafeConstructor.construct_yaml_null) - -SafeConstructor.add_constructor( - 'tag:yaml.org,2002:bool', - SafeConstructor.construct_yaml_bool) - -SafeConstructor.add_constructor( - 'tag:yaml.org,2002:int', - SafeConstructor.construct_yaml_int) - -SafeConstructor.add_constructor( - 'tag:yaml.org,2002:float', - SafeConstructor.construct_yaml_float) - -SafeConstructor.add_constructor( - 'tag:yaml.org,2002:binary', - SafeConstructor.construct_yaml_binary) - -SafeConstructor.add_constructor( - 'tag:yaml.org,2002:timestamp', - SafeConstructor.construct_yaml_timestamp) - -SafeConstructor.add_constructor( - 'tag:yaml.org,2002:omap', - SafeConstructor.construct_yaml_omap) - -SafeConstructor.add_constructor( - 'tag:yaml.org,2002:pairs', - SafeConstructor.construct_yaml_pairs) - -SafeConstructor.add_constructor( - 'tag:yaml.org,2002:set', - SafeConstructor.construct_yaml_set) - -SafeConstructor.add_constructor( - 'tag:yaml.org,2002:str', - SafeConstructor.construct_yaml_str) - -SafeConstructor.add_constructor( - 'tag:yaml.org,2002:seq', - SafeConstructor.construct_yaml_seq) - -SafeConstructor.add_constructor( - 'tag:yaml.org,2002:map', - SafeConstructor.construct_yaml_map) - -SafeConstructor.add_constructor(None, - SafeConstructor.construct_undefined) - -class FullConstructor(SafeConstructor): - # 'extend' is blacklisted because it is used by - # construct_python_object_apply to add `listitems` to a newly generate - # python instance - def get_state_keys_blacklist(self): - return ['^extend$', '^__.*__$'] - - def get_state_keys_blacklist_regexp(self): - if not hasattr(self, 'state_keys_blacklist_regexp'): - self.state_keys_blacklist_regexp = re.compile('(' + '|'.join(self.get_state_keys_blacklist()) + ')') - return self.state_keys_blacklist_regexp - - def construct_python_str(self, node): - return self.construct_scalar(node) - - def construct_python_unicode(self, node): - return self.construct_scalar(node) - - def construct_python_bytes(self, node): - try: - value = self.construct_scalar(node).encode('ascii') - except UnicodeEncodeError as exc: - raise ConstructorError(None, None, - "failed to convert base64 data into ascii: %s" % exc, - node.start_mark) - try: - if hasattr(base64, 'decodebytes'): - return base64.decodebytes(value) - else: - return base64.decodestring(value) - except binascii.Error as exc: - raise ConstructorError(None, None, - "failed to decode base64 data: %s" % exc, node.start_mark) - - def construct_python_long(self, node): - return self.construct_yaml_int(node) - - def construct_python_complex(self, node): - return complex(self.construct_scalar(node)) - - def construct_python_tuple(self, node): - return tuple(self.construct_sequence(node)) - - def find_python_module(self, name, mark, unsafe=False): - if not name: - raise ConstructorError("while constructing a Python module", mark, - "expected non-empty name appended to the tag", mark) - if unsafe: - try: - __import__(name) - except ImportError as exc: - raise ConstructorError("while constructing a Python module", mark, - "cannot find module %r (%s)" % (name, exc), mark) - if name not in sys.modules: - raise ConstructorError("while constructing a Python module", mark, - "module %r is not imported" % name, mark) - return sys.modules[name] - - def find_python_name(self, name, mark, unsafe=False): - if not name: - raise ConstructorError("while constructing a Python object", mark, - "expected non-empty name appended to the tag", mark) - if '.' in name: - module_name, object_name = name.rsplit('.', 1) - else: - module_name = 'builtins' - object_name = name - if unsafe: - try: - __import__(module_name) - except ImportError as exc: - raise ConstructorError("while constructing a Python object", mark, - "cannot find module %r (%s)" % (module_name, exc), mark) - if module_name not in sys.modules: - raise ConstructorError("while constructing a Python object", mark, - "module %r is not imported" % module_name, mark) - module = sys.modules[module_name] - if not hasattr(module, object_name): - raise ConstructorError("while constructing a Python object", mark, - "cannot find %r in the module %r" - % (object_name, module.__name__), mark) - return getattr(module, object_name) - - def construct_python_name(self, suffix, node): - value = self.construct_scalar(node) - if value: - raise ConstructorError("while constructing a Python name", node.start_mark, - "expected the empty value, but found %r" % value, node.start_mark) - return self.find_python_name(suffix, node.start_mark) - - def construct_python_module(self, suffix, node): - value = self.construct_scalar(node) - if value: - raise ConstructorError("while constructing a Python module", node.start_mark, - "expected the empty value, but found %r" % value, node.start_mark) - return self.find_python_module(suffix, node.start_mark) - - def make_python_instance(self, suffix, node, - args=None, kwds=None, newobj=False, unsafe=False): - if not args: - args = [] - if not kwds: - kwds = {} - cls = self.find_python_name(suffix, node.start_mark) - if not (unsafe or isinstance(cls, type)): - raise ConstructorError("while constructing a Python instance", node.start_mark, - "expected a class, but found %r" % type(cls), - node.start_mark) - if newobj and isinstance(cls, type): - return cls.__new__(cls, *args, **kwds) - else: - return cls(*args, **kwds) - - def set_python_instance_state(self, instance, state, unsafe=False): - if hasattr(instance, '__setstate__'): - instance.__setstate__(state) - else: - slotstate = {} - if isinstance(state, tuple) and len(state) == 2: - state, slotstate = state - if hasattr(instance, '__dict__'): - if not unsafe and state: - for key in state.keys(): - self.check_state_key(key) - instance.__dict__.update(state) - elif state: - slotstate.update(state) - for key, value in slotstate.items(): - if not unsafe: - self.check_state_key(key) - setattr(instance, key, value) - - def construct_python_object(self, suffix, node): - # Format: - # !!python/object:module.name { ... state ... } - instance = self.make_python_instance(suffix, node, newobj=True) - yield instance - deep = hasattr(instance, '__setstate__') - state = self.construct_mapping(node, deep=deep) - self.set_python_instance_state(instance, state) - - def construct_python_object_apply(self, suffix, node, newobj=False): - # Format: - # !!python/object/apply # (or !!python/object/new) - # args: [ ... arguments ... ] - # kwds: { ... keywords ... } - # state: ... state ... - # listitems: [ ... listitems ... ] - # dictitems: { ... dictitems ... } - # or short format: - # !!python/object/apply [ ... arguments ... ] - # The difference between !!python/object/apply and !!python/object/new - # is how an object is created, check make_python_instance for details. - if isinstance(node, SequenceNode): - args = self.construct_sequence(node, deep=True) - kwds = {} - state = {} - listitems = [] - dictitems = {} - else: - value = self.construct_mapping(node, deep=True) - args = value.get('args', []) - kwds = value.get('kwds', {}) - state = value.get('state', {}) - listitems = value.get('listitems', []) - dictitems = value.get('dictitems', {}) - instance = self.make_python_instance(suffix, node, args, kwds, newobj) - if state: - self.set_python_instance_state(instance, state) - if listitems: - instance.extend(listitems) - if dictitems: - for key in dictitems: - instance[key] = dictitems[key] - return instance - - def construct_python_object_new(self, suffix, node): - return self.construct_python_object_apply(suffix, node, newobj=True) - -FullConstructor.add_constructor( - 'tag:yaml.org,2002:python/none', - FullConstructor.construct_yaml_null) - -FullConstructor.add_constructor( - 'tag:yaml.org,2002:python/bool', - FullConstructor.construct_yaml_bool) - -FullConstructor.add_constructor( - 'tag:yaml.org,2002:python/str', - FullConstructor.construct_python_str) - -FullConstructor.add_constructor( - 'tag:yaml.org,2002:python/unicode', - FullConstructor.construct_python_unicode) - -FullConstructor.add_constructor( - 'tag:yaml.org,2002:python/bytes', - FullConstructor.construct_python_bytes) - -FullConstructor.add_constructor( - 'tag:yaml.org,2002:python/int', - FullConstructor.construct_yaml_int) - -FullConstructor.add_constructor( - 'tag:yaml.org,2002:python/long', - FullConstructor.construct_python_long) - -FullConstructor.add_constructor( - 'tag:yaml.org,2002:python/float', - FullConstructor.construct_yaml_float) - -FullConstructor.add_constructor( - 'tag:yaml.org,2002:python/complex', - FullConstructor.construct_python_complex) - -FullConstructor.add_constructor( - 'tag:yaml.org,2002:python/list', - FullConstructor.construct_yaml_seq) - -FullConstructor.add_constructor( - 'tag:yaml.org,2002:python/tuple', - FullConstructor.construct_python_tuple) - -FullConstructor.add_constructor( - 'tag:yaml.org,2002:python/dict', - FullConstructor.construct_yaml_map) - -FullConstructor.add_multi_constructor( - 'tag:yaml.org,2002:python/name:', - FullConstructor.construct_python_name) - -FullConstructor.add_multi_constructor( - 'tag:yaml.org,2002:python/module:', - FullConstructor.construct_python_module) - -FullConstructor.add_multi_constructor( - 'tag:yaml.org,2002:python/object:', - FullConstructor.construct_python_object) - -FullConstructor.add_multi_constructor( - 'tag:yaml.org,2002:python/object/new:', - FullConstructor.construct_python_object_new) - -class UnsafeConstructor(FullConstructor): - - def find_python_module(self, name, mark): - return super(UnsafeConstructor, self).find_python_module(name, mark, unsafe=True) - - def find_python_name(self, name, mark): - return super(UnsafeConstructor, self).find_python_name(name, mark, unsafe=True) - - def make_python_instance(self, suffix, node, args=None, kwds=None, newobj=False): - return super(UnsafeConstructor, self).make_python_instance( - suffix, node, args, kwds, newobj, unsafe=True) - - def set_python_instance_state(self, instance, state): - return super(UnsafeConstructor, self).set_python_instance_state( - instance, state, unsafe=True) - -UnsafeConstructor.add_multi_constructor( - 'tag:yaml.org,2002:python/object/apply:', - UnsafeConstructor.construct_python_object_apply) - -# Constructor is same as UnsafeConstructor. Need to leave this in place in case -# people have extended it directly. -class Constructor(UnsafeConstructor): - pass diff --git a/src/yaml/cyaml.py b/src/yaml/cyaml.py deleted file mode 100644 index 1e606c7..0000000 --- a/src/yaml/cyaml.py +++ /dev/null @@ -1,101 +0,0 @@ - -__all__ = [ - 'CBaseLoader', 'CSafeLoader', 'CFullLoader', 'CUnsafeLoader', 'CLoader', - 'CBaseDumper', 'CSafeDumper', 'CDumper' -] - -from _yaml import CParser, CEmitter - -from .constructor import * - -from .serializer import * -from .representer import * - -from .resolver import * - -class CBaseLoader(CParser, BaseConstructor, BaseResolver): - - def __init__(self, stream): - CParser.__init__(self, stream) - BaseConstructor.__init__(self) - BaseResolver.__init__(self) - -class CSafeLoader(CParser, SafeConstructor, Resolver): - - def __init__(self, stream): - CParser.__init__(self, stream) - SafeConstructor.__init__(self) - Resolver.__init__(self) - -class CFullLoader(CParser, FullConstructor, Resolver): - - def __init__(self, stream): - CParser.__init__(self, stream) - FullConstructor.__init__(self) - Resolver.__init__(self) - -class CUnsafeLoader(CParser, UnsafeConstructor, Resolver): - - def __init__(self, stream): - CParser.__init__(self, stream) - UnsafeConstructor.__init__(self) - Resolver.__init__(self) - -class CLoader(CParser, Constructor, Resolver): - - def __init__(self, stream): - CParser.__init__(self, stream) - Constructor.__init__(self) - Resolver.__init__(self) - -class CBaseDumper(CEmitter, BaseRepresenter, BaseResolver): - - def __init__(self, stream, - default_style=None, default_flow_style=False, - canonical=None, indent=None, width=None, - allow_unicode=None, line_break=None, - encoding=None, explicit_start=None, explicit_end=None, - version=None, tags=None, sort_keys=True): - CEmitter.__init__(self, stream, canonical=canonical, - indent=indent, width=width, encoding=encoding, - allow_unicode=allow_unicode, line_break=line_break, - explicit_start=explicit_start, explicit_end=explicit_end, - version=version, tags=tags) - Representer.__init__(self, default_style=default_style, - default_flow_style=default_flow_style, sort_keys=sort_keys) - Resolver.__init__(self) - -class CSafeDumper(CEmitter, SafeRepresenter, Resolver): - - def __init__(self, stream, - default_style=None, default_flow_style=False, - canonical=None, indent=None, width=None, - allow_unicode=None, line_break=None, - encoding=None, explicit_start=None, explicit_end=None, - version=None, tags=None, sort_keys=True): - CEmitter.__init__(self, stream, canonical=canonical, - indent=indent, width=width, encoding=encoding, - allow_unicode=allow_unicode, line_break=line_break, - explicit_start=explicit_start, explicit_end=explicit_end, - version=version, tags=tags) - SafeRepresenter.__init__(self, default_style=default_style, - default_flow_style=default_flow_style, sort_keys=sort_keys) - Resolver.__init__(self) - -class CDumper(CEmitter, Serializer, Representer, Resolver): - - def __init__(self, stream, - default_style=None, default_flow_style=False, - canonical=None, indent=None, width=None, - allow_unicode=None, line_break=None, - encoding=None, explicit_start=None, explicit_end=None, - version=None, tags=None, sort_keys=True): - CEmitter.__init__(self, stream, canonical=canonical, - indent=indent, width=width, encoding=encoding, - allow_unicode=allow_unicode, line_break=line_break, - explicit_start=explicit_start, explicit_end=explicit_end, - version=version, tags=tags) - Representer.__init__(self, default_style=default_style, - default_flow_style=default_flow_style, sort_keys=sort_keys) - Resolver.__init__(self) - diff --git a/src/yaml/dumper.py b/src/yaml/dumper.py deleted file mode 100644 index 6aadba5..0000000 --- a/src/yaml/dumper.py +++ /dev/null @@ -1,62 +0,0 @@ - -__all__ = ['BaseDumper', 'SafeDumper', 'Dumper'] - -from .emitter import * -from .serializer import * -from .representer import * -from .resolver import * - -class BaseDumper(Emitter, Serializer, BaseRepresenter, BaseResolver): - - def __init__(self, stream, - default_style=None, default_flow_style=False, - canonical=None, indent=None, width=None, - allow_unicode=None, line_break=None, - encoding=None, explicit_start=None, explicit_end=None, - version=None, tags=None, sort_keys=True): - Emitter.__init__(self, stream, canonical=canonical, - indent=indent, width=width, - allow_unicode=allow_unicode, line_break=line_break) - Serializer.__init__(self, encoding=encoding, - explicit_start=explicit_start, explicit_end=explicit_end, - version=version, tags=tags) - Representer.__init__(self, default_style=default_style, - default_flow_style=default_flow_style, sort_keys=sort_keys) - Resolver.__init__(self) - -class SafeDumper(Emitter, Serializer, SafeRepresenter, Resolver): - - def __init__(self, stream, - default_style=None, default_flow_style=False, - canonical=None, indent=None, width=None, - allow_unicode=None, line_break=None, - encoding=None, explicit_start=None, explicit_end=None, - version=None, tags=None, sort_keys=True): - Emitter.__init__(self, stream, canonical=canonical, - indent=indent, width=width, - allow_unicode=allow_unicode, line_break=line_break) - Serializer.__init__(self, encoding=encoding, - explicit_start=explicit_start, explicit_end=explicit_end, - version=version, tags=tags) - SafeRepresenter.__init__(self, default_style=default_style, - default_flow_style=default_flow_style, sort_keys=sort_keys) - Resolver.__init__(self) - -class Dumper(Emitter, Serializer, Representer, Resolver): - - def __init__(self, stream, - default_style=None, default_flow_style=False, - canonical=None, indent=None, width=None, - allow_unicode=None, line_break=None, - encoding=None, explicit_start=None, explicit_end=None, - version=None, tags=None, sort_keys=True): - Emitter.__init__(self, stream, canonical=canonical, - indent=indent, width=width, - allow_unicode=allow_unicode, line_break=line_break) - Serializer.__init__(self, encoding=encoding, - explicit_start=explicit_start, explicit_end=explicit_end, - version=version, tags=tags) - Representer.__init__(self, default_style=default_style, - default_flow_style=default_flow_style, sort_keys=sort_keys) - Resolver.__init__(self) - diff --git a/src/yaml/emitter.py b/src/yaml/emitter.py deleted file mode 100644 index a664d01..0000000 --- a/src/yaml/emitter.py +++ /dev/null @@ -1,1137 +0,0 @@ - -# Emitter expects events obeying the following grammar: -# stream ::= STREAM-START document* STREAM-END -# document ::= DOCUMENT-START node DOCUMENT-END -# node ::= SCALAR | sequence | mapping -# sequence ::= SEQUENCE-START node* SEQUENCE-END -# mapping ::= MAPPING-START (node node)* MAPPING-END - -__all__ = ['Emitter', 'EmitterError'] - -from .error import YAMLError -from .events import * - -class EmitterError(YAMLError): - pass - -class ScalarAnalysis: - def __init__(self, scalar, empty, multiline, - allow_flow_plain, allow_block_plain, - allow_single_quoted, allow_double_quoted, - allow_block): - self.scalar = scalar - self.empty = empty - self.multiline = multiline - self.allow_flow_plain = allow_flow_plain - self.allow_block_plain = allow_block_plain - self.allow_single_quoted = allow_single_quoted - self.allow_double_quoted = allow_double_quoted - self.allow_block = allow_block - -class Emitter: - - DEFAULT_TAG_PREFIXES = { - '!' : '!', - 'tag:yaml.org,2002:' : '!!', - } - - def __init__(self, stream, canonical=None, indent=None, width=None, - allow_unicode=None, line_break=None): - - # The stream should have the methods `write` and possibly `flush`. - self.stream = stream - - # Encoding can be overridden by STREAM-START. - self.encoding = None - - # Emitter is a state machine with a stack of states to handle nested - # structures. - self.states = [] - self.state = self.expect_stream_start - - # Current event and the event queue. - self.events = [] - self.event = None - - # The current indentation level and the stack of previous indents. - self.indents = [] - self.indent = None - - # Flow level. - self.flow_level = 0 - - # Contexts. - self.root_context = False - self.sequence_context = False - self.mapping_context = False - self.simple_key_context = False - - # Characteristics of the last emitted character: - # - current position. - # - is it a whitespace? - # - is it an indention character - # (indentation space, '-', '?', or ':')? - self.line = 0 - self.column = 0 - self.whitespace = True - self.indention = True - - # Whether the document requires an explicit document indicator - self.open_ended = False - - # Formatting details. - self.canonical = canonical - self.allow_unicode = allow_unicode - self.best_indent = 2 - if indent and 1 < indent < 10: - self.best_indent = indent - self.best_width = 80 - if width and width > self.best_indent*2: - self.best_width = width - self.best_line_break = '\n' - if line_break in ['\r', '\n', '\r\n']: - self.best_line_break = line_break - - # Tag prefixes. - self.tag_prefixes = None - - # Prepared anchor and tag. - self.prepared_anchor = None - self.prepared_tag = None - - # Scalar analysis and style. - self.analysis = None - self.style = None - - def dispose(self): - # Reset the state attributes (to clear self-references) - self.states = [] - self.state = None - - def emit(self, event): - self.events.append(event) - while not self.need_more_events(): - self.event = self.events.pop(0) - self.state() - self.event = None - - # In some cases, we wait for a few next events before emitting. - - def need_more_events(self): - if not self.events: - return True - event = self.events[0] - if isinstance(event, DocumentStartEvent): - return self.need_events(1) - elif isinstance(event, SequenceStartEvent): - return self.need_events(2) - elif isinstance(event, MappingStartEvent): - return self.need_events(3) - else: - return False - - def need_events(self, count): - level = 0 - for event in self.events[1:]: - if isinstance(event, (DocumentStartEvent, CollectionStartEvent)): - level += 1 - elif isinstance(event, (DocumentEndEvent, CollectionEndEvent)): - level -= 1 - elif isinstance(event, StreamEndEvent): - level = -1 - if level < 0: - return False - return (len(self.events) < count+1) - - def increase_indent(self, flow=False, indentless=False): - self.indents.append(self.indent) - if self.indent is None: - if flow: - self.indent = self.best_indent - else: - self.indent = 0 - elif not indentless: - self.indent += self.best_indent - - # States. - - # Stream handlers. - - def expect_stream_start(self): - if isinstance(self.event, StreamStartEvent): - if self.event.encoding and not hasattr(self.stream, 'encoding'): - self.encoding = self.event.encoding - self.write_stream_start() - self.state = self.expect_first_document_start - else: - raise EmitterError("expected StreamStartEvent, but got %s" - % self.event) - - def expect_nothing(self): - raise EmitterError("expected nothing, but got %s" % self.event) - - # Document handlers. - - def expect_first_document_start(self): - return self.expect_document_start(first=True) - - def expect_document_start(self, first=False): - if isinstance(self.event, DocumentStartEvent): - if (self.event.version or self.event.tags) and self.open_ended: - self.write_indicator('...', True) - self.write_indent() - if self.event.version: - version_text = self.prepare_version(self.event.version) - self.write_version_directive(version_text) - self.tag_prefixes = self.DEFAULT_TAG_PREFIXES.copy() - if self.event.tags: - handles = sorted(self.event.tags.keys()) - for handle in handles: - prefix = self.event.tags[handle] - self.tag_prefixes[prefix] = handle - handle_text = self.prepare_tag_handle(handle) - prefix_text = self.prepare_tag_prefix(prefix) - self.write_tag_directive(handle_text, prefix_text) - implicit = (first and not self.event.explicit and not self.canonical - and not self.event.version and not self.event.tags - and not self.check_empty_document()) - if not implicit: - self.write_indent() - self.write_indicator('---', True) - if self.canonical: - self.write_indent() - self.state = self.expect_document_root - elif isinstance(self.event, StreamEndEvent): - if self.open_ended: - self.write_indicator('...', True) - self.write_indent() - self.write_stream_end() - self.state = self.expect_nothing - else: - raise EmitterError("expected DocumentStartEvent, but got %s" - % self.event) - - def expect_document_end(self): - if isinstance(self.event, DocumentEndEvent): - self.write_indent() - if self.event.explicit: - self.write_indicator('...', True) - self.write_indent() - self.flush_stream() - self.state = self.expect_document_start - else: - raise EmitterError("expected DocumentEndEvent, but got %s" - % self.event) - - def expect_document_root(self): - self.states.append(self.expect_document_end) - self.expect_node(root=True) - - # Node handlers. - - def expect_node(self, root=False, sequence=False, mapping=False, - simple_key=False): - self.root_context = root - self.sequence_context = sequence - self.mapping_context = mapping - self.simple_key_context = simple_key - if isinstance(self.event, AliasEvent): - self.expect_alias() - elif isinstance(self.event, (ScalarEvent, CollectionStartEvent)): - self.process_anchor('&') - self.process_tag() - if isinstance(self.event, ScalarEvent): - self.expect_scalar() - elif isinstance(self.event, SequenceStartEvent): - if self.flow_level or self.canonical or self.event.flow_style \ - or self.check_empty_sequence(): - self.expect_flow_sequence() - else: - self.expect_block_sequence() - elif isinstance(self.event, MappingStartEvent): - if self.flow_level or self.canonical or self.event.flow_style \ - or self.check_empty_mapping(): - self.expect_flow_mapping() - else: - self.expect_block_mapping() - else: - raise EmitterError("expected NodeEvent, but got %s" % self.event) - - def expect_alias(self): - if self.event.anchor is None: - raise EmitterError("anchor is not specified for alias") - self.process_anchor('*') - self.state = self.states.pop() - - def expect_scalar(self): - self.increase_indent(flow=True) - self.process_scalar() - self.indent = self.indents.pop() - self.state = self.states.pop() - - # Flow sequence handlers. - - def expect_flow_sequence(self): - self.write_indicator('[', True, whitespace=True) - self.flow_level += 1 - self.increase_indent(flow=True) - self.state = self.expect_first_flow_sequence_item - - def expect_first_flow_sequence_item(self): - if isinstance(self.event, SequenceEndEvent): - self.indent = self.indents.pop() - self.flow_level -= 1 - self.write_indicator(']', False) - self.state = self.states.pop() - else: - if self.canonical or self.column > self.best_width: - self.write_indent() - self.states.append(self.expect_flow_sequence_item) - self.expect_node(sequence=True) - - def expect_flow_sequence_item(self): - if isinstance(self.event, SequenceEndEvent): - self.indent = self.indents.pop() - self.flow_level -= 1 - if self.canonical: - self.write_indicator(',', False) - self.write_indent() - self.write_indicator(']', False) - self.state = self.states.pop() - else: - self.write_indicator(',', False) - if self.canonical or self.column > self.best_width: - self.write_indent() - self.states.append(self.expect_flow_sequence_item) - self.expect_node(sequence=True) - - # Flow mapping handlers. - - def expect_flow_mapping(self): - self.write_indicator('{', True, whitespace=True) - self.flow_level += 1 - self.increase_indent(flow=True) - self.state = self.expect_first_flow_mapping_key - - def expect_first_flow_mapping_key(self): - if isinstance(self.event, MappingEndEvent): - self.indent = self.indents.pop() - self.flow_level -= 1 - self.write_indicator('}', False) - self.state = self.states.pop() - else: - if self.canonical or self.column > self.best_width: - self.write_indent() - if not self.canonical and self.check_simple_key(): - self.states.append(self.expect_flow_mapping_simple_value) - self.expect_node(mapping=True, simple_key=True) - else: - self.write_indicator('?', True) - self.states.append(self.expect_flow_mapping_value) - self.expect_node(mapping=True) - - def expect_flow_mapping_key(self): - if isinstance(self.event, MappingEndEvent): - self.indent = self.indents.pop() - self.flow_level -= 1 - if self.canonical: - self.write_indicator(',', False) - self.write_indent() - self.write_indicator('}', False) - self.state = self.states.pop() - else: - self.write_indicator(',', False) - if self.canonical or self.column > self.best_width: - self.write_indent() - if not self.canonical and self.check_simple_key(): - self.states.append(self.expect_flow_mapping_simple_value) - self.expect_node(mapping=True, simple_key=True) - else: - self.write_indicator('?', True) - self.states.append(self.expect_flow_mapping_value) - self.expect_node(mapping=True) - - def expect_flow_mapping_simple_value(self): - self.write_indicator(':', False) - self.states.append(self.expect_flow_mapping_key) - self.expect_node(mapping=True) - - def expect_flow_mapping_value(self): - if self.canonical or self.column > self.best_width: - self.write_indent() - self.write_indicator(':', True) - self.states.append(self.expect_flow_mapping_key) - self.expect_node(mapping=True) - - # Block sequence handlers. - - def expect_block_sequence(self): - indentless = (self.mapping_context and not self.indention) - self.increase_indent(flow=False, indentless=indentless) - self.state = self.expect_first_block_sequence_item - - def expect_first_block_sequence_item(self): - return self.expect_block_sequence_item(first=True) - - def expect_block_sequence_item(self, first=False): - if not first and isinstance(self.event, SequenceEndEvent): - self.indent = self.indents.pop() - self.state = self.states.pop() - else: - self.write_indent() - self.write_indicator('-', True, indention=True) - self.states.append(self.expect_block_sequence_item) - self.expect_node(sequence=True) - - # Block mapping handlers. - - def expect_block_mapping(self): - self.increase_indent(flow=False) - self.state = self.expect_first_block_mapping_key - - def expect_first_block_mapping_key(self): - return self.expect_block_mapping_key(first=True) - - def expect_block_mapping_key(self, first=False): - if not first and isinstance(self.event, MappingEndEvent): - self.indent = self.indents.pop() - self.state = self.states.pop() - else: - self.write_indent() - if self.check_simple_key(): - self.states.append(self.expect_block_mapping_simple_value) - self.expect_node(mapping=True, simple_key=True) - else: - self.write_indicator('?', True, indention=True) - self.states.append(self.expect_block_mapping_value) - self.expect_node(mapping=True) - - def expect_block_mapping_simple_value(self): - self.write_indicator(':', False) - self.states.append(self.expect_block_mapping_key) - self.expect_node(mapping=True) - - def expect_block_mapping_value(self): - self.write_indent() - self.write_indicator(':', True, indention=True) - self.states.append(self.expect_block_mapping_key) - self.expect_node(mapping=True) - - # Checkers. - - def check_empty_sequence(self): - return (isinstance(self.event, SequenceStartEvent) and self.events - and isinstance(self.events[0], SequenceEndEvent)) - - def check_empty_mapping(self): - return (isinstance(self.event, MappingStartEvent) and self.events - and isinstance(self.events[0], MappingEndEvent)) - - def check_empty_document(self): - if not isinstance(self.event, DocumentStartEvent) or not self.events: - return False - event = self.events[0] - return (isinstance(event, ScalarEvent) and event.anchor is None - and event.tag is None and event.implicit and event.value == '') - - def check_simple_key(self): - length = 0 - if isinstance(self.event, NodeEvent) and self.event.anchor is not None: - if self.prepared_anchor is None: - self.prepared_anchor = self.prepare_anchor(self.event.anchor) - length += len(self.prepared_anchor) - if isinstance(self.event, (ScalarEvent, CollectionStartEvent)) \ - and self.event.tag is not None: - if self.prepared_tag is None: - self.prepared_tag = self.prepare_tag(self.event.tag) - length += len(self.prepared_tag) - if isinstance(self.event, ScalarEvent): - if self.analysis is None: - self.analysis = self.analyze_scalar(self.event.value) - length += len(self.analysis.scalar) - return (length < 128 and (isinstance(self.event, AliasEvent) - or (isinstance(self.event, ScalarEvent) - and not self.analysis.empty and not self.analysis.multiline) - or self.check_empty_sequence() or self.check_empty_mapping())) - - # Anchor, Tag, and Scalar processors. - - def process_anchor(self, indicator): - if self.event.anchor is None: - self.prepared_anchor = None - return - if self.prepared_anchor is None: - self.prepared_anchor = self.prepare_anchor(self.event.anchor) - if self.prepared_anchor: - self.write_indicator(indicator+self.prepared_anchor, True) - self.prepared_anchor = None - - def process_tag(self): - tag = self.event.tag - if isinstance(self.event, ScalarEvent): - if self.style is None: - self.style = self.choose_scalar_style() - if ((not self.canonical or tag is None) and - ((self.style == '' and self.event.implicit[0]) - or (self.style != '' and self.event.implicit[1]))): - self.prepared_tag = None - return - if self.event.implicit[0] and tag is None: - tag = '!' - self.prepared_tag = None - else: - if (not self.canonical or tag is None) and self.event.implicit: - self.prepared_tag = None - return - if tag is None: - raise EmitterError("tag is not specified") - if self.prepared_tag is None: - self.prepared_tag = self.prepare_tag(tag) - if self.prepared_tag: - self.write_indicator(self.prepared_tag, True) - self.prepared_tag = None - - def choose_scalar_style(self): - if self.analysis is None: - self.analysis = self.analyze_scalar(self.event.value) - if self.event.style == '"' or self.canonical: - return '"' - if not self.event.style and self.event.implicit[0]: - if (not (self.simple_key_context and - (self.analysis.empty or self.analysis.multiline)) - and (self.flow_level and self.analysis.allow_flow_plain - or (not self.flow_level and self.analysis.allow_block_plain))): - return '' - if self.event.style and self.event.style in '|>': - if (not self.flow_level and not self.simple_key_context - and self.analysis.allow_block): - return self.event.style - if not self.event.style or self.event.style == '\'': - if (self.analysis.allow_single_quoted and - not (self.simple_key_context and self.analysis.multiline)): - return '\'' - return '"' - - def process_scalar(self): - if self.analysis is None: - self.analysis = self.analyze_scalar(self.event.value) - if self.style is None: - self.style = self.choose_scalar_style() - split = (not self.simple_key_context) - #if self.analysis.multiline and split \ - # and (not self.style or self.style in '\'\"'): - # self.write_indent() - if self.style == '"': - self.write_double_quoted(self.analysis.scalar, split) - elif self.style == '\'': - self.write_single_quoted(self.analysis.scalar, split) - elif self.style == '>': - self.write_folded(self.analysis.scalar) - elif self.style == '|': - self.write_literal(self.analysis.scalar) - else: - self.write_plain(self.analysis.scalar, split) - self.analysis = None - self.style = None - - # Analyzers. - - def prepare_version(self, version): - major, minor = version - if major != 1: - raise EmitterError("unsupported YAML version: %d.%d" % (major, minor)) - return '%d.%d' % (major, minor) - - def prepare_tag_handle(self, handle): - if not handle: - raise EmitterError("tag handle must not be empty") - if handle[0] != '!' or handle[-1] != '!': - raise EmitterError("tag handle must start and end with '!': %r" % handle) - for ch in handle[1:-1]: - if not ('0' <= ch <= '9' or 'A' <= ch <= 'Z' or 'a' <= ch <= 'z' \ - or ch in '-_'): - raise EmitterError("invalid character %r in the tag handle: %r" - % (ch, handle)) - return handle - - def prepare_tag_prefix(self, prefix): - if not prefix: - raise EmitterError("tag prefix must not be empty") - chunks = [] - start = end = 0 - if prefix[0] == '!': - end = 1 - while end < len(prefix): - ch = prefix[end] - if '0' <= ch <= '9' or 'A' <= ch <= 'Z' or 'a' <= ch <= 'z' \ - or ch in '-;/?!:@&=+$,_.~*\'()[]': - end += 1 - else: - if start < end: - chunks.append(prefix[start:end]) - start = end = end+1 - data = ch.encode('utf-8') - for ch in data: - chunks.append('%%%02X' % ord(ch)) - if start < end: - chunks.append(prefix[start:end]) - return ''.join(chunks) - - def prepare_tag(self, tag): - if not tag: - raise EmitterError("tag must not be empty") - if tag == '!': - return tag - handle = None - suffix = tag - prefixes = sorted(self.tag_prefixes.keys()) - for prefix in prefixes: - if tag.startswith(prefix) \ - and (prefix == '!' or len(prefix) < len(tag)): - handle = self.tag_prefixes[prefix] - suffix = tag[len(prefix):] - chunks = [] - start = end = 0 - while end < len(suffix): - ch = suffix[end] - if '0' <= ch <= '9' or 'A' <= ch <= 'Z' or 'a' <= ch <= 'z' \ - or ch in '-;/?:@&=+$,_.~*\'()[]' \ - or (ch == '!' and handle != '!'): - end += 1 - else: - if start < end: - chunks.append(suffix[start:end]) - start = end = end+1 - data = ch.encode('utf-8') - for ch in data: - chunks.append('%%%02X' % ch) - if start < end: - chunks.append(suffix[start:end]) - suffix_text = ''.join(chunks) - if handle: - return '%s%s' % (handle, suffix_text) - else: - return '!<%s>' % suffix_text - - def prepare_anchor(self, anchor): - if not anchor: - raise EmitterError("anchor must not be empty") - for ch in anchor: - if not ('0' <= ch <= '9' or 'A' <= ch <= 'Z' or 'a' <= ch <= 'z' \ - or ch in '-_'): - raise EmitterError("invalid character %r in the anchor: %r" - % (ch, anchor)) - return anchor - - def analyze_scalar(self, scalar): - - # Empty scalar is a special case. - if not scalar: - return ScalarAnalysis(scalar=scalar, empty=True, multiline=False, - allow_flow_plain=False, allow_block_plain=True, - allow_single_quoted=True, allow_double_quoted=True, - allow_block=False) - - # Indicators and special characters. - block_indicators = False - flow_indicators = False - line_breaks = False - special_characters = False - - # Important whitespace combinations. - leading_space = False - leading_break = False - trailing_space = False - trailing_break = False - break_space = False - space_break = False - - # Check document indicators. - if scalar.startswith('---') or scalar.startswith('...'): - block_indicators = True - flow_indicators = True - - # First character or preceded by a whitespace. - preceded_by_whitespace = True - - # Last character or followed by a whitespace. - followed_by_whitespace = (len(scalar) == 1 or - scalar[1] in '\0 \t\r\n\x85\u2028\u2029') - - # The previous character is a space. - previous_space = False - - # The previous character is a break. - previous_break = False - - index = 0 - while index < len(scalar): - ch = scalar[index] - - # Check for indicators. - if index == 0: - # Leading indicators are special characters. - if ch in '#,[]{}&*!|>\'\"%@`': - flow_indicators = True - block_indicators = True - if ch in '?:': - flow_indicators = True - if followed_by_whitespace: - block_indicators = True - if ch == '-' and followed_by_whitespace: - flow_indicators = True - block_indicators = True - else: - # Some indicators cannot appear within a scalar as well. - if ch in ',?[]{}': - flow_indicators = True - if ch == ':': - flow_indicators = True - if followed_by_whitespace: - block_indicators = True - if ch == '#' and preceded_by_whitespace: - flow_indicators = True - block_indicators = True - - # Check for line breaks, special, and unicode characters. - if ch in '\n\x85\u2028\u2029': - line_breaks = True - if not (ch == '\n' or '\x20' <= ch <= '\x7E'): - if (ch == '\x85' or '\xA0' <= ch <= '\uD7FF' - or '\uE000' <= ch <= '\uFFFD' - or '\U00010000' <= ch < '\U0010ffff') and ch != '\uFEFF': - unicode_characters = True - if not self.allow_unicode: - special_characters = True - else: - special_characters = True - - # Detect important whitespace combinations. - if ch == ' ': - if index == 0: - leading_space = True - if index == len(scalar)-1: - trailing_space = True - if previous_break: - break_space = True - previous_space = True - previous_break = False - elif ch in '\n\x85\u2028\u2029': - if index == 0: - leading_break = True - if index == len(scalar)-1: - trailing_break = True - if previous_space: - space_break = True - previous_space = False - previous_break = True - else: - previous_space = False - previous_break = False - - # Prepare for the next character. - index += 1 - preceded_by_whitespace = (ch in '\0 \t\r\n\x85\u2028\u2029') - followed_by_whitespace = (index+1 >= len(scalar) or - scalar[index+1] in '\0 \t\r\n\x85\u2028\u2029') - - # Let's decide what styles are allowed. - allow_flow_plain = True - allow_block_plain = True - allow_single_quoted = True - allow_double_quoted = True - allow_block = True - - # Leading and trailing whitespaces are bad for plain scalars. - if (leading_space or leading_break - or trailing_space or trailing_break): - allow_flow_plain = allow_block_plain = False - - # We do not permit trailing spaces for block scalars. - if trailing_space: - allow_block = False - - # Spaces at the beginning of a new line are only acceptable for block - # scalars. - if break_space: - allow_flow_plain = allow_block_plain = allow_single_quoted = False - - # Spaces followed by breaks, as well as special character are only - # allowed for double quoted scalars. - if space_break or special_characters: - allow_flow_plain = allow_block_plain = \ - allow_single_quoted = allow_block = False - - # Although the plain scalar writer supports breaks, we never emit - # multiline plain scalars. - if line_breaks: - allow_flow_plain = allow_block_plain = False - - # Flow indicators are forbidden for flow plain scalars. - if flow_indicators: - allow_flow_plain = False - - # Block indicators are forbidden for block plain scalars. - if block_indicators: - allow_block_plain = False - - return ScalarAnalysis(scalar=scalar, - empty=False, multiline=line_breaks, - allow_flow_plain=allow_flow_plain, - allow_block_plain=allow_block_plain, - allow_single_quoted=allow_single_quoted, - allow_double_quoted=allow_double_quoted, - allow_block=allow_block) - - # Writers. - - def flush_stream(self): - if hasattr(self.stream, 'flush'): - self.stream.flush() - - def write_stream_start(self): - # Write BOM if needed. - if self.encoding and self.encoding.startswith('utf-16'): - self.stream.write('\uFEFF'.encode(self.encoding)) - - def write_stream_end(self): - self.flush_stream() - - def write_indicator(self, indicator, need_whitespace, - whitespace=False, indention=False): - if self.whitespace or not need_whitespace: - data = indicator - else: - data = ' '+indicator - self.whitespace = whitespace - self.indention = self.indention and indention - self.column += len(data) - self.open_ended = False - if self.encoding: - data = data.encode(self.encoding) - self.stream.write(data) - - def write_indent(self): - indent = self.indent or 0 - if not self.indention or self.column > indent \ - or (self.column == indent and not self.whitespace): - self.write_line_break() - if self.column < indent: - self.whitespace = True - data = ' '*(indent-self.column) - self.column = indent - if self.encoding: - data = data.encode(self.encoding) - self.stream.write(data) - - def write_line_break(self, data=None): - if data is None: - data = self.best_line_break - self.whitespace = True - self.indention = True - self.line += 1 - self.column = 0 - if self.encoding: - data = data.encode(self.encoding) - self.stream.write(data) - - def write_version_directive(self, version_text): - data = '%%YAML %s' % version_text - if self.encoding: - data = data.encode(self.encoding) - self.stream.write(data) - self.write_line_break() - - def write_tag_directive(self, handle_text, prefix_text): - data = '%%TAG %s %s' % (handle_text, prefix_text) - if self.encoding: - data = data.encode(self.encoding) - self.stream.write(data) - self.write_line_break() - - # Scalar streams. - - def write_single_quoted(self, text, split=True): - self.write_indicator('\'', True) - spaces = False - breaks = False - start = end = 0 - while end <= len(text): - ch = None - if end < len(text): - ch = text[end] - if spaces: - if ch is None or ch != ' ': - if start+1 == end and self.column > self.best_width and split \ - and start != 0 and end != len(text): - self.write_indent() - else: - data = text[start:end] - self.column += len(data) - if self.encoding: - data = data.encode(self.encoding) - self.stream.write(data) - start = end - elif breaks: - if ch is None or ch not in '\n\x85\u2028\u2029': - if text[start] == '\n': - self.write_line_break() - for br in text[start:end]: - if br == '\n': - self.write_line_break() - else: - self.write_line_break(br) - self.write_indent() - start = end - else: - if ch is None or ch in ' \n\x85\u2028\u2029' or ch == '\'': - if start < end: - data = text[start:end] - self.column += len(data) - if self.encoding: - data = data.encode(self.encoding) - self.stream.write(data) - start = end - if ch == '\'': - data = '\'\'' - self.column += 2 - if self.encoding: - data = data.encode(self.encoding) - self.stream.write(data) - start = end + 1 - if ch is not None: - spaces = (ch == ' ') - breaks = (ch in '\n\x85\u2028\u2029') - end += 1 - self.write_indicator('\'', False) - - ESCAPE_REPLACEMENTS = { - '\0': '0', - '\x07': 'a', - '\x08': 'b', - '\x09': 't', - '\x0A': 'n', - '\x0B': 'v', - '\x0C': 'f', - '\x0D': 'r', - '\x1B': 'e', - '\"': '\"', - '\\': '\\', - '\x85': 'N', - '\xA0': '_', - '\u2028': 'L', - '\u2029': 'P', - } - - def write_double_quoted(self, text, split=True): - self.write_indicator('"', True) - start = end = 0 - while end <= len(text): - ch = None - if end < len(text): - ch = text[end] - if ch is None or ch in '"\\\x85\u2028\u2029\uFEFF' \ - or not ('\x20' <= ch <= '\x7E' - or (self.allow_unicode - and ('\xA0' <= ch <= '\uD7FF' - or '\uE000' <= ch <= '\uFFFD'))): - if start < end: - data = text[start:end] - self.column += len(data) - if self.encoding: - data = data.encode(self.encoding) - self.stream.write(data) - start = end - if ch is not None: - if ch in self.ESCAPE_REPLACEMENTS: - data = '\\'+self.ESCAPE_REPLACEMENTS[ch] - elif ch <= '\xFF': - data = '\\x%02X' % ord(ch) - elif ch <= '\uFFFF': - data = '\\u%04X' % ord(ch) - else: - data = '\\U%08X' % ord(ch) - self.column += len(data) - if self.encoding: - data = data.encode(self.encoding) - self.stream.write(data) - start = end+1 - if 0 < end < len(text)-1 and (ch == ' ' or start >= end) \ - and self.column+(end-start) > self.best_width and split: - data = text[start:end]+'\\' - if start < end: - start = end - self.column += len(data) - if self.encoding: - data = data.encode(self.encoding) - self.stream.write(data) - self.write_indent() - self.whitespace = False - self.indention = False - if text[start] == ' ': - data = '\\' - self.column += len(data) - if self.encoding: - data = data.encode(self.encoding) - self.stream.write(data) - end += 1 - self.write_indicator('"', False) - - def determine_block_hints(self, text): - hints = '' - if text: - if text[0] in ' \n\x85\u2028\u2029': - hints += str(self.best_indent) - if text[-1] not in '\n\x85\u2028\u2029': - hints += '-' - elif len(text) == 1 or text[-2] in '\n\x85\u2028\u2029': - hints += '+' - return hints - - def write_folded(self, text): - hints = self.determine_block_hints(text) - self.write_indicator('>'+hints, True) - if hints[-1:] == '+': - self.open_ended = True - self.write_line_break() - leading_space = True - spaces = False - breaks = True - start = end = 0 - while end <= len(text): - ch = None - if end < len(text): - ch = text[end] - if breaks: - if ch is None or ch not in '\n\x85\u2028\u2029': - if not leading_space and ch is not None and ch != ' ' \ - and text[start] == '\n': - self.write_line_break() - leading_space = (ch == ' ') - for br in text[start:end]: - if br == '\n': - self.write_line_break() - else: - self.write_line_break(br) - if ch is not None: - self.write_indent() - start = end - elif spaces: - if ch != ' ': - if start+1 == end and self.column > self.best_width: - self.write_indent() - else: - data = text[start:end] - self.column += len(data) - if self.encoding: - data = data.encode(self.encoding) - self.stream.write(data) - start = end - else: - if ch is None or ch in ' \n\x85\u2028\u2029': - data = text[start:end] - self.column += len(data) - if self.encoding: - data = data.encode(self.encoding) - self.stream.write(data) - if ch is None: - self.write_line_break() - start = end - if ch is not None: - breaks = (ch in '\n\x85\u2028\u2029') - spaces = (ch == ' ') - end += 1 - - def write_literal(self, text): - hints = self.determine_block_hints(text) - self.write_indicator('|'+hints, True) - if hints[-1:] == '+': - self.open_ended = True - self.write_line_break() - breaks = True - start = end = 0 - while end <= len(text): - ch = None - if end < len(text): - ch = text[end] - if breaks: - if ch is None or ch not in '\n\x85\u2028\u2029': - for br in text[start:end]: - if br == '\n': - self.write_line_break() - else: - self.write_line_break(br) - if ch is not None: - self.write_indent() - start = end - else: - if ch is None or ch in '\n\x85\u2028\u2029': - data = text[start:end] - if self.encoding: - data = data.encode(self.encoding) - self.stream.write(data) - if ch is None: - self.write_line_break() - start = end - if ch is not None: - breaks = (ch in '\n\x85\u2028\u2029') - end += 1 - - def write_plain(self, text, split=True): - if self.root_context: - self.open_ended = True - if not text: - return - if not self.whitespace: - data = ' ' - self.column += len(data) - if self.encoding: - data = data.encode(self.encoding) - self.stream.write(data) - self.whitespace = False - self.indention = False - spaces = False - breaks = False - start = end = 0 - while end <= len(text): - ch = None - if end < len(text): - ch = text[end] - if spaces: - if ch != ' ': - if start+1 == end and self.column > self.best_width and split: - self.write_indent() - self.whitespace = False - self.indention = False - else: - data = text[start:end] - self.column += len(data) - if self.encoding: - data = data.encode(self.encoding) - self.stream.write(data) - start = end - elif breaks: - if ch not in '\n\x85\u2028\u2029': - if text[start] == '\n': - self.write_line_break() - for br in text[start:end]: - if br == '\n': - self.write_line_break() - else: - self.write_line_break(br) - self.write_indent() - self.whitespace = False - self.indention = False - start = end - else: - if ch is None or ch in ' \n\x85\u2028\u2029': - data = text[start:end] - self.column += len(data) - if self.encoding: - data = data.encode(self.encoding) - self.stream.write(data) - start = end - if ch is not None: - spaces = (ch == ' ') - breaks = (ch in '\n\x85\u2028\u2029') - end += 1 diff --git a/src/yaml/error.py b/src/yaml/error.py deleted file mode 100644 index b796b4d..0000000 --- a/src/yaml/error.py +++ /dev/null @@ -1,75 +0,0 @@ - -__all__ = ['Mark', 'YAMLError', 'MarkedYAMLError'] - -class Mark: - - def __init__(self, name, index, line, column, buffer, pointer): - self.name = name - self.index = index - self.line = line - self.column = column - self.buffer = buffer - self.pointer = pointer - - def get_snippet(self, indent=4, max_length=75): - if self.buffer is None: - return None - head = '' - start = self.pointer - while start > 0 and self.buffer[start-1] not in '\0\r\n\x85\u2028\u2029': - start -= 1 - if self.pointer-start > max_length/2-1: - head = ' ... ' - start += 5 - break - tail = '' - end = self.pointer - while end < len(self.buffer) and self.buffer[end] not in '\0\r\n\x85\u2028\u2029': - end += 1 - if end-self.pointer > max_length/2-1: - tail = ' ... ' - end -= 5 - break - snippet = self.buffer[start:end] - return ' '*indent + head + snippet + tail + '\n' \ - + ' '*(indent+self.pointer-start+len(head)) + '^' - - def __str__(self): - snippet = self.get_snippet() - where = " in \"%s\", line %d, column %d" \ - % (self.name, self.line+1, self.column+1) - if snippet is not None: - where += ":\n"+snippet - return where - -class YAMLError(Exception): - pass - -class MarkedYAMLError(YAMLError): - - def __init__(self, context=None, context_mark=None, - problem=None, problem_mark=None, note=None): - self.context = context - self.context_mark = context_mark - self.problem = problem - self.problem_mark = problem_mark - self.note = note - - def __str__(self): - lines = [] - if self.context is not None: - lines.append(self.context) - if self.context_mark is not None \ - and (self.problem is None or self.problem_mark is None - or self.context_mark.name != self.problem_mark.name - or self.context_mark.line != self.problem_mark.line - or self.context_mark.column != self.problem_mark.column): - lines.append(str(self.context_mark)) - if self.problem is not None: - lines.append(self.problem) - if self.problem_mark is not None: - lines.append(str(self.problem_mark)) - if self.note is not None: - lines.append(self.note) - return '\n'.join(lines) - diff --git a/src/yaml/events.py b/src/yaml/events.py deleted file mode 100644 index f79ad38..0000000 --- a/src/yaml/events.py +++ /dev/null @@ -1,86 +0,0 @@ - -# Abstract classes. - -class Event(object): - def __init__(self, start_mark=None, end_mark=None): - self.start_mark = start_mark - self.end_mark = end_mark - def __repr__(self): - attributes = [key for key in ['anchor', 'tag', 'implicit', 'value'] - if hasattr(self, key)] - arguments = ', '.join(['%s=%r' % (key, getattr(self, key)) - for key in attributes]) - return '%s(%s)' % (self.__class__.__name__, arguments) - -class NodeEvent(Event): - def __init__(self, anchor, start_mark=None, end_mark=None): - self.anchor = anchor - self.start_mark = start_mark - self.end_mark = end_mark - -class CollectionStartEvent(NodeEvent): - def __init__(self, anchor, tag, implicit, start_mark=None, end_mark=None, - flow_style=None): - self.anchor = anchor - self.tag = tag - self.implicit = implicit - self.start_mark = start_mark - self.end_mark = end_mark - self.flow_style = flow_style - -class CollectionEndEvent(Event): - pass - -# Implementations. - -class StreamStartEvent(Event): - def __init__(self, start_mark=None, end_mark=None, encoding=None): - self.start_mark = start_mark - self.end_mark = end_mark - self.encoding = encoding - -class StreamEndEvent(Event): - pass - -class DocumentStartEvent(Event): - def __init__(self, start_mark=None, end_mark=None, - explicit=None, version=None, tags=None): - self.start_mark = start_mark - self.end_mark = end_mark - self.explicit = explicit - self.version = version - self.tags = tags - -class DocumentEndEvent(Event): - def __init__(self, start_mark=None, end_mark=None, - explicit=None): - self.start_mark = start_mark - self.end_mark = end_mark - self.explicit = explicit - -class AliasEvent(NodeEvent): - pass - -class ScalarEvent(NodeEvent): - def __init__(self, anchor, tag, implicit, value, - start_mark=None, end_mark=None, style=None): - self.anchor = anchor - self.tag = tag - self.implicit = implicit - self.value = value - self.start_mark = start_mark - self.end_mark = end_mark - self.style = style - -class SequenceStartEvent(CollectionStartEvent): - pass - -class SequenceEndEvent(CollectionEndEvent): - pass - -class MappingStartEvent(CollectionStartEvent): - pass - -class MappingEndEvent(CollectionEndEvent): - pass - diff --git a/src/yaml/loader.py b/src/yaml/loader.py deleted file mode 100644 index e90c112..0000000 --- a/src/yaml/loader.py +++ /dev/null @@ -1,63 +0,0 @@ - -__all__ = ['BaseLoader', 'FullLoader', 'SafeLoader', 'Loader', 'UnsafeLoader'] - -from .reader import * -from .scanner import * -from .parser import * -from .composer import * -from .constructor import * -from .resolver import * - -class BaseLoader(Reader, Scanner, Parser, Composer, BaseConstructor, BaseResolver): - - def __init__(self, stream): - Reader.__init__(self, stream) - Scanner.__init__(self) - Parser.__init__(self) - Composer.__init__(self) - BaseConstructor.__init__(self) - BaseResolver.__init__(self) - -class FullLoader(Reader, Scanner, Parser, Composer, FullConstructor, Resolver): - - def __init__(self, stream): - Reader.__init__(self, stream) - Scanner.__init__(self) - Parser.__init__(self) - Composer.__init__(self) - FullConstructor.__init__(self) - Resolver.__init__(self) - -class SafeLoader(Reader, Scanner, Parser, Composer, SafeConstructor, Resolver): - - def __init__(self, stream): - Reader.__init__(self, stream) - Scanner.__init__(self) - Parser.__init__(self) - Composer.__init__(self) - SafeConstructor.__init__(self) - Resolver.__init__(self) - -class Loader(Reader, Scanner, Parser, Composer, Constructor, Resolver): - - def __init__(self, stream): - Reader.__init__(self, stream) - Scanner.__init__(self) - Parser.__init__(self) - Composer.__init__(self) - Constructor.__init__(self) - Resolver.__init__(self) - -# UnsafeLoader is the same as Loader (which is and was always unsafe on -# untrusted input). Use of either Loader or UnsafeLoader should be rare, since -# FullLoad should be able to load almost all YAML safely. Loader is left intact -# to ensure backwards compatibility. -class UnsafeLoader(Reader, Scanner, Parser, Composer, Constructor, Resolver): - - def __init__(self, stream): - Reader.__init__(self, stream) - Scanner.__init__(self) - Parser.__init__(self) - Composer.__init__(self) - Constructor.__init__(self) - Resolver.__init__(self) diff --git a/src/yaml/nodes.py b/src/yaml/nodes.py deleted file mode 100644 index c4f070c..0000000 --- a/src/yaml/nodes.py +++ /dev/null @@ -1,49 +0,0 @@ - -class Node(object): - def __init__(self, tag, value, start_mark, end_mark): - self.tag = tag - self.value = value - self.start_mark = start_mark - self.end_mark = end_mark - def __repr__(self): - value = self.value - #if isinstance(value, list): - # if len(value) == 0: - # value = '' - # elif len(value) == 1: - # value = '<1 item>' - # else: - # value = '<%d items>' % len(value) - #else: - # if len(value) > 75: - # value = repr(value[:70]+u' ... ') - # else: - # value = repr(value) - value = repr(value) - return '%s(tag=%r, value=%s)' % (self.__class__.__name__, self.tag, value) - -class ScalarNode(Node): - id = 'scalar' - def __init__(self, tag, value, - start_mark=None, end_mark=None, style=None): - self.tag = tag - self.value = value - self.start_mark = start_mark - self.end_mark = end_mark - self.style = style - -class CollectionNode(Node): - def __init__(self, tag, value, - start_mark=None, end_mark=None, flow_style=None): - self.tag = tag - self.value = value - self.start_mark = start_mark - self.end_mark = end_mark - self.flow_style = flow_style - -class SequenceNode(CollectionNode): - id = 'sequence' - -class MappingNode(CollectionNode): - id = 'mapping' - diff --git a/src/yaml/parser.py b/src/yaml/parser.py deleted file mode 100644 index 13a5995..0000000 --- a/src/yaml/parser.py +++ /dev/null @@ -1,589 +0,0 @@ - -# The following YAML grammar is LL(1) and is parsed by a recursive descent -# parser. -# -# stream ::= STREAM-START implicit_document? explicit_document* STREAM-END -# implicit_document ::= block_node DOCUMENT-END* -# explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* -# block_node_or_indentless_sequence ::= -# ALIAS -# | properties (block_content | indentless_block_sequence)? -# | block_content -# | indentless_block_sequence -# block_node ::= ALIAS -# | properties block_content? -# | block_content -# flow_node ::= ALIAS -# | properties flow_content? -# | flow_content -# properties ::= TAG ANCHOR? | ANCHOR TAG? -# block_content ::= block_collection | flow_collection | SCALAR -# flow_content ::= flow_collection | SCALAR -# block_collection ::= block_sequence | block_mapping -# flow_collection ::= flow_sequence | flow_mapping -# block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END -# indentless_sequence ::= (BLOCK-ENTRY block_node?)+ -# block_mapping ::= BLOCK-MAPPING_START -# ((KEY block_node_or_indentless_sequence?)? -# (VALUE block_node_or_indentless_sequence?)?)* -# BLOCK-END -# flow_sequence ::= FLOW-SEQUENCE-START -# (flow_sequence_entry FLOW-ENTRY)* -# flow_sequence_entry? -# FLOW-SEQUENCE-END -# flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? -# flow_mapping ::= FLOW-MAPPING-START -# (flow_mapping_entry FLOW-ENTRY)* -# flow_mapping_entry? -# FLOW-MAPPING-END -# flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? -# -# FIRST sets: -# -# stream: { STREAM-START } -# explicit_document: { DIRECTIVE DOCUMENT-START } -# implicit_document: FIRST(block_node) -# block_node: { ALIAS TAG ANCHOR SCALAR BLOCK-SEQUENCE-START BLOCK-MAPPING-START FLOW-SEQUENCE-START FLOW-MAPPING-START } -# flow_node: { ALIAS ANCHOR TAG SCALAR FLOW-SEQUENCE-START FLOW-MAPPING-START } -# block_content: { BLOCK-SEQUENCE-START BLOCK-MAPPING-START FLOW-SEQUENCE-START FLOW-MAPPING-START SCALAR } -# flow_content: { FLOW-SEQUENCE-START FLOW-MAPPING-START SCALAR } -# block_collection: { BLOCK-SEQUENCE-START BLOCK-MAPPING-START } -# flow_collection: { FLOW-SEQUENCE-START FLOW-MAPPING-START } -# block_sequence: { BLOCK-SEQUENCE-START } -# block_mapping: { BLOCK-MAPPING-START } -# block_node_or_indentless_sequence: { ALIAS ANCHOR TAG SCALAR BLOCK-SEQUENCE-START BLOCK-MAPPING-START FLOW-SEQUENCE-START FLOW-MAPPING-START BLOCK-ENTRY } -# indentless_sequence: { ENTRY } -# flow_collection: { FLOW-SEQUENCE-START FLOW-MAPPING-START } -# flow_sequence: { FLOW-SEQUENCE-START } -# flow_mapping: { FLOW-MAPPING-START } -# flow_sequence_entry: { ALIAS ANCHOR TAG SCALAR FLOW-SEQUENCE-START FLOW-MAPPING-START KEY } -# flow_mapping_entry: { ALIAS ANCHOR TAG SCALAR FLOW-SEQUENCE-START FLOW-MAPPING-START KEY } - -__all__ = ['Parser', 'ParserError'] - -from .error import MarkedYAMLError -from .tokens import * -from .events import * -from .scanner import * - -class ParserError(MarkedYAMLError): - pass - -class Parser: - # Since writing a recursive-descendant parser is a straightforward task, we - # do not give many comments here. - - DEFAULT_TAGS = { - '!': '!', - '!!': 'tag:yaml.org,2002:', - } - - def __init__(self): - self.current_event = None - self.yaml_version = None - self.tag_handles = {} - self.states = [] - self.marks = [] - self.state = self.parse_stream_start - - def dispose(self): - # Reset the state attributes (to clear self-references) - self.states = [] - self.state = None - - def check_event(self, *choices): - # Check the type of the next event. - if self.current_event is None: - if self.state: - self.current_event = self.state() - if self.current_event is not None: - if not choices: - return True - for choice in choices: - if isinstance(self.current_event, choice): - return True - return False - - def peek_event(self): - # Get the next event. - if self.current_event is None: - if self.state: - self.current_event = self.state() - return self.current_event - - def get_event(self): - # Get the next event and proceed further. - if self.current_event is None: - if self.state: - self.current_event = self.state() - value = self.current_event - self.current_event = None - return value - - # stream ::= STREAM-START implicit_document? explicit_document* STREAM-END - # implicit_document ::= block_node DOCUMENT-END* - # explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END* - - def parse_stream_start(self): - - # Parse the stream start. - token = self.get_token() - event = StreamStartEvent(token.start_mark, token.end_mark, - encoding=token.encoding) - - # Prepare the next state. - self.state = self.parse_implicit_document_start - - return event - - def parse_implicit_document_start(self): - - # Parse an implicit document. - if not self.check_token(DirectiveToken, DocumentStartToken, - StreamEndToken): - self.tag_handles = self.DEFAULT_TAGS - token = self.peek_token() - start_mark = end_mark = token.start_mark - event = DocumentStartEvent(start_mark, end_mark, - explicit=False) - - # Prepare the next state. - self.states.append(self.parse_document_end) - self.state = self.parse_block_node - - return event - - else: - return self.parse_document_start() - - def parse_document_start(self): - - # Parse any extra document end indicators. - while self.check_token(DocumentEndToken): - self.get_token() - - # Parse an explicit document. - if not self.check_token(StreamEndToken): - token = self.peek_token() - start_mark = token.start_mark - version, tags = self.process_directives() - if not self.check_token(DocumentStartToken): - raise ParserError(None, None, - "expected '', but found %r" - % self.peek_token().id, - self.peek_token().start_mark) - token = self.get_token() - end_mark = token.end_mark - event = DocumentStartEvent(start_mark, end_mark, - explicit=True, version=version, tags=tags) - self.states.append(self.parse_document_end) - self.state = self.parse_document_content - else: - # Parse the end of the stream. - token = self.get_token() - event = StreamEndEvent(token.start_mark, token.end_mark) - assert not self.states - assert not self.marks - self.state = None - return event - - def parse_document_end(self): - - # Parse the document end. - token = self.peek_token() - start_mark = end_mark = token.start_mark - explicit = False - if self.check_token(DocumentEndToken): - token = self.get_token() - end_mark = token.end_mark - explicit = True - event = DocumentEndEvent(start_mark, end_mark, - explicit=explicit) - - # Prepare the next state. - self.state = self.parse_document_start - - return event - - def parse_document_content(self): - if self.check_token(DirectiveToken, - DocumentStartToken, DocumentEndToken, StreamEndToken): - event = self.process_empty_scalar(self.peek_token().start_mark) - self.state = self.states.pop() - return event - else: - return self.parse_block_node() - - def process_directives(self): - self.yaml_version = None - self.tag_handles = {} - while self.check_token(DirectiveToken): - token = self.get_token() - if token.name == 'YAML': - if self.yaml_version is not None: - raise ParserError(None, None, - "found duplicate YAML directive", token.start_mark) - major, minor = token.value - if major != 1: - raise ParserError(None, None, - "found incompatible YAML document (version 1.* is required)", - token.start_mark) - self.yaml_version = token.value - elif token.name == 'TAG': - handle, prefix = token.value - if handle in self.tag_handles: - raise ParserError(None, None, - "duplicate tag handle %r" % handle, - token.start_mark) - self.tag_handles[handle] = prefix - if self.tag_handles: - value = self.yaml_version, self.tag_handles.copy() - else: - value = self.yaml_version, None - for key in self.DEFAULT_TAGS: - if key not in self.tag_handles: - self.tag_handles[key] = self.DEFAULT_TAGS[key] - return value - - # block_node_or_indentless_sequence ::= ALIAS - # | properties (block_content | indentless_block_sequence)? - # | block_content - # | indentless_block_sequence - # block_node ::= ALIAS - # | properties block_content? - # | block_content - # flow_node ::= ALIAS - # | properties flow_content? - # | flow_content - # properties ::= TAG ANCHOR? | ANCHOR TAG? - # block_content ::= block_collection | flow_collection | SCALAR - # flow_content ::= flow_collection | SCALAR - # block_collection ::= block_sequence | block_mapping - # flow_collection ::= flow_sequence | flow_mapping - - def parse_block_node(self): - return self.parse_node(block=True) - - def parse_flow_node(self): - return self.parse_node() - - def parse_block_node_or_indentless_sequence(self): - return self.parse_node(block=True, indentless_sequence=True) - - def parse_node(self, block=False, indentless_sequence=False): - if self.check_token(AliasToken): - token = self.get_token() - event = AliasEvent(token.value, token.start_mark, token.end_mark) - self.state = self.states.pop() - else: - anchor = None - tag = None - start_mark = end_mark = tag_mark = None - if self.check_token(AnchorToken): - token = self.get_token() - start_mark = token.start_mark - end_mark = token.end_mark - anchor = token.value - if self.check_token(TagToken): - token = self.get_token() - tag_mark = token.start_mark - end_mark = token.end_mark - tag = token.value - elif self.check_token(TagToken): - token = self.get_token() - start_mark = tag_mark = token.start_mark - end_mark = token.end_mark - tag = token.value - if self.check_token(AnchorToken): - token = self.get_token() - end_mark = token.end_mark - anchor = token.value - if tag is not None: - handle, suffix = tag - if handle is not None: - if handle not in self.tag_handles: - raise ParserError("while parsing a node", start_mark, - "found undefined tag handle %r" % handle, - tag_mark) - tag = self.tag_handles[handle]+suffix - else: - tag = suffix - #if tag == '!': - # raise ParserError("while parsing a node", start_mark, - # "found non-specific tag '!'", tag_mark, - # "Please check 'http://pyyaml.org/wiki/YAMLNonSpecificTag' and share your opinion.") - if start_mark is None: - start_mark = end_mark = self.peek_token().start_mark - event = None - implicit = (tag is None or tag == '!') - if indentless_sequence and self.check_token(BlockEntryToken): - end_mark = self.peek_token().end_mark - event = SequenceStartEvent(anchor, tag, implicit, - start_mark, end_mark) - self.state = self.parse_indentless_sequence_entry - else: - if self.check_token(ScalarToken): - token = self.get_token() - end_mark = token.end_mark - if (token.plain and tag is None) or tag == '!': - implicit = (True, False) - elif tag is None: - implicit = (False, True) - else: - implicit = (False, False) - event = ScalarEvent(anchor, tag, implicit, token.value, - start_mark, end_mark, style=token.style) - self.state = self.states.pop() - elif self.check_token(FlowSequenceStartToken): - end_mark = self.peek_token().end_mark - event = SequenceStartEvent(anchor, tag, implicit, - start_mark, end_mark, flow_style=True) - self.state = self.parse_flow_sequence_first_entry - elif self.check_token(FlowMappingStartToken): - end_mark = self.peek_token().end_mark - event = MappingStartEvent(anchor, tag, implicit, - start_mark, end_mark, flow_style=True) - self.state = self.parse_flow_mapping_first_key - elif block and self.check_token(BlockSequenceStartToken): - end_mark = self.peek_token().start_mark - event = SequenceStartEvent(anchor, tag, implicit, - start_mark, end_mark, flow_style=False) - self.state = self.parse_block_sequence_first_entry - elif block and self.check_token(BlockMappingStartToken): - end_mark = self.peek_token().start_mark - event = MappingStartEvent(anchor, tag, implicit, - start_mark, end_mark, flow_style=False) - self.state = self.parse_block_mapping_first_key - elif anchor is not None or tag is not None: - # Empty scalars are allowed even if a tag or an anchor is - # specified. - event = ScalarEvent(anchor, tag, (implicit, False), '', - start_mark, end_mark) - self.state = self.states.pop() - else: - if block: - node = 'block' - else: - node = 'flow' - token = self.peek_token() - raise ParserError("while parsing a %s node" % node, start_mark, - "expected the node content, but found %r" % token.id, - token.start_mark) - return event - - # block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END - - def parse_block_sequence_first_entry(self): - token = self.get_token() - self.marks.append(token.start_mark) - return self.parse_block_sequence_entry() - - def parse_block_sequence_entry(self): - if self.check_token(BlockEntryToken): - token = self.get_token() - if not self.check_token(BlockEntryToken, BlockEndToken): - self.states.append(self.parse_block_sequence_entry) - return self.parse_block_node() - else: - self.state = self.parse_block_sequence_entry - return self.process_empty_scalar(token.end_mark) - if not self.check_token(BlockEndToken): - token = self.peek_token() - raise ParserError("while parsing a block collection", self.marks[-1], - "expected , but found %r" % token.id, token.start_mark) - token = self.get_token() - event = SequenceEndEvent(token.start_mark, token.end_mark) - self.state = self.states.pop() - self.marks.pop() - return event - - # indentless_sequence ::= (BLOCK-ENTRY block_node?)+ - - def parse_indentless_sequence_entry(self): - if self.check_token(BlockEntryToken): - token = self.get_token() - if not self.check_token(BlockEntryToken, - KeyToken, ValueToken, BlockEndToken): - self.states.append(self.parse_indentless_sequence_entry) - return self.parse_block_node() - else: - self.state = self.parse_indentless_sequence_entry - return self.process_empty_scalar(token.end_mark) - token = self.peek_token() - event = SequenceEndEvent(token.start_mark, token.start_mark) - self.state = self.states.pop() - return event - - # block_mapping ::= BLOCK-MAPPING_START - # ((KEY block_node_or_indentless_sequence?)? - # (VALUE block_node_or_indentless_sequence?)?)* - # BLOCK-END - - def parse_block_mapping_first_key(self): - token = self.get_token() - self.marks.append(token.start_mark) - return self.parse_block_mapping_key() - - def parse_block_mapping_key(self): - if self.check_token(KeyToken): - token = self.get_token() - if not self.check_token(KeyToken, ValueToken, BlockEndToken): - self.states.append(self.parse_block_mapping_value) - return self.parse_block_node_or_indentless_sequence() - else: - self.state = self.parse_block_mapping_value - return self.process_empty_scalar(token.end_mark) - if not self.check_token(BlockEndToken): - token = self.peek_token() - raise ParserError("while parsing a block mapping", self.marks[-1], - "expected , but found %r" % token.id, token.start_mark) - token = self.get_token() - event = MappingEndEvent(token.start_mark, token.end_mark) - self.state = self.states.pop() - self.marks.pop() - return event - - def parse_block_mapping_value(self): - if self.check_token(ValueToken): - token = self.get_token() - if not self.check_token(KeyToken, ValueToken, BlockEndToken): - self.states.append(self.parse_block_mapping_key) - return self.parse_block_node_or_indentless_sequence() - else: - self.state = self.parse_block_mapping_key - return self.process_empty_scalar(token.end_mark) - else: - self.state = self.parse_block_mapping_key - token = self.peek_token() - return self.process_empty_scalar(token.start_mark) - - # flow_sequence ::= FLOW-SEQUENCE-START - # (flow_sequence_entry FLOW-ENTRY)* - # flow_sequence_entry? - # FLOW-SEQUENCE-END - # flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? - # - # Note that while production rules for both flow_sequence_entry and - # flow_mapping_entry are equal, their interpretations are different. - # For `flow_sequence_entry`, the part `KEY flow_node? (VALUE flow_node?)?` - # generate an inline mapping (set syntax). - - def parse_flow_sequence_first_entry(self): - token = self.get_token() - self.marks.append(token.start_mark) - return self.parse_flow_sequence_entry(first=True) - - def parse_flow_sequence_entry(self, first=False): - if not self.check_token(FlowSequenceEndToken): - if not first: - if self.check_token(FlowEntryToken): - self.get_token() - else: - token = self.peek_token() - raise ParserError("while parsing a flow sequence", self.marks[-1], - "expected ',' or ']', but got %r" % token.id, token.start_mark) - - if self.check_token(KeyToken): - token = self.peek_token() - event = MappingStartEvent(None, None, True, - token.start_mark, token.end_mark, - flow_style=True) - self.state = self.parse_flow_sequence_entry_mapping_key - return event - elif not self.check_token(FlowSequenceEndToken): - self.states.append(self.parse_flow_sequence_entry) - return self.parse_flow_node() - token = self.get_token() - event = SequenceEndEvent(token.start_mark, token.end_mark) - self.state = self.states.pop() - self.marks.pop() - return event - - def parse_flow_sequence_entry_mapping_key(self): - token = self.get_token() - if not self.check_token(ValueToken, - FlowEntryToken, FlowSequenceEndToken): - self.states.append(self.parse_flow_sequence_entry_mapping_value) - return self.parse_flow_node() - else: - self.state = self.parse_flow_sequence_entry_mapping_value - return self.process_empty_scalar(token.end_mark) - - def parse_flow_sequence_entry_mapping_value(self): - if self.check_token(ValueToken): - token = self.get_token() - if not self.check_token(FlowEntryToken, FlowSequenceEndToken): - self.states.append(self.parse_flow_sequence_entry_mapping_end) - return self.parse_flow_node() - else: - self.state = self.parse_flow_sequence_entry_mapping_end - return self.process_empty_scalar(token.end_mark) - else: - self.state = self.parse_flow_sequence_entry_mapping_end - token = self.peek_token() - return self.process_empty_scalar(token.start_mark) - - def parse_flow_sequence_entry_mapping_end(self): - self.state = self.parse_flow_sequence_entry - token = self.peek_token() - return MappingEndEvent(token.start_mark, token.start_mark) - - # flow_mapping ::= FLOW-MAPPING-START - # (flow_mapping_entry FLOW-ENTRY)* - # flow_mapping_entry? - # FLOW-MAPPING-END - # flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)? - - def parse_flow_mapping_first_key(self): - token = self.get_token() - self.marks.append(token.start_mark) - return self.parse_flow_mapping_key(first=True) - - def parse_flow_mapping_key(self, first=False): - if not self.check_token(FlowMappingEndToken): - if not first: - if self.check_token(FlowEntryToken): - self.get_token() - else: - token = self.peek_token() - raise ParserError("while parsing a flow mapping", self.marks[-1], - "expected ',' or '}', but got %r" % token.id, token.start_mark) - if self.check_token(KeyToken): - token = self.get_token() - if not self.check_token(ValueToken, - FlowEntryToken, FlowMappingEndToken): - self.states.append(self.parse_flow_mapping_value) - return self.parse_flow_node() - else: - self.state = self.parse_flow_mapping_value - return self.process_empty_scalar(token.end_mark) - elif not self.check_token(FlowMappingEndToken): - self.states.append(self.parse_flow_mapping_empty_value) - return self.parse_flow_node() - token = self.get_token() - event = MappingEndEvent(token.start_mark, token.end_mark) - self.state = self.states.pop() - self.marks.pop() - return event - - def parse_flow_mapping_value(self): - if self.check_token(ValueToken): - token = self.get_token() - if not self.check_token(FlowEntryToken, FlowMappingEndToken): - self.states.append(self.parse_flow_mapping_key) - return self.parse_flow_node() - else: - self.state = self.parse_flow_mapping_key - return self.process_empty_scalar(token.end_mark) - else: - self.state = self.parse_flow_mapping_key - token = self.peek_token() - return self.process_empty_scalar(token.start_mark) - - def parse_flow_mapping_empty_value(self): - self.state = self.parse_flow_mapping_key - return self.process_empty_scalar(self.peek_token().start_mark) - - def process_empty_scalar(self, mark): - return ScalarEvent(None, None, (True, False), '', mark, mark) - diff --git a/src/yaml/reader.py b/src/yaml/reader.py deleted file mode 100644 index 774b021..0000000 --- a/src/yaml/reader.py +++ /dev/null @@ -1,185 +0,0 @@ -# This module contains abstractions for the input stream. You don't have to -# looks further, there are no pretty code. -# -# We define two classes here. -# -# Mark(source, line, column) -# It's just a record and its only use is producing nice error messages. -# Parser does not use it for any other purposes. -# -# Reader(source, data) -# Reader determines the encoding of `data` and converts it to unicode. -# Reader provides the following methods and attributes: -# reader.peek(length=1) - return the next `length` characters -# reader.forward(length=1) - move the current position to `length` characters. -# reader.index - the number of the current character. -# reader.line, stream.column - the line and the column of the current character. - -__all__ = ['Reader', 'ReaderError'] - -from .error import YAMLError, Mark - -import codecs, re - -class ReaderError(YAMLError): - - def __init__(self, name, position, character, encoding, reason): - self.name = name - self.character = character - self.position = position - self.encoding = encoding - self.reason = reason - - def __str__(self): - if isinstance(self.character, bytes): - return "'%s' codec can't decode byte #x%02x: %s\n" \ - " in \"%s\", position %d" \ - % (self.encoding, ord(self.character), self.reason, - self.name, self.position) - else: - return "unacceptable character #x%04x: %s\n" \ - " in \"%s\", position %d" \ - % (self.character, self.reason, - self.name, self.position) - -class Reader(object): - # Reader: - # - determines the data encoding and converts it to a unicode string, - # - checks if characters are in allowed range, - # - adds '\0' to the end. - - # Reader accepts - # - a `bytes` object, - # - a `str` object, - # - a file-like object with its `read` method returning `str`, - # - a file-like object with its `read` method returning `unicode`. - - # Yeah, it's ugly and slow. - - def __init__(self, stream): - self.name = None - self.stream = None - self.stream_pointer = 0 - self.eof = True - self.buffer = '' - self.pointer = 0 - self.raw_buffer = None - self.raw_decode = None - self.encoding = None - self.index = 0 - self.line = 0 - self.column = 0 - if isinstance(stream, str): - self.name = "" - self.check_printable(stream) - self.buffer = stream+'\0' - elif isinstance(stream, bytes): - self.name = "" - self.raw_buffer = stream - self.determine_encoding() - else: - self.stream = stream - self.name = getattr(stream, 'name', "") - self.eof = False - self.raw_buffer = None - self.determine_encoding() - - def peek(self, index=0): - try: - return self.buffer[self.pointer+index] - except IndexError: - self.update(index+1) - return self.buffer[self.pointer+index] - - def prefix(self, length=1): - if self.pointer+length >= len(self.buffer): - self.update(length) - return self.buffer[self.pointer:self.pointer+length] - - def forward(self, length=1): - if self.pointer+length+1 >= len(self.buffer): - self.update(length+1) - while length: - ch = self.buffer[self.pointer] - self.pointer += 1 - self.index += 1 - if ch in '\n\x85\u2028\u2029' \ - or (ch == '\r' and self.buffer[self.pointer] != '\n'): - self.line += 1 - self.column = 0 - elif ch != '\uFEFF': - self.column += 1 - length -= 1 - - def get_mark(self): - if self.stream is None: - return Mark(self.name, self.index, self.line, self.column, - self.buffer, self.pointer) - else: - return Mark(self.name, self.index, self.line, self.column, - None, None) - - def determine_encoding(self): - while not self.eof and (self.raw_buffer is None or len(self.raw_buffer) < 2): - self.update_raw() - if isinstance(self.raw_buffer, bytes): - if self.raw_buffer.startswith(codecs.BOM_UTF16_LE): - self.raw_decode = codecs.utf_16_le_decode - self.encoding = 'utf-16-le' - elif self.raw_buffer.startswith(codecs.BOM_UTF16_BE): - self.raw_decode = codecs.utf_16_be_decode - self.encoding = 'utf-16-be' - else: - self.raw_decode = codecs.utf_8_decode - self.encoding = 'utf-8' - self.update(1) - - NON_PRINTABLE = re.compile('[^\x09\x0A\x0D\x20-\x7E\x85\xA0-\uD7FF\uE000-\uFFFD\U00010000-\U0010ffff]') - def check_printable(self, data): - match = self.NON_PRINTABLE.search(data) - if match: - character = match.group() - position = self.index+(len(self.buffer)-self.pointer)+match.start() - raise ReaderError(self.name, position, ord(character), - 'unicode', "special characters are not allowed") - - def update(self, length): - if self.raw_buffer is None: - return - self.buffer = self.buffer[self.pointer:] - self.pointer = 0 - while len(self.buffer) < length: - if not self.eof: - self.update_raw() - if self.raw_decode is not None: - try: - data, converted = self.raw_decode(self.raw_buffer, - 'strict', self.eof) - except UnicodeDecodeError as exc: - character = self.raw_buffer[exc.start] - if self.stream is not None: - position = self.stream_pointer-len(self.raw_buffer)+exc.start - else: - position = exc.start - raise ReaderError(self.name, position, character, - exc.encoding, exc.reason) - else: - data = self.raw_buffer - converted = len(data) - self.check_printable(data) - self.buffer += data - self.raw_buffer = self.raw_buffer[converted:] - if self.eof: - self.buffer += '\0' - self.raw_buffer = None - break - - def update_raw(self, size=4096): - data = self.stream.read(size) - if self.raw_buffer is None: - self.raw_buffer = data - else: - self.raw_buffer += data - self.stream_pointer += len(data) - if not data: - self.eof = True diff --git a/src/yaml/representer.py b/src/yaml/representer.py deleted file mode 100644 index 3b0b192..0000000 --- a/src/yaml/representer.py +++ /dev/null @@ -1,389 +0,0 @@ - -__all__ = ['BaseRepresenter', 'SafeRepresenter', 'Representer', - 'RepresenterError'] - -from .error import * -from .nodes import * - -import datetime, copyreg, types, base64, collections - -class RepresenterError(YAMLError): - pass - -class BaseRepresenter: - - yaml_representers = {} - yaml_multi_representers = {} - - def __init__(self, default_style=None, default_flow_style=False, sort_keys=True): - self.default_style = default_style - self.sort_keys = sort_keys - self.default_flow_style = default_flow_style - self.represented_objects = {} - self.object_keeper = [] - self.alias_key = None - - def represent(self, data): - node = self.represent_data(data) - self.serialize(node) - self.represented_objects = {} - self.object_keeper = [] - self.alias_key = None - - def represent_data(self, data): - if self.ignore_aliases(data): - self.alias_key = None - else: - self.alias_key = id(data) - if self.alias_key is not None: - if self.alias_key in self.represented_objects: - node = self.represented_objects[self.alias_key] - #if node is None: - # raise RepresenterError("recursive objects are not allowed: %r" % data) - return node - #self.represented_objects[alias_key] = None - self.object_keeper.append(data) - data_types = type(data).__mro__ - if data_types[0] in self.yaml_representers: - node = self.yaml_representers[data_types[0]](self, data) - else: - for data_type in data_types: - if data_type in self.yaml_multi_representers: - node = self.yaml_multi_representers[data_type](self, data) - break - else: - if None in self.yaml_multi_representers: - node = self.yaml_multi_representers[None](self, data) - elif None in self.yaml_representers: - node = self.yaml_representers[None](self, data) - else: - node = ScalarNode(None, str(data)) - #if alias_key is not None: - # self.represented_objects[alias_key] = node - return node - - @classmethod - def add_representer(cls, data_type, representer): - if not 'yaml_representers' in cls.__dict__: - cls.yaml_representers = cls.yaml_representers.copy() - cls.yaml_representers[data_type] = representer - - @classmethod - def add_multi_representer(cls, data_type, representer): - if not 'yaml_multi_representers' in cls.__dict__: - cls.yaml_multi_representers = cls.yaml_multi_representers.copy() - cls.yaml_multi_representers[data_type] = representer - - def represent_scalar(self, tag, value, style=None): - if style is None: - style = self.default_style - node = ScalarNode(tag, value, style=style) - if self.alias_key is not None: - self.represented_objects[self.alias_key] = node - return node - - def represent_sequence(self, tag, sequence, flow_style=None): - value = [] - node = SequenceNode(tag, value, flow_style=flow_style) - if self.alias_key is not None: - self.represented_objects[self.alias_key] = node - best_style = True - for item in sequence: - node_item = self.represent_data(item) - if not (isinstance(node_item, ScalarNode) and not node_item.style): - best_style = False - value.append(node_item) - if flow_style is None: - if self.default_flow_style is not None: - node.flow_style = self.default_flow_style - else: - node.flow_style = best_style - return node - - def represent_mapping(self, tag, mapping, flow_style=None): - value = [] - node = MappingNode(tag, value, flow_style=flow_style) - if self.alias_key is not None: - self.represented_objects[self.alias_key] = node - best_style = True - if hasattr(mapping, 'items'): - mapping = list(mapping.items()) - if self.sort_keys: - try: - mapping = sorted(mapping) - except TypeError: - pass - for item_key, item_value in mapping: - node_key = self.represent_data(item_key) - node_value = self.represent_data(item_value) - if not (isinstance(node_key, ScalarNode) and not node_key.style): - best_style = False - if not (isinstance(node_value, ScalarNode) and not node_value.style): - best_style = False - value.append((node_key, node_value)) - if flow_style is None: - if self.default_flow_style is not None: - node.flow_style = self.default_flow_style - else: - node.flow_style = best_style - return node - - def ignore_aliases(self, data): - return False - -class SafeRepresenter(BaseRepresenter): - - def ignore_aliases(self, data): - if data is None: - return True - if isinstance(data, tuple) and data == (): - return True - if isinstance(data, (str, bytes, bool, int, float)): - return True - - def represent_none(self, data): - return self.represent_scalar('tag:yaml.org,2002:null', 'null') - - def represent_str(self, data): - return self.represent_scalar('tag:yaml.org,2002:str', data) - - def represent_binary(self, data): - if hasattr(base64, 'encodebytes'): - data = base64.encodebytes(data).decode('ascii') - else: - data = base64.encodestring(data).decode('ascii') - return self.represent_scalar('tag:yaml.org,2002:binary', data, style='|') - - def represent_bool(self, data): - if data: - value = 'true' - else: - value = 'false' - return self.represent_scalar('tag:yaml.org,2002:bool', value) - - def represent_int(self, data): - return self.represent_scalar('tag:yaml.org,2002:int', str(data)) - - inf_value = 1e300 - while repr(inf_value) != repr(inf_value*inf_value): - inf_value *= inf_value - - def represent_float(self, data): - if data != data or (data == 0.0 and data == 1.0): - value = '.nan' - elif data == self.inf_value: - value = '.inf' - elif data == -self.inf_value: - value = '-.inf' - else: - value = repr(data).lower() - # Note that in some cases `repr(data)` represents a float number - # without the decimal parts. For instance: - # >>> repr(1e17) - # '1e17' - # Unfortunately, this is not a valid float representation according - # to the definition of the `!!float` tag. We fix this by adding - # '.0' before the 'e' symbol. - if '.' not in value and 'e' in value: - value = value.replace('e', '.0e', 1) - return self.represent_scalar('tag:yaml.org,2002:float', value) - - def represent_list(self, data): - #pairs = (len(data) > 0 and isinstance(data, list)) - #if pairs: - # for item in data: - # if not isinstance(item, tuple) or len(item) != 2: - # pairs = False - # break - #if not pairs: - return self.represent_sequence('tag:yaml.org,2002:seq', data) - #value = [] - #for item_key, item_value in data: - # value.append(self.represent_mapping(u'tag:yaml.org,2002:map', - # [(item_key, item_value)])) - #return SequenceNode(u'tag:yaml.org,2002:pairs', value) - - def represent_dict(self, data): - return self.represent_mapping('tag:yaml.org,2002:map', data) - - def represent_set(self, data): - value = {} - for key in data: - value[key] = None - return self.represent_mapping('tag:yaml.org,2002:set', value) - - def represent_date(self, data): - value = data.isoformat() - return self.represent_scalar('tag:yaml.org,2002:timestamp', value) - - def represent_datetime(self, data): - value = data.isoformat(' ') - return self.represent_scalar('tag:yaml.org,2002:timestamp', value) - - def represent_yaml_object(self, tag, data, cls, flow_style=None): - if hasattr(data, '__getstate__'): - state = data.__getstate__() - else: - state = data.__dict__.copy() - return self.represent_mapping(tag, state, flow_style=flow_style) - - def represent_undefined(self, data): - raise RepresenterError("cannot represent an object", data) - -SafeRepresenter.add_representer(type(None), - SafeRepresenter.represent_none) - -SafeRepresenter.add_representer(str, - SafeRepresenter.represent_str) - -SafeRepresenter.add_representer(bytes, - SafeRepresenter.represent_binary) - -SafeRepresenter.add_representer(bool, - SafeRepresenter.represent_bool) - -SafeRepresenter.add_representer(int, - SafeRepresenter.represent_int) - -SafeRepresenter.add_representer(float, - SafeRepresenter.represent_float) - -SafeRepresenter.add_representer(list, - SafeRepresenter.represent_list) - -SafeRepresenter.add_representer(tuple, - SafeRepresenter.represent_list) - -SafeRepresenter.add_representer(dict, - SafeRepresenter.represent_dict) - -SafeRepresenter.add_representer(set, - SafeRepresenter.represent_set) - -SafeRepresenter.add_representer(datetime.date, - SafeRepresenter.represent_date) - -SafeRepresenter.add_representer(datetime.datetime, - SafeRepresenter.represent_datetime) - -SafeRepresenter.add_representer(None, - SafeRepresenter.represent_undefined) - -class Representer(SafeRepresenter): - - def represent_complex(self, data): - if data.imag == 0.0: - data = '%r' % data.real - elif data.real == 0.0: - data = '%rj' % data.imag - elif data.imag > 0: - data = '%r+%rj' % (data.real, data.imag) - else: - data = '%r%rj' % (data.real, data.imag) - return self.represent_scalar('tag:yaml.org,2002:python/complex', data) - - def represent_tuple(self, data): - return self.represent_sequence('tag:yaml.org,2002:python/tuple', data) - - def represent_name(self, data): - name = '%s.%s' % (data.__module__, data.__name__) - return self.represent_scalar('tag:yaml.org,2002:python/name:'+name, '') - - def represent_module(self, data): - return self.represent_scalar( - 'tag:yaml.org,2002:python/module:'+data.__name__, '') - - def represent_object(self, data): - # We use __reduce__ API to save the data. data.__reduce__ returns - # a tuple of length 2-5: - # (function, args, state, listitems, dictitems) - - # For reconstructing, we calls function(*args), then set its state, - # listitems, and dictitems if they are not None. - - # A special case is when function.__name__ == '__newobj__'. In this - # case we create the object with args[0].__new__(*args). - - # Another special case is when __reduce__ returns a string - we don't - # support it. - - # We produce a !!python/object, !!python/object/new or - # !!python/object/apply node. - - cls = type(data) - if cls in copyreg.dispatch_table: - reduce = copyreg.dispatch_table[cls](data) - elif hasattr(data, '__reduce_ex__'): - reduce = data.__reduce_ex__(2) - elif hasattr(data, '__reduce__'): - reduce = data.__reduce__() - else: - raise RepresenterError("cannot represent an object", data) - reduce = (list(reduce)+[None]*5)[:5] - function, args, state, listitems, dictitems = reduce - args = list(args) - if state is None: - state = {} - if listitems is not None: - listitems = list(listitems) - if dictitems is not None: - dictitems = dict(dictitems) - if function.__name__ == '__newobj__': - function = args[0] - args = args[1:] - tag = 'tag:yaml.org,2002:python/object/new:' - newobj = True - else: - tag = 'tag:yaml.org,2002:python/object/apply:' - newobj = False - function_name = '%s.%s' % (function.__module__, function.__name__) - if not args and not listitems and not dictitems \ - and isinstance(state, dict) and newobj: - return self.represent_mapping( - 'tag:yaml.org,2002:python/object:'+function_name, state) - if not listitems and not dictitems \ - and isinstance(state, dict) and not state: - return self.represent_sequence(tag+function_name, args) - value = {} - if args: - value['args'] = args - if state or not isinstance(state, dict): - value['state'] = state - if listitems: - value['listitems'] = listitems - if dictitems: - value['dictitems'] = dictitems - return self.represent_mapping(tag+function_name, value) - - def represent_ordered_dict(self, data): - # Provide uniform representation across different Python versions. - data_type = type(data) - tag = 'tag:yaml.org,2002:python/object/apply:%s.%s' \ - % (data_type.__module__, data_type.__name__) - items = [[key, value] for key, value in data.items()] - return self.represent_sequence(tag, [items]) - -Representer.add_representer(complex, - Representer.represent_complex) - -Representer.add_representer(tuple, - Representer.represent_tuple) - -Representer.add_representer(type, - Representer.represent_name) - -Representer.add_representer(collections.OrderedDict, - Representer.represent_ordered_dict) - -Representer.add_representer(types.FunctionType, - Representer.represent_name) - -Representer.add_representer(types.BuiltinFunctionType, - Representer.represent_name) - -Representer.add_representer(types.ModuleType, - Representer.represent_module) - -Representer.add_multi_representer(object, - Representer.represent_object) - diff --git a/src/yaml/resolver.py b/src/yaml/resolver.py deleted file mode 100644 index 02b82e7..0000000 --- a/src/yaml/resolver.py +++ /dev/null @@ -1,227 +0,0 @@ - -__all__ = ['BaseResolver', 'Resolver'] - -from .error import * -from .nodes import * - -import re - -class ResolverError(YAMLError): - pass - -class BaseResolver: - - DEFAULT_SCALAR_TAG = 'tag:yaml.org,2002:str' - DEFAULT_SEQUENCE_TAG = 'tag:yaml.org,2002:seq' - DEFAULT_MAPPING_TAG = 'tag:yaml.org,2002:map' - - yaml_implicit_resolvers = {} - yaml_path_resolvers = {} - - def __init__(self): - self.resolver_exact_paths = [] - self.resolver_prefix_paths = [] - - @classmethod - def add_implicit_resolver(cls, tag, regexp, first): - if not 'yaml_implicit_resolvers' in cls.__dict__: - implicit_resolvers = {} - for key in cls.yaml_implicit_resolvers: - implicit_resolvers[key] = cls.yaml_implicit_resolvers[key][:] - cls.yaml_implicit_resolvers = implicit_resolvers - if first is None: - first = [None] - for ch in first: - cls.yaml_implicit_resolvers.setdefault(ch, []).append((tag, regexp)) - - @classmethod - def add_path_resolver(cls, tag, path, kind=None): - # Note: `add_path_resolver` is experimental. The API could be changed. - # `new_path` is a pattern that is matched against the path from the - # root to the node that is being considered. `node_path` elements are - # tuples `(node_check, index_check)`. `node_check` is a node class: - # `ScalarNode`, `SequenceNode`, `MappingNode` or `None`. `None` - # matches any kind of a node. `index_check` could be `None`, a boolean - # value, a string value, or a number. `None` and `False` match against - # any _value_ of sequence and mapping nodes. `True` matches against - # any _key_ of a mapping node. A string `index_check` matches against - # a mapping value that corresponds to a scalar key which content is - # equal to the `index_check` value. An integer `index_check` matches - # against a sequence value with the index equal to `index_check`. - if not 'yaml_path_resolvers' in cls.__dict__: - cls.yaml_path_resolvers = cls.yaml_path_resolvers.copy() - new_path = [] - for element in path: - if isinstance(element, (list, tuple)): - if len(element) == 2: - node_check, index_check = element - elif len(element) == 1: - node_check = element[0] - index_check = True - else: - raise ResolverError("Invalid path element: %s" % element) - else: - node_check = None - index_check = element - if node_check is str: - node_check = ScalarNode - elif node_check is list: - node_check = SequenceNode - elif node_check is dict: - node_check = MappingNode - elif node_check not in [ScalarNode, SequenceNode, MappingNode] \ - and not isinstance(node_check, str) \ - and node_check is not None: - raise ResolverError("Invalid node checker: %s" % node_check) - if not isinstance(index_check, (str, int)) \ - and index_check is not None: - raise ResolverError("Invalid index checker: %s" % index_check) - new_path.append((node_check, index_check)) - if kind is str: - kind = ScalarNode - elif kind is list: - kind = SequenceNode - elif kind is dict: - kind = MappingNode - elif kind not in [ScalarNode, SequenceNode, MappingNode] \ - and kind is not None: - raise ResolverError("Invalid node kind: %s" % kind) - cls.yaml_path_resolvers[tuple(new_path), kind] = tag - - def descend_resolver(self, current_node, current_index): - if not self.yaml_path_resolvers: - return - exact_paths = {} - prefix_paths = [] - if current_node: - depth = len(self.resolver_prefix_paths) - for path, kind in self.resolver_prefix_paths[-1]: - if self.check_resolver_prefix(depth, path, kind, - current_node, current_index): - if len(path) > depth: - prefix_paths.append((path, kind)) - else: - exact_paths[kind] = self.yaml_path_resolvers[path, kind] - else: - for path, kind in self.yaml_path_resolvers: - if not path: - exact_paths[kind] = self.yaml_path_resolvers[path, kind] - else: - prefix_paths.append((path, kind)) - self.resolver_exact_paths.append(exact_paths) - self.resolver_prefix_paths.append(prefix_paths) - - def ascend_resolver(self): - if not self.yaml_path_resolvers: - return - self.resolver_exact_paths.pop() - self.resolver_prefix_paths.pop() - - def check_resolver_prefix(self, depth, path, kind, - current_node, current_index): - node_check, index_check = path[depth-1] - if isinstance(node_check, str): - if current_node.tag != node_check: - return - elif node_check is not None: - if not isinstance(current_node, node_check): - return - if index_check is True and current_index is not None: - return - if (index_check is False or index_check is None) \ - and current_index is None: - return - if isinstance(index_check, str): - if not (isinstance(current_index, ScalarNode) - and index_check == current_index.value): - return - elif isinstance(index_check, int) and not isinstance(index_check, bool): - if index_check != current_index: - return - return True - - def resolve(self, kind, value, implicit): - if kind is ScalarNode and implicit[0]: - if value == '': - resolvers = self.yaml_implicit_resolvers.get('', []) - else: - resolvers = self.yaml_implicit_resolvers.get(value[0], []) - resolvers += self.yaml_implicit_resolvers.get(None, []) - for tag, regexp in resolvers: - if regexp.match(value): - return tag - implicit = implicit[1] - if self.yaml_path_resolvers: - exact_paths = self.resolver_exact_paths[-1] - if kind in exact_paths: - return exact_paths[kind] - if None in exact_paths: - return exact_paths[None] - if kind is ScalarNode: - return self.DEFAULT_SCALAR_TAG - elif kind is SequenceNode: - return self.DEFAULT_SEQUENCE_TAG - elif kind is MappingNode: - return self.DEFAULT_MAPPING_TAG - -class Resolver(BaseResolver): - pass - -Resolver.add_implicit_resolver( - 'tag:yaml.org,2002:bool', - re.compile(r'''^(?:yes|Yes|YES|no|No|NO - |true|True|TRUE|false|False|FALSE - |on|On|ON|off|Off|OFF)$''', re.X), - list('yYnNtTfFoO')) - -Resolver.add_implicit_resolver( - 'tag:yaml.org,2002:float', - re.compile(r'''^(?:[-+]?(?:[0-9][0-9_]*)\.[0-9_]*(?:[eE][-+][0-9]+)? - |\.[0-9_]+(?:[eE][-+][0-9]+)? - |[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\.[0-9_]* - |[-+]?\.(?:inf|Inf|INF) - |\.(?:nan|NaN|NAN))$''', re.X), - list('-+0123456789.')) - -Resolver.add_implicit_resolver( - 'tag:yaml.org,2002:int', - re.compile(r'''^(?:[-+]?0b[0-1_]+ - |[-+]?0[0-7_]+ - |[-+]?(?:0|[1-9][0-9_]*) - |[-+]?0x[0-9a-fA-F_]+ - |[-+]?[1-9][0-9_]*(?::[0-5]?[0-9])+)$''', re.X), - list('-+0123456789')) - -Resolver.add_implicit_resolver( - 'tag:yaml.org,2002:merge', - re.compile(r'^(?:<<)$'), - ['<']) - -Resolver.add_implicit_resolver( - 'tag:yaml.org,2002:null', - re.compile(r'''^(?: ~ - |null|Null|NULL - | )$''', re.X), - ['~', 'n', 'N', '']) - -Resolver.add_implicit_resolver( - 'tag:yaml.org,2002:timestamp', - re.compile(r'''^(?:[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] - |[0-9][0-9][0-9][0-9] -[0-9][0-9]? -[0-9][0-9]? - (?:[Tt]|[ \t]+)[0-9][0-9]? - :[0-9][0-9] :[0-9][0-9] (?:\.[0-9]*)? - (?:[ \t]*(?:Z|[-+][0-9][0-9]?(?::[0-9][0-9])?))?)$''', re.X), - list('0123456789')) - -Resolver.add_implicit_resolver( - 'tag:yaml.org,2002:value', - re.compile(r'^(?:=)$'), - ['=']) - -# The following resolver is only for documentation purposes. It cannot work -# because plain scalars cannot start with '!', '&', or '*'. -Resolver.add_implicit_resolver( - 'tag:yaml.org,2002:yaml', - re.compile(r'^(?:!|&|\*)$'), - list('!&*')) - diff --git a/src/yaml/scanner.py b/src/yaml/scanner.py deleted file mode 100644 index 7437ede..0000000 --- a/src/yaml/scanner.py +++ /dev/null @@ -1,1435 +0,0 @@ - -# Scanner produces tokens of the following types: -# STREAM-START -# STREAM-END -# DIRECTIVE(name, value) -# DOCUMENT-START -# DOCUMENT-END -# BLOCK-SEQUENCE-START -# BLOCK-MAPPING-START -# BLOCK-END -# FLOW-SEQUENCE-START -# FLOW-MAPPING-START -# FLOW-SEQUENCE-END -# FLOW-MAPPING-END -# BLOCK-ENTRY -# FLOW-ENTRY -# KEY -# VALUE -# ALIAS(value) -# ANCHOR(value) -# TAG(value) -# SCALAR(value, plain, style) -# -# Read comments in the Scanner code for more details. -# - -__all__ = ['Scanner', 'ScannerError'] - -from .error import MarkedYAMLError -from .tokens import * - -class ScannerError(MarkedYAMLError): - pass - -class SimpleKey: - # See below simple keys treatment. - - def __init__(self, token_number, required, index, line, column, mark): - self.token_number = token_number - self.required = required - self.index = index - self.line = line - self.column = column - self.mark = mark - -class Scanner: - - def __init__(self): - """Initialize the scanner.""" - # It is assumed that Scanner and Reader will have a common descendant. - # Reader do the dirty work of checking for BOM and converting the - # input data to Unicode. It also adds NUL to the end. - # - # Reader supports the following methods - # self.peek(i=0) # peek the next i-th character - # self.prefix(l=1) # peek the next l characters - # self.forward(l=1) # read the next l characters and move the pointer. - - # Had we reached the end of the stream? - self.done = False - - # The number of unclosed '{' and '['. `flow_level == 0` means block - # context. - self.flow_level = 0 - - # List of processed tokens that are not yet emitted. - self.tokens = [] - - # Add the STREAM-START token. - self.fetch_stream_start() - - # Number of tokens that were emitted through the `get_token` method. - self.tokens_taken = 0 - - # The current indentation level. - self.indent = -1 - - # Past indentation levels. - self.indents = [] - - # Variables related to simple keys treatment. - - # A simple key is a key that is not denoted by the '?' indicator. - # Example of simple keys: - # --- - # block simple key: value - # ? not a simple key: - # : { flow simple key: value } - # We emit the KEY token before all keys, so when we find a potential - # simple key, we try to locate the corresponding ':' indicator. - # Simple keys should be limited to a single line and 1024 characters. - - # Can a simple key start at the current position? A simple key may - # start: - # - at the beginning of the line, not counting indentation spaces - # (in block context), - # - after '{', '[', ',' (in the flow context), - # - after '?', ':', '-' (in the block context). - # In the block context, this flag also signifies if a block collection - # may start at the current position. - self.allow_simple_key = True - - # Keep track of possible simple keys. This is a dictionary. The key - # is `flow_level`; there can be no more that one possible simple key - # for each level. The value is a SimpleKey record: - # (token_number, required, index, line, column, mark) - # A simple key may start with ALIAS, ANCHOR, TAG, SCALAR(flow), - # '[', or '{' tokens. - self.possible_simple_keys = {} - - # Public methods. - - def check_token(self, *choices): - # Check if the next token is one of the given types. - while self.need_more_tokens(): - self.fetch_more_tokens() - if self.tokens: - if not choices: - return True - for choice in choices: - if isinstance(self.tokens[0], choice): - return True - return False - - def peek_token(self): - # Return the next token, but do not delete if from the queue. - # Return None if no more tokens. - while self.need_more_tokens(): - self.fetch_more_tokens() - if self.tokens: - return self.tokens[0] - else: - return None - - def get_token(self): - # Return the next token. - while self.need_more_tokens(): - self.fetch_more_tokens() - if self.tokens: - self.tokens_taken += 1 - return self.tokens.pop(0) - - # Private methods. - - def need_more_tokens(self): - if self.done: - return False - if not self.tokens: - return True - # The current token may be a potential simple key, so we - # need to look further. - self.stale_possible_simple_keys() - if self.next_possible_simple_key() == self.tokens_taken: - return True - - def fetch_more_tokens(self): - - # Eat whitespaces and comments until we reach the next token. - self.scan_to_next_token() - - # Remove obsolete possible simple keys. - self.stale_possible_simple_keys() - - # Compare the current indentation and column. It may add some tokens - # and decrease the current indentation level. - self.unwind_indent(self.column) - - # Peek the next character. - ch = self.peek() - - # Is it the end of stream? - if ch == '\0': - return self.fetch_stream_end() - - # Is it a directive? - if ch == '%' and self.check_directive(): - return self.fetch_directive() - - # Is it the document start? - if ch == '-' and self.check_document_start(): - return self.fetch_document_start() - - # Is it the document end? - if ch == '.' and self.check_document_end(): - return self.fetch_document_end() - - # TODO: support for BOM within a stream. - #if ch == '\uFEFF': - # return self.fetch_bom() <-- issue BOMToken - - # Note: the order of the following checks is NOT significant. - - # Is it the flow sequence start indicator? - if ch == '[': - return self.fetch_flow_sequence_start() - - # Is it the flow mapping start indicator? - if ch == '{': - return self.fetch_flow_mapping_start() - - # Is it the flow sequence end indicator? - if ch == ']': - return self.fetch_flow_sequence_end() - - # Is it the flow mapping end indicator? - if ch == '}': - return self.fetch_flow_mapping_end() - - # Is it the flow entry indicator? - if ch == ',': - return self.fetch_flow_entry() - - # Is it the block entry indicator? - if ch == '-' and self.check_block_entry(): - return self.fetch_block_entry() - - # Is it the key indicator? - if ch == '?' and self.check_key(): - return self.fetch_key() - - # Is it the value indicator? - if ch == ':' and self.check_value(): - return self.fetch_value() - - # Is it an alias? - if ch == '*': - return self.fetch_alias() - - # Is it an anchor? - if ch == '&': - return self.fetch_anchor() - - # Is it a tag? - if ch == '!': - return self.fetch_tag() - - # Is it a literal scalar? - if ch == '|' and not self.flow_level: - return self.fetch_literal() - - # Is it a folded scalar? - if ch == '>' and not self.flow_level: - return self.fetch_folded() - - # Is it a single quoted scalar? - if ch == '\'': - return self.fetch_single() - - # Is it a double quoted scalar? - if ch == '\"': - return self.fetch_double() - - # It must be a plain scalar then. - if self.check_plain(): - return self.fetch_plain() - - # No? It's an error. Let's produce a nice error message. - raise ScannerError("while scanning for the next token", None, - "found character %r that cannot start any token" % ch, - self.get_mark()) - - # Simple keys treatment. - - def next_possible_simple_key(self): - # Return the number of the nearest possible simple key. Actually we - # don't need to loop through the whole dictionary. We may replace it - # with the following code: - # if not self.possible_simple_keys: - # return None - # return self.possible_simple_keys[ - # min(self.possible_simple_keys.keys())].token_number - min_token_number = None - for level in self.possible_simple_keys: - key = self.possible_simple_keys[level] - if min_token_number is None or key.token_number < min_token_number: - min_token_number = key.token_number - return min_token_number - - def stale_possible_simple_keys(self): - # Remove entries that are no longer possible simple keys. According to - # the YAML specification, simple keys - # - should be limited to a single line, - # - should be no longer than 1024 characters. - # Disabling this procedure will allow simple keys of any length and - # height (may cause problems if indentation is broken though). - for level in list(self.possible_simple_keys): - key = self.possible_simple_keys[level] - if key.line != self.line \ - or self.index-key.index > 1024: - if key.required: - raise ScannerError("while scanning a simple key", key.mark, - "could not find expected ':'", self.get_mark()) - del self.possible_simple_keys[level] - - def save_possible_simple_key(self): - # The next token may start a simple key. We check if it's possible - # and save its position. This function is called for - # ALIAS, ANCHOR, TAG, SCALAR(flow), '[', and '{'. - - # Check if a simple key is required at the current position. - required = not self.flow_level and self.indent == self.column - - # The next token might be a simple key. Let's save it's number and - # position. - if self.allow_simple_key: - self.remove_possible_simple_key() - token_number = self.tokens_taken+len(self.tokens) - key = SimpleKey(token_number, required, - self.index, self.line, self.column, self.get_mark()) - self.possible_simple_keys[self.flow_level] = key - - def remove_possible_simple_key(self): - # Remove the saved possible key position at the current flow level. - if self.flow_level in self.possible_simple_keys: - key = self.possible_simple_keys[self.flow_level] - - if key.required: - raise ScannerError("while scanning a simple key", key.mark, - "could not find expected ':'", self.get_mark()) - - del self.possible_simple_keys[self.flow_level] - - # Indentation functions. - - def unwind_indent(self, column): - - ## In flow context, tokens should respect indentation. - ## Actually the condition should be `self.indent >= column` according to - ## the spec. But this condition will prohibit intuitively correct - ## constructions such as - ## key : { - ## } - #if self.flow_level and self.indent > column: - # raise ScannerError(None, None, - # "invalid indentation or unclosed '[' or '{'", - # self.get_mark()) - - # In the flow context, indentation is ignored. We make the scanner less - # restrictive then specification requires. - if self.flow_level: - return - - # In block context, we may need to issue the BLOCK-END tokens. - while self.indent > column: - mark = self.get_mark() - self.indent = self.indents.pop() - self.tokens.append(BlockEndToken(mark, mark)) - - def add_indent(self, column): - # Check if we need to increase indentation. - if self.indent < column: - self.indents.append(self.indent) - self.indent = column - return True - return False - - # Fetchers. - - def fetch_stream_start(self): - # We always add STREAM-START as the first token and STREAM-END as the - # last token. - - # Read the token. - mark = self.get_mark() - - # Add STREAM-START. - self.tokens.append(StreamStartToken(mark, mark, - encoding=self.encoding)) - - - def fetch_stream_end(self): - - # Set the current indentation to -1. - self.unwind_indent(-1) - - # Reset simple keys. - self.remove_possible_simple_key() - self.allow_simple_key = False - self.possible_simple_keys = {} - - # Read the token. - mark = self.get_mark() - - # Add STREAM-END. - self.tokens.append(StreamEndToken(mark, mark)) - - # The steam is finished. - self.done = True - - def fetch_directive(self): - - # Set the current indentation to -1. - self.unwind_indent(-1) - - # Reset simple keys. - self.remove_possible_simple_key() - self.allow_simple_key = False - - # Scan and add DIRECTIVE. - self.tokens.append(self.scan_directive()) - - def fetch_document_start(self): - self.fetch_document_indicator(DocumentStartToken) - - def fetch_document_end(self): - self.fetch_document_indicator(DocumentEndToken) - - def fetch_document_indicator(self, TokenClass): - - # Set the current indentation to -1. - self.unwind_indent(-1) - - # Reset simple keys. Note that there could not be a block collection - # after '---'. - self.remove_possible_simple_key() - self.allow_simple_key = False - - # Add DOCUMENT-START or DOCUMENT-END. - start_mark = self.get_mark() - self.forward(3) - end_mark = self.get_mark() - self.tokens.append(TokenClass(start_mark, end_mark)) - - def fetch_flow_sequence_start(self): - self.fetch_flow_collection_start(FlowSequenceStartToken) - - def fetch_flow_mapping_start(self): - self.fetch_flow_collection_start(FlowMappingStartToken) - - def fetch_flow_collection_start(self, TokenClass): - - # '[' and '{' may start a simple key. - self.save_possible_simple_key() - - # Increase the flow level. - self.flow_level += 1 - - # Simple keys are allowed after '[' and '{'. - self.allow_simple_key = True - - # Add FLOW-SEQUENCE-START or FLOW-MAPPING-START. - start_mark = self.get_mark() - self.forward() - end_mark = self.get_mark() - self.tokens.append(TokenClass(start_mark, end_mark)) - - def fetch_flow_sequence_end(self): - self.fetch_flow_collection_end(FlowSequenceEndToken) - - def fetch_flow_mapping_end(self): - self.fetch_flow_collection_end(FlowMappingEndToken) - - def fetch_flow_collection_end(self, TokenClass): - - # Reset possible simple key on the current level. - self.remove_possible_simple_key() - - # Decrease the flow level. - self.flow_level -= 1 - - # No simple keys after ']' or '}'. - self.allow_simple_key = False - - # Add FLOW-SEQUENCE-END or FLOW-MAPPING-END. - start_mark = self.get_mark() - self.forward() - end_mark = self.get_mark() - self.tokens.append(TokenClass(start_mark, end_mark)) - - def fetch_flow_entry(self): - - # Simple keys are allowed after ','. - self.allow_simple_key = True - - # Reset possible simple key on the current level. - self.remove_possible_simple_key() - - # Add FLOW-ENTRY. - start_mark = self.get_mark() - self.forward() - end_mark = self.get_mark() - self.tokens.append(FlowEntryToken(start_mark, end_mark)) - - def fetch_block_entry(self): - - # Block context needs additional checks. - if not self.flow_level: - - # Are we allowed to start a new entry? - if not self.allow_simple_key: - raise ScannerError(None, None, - "sequence entries are not allowed here", - self.get_mark()) - - # We may need to add BLOCK-SEQUENCE-START. - if self.add_indent(self.column): - mark = self.get_mark() - self.tokens.append(BlockSequenceStartToken(mark, mark)) - - # It's an error for the block entry to occur in the flow context, - # but we let the parser detect this. - else: - pass - - # Simple keys are allowed after '-'. - self.allow_simple_key = True - - # Reset possible simple key on the current level. - self.remove_possible_simple_key() - - # Add BLOCK-ENTRY. - start_mark = self.get_mark() - self.forward() - end_mark = self.get_mark() - self.tokens.append(BlockEntryToken(start_mark, end_mark)) - - def fetch_key(self): - - # Block context needs additional checks. - if not self.flow_level: - - # Are we allowed to start a key (not necessary a simple)? - if not self.allow_simple_key: - raise ScannerError(None, None, - "mapping keys are not allowed here", - self.get_mark()) - - # We may need to add BLOCK-MAPPING-START. - if self.add_indent(self.column): - mark = self.get_mark() - self.tokens.append(BlockMappingStartToken(mark, mark)) - - # Simple keys are allowed after '?' in the block context. - self.allow_simple_key = not self.flow_level - - # Reset possible simple key on the current level. - self.remove_possible_simple_key() - - # Add KEY. - start_mark = self.get_mark() - self.forward() - end_mark = self.get_mark() - self.tokens.append(KeyToken(start_mark, end_mark)) - - def fetch_value(self): - - # Do we determine a simple key? - if self.flow_level in self.possible_simple_keys: - - # Add KEY. - key = self.possible_simple_keys[self.flow_level] - del self.possible_simple_keys[self.flow_level] - self.tokens.insert(key.token_number-self.tokens_taken, - KeyToken(key.mark, key.mark)) - - # If this key starts a new block mapping, we need to add - # BLOCK-MAPPING-START. - if not self.flow_level: - if self.add_indent(key.column): - self.tokens.insert(key.token_number-self.tokens_taken, - BlockMappingStartToken(key.mark, key.mark)) - - # There cannot be two simple keys one after another. - self.allow_simple_key = False - - # It must be a part of a complex key. - else: - - # Block context needs additional checks. - # (Do we really need them? They will be caught by the parser - # anyway.) - if not self.flow_level: - - # We are allowed to start a complex value if and only if - # we can start a simple key. - if not self.allow_simple_key: - raise ScannerError(None, None, - "mapping values are not allowed here", - self.get_mark()) - - # If this value starts a new block mapping, we need to add - # BLOCK-MAPPING-START. It will be detected as an error later by - # the parser. - if not self.flow_level: - if self.add_indent(self.column): - mark = self.get_mark() - self.tokens.append(BlockMappingStartToken(mark, mark)) - - # Simple keys are allowed after ':' in the block context. - self.allow_simple_key = not self.flow_level - - # Reset possible simple key on the current level. - self.remove_possible_simple_key() - - # Add VALUE. - start_mark = self.get_mark() - self.forward() - end_mark = self.get_mark() - self.tokens.append(ValueToken(start_mark, end_mark)) - - def fetch_alias(self): - - # ALIAS could be a simple key. - self.save_possible_simple_key() - - # No simple keys after ALIAS. - self.allow_simple_key = False - - # Scan and add ALIAS. - self.tokens.append(self.scan_anchor(AliasToken)) - - def fetch_anchor(self): - - # ANCHOR could start a simple key. - self.save_possible_simple_key() - - # No simple keys after ANCHOR. - self.allow_simple_key = False - - # Scan and add ANCHOR. - self.tokens.append(self.scan_anchor(AnchorToken)) - - def fetch_tag(self): - - # TAG could start a simple key. - self.save_possible_simple_key() - - # No simple keys after TAG. - self.allow_simple_key = False - - # Scan and add TAG. - self.tokens.append(self.scan_tag()) - - def fetch_literal(self): - self.fetch_block_scalar(style='|') - - def fetch_folded(self): - self.fetch_block_scalar(style='>') - - def fetch_block_scalar(self, style): - - # A simple key may follow a block scalar. - self.allow_simple_key = True - - # Reset possible simple key on the current level. - self.remove_possible_simple_key() - - # Scan and add SCALAR. - self.tokens.append(self.scan_block_scalar(style)) - - def fetch_single(self): - self.fetch_flow_scalar(style='\'') - - def fetch_double(self): - self.fetch_flow_scalar(style='"') - - def fetch_flow_scalar(self, style): - - # A flow scalar could be a simple key. - self.save_possible_simple_key() - - # No simple keys after flow scalars. - self.allow_simple_key = False - - # Scan and add SCALAR. - self.tokens.append(self.scan_flow_scalar(style)) - - def fetch_plain(self): - - # A plain scalar could be a simple key. - self.save_possible_simple_key() - - # No simple keys after plain scalars. But note that `scan_plain` will - # change this flag if the scan is finished at the beginning of the - # line. - self.allow_simple_key = False - - # Scan and add SCALAR. May change `allow_simple_key`. - self.tokens.append(self.scan_plain()) - - # Checkers. - - def check_directive(self): - - # DIRECTIVE: ^ '%' ... - # The '%' indicator is already checked. - if self.column == 0: - return True - - def check_document_start(self): - - # DOCUMENT-START: ^ '---' (' '|'\n') - if self.column == 0: - if self.prefix(3) == '---' \ - and self.peek(3) in '\0 \t\r\n\x85\u2028\u2029': - return True - - def check_document_end(self): - - # DOCUMENT-END: ^ '...' (' '|'\n') - if self.column == 0: - if self.prefix(3) == '...' \ - and self.peek(3) in '\0 \t\r\n\x85\u2028\u2029': - return True - - def check_block_entry(self): - - # BLOCK-ENTRY: '-' (' '|'\n') - return self.peek(1) in '\0 \t\r\n\x85\u2028\u2029' - - def check_key(self): - - # KEY(flow context): '?' - if self.flow_level: - return True - - # KEY(block context): '?' (' '|'\n') - else: - return self.peek(1) in '\0 \t\r\n\x85\u2028\u2029' - - def check_value(self): - - # VALUE(flow context): ':' - if self.flow_level: - return True - - # VALUE(block context): ':' (' '|'\n') - else: - return self.peek(1) in '\0 \t\r\n\x85\u2028\u2029' - - def check_plain(self): - - # A plain scalar may start with any non-space character except: - # '-', '?', ':', ',', '[', ']', '{', '}', - # '#', '&', '*', '!', '|', '>', '\'', '\"', - # '%', '@', '`'. - # - # It may also start with - # '-', '?', ':' - # if it is followed by a non-space character. - # - # Note that we limit the last rule to the block context (except the - # '-' character) because we want the flow context to be space - # independent. - ch = self.peek() - return ch not in '\0 \t\r\n\x85\u2028\u2029-?:,[]{}#&*!|>\'\"%@`' \ - or (self.peek(1) not in '\0 \t\r\n\x85\u2028\u2029' - and (ch == '-' or (not self.flow_level and ch in '?:'))) - - # Scanners. - - def scan_to_next_token(self): - # We ignore spaces, line breaks and comments. - # If we find a line break in the block context, we set the flag - # `allow_simple_key` on. - # The byte order mark is stripped if it's the first character in the - # stream. We do not yet support BOM inside the stream as the - # specification requires. Any such mark will be considered as a part - # of the document. - # - # TODO: We need to make tab handling rules more sane. A good rule is - # Tabs cannot precede tokens - # BLOCK-SEQUENCE-START, BLOCK-MAPPING-START, BLOCK-END, - # KEY(block), VALUE(block), BLOCK-ENTRY - # So the checking code is - # if : - # self.allow_simple_keys = False - # We also need to add the check for `allow_simple_keys == True` to - # `unwind_indent` before issuing BLOCK-END. - # Scanners for block, flow, and plain scalars need to be modified. - - if self.index == 0 and self.peek() == '\uFEFF': - self.forward() - found = False - while not found: - while self.peek() == ' ': - self.forward() - if self.peek() == '#': - while self.peek() not in '\0\r\n\x85\u2028\u2029': - self.forward() - if self.scan_line_break(): - if not self.flow_level: - self.allow_simple_key = True - else: - found = True - - def scan_directive(self): - # See the specification for details. - start_mark = self.get_mark() - self.forward() - name = self.scan_directive_name(start_mark) - value = None - if name == 'YAML': - value = self.scan_yaml_directive_value(start_mark) - end_mark = self.get_mark() - elif name == 'TAG': - value = self.scan_tag_directive_value(start_mark) - end_mark = self.get_mark() - else: - end_mark = self.get_mark() - while self.peek() not in '\0\r\n\x85\u2028\u2029': - self.forward() - self.scan_directive_ignored_line(start_mark) - return DirectiveToken(name, value, start_mark, end_mark) - - def scan_directive_name(self, start_mark): - # See the specification for details. - length = 0 - ch = self.peek(length) - while '0' <= ch <= '9' or 'A' <= ch <= 'Z' or 'a' <= ch <= 'z' \ - or ch in '-_': - length += 1 - ch = self.peek(length) - if not length: - raise ScannerError("while scanning a directive", start_mark, - "expected alphabetic or numeric character, but found %r" - % ch, self.get_mark()) - value = self.prefix(length) - self.forward(length) - ch = self.peek() - if ch not in '\0 \r\n\x85\u2028\u2029': - raise ScannerError("while scanning a directive", start_mark, - "expected alphabetic or numeric character, but found %r" - % ch, self.get_mark()) - return value - - def scan_yaml_directive_value(self, start_mark): - # See the specification for details. - while self.peek() == ' ': - self.forward() - major = self.scan_yaml_directive_number(start_mark) - if self.peek() != '.': - raise ScannerError("while scanning a directive", start_mark, - "expected a digit or '.', but found %r" % self.peek(), - self.get_mark()) - self.forward() - minor = self.scan_yaml_directive_number(start_mark) - if self.peek() not in '\0 \r\n\x85\u2028\u2029': - raise ScannerError("while scanning a directive", start_mark, - "expected a digit or ' ', but found %r" % self.peek(), - self.get_mark()) - return (major, minor) - - def scan_yaml_directive_number(self, start_mark): - # See the specification for details. - ch = self.peek() - if not ('0' <= ch <= '9'): - raise ScannerError("while scanning a directive", start_mark, - "expected a digit, but found %r" % ch, self.get_mark()) - length = 0 - while '0' <= self.peek(length) <= '9': - length += 1 - value = int(self.prefix(length)) - self.forward(length) - return value - - def scan_tag_directive_value(self, start_mark): - # See the specification for details. - while self.peek() == ' ': - self.forward() - handle = self.scan_tag_directive_handle(start_mark) - while self.peek() == ' ': - self.forward() - prefix = self.scan_tag_directive_prefix(start_mark) - return (handle, prefix) - - def scan_tag_directive_handle(self, start_mark): - # See the specification for details. - value = self.scan_tag_handle('directive', start_mark) - ch = self.peek() - if ch != ' ': - raise ScannerError("while scanning a directive", start_mark, - "expected ' ', but found %r" % ch, self.get_mark()) - return value - - def scan_tag_directive_prefix(self, start_mark): - # See the specification for details. - value = self.scan_tag_uri('directive', start_mark) - ch = self.peek() - if ch not in '\0 \r\n\x85\u2028\u2029': - raise ScannerError("while scanning a directive", start_mark, - "expected ' ', but found %r" % ch, self.get_mark()) - return value - - def scan_directive_ignored_line(self, start_mark): - # See the specification for details. - while self.peek() == ' ': - self.forward() - if self.peek() == '#': - while self.peek() not in '\0\r\n\x85\u2028\u2029': - self.forward() - ch = self.peek() - if ch not in '\0\r\n\x85\u2028\u2029': - raise ScannerError("while scanning a directive", start_mark, - "expected a comment or a line break, but found %r" - % ch, self.get_mark()) - self.scan_line_break() - - def scan_anchor(self, TokenClass): - # The specification does not restrict characters for anchors and - # aliases. This may lead to problems, for instance, the document: - # [ *alias, value ] - # can be interpreted in two ways, as - # [ "value" ] - # and - # [ *alias , "value" ] - # Therefore we restrict aliases to numbers and ASCII letters. - start_mark = self.get_mark() - indicator = self.peek() - if indicator == '*': - name = 'alias' - else: - name = 'anchor' - self.forward() - length = 0 - ch = self.peek(length) - while '0' <= ch <= '9' or 'A' <= ch <= 'Z' or 'a' <= ch <= 'z' \ - or ch in '-_': - length += 1 - ch = self.peek(length) - if not length: - raise ScannerError("while scanning an %s" % name, start_mark, - "expected alphabetic or numeric character, but found %r" - % ch, self.get_mark()) - value = self.prefix(length) - self.forward(length) - ch = self.peek() - if ch not in '\0 \t\r\n\x85\u2028\u2029?:,]}%@`': - raise ScannerError("while scanning an %s" % name, start_mark, - "expected alphabetic or numeric character, but found %r" - % ch, self.get_mark()) - end_mark = self.get_mark() - return TokenClass(value, start_mark, end_mark) - - def scan_tag(self): - # See the specification for details. - start_mark = self.get_mark() - ch = self.peek(1) - if ch == '<': - handle = None - self.forward(2) - suffix = self.scan_tag_uri('tag', start_mark) - if self.peek() != '>': - raise ScannerError("while parsing a tag", start_mark, - "expected '>', but found %r" % self.peek(), - self.get_mark()) - self.forward() - elif ch in '\0 \t\r\n\x85\u2028\u2029': - handle = None - suffix = '!' - self.forward() - else: - length = 1 - use_handle = False - while ch not in '\0 \r\n\x85\u2028\u2029': - if ch == '!': - use_handle = True - break - length += 1 - ch = self.peek(length) - handle = '!' - if use_handle: - handle = self.scan_tag_handle('tag', start_mark) - else: - handle = '!' - self.forward() - suffix = self.scan_tag_uri('tag', start_mark) - ch = self.peek() - if ch not in '\0 \r\n\x85\u2028\u2029': - raise ScannerError("while scanning a tag", start_mark, - "expected ' ', but found %r" % ch, self.get_mark()) - value = (handle, suffix) - end_mark = self.get_mark() - return TagToken(value, start_mark, end_mark) - - def scan_block_scalar(self, style): - # See the specification for details. - - if style == '>': - folded = True - else: - folded = False - - chunks = [] - start_mark = self.get_mark() - - # Scan the header. - self.forward() - chomping, increment = self.scan_block_scalar_indicators(start_mark) - self.scan_block_scalar_ignored_line(start_mark) - - # Determine the indentation level and go to the first non-empty line. - min_indent = self.indent+1 - if min_indent < 1: - min_indent = 1 - if increment is None: - breaks, max_indent, end_mark = self.scan_block_scalar_indentation() - indent = max(min_indent, max_indent) - else: - indent = min_indent+increment-1 - breaks, end_mark = self.scan_block_scalar_breaks(indent) - line_break = '' - - # Scan the inner part of the block scalar. - while self.column == indent and self.peek() != '\0': - chunks.extend(breaks) - leading_non_space = self.peek() not in ' \t' - length = 0 - while self.peek(length) not in '\0\r\n\x85\u2028\u2029': - length += 1 - chunks.append(self.prefix(length)) - self.forward(length) - line_break = self.scan_line_break() - breaks, end_mark = self.scan_block_scalar_breaks(indent) - if self.column == indent and self.peek() != '\0': - - # Unfortunately, folding rules are ambiguous. - # - # This is the folding according to the specification: - - if folded and line_break == '\n' \ - and leading_non_space and self.peek() not in ' \t': - if not breaks: - chunks.append(' ') - else: - chunks.append(line_break) - - # This is Clark Evans's interpretation (also in the spec - # examples): - # - #if folded and line_break == '\n': - # if not breaks: - # if self.peek() not in ' \t': - # chunks.append(' ') - # else: - # chunks.append(line_break) - #else: - # chunks.append(line_break) - else: - break - - # Chomp the tail. - if chomping is not False: - chunks.append(line_break) - if chomping is True: - chunks.extend(breaks) - - # We are done. - return ScalarToken(''.join(chunks), False, start_mark, end_mark, - style) - - def scan_block_scalar_indicators(self, start_mark): - # See the specification for details. - chomping = None - increment = None - ch = self.peek() - if ch in '+-': - if ch == '+': - chomping = True - else: - chomping = False - self.forward() - ch = self.peek() - if ch in '0123456789': - increment = int(ch) - if increment == 0: - raise ScannerError("while scanning a block scalar", start_mark, - "expected indentation indicator in the range 1-9, but found 0", - self.get_mark()) - self.forward() - elif ch in '0123456789': - increment = int(ch) - if increment == 0: - raise ScannerError("while scanning a block scalar", start_mark, - "expected indentation indicator in the range 1-9, but found 0", - self.get_mark()) - self.forward() - ch = self.peek() - if ch in '+-': - if ch == '+': - chomping = True - else: - chomping = False - self.forward() - ch = self.peek() - if ch not in '\0 \r\n\x85\u2028\u2029': - raise ScannerError("while scanning a block scalar", start_mark, - "expected chomping or indentation indicators, but found %r" - % ch, self.get_mark()) - return chomping, increment - - def scan_block_scalar_ignored_line(self, start_mark): - # See the specification for details. - while self.peek() == ' ': - self.forward() - if self.peek() == '#': - while self.peek() not in '\0\r\n\x85\u2028\u2029': - self.forward() - ch = self.peek() - if ch not in '\0\r\n\x85\u2028\u2029': - raise ScannerError("while scanning a block scalar", start_mark, - "expected a comment or a line break, but found %r" % ch, - self.get_mark()) - self.scan_line_break() - - def scan_block_scalar_indentation(self): - # See the specification for details. - chunks = [] - max_indent = 0 - end_mark = self.get_mark() - while self.peek() in ' \r\n\x85\u2028\u2029': - if self.peek() != ' ': - chunks.append(self.scan_line_break()) - end_mark = self.get_mark() - else: - self.forward() - if self.column > max_indent: - max_indent = self.column - return chunks, max_indent, end_mark - - def scan_block_scalar_breaks(self, indent): - # See the specification for details. - chunks = [] - end_mark = self.get_mark() - while self.column < indent and self.peek() == ' ': - self.forward() - while self.peek() in '\r\n\x85\u2028\u2029': - chunks.append(self.scan_line_break()) - end_mark = self.get_mark() - while self.column < indent and self.peek() == ' ': - self.forward() - return chunks, end_mark - - def scan_flow_scalar(self, style): - # See the specification for details. - # Note that we loose indentation rules for quoted scalars. Quoted - # scalars don't need to adhere indentation because " and ' clearly - # mark the beginning and the end of them. Therefore we are less - # restrictive then the specification requires. We only need to check - # that document separators are not included in scalars. - if style == '"': - double = True - else: - double = False - chunks = [] - start_mark = self.get_mark() - quote = self.peek() - self.forward() - chunks.extend(self.scan_flow_scalar_non_spaces(double, start_mark)) - while self.peek() != quote: - chunks.extend(self.scan_flow_scalar_spaces(double, start_mark)) - chunks.extend(self.scan_flow_scalar_non_spaces(double, start_mark)) - self.forward() - end_mark = self.get_mark() - return ScalarToken(''.join(chunks), False, start_mark, end_mark, - style) - - ESCAPE_REPLACEMENTS = { - '0': '\0', - 'a': '\x07', - 'b': '\x08', - 't': '\x09', - '\t': '\x09', - 'n': '\x0A', - 'v': '\x0B', - 'f': '\x0C', - 'r': '\x0D', - 'e': '\x1B', - ' ': '\x20', - '\"': '\"', - '\\': '\\', - '/': '/', - 'N': '\x85', - '_': '\xA0', - 'L': '\u2028', - 'P': '\u2029', - } - - ESCAPE_CODES = { - 'x': 2, - 'u': 4, - 'U': 8, - } - - def scan_flow_scalar_non_spaces(self, double, start_mark): - # See the specification for details. - chunks = [] - while True: - length = 0 - while self.peek(length) not in '\'\"\\\0 \t\r\n\x85\u2028\u2029': - length += 1 - if length: - chunks.append(self.prefix(length)) - self.forward(length) - ch = self.peek() - if not double and ch == '\'' and self.peek(1) == '\'': - chunks.append('\'') - self.forward(2) - elif (double and ch == '\'') or (not double and ch in '\"\\'): - chunks.append(ch) - self.forward() - elif double and ch == '\\': - self.forward() - ch = self.peek() - if ch in self.ESCAPE_REPLACEMENTS: - chunks.append(self.ESCAPE_REPLACEMENTS[ch]) - self.forward() - elif ch in self.ESCAPE_CODES: - length = self.ESCAPE_CODES[ch] - self.forward() - for k in range(length): - if self.peek(k) not in '0123456789ABCDEFabcdef': - raise ScannerError("while scanning a double-quoted scalar", start_mark, - "expected escape sequence of %d hexdecimal numbers, but found %r" % - (length, self.peek(k)), self.get_mark()) - code = int(self.prefix(length), 16) - chunks.append(chr(code)) - self.forward(length) - elif ch in '\r\n\x85\u2028\u2029': - self.scan_line_break() - chunks.extend(self.scan_flow_scalar_breaks(double, start_mark)) - else: - raise ScannerError("while scanning a double-quoted scalar", start_mark, - "found unknown escape character %r" % ch, self.get_mark()) - else: - return chunks - - def scan_flow_scalar_spaces(self, double, start_mark): - # See the specification for details. - chunks = [] - length = 0 - while self.peek(length) in ' \t': - length += 1 - whitespaces = self.prefix(length) - self.forward(length) - ch = self.peek() - if ch == '\0': - raise ScannerError("while scanning a quoted scalar", start_mark, - "found unexpected end of stream", self.get_mark()) - elif ch in '\r\n\x85\u2028\u2029': - line_break = self.scan_line_break() - breaks = self.scan_flow_scalar_breaks(double, start_mark) - if line_break != '\n': - chunks.append(line_break) - elif not breaks: - chunks.append(' ') - chunks.extend(breaks) - else: - chunks.append(whitespaces) - return chunks - - def scan_flow_scalar_breaks(self, double, start_mark): - # See the specification for details. - chunks = [] - while True: - # Instead of checking indentation, we check for document - # separators. - prefix = self.prefix(3) - if (prefix == '---' or prefix == '...') \ - and self.peek(3) in '\0 \t\r\n\x85\u2028\u2029': - raise ScannerError("while scanning a quoted scalar", start_mark, - "found unexpected document separator", self.get_mark()) - while self.peek() in ' \t': - self.forward() - if self.peek() in '\r\n\x85\u2028\u2029': - chunks.append(self.scan_line_break()) - else: - return chunks - - def scan_plain(self): - # See the specification for details. - # We add an additional restriction for the flow context: - # plain scalars in the flow context cannot contain ',' or '?'. - # We also keep track of the `allow_simple_key` flag here. - # Indentation rules are loosed for the flow context. - chunks = [] - start_mark = self.get_mark() - end_mark = start_mark - indent = self.indent+1 - # We allow zero indentation for scalars, but then we need to check for - # document separators at the beginning of the line. - #if indent == 0: - # indent = 1 - spaces = [] - while True: - length = 0 - if self.peek() == '#': - break - while True: - ch = self.peek(length) - if ch in '\0 \t\r\n\x85\u2028\u2029' \ - or (ch == ':' and - self.peek(length+1) in '\0 \t\r\n\x85\u2028\u2029' - + (u',[]{}' if self.flow_level else u''))\ - or (self.flow_level and ch in ',?[]{}'): - break - length += 1 - if length == 0: - break - self.allow_simple_key = False - chunks.extend(spaces) - chunks.append(self.prefix(length)) - self.forward(length) - end_mark = self.get_mark() - spaces = self.scan_plain_spaces(indent, start_mark) - if not spaces or self.peek() == '#' \ - or (not self.flow_level and self.column < indent): - break - return ScalarToken(''.join(chunks), True, start_mark, end_mark) - - def scan_plain_spaces(self, indent, start_mark): - # See the specification for details. - # The specification is really confusing about tabs in plain scalars. - # We just forbid them completely. Do not use tabs in YAML! - chunks = [] - length = 0 - while self.peek(length) in ' ': - length += 1 - whitespaces = self.prefix(length) - self.forward(length) - ch = self.peek() - if ch in '\r\n\x85\u2028\u2029': - line_break = self.scan_line_break() - self.allow_simple_key = True - prefix = self.prefix(3) - if (prefix == '---' or prefix == '...') \ - and self.peek(3) in '\0 \t\r\n\x85\u2028\u2029': - return - breaks = [] - while self.peek() in ' \r\n\x85\u2028\u2029': - if self.peek() == ' ': - self.forward() - else: - breaks.append(self.scan_line_break()) - prefix = self.prefix(3) - if (prefix == '---' or prefix == '...') \ - and self.peek(3) in '\0 \t\r\n\x85\u2028\u2029': - return - if line_break != '\n': - chunks.append(line_break) - elif not breaks: - chunks.append(' ') - chunks.extend(breaks) - elif whitespaces: - chunks.append(whitespaces) - return chunks - - def scan_tag_handle(self, name, start_mark): - # See the specification for details. - # For some strange reasons, the specification does not allow '_' in - # tag handles. I have allowed it anyway. - ch = self.peek() - if ch != '!': - raise ScannerError("while scanning a %s" % name, start_mark, - "expected '!', but found %r" % ch, self.get_mark()) - length = 1 - ch = self.peek(length) - if ch != ' ': - while '0' <= ch <= '9' or 'A' <= ch <= 'Z' or 'a' <= ch <= 'z' \ - or ch in '-_': - length += 1 - ch = self.peek(length) - if ch != '!': - self.forward(length) - raise ScannerError("while scanning a %s" % name, start_mark, - "expected '!', but found %r" % ch, self.get_mark()) - length += 1 - value = self.prefix(length) - self.forward(length) - return value - - def scan_tag_uri(self, name, start_mark): - # See the specification for details. - # Note: we do not check if URI is well-formed. - chunks = [] - length = 0 - ch = self.peek(length) - while '0' <= ch <= '9' or 'A' <= ch <= 'Z' or 'a' <= ch <= 'z' \ - or ch in '-;/?:@&=+$,_.!~*\'()[]%': - if ch == '%': - chunks.append(self.prefix(length)) - self.forward(length) - length = 0 - chunks.append(self.scan_uri_escapes(name, start_mark)) - else: - length += 1 - ch = self.peek(length) - if length: - chunks.append(self.prefix(length)) - self.forward(length) - length = 0 - if not chunks: - raise ScannerError("while parsing a %s" % name, start_mark, - "expected URI, but found %r" % ch, self.get_mark()) - return ''.join(chunks) - - def scan_uri_escapes(self, name, start_mark): - # See the specification for details. - codes = [] - mark = self.get_mark() - while self.peek() == '%': - self.forward() - for k in range(2): - if self.peek(k) not in '0123456789ABCDEFabcdef': - raise ScannerError("while scanning a %s" % name, start_mark, - "expected URI escape sequence of 2 hexdecimal numbers, but found %r" - % self.peek(k), self.get_mark()) - codes.append(int(self.prefix(2), 16)) - self.forward(2) - try: - value = bytes(codes).decode('utf-8') - except UnicodeDecodeError as exc: - raise ScannerError("while scanning a %s" % name, start_mark, str(exc), mark) - return value - - def scan_line_break(self): - # Transforms: - # '\r\n' : '\n' - # '\r' : '\n' - # '\n' : '\n' - # '\x85' : '\n' - # '\u2028' : '\u2028' - # '\u2029 : '\u2029' - # default : '' - ch = self.peek() - if ch in '\r\n\x85': - if self.prefix(2) == '\r\n': - self.forward(2) - else: - self.forward() - return '\n' - elif ch in '\u2028\u2029': - self.forward() - return ch - return '' diff --git a/src/yaml/serializer.py b/src/yaml/serializer.py deleted file mode 100644 index fe911e6..0000000 --- a/src/yaml/serializer.py +++ /dev/null @@ -1,111 +0,0 @@ - -__all__ = ['Serializer', 'SerializerError'] - -from .error import YAMLError -from .events import * -from .nodes import * - -class SerializerError(YAMLError): - pass - -class Serializer: - - ANCHOR_TEMPLATE = 'id%03d' - - def __init__(self, encoding=None, - explicit_start=None, explicit_end=None, version=None, tags=None): - self.use_encoding = encoding - self.use_explicit_start = explicit_start - self.use_explicit_end = explicit_end - self.use_version = version - self.use_tags = tags - self.serialized_nodes = {} - self.anchors = {} - self.last_anchor_id = 0 - self.closed = None - - def open(self): - if self.closed is None: - self.emit(StreamStartEvent(encoding=self.use_encoding)) - self.closed = False - elif self.closed: - raise SerializerError("serializer is closed") - else: - raise SerializerError("serializer is already opened") - - def close(self): - if self.closed is None: - raise SerializerError("serializer is not opened") - elif not self.closed: - self.emit(StreamEndEvent()) - self.closed = True - - #def __del__(self): - # self.close() - - def serialize(self, node): - if self.closed is None: - raise SerializerError("serializer is not opened") - elif self.closed: - raise SerializerError("serializer is closed") - self.emit(DocumentStartEvent(explicit=self.use_explicit_start, - version=self.use_version, tags=self.use_tags)) - self.anchor_node(node) - self.serialize_node(node, None, None) - self.emit(DocumentEndEvent(explicit=self.use_explicit_end)) - self.serialized_nodes = {} - self.anchors = {} - self.last_anchor_id = 0 - - def anchor_node(self, node): - if node in self.anchors: - if self.anchors[node] is None: - self.anchors[node] = self.generate_anchor(node) - else: - self.anchors[node] = None - if isinstance(node, SequenceNode): - for item in node.value: - self.anchor_node(item) - elif isinstance(node, MappingNode): - for key, value in node.value: - self.anchor_node(key) - self.anchor_node(value) - - def generate_anchor(self, node): - self.last_anchor_id += 1 - return self.ANCHOR_TEMPLATE % self.last_anchor_id - - def serialize_node(self, node, parent, index): - alias = self.anchors[node] - if node in self.serialized_nodes: - self.emit(AliasEvent(alias)) - else: - self.serialized_nodes[node] = True - self.descend_resolver(parent, index) - if isinstance(node, ScalarNode): - detected_tag = self.resolve(ScalarNode, node.value, (True, False)) - default_tag = self.resolve(ScalarNode, node.value, (False, True)) - implicit = (node.tag == detected_tag), (node.tag == default_tag) - self.emit(ScalarEvent(alias, node.tag, implicit, node.value, - style=node.style)) - elif isinstance(node, SequenceNode): - implicit = (node.tag - == self.resolve(SequenceNode, node.value, True)) - self.emit(SequenceStartEvent(alias, node.tag, implicit, - flow_style=node.flow_style)) - index = 0 - for item in node.value: - self.serialize_node(item, node, index) - index += 1 - self.emit(SequenceEndEvent()) - elif isinstance(node, MappingNode): - implicit = (node.tag - == self.resolve(MappingNode, node.value, True)) - self.emit(MappingStartEvent(alias, node.tag, implicit, - flow_style=node.flow_style)) - for key, value in node.value: - self.serialize_node(key, node, None) - self.serialize_node(value, node, key) - self.emit(MappingEndEvent()) - self.ascend_resolver() - diff --git a/src/yaml/tokens.py b/src/yaml/tokens.py deleted file mode 100644 index 4d0b48a..0000000 --- a/src/yaml/tokens.py +++ /dev/null @@ -1,104 +0,0 @@ - -class Token(object): - def __init__(self, start_mark, end_mark): - self.start_mark = start_mark - self.end_mark = end_mark - def __repr__(self): - attributes = [key for key in self.__dict__ - if not key.endswith('_mark')] - attributes.sort() - arguments = ', '.join(['%s=%r' % (key, getattr(self, key)) - for key in attributes]) - return '%s(%s)' % (self.__class__.__name__, arguments) - -#class BOMToken(Token): -# id = '' - -class DirectiveToken(Token): - id = '' - def __init__(self, name, value, start_mark, end_mark): - self.name = name - self.value = value - self.start_mark = start_mark - self.end_mark = end_mark - -class DocumentStartToken(Token): - id = '' - -class DocumentEndToken(Token): - id = '' - -class StreamStartToken(Token): - id = '' - def __init__(self, start_mark=None, end_mark=None, - encoding=None): - self.start_mark = start_mark - self.end_mark = end_mark - self.encoding = encoding - -class StreamEndToken(Token): - id = '' - -class BlockSequenceStartToken(Token): - id = '' - -class BlockMappingStartToken(Token): - id = '' - -class BlockEndToken(Token): - id = '' - -class FlowSequenceStartToken(Token): - id = '[' - -class FlowMappingStartToken(Token): - id = '{' - -class FlowSequenceEndToken(Token): - id = ']' - -class FlowMappingEndToken(Token): - id = '}' - -class KeyToken(Token): - id = '?' - -class ValueToken(Token): - id = ':' - -class BlockEntryToken(Token): - id = '-' - -class FlowEntryToken(Token): - id = ',' - -class AliasToken(Token): - id = '' - def __init__(self, value, start_mark, end_mark): - self.value = value - self.start_mark = start_mark - self.end_mark = end_mark - -class AnchorToken(Token): - id = '' - def __init__(self, value, start_mark, end_mark): - self.value = value - self.start_mark = start_mark - self.end_mark = end_mark - -class TagToken(Token): - id = '' - def __init__(self, value, start_mark, end_mark): - self.value = value - self.start_mark = start_mark - self.end_mark = end_mark - -class ScalarToken(Token): - id = '' - def __init__(self, value, plain, start_mark, end_mark, style=None): - self.value = value - self.plain = plain - self.start_mark = start_mark - self.end_mark = end_mark - self.style = style - From 9af391ff9de63f30eb9709ac2d177390dc54ed2d Mon Sep 17 00:00:00 2001 From: Andreas Nordin Date: Wed, 24 Jun 2020 20:08:53 +0200 Subject: [PATCH 11/35] clean up imports, cmdline handling Order imports properly. Fix path when running script directly from repo rather than as an installed package. Refactor command line handling. --- src/wireviz/wireviz.py | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/src/wireviz/wireviz.py b/src/wireviz/wireviz.py index ceb350a..70fb85f 100755 --- a/src/wireviz/wireviz.py +++ b/src/wireviz/wireviz.py @@ -1,12 +1,16 @@ #!/usr/bin/env python3 import argparse -import os -from dataclasses import dataclass, field -from typing import Any, List from collections import Counter -import yaml +from dataclasses import dataclass, field from graphviz import Graph +import os +from typing import Any, List +import yaml + +if __name__== '__main__': + import sys + sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) from wireviz import wv_colors from wireviz.wv_helper import nested, int2tuple, awg_equiv, flatten2d, tuplelist2tsv @@ -622,14 +626,26 @@ def parse(file_in, file_out=None, gen_bom=False): h.output(filename=file_out, format=('png','svg'), gen_bom=gen_bom, view=False) -def main(): - ap = argparse.ArgumentParser() - ap.add_argument('file_input', nargs='?', default='_test/test.yml') - ap.add_argument('file_output', nargs='?', default=None) - ap.add_argument('--bom', action='store_const', default=True, const=True) - args = ap.parse_args() +def parse_cmdline(): + parser = argparse.ArgumentParser( + description='Generate cable and wiring harness documentation from YAML descriptions' + ) - parse(args.file_input, file_out=args.file_output, gen_bom=args.bom) + 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) + + args = parser.parse_args() + + return args + +def main(): + + args = parse_cmdline() + + parse(args.input_file, file_out=args.output_file, gen_bom=args.generate_bom) if __name__ == '__main__': main() From 60cd069754d8dab702568ec6bcf9fbdad06c3982 Mon Sep 17 00:00:00 2001 From: Andreas Nordin Date: Wed, 24 Jun 2020 18:52:25 +0200 Subject: [PATCH 12/35] add install instructions to readme --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index df7092a..0ec6f6b 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,16 @@ WireViz is a tool for easily documenting cables, wiring harnesses and connector _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 + +Installation can be done using pip after cloning the repository: + +``` +git clone +cd +pip3 install -e . +``` + ## Examples ### Demo 01 From cdb2cf2b91fd2f3c6edf39e10a48de6751766dc4 Mon Sep 17 00:00:00 2001 From: Andreas Nordin Date: Wed, 24 Jun 2020 19:09:08 +0200 Subject: [PATCH 13/35] update build_examples script --- README.md | 8 ++++++ src/wireviz/batch.py | 50 ----------------------------------- src/wireviz/build_examples.py | 26 +++++++++--------- 3 files changed, 22 insertions(+), 62 deletions(-) delete mode 100644 src/wireviz/batch.py mode change 100644 => 100755 src/wireviz/build_examples.py diff --git a/README.md b/README.md index 0ec6f6b..3f90415 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,14 @@ pip3 install -e . ## Examples +### (re)building the example projects + +If you would like to rebuild all of the included demos, examples and tutorials, use the ```build_examples.py``` script: + +```cd src/wireviz +./build_examples.py +``` + ### Demo 01 [WireViz input file](examples/demo01.yml): diff --git a/src/wireviz/batch.py b/src/wireviz/batch.py deleted file mode 100644 index 6add6a9..0000000 --- a/src/wireviz/batch.py +++ /dev/null @@ -1,50 +0,0 @@ -import wireviz -import os - -demos = 2 # 2 -examples = 9 # 9 -tutorials = 7 # 7 - -if demos: - for i in range(1,demos+1): - fn = '../examples/demo{:02d}.yml'.format(i) - print(fn) - wireviz.parse(fn, gen_bom=True) - -if examples: - with open(os.path.abspath('../examples/readme.md'), 'w') as file: - file.write('# Example gallery\n') - for i in range(1,examples+1): - fn = '../examples/ex{:02d}.yml'.format(i) - print(fn) - wireviz.parse(fn, gen_bom=True) - - file.write('## Example {:02d}\n'.format(i)) - file.write('![](ex{:02d}.png)\n\n'.format(i)) - file.write('[Source](ex{:02d}.yml) - [Bill of Materials](ex{:02d}.bom.tsv)\n\n\n'.format(i,i)) - -if tutorials: - with open(os.path.abspath('../tutorial/readme.md'), 'w') as file: - file.write('# WireViz Tutorial\n') - for i in range(1,tutorials+1): - fn = '../tutorial/tutorial{:02d}.yml'.format(i) - print(fn) - wireviz.parse(fn, gen_bom=True) - - with open(os.path.abspath('../tutorial/tutorial{:02d}.md'.format(i)), 'r') as info: - for line in info: - file.write(line.replace('## ', '## {} - '.format(i))) - file.write('\n[Source](tutorial{:02d}.yml):\n\n'.format(i)) - - with open(os.path.abspath('../tutorial/tutorial{:02d}.yml'.format(i)), 'r') as src: - file.write('```yaml\n') - for line in src: - file.write(line) - file.write('```\n') - file.write('\n') - - file.write('\nOutput:\n\n'.format(i)) - - file.write('![](tutorial{:02d}.png)\n\n'.format(i)) - - file.write('[Bill of Materials](tutorial{:02d}.bom.tsv)\n\n\n'.format(i)) diff --git a/src/wireviz/build_examples.py b/src/wireviz/build_examples.py old mode 100644 new mode 100755 index d989ae1..8d8afbc --- a/src/wireviz/build_examples.py +++ b/src/wireviz/build_examples.py @@ -1,25 +1,27 @@ -import wireviz +#!/usr/bin/python3 + import os +import sys + +sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) + +from wireviz import wireviz demos = 2 # 2 -<<<<<<< HEAD:src/wireviz/batch.py examples = 9 # 9 -======= -examples = 6 # 6 ->>>>>>> 2d428e8... refactor dependencies and installation:src/wireviz/build_examples.py tutorials = 7 # 7 if demos: for i in range(1,demos+1): - fn = '../examples/demo{:02d}.yml'.format(i) + fn = '../../examples/demo{:02d}.yml'.format(i) print(fn) wireviz.parse(fn, gen_bom=True) if examples: - with open(os.path.abspath('../examples/readme.md'), 'w') as file: + with open(os.path.abspath('../../examples/readme.md'), 'w') as file: file.write('# Example gallery\n') for i in range(1,examples+1): - fn = '../examples/ex{:02d}.yml'.format(i) + fn = '../../examples/ex{:02d}.yml'.format(i) print(fn) wireviz.parse(fn, gen_bom=True) @@ -28,19 +30,19 @@ if examples: file.write('[Source](ex{:02d}.yml) - [Bill of Materials](ex{:02d}.bom.tsv)\n\n\n'.format(i,i)) if tutorials: - with open(os.path.abspath('../tutorial/readme.md'), 'w') as file: + with open(os.path.abspath('../../tutorial/readme.md'), 'w') as file: file.write('# WireViz Tutorial\n') for i in range(1,tutorials+1): - fn = '../tutorial/tutorial{:02d}.yml'.format(i) + fn = '../../tutorial/tutorial{:02d}.yml'.format(i) print(fn) wireviz.parse(fn, gen_bom=True) - with open(os.path.abspath('../tutorial/tutorial{:02d}.md'.format(i)), 'r') as info: + with open(os.path.abspath('../../tutorial/tutorial{:02d}.md'.format(i)), 'r') as info: for line in info: file.write(line.replace('## ', '## {} - '.format(i))) file.write('\n[Source](tutorial{:02d}.yml):\n\n'.format(i)) - with open(os.path.abspath('../tutorial/tutorial{:02d}.yml'.format(i)), 'r') as src: + with open(os.path.abspath('../../tutorial/tutorial{:02d}.yml'.format(i)), 'r') as src: file.write('```yaml\n') for line in src: file.write(line) From 668667d4fe4e1cd4ad873910a0cd11b4bafdda38 Mon Sep 17 00:00:00 2001 From: Andreas Nordin Date: Wed, 24 Jun 2020 17:14:25 +0200 Subject: [PATCH 14/35] Fix typo --- TODO | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TODO b/TODO index dc40abd..619e1ec 100644 --- a/TODO +++ b/TODO @@ -35,7 +35,7 @@ ## Other -* Imrpove tutorial texts +* Improve tutorial texts * Create syntax reference / cheat sheet * Set global parameters (show_pins, ...) and allow override on per-item basis * Allow custom GraphViz code before/after WireViz-generated code From a1f511738e7b3e810ff388d062c46bb6a8eae167 Mon Sep 17 00:00:00 2001 From: Andreas Nordin Date: Thu, 25 Jun 2020 11:34:58 +0200 Subject: [PATCH 15/35] fix install notes Explicitly mention the system graphviz dependency and clarify possible need for separate python install on old ubuntus --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3f90415..8b2dc48 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,9 @@ _Note_: WireViz is not designed to represent the complete wiring of a system. It ## Installation -Installation can be done using pip after cloning the repository: +WireWiz requires the ```graphviz``` package as well as it's python bindings. Graphviz itself is installed using your regular package manager, e.g. ```apt-get install graphviz```. The Graphviz python bindings are automatically installed as dependencies by the install script. + +Installation of the WireWiz package and its python dependencies can be done using pip after cloning the repository: ``` git clone @@ -97,7 +99,7 @@ as well as the [example gallery](examples/readme.md) to see more of what WireViz ## Usage ``` -$ python3 wireviz.py ~/path/to/file/mywire.yml +$ wireviz ~/path/to/file/mywire.yml ``` This will output the following files @@ -116,7 +118,7 @@ This is very much a [work in progress](TODO). Source code, API, syntax and funct ## Requirements -Developed and tested using Python 3.7; might not work with older Python versions. +Developed and tested using Python 3.7; might not work with older Python versions. 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 From f14a07fe95c21e85e3de3e5e96f7796378b8e684 Mon Sep 17 00:00:00 2001 From: Andreas Nordin Date: Thu, 25 Jun 2020 13:34:46 +0200 Subject: [PATCH 16/35] feature: add --prepend-file option - Allow prepending a separate YAML file for e.g. including common template definitions. This is accomodated by a new commandline option, --prepend-file, which takes a path to a YAML file. This is prepended to the regular input as-is. - Refactor file loading to accomodate the above. This includes moving relevant parts to main() and instead supplying parse () with a string representation of the YAML data. Also add early file existance checks and bail out if any of the inputs are inaccessible or nonexistant. --- src/wireviz/wireviz.py | 43 +++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) diff --git a/src/wireviz/wireviz.py b/src/wireviz/wireviz.py index 70fb85f..af37544 100755 --- a/src/wireviz/wireviz.py +++ b/src/wireviz/wireviz.py @@ -5,11 +5,11 @@ from collections import Counter from dataclasses import dataclass, field from graphviz import Graph import os +import sys from typing import Any, List import yaml if __name__== '__main__': - import sys sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) from wireviz import wv_colors @@ -448,17 +448,9 @@ class Connection: to_name: Any to_port: Any -def parse(file_in, file_out=None, gen_bom=False): +def parse(yaml_input, file_out=None, generate_bom=False): - file_in = os.path.abspath(file_in) - if not file_out: - file_out = file_in - pre, ext = os.path.splitext(file_out) - file_out = pre # extension will be added by graphviz output function - file_out = os.path.abspath(file_out) - - with open(file_in, 'r') as stream: - input = yaml.safe_load(stream) + input = yaml.safe_load(yaml_input) def expand(input): # input can be: @@ -624,7 +616,7 @@ def parse(file_in, file_out=None, gen_bom=False): else: raise Exception('Wrong number of connection parameters') - h.output(filename=file_out, format=('png','svg'), gen_bom=gen_bom, view=False) + h.output(filename=file_out, format=('png','svg'), gen_bom=generate_bom, view=False) def parse_cmdline(): parser = argparse.ArgumentParser( @@ -637,6 +629,8 @@ def parse_cmdline(): parser.add_argument('--generate-bom', action='store_true', default=True) + parser.add_argument('--prepend-file', action='store', type=str, metavar='YAML_FILE') + args = parser.parse_args() return args @@ -645,7 +639,30 @@ def main(): args = parse_cmdline() - parse(args.input_file, file_out=args.output_file, gen_bom=args.generate_bom) + if not os.path.exists(args.input_file): + print('Error: input file {} inaccessible or does not exist, check path'.format(args.input_file)) + sys.exit(1) + + with open(args.input_file) as fh: + yaml_input = fh.read() + + if args.prepend_file: + if not os.path.exists(args.prepend_file): + print('Error: prepend input file {} inaccessible or does not exist, check path'.format(args.prepend_file)) + sys.exit(1) + with open(args.prepend_file) as fh: + prepend = fh.read() + yaml_input = prepend + yaml_input + + if not args.output_file: + file_out = args.input_file + pre, _ = os.path.splitext(file_out) + file_out = pre # extension will be added by graphviz output function + else: + file_out = args.output_file + file_out = os.path.abspath(file_out) + + parse(yaml_input, file_out=file_out, generate_bom=args.generate_bom) if __name__ == '__main__': main() From 1f06c6017c4c33661fe5429ebaa6222e04c423e7 Mon Sep 17 00:00:00 2001 From: Andreas Nordin Date: Thu, 25 Jun 2020 13:41:00 +0200 Subject: [PATCH 17/35] refactor: rename 'input' -> 'yaml_data' 'input' overloads a python built-in name. Refactor to avoid this. --- src/wireviz/wireviz.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/wireviz/wireviz.py b/src/wireviz/wireviz.py index af37544..fddbdd1 100755 --- a/src/wireviz/wireviz.py +++ b/src/wireviz/wireviz.py @@ -450,17 +450,17 @@ class Connection: def parse(yaml_input, file_out=None, generate_bom=False): - input = yaml.safe_load(yaml_input) + yaml_data = yaml.safe_load(yaml_input) - def expand(input): - # input can be: + def expand(yaml_data): + # yaml_data can be: # - a singleton (normally str or int) # - a list of str or int # if str is of the format '#-#', it is treated as a range (inclusive) and expanded output = [] - if not isinstance(input, list): - input = [input,] - for e in input: + if not isinstance(yaml_data, list): + yaml_data = [yaml_data,] + for e in yaml_data: e = str(e) if '-' in e: # list of pins a, b = tuple(map(int, e.split('-'))) @@ -482,7 +482,7 @@ def parse(yaml_input, file_out=None, generate_bom=False): def check_designators(what, where): for i, x in enumerate(what): - if x not in input[where[i]]: + if x not in yaml_data[where[i]]: return False return True @@ -492,10 +492,10 @@ def parse(yaml_input, file_out=None, generate_bom=False): sections = ['connectors','cables','ferrules','connections'] types = [dict, dict, dict, list] for sec, ty in zip(sections, types): - if sec in input and type(input[sec]) == ty: - if len(input[sec]) > 0: + if sec in yaml_data and type(yaml_data[sec]) == ty: + if len(yaml_data[sec]) > 0: if ty == dict: - for k, o in input[sec].items(): + for k, o in yaml_data[sec].items(): if sec == 'connectors': h.add_connector(name=k, **o) elif sec == 'cables': @@ -506,13 +506,13 @@ def parse(yaml_input, file_out=None, generate_bom=False): pass # section exists but is empty else: # section does not exist, create empty section if ty == dict: - input[sec] = {} + yaml_data[sec] = {} elif ty == list: - input[sec] = [] + yaml_data[sec] = [] # add connections ferrule_counter = 0 - for con in input['connections']: + for con in yaml_data['connections']: if len(con) == 3: # format: connector -- cable -- conector for c in con: @@ -601,7 +601,7 @@ def parse(yaml_input, file_out=None, generate_bom=False): cable_name = from_name cable_pins = from_pins - ferrule_params = input['ferrules'][ferrule_name] + ferrule_params = yaml_data['ferrules'][ferrule_name] for cable_pin in cable_pins: ferrule_counter = ferrule_counter + 1 ferrule_id = '_F{}'.format(ferrule_counter) From 154e28f257ec837e5c13de8a6075adf3f0fd7e6d Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Sun, 28 Jun 2020 11:43:22 +0200 Subject: [PATCH 18/35] Change gen_bom to generate_bom --- src/wireviz/build_examples.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/wireviz/build_examples.py b/src/wireviz/build_examples.py index 8d8afbc..b7be539 100755 --- a/src/wireviz/build_examples.py +++ b/src/wireviz/build_examples.py @@ -15,7 +15,7 @@ if demos: for i in range(1,demos+1): fn = '../../examples/demo{:02d}.yml'.format(i) print(fn) - wireviz.parse(fn, gen_bom=True) + wireviz.parse(fn, generate_bom=True) if examples: with open(os.path.abspath('../../examples/readme.md'), 'w') as file: @@ -23,7 +23,7 @@ if examples: for i in range(1,examples+1): fn = '../../examples/ex{:02d}.yml'.format(i) print(fn) - wireviz.parse(fn, gen_bom=True) + wireviz.parse(fn, generate_bom=True) file.write('## Example {:02d}\n'.format(i)) file.write('![](ex{:02d}.png)\n\n'.format(i)) @@ -35,7 +35,7 @@ if tutorials: for i in range(1,tutorials+1): fn = '../../tutorial/tutorial{:02d}.yml'.format(i) print(fn) - wireviz.parse(fn, gen_bom=True) + wireviz.parse(fn, generate_bom=True) with open(os.path.abspath('../../tutorial/tutorial{:02d}.md'.format(i)), 'r') as info: for line in info: From 5d84bb86eb1e340ed964288a811ad2bd08794fac Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Sun, 28 Jun 2020 11:43:31 +0200 Subject: [PATCH 19/35] Update gitignore --- src/wireviz/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/src/wireviz/.gitignore b/src/wireviz/.gitignore index 3000943..677cf18 100644 --- a/src/wireviz/.gitignore +++ b/src/wireviz/.gitignore @@ -1,2 +1,3 @@ __pycache__/ _test/ +wv-env/ From 7060c38f07c9eba575c4acc436eff191a6b9e192 Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Sun, 28 Jun 2020 12:28:13 +0200 Subject: [PATCH 20/35] Add parse_file() function and use it in build_examples.py --- src/wireviz/build_examples.py | 6 +++--- src/wireviz/wireviz.py | 12 ++++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/wireviz/build_examples.py b/src/wireviz/build_examples.py index b7be539..fc04fce 100755 --- a/src/wireviz/build_examples.py +++ b/src/wireviz/build_examples.py @@ -15,7 +15,7 @@ if demos: for i in range(1,demos+1): fn = '../../examples/demo{:02d}.yml'.format(i) print(fn) - wireviz.parse(fn, generate_bom=True) + wireviz.parse_file(fn, generate_bom=True) if examples: with open(os.path.abspath('../../examples/readme.md'), 'w') as file: @@ -23,7 +23,7 @@ if examples: for i in range(1,examples+1): fn = '../../examples/ex{:02d}.yml'.format(i) print(fn) - wireviz.parse(fn, generate_bom=True) + wireviz.parse_file(fn, generate_bom=True) file.write('## Example {:02d}\n'.format(i)) file.write('![](ex{:02d}.png)\n\n'.format(i)) @@ -35,7 +35,7 @@ if tutorials: for i in range(1,tutorials+1): fn = '../../tutorial/tutorial{:02d}.yml'.format(i) print(fn) - wireviz.parse(fn, generate_bom=True) + wireviz.parse_file(fn, generate_bom=True) with open(os.path.abspath('../../tutorial/tutorial{:02d}.md'.format(i)), 'r') as info: for line in info: diff --git a/src/wireviz/wireviz.py b/src/wireviz/wireviz.py index fddbdd1..85a0361 100755 --- a/src/wireviz/wireviz.py +++ b/src/wireviz/wireviz.py @@ -618,6 +618,18 @@ def parse(yaml_input, file_out=None, generate_bom=False): h.output(filename=file_out, format=('png','svg'), gen_bom=generate_bom, view=False) +def parse_file(yaml_file, file_out=None, generate_bom=False): + with open(yaml_file, 'r') as file: + yaml_input = file.read() + + if not file_out: + fn, fext = os.path.splitext(yaml_file) + file_out = fn + file_out = os.path.abspath(file_out) + + parse(yaml_input, file_out=file_out, generate_bom=generate_bom) + + def parse_cmdline(): parser = argparse.ArgumentParser( description='Generate cable and wiring harness documentation from YAML descriptions' From 69bc20a31e1eb851495ebca1e25fcd86c61b0726 Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Sun, 28 Jun 2020 13:16:38 +0200 Subject: [PATCH 21/35] Remove TODO file, move to-do's to GitHub Projects --- TODO | 49 ------------------------------------------------- 1 file changed, 49 deletions(-) delete mode 100644 TODO diff --git a/TODO b/TODO deleted file mode 100644 index 619e1ec..0000000 --- a/TODO +++ /dev/null @@ -1,49 +0,0 @@ -# To-do: - -## Support for more connector types - -* Inline connectors (IDC) - * Possibly join two logical wires into one physical wire, add up length for BOM creation - * Designators like W1_1, W1_2 or similar to group them? - -## Support for more wire types - -* Coax cables - * Graphical representation -* Twisted pairs - * Logical representation - * Graphical representation -* Ribbon cables - * Folds - * Splits - * Orientation of IDC connectors - -## Support for more links/connections - -* Cable splicing - * as pseudo-connector? -* Heatshrink / sheathing - -## Visualization - -* Parse and render double-colored, striped cables ('RDBU' etc) -* Display picture of connector underneath (including pin 1 location) - -## Export - -* Export to PDF with frame, title block, ... - -## Other - -* Improve tutorial texts -* Create syntax reference / cheat sheet -* Set global parameters (show_pins, ...) and allow override on per-item basis -* Allow custom GraphViz code before/after WireViz-generated code -* Make "unit tests" for different features/situations - * Missing parameters - * Connection formats - * single wire 1 - * multiple wires [1,2,3] - * wire ranges [1-10] - * Loops - * ... From eb65be39dcdf0428c19abcf5a8b0f0ff93855a58 Mon Sep 17 00:00:00 2001 From: Florian Pigorsch Date: Sun, 28 Jun 2020 14:55:09 +0200 Subject: [PATCH 22/35] Fix some typos: budnle, conector, separetely --- src/wireviz/wireviz.py | 2 +- tutorial/readme.md | 6 +++--- tutorial/tutorial05.yml | 2 +- tutorial/tutorial06.yml | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/wireviz/wireviz.py b/src/wireviz/wireviz.py index 85a0361..43b7613 100755 --- a/src/wireviz/wireviz.py +++ b/src/wireviz/wireviz.py @@ -513,7 +513,7 @@ def parse(yaml_input, file_out=None, generate_bom=False): # add connections ferrule_counter = 0 for con in yaml_data['connections']: - if len(con) == 3: # format: connector -- cable -- conector + if len(con) == 3: # format: connector -- cable -- connector for c in con: if len(list(c.keys())) != 1: # check that each entry in con has only one key, which is the designator diff --git a/tutorial/readme.md b/tutorial/readme.md index 7b01e5b..dc7bbcb 100644 --- a/tutorial/readme.md +++ b/tutorial/readme.md @@ -221,7 +221,7 @@ connections: - # attach ferrules - F1 # no need for list of connections; one ferrule per wire is auto-generated and attached - W1: [1-4] # a new ferrule is auto-generated for each wire - - # attach connectors (separetely from ferrules) + - # attach connectors (separately from ferrules) - W1: [1-4] - X1: [1-4] ``` @@ -262,7 +262,7 @@ ferrules: # ferrules cables: W1: - category: bundle # budnle + category: bundle # bundle length: 0.3 gauge: 0.5 mm2 colors: [YE, BK, BK, RD] # custom colors, wirecount is implicit @@ -271,7 +271,7 @@ connections: - # attach ferrules - F_05 - W1: [1,4] # a new ferrule is auto-generated for each wire - - # attach connectors (separetely from ferrules) + - # attach connectors (separately from ferrules) - W1: [1-4] - X1: [1-4] - diff --git a/tutorial/tutorial05.yml b/tutorial/tutorial05.yml index 148879b..e238f30 100644 --- a/tutorial/tutorial05.yml +++ b/tutorial/tutorial05.yml @@ -21,6 +21,6 @@ connections: - # attach ferrules - F1 # no need for list of connections; one ferrule per wire is auto-generated and attached - W1: [1-4] # a new ferrule is auto-generated for each wire - - # attach connectors (separetely from ferrules) + - # attach connectors (separately from ferrules) - W1: [1-4] - X1: [1-4] diff --git a/tutorial/tutorial06.yml b/tutorial/tutorial06.yml index 2f2ab64..f69499c 100644 --- a/tutorial/tutorial06.yml +++ b/tutorial/tutorial06.yml @@ -17,7 +17,7 @@ ferrules: # ferrules cables: W1: - category: bundle # budnle + category: bundle # bundle length: 0.3 gauge: 0.5 mm2 colors: [YE, BK, BK, RD] # custom colors, wirecount is implicit @@ -26,7 +26,7 @@ connections: - # attach ferrules - F_05 - W1: [1,4] # a new ferrule is auto-generated for each wire - - # attach connectors (separetely from ferrules) + - # attach connectors (separately from ferrules) - W1: [1-4] - X1: [1-4] - From 6cf7178a9f0bea304d637f5aef10dde4d281c0c4 Mon Sep 17 00:00:00 2001 From: Florian Pigorsch Date: Sun, 28 Jun 2020 14:59:29 +0200 Subject: [PATCH 23/35] [ci] Setup Github actions to run 'build_examples.py' as a test on each pull/pull request. (#34) Co-authored-by: Florian Pigorsch --- .github/workflows/main.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 .github/workflows/main.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..ec26b95 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,25 @@ +name: Create Examples + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-latest + strategy: + max-parallel: 4 + matrix: + python-version: [3.7, 3.8] + steps: + - uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Setup Graphviz + uses: ts-graphviz/setup-graphviz@v1 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install . + - name: Create Examples + run: PYTHONPATH=$(pwd)/src:$PYTHONPATH cd src/wireviz/ && python build_examples.py \ No newline at end of file From 0a42b350c8de8d41b17c7804ddcf1eec500812e9 Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Sun, 28 Jun 2020 15:22:59 +0200 Subject: [PATCH 24/35] Update readme --- README.md | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 8b2dc48..3b90b58 100644 --- a/README.md +++ b/README.md @@ -26,9 +26,9 @@ _Note_: WireViz is not designed to represent the complete wiring of a system. It ## Installation -WireWiz requires the ```graphviz``` package as well as it's python bindings. Graphviz itself is installed using your regular package manager, e.g. ```apt-get install graphviz```. The Graphviz python bindings are automatically installed as dependencies by the install script. +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: +Installation of the WireWiz package and its Python dependencies can be done using pip after cloning the repository: ``` git clone @@ -38,14 +38,6 @@ pip3 install -e . ## Examples -### (re)building the example projects - -If you would like to rebuild all of the included demos, examples and tutorials, use the ```build_examples.py``` script: - -```cd src/wireviz -./build_examples.py -``` - ### Demo 01 [WireViz input file](examples/demo01.yml): @@ -96,6 +88,14 @@ Output file: 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. +### (Re-)Building the example projects + +If you would like to rebuild all of the included demos, examples and tutorials, use the ```build_examples.py``` script: + +```cd src/wireviz +./build_examples.py +``` + ## Usage ``` @@ -114,11 +114,13 @@ mywire.html HTML page with wiring diagram and BOM embedded ## Status -This is very much a [work in progress](TODO). Source code, API, syntax and functionality may change wildly at any time. +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 -Developed and tested using Python 3.7; might not work with older Python versions. 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. +Developed and tested using Python 3.7; might not work with older Python versions. + +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 From a3728f52ce5f3d6be6bcf82c0204d362d4c6376a Mon Sep 17 00:00:00 2001 From: Tyler Ward Date: Sun, 28 Jun 2020 21:58:24 +0100 Subject: [PATCH 25/35] Fix for Designators apearing across all colours of wires of a guage. (#37) The wirelist for the bom now has individual designators added. this also alows for the removal of designator list merging later. --- src/wireviz/wireviz.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/wireviz/wireviz.py b/src/wireviz/wireviz.py index 43b7613..83dba1e 100755 --- a/src/wireviz/wireviz.py +++ b/src/wireviz/wireviz.py @@ -287,15 +287,13 @@ class Harness: for bundle in items.values(): # add each wire from each bundle to the wirelist for color in bundle.colors: - wirelist.append({'gauge': shared.gauge, 'gauge_unit': shared.gauge_unit, 'length': shared.length, 'color': color, 'designators': list(items.keys())}) + wirelist.append({'gauge': shared.gauge, 'gauge_unit': shared.gauge_unit, 'length': shared.length, 'color': color, 'designator': bundle.name}) # join similar wires from all the bundles to a single BOM item types = Counter([(v['gauge'], v['gauge_unit'], v['color']) for v in wirelist]) for type in types: items = [v for v in wirelist if (v['gauge'], v['gauge_unit'], v['color']) == type] shared = items[0] - designators = [i['designators'] for i in items] - # flatten nested list - designators = [item for sublist in designators for item in sublist] # https://stackoverflow.com/a/952952 + designators = [i['designator'] for i in items] # remove duplicates designators = list(dict.fromkeys(designators)) designators.sort() From 82b173f2cebe32b23c8df14bec9e0c2c299ee48c Mon Sep 17 00:00:00 2001 From: Gabe R Date: Mon, 29 Jun 2020 04:39:34 -0500 Subject: [PATCH 26/35] Refactor and clean up code (#39) * Format all files using autopep8 to add basic PEP8 conformity. * Add Exception types to bare excepts to prevent catching `ctrl+c` * Remove some unnecessary assignment to dummy variables before returning * Add `Optional` to type hints that can be `NoneType` * Change a number of single-letter variables to more descriptive names * Replace string.format() use with Python's f-strings, as they tends to be cleaner, and provide a performance boost. * One multiline string was left as string.format() as I do not believe f-strings support multiline * Some of the string.format() instances had unused/ignored arguments. I left them out of the f-strings, but I marked those cases with a comments that begins `# FIXME:` * Rename variables that were shadowding python standard functions (specifically `format->fmt`, `input->inp`, `type->maintype`) * Some instances of `type` were not changed, as it breaks the yaml parsing. Needs to be looked into. * Move classes in `wireviz.py` to two new files `DataClasses.py` and `Harness.py`. Co-authored-by: Daniel Rojas --- src/wireviz/DataClasses.py | 136 +++++++++ src/wireviz/Harness.py | 332 +++++++++++++++++++++ src/wireviz/wireviz.py | 583 +++++-------------------------------- src/wireviz/wv_colors.py | 105 +++---- src/wireviz/wv_helper.py | 71 ++--- 5 files changed, 635 insertions(+), 592 deletions(-) create mode 100644 src/wireviz/DataClasses.py create mode 100644 src/wireviz/Harness.py diff --git a/src/wireviz/DataClasses.py b/src/wireviz/DataClasses.py new file mode 100644 index 0000000..c7dc007 --- /dev/null +++ b/src/wireviz/DataClasses.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +from typing import Optional, List, Any +from dataclasses import dataclass, field +from wireviz.wv_helper import int2tuple +from wireviz import wv_colors + + +@dataclass +class Connector: + name: str + category: Optional[str] = None + type: Optional[str] = None + subtype: Optional[str] = None + pincount: Optional[int] = None + notes: Optional[str] = None + pinout: List[Any] = field(default_factory=list) + pinnumbers: List[Any] = field(default_factory=list) + color: Optional[str] = None + show_name: bool = True + show_pincount: bool = True + hide_disconnected_pins: bool = False + + def __post_init__(self): + self.ports_left = False + self.ports_right = False + self.loops = [] + self.visible_pins = {} + + if self.pincount is None: + if self.pinout: + self.pincount = len(self.pinout) + elif self.pinnumbers: + self.pincount = len(self.pinnumbers) + elif self.category == 'ferrule': + self.pincount = 1 + else: + raise Exception('You need to specify at least one, pincount, pinout or pinnumbers') + + if self.pinout and self.pinnumbers: + if len(self.pinout) != len(self.pinnumbers): + raise Exception('Given pinout and pinnumbers size mismatch') + + # create default lists for pinnumbers (sequential) and pinouts (blank) if not specified + if not self.pinnumbers: + self.pinnumbers = list(range(1, self.pincount + 1)) + if not self.pinout: + self.pinout = [''] * self.pincount + + def loop(self, from_pin, to_pin): + self.loops.append((from_pin, to_pin)) + if self.hide_disconnected_pins: + self.visible_pins[from_pin] = True + self.visible_pins[to_pin] = True + + def activate_pin(self, pin): + self.visible_pins[pin] = True + + +@dataclass +class Cable: + name: str + category: Optional[str] = None + type: Optional[str] = None + gauge: Optional[float] = None + gauge_unit: Optional[str] = None + show_equiv: bool = False + length: float = 0 + wirecount: Optional[int] = None + shield: bool = False + notes: Optional[str] = None + colors: List[Any] = field(default_factory=list) + color_code: Optional[str] = None + show_name: bool = True + show_pinout: bool = False + show_wirecount: bool = True + + def __post_init__(self): + + if isinstance(self.gauge, str): # gauge and unit specified + try: + g, u = self.gauge.split(' ') + except Exception: + raise Exception('Gauge must be a number, or number and unit separated by a space') + self.gauge = g + self.gauge_unit = u.replace('mm2', 'mm\u00B2') + elif self.gauge is not None: # gauge specified, assume mm2 + if self.gauge_unit is None: + self.gauge_unit = 'mm\u00B2' + else: + pass # gauge not specified + + self.connections = [] + + if self.wirecount: # number of wires explicitly defined + if self.colors: # use custom color palette (partly or looped if needed) + pass + elif self.color_code: # use standard color palette (partly or looped if needed) + if self.color_code not in wv_colors.COLOR_CODES: + raise Exception('Unknown color code') + self.colors = wv_colors.COLOR_CODES[self.color_code] + else: # no colors defined, add dummy colors + self.colors = [''] * self.wirecount + + # make color code loop around if more wires than colors + if self.wirecount > len(self.colors): + m = self.wirecount // len(self.colors) + 1 + self.colors = self.colors * int(m) + # cut off excess after looping + self.colors = self.colors[:self.wirecount] + else: # wirecount implicit in length of color list + if not self.colors: + raise Exception('Unknown number of wires. Must specify wirecount or colors (implicit length)') + self.wirecount = len(self.colors) + + # for BOM generation + self.wirecount_and_shield = (self.wirecount, self.shield) + + def connect(self, from_name, from_pin, via_pin, to_name, to_pin): + from_pin = int2tuple(from_pin) + via_pin = int2tuple(via_pin) + to_pin = int2tuple(to_pin) + if len(from_pin) != len(to_pin): + raise Exception('from_pin must have the same number of elements as to_pin') + for i, _ in enumerate(from_pin): + # self.connections.append((from_name, from_pin[i], via_pin[i], to_name, to_pin[i])) + self.connections.append(Connection(from_name, from_pin[i], via_pin[i], to_name, to_pin[i])) + + +@dataclass +class Connection: + from_name: Any + from_port: Any + via_port: Any + to_name: Any + to_port: Any diff --git a/src/wireviz/Harness.py b/src/wireviz/Harness.py new file mode 100644 index 0000000..595d13d --- /dev/null +++ b/src/wireviz/Harness.py @@ -0,0 +1,332 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from wireviz.DataClasses import Connector, Cable +from graphviz import Graph +from wireviz import wv_colors +from wireviz.wv_helper import awg_equiv, tuplelist2tsv, nested, flatten2d +from collections import Counter +from typing import List + + +class Harness: + + def __init__(self): + self.color_mode = 'SHORT' + self.connectors = {} + self.cables = {} + + def add_connector(self, name, *args, **kwargs): + self.connectors[name] = Connector(name, *args, **kwargs) + + def add_cable(self, name, *args, **kwargs): + self.cables[name] = Cable(name, *args, **kwargs) + + def loop(self, connector_name, from_pin, to_pin): + self.connectors[connector_name].loop(from_pin, to_pin) + + def connect(self, from_name, from_pin, via_name, via_pin, to_name, to_pin): + self.cables[via_name].connect(from_name, from_pin, via_pin, to_name, to_pin) + if from_name in self.connectors: + self.connectors[from_name].activate_pin(from_pin) + if to_name in self.connectors: + self.connectors[to_name].activate_pin(to_pin) + + def create_graph(self): + dot = Graph() + dot.body.append('// Graph generated by WireViz') + dot.body.append('// https://github.com/formatc1702/WireViz') + font = 'arial' + dot.attr('graph', rankdir='LR', + ranksep='2', + bgcolor='white', + nodesep='0.33', + fontname=font) + dot.attr('node', shape='record', + style='filled', + fillcolor='white', + fontname=font) + dot.attr('edge', style='bold', + fontname=font) + + # prepare ports on connectors depending on which side they will connect + for _, cable in self.cables.items(): + for connection in cable.connections: + if connection.from_port is not None: # connect to left + self.connectors[connection.from_name].ports_right = True + if connection.to_port is not None: # connect to right + self.connectors[connection.to_name].ports_left = True + + for key, connector in self.connectors.items(): + if connector.category == 'ferrule': + subtype = f', {connector.subtype}' if connector.subtype else '' + color = wv_colors.translate_color(connector.color, self.color_mode) if connector.color else '' + infostring = f'{connector.type}{subtype} {color}' + infostring_l = infostring if connector.ports_right else '' + infostring_r = infostring if connector.ports_left else '' + + # INFO: Leaving this one as a string.format form because f-strings do not work well with triple quotes + colorbar = f'' if connector.color else '' + dot.node(key, shape='none', + style='filled', + margin='0', + orientation='0' if connector.ports_left else '180', + label='''< + + + + {colorbar} + +
{infostring_l} {infostring_r}
+ + + >'''.format(infostring_l=infostring_l, infostring_r=infostring_r, colorbar=colorbar)) + + else: # not a ferrule + attributes = [connector.type, + connector.subtype, + f'{connector.pincount}-pin' if connector.show_pincount else''] + pinouts = [[], [], []] + for pinnumber, pinname in zip(connector.pinnumbers, connector.pinout): + if connector.hide_disconnected_pins and not connector.visible_pins.get(pinnumber, False): + continue + pinouts[1].append(pinname) + if connector.ports_left: + pinouts[0].append(f'{pinnumber}') + if connector.ports_right: + pinouts[2].append(f'{pinnumber}') + label = [connector.name if connector.show_name else '', attributes, pinouts, connector.notes] + dot.node(key, label=nested(label)) + + if len(connector.loops) > 0: + dot.attr('edge', color='#000000:#ffffff:#000000') + if connector.ports_left: + loop_side = 'l' + loop_dir = 'w' + elif connector.ports_right: + loop_side = 'r' + loop_dir = 'e' + else: + raise Exception('No side for loops') + for loop in connector.loops: + + # FIXME: Original string.format style had some unused arguments (port_to for 1st arg, + # port_from for 2nd arg). De we need them back? + + dot.edge(f'{connector.name}:p{loop[0]}{loop_side}:{loop_dir}', + f'{connector.name}:p{loop[1]}{loop_side}:{loop_dir}') + + for _, cable in self.cables.items(): + awg_fmt = f' ({awg_equiv(cable.gauge)} AWG)' if cable.gauge_unit == 'mm\u00B2' and cable.show_equiv else '' + attributes = [f'{len(cable.colors)}x' if cable.show_wirecount else '', + f'{cable.gauge} {cable.gauge_unit}{awg_fmt}' if cable.gauge else '', # TODO: show equiv + '+ S' if cable.shield else '', + f'{cable.length} m' if cable.length > 0 else ''] + attributes = list(filter(None, attributes)) + + html = '' # name+attributes table + + html = f'{html}' # spacer between attributes and wires + + html = f'{html}' # main table + if cable.notes: + html = f'{html}' # notes table + html = f'{html}' # spacer at the end + + html = f'{html}
' # main table + + html = f'{html}' # name+attributes table + if cable.show_name: + html = f'{html}' + html = f'{html}' # attribute row + for attrib in attributes: + html = f'{html}' + html = f'{html}' # attribute row + html = f'{html}
{cable.name}
{attrib}
 
' # conductor table + + for i, connection in enumerate(cable.colors, 1): + p = [] + p.append(f'') + p.append(wv_colors.translate_color(connection, self.color_mode)) + p.append(f'') + html = f'{html}' + for bla in p: + html = f'{html}' + html = f'{html}' + bgcolor = wv_colors.translate_color(connection, 'hex') + bgcolor = bgcolor if bgcolor != '' else '#ffffff' + html = f'{html}' + + if cable.shield: + p = ['', 'Shield', ''] + html = f'{html}' # spacer + html = f'{html}' + for bla in p: + html = html + f'' + html = f'{html}' + + # FIXME, original string.format had a unused bgcolor argument. Do we need it back + html = f'{html}' + + html = f'{html}' # spacer at the end + + html = f'{html}
{bla}
 
{bla}
 
' # conductor table + + html = f'{html}
{cable.notes}
 
' # main table + + # connections + for connection in cable.connections: + if isinstance(connection.via_port, int): # check if it's an actual wire and not a shield + search_color = cable.colors[connection.via_port - 1] + if search_color in wv_colors.color_hex: + dot.attr('edge', color=f'#000000:{wv_colors.color_hex[search_color]}:#000000') + else: # color name not found + dot.attr('edge', color='#000000:#ffffff:#000000') + else: # it's a shield connection + dot.attr('edge', color='#000000') + + if connection.from_port is not None: # connect to left + from_ferrule = self.connectors[connection.from_name].category == 'ferrule' + port = f':p{connection.from_port}r' if not from_ferrule else '' + code_left_1 = f'{connection.from_name}{port}:e' + # FIXME: Uncomment, then add to end of f-string if needed + # via_subport = 'i' if c.show_pinout else '' + code_left_2 = f'{cable.name}:w{connection.via_port}:w' + dot.edge(code_left_1, code_left_2) + from_string = f'{connection.from_name}:{connection.from_port}' if not from_ferrule else '' + html = html.replace(f'', from_string) + if connection.to_port is not None: # connect to right + to_ferrule = self.connectors[connection.to_name].category == 'ferrule' + + # FIXME: Add in if it was supposed to be here. the add to fstring two lines down + # via_subport = 'o' if c.show_pinout else '' + code_right_1 = f'{cable.name}:w{connection.via_port}:e' + to_port = f':p{connection.to_port}l' if not to_ferrule else '' + code_right_2 = f'{connection.to_name}{to_port}:w' + dot.edge(code_right_1, code_right_2) + to_string = f'{connection.to_name}:{connection.to_port}' if not to_ferrule else '' + html = html.replace(f'', to_string) + + dot.node(cable.name, label=f'<{html}>', shape='box', + style='filled,dashed' if cable.category == 'bundle' else '', margin='0', fillcolor='white') + + return dot + + def output(self, filename, directory='_output', view=False, cleanup=True, fmt='pdf', gen_bom=False): + # graphical output + digraph = self.create_graph() + for f in fmt: + digraph.format = f + digraph.render(filename=filename, directory=directory, view=view, cleanup=cleanup) + digraph.save(filename=f'{filename}.gv', directory=directory) + # bom output + bom_list = self.bom_list() + with open(f'{filename}.bom.tsv', 'w') as file: + file.write(tuplelist2tsv(bom_list)) + # HTML output + with open(f'{filename}.html', 'w') as file: + file.write('') + + file.write('

Diagram

') + with open(f'{filename}.svg') as svg: + for svgdata in svg: + file.write(svgdata) + + file.write('

Bill of Materials

') + listy = flatten2d(bom_list) + file.write('') + file.write('') + for item in listy[0]: + file.write(f'') + file.write('') + for row in listy[1:]: + file.write('') + for i, item in enumerate(row): + align = 'align="right"' if listy[0][i] == 'Qty' else '' + file.write(f'') + file.write('') + file.write('
{item}
{item}
') + + file.write('') + + def bom(self): + bom = [] + bom_connectors = [] + bom_cables = [] + # connectors + types = Counter([(v.type, v.subtype, v.pincount) for v in self.connectors.values()]) + for maintype in types: + items = {k: v for k, v in self.connectors.items() if (v.type, v.subtype, v.pincount) == maintype} + shared = next(iter(items.values())) + designators = list(items.keys()) + designators.sort() + conn_type = f', {shared.type}' if shared.type else '' + conn_subtype = f', {shared.subtype}' if shared.subtype else '' + conn_pincount = f', {shared.pincount} pins' if shared.category != 'ferrule' else '' + conn_color = f', {shared.color}' if shared.color else '' + name = f'Connector{conn_type}{conn_subtype}{conn_pincount}{conn_color}' + item = {'item': name, 'qty': len(designators), 'unit': '', + 'designators': designators if shared.category != 'ferrule' else ''} + bom_connectors.append(item) + bom_connectors = sorted(bom_connectors, key=lambda k: k['item']) # https://stackoverflow.com/a/73050 + bom.extend(bom_connectors) + # cables + types = Counter([(v.category, v.gauge, v.gauge_unit, v.wirecount, v.shield) for v in self.cables.values()]) + for maintype in types: + items = {k: v for k, v in self.cables.items() if ( + v.category, v.gauge, v.gauge_unit, v.wirecount, v.shield) == maintype} + shared = next(iter(items.values())) + if shared.category != 'bundle': + designators = list(items.keys()) + designators.sort() + total_length = sum(i.length for i in items.values()) + gauge_name = f' x {shared.gauge} {shared.gauge_unit}'if shared.gauge else ' wires' + shield_name = ' shielded' if shared.shield else '' + name = f'Cable, {shared.wirecount}{gauge_name}{shield_name}' + item = {'item': name, 'qty': round(total_length, 3), 'unit': 'm', 'designators': designators} + bom_cables.append(item) + # bundles (ignores wirecount) + wirelist = [] + # list all cables again, since bundles are represented as wires internally, with the category='bundle' set + types = Counter([(v.category, v.gauge, v.gauge_unit, v.length) for v in self.cables.values()]) + for maintype in types: + items = {k: v for k, v in self.cables.items() if (v.category, v.gauge, v.gauge_unit, v.length) == maintype} + shared = next(iter(items.values())) + # filter out cables that are not bundles + if shared.category == 'bundle': + for bundle in items.values(): + # add each wire from each bundle to the wirelist + for color in bundle.colors: + wirelist.append({'gauge': shared.gauge, 'gauge_unit': shared.gauge_unit, + 'length': shared.length, 'color': color, 'designator': bundle.name}) + # join similar wires from all the bundles to a single BOM item + types = Counter([(v['gauge'], v['gauge_unit'], v['color']) for v in wirelist]) + for maintype in types: + items = [v for v in wirelist if (v['gauge'], v['gauge_unit'], v['color']) == maintype] + shared = items[0] + designators = [i['designator'] for i in items] + # remove duplicates + designators = list(dict.fromkeys(designators)) + designators.sort() + total_length = sum(i['length'] for i in items) + gauge_name = f', {shared["gauge"]} {shared["gauge_unit"]}' if shared['gauge'] else '' + gauge_color = f', {shared["color"]}' if shared['color'] != '' else '' + name = f'Wire{gauge_name}{gauge_color}' + item = {'item': name, 'qty': round(total_length, 3), 'unit': 'm', 'designators': designators} + bom_cables.append(item) + bom_cables = sorted(bom_cables, key=lambda k: k['item']) # https://stackoverflow.com/a/73050 + bom.extend(bom_cables) + return bom + + def bom_list(self): + bom = self.bom() + keys = ['item', 'qty', 'unit', 'designators'] + bom_list = [] + bom_list.append([k.capitalize() for k in keys]) # create header row with keys + for item in bom: + item_list = [item.get(key, '') for key in keys] # fill missing values with blanks + for i, subitem in enumerate(item_list): + if isinstance(subitem, List): # convert any lists into comma separated strings + item_list[i] = ', '.join(subitem) + bom_list.append(item_list) + return bom_list diff --git a/src/wireviz/wireviz.py b/src/wireviz/wireviz.py index 83dba1e..b94b459 100755 --- a/src/wireviz/wireviz.py +++ b/src/wireviz/wireviz.py @@ -1,450 +1,18 @@ #!/usr/bin/env python3 +# -*- coding: utf-8 -*- + import argparse -from collections import Counter -from dataclasses import dataclass, field -from graphviz import Graph import os import sys -from typing import Any, List + import yaml -if __name__== '__main__': +if __name__ == '__main__': sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) -from wireviz import wv_colors -from wireviz.wv_helper import nested, int2tuple, awg_equiv, flatten2d, tuplelist2tsv +from wireviz.Harness import Harness -class Harness: - - def __init__(self): - self.color_mode = 'SHORT' - self.connectors = {} - self.cables = {} - - def add_connector(self, name, *args, **kwargs): - self.connectors[name] = Connector(name, *args, **kwargs) - - def add_cable(self, name, *args, **kwargs): - self.cables[name] = Cable(name, *args, **kwargs) - - def loop(self, connector_name, from_pin, to_pin): - self.connectors[connector_name].loop(from_pin, to_pin) - - def connect(self, from_name, from_pin, via_name, via_pin, to_name, to_pin): - self.cables[via_name].connect(from_name, from_pin, via_pin, to_name, to_pin) - if from_name in self.connectors: - self.connectors[from_name].activate_pin(from_pin) - if to_name in self.connectors: - self.connectors[to_name].activate_pin(to_pin) - - def create_graph(self): - dot = Graph() - dot.body.append('// Graph generated by WireViz') - dot.body.append('// https://github.com/formatc1702/WireViz') - font = 'arial' - dot.attr('graph', rankdir='LR', - ranksep='2', - bgcolor='white', - nodesep='0.33', - fontname=font) - dot.attr('node', shape='record', - style='filled', - fillcolor='white', - fontname=font) - dot.attr('edge', style='bold', - fontname=font) - - # prepare ports on connectors depending on which side they will connect - for k, c in self.cables.items(): - for x in c.connections: - if x.from_port is not None: # connect to left - self.connectors[x.from_name].ports_right = True - if x.to_port is not None: # connect to right - self.connectors[x.to_name].ports_left = True - - for k, n in self.connectors.items(): - if n.category == 'ferrule': - infostring = '{type}{subtype} {color}'.format(type=n.type, - subtype=', {}'.format(n.subtype) if n.subtype else '', - color=wv_colors.translate_color(n.color, self.color_mode) if n.color else '') - infostring_l = infostring if n.ports_right else '' - infostring_r = infostring if n.ports_left else '' - - dot.node(k, shape='none', - style='filled', - margin='0', - orientation = '0' if n.ports_left else '180', - label='''< - - - - {colorbar} - -
{infostring_l} {infostring_r}
- - - >'''.format(infostring_l=infostring_l, - infostring_r=infostring_r, - colorbar=''.format(wv_colors.translate_color(n.color, 'HEX')) if n.color else '')) - - else: # not a ferrule - # a = attributes - a = [n.type, - n.subtype, - '{}-pin'.format(n.pincount) if n.show_pincount else ''] - # p = pinout - p = [[],[],[]] - for pinnumber, pinname in zip(n.pinnumbers, n.pinout): - if n.hide_disconnected_pins and not n.visible_pins.get(pinnumber, False): - continue - p[1].append(pinname) - if n.ports_left: - p[0].append('{portno}'.format(portno=pinnumber)) - if n.ports_right: - p[2].append('{portno}'.format(portno=pinnumber)) - # l = label - l = [n.name if n.show_name else '', a, p, n.notes] - dot.node(k, label=nested(l)) - - if len(n.loops) > 0: - dot.attr('edge',color='#000000:#ffffff:#000000') - if n.ports_left: - loop_side = 'l' - loop_dir = 'w' - elif n.ports_right: - loop_side = 'r' - loop_dir = 'e' - else: - raise Exception('No side for loops') - for loop in n.loops: - dot.edge('{name}:p{port_from}{loop_side}:{loop_dir}'.format(name=n.name, port_from=loop[0], port_to=loop[1], loop_side=loop_side, loop_dir=loop_dir), - '{name}:p{port_to}{loop_side}:{loop_dir}'.format(name=n.name, port_from=loop[0], port_to=loop[1], loop_side=loop_side, loop_dir=loop_dir)) - - for k, c in self.cables.items(): - # a = attributes - a = ['{}x'.format(len(c.colors)) if c.show_wirecount else '', - '{} {}{}'.format(c.gauge, c.gauge_unit, ' ({} AWG)'.format(awg_equiv(c.gauge)) if c.gauge_unit == 'mm\u00B2' and c.show_equiv else '') if c.gauge else '', # TODO: show equiv - '+ S' if c.shield else '', - '{} m'.format(c.length) if c.length > 0 else ''] - a = list(filter(None, a)) - - html = '' # name+attributes table - - html = html + '' # spacer between attributes and wires - - html = html + '' # main table - if c.notes: - html = html + ''.format(c.notes) # notes table - html = html + '' # spacer at the end - - html = html + '
' # main table - - html = html + '' # name+attributes table - if c.show_name: - html = html + ''.format(colspan=len(a), name=c.name) - html = html + '' # attribute row - for attrib in a: - html = html + ''.format(attrib=attrib) - html = html + '' # attribute row - html = html + '
{name}
{attrib}
 
' # conductor table - - for i, x in enumerate(c.colors,1): - p = [] - p.append(''.format(i)) - p.append(wv_colors.translate_color(x, self.color_mode)) - p.append(''.format(i)) - html = html + '' - for bla in p: - html = html + ''.format(bla) - html = html + '' - bgcolor = wv_colors.translate_color(x, 'hex') - html = html + ''.format(colspan=len(p), bgcolor=bgcolor if bgcolor != '' else '#ffffff', port='w{}'.format(i)) - - if c.shield: - p = ['', 'Shield', ''] - html = html + '' # spacer - html = html + '' - for bla in p: - html = html + ''.format(bla) - html = html + '' - html = html + ''.format(colspan=len(p), bgcolor=wv_colors.translate_color(x, 'hex'), port='ws') - - html = html + '' # spacer at the end - - html = html + '
{}
 
{}
 
' # conductor table - - html = html + '
{}
 
' # main table - - # connections - for x in c.connections: - if isinstance(x.via_port, int): # check if it's an actual wire and not a shield - search_color = c.colors[x.via_port-1] - if search_color in wv_colors.color_hex: - dot.attr('edge',color='#000000:{wire_color}:#000000'.format(wire_color=wv_colors.color_hex[search_color])) - else: # color name not found - dot.attr('edge',color='#000000:#ffffff:#000000') - else: # it's a shield connection - dot.attr('edge',color='#000000') - - if x.from_port is not None: # connect to left - from_ferrule = self.connectors[x.from_name].category == 'ferrule' - code_left_1 = '{from_name}{from_port}:e'.format(from_name=x.from_name, from_port=':p{}r'.format(x.from_port) if not from_ferrule else '') - code_left_2 = '{via_name}:w{via_wire}:w'.format(via_name=c.name, via_wire=x.via_port, via_subport='i' if c.show_pinout else '') - dot.edge(code_left_1, code_left_2) - from_string = '{}:{}'.format(x.from_name, x.from_port) if not from_ferrule else '' - html = html.replace(''.format(x.via_port), from_string) - if x.to_port is not None: # connect to right - to_ferrule = self.connectors[x.to_name].category == 'ferrule' - code_right_1 = '{via_name}:w{via_wire}:e'.format(via_name=c.name, via_wire=x.via_port, via_subport='o' if c.show_pinout else '') - code_right_2 = '{to_name}{to_port}:w'.format(to_name=x.to_name, to_port=':p{}l'.format(x.to_port) if not to_ferrule else '') - dot.edge(code_right_1, code_right_2) - to_string = '{}:{}'.format(x.to_name, x.to_port) if not to_ferrule else '' - html = html.replace(''.format(x.via_port), to_string) - - dot.node(c.name, label='<{html}>'.format(html=html), shape='box', style='filled,dashed' if c.category=='bundle' else '', margin='0', fillcolor='white') - - return dot - - def output(self, filename, directory='_output', view=False, cleanup=True, format='pdf', gen_bom=False): - # graphical output - d = self.create_graph() - for f in format: - d.format = f - d.render(filename=filename, directory=directory, view=view, cleanup=cleanup) - d.save(filename='{}.gv'.format(filename), directory=directory) - # bom output - bom_list = self.bom_list() - with open('{}.bom.tsv'.format(filename),'w') as file: - file.write(tuplelist2tsv(bom_list)) - # HTML output - with open('{}.html'.format(filename),'w') as file: - file.write('') - - file.write('

Diagram

') - with open('{}.svg'.format(filename),'r') as svg: - for l in svg: - file.write(l) - - file.write('

Bill of Materials

') - listy = flatten2d(bom_list) - file.write('') - file.write('') - for item in listy[0]: - file.write(''.format(item)) - file.write('') - for row in listy[1:]: - file.write('') - for i, item in enumerate(row): - file.write(''.format(content=item, align='align="right"' if listy[0][i] == 'Qty' else '')) - file.write('') - file.write('
{}
{content}
') - - file.write('') - - def bom(self): - bom = [] - bom_connectors = [] - bom_cables = [] - # connectors - types = Counter([(v.type, v.subtype, v.pincount) for v in self.connectors.values()]) - for type in types: - items = {k: v for k, v in self.connectors.items() if (v.type, v.subtype, v.pincount) == type} - shared = next(iter(items.values())) - designators = list(items.keys()) - designators.sort() - name = 'Connector{type}{subtype}{pincount}{color}'.format(type = ', {}'.format(shared.type) if shared.type else '', - subtype = ', {}'.format(shared.subtype) if shared.subtype else '', - pincount = ', {} pins'.format(shared.pincount) if shared.category != 'ferrule' else '', - color = ', {}'.format(shared.color) if shared.color else '') - item = {'item': name, 'qty': len(designators), 'unit': '', 'designators': designators if shared.category != 'ferrule' else ''} - bom_connectors.append(item) - bom_connectors = sorted(bom_connectors, key=lambda k: k['item']) # https://stackoverflow.com/a/73050 - bom.extend(bom_connectors) - # cables - types = Counter([(v.category, v.gauge, v.gauge_unit, v.wirecount, v.shield) for v in self.cables.values()]) - for type in types: - items = {k: v for k, v in self.cables.items() if (v.category, v.gauge, v.gauge_unit, v.wirecount, v.shield) == type} - shared = next(iter(items.values())) - if shared.category != 'bundle': - designators = list(items.keys()) - designators.sort() - total_length = sum(i.length for i in items.values()) - name = 'Cable, {wirecount}{gauge}{shield}'.format(wirecount = shared.wirecount, - gauge = ' x {} {}'.format(shared.gauge, shared.gauge_unit) if shared.gauge else ' wires', - shield = ' shielded' if shared.shield else '') - item = {'item': name, 'qty': round(total_length, 3), 'unit': 'm', 'designators': designators} - bom_cables.append(item) - # bundles (ignores wirecount) - wirelist = [] - # list all cables again, since bundles are represented as wires internally, with the category='bundle' set - types = Counter([(v.category, v.gauge, v.gauge_unit, v.length) for v in self.cables.values()]) - for type in types: - items = {k: v for k, v in self.cables.items() if (v.category, v.gauge, v.gauge_unit, v.length) == type} - shared = next(iter(items.values())) - # filter out cables that are not bundles - if shared.category == 'bundle': - for bundle in items.values(): - # add each wire from each bundle to the wirelist - for color in bundle.colors: - wirelist.append({'gauge': shared.gauge, 'gauge_unit': shared.gauge_unit, 'length': shared.length, 'color': color, 'designator': bundle.name}) - # join similar wires from all the bundles to a single BOM item - types = Counter([(v['gauge'], v['gauge_unit'], v['color']) for v in wirelist]) - for type in types: - items = [v for v in wirelist if (v['gauge'], v['gauge_unit'], v['color']) == type] - shared = items[0] - designators = [i['designator'] for i in items] - # remove duplicates - designators = list(dict.fromkeys(designators)) - designators.sort() - total_length = sum(i['length'] for i in items) - name = 'Wire{gauge}{color}'.format(gauge=', {} {}'.format(shared['gauge'], shared['gauge_unit']) if shared['gauge'] else '', - color=', {}'.format(shared['color']) if shared['color'] != '' else '') - item = {'item': name, 'qty': round(total_length, 3), 'unit': 'm', 'designators': designators} - bom_cables.append(item) - bom_cables = sorted(bom_cables, key=lambda k: k['item']) # https://stackoverflow.com/a/73050 - bom.extend(bom_cables) - return bom - - def bom_list(self): - bom = self.bom() - keys = ['item', 'qty', 'unit', 'designators'] - bom_list = [] - bom_list.append([k.capitalize() for k in keys]) # create header row with keys - for item in bom: - item_list = [item.get(key, '') for key in keys] # fill missing values with blanks - for i, subitem in enumerate(item_list): - if isinstance(subitem, List): # convert any lists into comma separated strings - item_list[i] = ', '.join(subitem) - bom_list.append(item_list) - return bom_list - -@dataclass -class Connector: - name: str - category: str = None - type: str = None - subtype: str = None - pincount: int = None - notes: str = None - pinout: List[Any] = field(default_factory=list) - pinnumbers: List[Any] = field(default_factory=list) - color: str = None - show_name: bool = True - show_pincount: bool = True - hide_disconnected_pins: bool = False - - def __post_init__(self): - self.ports_left = False - self.ports_right = False - self.loops = [] - self.visible_pins = {} - - if self.pincount is None: - if self.pinout: - self.pincount = len(self.pinout) - elif self.pinnumbers: - self.pincount = len(self.pinnumbers) - elif self.category == 'ferrule': - self.pincount = 1 - else: - raise Exception('You need to specify at least one, pincount, pinout or pinnumbers') - - if self.pinout and self.pinnumbers: - if len(self.pinout) != len(self.pinnumbers): - raise Exception('Given pinout and pinnumbers size mismatch') - - # create default lists for pinnumbers (sequential) and pinouts (blank) if not specified - if not self.pinnumbers: - self.pinnumbers = list(range(1,self.pincount + 1)) - if not self.pinout: - self.pinout = [''] * self.pincount - - def loop(self, from_pin, to_pin): - self.loops.append((from_pin, to_pin)) - if self.hide_disconnected_pins: - self.visible_pins[from_pin] = True - self.visible_pins[to_pin] = True - - def activate_pin(self, pin): - self.visible_pins[pin] = True - -@dataclass -class Cable: - name: str - category : str = None - type: str = None - gauge: float = None - gauge_unit : str = None - show_equiv: bool = False - length: float = 0 - wirecount: int = None - shield: bool = False - notes: str = None - colors: List[Any] = field(default_factory=list) - color_code: str = None - show_name: bool = True - show_pinout: bool = False - show_wirecount: bool = True - - def __post_init__(self): - - if isinstance(self.gauge, str): # gauge and unit specified - try: - g, u = self.gauge.split(' ') - except: - raise Exception('Gauge must be a number, or number and unit separated by a space') - self.gauge = g - self.gauge_unit = u.replace('mm2','mm\u00B2') - elif self.gauge is not None: # gauge specified, assume mm2 - if self.gauge_unit is None: - self.gauge_unit = 'mm\u00B2' - else: - pass # gauge not specified - - self.connections = [] - - if self.wirecount: # number of wires explicitly defined - if self.colors: # use custom color palette (partly or looped if needed) - pass - elif self.color_code: # use standard color palette (partly or looped if needed) - if self.color_code not in wv_colors.COLOR_CODES: - raise Exception('Unknown color code') - self.colors = wv_colors.COLOR_CODES[self.color_code] - else: # no colors defined, add dummy colors - self.colors = [''] * self.wirecount - - # make color code loop around if more wires than colors - if self.wirecount > len(self.colors): - m = self.wirecount // len(self.colors) + 1 - self.colors = self.colors * int(m) - # cut off excess after looping - self.colors = self.colors[:self.wirecount] - else: # wirecount implicit in length of color list - if not self.colors: - raise Exception('Unknown number of wires. Must specify wirecount or colors (implicit length)') - self.wirecount = len(self.colors) - - # for BOM generation - self.wirecount_and_shield = (self.wirecount, self.shield) - - def connect(self, from_name, from_pin, via_pin, to_name, to_pin): - from_pin = int2tuple(from_pin) - via_pin = int2tuple(via_pin) - to_pin = int2tuple(to_pin) - if len(from_pin) != len(to_pin): - raise Exception('from_pin must have the same number of elements as to_pin') - for i, x in enumerate(from_pin): - # self.connections.append((from_name, from_pin[i], via_pin[i], to_name, to_pin[i])) - self.connections.append(Connection(from_name, from_pin[i], via_pin[i], to_name, to_pin[i])) - -@dataclass -class Connection: - from_name: Any - from_port: Any - via_port: Any - to_name: Any - to_port: Any def parse(yaml_input, file_out=None, generate_bom=False): @@ -457,23 +25,23 @@ def parse(yaml_input, file_out=None, generate_bom=False): # if str is of the format '#-#', it is treated as a range (inclusive) and expanded output = [] if not isinstance(yaml_data, list): - yaml_data = [yaml_data,] + yaml_data = [yaml_data] for e in yaml_data: e = str(e) - if '-' in e: # list of pins + if '-' in e: # list of pins a, b = tuple(map(int, e.split('-'))) if a < b: - for x in range(a,b+1): + for x in range(a, b + 1): output.append(x) elif a > b: - for x in range(a,b-1,-1): + for x in range(a, b - 1, -1): output.append(x) elif a == b: output.append(a) else: try: x = int(e) - except: + except Exception: x = e output.append(x) return output @@ -484,25 +52,25 @@ def parse(yaml_input, file_out=None, generate_bom=False): return False return True - h = Harness() + harness = Harness() # add items - sections = ['connectors','cables','ferrules','connections'] - types = [dict, dict, dict, list] + sections = ['connectors', 'cables', 'ferrules', 'connections'] + types = [dict, dict, dict, list] for sec, ty in zip(sections, types): if sec in yaml_data and type(yaml_data[sec]) == ty: if len(yaml_data[sec]) > 0: if ty == dict: - for k, o in yaml_data[sec].items(): + for key, o in yaml_data[sec].items(): if sec == 'connectors': - h.add_connector(name=k, **o) + harness.add_connector(name=key, **o) elif sec == 'cables': - h.add_cable(name=k, **o) + harness.add_cable(name=key, **o) elif sec == 'ferrules': pass else: - pass # section exists but is empty - else: # section does not exist, create empty section + pass # section exists but is empty + else: # section does not exist, create empty section if ty == dict: yaml_data[sec] = {} elif ty == list: @@ -510,64 +78,63 @@ def parse(yaml_input, file_out=None, generate_bom=False): # add connections ferrule_counter = 0 - for con in yaml_data['connections']: - if len(con) == 3: # format: connector -- cable -- connector + for connections in yaml_data['connections']: + if len(connections) == 3: # format: connector -- cable -- connector - for c in con: - if len(list(c.keys())) != 1: # check that each entry in con has only one key, which is the designator + for connection in connections: + if len(list(connection.keys())) != 1: # check that each entry in con has only one key, which is the designator raise Exception('Too many keys') - from_name = list(con[0].keys())[0] - via_name = list(con[1].keys())[0] - to_name = list(con[2].keys())[0] + from_name = list(connections[0].keys())[0] + via_name = list(connections[1].keys())[0] + to_name = list(connections[2].keys())[0] - if not check_designators([from_name,via_name,to_name],('connectors','cables','connectors')): - print([from_name,via_name,to_name]) + if not check_designators([from_name, via_name, to_name], ('connectors', 'cables', 'connectors')): + print([from_name, via_name, to_name]) raise Exception('Bad connection definition (3)') - from_pins = expand(con[0][from_name]) - via_pins = expand(con[1][via_name]) - to_pins = expand(con[2][to_name]) + from_pins = expand(connections[0][from_name]) + via_pins = expand(connections[1][via_name]) + to_pins = expand(connections[2][to_name]) if len(from_pins) != len(via_pins) or len(via_pins) != len(to_pins): raise Exception('List length mismatch') for (from_pin, via_pin, to_pin) in zip(from_pins, via_pins, to_pins): - h.connect(from_name, from_pin, via_name, via_pin, to_name, to_pin) + harness.connect(from_name, from_pin, via_name, via_pin, to_name, to_pin) - elif len(con) == 2: + elif len(connections) == 2: - for c in con: - if type(c) is dict: - if len(list(c.keys())) != 1: # check that each entry in con has only one key, which is the designator + for connection in connections: + if type(connection) is dict: + if len(list(connection.keys())) != 1: # check that each entry in con has only one key, which is the designator raise Exception('Too many keys') # hack to make the format for ferrules compatible with the formats for connectors and cables - if type(con[0]) == str: - name = con[0] - con[0] = {} - con[0][name] = name - if type(con[1]) == str: - name = con[1] - con[1] = {} - con[1][name] = name + if type(connections[0]) == str: + name = connections[0] + connections[0] = {} + connections[0][name] = name + if type(connections[1]) == str: + name = connections[1] + connections[1] = {} + connections[1][name] = name - from_name = list(con[0].keys())[0] - to_name = list(con[1].keys())[0] + from_name = list(connections[0].keys())[0] + to_name = list(connections[1].keys())[0] - con_cbl = check_designators([from_name, to_name],('connectors','cables')) - cbl_con = check_designators([from_name, to_name],('cables','connectors')) - con_con = check_designators([from_name, to_name],('connectors','connectors')) + con_cbl = check_designators([from_name, to_name], ('connectors', 'cables')) + cbl_con = check_designators([from_name, to_name], ('cables', 'connectors')) + con_con = check_designators([from_name, to_name], ('connectors', 'connectors')) - - fer_cbl = check_designators([from_name, to_name],('ferrules','cables')) - cbl_fer = check_designators([from_name, to_name],('cables','ferrules')) + fer_cbl = check_designators([from_name, to_name], ('ferrules', 'cables')) + cbl_fer = check_designators([from_name, to_name], ('cables', 'ferrules')) if not con_cbl and not cbl_con and not con_con and not fer_cbl and not cbl_fer: raise Exception('Wrong designators') - from_pins = expand(con[0][from_name]) - to_pins = expand(con[1][to_name]) + from_pins = expand(connections[0][from_name]) + to_pins = expand(connections[1][to_name]) if con_cbl or cbl_con or con_con: if len(from_pins) != len(to_pins): @@ -576,19 +143,19 @@ def parse(yaml_input, file_out=None, generate_bom=False): if con_cbl or cbl_con: for (from_pin, to_pin) in zip(from_pins, to_pins): if con_cbl: - h.connect(from_name, from_pin, to_name, to_pin, None, None) - else: # cbl_con - h.connect(None, None, from_name, from_pin, to_name, to_pin) + harness.connect(from_name, from_pin, to_name, to_pin, None, None) + else: # cbl_con + harness.connect(None, None, from_name, from_pin, to_name, to_pin) elif con_con: - cocon_coname = list(con[0].keys())[0] - from_pins = expand(con[0][from_name]) - to_pins = expand(con[1][to_name]) + cocon_coname = list(connections[0].keys())[0] + from_pins = expand(connections[0][from_name]) + to_pins = expand(connections[1][to_name]) for (from_pin, to_pin) in zip(from_pins, to_pins): - h.loop(cocon_coname, from_pin, to_pin) + harness.loop(cocon_coname, from_pin, to_pin) if fer_cbl or cbl_fer: - from_pins = expand(con[0][from_name]) - to_pins = expand(con[1][to_name]) + from_pins = expand(connections[0][from_name]) + to_pins = expand(connections[1][to_name]) if fer_cbl: ferrule_name = from_name @@ -602,19 +169,19 @@ def parse(yaml_input, file_out=None, generate_bom=False): ferrule_params = yaml_data['ferrules'][ferrule_name] for cable_pin in cable_pins: ferrule_counter = ferrule_counter + 1 - ferrule_id = '_F{}'.format(ferrule_counter) - h.add_connector(ferrule_id, category='ferrule', **ferrule_params) + ferrule_id = f'_F{ferrule_counter}' + harness.add_connector(ferrule_id, category='ferrule', **ferrule_params) if fer_cbl: - h.connect(ferrule_id, 1, cable_name, cable_pin, None, None) + harness.connect(ferrule_id, 1, cable_name, cable_pin, None, None) else: - h.connect(None, None, cable_name, cable_pin, ferrule_id, 1) - + harness.connect(None, None, cable_name, cable_pin, ferrule_id, 1) else: raise Exception('Wrong number of connection parameters') - h.output(filename=file_out, format=('png','svg'), gen_bom=generate_bom, view=False) + harness.output(filename=file_out, fmt=('png', 'svg'), gen_bom=generate_bom, view=False) + def parse_file(yaml_file, file_out=None, generate_bom=False): with open(yaml_file, 'r') as file: @@ -630,27 +197,26 @@ def parse_file(yaml_file, file_out=None, generate_bom=False): def parse_cmdline(): parser = argparse.ArgumentParser( - description='Generate cable and wiring harness documentation from YAML descriptions' - ) + description='Generate cable and wiring harness documentation from YAML descriptions', + ) 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('-o', '--output_file', action='store', type=str, metavar='OUTPUT') parser.add_argument('--generate-bom', action='store_true', default=True) parser.add_argument('--prepend-file', action='store', type=str, metavar='YAML_FILE') - args = parser.parse_args() + return parser.parse_args() - return args def main(): args = parse_cmdline() if not os.path.exists(args.input_file): - print('Error: input file {} inaccessible or does not exist, check path'.format(args.input_file)) + print(f'Error: input file {args.input_file} inaccessible or does not exist, check path') sys.exit(1) with open(args.input_file) as fh: @@ -658,7 +224,7 @@ def main(): if args.prepend_file: if not os.path.exists(args.prepend_file): - print('Error: prepend input file {} inaccessible or does not exist, check path'.format(args.prepend_file)) + print(f'Error: prepend input file {args.prepend_file} inaccessible or does not exist, check path') sys.exit(1) with open(args.prepend_file) as fh: prepend = fh.read() @@ -667,12 +233,13 @@ def main(): if not args.output_file: file_out = args.input_file pre, _ = os.path.splitext(file_out) - file_out = pre # extension will be added by graphviz output function + file_out = pre # extension will be added by graphviz output function else: file_out = args.output_file file_out = os.path.abspath(file_out) parse(yaml_input, file_out=file_out, generate_bom=args.generate_bom) + if __name__ == '__main__': main() diff --git a/src/wireviz/wv_colors.py b/src/wireviz/wv_colors.py index 32c90c9..ad22659 100644 --- a/src/wireviz/wv_colors.py +++ b/src/wireviz/wv_colors.py @@ -1,74 +1,77 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- COLOR_CODES = { - 'DIN': ['WH','BN','GN','YE','GY','PK','BU','RD','BK','VT'], # ,'GYPK','RDBU','WHGN','BNGN','WHYE','YEBN','WHGY','GYBN','WHPK','PKBN'], - 'IEC': ['BN','RD','OG','YE','GN','BU','VT','GY','WH','BK'], - 'BW': ['BK','WH'] - } + 'DIN': ['WH', 'BN', 'GN', 'YE', 'GY', 'PK', 'BU', 'RD', 'BK', 'VT'], # ,'GYPK','RDBU','WHGN','BNGN','WHYE','YEBN','WHGY','GYBN','WHPK','PKBN'], + 'IEC': ['BN', 'RD', 'OG', 'YE', 'GN', 'BU', 'VT', 'GY', 'WH', 'BK'], + 'BW': ['BK', 'WH'], +} color_hex = { - 'BK': '#000000', - 'WH': '#ffffff', - 'GY': '#999999', - 'PK': '#ff66cc', - 'RD': '#ff0000', - 'OG': '#ff8000', - 'YE': '#ffff00', - 'GN': '#00ff00', - 'TQ': '#00ffff', - 'BU': '#0066ff', - 'VT': '#8000ff', - 'BN': '#666600', - } + 'BK': '#000000', + 'WH': '#ffffff', + 'GY': '#999999', + 'PK': '#ff66cc', + 'RD': '#ff0000', + 'OG': '#ff8000', + 'YE': '#ffff00', + 'GN': '#00ff00', + 'TQ': '#00ffff', + 'BU': '#0066ff', + 'VT': '#8000ff', + 'BN': '#666600', +} color_full = { - 'BK': 'black', - 'WH': 'white', - 'GY': 'grey', - 'PK': 'pink', - 'RD': 'red', - 'OG': 'orange', - 'YE': 'yellow', - 'GN': 'green', - 'TQ': 'turquoise', - 'BU': 'blue', - 'VT': 'violet', - 'BN': 'brown', + 'BK': 'black', + 'WH': 'white', + 'GY': 'grey', + 'PK': 'pink', + 'RD': 'red', + 'OG': 'orange', + 'YE': 'yellow', + 'GN': 'green', + 'TQ': 'turquoise', + 'BU': 'blue', + 'VT': 'violet', + 'BN': 'brown', } color_ger = { - 'BK': 'sw', - 'WH': 'ws', - 'GY': 'gr', - 'PK': 'rs', - 'RD': 'rt', - 'OG': 'or', - 'YE': 'ge', - 'GN': 'gn', - 'TQ': 'tk', - 'BU': 'bl', - 'VT': 'vi', - 'BN': 'br', + 'BK': 'sw', + 'WH': 'ws', + 'GY': 'gr', + 'PK': 'rs', + 'RD': 'rt', + 'OG': 'or', + 'YE': 'ge', + 'GN': 'gn', + 'TQ': 'tk', + 'BU': 'bl', + 'VT': 'vi', + 'BN': 'br', } -def translate_color(input, color_mode): - if input == '': + +def translate_color(inp, color_mode): + if inp == '': output = '' else: if color_mode == 'full': - output = color_full[input].lower() + output = color_full[inp].lower() elif color_mode == 'FULL': - output = color_full[input].upper() + output = color_full[inp].upper() elif color_mode == 'hex': - output = color_hex[input].lower() + output = color_hex[inp].lower() elif color_mode == 'HEX': - output = color_hex[input].upper() + output = color_hex[inp].upper() elif color_mode == 'ger': - output = color_ger[input].lower() + output = color_ger[inp].lower() elif color_mode == 'GER': - output = color_ger[input].upper() + output = color_ger[inp].upper() elif color_mode == 'short': - output = input.lower() + output = inp.lower() elif color_mode == 'SHORT': - output = input.upper() + output = inp.upper() else: raise Exception('Unknown color mode') return output diff --git a/src/wireviz/wv_helper.py b/src/wireviz/wv_helper.py index 1c803fd..b06d40e 100644 --- a/src/wireviz/wv_helper.py +++ b/src/wireviz/wv_helper.py @@ -1,33 +1,37 @@ -from typing import Any, List +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +from typing import List + def awg_equiv(mm2): awg_equiv_table = { - '0.09': 28, - '0.14': 26, - '0.25': 24, - '0.34': 22, - '0.5': 21, - '0.75': 20, - '1': 18, - '1.5': 16, - '2.5': 14, - '4': 12, - '6': 10, - '10': 8, - '16': 6, - '25': 4, - '35': 2, - '50': 1, - } + '0.09': 28, + '0.14': 26, + '0.25': 24, + '0.34': 22, + '0.5': 21, + '0.75': 20, + '1': 18, + '1.5': 16, + '2.5': 14, + '4': 12, + '6': 10, + '10': 8, + '16': 6, + '25': 4, + '35': 2, + '50': 1, + } k = str(mm2) if k in awg_equiv_table: return awg_equiv_table[k] else: return 'unknown' -def nested(input): + +def nested(inp): l = [] - for x in input: + for x in inp: if isinstance(x, list): if len(x) > 0: n = nested(x) @@ -37,25 +41,26 @@ def nested(input): if x is not None: if x != '': l.append(str(x)) - s = '|'.join(l) - return s + return '|'.join(l) -def int2tuple(input): - if isinstance(input, tuple): - output = input + +def int2tuple(inp): + if isinstance(inp, tuple): + output = inp else: - output = (input,) + output = (inp,) return output -def flatten2d(input): - output = [[str(item) if not isinstance(item, List) else ', '.join(item) for item in row] for row in input] - return output -def tuplelist2tsv(input, header=None): +def flatten2d(inp): + return [[str(item) if not isinstance(item, List) else ', '.join(item) for item in row] for row in inp] + + +def tuplelist2tsv(inp, header=None): output = '' if header is not None: - input.insert(0, header) - input = flatten2d(input) - for row in input: + inp.insert(0, header) + inp = flatten2d(inp) + for row in inp: output = output + '\t'.join(str(item) for item in row) + '\n' return output From c42b33b38d3bf3f2ee4aa157a7445caeedde5bb3 Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Mon, 29 Jun 2020 12:30:07 +0200 Subject: [PATCH 27/35] Address FIXMEs and fine-tune merge of #39 --- src/wireviz/DataClasses.py | 2 +- src/wireviz/Harness.py | 19 ++++--------------- src/wireviz/build_examples.py | 1 + src/wireviz/wireviz.py | 6 ------ src/wireviz/wv_colors.py | 1 + src/wireviz/wv_helper.py | 1 + 6 files changed, 8 insertions(+), 22 deletions(-) diff --git a/src/wireviz/DataClasses.py b/src/wireviz/DataClasses.py index c7dc007..a2f2a9e 100644 --- a/src/wireviz/DataClasses.py +++ b/src/wireviz/DataClasses.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- + from typing import Optional, List, Any from dataclasses import dataclass, field from wireviz.wv_helper import int2tuple @@ -72,7 +73,6 @@ class Cable: colors: List[Any] = field(default_factory=list) color_code: Optional[str] = None show_name: bool = True - show_pinout: bool = False show_wirecount: bool = True def __post_init__(self): diff --git a/src/wireviz/Harness.py b/src/wireviz/Harness.py index 595d13d..c11ad9a 100644 --- a/src/wireviz/Harness.py +++ b/src/wireviz/Harness.py @@ -109,10 +109,6 @@ class Harness: else: raise Exception('No side for loops') for loop in connector.loops: - - # FIXME: Original string.format style had some unused arguments (port_to for 1st arg, - # port_from for 2nd arg). De we need them back? - dot.edge(f'{connector.name}:p{loop[0]}{loop_side}:{loop_dir}', f'{connector.name}:p{loop[1]}{loop_side}:{loop_dir}') @@ -159,8 +155,6 @@ class Harness: for bla in p: html = html + f'{bla}' html = f'{html}' - - # FIXME, original string.format had a unused bgcolor argument. Do we need it back html = f'{html}' html = f'{html} ' # spacer at the end @@ -189,17 +183,12 @@ class Harness: from_ferrule = self.connectors[connection.from_name].category == 'ferrule' port = f':p{connection.from_port}r' if not from_ferrule else '' code_left_1 = f'{connection.from_name}{port}:e' - # FIXME: Uncomment, then add to end of f-string if needed - # via_subport = 'i' if c.show_pinout else '' code_left_2 = f'{cable.name}:w{connection.via_port}:w' dot.edge(code_left_1, code_left_2) from_string = f'{connection.from_name}:{connection.from_port}' if not from_ferrule else '' html = html.replace(f'', from_string) if connection.to_port is not None: # connect to right to_ferrule = self.connectors[connection.to_name].category == 'ferrule' - - # FIXME: Add in if it was supposed to be here. the add to fstring two lines down - # via_subport = 'o' if c.show_pinout else '' code_right_1 = f'{cable.name}:w{connection.via_port}:e' to_port = f':p{connection.to_port}l' if not to_ferrule else '' code_right_2 = f'{connection.to_name}{to_port}:w' @@ -214,11 +203,11 @@ class Harness: def output(self, filename, directory='_output', view=False, cleanup=True, fmt='pdf', gen_bom=False): # graphical output - digraph = self.create_graph() + graph = self.create_graph() for f in fmt: - digraph.format = f - digraph.render(filename=filename, directory=directory, view=view, cleanup=cleanup) - digraph.save(filename=f'{filename}.gv', directory=directory) + graph.format = f + graph.render(filename=filename, directory=directory, view=view, cleanup=cleanup) + graph.save(filename=f'{filename}.gv', directory=directory) # bom output bom_list = self.bom_list() with open(f'{filename}.bom.tsv', 'w') as file: diff --git a/src/wireviz/build_examples.py b/src/wireviz/build_examples.py index fc04fce..078e4e2 100755 --- a/src/wireviz/build_examples.py +++ b/src/wireviz/build_examples.py @@ -1,4 +1,5 @@ #!/usr/bin/python3 +# -*- coding: utf-8 -*- import os import sys diff --git a/src/wireviz/wireviz.py b/src/wireviz/wireviz.py index b94b459..81b4771 100755 --- a/src/wireviz/wireviz.py +++ b/src/wireviz/wireviz.py @@ -1,7 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- - import argparse import os import sys @@ -199,15 +198,10 @@ def parse_cmdline(): parser = argparse.ArgumentParser( description='Generate cable and wiring harness documentation from YAML descriptions', ) - 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) - parser.add_argument('--prepend-file', action='store', type=str, metavar='YAML_FILE') - return parser.parse_args() diff --git a/src/wireviz/wv_colors.py b/src/wireviz/wv_colors.py index ad22659..055b467 100644 --- a/src/wireviz/wv_colors.py +++ b/src/wireviz/wv_colors.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- + COLOR_CODES = { 'DIN': ['WH', 'BN', 'GN', 'YE', 'GY', 'PK', 'BU', 'RD', 'BK', 'VT'], # ,'GYPK','RDBU','WHGN','BNGN','WHYE','YEBN','WHGY','GYBN','WHPK','PKBN'], 'IEC': ['BN', 'RD', 'OG', 'YE', 'GN', 'BU', 'VT', 'GY', 'WH', 'BK'], diff --git a/src/wireviz/wv_helper.py b/src/wireviz/wv_helper.py index b06d40e..65ccdb3 100644 --- a/src/wireviz/wv_helper.py +++ b/src/wireviz/wv_helper.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- + from typing import List From c7014a2ea077d7847d009a068e8f45dab9e81cff Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Mon, 29 Jun 2020 14:22:32 +0200 Subject: [PATCH 28/35] Fix URL in setup.py (fixes #42) --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 83dbc55..950e314 100644 --- a/setup.py +++ b/setup.py @@ -26,7 +26,7 @@ setup( ], license='GPLv3', keywords='cable connector hardware harness wiring wiring-diagram wiring-harness', - url='https://github.com/n42/WireViz', + url='https://github.com/formatc1702/WireViz', package_dir={'': 'src'}, packages=find_packages('src'), entry_points={ From 08e53bcd48b11b2e5982bc891ec8c55b5585291f Mon Sep 17 00:00:00 2001 From: Andreas Nordin Date: Mon, 29 Jun 2020 14:41:45 +0200 Subject: [PATCH 29/35] Feature: bidirectional AWG/mm2 unit conversion (#41) * Fix AWG<-> mm2 conversions Add an inverted dictionary and a lookup function from awg -> mm2. Also do some minor refactoring. Both sides of the conversion table were converted to strings, since '0000' and '2/0' are perfectly valid AWG values. * Update example ex02 with awg -> mm2 conversion Show conversions for ex02, and make sure it displays conversions in both directions. Rebuild the example files. * Fix faulty conversion of non-(mm2,AWG) units The parsing allows arbitrary units to be used for cable dimensions -- this might be valid units, e.g. square inches, or invalid, e.g. bananas. We only allow conversion between mm2 and AWG, so check that the gauge_unit is either of those before conversion. If not, pass through as is. * Fix AWG string casing in output Convert e.g. 'awg, 'AwG' to upper case for consistent rendering. Leave any other input gauge units as they were. Co-authored-by: Daniel Rojas --- examples/ex02.bom.tsv | 3 +- examples/ex02.gv | 2 +- examples/ex02.html | 74 ++++++++++++++++++------------------- examples/ex02.png | Bin 81203 -> 86866 bytes examples/ex02.svg | 72 ++++++++++++++++++------------------ examples/ex02.yml | 1 + src/wireviz/DataClasses.py | 7 +++- src/wireviz/Harness.py | 16 ++++++-- src/wireviz/wv_helper.py | 46 +++++++++++------------ 9 files changed, 119 insertions(+), 102 deletions(-) diff --git a/examples/ex02.bom.tsv b/examples/ex02.bom.tsv index 4c8d11e..a85de3e 100644 --- a/examples/ex02.bom.tsv +++ b/examples/ex02.bom.tsv @@ -1,4 +1,5 @@ Item Qty Unit Designators Connector, Molex Micro-Fit, female, 2 pins 3 X2, X3, X4 Connector, Molex Micro-Fit, male, 2 pins 1 X1 -Cable, 2 x 0.25 mm² 0.6 m W1, W2, W3 +Cable, 2 x 0.25 mm² 0.4 m W1, W2 +Cable, 2 x 20 awg 0.2 m W3 diff --git a/examples/ex02.gv b/examples/ex02.gv index b914864..030934d 100644 --- a/examples/ex02.gv +++ b/examples/ex02.gv @@ -28,5 +28,5 @@ graph { edge [color="#000000:#ff0000:#000000"] X1:p2r:e -- W3:w2:w W3:w2:e -- X4:p2l:w - W3 [label=<
W3
2x0.25 mm² (24 AWG)0.2 m
 
X1:1BKX4:1
X1:2RDX4:2
 
> fillcolor=white margin=0 shape=box style=""] + W3 [label=<
W3
2x20 awg (0.75 mm²)0.2 m
 
X1:1BKX4:1
X1:2RDX4:2
 
> fillcolor=white margin=0 shape=box style=""] } diff --git a/examples/ex02.html b/examples/ex02.html index 148fa57..aafa0e9 100644 --- a/examples/ex02.html +++ b/examples/ex02.html @@ -1,7 +1,7 @@

Diagram

- W3 - - -W3 - -2x - -0.25 mm² (24 AWG) - -0.2 m -  -X1:1 -BK -X4:1 - - - -X1:2 -RD -X4:2 - - - -  + + +W3 + +2x + +20 awg (0.75 mm²) + +0.2 m +  +X1:1 +BK +X4:1 + + + +X1:2 +RD +X4:2 + + + +  X1:e--W3:w - - - + + + X1:e--W3:w - - - + + + @@ -242,17 +242,17 @@ W3:e--X4:w - - - + + + W3:e--X4:w - - - + + + -

Bill of Materials

ItemQtyUnitDesignators
Connector, Molex Micro-Fit, female, 2 pins3X2, X3, X4
Connector, Molex Micro-Fit, male, 2 pins1X1
Cable, 2 x 0.25 mm²0.6mW1, W2, W3
\ No newline at end of file +

Bill of Materials

ItemQtyUnitDesignators
Connector, Molex Micro-Fit, female, 2 pins3X2, X3, X4
Connector, Molex Micro-Fit, male, 2 pins1X1
Cable, 2 x 0.25 mm²0.4mW1, W2
Cable, 2 x 20 awg0.2mW3
\ No newline at end of file diff --git a/examples/ex02.png b/examples/ex02.png index 7dbb395b6c9710d23edf3499f471915c78c9fe50..0a989728918b3f997fa1dddbccad0cc1cb512f00 100644 GIT binary patch literal 86866 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

Diagram

- W3 - - -W3 - -2x - -20 awg (0.75 mm²) - -0.2 m -  -X1:1 -BK -X4:1 - - - -X1:2 -RD -X4:2 - - - -  + + +W3 + +2x + +20 AWG (0.75 mm²) + +0.2 m +  +X1:1 +BK +X4:1 + + + +X1:2 +RD +X4:2 + + + +  X1:e--W3:w - - - + + + X1:e--W3:w - - - + + + @@ -242,17 +242,17 @@ W3:e--X4:w - - - + + + W3:e--X4:w - - - + + + -

Bill of Materials

ItemQtyUnitDesignators
Connector, Molex Micro-Fit, female, 2 pins3X2, X3, X4
Connector, Molex Micro-Fit, male, 2 pins1X1
Cable, 2 x 0.25 mm²0.4mW1, W2
Cable, 2 x 20 awg0.2mW3
\ No newline at end of file +

Bill of Materials

ItemQtyUnitDesignators
Connector, Molex Micro-Fit, female, 2 pins3X2, X3, X4
Connector, Molex Micro-Fit, male, 2 pins1X1
Cable, 2 x 0.25 mm²0.4mW1, W2
Cable, 2 x 20 AWG0.2mW3
\ No newline at end of file diff --git a/examples/ex02.png b/examples/ex02.png index 0a989728918b3f997fa1dddbccad0cc1cb512f00..28d54ebe08b77d02993e1a9118f5071e1615b55e 100644 GIT binary patch literal 81326 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 }2UTR6am7SZrxwyF4xGr!TrRVI|NCTBms^&+$ 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¨qSSJN?qw;Q%<<>uL3;@sA)!U} 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 AWB>pF literal 86866 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

%^!sPWwxjuny2Hrq(iGA) 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 Q@R!9X>yf9-X0H4H0Lqki4FCWD literal 81203 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 }2UTR6am7SZrxwyF4xGr!TrRVI|NCTBms^&+$ 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¨qSSJN?qw;Q%<<>uL3;@sA)!U} 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[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 - W3 - - -W3 - -2x - -0.25 mm² (24 AWG) - -0.2 m -  -X1:1 -BK -X4:1 - - - -X1:2 -RD -X4:2 - - - -  + + +W3 + +2x + +20 awg (0.75 mm²) + +0.2 m +  +X1:1 +BK +X4:1 + + + +X1:2 +RD +X4:2 + + + +  X1:e--W3:w - - - + + + X1:e--W3:w - - - + + + @@ -242,16 +242,16 @@ W3:e--X4:w - - - + + + W3:e--X4:w - - - + + + diff --git a/examples/ex02.yml b/examples/ex02.yml index 056e6fe..8a671e6 100644 --- a/examples/ex02.yml +++ b/examples/ex02.yml @@ -22,6 +22,7 @@ cables: <<: *wire_power # create from template W3: <<: *wire_power # create from template + gauge: 20 awg connections: - diff --git a/src/wireviz/DataClasses.py b/src/wireviz/DataClasses.py index a2f2a9e..6bc9eb8 100644 --- a/src/wireviz/DataClasses.py +++ b/src/wireviz/DataClasses.py @@ -83,7 +83,12 @@ class Cable: except Exception: raise Exception('Gauge must be a number, or number and unit separated by a space') self.gauge = g - self.gauge_unit = u.replace('mm2', 'mm\u00B2') + + if u.upper() == 'AWG': + self.gauge_unit = u.upper() + else: + self.gauge_unit = u.replace('mm2', 'mm\u00B2') + elif self.gauge is not None: # gauge specified, assume mm2 if self.gauge_unit is None: self.gauge_unit = 'mm\u00B2' diff --git a/src/wireviz/Harness.py b/src/wireviz/Harness.py index c11ad9a..c50384e 100644 --- a/src/wireviz/Harness.py +++ b/src/wireviz/Harness.py @@ -4,7 +4,7 @@ from wireviz.DataClasses import Connector, Cable from graphviz import Graph from wireviz import wv_colors -from wireviz.wv_helper import awg_equiv, tuplelist2tsv, nested, flatten2d +from wireviz.wv_helper import awg_equiv, mm2_equiv, tuplelist2tsv, nested, flatten2d from collections import Counter from typing import List @@ -113,9 +113,19 @@ class Harness: f'{connector.name}:p{loop[1]}{loop_side}:{loop_dir}') for _, cable in self.cables.items(): - awg_fmt = f' ({awg_equiv(cable.gauge)} AWG)' if cable.gauge_unit == 'mm\u00B2' and cable.show_equiv else '' + + awg_fmt = '' + if cable.show_equiv: + # Only convert units we actually know about, i.e. currently + # mm2 and awg --- other units _are_ technically allowed, + # and passed through as-is. + if cable.gauge_unit =='mm\u00B2': + awg_fmt = f' ({awg_equiv(cable.gauge)} AWG)' + elif cable.gauge_unit.upper() == 'AWG': + awg_fmt = f' ({mm2_equiv(cable.gauge)} mm\u00B2)' + attributes = [f'{len(cable.colors)}x' if cable.show_wirecount else '', - f'{cable.gauge} {cable.gauge_unit}{awg_fmt}' if cable.gauge else '', # TODO: show equiv + f'{cable.gauge} {cable.gauge_unit}{awg_fmt}' if cable.gauge else '', '+ S' if cable.shield else '', f'{cable.length} m' if cable.length > 0 else ''] attributes = list(filter(None, attributes)) diff --git a/src/wireviz/wv_helper.py b/src/wireviz/wv_helper.py index 65ccdb3..222fd74 100644 --- a/src/wireviz/wv_helper.py +++ b/src/wireviz/wv_helper.py @@ -3,32 +3,32 @@ from typing import List +awg_equiv_table = { + '0.09': '28', + '0.14': '26', + '0.25': '24', + '0.34': '22', + '0.5': '21', + '0.75': '20', + '1': '18', + '1.5': '16', + '2.5': '14', + '4': '12', + '6': '10', + '10': '8', + '16': '6', + '25': '4', + '35': '2', + '50': '1', +} + +mm2_equiv_table = {v:k for k,v in awg_equiv_table.items()} def awg_equiv(mm2): - awg_equiv_table = { - '0.09': 28, - '0.14': 26, - '0.25': 24, - '0.34': 22, - '0.5': 21, - '0.75': 20, - '1': 18, - '1.5': 16, - '2.5': 14, - '4': 12, - '6': 10, - '10': 8, - '16': 6, - '25': 4, - '35': 2, - '50': 1, - } - k = str(mm2) - if k in awg_equiv_table: - return awg_equiv_table[k] - else: - return 'unknown' + return awg_equiv_table.get(str(mm2), 'Unknown') +def mm2_equiv(awg): + return mm2_equiv_table.get(str(awg), 'Unknown') def nested(inp): l = [] From 52a8af298d73da8e16b44cbb91447ae5095689d7 Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Mon, 29 Jun 2020 14:44:44 +0200 Subject: [PATCH 30/35] Rebuild example 02 after fixes from #41 --- examples/ex02.bom.tsv | 2 +- examples/ex02.gv | 2 +- examples/ex02.html | 74 +++++++++++++++++++++--------------------- examples/ex02.png | Bin 86866 -> 81326 bytes examples/ex02.svg | 72 ++++++++++++++++++++-------------------- 5 files changed, 75 insertions(+), 75 deletions(-) diff --git a/examples/ex02.bom.tsv b/examples/ex02.bom.tsv index a85de3e..67cb7f0 100644 --- a/examples/ex02.bom.tsv +++ b/examples/ex02.bom.tsv @@ -2,4 +2,4 @@ Item Qty Unit Designators Connector, Molex Micro-Fit, female, 2 pins 3 X2, X3, X4 Connector, Molex Micro-Fit, male, 2 pins 1 X1 Cable, 2 x 0.25 mm² 0.4 m W1, W2 -Cable, 2 x 20 awg 0.2 m W3 +Cable, 2 x 20 AWG 0.2 m W3 diff --git a/examples/ex02.gv b/examples/ex02.gv index 030934d..8f29aaf 100644 --- a/examples/ex02.gv +++ b/examples/ex02.gv @@ -28,5 +28,5 @@ graph { edge [color="#000000:#ff0000:#000000"] X1:p2r:e -- W3:w2:w W3:w2:e -- X4:p2l:w - W3 [label=<
W3
2x20 awg (0.75 mm²)0.2 m
 
X1:1BKX4:1
X1:2RDX4:2
 
> fillcolor=white margin=0 shape=box style=""] + W3 [label=<
W3
2x20 AWG (0.75 mm²)0.2 m
 
X1:1BKX4:1
X1:2RDX4:2
 
> fillcolor=white margin=0 shape=box style=""] } diff --git a/examples/ex02.html b/examples/ex02.html index aafa0e9..be3f0ab 100644 --- a/examples/ex02.html +++ b/examples/ex02.html @@ -1,7 +1,7 @@

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

%^!sPWwxjuny2Hrq(iGA) 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 Q@R!9X>yf9-X0H4H0Lqki4FCWD diff --git a/examples/ex02.svg b/examples/ex02.svg index fe7e3a1..5de828e 100644 --- a/examples/ex02.svg +++ b/examples/ex02.svg @@ -1,7 +1,7 @@ - W3 - - -W3 - -2x - -20 awg (0.75 mm²) - -0.2 m -  -X1:1 -BK -X4:1 - - - -X1:2 -RD -X4:2 - - - -  + + +W3 + +2x + +20 AWG (0.75 mm²) + +0.2 m +  +X1:1 +BK +X4:1 + + + +X1:2 +RD +X4:2 + + + +  X1:e--W3:w - - - + + + X1:e--W3:w - - - + + + @@ -242,16 +242,16 @@ W3:e--X4:w - - - + + + W3:e--X4:w - - - + + + From e047f06b6d8eef8403999a2ca1de095834a6d217 Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Mon, 29 Jun 2020 14:54:06 +0200 Subject: [PATCH 31/35] Update readme to reflect changes from #41 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3b90b58..abf8db7 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ WireViz is a tool for easily documenting cables, wiring harnesses and connector * [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/...) * Understands wire gauge in mm² or AWG - * Optionally auto-calculates and displays AWG equivalent when specifying mm² + * Optionally auto-calculates equivalent gauge between mm² and AWG * Allows more than one connector per side, as well as loopbacks * Allows for easy-autorouting for 1-to-1 wiring * Generates BOM (Bill of Materials) From 9d2c193533aa4b39b4712558c33f4c85b5b819de Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Mon, 29 Jun 2020 17:46:45 +0200 Subject: [PATCH 32/35] Update example 08 to hide pincount on 3.5mm jack --- examples/ex08.gv | 2 +- examples/ex08.html | 122 ++++++++++++++++++++++----------------------- examples/ex08.png | Bin 32765 -> 32397 bytes examples/ex08.svg | 122 ++++++++++++++++++++++----------------------- examples/ex08.yml | 1 + 5 files changed, 122 insertions(+), 125 deletions(-) diff --git a/examples/ex08.gv b/examples/ex08.gv index a949333..2e189bb 100644 --- a/examples/ex08.gv +++ b/examples/ex08.gv @@ -4,7 +4,7 @@ graph { graph [bgcolor=white fontname=arial nodesep=0.33 rankdir=LR ranksep=2] node [fillcolor=white fontname=arial shape=record style=filled] edge [fontname=arial style=bold] - Key [label="Key|{Phone Connector|male 3.5|3-pin}|{{Dot|Dash|Ground}|{T|R|S}}"] + Key [label="Key|{Phone Connector|male 3.5}|{{Dot|Dash|Ground}|{T|R|S}}"] edge [color="#000000:#ffffff:#000000"] Key:pSr:e -- W1:w1:w edge [color="#000000:#666600:#000000"] diff --git a/examples/ex08.html b/examples/ex08.html index c290a0f..854d239 100644 --- a/examples/ex08.html +++ b/examples/ex08.html @@ -4,95 +4,93 @@ - + - + Key - -Key - + +Key + Phone Connector male 3.5 - -3-pin - -Dot - -Dash - -Ground - -T - -R - -S + +Dot + +Dash + +Ground + +T + +R + +S W1 - - -W1 - -3x - -24 AWG - -+ S - -0.2 m -  -Key:S -WH - - - -Key:R -BN - - - -Key:T -GN - - - -  -Key:S -Shield - -  + + +W1 + +3x + +24 AWG + ++ S + +0.2 m +  +Key:S +WH + + + +Key:R +BN + + + +Key:T +GN + + + +  +Key:S +Shield + +  Key:e--W1:w - - - + + + Key:e--W1:w - - - + + + Key:e--W1:w - - - + + + Key:e--W1:w - + diff --git a/examples/ex08.png b/examples/ex08.png index a0270f7852119679d541317f85eddb1891db9896..7767320d96c6a9a587f0c3171e43d71d37aeb83b 100644 GIT binary patch literal 32397 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 XS=pz~Y6#~a3tZL~w&vMp9_#-PV|#Js literal 32765 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 C7gcQl diff --git a/examples/ex08.svg b/examples/ex08.svg index 0599c11..630f541 100644 --- a/examples/ex08.svg +++ b/examples/ex08.svg @@ -4,95 +4,93 @@ - + - + Key - -Key - + +Key + Phone Connector male 3.5 - -3-pin - -Dot - -Dash - -Ground - -T - -R - -S + +Dot + +Dash + +Ground + +T + +R + +S W1 - - -W1 - -3x - -24 AWG - -+ S - -0.2 m -  -Key:S -WH - - - -Key:R -BN - - - -Key:T -GN - - - -  -Key:S -Shield - -  + + +W1 + +3x + +24 AWG + ++ S + +0.2 m +  +Key:S +WH + + + +Key:R +BN + + + +Key:T +GN + + + +  +Key:S +Shield + +  Key:e--W1:w - - - + + + Key:e--W1:w - - - + + + Key:e--W1:w - - - + + + Key:e--W1:w - + diff --git a/examples/ex08.yml b/examples/ex08.yml index 0d42be5..e65813a 100644 --- a/examples/ex08.yml +++ b/examples/ex08.yml @@ -6,6 +6,7 @@ connectors: subtype: male 3.5 pinnumbers: [T, R, S] pinout: [Dot, Dash, Ground] + show_pincount: false cables: W1: From 23e22f5249984fda57b65861b1c6a0621c7a0a2e Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Tue, 30 Jun 2020 13:53:54 +0200 Subject: [PATCH 33/35] Reorder readme --- README.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index abf8db7..43754fe 100644 --- a/README.md +++ b/README.md @@ -88,14 +88,6 @@ Output file: 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. -### (Re-)Building the example projects - -If you would like to rebuild all of the included demos, examples and tutorials, use the ```build_examples.py``` script: - -```cd src/wireviz -./build_examples.py -``` - ## Usage ``` @@ -112,6 +104,13 @@ 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 + +If you would like to rebuild all of the included demos, examples and tutorials, use the ```build_examples.py``` script: + +```cd src/wireviz +./build_examples.py +``` ## 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. From b163b7a586cb55f6f3dffdcc12f7ea922e24da6a Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Tue, 30 Jun 2020 14:10:32 +0200 Subject: [PATCH 34/35] Update .gitignore to include venv/ directory --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index c121d2f..cc614ad 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ __pycache__ build data dist +venv/ From 49322fc65ff22a4e520850bc4a868a86268eaed9 Mon Sep 17 00:00:00 2001 From: Daniel Rojas Date: Tue, 30 Jun 2020 17:35:03 +0200 Subject: [PATCH 35/35] Fix demo 01 --- README.md | 2 +- examples/demo01.gv | 4 ++-- examples/demo01.html | 8 ++++---- examples/demo01.png | Bin 48678 -> 45870 bytes examples/demo01.svg | 8 ++++---- examples/demo01.yml | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 43754fe..b96dd42 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ cables: connections: - - - X1: [5,2,1] + - X1: [5,2,3] - W1: [1,2,3] - X2: [1,3,2] - diff --git a/examples/demo01.gv b/examples/demo01.gv index 24abe51..09194a3 100644 --- a/examples/demo01.gv +++ b/examples/demo01.gv @@ -13,9 +13,9 @@ graph { X1:p2r:e -- W1:w2:w W1:w2:e -- X2:p3l:w edge [color="#000000:#00ff00:#000000"] - X1:p1r:e -- W1:w3:w + X1:p3r:e -- W1:w3:w W1:w3:e -- X2:p2l:w edge [color="#000000"] X1:p5r:e -- W1:ws:w - W1 [label=<
W1
3x0.25 mm²+ S0.2 m
 
X1:5WHX2:1
X1:2BNX2:3
X1:1GNX2:2
 
X1:5Shield
 
> fillcolor=white margin=0 shape=box style=""] + W1 [label=<
W1
3x0.25 mm²+ S0.2 m
 
X1:5WHX2:1
X1:2BNX2:3
X1:3GNX2:2
 
X1:5Shield
 
> fillcolor=white margin=0 shape=box style=""] } diff --git a/examples/demo01.html b/examples/demo01.html index cfedd06..d5231e0 100644 --- a/examples/demo01.html +++ b/examples/demo01.html @@ -83,7 +83,7 @@ -X1:1 +X1:3 GN X2:2 @@ -112,9 +112,9 @@ X1:e--W1:w - - - + + + diff --git a/examples/demo01.png b/examples/demo01.png index 6e56db1bed6392d55c2a3702789d41eb9935f01b..77efff4a839165c4572264e0a4303259be3495ce 100644 GIT binary patch literal 45870 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 z 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 RvXkGgwNGEYSk*4%{{uer@<;#x literal 48678 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

YjkwYCi5eM}0 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 diff --git a/examples/demo01.svg b/examples/demo01.svg index bc7b2f9..517d58e 100644 --- a/examples/demo01.svg +++ b/examples/demo01.svg @@ -83,7 +83,7 @@ -X1:1 +X1:3 GN X2:2 @@ -112,9 +112,9 @@ X1:e--W1:w - - - + + + diff --git a/examples/demo01.yml b/examples/demo01.yml index b125176..ae1b4a5 100644 --- a/examples/demo01.yml +++ b/examples/demo01.yml @@ -18,7 +18,7 @@ cables: connections: - - - X1: [5,2,1] + - X1: [5,2,3] - W1: [1,2,3] - X2: [1,3,2] -