Merge branch 'dev' into feature-multicolor-wires
# Conflicts: # .gitignore # src/batch.py # src/wireviz.py # src/wv_colors.py
25
.github/workflows/main.yml
vendored
Normal file
@ -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
|
||||||
14
.gitignore
vendored
@ -1,12 +1,18 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
temp/
|
.eggs
|
||||||
|
__pycache__
|
||||||
|
.*.swp
|
||||||
|
*.egg-info
|
||||||
|
*.pyc
|
||||||
|
build
|
||||||
|
data
|
||||||
|
dist
|
||||||
|
venv/
|
||||||
|
|
||||||
.vscode/
|
.vscode/
|
||||||
|
|
||||||
.idea/
|
|
||||||
|
|
||||||
|
# Jetbrains Stuff
|
||||||
# IntelliJ Stuff
|
|
||||||
# Default ignored files
|
# Default ignored files
|
||||||
/shelf/
|
/shelf/
|
||||||
/workspace.xml
|
/workspace.xml
|
||||||
|
|||||||
@ -17,13 +17,25 @@ 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/...)
|
* [DIN 47100](https://en.wikipedia.org/wiki/DIN_47100) (WT/BN/GN/YE/GY/PK/BU/RD/BK/VT/...)
|
||||||
* [IEC 62](https://en.wikipedia.org/wiki/Electronic_color_code#Color_band_system) (BN/RD/OR/YE/GN/BU/VT/GY/WT/BK/...)
|
* [IEC 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
|
* 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 more than one connector per side, as well as loopbacks
|
||||||
* Allows for easy-autorouting for 1-to-1 wiring
|
* Allows for easy-autorouting for 1-to-1 wiring
|
||||||
* Generates BOM (Bill of Materials)
|
* Generates BOM (Bill of Materials)
|
||||||
|
|
||||||
_Note_: WireViz is not designed to represent the complete wiring of a system. Its main aim is to document the construction of individual wires and harnesses.
|
_Note_: WireViz is not designed to represent the complete wiring of a system. Its main aim is to document the construction of individual wires and harnesses.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
WireWiz requires GraphViz to be installed in order to work. See the [GraphViz download page](https://graphviz.org/download/) for OS-specific instructions.
|
||||||
|
|
||||||
|
Installation of the WireWiz package and its Python dependencies can be done using pip after cloning the repository:
|
||||||
|
|
||||||
|
```
|
||||||
|
git clone <repo url>
|
||||||
|
cd <working copy>
|
||||||
|
pip3 install -e .
|
||||||
|
```
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
### Demo 01
|
### Demo 01
|
||||||
@ -51,7 +63,7 @@ cables:
|
|||||||
|
|
||||||
connections:
|
connections:
|
||||||
-
|
-
|
||||||
- X1: [5,2,1]
|
- X1: [5,2,3]
|
||||||
- W1: [1,2,3]
|
- W1: [1,2,3]
|
||||||
- X2: [1,3,2]
|
- X2: [1,3,2]
|
||||||
-
|
-
|
||||||
@ -79,7 +91,7 @@ as well as the [example gallery](examples/readme.md) to see more of what WireViz
|
|||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
$ python3 wireviz.py ~/path/to/file/mywire.yml
|
$ wireviz ~/path/to/file/mywire.yml
|
||||||
```
|
```
|
||||||
|
|
||||||
This will output the following files
|
This will output the following files
|
||||||
@ -92,14 +104,23 @@ mywire.bom.tsv BOM (bill of materials) as tab-separated text file
|
|||||||
mywire.html HTML page with wiring diagram and BOM embedded
|
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
|
## 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](https://github.com/formatc1702/WireViz/projects/1). Source code, API, syntax and functionality may change wildly at any time.
|
||||||
|
|
||||||
## Requirements
|
## 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
|
## License
|
||||||
|
|
||||||
GNU GPLv3
|
GNU GPLv3
|
||||||
@ -1,4 +1,4 @@
|
|||||||
Item Qty Unit Designators
|
Item Qty Unit Designators
|
||||||
D-Sub, female, 9 pins 1 X1
|
Connector, D-Sub, female, 9 pins 1 X1
|
||||||
Molex KK 254, female, 3 pins 1 X2
|
Connector, Molex KK 254, female, 3 pins 1 X2
|
||||||
Cable 3 x 0.25 mm² shielded 0.2 m W1
|
Cable, 3 x 0.25 mm² shielded 0.2 m W1
|
||||||
|
|||||||
|
@ -13,9 +13,9 @@ graph {
|
|||||||
X1:p2r:e -- W1:w2:w
|
X1:p2r:e -- W1:w2:w
|
||||||
W1:w2:e -- X2:p3l:w
|
W1:w2:e -- X2:p3l:w
|
||||||
edge [color="#000000:#00ff00:#000000"]
|
edge [color="#000000:#00ff00:#000000"]
|
||||||
X1:p1r:e -- W1:w3:w
|
X1:p3r:e -- W1:w3:w
|
||||||
W1:w3:e -- X2:p2l:w
|
W1:w3:e -- X2:p2l:w
|
||||||
edge [color="#000000"]
|
edge [color="#000000"]
|
||||||
X1:p5r:e -- W1:ws:w
|
X1:p5r:e -- W1:ws:w
|
||||||
W1 [label=<<table border="0" cellspacing="0" cellpadding="0"><tr><td><table border="0" cellspacing="0" cellpadding="3" cellborder="1"><tr><td colspan="4">W1</td></tr><tr><td>3x</td><td>0.25 mm²</td><td>+ S</td><td>0.2 m</td></tr></table></td></tr><tr><td> </td></tr><tr><td><table border="0" cellspacing="0" cellborder="0"><tr><td>X1:5</td><td>WH</td><td>X2:1</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#ffffff" border="2" sides="tb" port="w1"></td></tr><tr><td>X1:2</td><td>BN</td><td>X2:3</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#666600" border="2" sides="tb" port="w2"></td></tr><tr><td>X1:1</td><td>GN</td><td>X2:2</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#00ff00" border="2" sides="tb" port="w3"></td></tr><tr><td> </td></tr><tr><td>X1:5</td><td>Shield</td><td><!-- s_out --></td></tr><tr><td colspan="3" cellpadding="0" height="6" border="2" sides="b" port="ws"></td></tr><tr><td> </td></tr></table></td></tr></table>> fillcolor=white margin=0 shape=box style=""]
|
W1 [label=<<table border="0" cellspacing="0" cellpadding="0"><tr><td><table border="0" cellspacing="0" cellpadding="3" cellborder="1"><tr><td colspan="4">W1</td></tr><tr><td>3x</td><td>0.25 mm²</td><td>+ S</td><td>0.2 m</td></tr></table></td></tr><tr><td> </td></tr><tr><td><table border="0" cellspacing="0" cellborder="0"><tr><td>X1:5</td><td>WH</td><td>X2:1</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#ffffff" border="2" sides="tb" port="w1"></td></tr><tr><td>X1:2</td><td>BN</td><td>X2:3</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#666600" border="2" sides="tb" port="w2"></td></tr><tr><td>X1:3</td><td>GN</td><td>X2:2</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#00ff00" border="2" sides="tb" port="w3"></td></tr><tr><td> </td></tr><tr><td>X1:5</td><td>Shield</td><td><!-- s_out --></td></tr><tr><td colspan="3" cellpadding="0" height="6" border="2" sides="b" port="ws"></td></tr><tr><td> </td></tr></table></td></tr></table>> fillcolor=white margin=0 shape=box style=""]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -83,7 +83,7 @@
|
|||||||
<polygon fill="#666600" stroke="transparent" stroke-width="2" points="304.5,-170 304.5,-176 467.5,-176 467.5,-170 304.5,-170"/>
|
<polygon fill="#666600" stroke="transparent" stroke-width="2" points="304.5,-170 304.5,-176 467.5,-176 467.5,-170 304.5,-170"/>
|
||||||
<polyline fill="none" stroke="black" stroke-width="2" points="305.5,-171 466.5,-171 "/>
|
<polyline fill="none" stroke="black" stroke-width="2" points="305.5,-171 466.5,-171 "/>
|
||||||
<polyline fill="none" stroke="black" stroke-width="2" points="466.5,-175 305.5,-175 "/>
|
<polyline fill="none" stroke="black" stroke-width="2" points="466.5,-175 305.5,-175 "/>
|
||||||
<text text-anchor="start" x="316" y="-156.8" font-family="arial" font-size="14.00">X1:1</text>
|
<text text-anchor="start" x="316" y="-156.8" font-family="arial" font-size="14.00">X1:3</text>
|
||||||
<text text-anchor="start" x="375" y="-156.8" font-family="arial" font-size="14.00">GN</text>
|
<text text-anchor="start" x="375" y="-156.8" font-family="arial" font-size="14.00">GN</text>
|
||||||
<text text-anchor="start" x="428" y="-156.8" font-family="arial" font-size="14.00">X2:2</text>
|
<text text-anchor="start" x="428" y="-156.8" font-family="arial" font-size="14.00">X2:2</text>
|
||||||
<polygon fill="#00ff00" stroke="transparent" stroke-width="2" points="304.5,-145 304.5,-151 467.5,-151 467.5,-145 304.5,-145"/>
|
<polygon fill="#00ff00" stroke="transparent" stroke-width="2" points="304.5,-145 304.5,-151 467.5,-151 467.5,-145 304.5,-145"/>
|
||||||
@ -112,9 +112,9 @@
|
|||||||
<!-- X1--W1 -->
|
<!-- X1--W1 -->
|
||||||
<g id="edge5" class="edge">
|
<g id="edge5" class="edge">
|
||||||
<title>X1:e--W1:w</title>
|
<title>X1:e--W1:w</title>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M160,-194C225.5,-195.63 234.57,-147.63 304,-146"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M160,-148C223.76,-148.02 239.75,-146.02 304,-146"/>
|
||||||
<path fill="none" stroke="#00ff00" stroke-width="2" d="M160,-196C227.46,-196 236.54,-148 304,-148"/>
|
<path fill="none" stroke="#00ff00" stroke-width="2" d="M160,-150C224.01,-150 239.99,-148 304,-148"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M160,-198C229.43,-196.37 238.5,-148.37 304,-150"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M160,-152C224.25,-151.98 240.24,-149.98 304,-150"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- X1--W1 -->
|
<!-- X1--W1 -->
|
||||||
<g id="edge7" class="edge">
|
<g id="edge7" class="edge">
|
||||||
@ -168,4 +168,4 @@
|
|||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
<h1>Bill of Materials</h1><table style="border:1px solid #000000; font-size: 14pt; border-spacing: 0px"><tr><th align="left" style="border:1px solid #000000; padding: 8px">Item</th><th align="left" style="border:1px solid #000000; padding: 8px">Qty</th><th align="left" style="border:1px solid #000000; padding: 8px">Unit</th><th align="left" style="border:1px solid #000000; padding: 8px">Designators</th></tr><tr><td style="border:1px solid #000000; padding: 4px">D-Sub, female, 9 pins</td><td align="right" style="border:1px solid #000000; padding: 4px">1</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px">X1</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Molex KK 254, female, 3 pins</td><td align="right" style="border:1px solid #000000; padding: 4px">1</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px">X2</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Cable 3 x 0.25 mm² shielded</td><td align="right" style="border:1px solid #000000; padding: 4px">0.2</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1</td></tr></table></body></html>
|
<h1>Bill of Materials</h1><table style="border:1px solid #000000; font-size: 14pt; border-spacing: 0px"><tr><th align="left" style="border:1px solid #000000; padding: 8px">Item</th><th align="left" style="border:1px solid #000000; padding: 8px">Qty</th><th align="left" style="border:1px solid #000000; padding: 8px">Unit</th><th align="left" style="border:1px solid #000000; padding: 8px">Designators</th></tr><tr><td style="border:1px solid #000000; padding: 4px">Connector, D-Sub, female, 9 pins</td><td align="right" style="border:1px solid #000000; padding: 4px">1</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px">X1</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Connector, Molex KK 254, female, 3 pins</td><td align="right" style="border:1px solid #000000; padding: 4px">1</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px">X2</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Cable, 3 x 0.25 mm² shielded</td><td align="right" style="border:1px solid #000000; padding: 4px">0.2</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1</td></tr></table></body></html>
|
||||||
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 45 KiB |
@ -83,7 +83,7 @@
|
|||||||
<polygon fill="#666600" stroke="transparent" stroke-width="2" points="304.5,-170 304.5,-176 467.5,-176 467.5,-170 304.5,-170"/>
|
<polygon fill="#666600" stroke="transparent" stroke-width="2" points="304.5,-170 304.5,-176 467.5,-176 467.5,-170 304.5,-170"/>
|
||||||
<polyline fill="none" stroke="black" stroke-width="2" points="305.5,-171 466.5,-171 "/>
|
<polyline fill="none" stroke="black" stroke-width="2" points="305.5,-171 466.5,-171 "/>
|
||||||
<polyline fill="none" stroke="black" stroke-width="2" points="466.5,-175 305.5,-175 "/>
|
<polyline fill="none" stroke="black" stroke-width="2" points="466.5,-175 305.5,-175 "/>
|
||||||
<text text-anchor="start" x="316" y="-156.8" font-family="arial" font-size="14.00">X1:1</text>
|
<text text-anchor="start" x="316" y="-156.8" font-family="arial" font-size="14.00">X1:3</text>
|
||||||
<text text-anchor="start" x="375" y="-156.8" font-family="arial" font-size="14.00">GN</text>
|
<text text-anchor="start" x="375" y="-156.8" font-family="arial" font-size="14.00">GN</text>
|
||||||
<text text-anchor="start" x="428" y="-156.8" font-family="arial" font-size="14.00">X2:2</text>
|
<text text-anchor="start" x="428" y="-156.8" font-family="arial" font-size="14.00">X2:2</text>
|
||||||
<polygon fill="#00ff00" stroke="transparent" stroke-width="2" points="304.5,-145 304.5,-151 467.5,-151 467.5,-145 304.5,-145"/>
|
<polygon fill="#00ff00" stroke="transparent" stroke-width="2" points="304.5,-145 304.5,-151 467.5,-151 467.5,-145 304.5,-145"/>
|
||||||
@ -112,9 +112,9 @@
|
|||||||
<!-- X1--W1 -->
|
<!-- X1--W1 -->
|
||||||
<g id="edge5" class="edge">
|
<g id="edge5" class="edge">
|
||||||
<title>X1:e--W1:w</title>
|
<title>X1:e--W1:w</title>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M160,-194C225.5,-195.63 234.57,-147.63 304,-146"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M160,-148C223.76,-148.02 239.75,-146.02 304,-146"/>
|
||||||
<path fill="none" stroke="#00ff00" stroke-width="2" d="M160,-196C227.46,-196 236.54,-148 304,-148"/>
|
<path fill="none" stroke="#00ff00" stroke-width="2" d="M160,-150C224.01,-150 239.99,-148 304,-148"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M160,-198C229.43,-196.37 238.5,-148.37 304,-150"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M160,-152C224.25,-151.98 240.24,-149.98 304,-150"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- X1--W1 -->
|
<!-- X1--W1 -->
|
||||||
<g id="edge7" class="edge">
|
<g id="edge7" class="edge">
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
@ -18,7 +18,7 @@ cables:
|
|||||||
|
|
||||||
connections:
|
connections:
|
||||||
-
|
-
|
||||||
- X1: [5,2,1]
|
- X1: [5,2,3]
|
||||||
- W1: [1,2,3]
|
- W1: [1,2,3]
|
||||||
- X2: [1,3,2]
|
- X2: [1,3,2]
|
||||||
-
|
-
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
Item Qty Unit Designators
|
Item Qty Unit Designators
|
||||||
Crimp ferrule, 0.25 mm² 2
|
Connector, Crimp ferrule, 0.25 mm² 2
|
||||||
Molex KK 254, female, 4 pins 2 X2, X3
|
Connector, Molex KK 254, female, 4 pins 2 X2, X3
|
||||||
Molex KK 254, female, 5 pins 1 X4
|
Connector, Molex KK 254, female, 5 pins 1 X4
|
||||||
Molex KK 254, female, 8 pins 1 X1
|
Connector, Molex KK 254, female, 8 pins 1 X1
|
||||||
Cable 2 x 0.25 mm² 0.3 m W4
|
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², BK 0.9 m W1, W2, W3
|
||||||
Wire 0.14 mm² BU 0.3 m W3
|
Wire, 0.14 mm², BU 0.3 m W3
|
||||||
Wire 0.14 mm² GN 0.6 m W1, W2
|
Wire, 0.14 mm², GN 0.6 m W1, W2
|
||||||
Wire 0.14 mm² OG 0.3 m W3
|
Wire, 0.14 mm², OG 0.3 m W3
|
||||||
Wire 0.14 mm² RD 0.6 m W1, W2
|
Wire, 0.14 mm², RD 0.6 m W1, W2
|
||||||
Wire 0.14 mm² VT 0.3 m W3
|
Wire, 0.14 mm², VT 0.3 m W3
|
||||||
Wire 0.14 mm² YE 0.6 m W1, W2
|
Wire, 0.14 mm², YE 0.6 m W1, W2
|
||||||
|
|||||||
|
@ -8,7 +8,7 @@ graph {
|
|||||||
X2 [label="X2|{Molex KK 254|female|4-pin}|{{<p1l>1|<p2l>2|<p3l>3|<p4l>4}|{GND|+5V|SCL|SDA}}"]
|
X2 [label="X2|{Molex KK 254|female|4-pin}|{{<p1l>1|<p2l>2|<p3l>3|<p4l>4}|{GND|+5V|SCL|SDA}}"]
|
||||||
X3 [label="X3|{Molex KK 254|female|4-pin}|{{<p1l>1|<p2l>2|<p3l>3|<p4l>4}|{GND|+5V|SCL|SDA}}"]
|
X3 [label="X3|{Molex KK 254|female|4-pin}|{{<p1l>1|<p2l>2|<p3l>3|<p4l>4}|{GND|+5V|SCL|SDA}}"]
|
||||||
X4 [label="X4|{Molex KK 254|female|5-pin}|{{<p1l>1|<p2l>2|<p3l>3|<p4l>4|<p5l>5}|{GND|+12V|MISO|MOSI|SCK}}"]
|
X4 [label="X4|{Molex KK 254|female|5-pin}|{{<p1l>1|<p2l>2|<p3l>3|<p4l>4|<p5l>5}|{GND|+12V|MISO|MOSI|SCK}}"]
|
||||||
F1 [label=<
|
_F1 [label=<
|
||||||
|
|
||||||
<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="2"><TR>
|
<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="2"><TR>
|
||||||
<TD PORT="p1l"> Crimp ferrule, 0.25 mm² </TD>
|
<TD PORT="p1l"> Crimp ferrule, 0.25 mm² </TD>
|
||||||
@ -18,7 +18,7 @@ graph {
|
|||||||
|
|
||||||
|
|
||||||
> margin=0 orientation=180 shape=none style=filled]
|
> margin=0 orientation=180 shape=none style=filled]
|
||||||
F2 [label=<
|
_F2 [label=<
|
||||||
|
|
||||||
<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="2"><TR>
|
<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="2"><TR>
|
||||||
<TD PORT="p1l"> Crimp ferrule, 0.25 mm² </TD>
|
<TD PORT="p1l"> Crimp ferrule, 0.25 mm² </TD>
|
||||||
@ -68,9 +68,9 @@ graph {
|
|||||||
W3:w4:e -- X4:p5l:w
|
W3:w4:e -- X4:p5l:w
|
||||||
W3 [label=<<table border="0" cellspacing="0" cellpadding="0"><tr><td><table border="0" cellspacing="0" cellpadding="3" cellborder="1"><tr><td colspan="3">W3</td></tr><tr><td>4x</td><td>0.14 mm² (26 AWG)</td><td>0.3 m</td></tr></table></td></tr><tr><td> </td></tr><tr><td><table border="0" cellspacing="0" cellborder="0"><tr><td>X1:1</td><td>BK</td><td>X4:1</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#000000" border="2" sides="tb" port="w1"></td></tr><tr><td>X1:5</td><td>BU</td><td>X4:3</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#0066ff" border="2" sides="tb" port="w2"></td></tr><tr><td>X1:6</td><td>OG</td><td>X4:4</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#ff8000" border="2" sides="tb" port="w3"></td></tr><tr><td>X1:7</td><td>VT</td><td>X4:5</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#8000ff" border="2" sides="tb" port="w4"></td></tr><tr><td> </td></tr></table></td></tr></table>> fillcolor=white margin=0 shape=box style="filled,dashed"]
|
W3 [label=<<table border="0" cellspacing="0" cellpadding="0"><tr><td><table border="0" cellspacing="0" cellpadding="3" cellborder="1"><tr><td colspan="3">W3</td></tr><tr><td>4x</td><td>0.14 mm² (26 AWG)</td><td>0.3 m</td></tr></table></td></tr><tr><td> </td></tr><tr><td><table border="0" cellspacing="0" cellborder="0"><tr><td>X1:1</td><td>BK</td><td>X4:1</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#000000" border="2" sides="tb" port="w1"></td></tr><tr><td>X1:5</td><td>BU</td><td>X4:3</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#0066ff" border="2" sides="tb" port="w2"></td></tr><tr><td>X1:6</td><td>OG</td><td>X4:4</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#ff8000" border="2" sides="tb" port="w3"></td></tr><tr><td>X1:7</td><td>VT</td><td>X4:5</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#8000ff" border="2" sides="tb" port="w4"></td></tr><tr><td> </td></tr></table></td></tr></table>> fillcolor=white margin=0 shape=box style="filled,dashed"]
|
||||||
edge [color="#000000:#000000:#000000"]
|
edge [color="#000000:#000000:#000000"]
|
||||||
F1:e -- W4:w1:w
|
_F1:e -- W4:w1:w
|
||||||
edge [color="#000000:#ff0000:#000000"]
|
edge [color="#000000:#ff0000:#000000"]
|
||||||
F2:e -- W4:w2:w
|
_F2:e -- W4:w2:w
|
||||||
edge [color="#000000:#000000:#000000"]
|
edge [color="#000000:#000000:#000000"]
|
||||||
W4:w1:e -- X4:p1l:w
|
W4:w1:e -- X4:p1l:w
|
||||||
edge [color="#000000:#ff0000:#000000"]
|
edge [color="#000000:#ff0000:#000000"]
|
||||||
|
|||||||
@ -341,9 +341,9 @@
|
|||||||
<polyline fill="none" stroke="black" points="780,-191.5 898,-191.5 "/>
|
<polyline fill="none" stroke="black" points="780,-191.5 898,-191.5 "/>
|
||||||
<text text-anchor="middle" x="839" y="-176.3" font-family="arial" font-size="14.00">SCK</text>
|
<text text-anchor="middle" x="839" y="-176.3" font-family="arial" font-size="14.00">SCK</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- F1 -->
|
<!-- _F1 -->
|
||||||
<g id="node5" class="node">
|
<g id="node5" class="node">
|
||||||
<title>F1</title>
|
<title>_F1</title>
|
||||||
<polygon fill="white" stroke="transparent" points="15.5,-60 190.5,-60 190.5,-96 15.5,-96 15.5,-60"/>
|
<polygon fill="white" stroke="transparent" points="15.5,-60 190.5,-60 190.5,-96 15.5,-96 15.5,-60"/>
|
||||||
<text text-anchor="start" x="19" y="-73.8" font-family="arial" font-size="14.00"> Crimp ferrule, 0.25 mm²  </text>
|
<text text-anchor="start" x="19" y="-73.8" font-family="arial" font-size="14.00"> Crimp ferrule, 0.25 mm²  </text>
|
||||||
<text text-anchor="start" x="180" y="-73.8" font-family="arial" font-size="14.00">  </text>
|
<text text-anchor="start" x="180" y="-73.8" font-family="arial" font-size="14.00">  </text>
|
||||||
@ -374,24 +374,24 @@
|
|||||||
<polyline fill="none" stroke="black" stroke-width="2" points="547,-37 351,-37 "/>
|
<polyline fill="none" stroke="black" stroke-width="2" points="547,-37 351,-37 "/>
|
||||||
<text text-anchor="start" x="374.5" y="-18.8" font-family="arial" font-size="14.00"> </text>
|
<text text-anchor="start" x="374.5" y="-18.8" font-family="arial" font-size="14.00"> </text>
|
||||||
</g>
|
</g>
|
||||||
<!-- F1--W4 -->
|
<!-- _F1--W4 -->
|
||||||
<g id="edge25" class="edge">
|
<g id="edge25" class="edge">
|
||||||
<title>F1:e--W4:w</title>
|
<title>_F1:e--W4:w</title>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M192,-76C261.21,-76.64 277.86,-58.64 350,-58"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M192,-76C261.21,-76.64 277.86,-58.64 350,-58"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M192,-78C262.68,-78 279.32,-60 350,-60"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M192,-78C262.68,-78 279.32,-60 350,-60"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M192,-80C264.14,-79.36 280.79,-61.36 350,-62"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M192,-80C264.14,-79.36 280.79,-61.36 350,-62"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F2 -->
|
<!-- _F2 -->
|
||||||
<g id="node6" class="node">
|
<g id="node6" class="node">
|
||||||
<title>F2</title>
|
<title>_F2</title>
|
||||||
<polygon fill="white" stroke="transparent" points="15.5,0 190.5,0 190.5,-36 15.5,-36 15.5,0"/>
|
<polygon fill="white" stroke="transparent" points="15.5,0 190.5,0 190.5,-36 15.5,-36 15.5,0"/>
|
||||||
<text text-anchor="start" x="19" y="-13.8" font-family="arial" font-size="14.00"> Crimp ferrule, 0.25 mm²  </text>
|
<text text-anchor="start" x="19" y="-13.8" font-family="arial" font-size="14.00"> Crimp ferrule, 0.25 mm²  </text>
|
||||||
<text text-anchor="start" x="180" y="-13.8" font-family="arial" font-size="14.00">  </text>
|
<text text-anchor="start" x="180" y="-13.8" font-family="arial" font-size="14.00">  </text>
|
||||||
<polygon fill="none" stroke="black" points="15.5,-7.5 15.5,-28.5 190.5,-28.5 190.5,-7.5 15.5,-7.5"/>
|
<polygon fill="none" stroke="black" points="15.5,-7.5 15.5,-28.5 190.5,-28.5 190.5,-7.5 15.5,-7.5"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F2--W4 -->
|
<!-- _F2--W4 -->
|
||||||
<g id="edge26" class="edge">
|
<g id="edge26" class="edge">
|
||||||
<title>F2:e--W4:w</title>
|
<title>_F2:e--W4:w</title>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M192,-16C264.05,-16.6 280.8,-33.6 350,-33"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M192,-16C264.05,-16.6 280.8,-33.6 350,-33"/>
|
||||||
<path fill="none" stroke="#ff0000" stroke-width="2" d="M192,-18C262.63,-18 279.37,-35 350,-35"/>
|
<path fill="none" stroke="#ff0000" stroke-width="2" d="M192,-18C262.63,-18 279.37,-35 350,-35"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M192,-20C261.2,-19.4 277.95,-36.4 350,-37"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M192,-20C261.2,-19.4 277.95,-36.4 350,-37"/>
|
||||||
@ -496,4 +496,4 @@
|
|||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
<h1>Bill of Materials</h1><table style="border:1px solid #000000; font-size: 14pt; border-spacing: 0px"><tr><th align="left" style="border:1px solid #000000; padding: 8px">Item</th><th align="left" style="border:1px solid #000000; padding: 8px">Qty</th><th align="left" style="border:1px solid #000000; padding: 8px">Unit</th><th align="left" style="border:1px solid #000000; padding: 8px">Designators</th></tr><tr><td style="border:1px solid #000000; padding: 4px">Crimp ferrule, 0.25 mm²</td><td align="right" style="border:1px solid #000000; padding: 4px">2</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px"></td></tr><tr><td style="border:1px solid #000000; padding: 4px">Molex KK 254, female, 4 pins</td><td align="right" style="border:1px solid #000000; padding: 4px">2</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px">X2, X3</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Molex KK 254, female, 5 pins</td><td align="right" style="border:1px solid #000000; padding: 4px">1</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px">X4</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Molex KK 254, female, 8 pins</td><td align="right" style="border:1px solid #000000; padding: 4px">1</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px">X1</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Cable 2 x 0.25 mm²</td><td align="right" style="border:1px solid #000000; padding: 4px">0.3</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W4</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire 0.14 mm² BK</td><td align="right" style="border:1px solid #000000; padding: 4px">0.9</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1, W2, W3</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire 0.14 mm² BU</td><td align="right" style="border:1px solid #000000; padding: 4px">0.3</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W3</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire 0.14 mm² GN</td><td align="right" style="border:1px solid #000000; padding: 4px">0.6</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1, W2</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire 0.14 mm² OG</td><td align="right" style="border:1px solid #000000; padding: 4px">0.3</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W3</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire 0.14 mm² RD</td><td align="right" style="border:1px solid #000000; padding: 4px">0.6</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1, W2</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire 0.14 mm² VT</td><td align="right" style="border:1px solid #000000; padding: 4px">0.3</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W3</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire 0.14 mm² YE</td><td align="right" style="border:1px solid #000000; padding: 4px">0.6</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1, W2</td></tr></table></body></html>
|
<h1>Bill of Materials</h1><table style="border:1px solid #000000; font-size: 14pt; border-spacing: 0px"><tr><th align="left" style="border:1px solid #000000; padding: 8px">Item</th><th align="left" style="border:1px solid #000000; padding: 8px">Qty</th><th align="left" style="border:1px solid #000000; padding: 8px">Unit</th><th align="left" style="border:1px solid #000000; padding: 8px">Designators</th></tr><tr><td style="border:1px solid #000000; padding: 4px">Connector, Crimp ferrule, 0.25 mm²</td><td align="right" style="border:1px solid #000000; padding: 4px">2</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px"></td></tr><tr><td style="border:1px solid #000000; padding: 4px">Connector, Molex KK 254, female, 4 pins</td><td align="right" style="border:1px solid #000000; padding: 4px">2</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px">X2, X3</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Connector, Molex KK 254, female, 5 pins</td><td align="right" style="border:1px solid #000000; padding: 4px">1</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px">X4</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Connector, Molex KK 254, female, 8 pins</td><td align="right" style="border:1px solid #000000; padding: 4px">1</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px">X1</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Cable, 2 x 0.25 mm²</td><td align="right" style="border:1px solid #000000; padding: 4px">0.3</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W4</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire, 0.14 mm², BK</td><td align="right" style="border:1px solid #000000; padding: 4px">0.9</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1, W2, W3</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire, 0.14 mm², BU</td><td align="right" style="border:1px solid #000000; padding: 4px">0.3</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W3</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire, 0.14 mm², GN</td><td align="right" style="border:1px solid #000000; padding: 4px">0.6</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1, W2</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire, 0.14 mm², OG</td><td align="right" style="border:1px solid #000000; padding: 4px">0.3</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W3</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire, 0.14 mm², RD</td><td align="right" style="border:1px solid #000000; padding: 4px">0.6</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1, W2</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire, 0.14 mm², VT</td><td align="right" style="border:1px solid #000000; padding: 4px">0.3</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W3</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire, 0.14 mm², YE</td><td align="right" style="border:1px solid #000000; padding: 4px">0.6</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1, W2</td></tr></table></body></html>
|
||||||
@ -341,9 +341,9 @@
|
|||||||
<polyline fill="none" stroke="black" points="780,-191.5 898,-191.5 "/>
|
<polyline fill="none" stroke="black" points="780,-191.5 898,-191.5 "/>
|
||||||
<text text-anchor="middle" x="839" y="-176.3" font-family="arial" font-size="14.00">SCK</text>
|
<text text-anchor="middle" x="839" y="-176.3" font-family="arial" font-size="14.00">SCK</text>
|
||||||
</g>
|
</g>
|
||||||
<!-- F1 -->
|
<!-- _F1 -->
|
||||||
<g id="node5" class="node">
|
<g id="node5" class="node">
|
||||||
<title>F1</title>
|
<title>_F1</title>
|
||||||
<polygon fill="white" stroke="transparent" points="15.5,-60 190.5,-60 190.5,-96 15.5,-96 15.5,-60"/>
|
<polygon fill="white" stroke="transparent" points="15.5,-60 190.5,-60 190.5,-96 15.5,-96 15.5,-60"/>
|
||||||
<text text-anchor="start" x="19" y="-73.8" font-family="arial" font-size="14.00"> Crimp ferrule, 0.25 mm²  </text>
|
<text text-anchor="start" x="19" y="-73.8" font-family="arial" font-size="14.00"> Crimp ferrule, 0.25 mm²  </text>
|
||||||
<text text-anchor="start" x="180" y="-73.8" font-family="arial" font-size="14.00">  </text>
|
<text text-anchor="start" x="180" y="-73.8" font-family="arial" font-size="14.00">  </text>
|
||||||
@ -374,24 +374,24 @@
|
|||||||
<polyline fill="none" stroke="black" stroke-width="2" points="547,-37 351,-37 "/>
|
<polyline fill="none" stroke="black" stroke-width="2" points="547,-37 351,-37 "/>
|
||||||
<text text-anchor="start" x="374.5" y="-18.8" font-family="arial" font-size="14.00"> </text>
|
<text text-anchor="start" x="374.5" y="-18.8" font-family="arial" font-size="14.00"> </text>
|
||||||
</g>
|
</g>
|
||||||
<!-- F1--W4 -->
|
<!-- _F1--W4 -->
|
||||||
<g id="edge25" class="edge">
|
<g id="edge25" class="edge">
|
||||||
<title>F1:e--W4:w</title>
|
<title>_F1:e--W4:w</title>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M192,-76C261.21,-76.64 277.86,-58.64 350,-58"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M192,-76C261.21,-76.64 277.86,-58.64 350,-58"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M192,-78C262.68,-78 279.32,-60 350,-60"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M192,-78C262.68,-78 279.32,-60 350,-60"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M192,-80C264.14,-79.36 280.79,-61.36 350,-62"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M192,-80C264.14,-79.36 280.79,-61.36 350,-62"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F2 -->
|
<!-- _F2 -->
|
||||||
<g id="node6" class="node">
|
<g id="node6" class="node">
|
||||||
<title>F2</title>
|
<title>_F2</title>
|
||||||
<polygon fill="white" stroke="transparent" points="15.5,0 190.5,0 190.5,-36 15.5,-36 15.5,0"/>
|
<polygon fill="white" stroke="transparent" points="15.5,0 190.5,0 190.5,-36 15.5,-36 15.5,0"/>
|
||||||
<text text-anchor="start" x="19" y="-13.8" font-family="arial" font-size="14.00"> Crimp ferrule, 0.25 mm²  </text>
|
<text text-anchor="start" x="19" y="-13.8" font-family="arial" font-size="14.00"> Crimp ferrule, 0.25 mm²  </text>
|
||||||
<text text-anchor="start" x="180" y="-13.8" font-family="arial" font-size="14.00">  </text>
|
<text text-anchor="start" x="180" y="-13.8" font-family="arial" font-size="14.00">  </text>
|
||||||
<polygon fill="none" stroke="black" points="15.5,-7.5 15.5,-28.5 190.5,-28.5 190.5,-7.5 15.5,-7.5"/>
|
<polygon fill="none" stroke="black" points="15.5,-7.5 15.5,-28.5 190.5,-28.5 190.5,-7.5 15.5,-7.5"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F2--W4 -->
|
<!-- _F2--W4 -->
|
||||||
<g id="edge26" class="edge">
|
<g id="edge26" class="edge">
|
||||||
<title>F2:e--W4:w</title>
|
<title>_F2:e--W4:w</title>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M192,-16C264.05,-16.6 280.8,-33.6 350,-33"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M192,-16C264.05,-16.6 280.8,-33.6 350,-33"/>
|
||||||
<path fill="none" stroke="#ff0000" stroke-width="2" d="M192,-18C262.63,-18 279.37,-35 350,-35"/>
|
<path fill="none" stroke="#ff0000" stroke-width="2" d="M192,-18C262.63,-18 279.37,-35 350,-35"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M192,-20C261.2,-19.4 277.95,-36.4 350,-37"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M192,-20C261.2,-19.4 277.95,-36.4 350,-37"/>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
@ -1,3 +1,3 @@
|
|||||||
Item Qty Unit Designators
|
Item Qty Unit Designators
|
||||||
Molex KK 254, female, 4 pins 2 X1, X2
|
Connector, Molex KK 254, female, 4 pins 2 X1, X2
|
||||||
Cable 4 x 0.25 mm² shielded 0.2 m W1
|
Cable, 4 x 0.25 mm² shielded 0.2 m W1
|
||||||
|
|||||||
|
@ -172,4 +172,4 @@
|
|||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
<h1>Bill of Materials</h1><table style="border:1px solid #000000; font-size: 14pt; border-spacing: 0px"><tr><th align="left" style="border:1px solid #000000; padding: 8px">Item</th><th align="left" style="border:1px solid #000000; padding: 8px">Qty</th><th align="left" style="border:1px solid #000000; padding: 8px">Unit</th><th align="left" style="border:1px solid #000000; padding: 8px">Designators</th></tr><tr><td style="border:1px solid #000000; padding: 4px">Molex KK 254, female, 4 pins</td><td align="right" style="border:1px solid #000000; padding: 4px">2</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px">X1, X2</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Cable 4 x 0.25 mm² shielded</td><td align="right" style="border:1px solid #000000; padding: 4px">0.2</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1</td></tr></table></body></html>
|
<h1>Bill of Materials</h1><table style="border:1px solid #000000; font-size: 14pt; border-spacing: 0px"><tr><th align="left" style="border:1px solid #000000; padding: 8px">Item</th><th align="left" style="border:1px solid #000000; padding: 8px">Qty</th><th align="left" style="border:1px solid #000000; padding: 8px">Unit</th><th align="left" style="border:1px solid #000000; padding: 8px">Designators</th></tr><tr><td style="border:1px solid #000000; padding: 4px">Connector, Molex KK 254, female, 4 pins</td><td align="right" style="border:1px solid #000000; padding: 4px">2</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px">X1, X2</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Cable, 4 x 0.25 mm² shielded</td><td align="right" style="border:1px solid #000000; padding: 4px">0.2</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1</td></tr></table></body></html>
|
||||||
@ -1,4 +1,5 @@
|
|||||||
Item Qty Unit Designators
|
Item Qty Unit Designators
|
||||||
Molex Micro-Fit, female, 2 pins 3 X2, X3, X4
|
Connector, Molex Micro-Fit, female, 2 pins 3 X2, X3, X4
|
||||||
Molex Micro-Fit, male, 2 pins 1 X1
|
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
|
||||||
|
|||||||
|
@ -28,5 +28,5 @@ graph {
|
|||||||
edge [color="#000000:#ff0000:#000000"]
|
edge [color="#000000:#ff0000:#000000"]
|
||||||
X1:p2r:e -- W3:w2:w
|
X1:p2r:e -- W3:w2:w
|
||||||
W3:w2:e -- X4:p2l:w
|
W3:w2:e -- X4:p2l:w
|
||||||
W3 [label=<<table border="0" cellspacing="0" cellpadding="0"><tr><td><table border="0" cellspacing="0" cellpadding="3" cellborder="1"><tr><td colspan="3">W3</td></tr><tr><td>2x</td><td>0.25 mm² (24 AWG)</td><td>0.2 m</td></tr></table></td></tr><tr><td> </td></tr><tr><td><table border="0" cellspacing="0" cellborder="0"><tr><td>X1:1</td><td>BK</td><td>X4:1</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#000000" border="2" sides="tb" port="w1"></td></tr><tr><td>X1:2</td><td>RD</td><td>X4:2</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#ff0000" border="2" sides="tb" port="w2"></td></tr><tr><td> </td></tr></table></td></tr></table>> fillcolor=white margin=0 shape=box style=""]
|
W3 [label=<<table border="0" cellspacing="0" cellpadding="0"><tr><td><table border="0" cellspacing="0" cellpadding="3" cellborder="1"><tr><td colspan="3">W3</td></tr><tr><td>2x</td><td>20 AWG (0.75 mm²)</td><td>0.2 m</td></tr></table></td></tr><tr><td> </td></tr><tr><td><table border="0" cellspacing="0" cellborder="0"><tr><td>X1:1</td><td>BK</td><td>X4:1</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#000000" border="2" sides="tb" port="w1"></td></tr><tr><td>X1:2</td><td>RD</td><td>X4:2</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#ff0000" border="2" sides="tb" port="w2"></td></tr><tr><td> </td></tr></table></td></tr></table>> fillcolor=white margin=0 shape=box style=""]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -119,7 +119,7 @@
|
|||||||
<polygon fill="none" stroke="black" points="348,-84 348,-107 371,-107 371,-84 348,-84"/>
|
<polygon fill="none" stroke="black" points="348,-84 348,-107 371,-107 371,-84 348,-84"/>
|
||||||
<text text-anchor="start" x="352" y="-91.8" font-family="arial" font-size="14.00">2x</text>
|
<text text-anchor="start" x="352" y="-91.8" font-family="arial" font-size="14.00">2x</text>
|
||||||
<polygon fill="none" stroke="black" points="371,-84 371,-107 503,-107 503,-84 371,-84"/>
|
<polygon fill="none" stroke="black" points="371,-84 371,-107 503,-107 503,-84 371,-84"/>
|
||||||
<text text-anchor="start" x="375" y="-91.8" font-family="arial" font-size="14.00">0.25 mm² (24 AWG)</text>
|
<text text-anchor="start" x="375" y="-91.8" font-family="arial" font-size="14.00">20 AWG (0.75 mm²)</text>
|
||||||
<polygon fill="none" stroke="black" points="503,-84 503,-107 546,-107 546,-84 503,-84"/>
|
<polygon fill="none" stroke="black" points="503,-84 503,-107 546,-107 546,-84 503,-84"/>
|
||||||
<text text-anchor="start" x="507" y="-91.8" font-family="arial" font-size="14.00">0.2 m</text>
|
<text text-anchor="start" x="507" y="-91.8" font-family="arial" font-size="14.00">0.2 m</text>
|
||||||
<text text-anchor="start" x="445" y="-72.8" font-family="arial" font-size="14.00"> </text>
|
<text text-anchor="start" x="445" y="-72.8" font-family="arial" font-size="14.00"> </text>
|
||||||
@ -255,4 +255,4 @@
|
|||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
<h1>Bill of Materials</h1><table style="border:1px solid #000000; font-size: 14pt; border-spacing: 0px"><tr><th align="left" style="border:1px solid #000000; padding: 8px">Item</th><th align="left" style="border:1px solid #000000; padding: 8px">Qty</th><th align="left" style="border:1px solid #000000; padding: 8px">Unit</th><th align="left" style="border:1px solid #000000; padding: 8px">Designators</th></tr><tr><td style="border:1px solid #000000; padding: 4px">Molex Micro-Fit, female, 2 pins</td><td align="right" style="border:1px solid #000000; padding: 4px">3</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px">X2, X3, X4</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Molex Micro-Fit, male, 2 pins</td><td align="right" style="border:1px solid #000000; padding: 4px">1</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px">X1</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Cable 2 x 0.25 mm²</td><td align="right" style="border:1px solid #000000; padding: 4px">0.6</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1, W2, W3</td></tr></table></body></html>
|
<h1>Bill of Materials</h1><table style="border:1px solid #000000; font-size: 14pt; border-spacing: 0px"><tr><th align="left" style="border:1px solid #000000; padding: 8px">Item</th><th align="left" style="border:1px solid #000000; padding: 8px">Qty</th><th align="left" style="border:1px solid #000000; padding: 8px">Unit</th><th align="left" style="border:1px solid #000000; padding: 8px">Designators</th></tr><tr><td style="border:1px solid #000000; padding: 4px">Connector, Molex Micro-Fit, female, 2 pins</td><td align="right" style="border:1px solid #000000; padding: 4px">3</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px">X2, X3, X4</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Connector, Molex Micro-Fit, male, 2 pins</td><td align="right" style="border:1px solid #000000; padding: 4px">1</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px">X1</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Cable, 2 x 0.25 mm²</td><td align="right" style="border:1px solid #000000; padding: 4px">0.4</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1, W2</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Cable, 2 x 20 AWG</td><td align="right" style="border:1px solid #000000; padding: 4px">0.2</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W3</td></tr></table></body></html>
|
||||||
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 79 KiB |
@ -119,7 +119,7 @@
|
|||||||
<polygon fill="none" stroke="black" points="348,-84 348,-107 371,-107 371,-84 348,-84"/>
|
<polygon fill="none" stroke="black" points="348,-84 348,-107 371,-107 371,-84 348,-84"/>
|
||||||
<text text-anchor="start" x="352" y="-91.8" font-family="arial" font-size="14.00">2x</text>
|
<text text-anchor="start" x="352" y="-91.8" font-family="arial" font-size="14.00">2x</text>
|
||||||
<polygon fill="none" stroke="black" points="371,-84 371,-107 503,-107 503,-84 371,-84"/>
|
<polygon fill="none" stroke="black" points="371,-84 371,-107 503,-107 503,-84 371,-84"/>
|
||||||
<text text-anchor="start" x="375" y="-91.8" font-family="arial" font-size="14.00">0.25 mm² (24 AWG)</text>
|
<text text-anchor="start" x="375" y="-91.8" font-family="arial" font-size="14.00">20 AWG (0.75 mm²)</text>
|
||||||
<polygon fill="none" stroke="black" points="503,-84 503,-107 546,-107 546,-84 503,-84"/>
|
<polygon fill="none" stroke="black" points="503,-84 503,-107 546,-107 546,-84 503,-84"/>
|
||||||
<text text-anchor="start" x="507" y="-91.8" font-family="arial" font-size="14.00">0.2 m</text>
|
<text text-anchor="start" x="507" y="-91.8" font-family="arial" font-size="14.00">0.2 m</text>
|
||||||
<text text-anchor="start" x="445" y="-72.8" font-family="arial" font-size="14.00"> </text>
|
<text text-anchor="start" x="445" y="-72.8" font-family="arial" font-size="14.00"> </text>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
@ -22,6 +22,7 @@ cables:
|
|||||||
<<: *wire_power # create from template
|
<<: *wire_power # create from template
|
||||||
W3:
|
W3:
|
||||||
<<: *wire_power # create from template
|
<<: *wire_power # create from template
|
||||||
|
gauge: 20 awg
|
||||||
|
|
||||||
connections:
|
connections:
|
||||||
-
|
-
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
Item Qty Unit Designators
|
Item Qty Unit Designators
|
||||||
Molex Micro-Fit, female, 2 pins 3 X2, X3, X4
|
Connector, Molex Micro-Fit, female, 2 pins 3 X2, X3, X4
|
||||||
Molex Micro-Fit, male, 2 pins 1 X1
|
Connector, Molex Micro-Fit, male, 2 pins 1 X1
|
||||||
Wire 0.25 mm² BK 0.6 m W1
|
Wire, 0.25 mm², BK 0.6 m W1
|
||||||
Wire 0.25 mm² RD 0.6 m W1
|
Wire, 0.25 mm², RD 0.6 m W1
|
||||||
|
|||||||
|
@ -225,4 +225,4 @@
|
|||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
<h1>Bill of Materials</h1><table style="border:1px solid #000000; font-size: 14pt; border-spacing: 0px"><tr><th align="left" style="border:1px solid #000000; padding: 8px">Item</th><th align="left" style="border:1px solid #000000; padding: 8px">Qty</th><th align="left" style="border:1px solid #000000; padding: 8px">Unit</th><th align="left" style="border:1px solid #000000; padding: 8px">Designators</th></tr><tr><td style="border:1px solid #000000; padding: 4px">Molex Micro-Fit, female, 2 pins</td><td align="right" style="border:1px solid #000000; padding: 4px">3</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px">X2, X3, X4</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Molex Micro-Fit, male, 2 pins</td><td align="right" style="border:1px solid #000000; padding: 4px">1</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px">X1</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire 0.25 mm² BK</td><td align="right" style="border:1px solid #000000; padding: 4px">0.6</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire 0.25 mm² RD</td><td align="right" style="border:1px solid #000000; padding: 4px">0.6</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1</td></tr></table></body></html>
|
<h1>Bill of Materials</h1><table style="border:1px solid #000000; font-size: 14pt; border-spacing: 0px"><tr><th align="left" style="border:1px solid #000000; padding: 8px">Item</th><th align="left" style="border:1px solid #000000; padding: 8px">Qty</th><th align="left" style="border:1px solid #000000; padding: 8px">Unit</th><th align="left" style="border:1px solid #000000; padding: 8px">Designators</th></tr><tr><td style="border:1px solid #000000; padding: 4px">Connector, Molex Micro-Fit, female, 2 pins</td><td align="right" style="border:1px solid #000000; padding: 4px">3</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px">X2, X3, X4</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Connector, Molex Micro-Fit, male, 2 pins</td><td align="right" style="border:1px solid #000000; padding: 4px">1</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px">X1</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire, 0.25 mm², BK</td><td align="right" style="border:1px solid #000000; padding: 4px">0.6</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire, 0.25 mm², RD</td><td align="right" style="border:1px solid #000000; padding: 4px">0.6</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1</td></tr></table></body></html>
|
||||||
@ -1,8 +1,8 @@
|
|||||||
Item Qty Unit Designators
|
Item Qty Unit Designators
|
||||||
Crimp ferrule 12
|
Connector, Crimp ferrule 12
|
||||||
Wire 0.25 mm² BN 0.2 m W1
|
Wire, 0.25 mm², BN 0.2 m W1
|
||||||
Wire 0.25 mm² BU 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², GN 0.2 m W1
|
||||||
Wire 0.25 mm² OG 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², RD 0.2 m W1
|
||||||
Wire 0.25 mm² YE 0.2 m W1
|
Wire, 0.25 mm², YE 0.2 m W1
|
||||||
|
|||||||
|
@ -4,7 +4,7 @@ graph {
|
|||||||
graph [bgcolor=white fontname=arial nodesep=0.33 rankdir=LR ranksep=2]
|
graph [bgcolor=white fontname=arial nodesep=0.33 rankdir=LR ranksep=2]
|
||||||
node [fillcolor=white fontname=arial shape=record style=filled]
|
node [fillcolor=white fontname=arial shape=record style=filled]
|
||||||
edge [fontname=arial style=bold]
|
edge [fontname=arial style=bold]
|
||||||
F1 [label=<
|
_F1 [label=<
|
||||||
|
|
||||||
<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="2"><TR>
|
<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="2"><TR>
|
||||||
<TD PORT="p1l"> Crimp ferrule </TD>
|
<TD PORT="p1l"> Crimp ferrule </TD>
|
||||||
@ -14,7 +14,7 @@ graph {
|
|||||||
|
|
||||||
|
|
||||||
> margin=0 orientation=180 shape=none style=filled]
|
> margin=0 orientation=180 shape=none style=filled]
|
||||||
F2 [label=<
|
_F2 [label=<
|
||||||
|
|
||||||
<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="2"><TR>
|
<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="2"><TR>
|
||||||
<TD PORT="p1l"> Crimp ferrule </TD>
|
<TD PORT="p1l"> Crimp ferrule </TD>
|
||||||
@ -24,7 +24,7 @@ graph {
|
|||||||
|
|
||||||
|
|
||||||
> margin=0 orientation=180 shape=none style=filled]
|
> margin=0 orientation=180 shape=none style=filled]
|
||||||
F3 [label=<
|
_F3 [label=<
|
||||||
|
|
||||||
<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="2"><TR>
|
<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="2"><TR>
|
||||||
<TD PORT="p1l"> Crimp ferrule </TD>
|
<TD PORT="p1l"> Crimp ferrule </TD>
|
||||||
@ -34,7 +34,7 @@ graph {
|
|||||||
|
|
||||||
|
|
||||||
> margin=0 orientation=180 shape=none style=filled]
|
> margin=0 orientation=180 shape=none style=filled]
|
||||||
F4 [label=<
|
_F4 [label=<
|
||||||
|
|
||||||
<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="2"><TR>
|
<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="2"><TR>
|
||||||
<TD PORT="p1l"> Crimp ferrule </TD>
|
<TD PORT="p1l"> Crimp ferrule </TD>
|
||||||
@ -44,7 +44,7 @@ graph {
|
|||||||
|
|
||||||
|
|
||||||
> margin=0 orientation=180 shape=none style=filled]
|
> margin=0 orientation=180 shape=none style=filled]
|
||||||
F5 [label=<
|
_F5 [label=<
|
||||||
|
|
||||||
<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="2"><TR>
|
<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="2"><TR>
|
||||||
<TD PORT="p1l"> Crimp ferrule </TD>
|
<TD PORT="p1l"> Crimp ferrule </TD>
|
||||||
@ -54,7 +54,7 @@ graph {
|
|||||||
|
|
||||||
|
|
||||||
> margin=0 orientation=180 shape=none style=filled]
|
> margin=0 orientation=180 shape=none style=filled]
|
||||||
F6 [label=<
|
_F6 [label=<
|
||||||
|
|
||||||
<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="2"><TR>
|
<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="2"><TR>
|
||||||
<TD PORT="p1l"> Crimp ferrule </TD>
|
<TD PORT="p1l"> Crimp ferrule </TD>
|
||||||
@ -64,7 +64,7 @@ graph {
|
|||||||
|
|
||||||
|
|
||||||
> margin=0 orientation=180 shape=none style=filled]
|
> margin=0 orientation=180 shape=none style=filled]
|
||||||
F7 [label=<
|
_F7 [label=<
|
||||||
|
|
||||||
<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="2"><TR>
|
<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="2"><TR>
|
||||||
<TD PORT="p1l"> </TD>
|
<TD PORT="p1l"> </TD>
|
||||||
@ -74,7 +74,7 @@ graph {
|
|||||||
|
|
||||||
|
|
||||||
> margin=0 orientation=0 shape=none style=filled]
|
> margin=0 orientation=0 shape=none style=filled]
|
||||||
F8 [label=<
|
_F8 [label=<
|
||||||
|
|
||||||
<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="2"><TR>
|
<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="2"><TR>
|
||||||
<TD PORT="p1l"> </TD>
|
<TD PORT="p1l"> </TD>
|
||||||
@ -84,7 +84,7 @@ graph {
|
|||||||
|
|
||||||
|
|
||||||
> margin=0 orientation=0 shape=none style=filled]
|
> margin=0 orientation=0 shape=none style=filled]
|
||||||
F9 [label=<
|
_F9 [label=<
|
||||||
|
|
||||||
<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="2"><TR>
|
<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="2"><TR>
|
||||||
<TD PORT="p1l"> </TD>
|
<TD PORT="p1l"> </TD>
|
||||||
@ -94,7 +94,7 @@ graph {
|
|||||||
|
|
||||||
|
|
||||||
> margin=0 orientation=0 shape=none style=filled]
|
> margin=0 orientation=0 shape=none style=filled]
|
||||||
F10 [label=<
|
_F10 [label=<
|
||||||
|
|
||||||
<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="2"><TR>
|
<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="2"><TR>
|
||||||
<TD PORT="p1l"> </TD>
|
<TD PORT="p1l"> </TD>
|
||||||
@ -104,7 +104,7 @@ graph {
|
|||||||
|
|
||||||
|
|
||||||
> margin=0 orientation=0 shape=none style=filled]
|
> margin=0 orientation=0 shape=none style=filled]
|
||||||
F11 [label=<
|
_F11 [label=<
|
||||||
|
|
||||||
<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="2"><TR>
|
<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="2"><TR>
|
||||||
<TD PORT="p1l"> </TD>
|
<TD PORT="p1l"> </TD>
|
||||||
@ -114,7 +114,7 @@ graph {
|
|||||||
|
|
||||||
|
|
||||||
> margin=0 orientation=0 shape=none style=filled]
|
> margin=0 orientation=0 shape=none style=filled]
|
||||||
F12 [label=<
|
_F12 [label=<
|
||||||
|
|
||||||
<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="2"><TR>
|
<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="2"><TR>
|
||||||
<TD PORT="p1l"> </TD>
|
<TD PORT="p1l"> </TD>
|
||||||
@ -125,28 +125,28 @@ graph {
|
|||||||
|
|
||||||
> margin=0 orientation=0 shape=none style=filled]
|
> margin=0 orientation=0 shape=none style=filled]
|
||||||
edge [color="#000000:#666600:#000000"]
|
edge [color="#000000:#666600:#000000"]
|
||||||
F1:e -- W1:w1:w
|
_F1:e -- W1:w1:w
|
||||||
edge [color="#000000:#ff0000:#000000"]
|
edge [color="#000000:#ff0000:#000000"]
|
||||||
F2:e -- W1:w2:w
|
_F2:e -- W1:w2:w
|
||||||
edge [color="#000000:#ff8000:#000000"]
|
edge [color="#000000:#ff8000:#000000"]
|
||||||
F3:e -- W1:w3:w
|
_F3:e -- W1:w3:w
|
||||||
edge [color="#000000:#ffff00:#000000"]
|
edge [color="#000000:#ffff00:#000000"]
|
||||||
F4:e -- W1:w4:w
|
_F4:e -- W1:w4:w
|
||||||
edge [color="#000000:#00ff00:#000000"]
|
edge [color="#000000:#00ff00:#000000"]
|
||||||
F5:e -- W1:w5:w
|
_F5:e -- W1:w5:w
|
||||||
edge [color="#000000:#0066ff:#000000"]
|
edge [color="#000000:#0066ff:#000000"]
|
||||||
F6:e -- W1:w6:w
|
_F6:e -- W1:w6:w
|
||||||
edge [color="#000000:#0066ff:#000000"]
|
edge [color="#000000:#0066ff:#000000"]
|
||||||
W1:w6:e -- F7:w
|
W1:w6:e -- _F7:w
|
||||||
edge [color="#000000:#00ff00:#000000"]
|
edge [color="#000000:#00ff00:#000000"]
|
||||||
W1:w5:e -- F8:w
|
W1:w5:e -- _F8:w
|
||||||
edge [color="#000000:#ffff00:#000000"]
|
edge [color="#000000:#ffff00:#000000"]
|
||||||
W1:w4:e -- F9:w
|
W1:w4:e -- _F9:w
|
||||||
edge [color="#000000:#ff8000:#000000"]
|
edge [color="#000000:#ff8000:#000000"]
|
||||||
W1:w3:e -- F10:w
|
W1:w3:e -- _F10:w
|
||||||
edge [color="#000000:#ff0000:#000000"]
|
edge [color="#000000:#ff0000:#000000"]
|
||||||
W1:w2:e -- F11:w
|
W1:w2:e -- _F11:w
|
||||||
edge [color="#000000:#666600:#000000"]
|
edge [color="#000000:#666600:#000000"]
|
||||||
W1:w1:e -- F12:w
|
W1:w1:e -- _F12:w
|
||||||
W1 [label=<<table border="0" cellspacing="0" cellpadding="0"><tr><td><table border="0" cellspacing="0" cellpadding="3" cellborder="1"><tr><td colspan="3">W1</td></tr><tr><td>6x</td><td>0.25 mm² (24 AWG)</td><td>0.2 m</td></tr></table></td></tr><tr><td> </td></tr><tr><td><table border="0" cellspacing="0" cellborder="0"><tr><td></td><td>BN</td><td></td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#666600" border="2" sides="tb" port="w1"></td></tr><tr><td></td><td>RD</td><td></td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#ff0000" border="2" sides="tb" port="w2"></td></tr><tr><td></td><td>OG</td><td></td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#ff8000" border="2" sides="tb" port="w3"></td></tr><tr><td></td><td>YE</td><td></td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#ffff00" border="2" sides="tb" port="w4"></td></tr><tr><td></td><td>GN</td><td></td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#00ff00" border="2" sides="tb" port="w5"></td></tr><tr><td></td><td>BU</td><td></td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#0066ff" border="2" sides="tb" port="w6"></td></tr><tr><td> </td></tr></table></td></tr></table>> fillcolor=white margin=0 shape=box style="filled,dashed"]
|
W1 [label=<<table border="0" cellspacing="0" cellpadding="0"><tr><td><table border="0" cellspacing="0" cellpadding="3" cellborder="1"><tr><td colspan="3">W1</td></tr><tr><td>6x</td><td>0.25 mm² (24 AWG)</td><td>0.2 m</td></tr></table></td></tr><tr><td> </td></tr><tr><td><table border="0" cellspacing="0" cellborder="0"><tr><td></td><td>BN</td><td></td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#666600" border="2" sides="tb" port="w1"></td></tr><tr><td></td><td>RD</td><td></td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#ff0000" border="2" sides="tb" port="w2"></td></tr><tr><td></td><td>OG</td><td></td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#ff8000" border="2" sides="tb" port="w3"></td></tr><tr><td></td><td>YE</td><td></td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#ffff00" border="2" sides="tb" port="w4"></td></tr><tr><td></td><td>GN</td><td></td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#00ff00" border="2" sides="tb" port="w5"></td></tr><tr><td></td><td>BU</td><td></td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#0066ff" border="2" sides="tb" port="w6"></td></tr><tr><td> </td></tr></table></td></tr></table>> fillcolor=white margin=0 shape=box style="filled,dashed"]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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">
|
viewBox="0.00 0.00 712.00 344.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 340)">
|
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 340)">
|
||||||
<polygon fill="white" stroke="transparent" points="-4,4 -4,-340 708,-340 708,4 -4,4"/>
|
<polygon fill="white" stroke="transparent" points="-4,4 -4,-340 708,-340 708,4 -4,4"/>
|
||||||
<!-- F1 -->
|
<!-- _F1 -->
|
||||||
<g id="node1" class="node">
|
<g id="node1" class="node">
|
||||||
<title>F1</title>
|
<title>_F1</title>
|
||||||
<polygon fill="white" stroke="transparent" points="0,-300 109,-300 109,-336 0,-336 0,-300"/>
|
<polygon fill="white" stroke="transparent" points="0,-300 109,-300 109,-336 0,-336 0,-300"/>
|
||||||
<text text-anchor="start" x="3.5" y="-313.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
<text text-anchor="start" x="3.5" y="-313.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
||||||
<text text-anchor="start" x="98.5" y="-313.8" font-family="arial" font-size="14.00">  </text>
|
<text text-anchor="start" x="98.5" y="-313.8" font-family="arial" font-size="14.00">  </text>
|
||||||
@ -55,178 +55,178 @@
|
|||||||
<polyline fill="none" stroke="black" stroke-width="2" points="450,-107 254,-107 "/>
|
<polyline fill="none" stroke="black" stroke-width="2" points="450,-107 254,-107 "/>
|
||||||
<text text-anchor="start" x="281.5" y="-88.8" font-family="arial" font-size="14.00"> </text>
|
<text text-anchor="start" x="281.5" y="-88.8" font-family="arial" font-size="14.00"> </text>
|
||||||
</g>
|
</g>
|
||||||
<!-- F1--W1 -->
|
<!-- _F1--W1 -->
|
||||||
<g id="edge1" class="edge">
|
<g id="edge1" class="edge">
|
||||||
<title>F1:e--W1:w</title>
|
<title>_F1:e--W1:w</title>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-316C182.01,-318.14 176,-230.14 253,-228"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-316C182.01,-318.14 176,-230.14 253,-228"/>
|
||||||
<path fill="none" stroke="#666600" stroke-width="2" d="M109,-318C184,-318 178,-230 253,-230"/>
|
<path fill="none" stroke="#666600" stroke-width="2" d="M109,-318C184,-318 178,-230 253,-230"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-320C186,-317.86 179.99,-229.86 253,-232"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-320C186,-317.86 179.99,-229.86 253,-232"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F2 -->
|
<!-- _F2 -->
|
||||||
<g id="node2" class="node">
|
<g id="node2" class="node">
|
||||||
<title>F2</title>
|
<title>_F2</title>
|
||||||
<polygon fill="white" stroke="transparent" points="0,-240 109,-240 109,-276 0,-276 0,-240"/>
|
<polygon fill="white" stroke="transparent" points="0,-240 109,-240 109,-276 0,-276 0,-240"/>
|
||||||
<text text-anchor="start" x="3.5" y="-253.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
<text text-anchor="start" x="3.5" y="-253.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
||||||
<text text-anchor="start" x="98.5" y="-253.8" font-family="arial" font-size="14.00">  </text>
|
<text text-anchor="start" x="98.5" y="-253.8" font-family="arial" font-size="14.00">  </text>
|
||||||
<polygon fill="none" stroke="black" points="0,-247.5 0,-268.5 109,-268.5 109,-247.5 0,-247.5"/>
|
<polygon fill="none" stroke="black" points="0,-247.5 0,-268.5 109,-268.5 109,-247.5 0,-247.5"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F2--W1 -->
|
<!-- _F2--W1 -->
|
||||||
<g id="edge2" class="edge">
|
<g id="edge2" class="edge">
|
||||||
<title>F2:e--W1:w</title>
|
<title>_F2:e--W1:w</title>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-256C175.22,-257.72 182.82,-204.72 253,-203"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-256C175.22,-257.72 182.82,-204.72 253,-203"/>
|
||||||
<path fill="none" stroke="#ff0000" stroke-width="2" d="M109,-258C177.2,-258 184.8,-205 253,-205"/>
|
<path fill="none" stroke="#ff0000" stroke-width="2" d="M109,-258C177.2,-258 184.8,-205 253,-205"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-260C179.18,-258.28 186.78,-205.28 253,-207"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-260C179.18,-258.28 186.78,-205.28 253,-207"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F3 -->
|
<!-- _F3 -->
|
||||||
<g id="node3" class="node">
|
<g id="node3" class="node">
|
||||||
<title>F3</title>
|
<title>_F3</title>
|
||||||
<polygon fill="white" stroke="transparent" points="0,-180 109,-180 109,-216 0,-216 0,-180"/>
|
<polygon fill="white" stroke="transparent" points="0,-180 109,-180 109,-216 0,-216 0,-180"/>
|
||||||
<text text-anchor="start" x="3.5" y="-193.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
<text text-anchor="start" x="3.5" y="-193.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
||||||
<text text-anchor="start" x="98.5" y="-193.8" font-family="arial" font-size="14.00">  </text>
|
<text text-anchor="start" x="98.5" y="-193.8" font-family="arial" font-size="14.00">  </text>
|
||||||
<polygon fill="none" stroke="black" points="0,-187.5 0,-208.5 109,-208.5 109,-187.5 0,-187.5"/>
|
<polygon fill="none" stroke="black" points="0,-187.5 0,-208.5 109,-208.5 109,-187.5 0,-187.5"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F3--W1 -->
|
<!-- _F3--W1 -->
|
||||||
<g id="edge3" class="edge">
|
<g id="edge3" class="edge">
|
||||||
<title>F3:e--W1:w</title>
|
<title>_F3:e--W1:w</title>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-196C171.96,-196.72 186.97,-178.72 253,-178"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-196C171.96,-196.72 186.97,-178.72 253,-178"/>
|
||||||
<path fill="none" stroke="#ff8000" stroke-width="2" d="M109,-198C173.5,-198 188.5,-180 253,-180"/>
|
<path fill="none" stroke="#ff8000" stroke-width="2" d="M109,-198C173.5,-198 188.5,-180 253,-180"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-200C175.03,-199.28 190.04,-181.28 253,-182"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-200C175.03,-199.28 190.04,-181.28 253,-182"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F4 -->
|
<!-- _F4 -->
|
||||||
<g id="node4" class="node">
|
<g id="node4" class="node">
|
||||||
<title>F4</title>
|
<title>_F4</title>
|
||||||
<polygon fill="white" stroke="transparent" points="0,-120 109,-120 109,-156 0,-156 0,-120"/>
|
<polygon fill="white" stroke="transparent" points="0,-120 109,-120 109,-156 0,-156 0,-120"/>
|
||||||
<text text-anchor="start" x="3.5" y="-133.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
<text text-anchor="start" x="3.5" y="-133.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
||||||
<text text-anchor="start" x="98.5" y="-133.8" font-family="arial" font-size="14.00">  </text>
|
<text text-anchor="start" x="98.5" y="-133.8" font-family="arial" font-size="14.00">  </text>
|
||||||
<polygon fill="none" stroke="black" points="0,-127.5 0,-148.5 109,-148.5 109,-127.5 0,-127.5"/>
|
<polygon fill="none" stroke="black" points="0,-127.5 0,-148.5 109,-148.5 109,-127.5 0,-127.5"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F4--W1 -->
|
<!-- _F4--W1 -->
|
||||||
<g id="edge4" class="edge">
|
<g id="edge4" class="edge">
|
||||||
<title>F4:e--W1:w</title>
|
<title>_F4:e--W1:w</title>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-136C174.94,-136.67 190.05,-153.67 253,-153"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-136C174.94,-136.67 190.05,-153.67 253,-153"/>
|
||||||
<path fill="none" stroke="#ffff00" stroke-width="2" d="M109,-138C173.44,-138 188.56,-155 253,-155"/>
|
<path fill="none" stroke="#ffff00" stroke-width="2" d="M109,-138C173.44,-138 188.56,-155 253,-155"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-140C171.95,-139.33 187.06,-156.33 253,-157"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-140C171.95,-139.33 187.06,-156.33 253,-157"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F5 -->
|
<!-- _F5 -->
|
||||||
<g id="node5" class="node">
|
<g id="node5" class="node">
|
||||||
<title>F5</title>
|
<title>_F5</title>
|
||||||
<polygon fill="white" stroke="transparent" points="0,-60 109,-60 109,-96 0,-96 0,-60"/>
|
<polygon fill="white" stroke="transparent" points="0,-60 109,-60 109,-96 0,-96 0,-60"/>
|
||||||
<text text-anchor="start" x="3.5" y="-73.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
<text text-anchor="start" x="3.5" y="-73.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
||||||
<text text-anchor="start" x="98.5" y="-73.8" font-family="arial" font-size="14.00">  </text>
|
<text text-anchor="start" x="98.5" y="-73.8" font-family="arial" font-size="14.00">  </text>
|
||||||
<polygon fill="none" stroke="black" points="0,-67.5 0,-88.5 109,-88.5 109,-67.5 0,-67.5"/>
|
<polygon fill="none" stroke="black" points="0,-67.5 0,-88.5 109,-88.5 109,-67.5 0,-67.5"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F5--W1 -->
|
<!-- _F5--W1 -->
|
||||||
<g id="edge5" class="edge">
|
<g id="edge5" class="edge">
|
||||||
<title>F5:e--W1:w</title>
|
<title>_F5:e--W1:w</title>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-76C179.02,-77.7 186.93,-129.7 253,-128"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-76C179.02,-77.7 186.93,-129.7 253,-128"/>
|
||||||
<path fill="none" stroke="#00ff00" stroke-width="2" d="M109,-78C177.05,-78 184.95,-130 253,-130"/>
|
<path fill="none" stroke="#00ff00" stroke-width="2" d="M109,-78C177.05,-78 184.95,-130 253,-130"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-80C175.07,-78.3 182.98,-130.3 253,-132"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-80C175.07,-78.3 182.98,-130.3 253,-132"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F6 -->
|
<!-- _F6 -->
|
||||||
<g id="node6" class="node">
|
<g id="node6" class="node">
|
||||||
<title>F6</title>
|
<title>_F6</title>
|
||||||
<polygon fill="white" stroke="transparent" points="0,0 109,0 109,-36 0,-36 0,0"/>
|
<polygon fill="white" stroke="transparent" points="0,0 109,0 109,-36 0,-36 0,0"/>
|
||||||
<text text-anchor="start" x="3.5" y="-13.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
<text text-anchor="start" x="3.5" y="-13.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
||||||
<text text-anchor="start" x="98.5" y="-13.8" font-family="arial" font-size="14.00">  </text>
|
<text text-anchor="start" x="98.5" y="-13.8" font-family="arial" font-size="14.00">  </text>
|
||||||
<polygon fill="none" stroke="black" points="0,-7.5 0,-28.5 109,-28.5 109,-7.5 0,-7.5"/>
|
<polygon fill="none" stroke="black" points="0,-7.5 0,-28.5 109,-28.5 109,-7.5 0,-7.5"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F6--W1 -->
|
<!-- _F6--W1 -->
|
||||||
<g id="edge6" class="edge">
|
<g id="edge6" class="edge">
|
||||||
<title>F6:e--W1:w</title>
|
<title>_F6:e--W1:w</title>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-16C185.77,-18.13 180.22,-105.13 253,-103"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-16C185.77,-18.13 180.22,-105.13 253,-103"/>
|
||||||
<path fill="none" stroke="#0066ff" stroke-width="2" d="M109,-18C183.77,-18 178.23,-105 253,-105"/>
|
<path fill="none" stroke="#0066ff" stroke-width="2" d="M109,-18C183.77,-18 178.23,-105 253,-105"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-20C181.78,-17.87 176.23,-104.87 253,-107"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-20C181.78,-17.87 176.23,-104.87 253,-107"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F7 -->
|
<!-- _F7 -->
|
||||||
<g id="node7" class="node">
|
<g id="node7" class="node">
|
||||||
<title>F7</title>
|
<title>_F7</title>
|
||||||
<polygon fill="white" stroke="transparent" points="704,-36 595,-36 595,0 704,0 704,-36"/>
|
<polygon fill="white" stroke="transparent" points="704,-36 595,-36 595,0 704,0 704,-36"/>
|
||||||
<text text-anchor="start" x="598.5" y="-13.8" font-family="arial" font-size="14.00">  </text>
|
<text text-anchor="start" x="598.5" y="-13.8" font-family="arial" font-size="14.00">  </text>
|
||||||
<text text-anchor="start" x="610.5" y="-13.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
<text text-anchor="start" x="610.5" y="-13.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
||||||
<polygon fill="none" stroke="black" points="595,-7.5 595,-28.5 704,-28.5 704,-7.5 595,-7.5"/>
|
<polygon fill="none" stroke="black" points="595,-7.5 595,-28.5 704,-28.5 704,-7.5 595,-7.5"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F8 -->
|
<!-- _F8 -->
|
||||||
<g id="node8" class="node">
|
<g id="node8" class="node">
|
||||||
<title>F8</title>
|
<title>_F8</title>
|
||||||
<polygon fill="white" stroke="transparent" points="704,-96 595,-96 595,-60 704,-60 704,-96"/>
|
<polygon fill="white" stroke="transparent" points="704,-96 595,-96 595,-60 704,-60 704,-96"/>
|
||||||
<text text-anchor="start" x="598.5" y="-73.8" font-family="arial" font-size="14.00">  </text>
|
<text text-anchor="start" x="598.5" y="-73.8" font-family="arial" font-size="14.00">  </text>
|
||||||
<text text-anchor="start" x="610.5" y="-73.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
<text text-anchor="start" x="610.5" y="-73.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
||||||
<polygon fill="none" stroke="black" points="595,-67.5 595,-88.5 704,-88.5 704,-67.5 595,-67.5"/>
|
<polygon fill="none" stroke="black" points="595,-67.5 595,-88.5 704,-88.5 704,-67.5 595,-67.5"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F9 -->
|
<!-- _F9 -->
|
||||||
<g id="node9" class="node">
|
<g id="node9" class="node">
|
||||||
<title>F9</title>
|
<title>_F9</title>
|
||||||
<polygon fill="white" stroke="transparent" points="704,-156 595,-156 595,-120 704,-120 704,-156"/>
|
<polygon fill="white" stroke="transparent" points="704,-156 595,-156 595,-120 704,-120 704,-156"/>
|
||||||
<text text-anchor="start" x="598.5" y="-133.8" font-family="arial" font-size="14.00">  </text>
|
<text text-anchor="start" x="598.5" y="-133.8" font-family="arial" font-size="14.00">  </text>
|
||||||
<text text-anchor="start" x="610.5" y="-133.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
<text text-anchor="start" x="610.5" y="-133.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
||||||
<polygon fill="none" stroke="black" points="595,-127.5 595,-148.5 704,-148.5 704,-127.5 595,-127.5"/>
|
<polygon fill="none" stroke="black" points="595,-127.5 595,-148.5 704,-148.5 704,-127.5 595,-127.5"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F10 -->
|
<!-- _F10 -->
|
||||||
<g id="node10" class="node">
|
<g id="node10" class="node">
|
||||||
<title>F10</title>
|
<title>_F10</title>
|
||||||
<polygon fill="white" stroke="transparent" points="704,-216 595,-216 595,-180 704,-180 704,-216"/>
|
<polygon fill="white" stroke="transparent" points="704,-216 595,-216 595,-180 704,-180 704,-216"/>
|
||||||
<text text-anchor="start" x="598.5" y="-193.8" font-family="arial" font-size="14.00">  </text>
|
<text text-anchor="start" x="598.5" y="-193.8" font-family="arial" font-size="14.00">  </text>
|
||||||
<text text-anchor="start" x="610.5" y="-193.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
<text text-anchor="start" x="610.5" y="-193.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
||||||
<polygon fill="none" stroke="black" points="595,-187.5 595,-208.5 704,-208.5 704,-187.5 595,-187.5"/>
|
<polygon fill="none" stroke="black" points="595,-187.5 595,-208.5 704,-208.5 704,-187.5 595,-187.5"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F11 -->
|
<!-- _F11 -->
|
||||||
<g id="node11" class="node">
|
<g id="node11" class="node">
|
||||||
<title>F11</title>
|
<title>_F11</title>
|
||||||
<polygon fill="white" stroke="transparent" points="704,-276 595,-276 595,-240 704,-240 704,-276"/>
|
<polygon fill="white" stroke="transparent" points="704,-276 595,-276 595,-240 704,-240 704,-276"/>
|
||||||
<text text-anchor="start" x="598.5" y="-253.8" font-family="arial" font-size="14.00">  </text>
|
<text text-anchor="start" x="598.5" y="-253.8" font-family="arial" font-size="14.00">  </text>
|
||||||
<text text-anchor="start" x="610.5" y="-253.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
<text text-anchor="start" x="610.5" y="-253.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
||||||
<polygon fill="none" stroke="black" points="595,-247.5 595,-268.5 704,-268.5 704,-247.5 595,-247.5"/>
|
<polygon fill="none" stroke="black" points="595,-247.5 595,-268.5 704,-268.5 704,-247.5 595,-247.5"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F12 -->
|
<!-- _F12 -->
|
||||||
<g id="node12" class="node">
|
<g id="node12" class="node">
|
||||||
<title>F12</title>
|
<title>_F12</title>
|
||||||
<polygon fill="white" stroke="transparent" points="704,-336 595,-336 595,-300 704,-300 704,-336"/>
|
<polygon fill="white" stroke="transparent" points="704,-336 595,-336 595,-300 704,-300 704,-336"/>
|
||||||
<text text-anchor="start" x="598.5" y="-313.8" font-family="arial" font-size="14.00">  </text>
|
<text text-anchor="start" x="598.5" y="-313.8" font-family="arial" font-size="14.00">  </text>
|
||||||
<text text-anchor="start" x="610.5" y="-313.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
<text text-anchor="start" x="610.5" y="-313.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
||||||
<polygon fill="none" stroke="black" points="595,-307.5 595,-328.5 704,-328.5 704,-307.5 595,-307.5"/>
|
<polygon fill="none" stroke="black" points="595,-307.5 595,-328.5 704,-328.5 704,-307.5 595,-307.5"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- W1--F7 -->
|
<!-- W1--_F7 -->
|
||||||
<g id="edge7" class="edge">
|
<g id="edge7" class="edge">
|
||||||
<title>W1:e--F7:w</title>
|
<title>W1:e--_F7:w</title>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-103C523.78,-105.13 518.23,-18.13 595,-16"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-103C523.78,-105.13 518.23,-18.13 595,-16"/>
|
||||||
<path fill="none" stroke="#0066ff" stroke-width="2" d="M451,-105C525.77,-105 520.23,-18 595,-18"/>
|
<path fill="none" stroke="#0066ff" stroke-width="2" d="M451,-105C525.77,-105 520.23,-18 595,-18"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-107C527.77,-104.87 522.22,-17.87 595,-20"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-107C527.77,-104.87 522.22,-17.87 595,-20"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- W1--F8 -->
|
<!-- W1--_F8 -->
|
||||||
<g id="edge8" class="edge">
|
<g id="edge8" class="edge">
|
||||||
<title>W1:e--F8:w</title>
|
<title>W1:e--_F8:w</title>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-128C517.07,-129.7 524.98,-77.7 595,-76"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-128C517.07,-129.7 524.98,-77.7 595,-76"/>
|
||||||
<path fill="none" stroke="#00ff00" stroke-width="2" d="M451,-130C519.05,-130 526.95,-78 595,-78"/>
|
<path fill="none" stroke="#00ff00" stroke-width="2" d="M451,-130C519.05,-130 526.95,-78 595,-78"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-132C521.02,-130.3 528.93,-78.3 595,-80"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-132C521.02,-130.3 528.93,-78.3 595,-80"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- W1--F9 -->
|
<!-- W1--_F9 -->
|
||||||
<g id="edge9" class="edge">
|
<g id="edge9" class="edge">
|
||||||
<title>W1:e--F9:w</title>
|
<title>W1:e--_F9:w</title>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-153C513.95,-153.67 529.06,-136.67 595,-136"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-153C513.95,-153.67 529.06,-136.67 595,-136"/>
|
||||||
<path fill="none" stroke="#ffff00" stroke-width="2" d="M451,-155C515.44,-155 530.56,-138 595,-138"/>
|
<path fill="none" stroke="#ffff00" stroke-width="2" d="M451,-155C515.44,-155 530.56,-138 595,-138"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-157C516.94,-156.33 532.05,-139.33 595,-140"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-157C516.94,-156.33 532.05,-139.33 595,-140"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- W1--F10 -->
|
<!-- W1--_F10 -->
|
||||||
<g id="edge10" class="edge">
|
<g id="edge10" class="edge">
|
||||||
<title>W1:e--F10:w</title>
|
<title>W1:e--_F10:w</title>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-178C517.03,-178.72 532.04,-196.72 595,-196"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-178C517.03,-178.72 532.04,-196.72 595,-196"/>
|
||||||
<path fill="none" stroke="#ff8000" stroke-width="2" d="M451,-180C515.5,-180 530.5,-198 595,-198"/>
|
<path fill="none" stroke="#ff8000" stroke-width="2" d="M451,-180C515.5,-180 530.5,-198 595,-198"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-182C513.96,-181.28 528.97,-199.28 595,-200"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-182C513.96,-181.28 528.97,-199.28 595,-200"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- W1--F11 -->
|
<!-- W1--_F11 -->
|
||||||
<g id="edge11" class="edge">
|
<g id="edge11" class="edge">
|
||||||
<title>W1:e--F11:w</title>
|
<title>W1:e--_F11:w</title>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-203C521.18,-204.72 528.78,-257.72 595,-256"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-203C521.18,-204.72 528.78,-257.72 595,-256"/>
|
||||||
<path fill="none" stroke="#ff0000" stroke-width="2" d="M451,-205C519.2,-205 526.8,-258 595,-258"/>
|
<path fill="none" stroke="#ff0000" stroke-width="2" d="M451,-205C519.2,-205 526.8,-258 595,-258"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-207C517.22,-205.28 524.82,-258.28 595,-260"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-207C517.22,-205.28 524.82,-258.28 595,-260"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- W1--F12 -->
|
<!-- W1--_F12 -->
|
||||||
<g id="edge12" class="edge">
|
<g id="edge12" class="edge">
|
||||||
<title>W1:e--F12:w</title>
|
<title>W1:e--_F12:w</title>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-228C528,-230.14 521.99,-318.14 595,-316"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-228C528,-230.14 521.99,-318.14 595,-316"/>
|
||||||
<path fill="none" stroke="#666600" stroke-width="2" d="M451,-230C526,-230 520,-318 595,-318"/>
|
<path fill="none" stroke="#666600" stroke-width="2" d="M451,-230C526,-230 520,-318 595,-318"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-232C524.01,-229.86 518,-317.86 595,-320"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-232C524.01,-229.86 518,-317.86 595,-320"/>
|
||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
<h1>Bill of Materials</h1><table style="border:1px solid #000000; font-size: 14pt; border-spacing: 0px"><tr><th align="left" style="border:1px solid #000000; padding: 8px">Item</th><th align="left" style="border:1px solid #000000; padding: 8px">Qty</th><th align="left" style="border:1px solid #000000; padding: 8px">Unit</th><th align="left" style="border:1px solid #000000; padding: 8px">Designators</th></tr><tr><td style="border:1px solid #000000; padding: 4px">Crimp ferrule</td><td align="right" style="border:1px solid #000000; padding: 4px">12</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px"></td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire 0.25 mm² BN</td><td align="right" style="border:1px solid #000000; padding: 4px">0.2</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire 0.25 mm² BU</td><td align="right" style="border:1px solid #000000; padding: 4px">0.2</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire 0.25 mm² GN</td><td align="right" style="border:1px solid #000000; padding: 4px">0.2</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire 0.25 mm² OG</td><td align="right" style="border:1px solid #000000; padding: 4px">0.2</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire 0.25 mm² RD</td><td align="right" style="border:1px solid #000000; padding: 4px">0.2</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire 0.25 mm² YE</td><td align="right" style="border:1px solid #000000; padding: 4px">0.2</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1</td></tr></table></body></html>
|
<h1>Bill of Materials</h1><table style="border:1px solid #000000; font-size: 14pt; border-spacing: 0px"><tr><th align="left" style="border:1px solid #000000; padding: 8px">Item</th><th align="left" style="border:1px solid #000000; padding: 8px">Qty</th><th align="left" style="border:1px solid #000000; padding: 8px">Unit</th><th align="left" style="border:1px solid #000000; padding: 8px">Designators</th></tr><tr><td style="border:1px solid #000000; padding: 4px">Connector, Crimp ferrule</td><td align="right" style="border:1px solid #000000; padding: 4px">12</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px"></td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire, 0.25 mm², BN</td><td align="right" style="border:1px solid #000000; padding: 4px">0.2</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire, 0.25 mm², BU</td><td align="right" style="border:1px solid #000000; padding: 4px">0.2</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire, 0.25 mm², GN</td><td align="right" style="border:1px solid #000000; padding: 4px">0.2</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire, 0.25 mm², OG</td><td align="right" style="border:1px solid #000000; padding: 4px">0.2</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire, 0.25 mm², RD</td><td align="right" style="border:1px solid #000000; padding: 4px">0.2</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire, 0.25 mm², YE</td><td align="right" style="border:1px solid #000000; padding: 4px">0.2</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1</td></tr></table></body></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">
|
viewBox="0.00 0.00 712.00 344.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 340)">
|
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 340)">
|
||||||
<polygon fill="white" stroke="transparent" points="-4,4 -4,-340 708,-340 708,4 -4,4"/>
|
<polygon fill="white" stroke="transparent" points="-4,4 -4,-340 708,-340 708,4 -4,4"/>
|
||||||
<!-- F1 -->
|
<!-- _F1 -->
|
||||||
<g id="node1" class="node">
|
<g id="node1" class="node">
|
||||||
<title>F1</title>
|
<title>_F1</title>
|
||||||
<polygon fill="white" stroke="transparent" points="0,-300 109,-300 109,-336 0,-336 0,-300"/>
|
<polygon fill="white" stroke="transparent" points="0,-300 109,-300 109,-336 0,-336 0,-300"/>
|
||||||
<text text-anchor="start" x="3.5" y="-313.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
<text text-anchor="start" x="3.5" y="-313.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
||||||
<text text-anchor="start" x="98.5" y="-313.8" font-family="arial" font-size="14.00">  </text>
|
<text text-anchor="start" x="98.5" y="-313.8" font-family="arial" font-size="14.00">  </text>
|
||||||
@ -55,174 +55,174 @@
|
|||||||
<polyline fill="none" stroke="black" stroke-width="2" points="450,-107 254,-107 "/>
|
<polyline fill="none" stroke="black" stroke-width="2" points="450,-107 254,-107 "/>
|
||||||
<text text-anchor="start" x="281.5" y="-88.8" font-family="arial" font-size="14.00"> </text>
|
<text text-anchor="start" x="281.5" y="-88.8" font-family="arial" font-size="14.00"> </text>
|
||||||
</g>
|
</g>
|
||||||
<!-- F1--W1 -->
|
<!-- _F1--W1 -->
|
||||||
<g id="edge1" class="edge">
|
<g id="edge1" class="edge">
|
||||||
<title>F1:e--W1:w</title>
|
<title>_F1:e--W1:w</title>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-316C182.01,-318.14 176,-230.14 253,-228"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-316C182.01,-318.14 176,-230.14 253,-228"/>
|
||||||
<path fill="none" stroke="#666600" stroke-width="2" d="M109,-318C184,-318 178,-230 253,-230"/>
|
<path fill="none" stroke="#666600" stroke-width="2" d="M109,-318C184,-318 178,-230 253,-230"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-320C186,-317.86 179.99,-229.86 253,-232"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-320C186,-317.86 179.99,-229.86 253,-232"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F2 -->
|
<!-- _F2 -->
|
||||||
<g id="node2" class="node">
|
<g id="node2" class="node">
|
||||||
<title>F2</title>
|
<title>_F2</title>
|
||||||
<polygon fill="white" stroke="transparent" points="0,-240 109,-240 109,-276 0,-276 0,-240"/>
|
<polygon fill="white" stroke="transparent" points="0,-240 109,-240 109,-276 0,-276 0,-240"/>
|
||||||
<text text-anchor="start" x="3.5" y="-253.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
<text text-anchor="start" x="3.5" y="-253.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
||||||
<text text-anchor="start" x="98.5" y="-253.8" font-family="arial" font-size="14.00">  </text>
|
<text text-anchor="start" x="98.5" y="-253.8" font-family="arial" font-size="14.00">  </text>
|
||||||
<polygon fill="none" stroke="black" points="0,-247.5 0,-268.5 109,-268.5 109,-247.5 0,-247.5"/>
|
<polygon fill="none" stroke="black" points="0,-247.5 0,-268.5 109,-268.5 109,-247.5 0,-247.5"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F2--W1 -->
|
<!-- _F2--W1 -->
|
||||||
<g id="edge2" class="edge">
|
<g id="edge2" class="edge">
|
||||||
<title>F2:e--W1:w</title>
|
<title>_F2:e--W1:w</title>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-256C175.22,-257.72 182.82,-204.72 253,-203"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-256C175.22,-257.72 182.82,-204.72 253,-203"/>
|
||||||
<path fill="none" stroke="#ff0000" stroke-width="2" d="M109,-258C177.2,-258 184.8,-205 253,-205"/>
|
<path fill="none" stroke="#ff0000" stroke-width="2" d="M109,-258C177.2,-258 184.8,-205 253,-205"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-260C179.18,-258.28 186.78,-205.28 253,-207"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-260C179.18,-258.28 186.78,-205.28 253,-207"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F3 -->
|
<!-- _F3 -->
|
||||||
<g id="node3" class="node">
|
<g id="node3" class="node">
|
||||||
<title>F3</title>
|
<title>_F3</title>
|
||||||
<polygon fill="white" stroke="transparent" points="0,-180 109,-180 109,-216 0,-216 0,-180"/>
|
<polygon fill="white" stroke="transparent" points="0,-180 109,-180 109,-216 0,-216 0,-180"/>
|
||||||
<text text-anchor="start" x="3.5" y="-193.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
<text text-anchor="start" x="3.5" y="-193.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
||||||
<text text-anchor="start" x="98.5" y="-193.8" font-family="arial" font-size="14.00">  </text>
|
<text text-anchor="start" x="98.5" y="-193.8" font-family="arial" font-size="14.00">  </text>
|
||||||
<polygon fill="none" stroke="black" points="0,-187.5 0,-208.5 109,-208.5 109,-187.5 0,-187.5"/>
|
<polygon fill="none" stroke="black" points="0,-187.5 0,-208.5 109,-208.5 109,-187.5 0,-187.5"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F3--W1 -->
|
<!-- _F3--W1 -->
|
||||||
<g id="edge3" class="edge">
|
<g id="edge3" class="edge">
|
||||||
<title>F3:e--W1:w</title>
|
<title>_F3:e--W1:w</title>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-196C171.96,-196.72 186.97,-178.72 253,-178"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-196C171.96,-196.72 186.97,-178.72 253,-178"/>
|
||||||
<path fill="none" stroke="#ff8000" stroke-width="2" d="M109,-198C173.5,-198 188.5,-180 253,-180"/>
|
<path fill="none" stroke="#ff8000" stroke-width="2" d="M109,-198C173.5,-198 188.5,-180 253,-180"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-200C175.03,-199.28 190.04,-181.28 253,-182"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-200C175.03,-199.28 190.04,-181.28 253,-182"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F4 -->
|
<!-- _F4 -->
|
||||||
<g id="node4" class="node">
|
<g id="node4" class="node">
|
||||||
<title>F4</title>
|
<title>_F4</title>
|
||||||
<polygon fill="white" stroke="transparent" points="0,-120 109,-120 109,-156 0,-156 0,-120"/>
|
<polygon fill="white" stroke="transparent" points="0,-120 109,-120 109,-156 0,-156 0,-120"/>
|
||||||
<text text-anchor="start" x="3.5" y="-133.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
<text text-anchor="start" x="3.5" y="-133.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
||||||
<text text-anchor="start" x="98.5" y="-133.8" font-family="arial" font-size="14.00">  </text>
|
<text text-anchor="start" x="98.5" y="-133.8" font-family="arial" font-size="14.00">  </text>
|
||||||
<polygon fill="none" stroke="black" points="0,-127.5 0,-148.5 109,-148.5 109,-127.5 0,-127.5"/>
|
<polygon fill="none" stroke="black" points="0,-127.5 0,-148.5 109,-148.5 109,-127.5 0,-127.5"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F4--W1 -->
|
<!-- _F4--W1 -->
|
||||||
<g id="edge4" class="edge">
|
<g id="edge4" class="edge">
|
||||||
<title>F4:e--W1:w</title>
|
<title>_F4:e--W1:w</title>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-136C174.94,-136.67 190.05,-153.67 253,-153"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-136C174.94,-136.67 190.05,-153.67 253,-153"/>
|
||||||
<path fill="none" stroke="#ffff00" stroke-width="2" d="M109,-138C173.44,-138 188.56,-155 253,-155"/>
|
<path fill="none" stroke="#ffff00" stroke-width="2" d="M109,-138C173.44,-138 188.56,-155 253,-155"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-140C171.95,-139.33 187.06,-156.33 253,-157"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-140C171.95,-139.33 187.06,-156.33 253,-157"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F5 -->
|
<!-- _F5 -->
|
||||||
<g id="node5" class="node">
|
<g id="node5" class="node">
|
||||||
<title>F5</title>
|
<title>_F5</title>
|
||||||
<polygon fill="white" stroke="transparent" points="0,-60 109,-60 109,-96 0,-96 0,-60"/>
|
<polygon fill="white" stroke="transparent" points="0,-60 109,-60 109,-96 0,-96 0,-60"/>
|
||||||
<text text-anchor="start" x="3.5" y="-73.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
<text text-anchor="start" x="3.5" y="-73.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
||||||
<text text-anchor="start" x="98.5" y="-73.8" font-family="arial" font-size="14.00">  </text>
|
<text text-anchor="start" x="98.5" y="-73.8" font-family="arial" font-size="14.00">  </text>
|
||||||
<polygon fill="none" stroke="black" points="0,-67.5 0,-88.5 109,-88.5 109,-67.5 0,-67.5"/>
|
<polygon fill="none" stroke="black" points="0,-67.5 0,-88.5 109,-88.5 109,-67.5 0,-67.5"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F5--W1 -->
|
<!-- _F5--W1 -->
|
||||||
<g id="edge5" class="edge">
|
<g id="edge5" class="edge">
|
||||||
<title>F5:e--W1:w</title>
|
<title>_F5:e--W1:w</title>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-76C179.02,-77.7 186.93,-129.7 253,-128"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-76C179.02,-77.7 186.93,-129.7 253,-128"/>
|
||||||
<path fill="none" stroke="#00ff00" stroke-width="2" d="M109,-78C177.05,-78 184.95,-130 253,-130"/>
|
<path fill="none" stroke="#00ff00" stroke-width="2" d="M109,-78C177.05,-78 184.95,-130 253,-130"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-80C175.07,-78.3 182.98,-130.3 253,-132"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-80C175.07,-78.3 182.98,-130.3 253,-132"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F6 -->
|
<!-- _F6 -->
|
||||||
<g id="node6" class="node">
|
<g id="node6" class="node">
|
||||||
<title>F6</title>
|
<title>_F6</title>
|
||||||
<polygon fill="white" stroke="transparent" points="0,0 109,0 109,-36 0,-36 0,0"/>
|
<polygon fill="white" stroke="transparent" points="0,0 109,0 109,-36 0,-36 0,0"/>
|
||||||
<text text-anchor="start" x="3.5" y="-13.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
<text text-anchor="start" x="3.5" y="-13.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
||||||
<text text-anchor="start" x="98.5" y="-13.8" font-family="arial" font-size="14.00">  </text>
|
<text text-anchor="start" x="98.5" y="-13.8" font-family="arial" font-size="14.00">  </text>
|
||||||
<polygon fill="none" stroke="black" points="0,-7.5 0,-28.5 109,-28.5 109,-7.5 0,-7.5"/>
|
<polygon fill="none" stroke="black" points="0,-7.5 0,-28.5 109,-28.5 109,-7.5 0,-7.5"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F6--W1 -->
|
<!-- _F6--W1 -->
|
||||||
<g id="edge6" class="edge">
|
<g id="edge6" class="edge">
|
||||||
<title>F6:e--W1:w</title>
|
<title>_F6:e--W1:w</title>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-16C185.77,-18.13 180.22,-105.13 253,-103"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-16C185.77,-18.13 180.22,-105.13 253,-103"/>
|
||||||
<path fill="none" stroke="#0066ff" stroke-width="2" d="M109,-18C183.77,-18 178.23,-105 253,-105"/>
|
<path fill="none" stroke="#0066ff" stroke-width="2" d="M109,-18C183.77,-18 178.23,-105 253,-105"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-20C181.78,-17.87 176.23,-104.87 253,-107"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M109,-20C181.78,-17.87 176.23,-104.87 253,-107"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F7 -->
|
<!-- _F7 -->
|
||||||
<g id="node7" class="node">
|
<g id="node7" class="node">
|
||||||
<title>F7</title>
|
<title>_F7</title>
|
||||||
<polygon fill="white" stroke="transparent" points="704,-36 595,-36 595,0 704,0 704,-36"/>
|
<polygon fill="white" stroke="transparent" points="704,-36 595,-36 595,0 704,0 704,-36"/>
|
||||||
<text text-anchor="start" x="598.5" y="-13.8" font-family="arial" font-size="14.00">  </text>
|
<text text-anchor="start" x="598.5" y="-13.8" font-family="arial" font-size="14.00">  </text>
|
||||||
<text text-anchor="start" x="610.5" y="-13.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
<text text-anchor="start" x="610.5" y="-13.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
||||||
<polygon fill="none" stroke="black" points="595,-7.5 595,-28.5 704,-28.5 704,-7.5 595,-7.5"/>
|
<polygon fill="none" stroke="black" points="595,-7.5 595,-28.5 704,-28.5 704,-7.5 595,-7.5"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F8 -->
|
<!-- _F8 -->
|
||||||
<g id="node8" class="node">
|
<g id="node8" class="node">
|
||||||
<title>F8</title>
|
<title>_F8</title>
|
||||||
<polygon fill="white" stroke="transparent" points="704,-96 595,-96 595,-60 704,-60 704,-96"/>
|
<polygon fill="white" stroke="transparent" points="704,-96 595,-96 595,-60 704,-60 704,-96"/>
|
||||||
<text text-anchor="start" x="598.5" y="-73.8" font-family="arial" font-size="14.00">  </text>
|
<text text-anchor="start" x="598.5" y="-73.8" font-family="arial" font-size="14.00">  </text>
|
||||||
<text text-anchor="start" x="610.5" y="-73.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
<text text-anchor="start" x="610.5" y="-73.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
||||||
<polygon fill="none" stroke="black" points="595,-67.5 595,-88.5 704,-88.5 704,-67.5 595,-67.5"/>
|
<polygon fill="none" stroke="black" points="595,-67.5 595,-88.5 704,-88.5 704,-67.5 595,-67.5"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F9 -->
|
<!-- _F9 -->
|
||||||
<g id="node9" class="node">
|
<g id="node9" class="node">
|
||||||
<title>F9</title>
|
<title>_F9</title>
|
||||||
<polygon fill="white" stroke="transparent" points="704,-156 595,-156 595,-120 704,-120 704,-156"/>
|
<polygon fill="white" stroke="transparent" points="704,-156 595,-156 595,-120 704,-120 704,-156"/>
|
||||||
<text text-anchor="start" x="598.5" y="-133.8" font-family="arial" font-size="14.00">  </text>
|
<text text-anchor="start" x="598.5" y="-133.8" font-family="arial" font-size="14.00">  </text>
|
||||||
<text text-anchor="start" x="610.5" y="-133.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
<text text-anchor="start" x="610.5" y="-133.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
||||||
<polygon fill="none" stroke="black" points="595,-127.5 595,-148.5 704,-148.5 704,-127.5 595,-127.5"/>
|
<polygon fill="none" stroke="black" points="595,-127.5 595,-148.5 704,-148.5 704,-127.5 595,-127.5"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F10 -->
|
<!-- _F10 -->
|
||||||
<g id="node10" class="node">
|
<g id="node10" class="node">
|
||||||
<title>F10</title>
|
<title>_F10</title>
|
||||||
<polygon fill="white" stroke="transparent" points="704,-216 595,-216 595,-180 704,-180 704,-216"/>
|
<polygon fill="white" stroke="transparent" points="704,-216 595,-216 595,-180 704,-180 704,-216"/>
|
||||||
<text text-anchor="start" x="598.5" y="-193.8" font-family="arial" font-size="14.00">  </text>
|
<text text-anchor="start" x="598.5" y="-193.8" font-family="arial" font-size="14.00">  </text>
|
||||||
<text text-anchor="start" x="610.5" y="-193.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
<text text-anchor="start" x="610.5" y="-193.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
||||||
<polygon fill="none" stroke="black" points="595,-187.5 595,-208.5 704,-208.5 704,-187.5 595,-187.5"/>
|
<polygon fill="none" stroke="black" points="595,-187.5 595,-208.5 704,-208.5 704,-187.5 595,-187.5"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F11 -->
|
<!-- _F11 -->
|
||||||
<g id="node11" class="node">
|
<g id="node11" class="node">
|
||||||
<title>F11</title>
|
<title>_F11</title>
|
||||||
<polygon fill="white" stroke="transparent" points="704,-276 595,-276 595,-240 704,-240 704,-276"/>
|
<polygon fill="white" stroke="transparent" points="704,-276 595,-276 595,-240 704,-240 704,-276"/>
|
||||||
<text text-anchor="start" x="598.5" y="-253.8" font-family="arial" font-size="14.00">  </text>
|
<text text-anchor="start" x="598.5" y="-253.8" font-family="arial" font-size="14.00">  </text>
|
||||||
<text text-anchor="start" x="610.5" y="-253.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
<text text-anchor="start" x="610.5" y="-253.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
||||||
<polygon fill="none" stroke="black" points="595,-247.5 595,-268.5 704,-268.5 704,-247.5 595,-247.5"/>
|
<polygon fill="none" stroke="black" points="595,-247.5 595,-268.5 704,-268.5 704,-247.5 595,-247.5"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- F12 -->
|
<!-- _F12 -->
|
||||||
<g id="node12" class="node">
|
<g id="node12" class="node">
|
||||||
<title>F12</title>
|
<title>_F12</title>
|
||||||
<polygon fill="white" stroke="transparent" points="704,-336 595,-336 595,-300 704,-300 704,-336"/>
|
<polygon fill="white" stroke="transparent" points="704,-336 595,-336 595,-300 704,-300 704,-336"/>
|
||||||
<text text-anchor="start" x="598.5" y="-313.8" font-family="arial" font-size="14.00">  </text>
|
<text text-anchor="start" x="598.5" y="-313.8" font-family="arial" font-size="14.00">  </text>
|
||||||
<text text-anchor="start" x="610.5" y="-313.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
<text text-anchor="start" x="610.5" y="-313.8" font-family="arial" font-size="14.00"> Crimp ferrule  </text>
|
||||||
<polygon fill="none" stroke="black" points="595,-307.5 595,-328.5 704,-328.5 704,-307.5 595,-307.5"/>
|
<polygon fill="none" stroke="black" points="595,-307.5 595,-328.5 704,-328.5 704,-307.5 595,-307.5"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- W1--F7 -->
|
<!-- W1--_F7 -->
|
||||||
<g id="edge7" class="edge">
|
<g id="edge7" class="edge">
|
||||||
<title>W1:e--F7:w</title>
|
<title>W1:e--_F7:w</title>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-103C523.78,-105.13 518.23,-18.13 595,-16"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-103C523.78,-105.13 518.23,-18.13 595,-16"/>
|
||||||
<path fill="none" stroke="#0066ff" stroke-width="2" d="M451,-105C525.77,-105 520.23,-18 595,-18"/>
|
<path fill="none" stroke="#0066ff" stroke-width="2" d="M451,-105C525.77,-105 520.23,-18 595,-18"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-107C527.77,-104.87 522.22,-17.87 595,-20"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-107C527.77,-104.87 522.22,-17.87 595,-20"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- W1--F8 -->
|
<!-- W1--_F8 -->
|
||||||
<g id="edge8" class="edge">
|
<g id="edge8" class="edge">
|
||||||
<title>W1:e--F8:w</title>
|
<title>W1:e--_F8:w</title>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-128C517.07,-129.7 524.98,-77.7 595,-76"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-128C517.07,-129.7 524.98,-77.7 595,-76"/>
|
||||||
<path fill="none" stroke="#00ff00" stroke-width="2" d="M451,-130C519.05,-130 526.95,-78 595,-78"/>
|
<path fill="none" stroke="#00ff00" stroke-width="2" d="M451,-130C519.05,-130 526.95,-78 595,-78"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-132C521.02,-130.3 528.93,-78.3 595,-80"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-132C521.02,-130.3 528.93,-78.3 595,-80"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- W1--F9 -->
|
<!-- W1--_F9 -->
|
||||||
<g id="edge9" class="edge">
|
<g id="edge9" class="edge">
|
||||||
<title>W1:e--F9:w</title>
|
<title>W1:e--_F9:w</title>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-153C513.95,-153.67 529.06,-136.67 595,-136"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-153C513.95,-153.67 529.06,-136.67 595,-136"/>
|
||||||
<path fill="none" stroke="#ffff00" stroke-width="2" d="M451,-155C515.44,-155 530.56,-138 595,-138"/>
|
<path fill="none" stroke="#ffff00" stroke-width="2" d="M451,-155C515.44,-155 530.56,-138 595,-138"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-157C516.94,-156.33 532.05,-139.33 595,-140"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-157C516.94,-156.33 532.05,-139.33 595,-140"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- W1--F10 -->
|
<!-- W1--_F10 -->
|
||||||
<g id="edge10" class="edge">
|
<g id="edge10" class="edge">
|
||||||
<title>W1:e--F10:w</title>
|
<title>W1:e--_F10:w</title>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-178C517.03,-178.72 532.04,-196.72 595,-196"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-178C517.03,-178.72 532.04,-196.72 595,-196"/>
|
||||||
<path fill="none" stroke="#ff8000" stroke-width="2" d="M451,-180C515.5,-180 530.5,-198 595,-198"/>
|
<path fill="none" stroke="#ff8000" stroke-width="2" d="M451,-180C515.5,-180 530.5,-198 595,-198"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-182C513.96,-181.28 528.97,-199.28 595,-200"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-182C513.96,-181.28 528.97,-199.28 595,-200"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- W1--F11 -->
|
<!-- W1--_F11 -->
|
||||||
<g id="edge11" class="edge">
|
<g id="edge11" class="edge">
|
||||||
<title>W1:e--F11:w</title>
|
<title>W1:e--_F11:w</title>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-203C521.18,-204.72 528.78,-257.72 595,-256"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-203C521.18,-204.72 528.78,-257.72 595,-256"/>
|
||||||
<path fill="none" stroke="#ff0000" stroke-width="2" d="M451,-205C519.2,-205 526.8,-258 595,-258"/>
|
<path fill="none" stroke="#ff0000" stroke-width="2" d="M451,-205C519.2,-205 526.8,-258 595,-258"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-207C517.22,-205.28 524.82,-258.28 595,-260"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-207C517.22,-205.28 524.82,-258.28 595,-260"/>
|
||||||
</g>
|
</g>
|
||||||
<!-- W1--F12 -->
|
<!-- W1--_F12 -->
|
||||||
<g id="edge12" class="edge">
|
<g id="edge12" class="edge">
|
||||||
<title>W1:e--F12:w</title>
|
<title>W1:e--_F12:w</title>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-228C528,-230.14 521.99,-318.14 595,-316"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-228C528,-230.14 521.99,-318.14 595,-316"/>
|
||||||
<path fill="none" stroke="#666600" stroke-width="2" d="M451,-230C526,-230 520,-318 595,-318"/>
|
<path fill="none" stroke="#666600" stroke-width="2" d="M451,-230C526,-230 520,-318 595,-318"/>
|
||||||
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-232C524.01,-229.86 518,-317.86 595,-320"/>
|
<path fill="none" stroke="#000000" stroke-width="2" d="M451,-232C524.01,-229.86 518,-317.86 595,-320"/>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
@ -1,6 +1,6 @@
|
|||||||
Item Qty Unit Designators
|
Item Qty Unit Designators
|
||||||
Molex KK 254, female, 4 pins 3 X1, X2, X3
|
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², PK 0.4 m W1, W2
|
||||||
Wire 0.25 mm² TQ 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², VT 0.4 m W1, W2
|
||||||
Wire 0.25 mm² YE 0.4 m W1, W2
|
Wire, 0.25 mm², YE 0.4 m W1, W2
|
||||||
|
|||||||
|
@ -292,4 +292,4 @@
|
|||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
<h1>Bill of Materials</h1><table style="border:1px solid #000000; font-size: 14pt; border-spacing: 0px"><tr><th align="left" style="border:1px solid #000000; padding: 8px">Item</th><th align="left" style="border:1px solid #000000; padding: 8px">Qty</th><th align="left" style="border:1px solid #000000; padding: 8px">Unit</th><th align="left" style="border:1px solid #000000; padding: 8px">Designators</th></tr><tr><td style="border:1px solid #000000; padding: 4px">Molex KK 254, female, 4 pins</td><td align="right" style="border:1px solid #000000; padding: 4px">3</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px">X1, X2, X3</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire 0.25 mm² PK</td><td align="right" style="border:1px solid #000000; padding: 4px">0.4</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1, W2</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire 0.25 mm² TQ</td><td align="right" style="border:1px solid #000000; padding: 4px">0.4</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1, W2</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire 0.25 mm² VT</td><td align="right" style="border:1px solid #000000; padding: 4px">0.4</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1, W2</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire 0.25 mm² YE</td><td align="right" style="border:1px solid #000000; padding: 4px">0.4</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1, W2</td></tr></table></body></html>
|
<h1>Bill of Materials</h1><table style="border:1px solid #000000; font-size: 14pt; border-spacing: 0px"><tr><th align="left" style="border:1px solid #000000; padding: 8px">Item</th><th align="left" style="border:1px solid #000000; padding: 8px">Qty</th><th align="left" style="border:1px solid #000000; padding: 8px">Unit</th><th align="left" style="border:1px solid #000000; padding: 8px">Designators</th></tr><tr><td style="border:1px solid #000000; padding: 4px">Connector, Molex KK 254, female, 4 pins</td><td align="right" style="border:1px solid #000000; padding: 4px">3</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px">X1, X2, X3</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire, 0.25 mm², PK</td><td align="right" style="border:1px solid #000000; padding: 4px">0.4</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1, W2</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire, 0.25 mm², TQ</td><td align="right" style="border:1px solid #000000; padding: 4px">0.4</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1, W2</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire, 0.25 mm², VT</td><td align="right" style="border:1px solid #000000; padding: 4px">0.4</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1, W2</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire, 0.25 mm², YE</td><td align="right" style="border:1px solid #000000; padding: 4px">0.4</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1, W2</td></tr></table></body></html>
|
||||||
@ -1,6 +1,6 @@
|
|||||||
Item Qty Unit Designators
|
Item Qty Unit Designators
|
||||||
Molex KK 254, female, 4 pins 6 X1, X2, X3, X4, X5, X6
|
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², 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², 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², VT 1.0 m W1, W2, W3, W4, W5
|
||||||
Wire 0.25 mm² YE 1.0 m W1, W2, W3, W4, W5
|
Wire, 0.25 mm², YE 1.0 m W1, W2, W3, W4, W5
|
||||||
|
|||||||
|
@ -653,4 +653,4 @@
|
|||||||
</g>
|
</g>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
<h1>Bill of Materials</h1><table style="border:1px solid #000000; font-size: 14pt; border-spacing: 0px"><tr><th align="left" style="border:1px solid #000000; padding: 8px">Item</th><th align="left" style="border:1px solid #000000; padding: 8px">Qty</th><th align="left" style="border:1px solid #000000; padding: 8px">Unit</th><th align="left" style="border:1px solid #000000; padding: 8px">Designators</th></tr><tr><td style="border:1px solid #000000; padding: 4px">Molex KK 254, female, 4 pins</td><td align="right" style="border:1px solid #000000; padding: 4px">6</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px">X1, X2, X3, X4, X5, X6</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire 0.25 mm² PK</td><td align="right" style="border:1px solid #000000; padding: 4px">1.0</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1, W2, W3, W4, W5</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire 0.25 mm² TQ</td><td align="right" style="border:1px solid #000000; padding: 4px">1.0</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1, W2, W3, W4, W5</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire 0.25 mm² VT</td><td align="right" style="border:1px solid #000000; padding: 4px">1.0</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1, W2, W3, W4, W5</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire 0.25 mm² YE</td><td align="right" style="border:1px solid #000000; padding: 4px">1.0</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1, W2, W3, W4, W5</td></tr></table></body></html>
|
<h1>Bill of Materials</h1><table style="border:1px solid #000000; font-size: 14pt; border-spacing: 0px"><tr><th align="left" style="border:1px solid #000000; padding: 8px">Item</th><th align="left" style="border:1px solid #000000; padding: 8px">Qty</th><th align="left" style="border:1px solid #000000; padding: 8px">Unit</th><th align="left" style="border:1px solid #000000; padding: 8px">Designators</th></tr><tr><td style="border:1px solid #000000; padding: 4px">Connector, Molex KK 254, female, 4 pins</td><td align="right" style="border:1px solid #000000; padding: 4px">6</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px">X1, X2, X3, X4, X5, X6</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire, 0.25 mm², PK</td><td align="right" style="border:1px solid #000000; padding: 4px">1.0</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1, W2, W3, W4, W5</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire, 0.25 mm², TQ</td><td align="right" style="border:1px solid #000000; padding: 4px">1.0</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1, W2, W3, W4, W5</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire, 0.25 mm², VT</td><td align="right" style="border:1px solid #000000; padding: 4px">1.0</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1, W2, W3, W4, W5</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Wire, 0.25 mm², YE</td><td align="right" style="border:1px solid #000000; padding: 4px">1.0</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1, W2, W3, W4, W5</td></tr></table></body></html>
|
||||||
4
examples/ex07.bom.tsv
Normal file
@ -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
|
||||||
|
16
examples/ex07.gv
Normal file
@ -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}|{{<p5r>5|<p6r>6}}|Unconnected pins are not shown"]
|
||||||
|
X2 [label="X2|{D-Sub|female|9-pin}|{{<p2l>2|<p7l>7}}|Unconnected pins are not shown"]
|
||||||
|
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=<<table border="0" cellspacing="0" cellpadding="0"><tr><td><table border="0" cellspacing="0" cellpadding="3" cellborder="1"><tr><td colspan="3">C1</td></tr><tr><td>2x</td><td>20 AWG</td><td>1 m</td></tr></table></td></tr><tr><td> </td></tr><tr><td><table border="0" cellspacing="0" cellborder="0"><tr><td>X1:5</td><td>YE</td><td>X2:7</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#ffff00" border="2" sides="tb" port="w1"></td></tr><tr><td>X1:6</td><td>GN</td><td>X2:2</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#00ff00" border="2" sides="tb" port="w2"></td></tr><tr><td> </td></tr></table></td></tr></table>> fillcolor=white margin=0 shape=box style=""]
|
||||||
|
}
|
||||||
104
examples/ex07.html
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
<html><body style="font-family:Arial"><h1>Diagram</h1><?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||||
|
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<!-- Generated by graphviz version 2.44.0 (20200408.0750)
|
||||||
|
-->
|
||||||
|
<!-- Pages: 1 -->
|
||||||
|
<svg width="837pt" height="150pt"
|
||||||
|
viewBox="0.00 0.00 837.00 150.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 146)">
|
||||||
|
<polygon fill="white" stroke="transparent" points="-4,4 -4,-146 833,-146 833,4 -4,4"/>
|
||||||
|
<!-- X1 -->
|
||||||
|
<g id="node1" class="node">
|
||||||
|
<title>X1</title>
|
||||||
|
<polygon fill="white" stroke="black" points="0,-0.5 0,-115.5 213,-115.5 213,-0.5 0,-0.5"/>
|
||||||
|
<text text-anchor="middle" x="106.5" y="-100.3" font-family="arial" font-size="14.00">X1</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-92.5 213,-92.5 "/>
|
||||||
|
<text text-anchor="middle" x="48.5" y="-77.3" font-family="arial" font-size="14.00">TE 776164-1</text>
|
||||||
|
<polyline fill="none" stroke="black" points="97,-69.5 97,-92.5 "/>
|
||||||
|
<text text-anchor="middle" x="127" y="-77.3" font-family="arial" font-size="14.00">female</text>
|
||||||
|
<polyline fill="none" stroke="black" points="157,-69.5 157,-92.5 "/>
|
||||||
|
<text text-anchor="middle" x="185" y="-77.3" font-family="arial" font-size="14.00">35-pin</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-69.5 213,-69.5 "/>
|
||||||
|
<text text-anchor="middle" x="106.5" y="-54.3" font-family="arial" font-size="14.00">5</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-46.5 213,-46.5 "/>
|
||||||
|
<text text-anchor="middle" x="106.5" y="-31.3" font-family="arial" font-size="14.00">6</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-23.5 213,-23.5 "/>
|
||||||
|
<text text-anchor="middle" x="106.5" y="-8.3" font-family="arial" font-size="14.00">Unconnected pins are not shown</text>
|
||||||
|
</g>
|
||||||
|
<!-- C1 -->
|
||||||
|
<g id="node3" class="node">
|
||||||
|
<title>C1</title>
|
||||||
|
<polygon fill="none" stroke="black" points="472,-142 357,-142 357,-12 472,-12 472,-142"/>
|
||||||
|
<polygon fill="none" stroke="black" points="357.5,-119 357.5,-142 472.5,-142 472.5,-119 357.5,-119"/>
|
||||||
|
<text text-anchor="start" x="406" y="-126.8" font-family="arial" font-size="14.00">C1</text>
|
||||||
|
<polygon fill="none" stroke="black" points="357.5,-96 357.5,-119 380.5,-119 380.5,-96 357.5,-96"/>
|
||||||
|
<text text-anchor="start" x="361.5" y="-103.8" font-family="arial" font-size="14.00">2x</text>
|
||||||
|
<polygon fill="none" stroke="black" points="380.5,-96 380.5,-119 440.5,-119 440.5,-96 380.5,-96"/>
|
||||||
|
<text text-anchor="start" x="384.5" y="-103.8" font-family="arial" font-size="14.00">20 AWG</text>
|
||||||
|
<polygon fill="none" stroke="black" points="440.5,-96 440.5,-119 472.5,-119 472.5,-96 440.5,-96"/>
|
||||||
|
<text text-anchor="start" x="444.5" y="-103.8" font-family="arial" font-size="14.00">1 m</text>
|
||||||
|
<text text-anchor="start" x="413" y="-84.8" font-family="arial" font-size="14.00"> </text>
|
||||||
|
<text text-anchor="start" x="364" y="-67.8" font-family="arial" font-size="14.00">X1:5</text>
|
||||||
|
<text text-anchor="start" x="406" y="-67.8" font-family="arial" font-size="14.00">YE</text>
|
||||||
|
<text text-anchor="start" x="438.5" y="-67.8" font-family="arial" font-size="14.00">X2:7</text>
|
||||||
|
<polygon fill="#ffff00" stroke="transparent" points="357.5,-56 357.5,-62 472.5,-62 472.5,-56 357.5,-56"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="358.5,-57 471.5,-57 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="471.5,-61 358.5,-61 "/>
|
||||||
|
<text text-anchor="start" x="364" y="-42.8" font-family="arial" font-size="14.00">X1:6</text>
|
||||||
|
<text text-anchor="start" x="404.5" y="-42.8" font-family="arial" font-size="14.00">GN</text>
|
||||||
|
<text text-anchor="start" x="438.5" y="-42.8" font-family="arial" font-size="14.00">X2:2</text>
|
||||||
|
<polygon fill="#00ff00" stroke="transparent" stroke-width="2" points="357.5,-31 357.5,-37 472.5,-37 472.5,-31 357.5,-31"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="358.5,-32 471.5,-32 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="471.5,-36 358.5,-36 "/>
|
||||||
|
<text text-anchor="start" x="376" y="-17.8" font-family="arial" font-size="14.00"> </text>
|
||||||
|
</g>
|
||||||
|
<!-- X1--C1 -->
|
||||||
|
<g id="edge1" class="edge">
|
||||||
|
<title>X1:e--C1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M213,-56C277.13,-56 293.12,-57 357,-57"/>
|
||||||
|
<path fill="none" stroke="#ffff00" stroke-width="2" d="M213,-58C277,-58 293,-59 357,-59"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M213,-60C276.88,-60 292.87,-61 357,-61"/>
|
||||||
|
</g>
|
||||||
|
<!-- X1--C1 -->
|
||||||
|
<g id="edge3" class="edge">
|
||||||
|
<title>X1:e--C1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M213,-33C276.88,-33 292.87,-32 357,-32"/>
|
||||||
|
<path fill="none" stroke="#00ff00" stroke-width="2" d="M213,-35C277,-35 293,-34 357,-34"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M213,-37C277.13,-37 293.12,-36 357,-36"/>
|
||||||
|
</g>
|
||||||
|
<!-- X2 -->
|
||||||
|
<g id="node2" class="node">
|
||||||
|
<title>X2</title>
|
||||||
|
<polygon fill="white" stroke="black" points="616,-0.5 616,-115.5 829,-115.5 829,-0.5 616,-0.5"/>
|
||||||
|
<text text-anchor="middle" x="722.5" y="-100.3" font-family="arial" font-size="14.00">X2</text>
|
||||||
|
<polyline fill="none" stroke="black" points="616,-92.5 829,-92.5 "/>
|
||||||
|
<text text-anchor="middle" x="652" y="-77.3" font-family="arial" font-size="14.00">D-Sub</text>
|
||||||
|
<polyline fill="none" stroke="black" points="688,-69.5 688,-92.5 "/>
|
||||||
|
<text text-anchor="middle" x="726" y="-77.3" font-family="arial" font-size="14.00">female</text>
|
||||||
|
<polyline fill="none" stroke="black" points="764,-69.5 764,-92.5 "/>
|
||||||
|
<text text-anchor="middle" x="796.5" y="-77.3" font-family="arial" font-size="14.00">9-pin</text>
|
||||||
|
<polyline fill="none" stroke="black" points="616,-69.5 829,-69.5 "/>
|
||||||
|
<text text-anchor="middle" x="722.5" y="-54.3" font-family="arial" font-size="14.00">2</text>
|
||||||
|
<polyline fill="none" stroke="black" points="616,-46.5 829,-46.5 "/>
|
||||||
|
<text text-anchor="middle" x="722.5" y="-31.3" font-family="arial" font-size="14.00">7</text>
|
||||||
|
<polyline fill="none" stroke="black" points="616,-23.5 829,-23.5 "/>
|
||||||
|
<text text-anchor="middle" x="722.5" y="-8.3" font-family="arial" font-size="14.00">Unconnected pins are not shown</text>
|
||||||
|
</g>
|
||||||
|
<!-- C1--X2 -->
|
||||||
|
<g id="edge2" class="edge">
|
||||||
|
<title>C1:e--X2:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M472,-57C535.16,-57.98 549.4,-33.98 616,-33"/>
|
||||||
|
<path fill="none" stroke="#ffff00" stroke-width="2" d="M472,-59C536.88,-59 551.12,-35 616,-35"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M472,-61C538.6,-60.02 552.84,-36.02 616,-37"/>
|
||||||
|
</g>
|
||||||
|
<!-- C1--X2 -->
|
||||||
|
<g id="edge4" class="edge">
|
||||||
|
<title>C1:e--X2:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M472,-32C538.6,-32.98 552.84,-56.98 616,-56"/>
|
||||||
|
<path fill="none" stroke="#00ff00" stroke-width="2" d="M472,-34C536.88,-34 551.12,-58 616,-58"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M472,-36C535.16,-35.02 549.4,-59.02 616,-60"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
<h1>Bill of Materials</h1><table style="border:1px solid #000000; font-size: 14pt; border-spacing: 0px"><tr><th align="left" style="border:1px solid #000000; padding: 8px">Item</th><th align="left" style="border:1px solid #000000; padding: 8px">Qty</th><th align="left" style="border:1px solid #000000; padding: 8px">Unit</th><th align="left" style="border:1px solid #000000; padding: 8px">Designators</th></tr><tr><td style="border:1px solid #000000; padding: 4px">Connector, D-Sub, female, 9 pins</td><td align="right" style="border:1px solid #000000; padding: 4px">1</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px">X2</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Connector, TE 776164-1, female, 35 pins</td><td align="right" style="border:1px solid #000000; padding: 4px">1</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px">X1</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Cable, 2 x 20 AWG</td><td align="right" style="border:1px solid #000000; padding: 4px">1</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">C1</td></tr></table></body></html>
|
||||||
BIN
examples/ex07.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
103
examples/ex07.svg
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||||
|
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<!-- Generated by graphviz version 2.44.0 (20200408.0750)
|
||||||
|
-->
|
||||||
|
<!-- Pages: 1 -->
|
||||||
|
<svg width="837pt" height="150pt"
|
||||||
|
viewBox="0.00 0.00 837.00 150.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 146)">
|
||||||
|
<polygon fill="white" stroke="transparent" points="-4,4 -4,-146 833,-146 833,4 -4,4"/>
|
||||||
|
<!-- X1 -->
|
||||||
|
<g id="node1" class="node">
|
||||||
|
<title>X1</title>
|
||||||
|
<polygon fill="white" stroke="black" points="0,-0.5 0,-115.5 213,-115.5 213,-0.5 0,-0.5"/>
|
||||||
|
<text text-anchor="middle" x="106.5" y="-100.3" font-family="arial" font-size="14.00">X1</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-92.5 213,-92.5 "/>
|
||||||
|
<text text-anchor="middle" x="48.5" y="-77.3" font-family="arial" font-size="14.00">TE 776164-1</text>
|
||||||
|
<polyline fill="none" stroke="black" points="97,-69.5 97,-92.5 "/>
|
||||||
|
<text text-anchor="middle" x="127" y="-77.3" font-family="arial" font-size="14.00">female</text>
|
||||||
|
<polyline fill="none" stroke="black" points="157,-69.5 157,-92.5 "/>
|
||||||
|
<text text-anchor="middle" x="185" y="-77.3" font-family="arial" font-size="14.00">35-pin</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-69.5 213,-69.5 "/>
|
||||||
|
<text text-anchor="middle" x="106.5" y="-54.3" font-family="arial" font-size="14.00">5</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-46.5 213,-46.5 "/>
|
||||||
|
<text text-anchor="middle" x="106.5" y="-31.3" font-family="arial" font-size="14.00">6</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-23.5 213,-23.5 "/>
|
||||||
|
<text text-anchor="middle" x="106.5" y="-8.3" font-family="arial" font-size="14.00">Unconnected pins are not shown</text>
|
||||||
|
</g>
|
||||||
|
<!-- C1 -->
|
||||||
|
<g id="node3" class="node">
|
||||||
|
<title>C1</title>
|
||||||
|
<polygon fill="none" stroke="black" points="472,-142 357,-142 357,-12 472,-12 472,-142"/>
|
||||||
|
<polygon fill="none" stroke="black" points="357.5,-119 357.5,-142 472.5,-142 472.5,-119 357.5,-119"/>
|
||||||
|
<text text-anchor="start" x="406" y="-126.8" font-family="arial" font-size="14.00">C1</text>
|
||||||
|
<polygon fill="none" stroke="black" points="357.5,-96 357.5,-119 380.5,-119 380.5,-96 357.5,-96"/>
|
||||||
|
<text text-anchor="start" x="361.5" y="-103.8" font-family="arial" font-size="14.00">2x</text>
|
||||||
|
<polygon fill="none" stroke="black" points="380.5,-96 380.5,-119 440.5,-119 440.5,-96 380.5,-96"/>
|
||||||
|
<text text-anchor="start" x="384.5" y="-103.8" font-family="arial" font-size="14.00">20 AWG</text>
|
||||||
|
<polygon fill="none" stroke="black" points="440.5,-96 440.5,-119 472.5,-119 472.5,-96 440.5,-96"/>
|
||||||
|
<text text-anchor="start" x="444.5" y="-103.8" font-family="arial" font-size="14.00">1 m</text>
|
||||||
|
<text text-anchor="start" x="413" y="-84.8" font-family="arial" font-size="14.00"> </text>
|
||||||
|
<text text-anchor="start" x="364" y="-67.8" font-family="arial" font-size="14.00">X1:5</text>
|
||||||
|
<text text-anchor="start" x="406" y="-67.8" font-family="arial" font-size="14.00">YE</text>
|
||||||
|
<text text-anchor="start" x="438.5" y="-67.8" font-family="arial" font-size="14.00">X2:7</text>
|
||||||
|
<polygon fill="#ffff00" stroke="transparent" points="357.5,-56 357.5,-62 472.5,-62 472.5,-56 357.5,-56"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="358.5,-57 471.5,-57 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="471.5,-61 358.5,-61 "/>
|
||||||
|
<text text-anchor="start" x="364" y="-42.8" font-family="arial" font-size="14.00">X1:6</text>
|
||||||
|
<text text-anchor="start" x="404.5" y="-42.8" font-family="arial" font-size="14.00">GN</text>
|
||||||
|
<text text-anchor="start" x="438.5" y="-42.8" font-family="arial" font-size="14.00">X2:2</text>
|
||||||
|
<polygon fill="#00ff00" stroke="transparent" stroke-width="2" points="357.5,-31 357.5,-37 472.5,-37 472.5,-31 357.5,-31"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="358.5,-32 471.5,-32 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="471.5,-36 358.5,-36 "/>
|
||||||
|
<text text-anchor="start" x="376" y="-17.8" font-family="arial" font-size="14.00"> </text>
|
||||||
|
</g>
|
||||||
|
<!-- X1--C1 -->
|
||||||
|
<g id="edge1" class="edge">
|
||||||
|
<title>X1:e--C1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M213,-56C277.13,-56 293.12,-57 357,-57"/>
|
||||||
|
<path fill="none" stroke="#ffff00" stroke-width="2" d="M213,-58C277,-58 293,-59 357,-59"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M213,-60C276.88,-60 292.87,-61 357,-61"/>
|
||||||
|
</g>
|
||||||
|
<!-- X1--C1 -->
|
||||||
|
<g id="edge3" class="edge">
|
||||||
|
<title>X1:e--C1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M213,-33C276.88,-33 292.87,-32 357,-32"/>
|
||||||
|
<path fill="none" stroke="#00ff00" stroke-width="2" d="M213,-35C277,-35 293,-34 357,-34"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M213,-37C277.13,-37 293.12,-36 357,-36"/>
|
||||||
|
</g>
|
||||||
|
<!-- X2 -->
|
||||||
|
<g id="node2" class="node">
|
||||||
|
<title>X2</title>
|
||||||
|
<polygon fill="white" stroke="black" points="616,-0.5 616,-115.5 829,-115.5 829,-0.5 616,-0.5"/>
|
||||||
|
<text text-anchor="middle" x="722.5" y="-100.3" font-family="arial" font-size="14.00">X2</text>
|
||||||
|
<polyline fill="none" stroke="black" points="616,-92.5 829,-92.5 "/>
|
||||||
|
<text text-anchor="middle" x="652" y="-77.3" font-family="arial" font-size="14.00">D-Sub</text>
|
||||||
|
<polyline fill="none" stroke="black" points="688,-69.5 688,-92.5 "/>
|
||||||
|
<text text-anchor="middle" x="726" y="-77.3" font-family="arial" font-size="14.00">female</text>
|
||||||
|
<polyline fill="none" stroke="black" points="764,-69.5 764,-92.5 "/>
|
||||||
|
<text text-anchor="middle" x="796.5" y="-77.3" font-family="arial" font-size="14.00">9-pin</text>
|
||||||
|
<polyline fill="none" stroke="black" points="616,-69.5 829,-69.5 "/>
|
||||||
|
<text text-anchor="middle" x="722.5" y="-54.3" font-family="arial" font-size="14.00">2</text>
|
||||||
|
<polyline fill="none" stroke="black" points="616,-46.5 829,-46.5 "/>
|
||||||
|
<text text-anchor="middle" x="722.5" y="-31.3" font-family="arial" font-size="14.00">7</text>
|
||||||
|
<polyline fill="none" stroke="black" points="616,-23.5 829,-23.5 "/>
|
||||||
|
<text text-anchor="middle" x="722.5" y="-8.3" font-family="arial" font-size="14.00">Unconnected pins are not shown</text>
|
||||||
|
</g>
|
||||||
|
<!-- C1--X2 -->
|
||||||
|
<g id="edge2" class="edge">
|
||||||
|
<title>C1:e--X2:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M472,-57C535.16,-57.98 549.4,-33.98 616,-33"/>
|
||||||
|
<path fill="none" stroke="#ffff00" stroke-width="2" d="M472,-59C536.88,-59 551.12,-35 616,-35"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M472,-61C538.6,-60.02 552.84,-36.02 616,-37"/>
|
||||||
|
</g>
|
||||||
|
<!-- C1--X2 -->
|
||||||
|
<g id="edge4" class="edge">
|
||||||
|
<title>C1:e--X2:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M472,-32C538.6,-32.98 552.84,-56.98 616,-56"/>
|
||||||
|
<path fill="none" stroke="#00ff00" stroke-width="2" d="M472,-34C536.88,-34 551.12,-58 616,-58"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M472,-36C535.16,-35.02 549.4,-59.02 616,-60"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 6.7 KiB |
29
examples/ex07.yml
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# 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:
|
||||||
|
wirecount: 2
|
||||||
|
gauge: 20 AWG
|
||||||
|
colors: [YE, GN]
|
||||||
|
length: 1
|
||||||
|
|
||||||
|
connections:
|
||||||
|
-
|
||||||
|
- X1: [5,6]
|
||||||
|
- C1: [1,2]
|
||||||
|
- X2: [7,2]
|
||||||
3
examples/ex08.bom.tsv
Normal file
@ -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
|
||||||
|
17
examples/ex08.gv
Normal file
@ -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}|{{Dot|Dash|Ground}|{<pTr>T|<pRr>R|<pSr>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=<<table border="0" cellspacing="0" cellpadding="0"><tr><td><table border="0" cellspacing="0" cellpadding="3" cellborder="1"><tr><td colspan="4">W1</td></tr><tr><td>3x</td><td>24 AWG</td><td>+ S</td><td>0.2 m</td></tr></table></td></tr><tr><td> </td></tr><tr><td><table border="0" cellspacing="0" cellborder="0"><tr><td>Key:S</td><td>WH</td><td><!-- 1_out --></td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#ffffff" border="2" sides="tb" port="w1"></td></tr><tr><td>Key:R</td><td>BN</td><td><!-- 2_out --></td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#666600" border="2" sides="tb" port="w2"></td></tr><tr><td>Key:T</td><td>GN</td><td><!-- 3_out --></td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#00ff00" border="2" sides="tb" port="w3"></td></tr><tr><td> </td></tr><tr><td>Key:S</td><td>Shield</td><td><!-- s_out --></td></tr><tr><td colspan="3" cellpadding="0" height="6" border="2" sides="b" port="ws"></td></tr><tr><td> </td></tr></table></td></tr></table>> fillcolor=white margin=0 shape=box style=""]
|
||||||
|
}
|
||||||
97
examples/ex08.html
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
<html><body style="font-family:Arial"><h1>Diagram</h1><?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||||
|
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<!-- Generated by graphviz version 2.44.0 (20200408.0750)
|
||||||
|
-->
|
||||||
|
<!-- Pages: 1 -->
|
||||||
|
<svg width="499pt" height="207pt"
|
||||||
|
viewBox="0.00 0.00 499.00 207.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 203)">
|
||||||
|
<polygon fill="white" stroke="transparent" points="-4,4 -4,-203 495,-203 495,4 -4,4"/>
|
||||||
|
<!-- Key -->
|
||||||
|
<g id="node1" class="node">
|
||||||
|
<title>Key</title>
|
||||||
|
<polygon fill="white" stroke="black" points="0,-33 0,-148 191,-148 191,-33 0,-33"/>
|
||||||
|
<text text-anchor="middle" x="95.5" y="-132.8" font-family="arial" font-size="14.00">Key</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-125 191,-125 "/>
|
||||||
|
<text text-anchor="middle" x="61" y="-109.8" font-family="arial" font-size="14.00">Phone Connector</text>
|
||||||
|
<polyline fill="none" stroke="black" points="122,-102 122,-125 "/>
|
||||||
|
<text text-anchor="middle" x="156.5" y="-109.8" font-family="arial" font-size="14.00">male 3.5</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-102 191,-102 "/>
|
||||||
|
<text text-anchor="middle" x="56.5" y="-86.8" font-family="arial" font-size="14.00">Dot</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-79 113,-79 "/>
|
||||||
|
<text text-anchor="middle" x="56.5" y="-63.8" font-family="arial" font-size="14.00">Dash</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-56 113,-56 "/>
|
||||||
|
<text text-anchor="middle" x="56.5" y="-40.8" font-family="arial" font-size="14.00">Ground</text>
|
||||||
|
<polyline fill="none" stroke="black" points="113,-33 113,-102 "/>
|
||||||
|
<text text-anchor="middle" x="152" y="-86.8" font-family="arial" font-size="14.00">T</text>
|
||||||
|
<polyline fill="none" stroke="black" points="113,-79 191,-79 "/>
|
||||||
|
<text text-anchor="middle" x="152" y="-63.8" font-family="arial" font-size="14.00">R</text>
|
||||||
|
<polyline fill="none" stroke="black" points="113,-56 191,-56 "/>
|
||||||
|
<text text-anchor="middle" x="152" y="-40.8" font-family="arial" font-size="14.00">S</text>
|
||||||
|
</g>
|
||||||
|
<!-- W1 -->
|
||||||
|
<g id="node2" class="node">
|
||||||
|
<title>W1</title>
|
||||||
|
<polygon fill="none" stroke="black" points="491,-199 335,-199 335,0 491,0 491,-199"/>
|
||||||
|
<polygon fill="none" stroke="black" points="335,-175.5 335,-198.5 491,-198.5 491,-175.5 335,-175.5"/>
|
||||||
|
<text text-anchor="start" x="402" y="-183.3" font-family="arial" font-size="14.00">W1</text>
|
||||||
|
<polygon fill="none" stroke="black" points="335,-152.5 335,-175.5 358,-175.5 358,-152.5 335,-152.5"/>
|
||||||
|
<text text-anchor="start" x="339" y="-160.3" font-family="arial" font-size="14.00">3x</text>
|
||||||
|
<polygon fill="none" stroke="black" points="358,-152.5 358,-175.5 418,-175.5 418,-152.5 358,-152.5"/>
|
||||||
|
<text text-anchor="start" x="362" y="-160.3" font-family="arial" font-size="14.00">24 AWG</text>
|
||||||
|
<polygon fill="none" stroke="black" points="418,-152.5 418,-175.5 448,-175.5 448,-152.5 418,-152.5"/>
|
||||||
|
<text text-anchor="start" x="422" y="-160.3" font-family="arial" font-size="14.00">+ S</text>
|
||||||
|
<polygon fill="none" stroke="black" points="448,-152.5 448,-175.5 491,-175.5 491,-152.5 448,-152.5"/>
|
||||||
|
<text text-anchor="start" x="452" y="-160.3" font-family="arial" font-size="14.00">0.2 m</text>
|
||||||
|
<text text-anchor="start" x="411" y="-141.3" font-family="arial" font-size="14.00"> </text>
|
||||||
|
<text text-anchor="start" x="348.5" y="-124.3" font-family="arial" font-size="14.00">Key:S</text>
|
||||||
|
<text text-anchor="start" x="419.5" y="-124.3" font-family="arial" font-size="14.00">WH</text>
|
||||||
|
<polygon fill="#ffffff" stroke="transparent" points="335,-112.5 335,-118.5 491,-118.5 491,-112.5 335,-112.5"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="336,-113.5 490,-113.5 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="490,-117.5 336,-117.5 "/>
|
||||||
|
<text text-anchor="start" x="348.5" y="-99.3" font-family="arial" font-size="14.00">Key:R</text>
|
||||||
|
<text text-anchor="start" x="422" y="-99.3" font-family="arial" font-size="14.00">BN</text>
|
||||||
|
<polygon fill="#666600" stroke="transparent" stroke-width="2" points="335,-87.5 335,-93.5 491,-93.5 491,-87.5 335,-87.5"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="336,-88.5 490,-88.5 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="490,-92.5 336,-92.5 "/>
|
||||||
|
<text text-anchor="start" x="349" y="-74.3" font-family="arial" font-size="14.00">Key:T</text>
|
||||||
|
<text text-anchor="start" x="420.5" y="-74.3" font-family="arial" font-size="14.00">GN</text>
|
||||||
|
<polygon fill="#00ff00" stroke="transparent" stroke-width="2" points="335,-62.5 335,-68.5 491,-68.5 491,-62.5 335,-62.5"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="336,-63.5 490,-63.5 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="490,-67.5 336,-67.5 "/>
|
||||||
|
<text text-anchor="start" x="365" y="-49.3" font-family="arial" font-size="14.00"> </text>
|
||||||
|
<text text-anchor="start" x="348.5" y="-30.3" font-family="arial" font-size="14.00">Key:S</text>
|
||||||
|
<text text-anchor="start" x="412.5" y="-30.3" font-family="arial" font-size="14.00">Shield</text>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="336,-19.5 490,-19.5 "/>
|
||||||
|
<text text-anchor="start" x="365" y="-5.3" font-family="arial" font-size="14.00"> </text>
|
||||||
|
</g>
|
||||||
|
<!-- Key--W1 -->
|
||||||
|
<g id="edge1" class="edge">
|
||||||
|
<title>Key:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M191,-42.5C264.36,-44.46 265.64,-115.46 335,-113.5"/>
|
||||||
|
<path fill="none" stroke="#ffffff" stroke-width="2" d="M191,-44.5C262.36,-44.5 263.64,-115.5 335,-115.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M191,-46.5C260.36,-44.54 261.64,-115.54 335,-117.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- Key--W1 -->
|
||||||
|
<g id="edge2" class="edge">
|
||||||
|
<title>Key:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M191,-65.5C257.51,-66.44 271.88,-89.44 335,-88.5"/>
|
||||||
|
<path fill="none" stroke="#666600" stroke-width="2" d="M191,-67.5C255.81,-67.5 270.19,-90.5 335,-90.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M191,-69.5C254.12,-68.56 268.49,-91.56 335,-92.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- Key--W1 -->
|
||||||
|
<g id="edge3" class="edge">
|
||||||
|
<title>Key:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M191,-88.5C254.21,-89.52 268.3,-64.52 335,-63.5"/>
|
||||||
|
<path fill="none" stroke="#00ff00" stroke-width="2" d="M191,-90.5C255.96,-90.5 270.04,-65.5 335,-65.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M191,-92.5C257.7,-91.48 271.79,-66.48 335,-67.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- Key--W1 -->
|
||||||
|
<g id="edge4" class="edge">
|
||||||
|
<title>Key:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M191,-44.5C255.81,-44.5 270.19,-21.5 335,-21.5"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
<h1>Bill of Materials</h1><table style="border:1px solid #000000; font-size: 14pt; border-spacing: 0px"><tr><th align="left" style="border:1px solid #000000; padding: 8px">Item</th><th align="left" style="border:1px solid #000000; padding: 8px">Qty</th><th align="left" style="border:1px solid #000000; padding: 8px">Unit</th><th align="left" style="border:1px solid #000000; padding: 8px">Designators</th></tr><tr><td style="border:1px solid #000000; padding: 4px">Connector, Phone Connector, male 3.5, 3 pins</td><td align="right" style="border:1px solid #000000; padding: 4px">1</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px">Key</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Cable, 3 x 24 AWG shielded</td><td align="right" style="border:1px solid #000000; padding: 4px">0.2</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1</td></tr></table></body></html>
|
||||||
BIN
examples/ex08.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
96
examples/ex08.svg
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||||
|
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<!-- Generated by graphviz version 2.44.0 (20200408.0750)
|
||||||
|
-->
|
||||||
|
<!-- Pages: 1 -->
|
||||||
|
<svg width="499pt" height="207pt"
|
||||||
|
viewBox="0.00 0.00 499.00 207.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 203)">
|
||||||
|
<polygon fill="white" stroke="transparent" points="-4,4 -4,-203 495,-203 495,4 -4,4"/>
|
||||||
|
<!-- Key -->
|
||||||
|
<g id="node1" class="node">
|
||||||
|
<title>Key</title>
|
||||||
|
<polygon fill="white" stroke="black" points="0,-33 0,-148 191,-148 191,-33 0,-33"/>
|
||||||
|
<text text-anchor="middle" x="95.5" y="-132.8" font-family="arial" font-size="14.00">Key</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-125 191,-125 "/>
|
||||||
|
<text text-anchor="middle" x="61" y="-109.8" font-family="arial" font-size="14.00">Phone Connector</text>
|
||||||
|
<polyline fill="none" stroke="black" points="122,-102 122,-125 "/>
|
||||||
|
<text text-anchor="middle" x="156.5" y="-109.8" font-family="arial" font-size="14.00">male 3.5</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-102 191,-102 "/>
|
||||||
|
<text text-anchor="middle" x="56.5" y="-86.8" font-family="arial" font-size="14.00">Dot</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-79 113,-79 "/>
|
||||||
|
<text text-anchor="middle" x="56.5" y="-63.8" font-family="arial" font-size="14.00">Dash</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-56 113,-56 "/>
|
||||||
|
<text text-anchor="middle" x="56.5" y="-40.8" font-family="arial" font-size="14.00">Ground</text>
|
||||||
|
<polyline fill="none" stroke="black" points="113,-33 113,-102 "/>
|
||||||
|
<text text-anchor="middle" x="152" y="-86.8" font-family="arial" font-size="14.00">T</text>
|
||||||
|
<polyline fill="none" stroke="black" points="113,-79 191,-79 "/>
|
||||||
|
<text text-anchor="middle" x="152" y="-63.8" font-family="arial" font-size="14.00">R</text>
|
||||||
|
<polyline fill="none" stroke="black" points="113,-56 191,-56 "/>
|
||||||
|
<text text-anchor="middle" x="152" y="-40.8" font-family="arial" font-size="14.00">S</text>
|
||||||
|
</g>
|
||||||
|
<!-- W1 -->
|
||||||
|
<g id="node2" class="node">
|
||||||
|
<title>W1</title>
|
||||||
|
<polygon fill="none" stroke="black" points="491,-199 335,-199 335,0 491,0 491,-199"/>
|
||||||
|
<polygon fill="none" stroke="black" points="335,-175.5 335,-198.5 491,-198.5 491,-175.5 335,-175.5"/>
|
||||||
|
<text text-anchor="start" x="402" y="-183.3" font-family="arial" font-size="14.00">W1</text>
|
||||||
|
<polygon fill="none" stroke="black" points="335,-152.5 335,-175.5 358,-175.5 358,-152.5 335,-152.5"/>
|
||||||
|
<text text-anchor="start" x="339" y="-160.3" font-family="arial" font-size="14.00">3x</text>
|
||||||
|
<polygon fill="none" stroke="black" points="358,-152.5 358,-175.5 418,-175.5 418,-152.5 358,-152.5"/>
|
||||||
|
<text text-anchor="start" x="362" y="-160.3" font-family="arial" font-size="14.00">24 AWG</text>
|
||||||
|
<polygon fill="none" stroke="black" points="418,-152.5 418,-175.5 448,-175.5 448,-152.5 418,-152.5"/>
|
||||||
|
<text text-anchor="start" x="422" y="-160.3" font-family="arial" font-size="14.00">+ S</text>
|
||||||
|
<polygon fill="none" stroke="black" points="448,-152.5 448,-175.5 491,-175.5 491,-152.5 448,-152.5"/>
|
||||||
|
<text text-anchor="start" x="452" y="-160.3" font-family="arial" font-size="14.00">0.2 m</text>
|
||||||
|
<text text-anchor="start" x="411" y="-141.3" font-family="arial" font-size="14.00"> </text>
|
||||||
|
<text text-anchor="start" x="348.5" y="-124.3" font-family="arial" font-size="14.00">Key:S</text>
|
||||||
|
<text text-anchor="start" x="419.5" y="-124.3" font-family="arial" font-size="14.00">WH</text>
|
||||||
|
<polygon fill="#ffffff" stroke="transparent" points="335,-112.5 335,-118.5 491,-118.5 491,-112.5 335,-112.5"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="336,-113.5 490,-113.5 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="490,-117.5 336,-117.5 "/>
|
||||||
|
<text text-anchor="start" x="348.5" y="-99.3" font-family="arial" font-size="14.00">Key:R</text>
|
||||||
|
<text text-anchor="start" x="422" y="-99.3" font-family="arial" font-size="14.00">BN</text>
|
||||||
|
<polygon fill="#666600" stroke="transparent" stroke-width="2" points="335,-87.5 335,-93.5 491,-93.5 491,-87.5 335,-87.5"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="336,-88.5 490,-88.5 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="490,-92.5 336,-92.5 "/>
|
||||||
|
<text text-anchor="start" x="349" y="-74.3" font-family="arial" font-size="14.00">Key:T</text>
|
||||||
|
<text text-anchor="start" x="420.5" y="-74.3" font-family="arial" font-size="14.00">GN</text>
|
||||||
|
<polygon fill="#00ff00" stroke="transparent" stroke-width="2" points="335,-62.5 335,-68.5 491,-68.5 491,-62.5 335,-62.5"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="336,-63.5 490,-63.5 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="490,-67.5 336,-67.5 "/>
|
||||||
|
<text text-anchor="start" x="365" y="-49.3" font-family="arial" font-size="14.00"> </text>
|
||||||
|
<text text-anchor="start" x="348.5" y="-30.3" font-family="arial" font-size="14.00">Key:S</text>
|
||||||
|
<text text-anchor="start" x="412.5" y="-30.3" font-family="arial" font-size="14.00">Shield</text>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="336,-19.5 490,-19.5 "/>
|
||||||
|
<text text-anchor="start" x="365" y="-5.3" font-family="arial" font-size="14.00"> </text>
|
||||||
|
</g>
|
||||||
|
<!-- Key--W1 -->
|
||||||
|
<g id="edge1" class="edge">
|
||||||
|
<title>Key:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M191,-42.5C264.36,-44.46 265.64,-115.46 335,-113.5"/>
|
||||||
|
<path fill="none" stroke="#ffffff" stroke-width="2" d="M191,-44.5C262.36,-44.5 263.64,-115.5 335,-115.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M191,-46.5C260.36,-44.54 261.64,-115.54 335,-117.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- Key--W1 -->
|
||||||
|
<g id="edge2" class="edge">
|
||||||
|
<title>Key:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M191,-65.5C257.51,-66.44 271.88,-89.44 335,-88.5"/>
|
||||||
|
<path fill="none" stroke="#666600" stroke-width="2" d="M191,-67.5C255.81,-67.5 270.19,-90.5 335,-90.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M191,-69.5C254.12,-68.56 268.49,-91.56 335,-92.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- Key--W1 -->
|
||||||
|
<g id="edge3" class="edge">
|
||||||
|
<title>Key:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M191,-88.5C254.21,-89.52 268.3,-64.52 335,-63.5"/>
|
||||||
|
<path fill="none" stroke="#00ff00" stroke-width="2" d="M191,-90.5C255.96,-90.5 270.04,-65.5 335,-65.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M191,-92.5C257.7,-91.48 271.79,-66.48 335,-67.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- Key--W1 -->
|
||||||
|
<g id="edge4" class="edge">
|
||||||
|
<title>Key:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M191,-44.5C255.81,-44.5 270.19,-21.5 335,-21.5"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 6.5 KiB |
25
examples/ex08.yml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# contributed by @cocide
|
||||||
|
|
||||||
|
connectors:
|
||||||
|
Key:
|
||||||
|
type: Phone Connector
|
||||||
|
subtype: male 3.5
|
||||||
|
pinnumbers: [T, R, S]
|
||||||
|
pinout: [Dot, Dash, Ground]
|
||||||
|
show_pincount: false
|
||||||
|
|
||||||
|
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
|
||||||
4
examples/ex09.bom.tsv
Normal file
@ -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
|
||||||
|
48
examples/ex09.gv
Normal file
@ -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}|{<p1r>1|<p14r>14|<p3r>3|<p16r>16|<p5r>5|<p18r>18|<p7r>7|<p20r>20|<p9r>9|<p22r>22|<p11r>11|<p24r>24|<p13r>13}}"]
|
||||||
|
X2 [label="X2|{F48|female|48-pin}|{{<pz2l>z2|<pb2l>b2|<pd2l>d2|<pz4l>z4|<pb4l>b4|<pd4l>d4|<pz6l>z6|<pb6l>b6|<pd6l>d6|<pz8l>z8|<pb8l>b8|<pd8l>d8|<pz10l>z10|<pb10l>b10|<pd10l>d10|<pz12l>z12|<pb12l>b12|<pd12l>d12|<pz14l>z14|<pb14l>b14|<pd14l>d14|<pz16l>z16|<pb16l>b16|<pd16l>d16|<pz18l>z18|<pb18l>b18|<pd18l>d18|<pz20l>z20|<pb20l>b20|<pd20l>d20|<pz22l>z22|<pb22l>b22|<pd22l>d22|<pz24l>z24|<pb24l>b24|<pd24l>d24|<pz26l>z26|<pb26l>b26|<pd26l>d26|<pz28l>z28|<pb28l>b28|<pd28l>d28|<pz30l>z30|<pb30l>b30|<pd30l>d30|<pz32l>z32|<pb32l>b32|<pd32l>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=<<table border="0" cellspacing="0" cellpadding="0"><tr><td><table border="0" cellspacing="0" cellpadding="3" cellborder="1"><tr><td colspan="4">W1</td></tr><tr><td>12x</td><td>0.25 mm²</td><td>+ S</td><td>0.2 m</td></tr></table></td></tr><tr><td> </td></tr><tr><td><table border="0" cellspacing="0" cellborder="0"><tr><td>X1:14</td><td>WH</td><td>X2:z2</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#ffffff" border="2" sides="tb" port="w1"></td></tr><tr><td>X1:1</td><td>BN</td><td>X2:d4</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#666600" border="2" sides="tb" port="w2"></td></tr><tr><td>X1:16</td><td>GN</td><td>X2:z8</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#00ff00" border="2" sides="tb" port="w3"></td></tr><tr><td>X1:3</td><td>YE</td><td>X2:d10</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#ffff00" border="2" sides="tb" port="w4"></td></tr><tr><td>X1:18</td><td>GY</td><td>X2:z14</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#999999" border="2" sides="tb" port="w5"></td></tr><tr><td>X1:5</td><td>PK</td><td>X2:d16</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#ff66cc" border="2" sides="tb" port="w6"></td></tr><tr><td>X1:20</td><td>BU</td><td>X2:z18</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#0066ff" border="2" sides="tb" port="w7"></td></tr><tr><td>X1:7</td><td>RD</td><td>X2:d20</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#ff0000" border="2" sides="tb" port="w8"></td></tr><tr><td>X1:22</td><td>BK</td><td>X2:z24</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#000000" border="2" sides="tb" port="w9"></td></tr><tr><td>X1:9</td><td>VT</td><td>X2:d26</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#8000ff" border="2" sides="tb" port="w10"></td></tr><tr><td>X1:24</td><td>WH</td><td>X2:z30</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#ffffff" border="2" sides="tb" port="w11"></td></tr><tr><td>X1:11</td><td>BN</td><td>X2:d32</td></tr><tr><td colspan="3" cellpadding="0" height="6" bgcolor="#666600" border="2" sides="tb" port="w12"></td></tr><tr><td> </td></tr><tr><td>X1:13</td><td>Shield</td><td><!-- s_out --></td></tr><tr><td colspan="3" cellpadding="0" height="6" border="2" sides="b" port="ws"></td></tr><tr><td> </td></tr></table></td></tr></table>> fillcolor=white margin=0 shape=box style=""]
|
||||||
|
}
|
||||||
451
examples/ex09.html
Normal file
@ -0,0 +1,451 @@
|
|||||||
|
<html><body style="font-family:Arial"><h1>Diagram</h1><?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||||
|
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<!-- Generated by graphviz version 2.44.0 (20200408.0750)
|
||||||
|
-->
|
||||||
|
<!-- Pages: 1 -->
|
||||||
|
<svg width="774pt" height="1159pt"
|
||||||
|
viewBox="0.00 0.00 774.00 1159.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 1155)">
|
||||||
|
<polygon fill="white" stroke="transparent" points="-4,4 -4,-1155 770,-1155 770,4 -4,4"/>
|
||||||
|
<!-- X1 -->
|
||||||
|
<g id="node1" class="node">
|
||||||
|
<title>X1</title>
|
||||||
|
<polygon fill="white" stroke="black" points="0,-377 0,-722 156,-722 156,-377 0,-377"/>
|
||||||
|
<text text-anchor="middle" x="78" y="-706.8" font-family="arial" font-size="14.00">X1</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-699 156,-699 "/>
|
||||||
|
<text text-anchor="middle" x="27.5" y="-683.8" font-family="arial" font-size="14.00">D-Sub</text>
|
||||||
|
<polyline fill="none" stroke="black" points="55,-676 55,-699 "/>
|
||||||
|
<text text-anchor="middle" x="78.5" y="-683.8" font-family="arial" font-size="14.00">male</text>
|
||||||
|
<polyline fill="none" stroke="black" points="102,-676 102,-699 "/>
|
||||||
|
<text text-anchor="middle" x="129" y="-683.8" font-family="arial" font-size="14.00">25-pin</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-676 156,-676 "/>
|
||||||
|
<text text-anchor="middle" x="54.5" y="-660.8" font-family="arial" font-size="14.00">SENSE_P_1</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-653 109,-653 "/>
|
||||||
|
<text text-anchor="middle" x="54.5" y="-637.8" font-family="arial" font-size="14.00">SENSE_N_1</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-630 109,-630 "/>
|
||||||
|
<text text-anchor="middle" x="54.5" y="-614.8" font-family="arial" font-size="14.00">SENSE_P_2</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-607 109,-607 "/>
|
||||||
|
<text text-anchor="middle" x="54.5" y="-591.8" font-family="arial" font-size="14.00">SENSE_N_2</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-584 109,-584 "/>
|
||||||
|
<text text-anchor="middle" x="54.5" y="-568.8" font-family="arial" font-size="14.00">SENSE_P_3</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-561 109,-561 "/>
|
||||||
|
<text text-anchor="middle" x="54.5" y="-545.8" font-family="arial" font-size="14.00">SENSE_N_3</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-538 109,-538 "/>
|
||||||
|
<text text-anchor="middle" x="54.5" y="-522.8" font-family="arial" font-size="14.00">SENSE_P_4</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-515 109,-515 "/>
|
||||||
|
<text text-anchor="middle" x="54.5" y="-499.8" font-family="arial" font-size="14.00">SENSE_N_4</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-492 109,-492 "/>
|
||||||
|
<text text-anchor="middle" x="54.5" y="-476.8" font-family="arial" font-size="14.00">SENSE_P_5</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-469 109,-469 "/>
|
||||||
|
<text text-anchor="middle" x="54.5" y="-453.8" font-family="arial" font-size="14.00">SENSE_N_5</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-446 109,-446 "/>
|
||||||
|
<text text-anchor="middle" x="54.5" y="-430.8" font-family="arial" font-size="14.00">SENSE_P_6</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-423 109,-423 "/>
|
||||||
|
<text text-anchor="middle" x="54.5" y="-407.8" font-family="arial" font-size="14.00">SENSE_N_6</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-400 109,-400 "/>
|
||||||
|
<text text-anchor="middle" x="54.5" y="-384.8" font-family="arial" font-size="14.00">GND</text>
|
||||||
|
<polyline fill="none" stroke="black" points="109,-377 109,-676 "/>
|
||||||
|
<text text-anchor="middle" x="132.5" y="-660.8" font-family="arial" font-size="14.00">1</text>
|
||||||
|
<polyline fill="none" stroke="black" points="109,-653 156,-653 "/>
|
||||||
|
<text text-anchor="middle" x="132.5" y="-637.8" font-family="arial" font-size="14.00">14</text>
|
||||||
|
<polyline fill="none" stroke="black" points="109,-630 156,-630 "/>
|
||||||
|
<text text-anchor="middle" x="132.5" y="-614.8" font-family="arial" font-size="14.00">3</text>
|
||||||
|
<polyline fill="none" stroke="black" points="109,-607 156,-607 "/>
|
||||||
|
<text text-anchor="middle" x="132.5" y="-591.8" font-family="arial" font-size="14.00">16</text>
|
||||||
|
<polyline fill="none" stroke="black" points="109,-584 156,-584 "/>
|
||||||
|
<text text-anchor="middle" x="132.5" y="-568.8" font-family="arial" font-size="14.00">5</text>
|
||||||
|
<polyline fill="none" stroke="black" points="109,-561 156,-561 "/>
|
||||||
|
<text text-anchor="middle" x="132.5" y="-545.8" font-family="arial" font-size="14.00">18</text>
|
||||||
|
<polyline fill="none" stroke="black" points="109,-538 156,-538 "/>
|
||||||
|
<text text-anchor="middle" x="132.5" y="-522.8" font-family="arial" font-size="14.00">7</text>
|
||||||
|
<polyline fill="none" stroke="black" points="109,-515 156,-515 "/>
|
||||||
|
<text text-anchor="middle" x="132.5" y="-499.8" font-family="arial" font-size="14.00">20</text>
|
||||||
|
<polyline fill="none" stroke="black" points="109,-492 156,-492 "/>
|
||||||
|
<text text-anchor="middle" x="132.5" y="-476.8" font-family="arial" font-size="14.00">9</text>
|
||||||
|
<polyline fill="none" stroke="black" points="109,-469 156,-469 "/>
|
||||||
|
<text text-anchor="middle" x="132.5" y="-453.8" font-family="arial" font-size="14.00">22</text>
|
||||||
|
<polyline fill="none" stroke="black" points="109,-446 156,-446 "/>
|
||||||
|
<text text-anchor="middle" x="132.5" y="-430.8" font-family="arial" font-size="14.00">11</text>
|
||||||
|
<polyline fill="none" stroke="black" points="109,-423 156,-423 "/>
|
||||||
|
<text text-anchor="middle" x="132.5" y="-407.8" font-family="arial" font-size="14.00">24</text>
|
||||||
|
<polyline fill="none" stroke="black" points="109,-400 156,-400 "/>
|
||||||
|
<text text-anchor="middle" x="132.5" y="-384.8" font-family="arial" font-size="14.00">13</text>
|
||||||
|
</g>
|
||||||
|
<!-- W1 -->
|
||||||
|
<g id="node3" class="node">
|
||||||
|
<title>W1</title>
|
||||||
|
<polygon fill="none" stroke="black" points="470,-772.5 300,-772.5 300,-348.5 470,-348.5 470,-772.5"/>
|
||||||
|
<polygon fill="none" stroke="black" points="300,-749.5 300,-772.5 470,-772.5 470,-749.5 300,-749.5"/>
|
||||||
|
<text text-anchor="start" x="374" y="-757.3" font-family="arial" font-size="14.00">W1</text>
|
||||||
|
<polygon fill="none" stroke="black" points="300,-726.5 300,-749.5 330,-749.5 330,-726.5 300,-726.5"/>
|
||||||
|
<text text-anchor="start" x="304" y="-734.3" font-family="arial" font-size="14.00">12x</text>
|
||||||
|
<polygon fill="none" stroke="black" points="330,-726.5 330,-749.5 397,-749.5 397,-726.5 330,-726.5"/>
|
||||||
|
<text text-anchor="start" x="334" y="-734.3" font-family="arial" font-size="14.00">0.25 mm²</text>
|
||||||
|
<polygon fill="none" stroke="black" points="397,-726.5 397,-749.5 427,-749.5 427,-726.5 397,-726.5"/>
|
||||||
|
<text text-anchor="start" x="401" y="-734.3" font-family="arial" font-size="14.00">+ S</text>
|
||||||
|
<polygon fill="none" stroke="black" points="427,-726.5 427,-749.5 470,-749.5 470,-726.5 427,-726.5"/>
|
||||||
|
<text text-anchor="start" x="431" y="-734.3" font-family="arial" font-size="14.00">0.2 m</text>
|
||||||
|
<text text-anchor="start" x="383" y="-715.3" font-family="arial" font-size="14.00"> </text>
|
||||||
|
<text text-anchor="start" x="309" y="-698.3" font-family="arial" font-size="14.00">X1:14</text>
|
||||||
|
<text text-anchor="start" x="370" y="-698.3" font-family="arial" font-size="14.00">WH</text>
|
||||||
|
<text text-anchor="start" x="422.5" y="-698.3" font-family="arial" font-size="14.00">X2:z2</text>
|
||||||
|
<polygon fill="#ffffff" stroke="transparent" points="300,-686.5 300,-692.5 470,-692.5 470,-686.5 300,-686.5"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="301,-687.5 469,-687.5 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="469,-691.5 301,-691.5 "/>
|
||||||
|
<text text-anchor="start" x="313" y="-673.3" font-family="arial" font-size="14.00">X1:1</text>
|
||||||
|
<text text-anchor="start" x="372.5" y="-673.3" font-family="arial" font-size="14.00">BN</text>
|
||||||
|
<text text-anchor="start" x="422" y="-673.3" font-family="arial" font-size="14.00">X2:d4</text>
|
||||||
|
<polygon fill="#666600" stroke="transparent" stroke-width="2" points="300,-661.5 300,-667.5 470,-667.5 470,-661.5 300,-661.5"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="301,-662.5 469,-662.5 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="469,-666.5 301,-666.5 "/>
|
||||||
|
<text text-anchor="start" x="309" y="-648.3" font-family="arial" font-size="14.00">X1:16</text>
|
||||||
|
<text text-anchor="start" x="371" y="-648.3" font-family="arial" font-size="14.00">GN</text>
|
||||||
|
<text text-anchor="start" x="422.5" y="-648.3" font-family="arial" font-size="14.00">X2:z8</text>
|
||||||
|
<polygon fill="#00ff00" stroke="transparent" stroke-width="2" points="300,-636.5 300,-642.5 470,-642.5 470,-636.5 300,-636.5"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="301,-637.5 469,-637.5 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="469,-641.5 301,-641.5 "/>
|
||||||
|
<text text-anchor="start" x="313" y="-623.3" font-family="arial" font-size="14.00">X1:3</text>
|
||||||
|
<text text-anchor="start" x="372.5" y="-623.3" font-family="arial" font-size="14.00">YE</text>
|
||||||
|
<text text-anchor="start" x="418.5" y="-623.3" font-family="arial" font-size="14.00">X2:d10</text>
|
||||||
|
<polygon fill="#ffff00" stroke="transparent" stroke-width="2" points="300,-611.5 300,-617.5 470,-617.5 470,-611.5 300,-611.5"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="301,-612.5 469,-612.5 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="469,-616.5 301,-616.5 "/>
|
||||||
|
<text text-anchor="start" x="309" y="-598.3" font-family="arial" font-size="14.00">X1:18</text>
|
||||||
|
<text text-anchor="start" x="371.5" y="-598.3" font-family="arial" font-size="14.00">GY</text>
|
||||||
|
<text text-anchor="start" x="418.5" y="-598.3" font-family="arial" font-size="14.00">X2:z14</text>
|
||||||
|
<polygon fill="#999999" stroke="transparent" stroke-width="2" points="300,-586.5 300,-592.5 470,-592.5 470,-586.5 300,-586.5"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="301,-587.5 469,-587.5 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="469,-591.5 301,-591.5 "/>
|
||||||
|
<text text-anchor="start" x="313" y="-573.3" font-family="arial" font-size="14.00">X1:5</text>
|
||||||
|
<text text-anchor="start" x="372.5" y="-573.3" font-family="arial" font-size="14.00">PK</text>
|
||||||
|
<text text-anchor="start" x="418.5" y="-573.3" font-family="arial" font-size="14.00">X2:d16</text>
|
||||||
|
<polygon fill="#ff66cc" stroke="transparent" stroke-width="2" points="300,-561.5 300,-567.5 470,-567.5 470,-561.5 300,-561.5"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="301,-562.5 469,-562.5 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="469,-566.5 301,-566.5 "/>
|
||||||
|
<text text-anchor="start" x="309" y="-548.3" font-family="arial" font-size="14.00">X1:20</text>
|
||||||
|
<text text-anchor="start" x="372.5" y="-548.3" font-family="arial" font-size="14.00">BU</text>
|
||||||
|
<text text-anchor="start" x="418.5" y="-548.3" font-family="arial" font-size="14.00">X2:z18</text>
|
||||||
|
<polygon fill="#0066ff" stroke="transparent" stroke-width="2" points="300,-536.5 300,-542.5 470,-542.5 470,-536.5 300,-536.5"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="301,-537.5 469,-537.5 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="469,-541.5 301,-541.5 "/>
|
||||||
|
<text text-anchor="start" x="313" y="-523.3" font-family="arial" font-size="14.00">X1:7</text>
|
||||||
|
<text text-anchor="start" x="372" y="-523.3" font-family="arial" font-size="14.00">RD</text>
|
||||||
|
<text text-anchor="start" x="418.5" y="-523.3" font-family="arial" font-size="14.00">X2:d20</text>
|
||||||
|
<polygon fill="#ff0000" stroke="transparent" stroke-width="2" points="300,-511.5 300,-517.5 470,-517.5 470,-511.5 300,-511.5"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="301,-512.5 469,-512.5 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="469,-516.5 301,-516.5 "/>
|
||||||
|
<text text-anchor="start" x="309" y="-498.3" font-family="arial" font-size="14.00">X1:22</text>
|
||||||
|
<text text-anchor="start" x="372.5" y="-498.3" font-family="arial" font-size="14.00">BK</text>
|
||||||
|
<text text-anchor="start" x="418.5" y="-498.3" font-family="arial" font-size="14.00">X2:z24</text>
|
||||||
|
<polygon fill="#000000" stroke="transparent" stroke-width="2" points="300,-486.5 300,-492.5 470,-492.5 470,-486.5 300,-486.5"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="301,-487.5 469,-487.5 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="469,-491.5 301,-491.5 "/>
|
||||||
|
<text text-anchor="start" x="313" y="-473.3" font-family="arial" font-size="14.00">X1:9</text>
|
||||||
|
<text text-anchor="start" x="373" y="-473.3" font-family="arial" font-size="14.00">VT</text>
|
||||||
|
<text text-anchor="start" x="418.5" y="-473.3" font-family="arial" font-size="14.00">X2:d26</text>
|
||||||
|
<polygon fill="#8000ff" stroke="transparent" stroke-width="2" points="300,-461.5 300,-467.5 470,-467.5 470,-461.5 300,-461.5"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="301,-462.5 469,-462.5 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="469,-466.5 301,-466.5 "/>
|
||||||
|
<text text-anchor="start" x="309" y="-448.3" font-family="arial" font-size="14.00">X1:24</text>
|
||||||
|
<text text-anchor="start" x="370" y="-448.3" font-family="arial" font-size="14.00">WH</text>
|
||||||
|
<text text-anchor="start" x="418.5" y="-448.3" font-family="arial" font-size="14.00">X2:z30</text>
|
||||||
|
<polygon fill="#ffffff" stroke="transparent" stroke-width="2" points="300,-436.5 300,-442.5 470,-442.5 470,-436.5 300,-436.5"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="301,-437.5 469,-437.5 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="469,-441.5 301,-441.5 "/>
|
||||||
|
<text text-anchor="start" x="309.5" y="-423.3" font-family="arial" font-size="14.00">X1:11</text>
|
||||||
|
<text text-anchor="start" x="372.5" y="-423.3" font-family="arial" font-size="14.00">BN</text>
|
||||||
|
<text text-anchor="start" x="418.5" y="-423.3" font-family="arial" font-size="14.00">X2:d32</text>
|
||||||
|
<polygon fill="#666600" stroke="transparent" stroke-width="2" points="300,-411.5 300,-417.5 470,-417.5 470,-411.5 300,-411.5"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="301,-412.5 469,-412.5 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="469,-416.5 301,-416.5 "/>
|
||||||
|
<text text-anchor="start" x="325" y="-398.3" font-family="arial" font-size="14.00"> </text>
|
||||||
|
<text text-anchor="start" x="309" y="-379.3" font-family="arial" font-size="14.00">X1:13</text>
|
||||||
|
<text text-anchor="start" x="363" y="-379.3" font-family="arial" font-size="14.00">Shield</text>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="301,-368.5 469,-368.5 "/>
|
||||||
|
<text text-anchor="start" x="325" y="-354.3" font-family="arial" font-size="14.00"> </text>
|
||||||
|
</g>
|
||||||
|
<!-- X1--W1 -->
|
||||||
|
<g id="edge1" class="edge">
|
||||||
|
<title>X1:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-662.5C220,-662.5 236,-662.5 300,-662.5"/>
|
||||||
|
<path fill="none" stroke="#666600" stroke-width="2" d="M156,-664.5C220,-664.5 236,-664.5 300,-664.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-666.5C220,-666.5 236,-666.5 300,-666.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- X1--W1 -->
|
||||||
|
<g id="edge3" class="edge">
|
||||||
|
<title>X1:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-639.5C225.43,-641.13 234.5,-689.13 300,-687.5"/>
|
||||||
|
<path fill="none" stroke="#ffffff" stroke-width="2" d="M156,-641.5C223.46,-641.5 232.54,-689.5 300,-689.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-643.5C221.5,-641.87 230.57,-689.87 300,-691.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- X1--W1 -->
|
||||||
|
<g id="edge5" class="edge">
|
||||||
|
<title>X1:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-616.5C219.54,-616.56 235.49,-612.56 300,-612.5"/>
|
||||||
|
<path fill="none" stroke="#ffff00" stroke-width="2" d="M156,-618.5C220.02,-618.5 235.98,-614.5 300,-614.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-620.5C220.51,-620.44 236.46,-616.44 300,-616.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- X1--W1 -->
|
||||||
|
<g id="edge7" class="edge">
|
||||||
|
<title>X1:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-593.5C224.87,-595.05 235.03,-639.05 300,-637.5"/>
|
||||||
|
<path fill="none" stroke="#00ff00" stroke-width="2" d="M156,-595.5C222.92,-595.5 233.08,-639.5 300,-639.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-597.5C220.97,-595.95 231.13,-639.95 300,-641.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- X1--W1 -->
|
||||||
|
<g id="edge9" class="edge">
|
||||||
|
<title>X1:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-570.5C219.2,-570.72 235,-562.72 300,-562.5"/>
|
||||||
|
<path fill="none" stroke="#ff66cc" stroke-width="2" d="M156,-572.5C220.1,-572.5 235.9,-564.5 300,-564.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-574.5C221,-574.28 236.8,-566.28 300,-566.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- X1--W1 -->
|
||||||
|
<g id="edge11" class="edge">
|
||||||
|
<title>X1:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-547.5C224.35,-548.96 235.5,-588.96 300,-587.5"/>
|
||||||
|
<path fill="none" stroke="#999999" stroke-width="2" d="M156,-549.5C222.42,-549.5 233.58,-589.5 300,-589.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-551.5C220.5,-550.04 231.65,-590.04 300,-591.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- X1--W1 -->
|
||||||
|
<g id="edge13" class="edge">
|
||||||
|
<title>X1:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-524.5C219,-524.92 234.56,-512.92 300,-512.5"/>
|
||||||
|
<path fill="none" stroke="#ff0000" stroke-width="2" d="M156,-526.5C220.22,-526.5 235.78,-514.5 300,-514.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-528.5C221.44,-528.08 237,-516.08 300,-516.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- X1--W1 -->
|
||||||
|
<g id="edge15" class="edge">
|
||||||
|
<title>X1:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-501.5C223.87,-502.86 235.93,-538.86 300,-537.5"/>
|
||||||
|
<path fill="none" stroke="#0066ff" stroke-width="2" d="M156,-503.5C221.97,-503.5 234.03,-539.5 300,-539.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-505.5C220.07,-504.14 232.13,-540.14 300,-541.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- X1--W1 -->
|
||||||
|
<g id="edge17" class="edge">
|
||||||
|
<title>X1:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-478.5C218.94,-479.12 234.16,-463.12 300,-462.5"/>
|
||||||
|
<path fill="none" stroke="#8000ff" stroke-width="2" d="M156,-480.5C220.39,-480.5 235.61,-464.5 300,-464.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-482.5C221.84,-481.88 237.06,-465.88 300,-466.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- X1--W1 -->
|
||||||
|
<g id="edge19" class="edge">
|
||||||
|
<title>X1:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-455.5C223.42,-456.75 236.29,-488.75 300,-487.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-457.5C221.56,-457.5 234.44,-489.5 300,-489.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-459.5C219.71,-458.25 232.58,-490.25 300,-491.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- X1--W1 -->
|
||||||
|
<g id="edge21" class="edge">
|
||||||
|
<title>X1:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-432.5C219.01,-433.31 233.78,-413.31 300,-412.5"/>
|
||||||
|
<path fill="none" stroke="#666600" stroke-width="2" d="M156,-434.5C220.61,-434.5 235.39,-414.5 300,-414.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-436.5C222.22,-435.69 236.99,-415.69 300,-416.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- X1--W1 -->
|
||||||
|
<g id="edge23" class="edge">
|
||||||
|
<title>X1:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-409.5C223,-410.63 236.6,-438.63 300,-437.5"/>
|
||||||
|
<path fill="none" stroke="#ffffff" stroke-width="2" d="M156,-411.5C221.2,-411.5 234.8,-439.5 300,-439.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-413.5C219.4,-412.37 233,-440.37 300,-441.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- X1--W1 -->
|
||||||
|
<g id="edge25" class="edge">
|
||||||
|
<title>X1:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-388.5C220.5,-388.5 235.5,-370.5 300,-370.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- X2 -->
|
||||||
|
<g id="node2" class="node">
|
||||||
|
<title>X2</title>
|
||||||
|
<polygon fill="white" stroke="black" points="614,-0.5 614,-1150.5 766,-1150.5 766,-0.5 614,-0.5"/>
|
||||||
|
<text text-anchor="middle" x="690" y="-1135.3" font-family="arial" font-size="14.00">X2</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-1127.5 766,-1127.5 "/>
|
||||||
|
<text text-anchor="middle" x="634" y="-1112.3" font-family="arial" font-size="14.00">F48</text>
|
||||||
|
<polyline fill="none" stroke="black" points="654,-1104.5 654,-1127.5 "/>
|
||||||
|
<text text-anchor="middle" x="683" y="-1112.3" font-family="arial" font-size="14.00">female</text>
|
||||||
|
<polyline fill="none" stroke="black" points="712,-1104.5 712,-1127.5 "/>
|
||||||
|
<text text-anchor="middle" x="739" y="-1112.3" font-family="arial" font-size="14.00">48-pin</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-1104.5 766,-1104.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-1089.3" font-family="arial" font-size="14.00">z2</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-1081.5 766,-1081.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-1066.3" font-family="arial" font-size="14.00">b2</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-1058.5 766,-1058.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-1043.3" font-family="arial" font-size="14.00">d2</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-1035.5 766,-1035.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-1020.3" font-family="arial" font-size="14.00">z4</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-1012.5 766,-1012.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-997.3" font-family="arial" font-size="14.00">b4</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-989.5 766,-989.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-974.3" font-family="arial" font-size="14.00">d4</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-966.5 766,-966.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-951.3" font-family="arial" font-size="14.00">z6</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-943.5 766,-943.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-928.3" font-family="arial" font-size="14.00">b6</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-920.5 766,-920.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-905.3" font-family="arial" font-size="14.00">d6</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-897.5 766,-897.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-882.3" font-family="arial" font-size="14.00">z8</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-874.5 766,-874.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-859.3" font-family="arial" font-size="14.00">b8</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-851.5 766,-851.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-836.3" font-family="arial" font-size="14.00">d8</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-828.5 766,-828.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-813.3" font-family="arial" font-size="14.00">z10</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-805.5 766,-805.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-790.3" font-family="arial" font-size="14.00">b10</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-782.5 766,-782.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-767.3" font-family="arial" font-size="14.00">d10</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-759.5 766,-759.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-744.3" font-family="arial" font-size="14.00">z12</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-736.5 766,-736.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-721.3" font-family="arial" font-size="14.00">b12</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-713.5 766,-713.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-698.3" font-family="arial" font-size="14.00">d12</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-690.5 766,-690.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-675.3" font-family="arial" font-size="14.00">z14</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-667.5 766,-667.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-652.3" font-family="arial" font-size="14.00">b14</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-644.5 766,-644.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-629.3" font-family="arial" font-size="14.00">d14</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-621.5 766,-621.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-606.3" font-family="arial" font-size="14.00">z16</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-598.5 766,-598.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-583.3" font-family="arial" font-size="14.00">b16</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-575.5 766,-575.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-560.3" font-family="arial" font-size="14.00">d16</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-552.5 766,-552.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-537.3" font-family="arial" font-size="14.00">z18</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-529.5 766,-529.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-514.3" font-family="arial" font-size="14.00">b18</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-506.5 766,-506.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-491.3" font-family="arial" font-size="14.00">d18</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-483.5 766,-483.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-468.3" font-family="arial" font-size="14.00">z20</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-460.5 766,-460.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-445.3" font-family="arial" font-size="14.00">b20</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-437.5 766,-437.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-422.3" font-family="arial" font-size="14.00">d20</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-414.5 766,-414.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-399.3" font-family="arial" font-size="14.00">z22</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-391.5 766,-391.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-376.3" font-family="arial" font-size="14.00">b22</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-368.5 766,-368.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-353.3" font-family="arial" font-size="14.00">d22</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-345.5 766,-345.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-330.3" font-family="arial" font-size="14.00">z24</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-322.5 766,-322.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-307.3" font-family="arial" font-size="14.00">b24</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-299.5 766,-299.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-284.3" font-family="arial" font-size="14.00">d24</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-276.5 766,-276.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-261.3" font-family="arial" font-size="14.00">z26</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-253.5 766,-253.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-238.3" font-family="arial" font-size="14.00">b26</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-230.5 766,-230.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-215.3" font-family="arial" font-size="14.00">d26</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-207.5 766,-207.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-192.3" font-family="arial" font-size="14.00">z28</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-184.5 766,-184.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-169.3" font-family="arial" font-size="14.00">b28</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-161.5 766,-161.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-146.3" font-family="arial" font-size="14.00">d28</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-138.5 766,-138.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-123.3" font-family="arial" font-size="14.00">z30</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-115.5 766,-115.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-100.3" font-family="arial" font-size="14.00">b30</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-92.5 766,-92.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-77.3" font-family="arial" font-size="14.00">d30</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-69.5 766,-69.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-54.3" font-family="arial" font-size="14.00">z32</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-46.5 766,-46.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-31.3" font-family="arial" font-size="14.00">b32</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-23.5 766,-23.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-8.3" font-family="arial" font-size="14.00">d32</text>
|
||||||
|
</g>
|
||||||
|
<!-- W1--X2 -->
|
||||||
|
<g id="edge2" class="edge">
|
||||||
|
<title>W1:e--X2:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-662.5C625.31,-665.42 462.24,-979.42 614,-976.5"/>
|
||||||
|
<path fill="none" stroke="#666600" stroke-width="2" d="M470,-664.5C623.53,-664.5 460.47,-978.5 614,-978.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-666.5C621.76,-663.58 458.69,-977.58 614,-980.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- W1--X2 -->
|
||||||
|
<g id="edge4" class="edge">
|
||||||
|
<title>W1:e--X2:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-687.5C662.35,-690.51 425.1,-1094.51 614,-1091.5"/>
|
||||||
|
<path fill="none" stroke="#ffffff" stroke-width="2" d="M470,-689.5C660.62,-689.5 423.38,-1093.5 614,-1093.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-691.5C658.9,-688.49 421.65,-1092.49 614,-1095.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- W1--X2 -->
|
||||||
|
<g id="edge6" class="edge">
|
||||||
|
<title>W1:e--X2:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-612.5C566.6,-615.06 521.24,-772.06 614,-769.5"/>
|
||||||
|
<path fill="none" stroke="#ffff00" stroke-width="2" d="M470,-614.5C564.68,-614.5 519.32,-771.5 614,-771.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-616.5C562.76,-613.94 517.4,-770.94 614,-773.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- W1--X2 -->
|
||||||
|
<g id="edge8" class="edge">
|
||||||
|
<title>W1:e--X2:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-637.5C598.9,-640.31 488.76,-887.31 614,-884.5"/>
|
||||||
|
<path fill="none" stroke="#00ff00" stroke-width="2" d="M470,-639.5C597.07,-639.5 486.93,-886.5 614,-886.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-641.5C595.24,-638.69 485.1,-885.69 614,-888.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- W1--X2 -->
|
||||||
|
<g id="edge10" class="edge">
|
||||||
|
<title>W1:e--X2:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-562.5C533.88,-562.5 549.87,-561.5 614,-561.5"/>
|
||||||
|
<path fill="none" stroke="#ff66cc" stroke-width="2" d="M470,-564.5C534,-564.5 550,-563.5 614,-563.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-566.5C534.13,-566.5 550.12,-565.5 614,-565.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- W1--X2 -->
|
||||||
|
<g id="edge12" class="edge">
|
||||||
|
<title>W1:e--X2:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-587.5C547.47,-589.65 540.52,-679.65 614,-677.5"/>
|
||||||
|
<path fill="none" stroke="#999999" stroke-width="2" d="M470,-589.5C545.47,-589.5 538.53,-679.5 614,-679.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-591.5C543.48,-589.35 536.53,-679.35 614,-681.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- W1--X2 -->
|
||||||
|
<g id="edge14" class="edge">
|
||||||
|
<title>W1:e--X2:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-512.5C543.24,-514.65 536.77,-425.65 614,-423.5"/>
|
||||||
|
<path fill="none" stroke="#ff0000" stroke-width="2" d="M470,-514.5C545.24,-514.5 538.76,-425.5 614,-425.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-516.5C547.23,-514.35 540.76,-425.35 614,-427.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- W1--X2 -->
|
||||||
|
<g id="edge16" class="edge">
|
||||||
|
<title>W1:e--X2:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-537.5C534.13,-537.5 550.12,-538.5 614,-538.5"/>
|
||||||
|
<path fill="none" stroke="#0066ff" stroke-width="2" d="M470,-539.5C534,-539.5 550,-540.5 614,-540.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-541.5C533.88,-541.5 549.87,-542.5 614,-542.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- W1--X2 -->
|
||||||
|
<g id="edge18" class="edge">
|
||||||
|
<title>W1:e--X2:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-462.5C594.86,-465.31 485.48,-219.31 614,-216.5"/>
|
||||||
|
<path fill="none" stroke="#8000ff" stroke-width="2" d="M470,-464.5C596.69,-464.5 487.31,-218.5 614,-218.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-466.5C598.52,-463.69 489.14,-217.69 614,-220.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- W1--X2 -->
|
||||||
|
<g id="edge20" class="edge">
|
||||||
|
<title>W1:e--X2:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-487.5C562.43,-490.05 517.72,-334.05 614,-331.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-489.5C564.36,-489.5 519.64,-333.5 614,-333.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-491.5C566.28,-488.95 521.57,-332.95 614,-335.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- W1--X2 -->
|
||||||
|
<g id="edge22" class="edge">
|
||||||
|
<title>W1:e--X2:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-412.5C658.48,-415.51 422.07,-12.51 614,-9.5"/>
|
||||||
|
<path fill="none" stroke="#666600" stroke-width="2" d="M470,-414.5C660.2,-414.5 423.8,-11.5 614,-11.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-416.5C661.93,-413.49 425.52,-10.49 614,-13.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- W1--X2 -->
|
||||||
|
<g id="edge24" class="edge">
|
||||||
|
<title>W1:e--X2:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-437.5C621.35,-440.42 459.1,-127.42 614,-124.5"/>
|
||||||
|
<path fill="none" stroke="#ffffff" stroke-width="2" d="M470,-439.5C623.13,-439.5 460.87,-126.5 614,-126.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-441.5C624.9,-438.58 462.65,-125.58 614,-128.5"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
<h1>Bill of Materials</h1><table style="border:1px solid #000000; font-size: 14pt; border-spacing: 0px"><tr><th align="left" style="border:1px solid #000000; padding: 8px">Item</th><th align="left" style="border:1px solid #000000; padding: 8px">Qty</th><th align="left" style="border:1px solid #000000; padding: 8px">Unit</th><th align="left" style="border:1px solid #000000; padding: 8px">Designators</th></tr><tr><td style="border:1px solid #000000; padding: 4px">Connector, D-Sub, male, 25 pins</td><td align="right" style="border:1px solid #000000; padding: 4px">1</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px">X1</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Connector, F48, female, 48 pins</td><td align="right" style="border:1px solid #000000; padding: 4px">1</td><td style="border:1px solid #000000; padding: 4px"></td><td style="border:1px solid #000000; padding: 4px">X2</td></tr><tr><td style="border:1px solid #000000; padding: 4px">Cable, 12 x 0.25 mm² shielded</td><td align="right" style="border:1px solid #000000; padding: 4px">0.2</td><td style="border:1px solid #000000; padding: 4px">m</td><td style="border:1px solid #000000; padding: 4px">W1</td></tr></table></body></html>
|
||||||
BIN
examples/ex09.png
Normal file
|
After Width: | Height: | Size: 203 KiB |
450
examples/ex09.svg
Normal file
@ -0,0 +1,450 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||||
|
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<!-- Generated by graphviz version 2.44.0 (20200408.0750)
|
||||||
|
-->
|
||||||
|
<!-- Pages: 1 -->
|
||||||
|
<svg width="774pt" height="1159pt"
|
||||||
|
viewBox="0.00 0.00 774.00 1159.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 1155)">
|
||||||
|
<polygon fill="white" stroke="transparent" points="-4,4 -4,-1155 770,-1155 770,4 -4,4"/>
|
||||||
|
<!-- X1 -->
|
||||||
|
<g id="node1" class="node">
|
||||||
|
<title>X1</title>
|
||||||
|
<polygon fill="white" stroke="black" points="0,-377 0,-722 156,-722 156,-377 0,-377"/>
|
||||||
|
<text text-anchor="middle" x="78" y="-706.8" font-family="arial" font-size="14.00">X1</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-699 156,-699 "/>
|
||||||
|
<text text-anchor="middle" x="27.5" y="-683.8" font-family="arial" font-size="14.00">D-Sub</text>
|
||||||
|
<polyline fill="none" stroke="black" points="55,-676 55,-699 "/>
|
||||||
|
<text text-anchor="middle" x="78.5" y="-683.8" font-family="arial" font-size="14.00">male</text>
|
||||||
|
<polyline fill="none" stroke="black" points="102,-676 102,-699 "/>
|
||||||
|
<text text-anchor="middle" x="129" y="-683.8" font-family="arial" font-size="14.00">25-pin</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-676 156,-676 "/>
|
||||||
|
<text text-anchor="middle" x="54.5" y="-660.8" font-family="arial" font-size="14.00">SENSE_P_1</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-653 109,-653 "/>
|
||||||
|
<text text-anchor="middle" x="54.5" y="-637.8" font-family="arial" font-size="14.00">SENSE_N_1</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-630 109,-630 "/>
|
||||||
|
<text text-anchor="middle" x="54.5" y="-614.8" font-family="arial" font-size="14.00">SENSE_P_2</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-607 109,-607 "/>
|
||||||
|
<text text-anchor="middle" x="54.5" y="-591.8" font-family="arial" font-size="14.00">SENSE_N_2</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-584 109,-584 "/>
|
||||||
|
<text text-anchor="middle" x="54.5" y="-568.8" font-family="arial" font-size="14.00">SENSE_P_3</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-561 109,-561 "/>
|
||||||
|
<text text-anchor="middle" x="54.5" y="-545.8" font-family="arial" font-size="14.00">SENSE_N_3</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-538 109,-538 "/>
|
||||||
|
<text text-anchor="middle" x="54.5" y="-522.8" font-family="arial" font-size="14.00">SENSE_P_4</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-515 109,-515 "/>
|
||||||
|
<text text-anchor="middle" x="54.5" y="-499.8" font-family="arial" font-size="14.00">SENSE_N_4</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-492 109,-492 "/>
|
||||||
|
<text text-anchor="middle" x="54.5" y="-476.8" font-family="arial" font-size="14.00">SENSE_P_5</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-469 109,-469 "/>
|
||||||
|
<text text-anchor="middle" x="54.5" y="-453.8" font-family="arial" font-size="14.00">SENSE_N_5</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-446 109,-446 "/>
|
||||||
|
<text text-anchor="middle" x="54.5" y="-430.8" font-family="arial" font-size="14.00">SENSE_P_6</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-423 109,-423 "/>
|
||||||
|
<text text-anchor="middle" x="54.5" y="-407.8" font-family="arial" font-size="14.00">SENSE_N_6</text>
|
||||||
|
<polyline fill="none" stroke="black" points="0,-400 109,-400 "/>
|
||||||
|
<text text-anchor="middle" x="54.5" y="-384.8" font-family="arial" font-size="14.00">GND</text>
|
||||||
|
<polyline fill="none" stroke="black" points="109,-377 109,-676 "/>
|
||||||
|
<text text-anchor="middle" x="132.5" y="-660.8" font-family="arial" font-size="14.00">1</text>
|
||||||
|
<polyline fill="none" stroke="black" points="109,-653 156,-653 "/>
|
||||||
|
<text text-anchor="middle" x="132.5" y="-637.8" font-family="arial" font-size="14.00">14</text>
|
||||||
|
<polyline fill="none" stroke="black" points="109,-630 156,-630 "/>
|
||||||
|
<text text-anchor="middle" x="132.5" y="-614.8" font-family="arial" font-size="14.00">3</text>
|
||||||
|
<polyline fill="none" stroke="black" points="109,-607 156,-607 "/>
|
||||||
|
<text text-anchor="middle" x="132.5" y="-591.8" font-family="arial" font-size="14.00">16</text>
|
||||||
|
<polyline fill="none" stroke="black" points="109,-584 156,-584 "/>
|
||||||
|
<text text-anchor="middle" x="132.5" y="-568.8" font-family="arial" font-size="14.00">5</text>
|
||||||
|
<polyline fill="none" stroke="black" points="109,-561 156,-561 "/>
|
||||||
|
<text text-anchor="middle" x="132.5" y="-545.8" font-family="arial" font-size="14.00">18</text>
|
||||||
|
<polyline fill="none" stroke="black" points="109,-538 156,-538 "/>
|
||||||
|
<text text-anchor="middle" x="132.5" y="-522.8" font-family="arial" font-size="14.00">7</text>
|
||||||
|
<polyline fill="none" stroke="black" points="109,-515 156,-515 "/>
|
||||||
|
<text text-anchor="middle" x="132.5" y="-499.8" font-family="arial" font-size="14.00">20</text>
|
||||||
|
<polyline fill="none" stroke="black" points="109,-492 156,-492 "/>
|
||||||
|
<text text-anchor="middle" x="132.5" y="-476.8" font-family="arial" font-size="14.00">9</text>
|
||||||
|
<polyline fill="none" stroke="black" points="109,-469 156,-469 "/>
|
||||||
|
<text text-anchor="middle" x="132.5" y="-453.8" font-family="arial" font-size="14.00">22</text>
|
||||||
|
<polyline fill="none" stroke="black" points="109,-446 156,-446 "/>
|
||||||
|
<text text-anchor="middle" x="132.5" y="-430.8" font-family="arial" font-size="14.00">11</text>
|
||||||
|
<polyline fill="none" stroke="black" points="109,-423 156,-423 "/>
|
||||||
|
<text text-anchor="middle" x="132.5" y="-407.8" font-family="arial" font-size="14.00">24</text>
|
||||||
|
<polyline fill="none" stroke="black" points="109,-400 156,-400 "/>
|
||||||
|
<text text-anchor="middle" x="132.5" y="-384.8" font-family="arial" font-size="14.00">13</text>
|
||||||
|
</g>
|
||||||
|
<!-- W1 -->
|
||||||
|
<g id="node3" class="node">
|
||||||
|
<title>W1</title>
|
||||||
|
<polygon fill="none" stroke="black" points="470,-772.5 300,-772.5 300,-348.5 470,-348.5 470,-772.5"/>
|
||||||
|
<polygon fill="none" stroke="black" points="300,-749.5 300,-772.5 470,-772.5 470,-749.5 300,-749.5"/>
|
||||||
|
<text text-anchor="start" x="374" y="-757.3" font-family="arial" font-size="14.00">W1</text>
|
||||||
|
<polygon fill="none" stroke="black" points="300,-726.5 300,-749.5 330,-749.5 330,-726.5 300,-726.5"/>
|
||||||
|
<text text-anchor="start" x="304" y="-734.3" font-family="arial" font-size="14.00">12x</text>
|
||||||
|
<polygon fill="none" stroke="black" points="330,-726.5 330,-749.5 397,-749.5 397,-726.5 330,-726.5"/>
|
||||||
|
<text text-anchor="start" x="334" y="-734.3" font-family="arial" font-size="14.00">0.25 mm²</text>
|
||||||
|
<polygon fill="none" stroke="black" points="397,-726.5 397,-749.5 427,-749.5 427,-726.5 397,-726.5"/>
|
||||||
|
<text text-anchor="start" x="401" y="-734.3" font-family="arial" font-size="14.00">+ S</text>
|
||||||
|
<polygon fill="none" stroke="black" points="427,-726.5 427,-749.5 470,-749.5 470,-726.5 427,-726.5"/>
|
||||||
|
<text text-anchor="start" x="431" y="-734.3" font-family="arial" font-size="14.00">0.2 m</text>
|
||||||
|
<text text-anchor="start" x="383" y="-715.3" font-family="arial" font-size="14.00"> </text>
|
||||||
|
<text text-anchor="start" x="309" y="-698.3" font-family="arial" font-size="14.00">X1:14</text>
|
||||||
|
<text text-anchor="start" x="370" y="-698.3" font-family="arial" font-size="14.00">WH</text>
|
||||||
|
<text text-anchor="start" x="422.5" y="-698.3" font-family="arial" font-size="14.00">X2:z2</text>
|
||||||
|
<polygon fill="#ffffff" stroke="transparent" points="300,-686.5 300,-692.5 470,-692.5 470,-686.5 300,-686.5"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="301,-687.5 469,-687.5 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="469,-691.5 301,-691.5 "/>
|
||||||
|
<text text-anchor="start" x="313" y="-673.3" font-family="arial" font-size="14.00">X1:1</text>
|
||||||
|
<text text-anchor="start" x="372.5" y="-673.3" font-family="arial" font-size="14.00">BN</text>
|
||||||
|
<text text-anchor="start" x="422" y="-673.3" font-family="arial" font-size="14.00">X2:d4</text>
|
||||||
|
<polygon fill="#666600" stroke="transparent" stroke-width="2" points="300,-661.5 300,-667.5 470,-667.5 470,-661.5 300,-661.5"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="301,-662.5 469,-662.5 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="469,-666.5 301,-666.5 "/>
|
||||||
|
<text text-anchor="start" x="309" y="-648.3" font-family="arial" font-size="14.00">X1:16</text>
|
||||||
|
<text text-anchor="start" x="371" y="-648.3" font-family="arial" font-size="14.00">GN</text>
|
||||||
|
<text text-anchor="start" x="422.5" y="-648.3" font-family="arial" font-size="14.00">X2:z8</text>
|
||||||
|
<polygon fill="#00ff00" stroke="transparent" stroke-width="2" points="300,-636.5 300,-642.5 470,-642.5 470,-636.5 300,-636.5"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="301,-637.5 469,-637.5 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="469,-641.5 301,-641.5 "/>
|
||||||
|
<text text-anchor="start" x="313" y="-623.3" font-family="arial" font-size="14.00">X1:3</text>
|
||||||
|
<text text-anchor="start" x="372.5" y="-623.3" font-family="arial" font-size="14.00">YE</text>
|
||||||
|
<text text-anchor="start" x="418.5" y="-623.3" font-family="arial" font-size="14.00">X2:d10</text>
|
||||||
|
<polygon fill="#ffff00" stroke="transparent" stroke-width="2" points="300,-611.5 300,-617.5 470,-617.5 470,-611.5 300,-611.5"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="301,-612.5 469,-612.5 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="469,-616.5 301,-616.5 "/>
|
||||||
|
<text text-anchor="start" x="309" y="-598.3" font-family="arial" font-size="14.00">X1:18</text>
|
||||||
|
<text text-anchor="start" x="371.5" y="-598.3" font-family="arial" font-size="14.00">GY</text>
|
||||||
|
<text text-anchor="start" x="418.5" y="-598.3" font-family="arial" font-size="14.00">X2:z14</text>
|
||||||
|
<polygon fill="#999999" stroke="transparent" stroke-width="2" points="300,-586.5 300,-592.5 470,-592.5 470,-586.5 300,-586.5"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="301,-587.5 469,-587.5 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="469,-591.5 301,-591.5 "/>
|
||||||
|
<text text-anchor="start" x="313" y="-573.3" font-family="arial" font-size="14.00">X1:5</text>
|
||||||
|
<text text-anchor="start" x="372.5" y="-573.3" font-family="arial" font-size="14.00">PK</text>
|
||||||
|
<text text-anchor="start" x="418.5" y="-573.3" font-family="arial" font-size="14.00">X2:d16</text>
|
||||||
|
<polygon fill="#ff66cc" stroke="transparent" stroke-width="2" points="300,-561.5 300,-567.5 470,-567.5 470,-561.5 300,-561.5"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="301,-562.5 469,-562.5 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="469,-566.5 301,-566.5 "/>
|
||||||
|
<text text-anchor="start" x="309" y="-548.3" font-family="arial" font-size="14.00">X1:20</text>
|
||||||
|
<text text-anchor="start" x="372.5" y="-548.3" font-family="arial" font-size="14.00">BU</text>
|
||||||
|
<text text-anchor="start" x="418.5" y="-548.3" font-family="arial" font-size="14.00">X2:z18</text>
|
||||||
|
<polygon fill="#0066ff" stroke="transparent" stroke-width="2" points="300,-536.5 300,-542.5 470,-542.5 470,-536.5 300,-536.5"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="301,-537.5 469,-537.5 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="469,-541.5 301,-541.5 "/>
|
||||||
|
<text text-anchor="start" x="313" y="-523.3" font-family="arial" font-size="14.00">X1:7</text>
|
||||||
|
<text text-anchor="start" x="372" y="-523.3" font-family="arial" font-size="14.00">RD</text>
|
||||||
|
<text text-anchor="start" x="418.5" y="-523.3" font-family="arial" font-size="14.00">X2:d20</text>
|
||||||
|
<polygon fill="#ff0000" stroke="transparent" stroke-width="2" points="300,-511.5 300,-517.5 470,-517.5 470,-511.5 300,-511.5"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="301,-512.5 469,-512.5 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="469,-516.5 301,-516.5 "/>
|
||||||
|
<text text-anchor="start" x="309" y="-498.3" font-family="arial" font-size="14.00">X1:22</text>
|
||||||
|
<text text-anchor="start" x="372.5" y="-498.3" font-family="arial" font-size="14.00">BK</text>
|
||||||
|
<text text-anchor="start" x="418.5" y="-498.3" font-family="arial" font-size="14.00">X2:z24</text>
|
||||||
|
<polygon fill="#000000" stroke="transparent" stroke-width="2" points="300,-486.5 300,-492.5 470,-492.5 470,-486.5 300,-486.5"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="301,-487.5 469,-487.5 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="469,-491.5 301,-491.5 "/>
|
||||||
|
<text text-anchor="start" x="313" y="-473.3" font-family="arial" font-size="14.00">X1:9</text>
|
||||||
|
<text text-anchor="start" x="373" y="-473.3" font-family="arial" font-size="14.00">VT</text>
|
||||||
|
<text text-anchor="start" x="418.5" y="-473.3" font-family="arial" font-size="14.00">X2:d26</text>
|
||||||
|
<polygon fill="#8000ff" stroke="transparent" stroke-width="2" points="300,-461.5 300,-467.5 470,-467.5 470,-461.5 300,-461.5"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="301,-462.5 469,-462.5 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="469,-466.5 301,-466.5 "/>
|
||||||
|
<text text-anchor="start" x="309" y="-448.3" font-family="arial" font-size="14.00">X1:24</text>
|
||||||
|
<text text-anchor="start" x="370" y="-448.3" font-family="arial" font-size="14.00">WH</text>
|
||||||
|
<text text-anchor="start" x="418.5" y="-448.3" font-family="arial" font-size="14.00">X2:z30</text>
|
||||||
|
<polygon fill="#ffffff" stroke="transparent" stroke-width="2" points="300,-436.5 300,-442.5 470,-442.5 470,-436.5 300,-436.5"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="301,-437.5 469,-437.5 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="469,-441.5 301,-441.5 "/>
|
||||||
|
<text text-anchor="start" x="309.5" y="-423.3" font-family="arial" font-size="14.00">X1:11</text>
|
||||||
|
<text text-anchor="start" x="372.5" y="-423.3" font-family="arial" font-size="14.00">BN</text>
|
||||||
|
<text text-anchor="start" x="418.5" y="-423.3" font-family="arial" font-size="14.00">X2:d32</text>
|
||||||
|
<polygon fill="#666600" stroke="transparent" stroke-width="2" points="300,-411.5 300,-417.5 470,-417.5 470,-411.5 300,-411.5"/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="301,-412.5 469,-412.5 "/>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="469,-416.5 301,-416.5 "/>
|
||||||
|
<text text-anchor="start" x="325" y="-398.3" font-family="arial" font-size="14.00"> </text>
|
||||||
|
<text text-anchor="start" x="309" y="-379.3" font-family="arial" font-size="14.00">X1:13</text>
|
||||||
|
<text text-anchor="start" x="363" y="-379.3" font-family="arial" font-size="14.00">Shield</text>
|
||||||
|
<polyline fill="none" stroke="black" stroke-width="2" points="301,-368.5 469,-368.5 "/>
|
||||||
|
<text text-anchor="start" x="325" y="-354.3" font-family="arial" font-size="14.00"> </text>
|
||||||
|
</g>
|
||||||
|
<!-- X1--W1 -->
|
||||||
|
<g id="edge1" class="edge">
|
||||||
|
<title>X1:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-662.5C220,-662.5 236,-662.5 300,-662.5"/>
|
||||||
|
<path fill="none" stroke="#666600" stroke-width="2" d="M156,-664.5C220,-664.5 236,-664.5 300,-664.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-666.5C220,-666.5 236,-666.5 300,-666.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- X1--W1 -->
|
||||||
|
<g id="edge3" class="edge">
|
||||||
|
<title>X1:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-639.5C225.43,-641.13 234.5,-689.13 300,-687.5"/>
|
||||||
|
<path fill="none" stroke="#ffffff" stroke-width="2" d="M156,-641.5C223.46,-641.5 232.54,-689.5 300,-689.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-643.5C221.5,-641.87 230.57,-689.87 300,-691.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- X1--W1 -->
|
||||||
|
<g id="edge5" class="edge">
|
||||||
|
<title>X1:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-616.5C219.54,-616.56 235.49,-612.56 300,-612.5"/>
|
||||||
|
<path fill="none" stroke="#ffff00" stroke-width="2" d="M156,-618.5C220.02,-618.5 235.98,-614.5 300,-614.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-620.5C220.51,-620.44 236.46,-616.44 300,-616.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- X1--W1 -->
|
||||||
|
<g id="edge7" class="edge">
|
||||||
|
<title>X1:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-593.5C224.87,-595.05 235.03,-639.05 300,-637.5"/>
|
||||||
|
<path fill="none" stroke="#00ff00" stroke-width="2" d="M156,-595.5C222.92,-595.5 233.08,-639.5 300,-639.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-597.5C220.97,-595.95 231.13,-639.95 300,-641.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- X1--W1 -->
|
||||||
|
<g id="edge9" class="edge">
|
||||||
|
<title>X1:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-570.5C219.2,-570.72 235,-562.72 300,-562.5"/>
|
||||||
|
<path fill="none" stroke="#ff66cc" stroke-width="2" d="M156,-572.5C220.1,-572.5 235.9,-564.5 300,-564.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-574.5C221,-574.28 236.8,-566.28 300,-566.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- X1--W1 -->
|
||||||
|
<g id="edge11" class="edge">
|
||||||
|
<title>X1:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-547.5C224.35,-548.96 235.5,-588.96 300,-587.5"/>
|
||||||
|
<path fill="none" stroke="#999999" stroke-width="2" d="M156,-549.5C222.42,-549.5 233.58,-589.5 300,-589.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-551.5C220.5,-550.04 231.65,-590.04 300,-591.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- X1--W1 -->
|
||||||
|
<g id="edge13" class="edge">
|
||||||
|
<title>X1:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-524.5C219,-524.92 234.56,-512.92 300,-512.5"/>
|
||||||
|
<path fill="none" stroke="#ff0000" stroke-width="2" d="M156,-526.5C220.22,-526.5 235.78,-514.5 300,-514.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-528.5C221.44,-528.08 237,-516.08 300,-516.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- X1--W1 -->
|
||||||
|
<g id="edge15" class="edge">
|
||||||
|
<title>X1:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-501.5C223.87,-502.86 235.93,-538.86 300,-537.5"/>
|
||||||
|
<path fill="none" stroke="#0066ff" stroke-width="2" d="M156,-503.5C221.97,-503.5 234.03,-539.5 300,-539.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-505.5C220.07,-504.14 232.13,-540.14 300,-541.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- X1--W1 -->
|
||||||
|
<g id="edge17" class="edge">
|
||||||
|
<title>X1:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-478.5C218.94,-479.12 234.16,-463.12 300,-462.5"/>
|
||||||
|
<path fill="none" stroke="#8000ff" stroke-width="2" d="M156,-480.5C220.39,-480.5 235.61,-464.5 300,-464.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-482.5C221.84,-481.88 237.06,-465.88 300,-466.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- X1--W1 -->
|
||||||
|
<g id="edge19" class="edge">
|
||||||
|
<title>X1:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-455.5C223.42,-456.75 236.29,-488.75 300,-487.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-457.5C221.56,-457.5 234.44,-489.5 300,-489.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-459.5C219.71,-458.25 232.58,-490.25 300,-491.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- X1--W1 -->
|
||||||
|
<g id="edge21" class="edge">
|
||||||
|
<title>X1:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-432.5C219.01,-433.31 233.78,-413.31 300,-412.5"/>
|
||||||
|
<path fill="none" stroke="#666600" stroke-width="2" d="M156,-434.5C220.61,-434.5 235.39,-414.5 300,-414.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-436.5C222.22,-435.69 236.99,-415.69 300,-416.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- X1--W1 -->
|
||||||
|
<g id="edge23" class="edge">
|
||||||
|
<title>X1:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-409.5C223,-410.63 236.6,-438.63 300,-437.5"/>
|
||||||
|
<path fill="none" stroke="#ffffff" stroke-width="2" d="M156,-411.5C221.2,-411.5 234.8,-439.5 300,-439.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-413.5C219.4,-412.37 233,-440.37 300,-441.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- X1--W1 -->
|
||||||
|
<g id="edge25" class="edge">
|
||||||
|
<title>X1:e--W1:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M156,-388.5C220.5,-388.5 235.5,-370.5 300,-370.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- X2 -->
|
||||||
|
<g id="node2" class="node">
|
||||||
|
<title>X2</title>
|
||||||
|
<polygon fill="white" stroke="black" points="614,-0.5 614,-1150.5 766,-1150.5 766,-0.5 614,-0.5"/>
|
||||||
|
<text text-anchor="middle" x="690" y="-1135.3" font-family="arial" font-size="14.00">X2</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-1127.5 766,-1127.5 "/>
|
||||||
|
<text text-anchor="middle" x="634" y="-1112.3" font-family="arial" font-size="14.00">F48</text>
|
||||||
|
<polyline fill="none" stroke="black" points="654,-1104.5 654,-1127.5 "/>
|
||||||
|
<text text-anchor="middle" x="683" y="-1112.3" font-family="arial" font-size="14.00">female</text>
|
||||||
|
<polyline fill="none" stroke="black" points="712,-1104.5 712,-1127.5 "/>
|
||||||
|
<text text-anchor="middle" x="739" y="-1112.3" font-family="arial" font-size="14.00">48-pin</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-1104.5 766,-1104.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-1089.3" font-family="arial" font-size="14.00">z2</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-1081.5 766,-1081.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-1066.3" font-family="arial" font-size="14.00">b2</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-1058.5 766,-1058.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-1043.3" font-family="arial" font-size="14.00">d2</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-1035.5 766,-1035.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-1020.3" font-family="arial" font-size="14.00">z4</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-1012.5 766,-1012.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-997.3" font-family="arial" font-size="14.00">b4</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-989.5 766,-989.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-974.3" font-family="arial" font-size="14.00">d4</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-966.5 766,-966.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-951.3" font-family="arial" font-size="14.00">z6</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-943.5 766,-943.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-928.3" font-family="arial" font-size="14.00">b6</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-920.5 766,-920.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-905.3" font-family="arial" font-size="14.00">d6</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-897.5 766,-897.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-882.3" font-family="arial" font-size="14.00">z8</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-874.5 766,-874.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-859.3" font-family="arial" font-size="14.00">b8</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-851.5 766,-851.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-836.3" font-family="arial" font-size="14.00">d8</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-828.5 766,-828.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-813.3" font-family="arial" font-size="14.00">z10</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-805.5 766,-805.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-790.3" font-family="arial" font-size="14.00">b10</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-782.5 766,-782.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-767.3" font-family="arial" font-size="14.00">d10</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-759.5 766,-759.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-744.3" font-family="arial" font-size="14.00">z12</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-736.5 766,-736.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-721.3" font-family="arial" font-size="14.00">b12</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-713.5 766,-713.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-698.3" font-family="arial" font-size="14.00">d12</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-690.5 766,-690.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-675.3" font-family="arial" font-size="14.00">z14</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-667.5 766,-667.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-652.3" font-family="arial" font-size="14.00">b14</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-644.5 766,-644.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-629.3" font-family="arial" font-size="14.00">d14</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-621.5 766,-621.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-606.3" font-family="arial" font-size="14.00">z16</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-598.5 766,-598.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-583.3" font-family="arial" font-size="14.00">b16</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-575.5 766,-575.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-560.3" font-family="arial" font-size="14.00">d16</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-552.5 766,-552.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-537.3" font-family="arial" font-size="14.00">z18</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-529.5 766,-529.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-514.3" font-family="arial" font-size="14.00">b18</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-506.5 766,-506.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-491.3" font-family="arial" font-size="14.00">d18</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-483.5 766,-483.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-468.3" font-family="arial" font-size="14.00">z20</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-460.5 766,-460.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-445.3" font-family="arial" font-size="14.00">b20</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-437.5 766,-437.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-422.3" font-family="arial" font-size="14.00">d20</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-414.5 766,-414.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-399.3" font-family="arial" font-size="14.00">z22</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-391.5 766,-391.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-376.3" font-family="arial" font-size="14.00">b22</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-368.5 766,-368.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-353.3" font-family="arial" font-size="14.00">d22</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-345.5 766,-345.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-330.3" font-family="arial" font-size="14.00">z24</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-322.5 766,-322.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-307.3" font-family="arial" font-size="14.00">b24</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-299.5 766,-299.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-284.3" font-family="arial" font-size="14.00">d24</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-276.5 766,-276.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-261.3" font-family="arial" font-size="14.00">z26</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-253.5 766,-253.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-238.3" font-family="arial" font-size="14.00">b26</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-230.5 766,-230.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-215.3" font-family="arial" font-size="14.00">d26</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-207.5 766,-207.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-192.3" font-family="arial" font-size="14.00">z28</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-184.5 766,-184.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-169.3" font-family="arial" font-size="14.00">b28</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-161.5 766,-161.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-146.3" font-family="arial" font-size="14.00">d28</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-138.5 766,-138.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-123.3" font-family="arial" font-size="14.00">z30</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-115.5 766,-115.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-100.3" font-family="arial" font-size="14.00">b30</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-92.5 766,-92.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-77.3" font-family="arial" font-size="14.00">d30</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-69.5 766,-69.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-54.3" font-family="arial" font-size="14.00">z32</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-46.5 766,-46.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-31.3" font-family="arial" font-size="14.00">b32</text>
|
||||||
|
<polyline fill="none" stroke="black" points="614,-23.5 766,-23.5 "/>
|
||||||
|
<text text-anchor="middle" x="690" y="-8.3" font-family="arial" font-size="14.00">d32</text>
|
||||||
|
</g>
|
||||||
|
<!-- W1--X2 -->
|
||||||
|
<g id="edge2" class="edge">
|
||||||
|
<title>W1:e--X2:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-662.5C625.31,-665.42 462.24,-979.42 614,-976.5"/>
|
||||||
|
<path fill="none" stroke="#666600" stroke-width="2" d="M470,-664.5C623.53,-664.5 460.47,-978.5 614,-978.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-666.5C621.76,-663.58 458.69,-977.58 614,-980.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- W1--X2 -->
|
||||||
|
<g id="edge4" class="edge">
|
||||||
|
<title>W1:e--X2:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-687.5C662.35,-690.51 425.1,-1094.51 614,-1091.5"/>
|
||||||
|
<path fill="none" stroke="#ffffff" stroke-width="2" d="M470,-689.5C660.62,-689.5 423.38,-1093.5 614,-1093.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-691.5C658.9,-688.49 421.65,-1092.49 614,-1095.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- W1--X2 -->
|
||||||
|
<g id="edge6" class="edge">
|
||||||
|
<title>W1:e--X2:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-612.5C566.6,-615.06 521.24,-772.06 614,-769.5"/>
|
||||||
|
<path fill="none" stroke="#ffff00" stroke-width="2" d="M470,-614.5C564.68,-614.5 519.32,-771.5 614,-771.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-616.5C562.76,-613.94 517.4,-770.94 614,-773.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- W1--X2 -->
|
||||||
|
<g id="edge8" class="edge">
|
||||||
|
<title>W1:e--X2:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-637.5C598.9,-640.31 488.76,-887.31 614,-884.5"/>
|
||||||
|
<path fill="none" stroke="#00ff00" stroke-width="2" d="M470,-639.5C597.07,-639.5 486.93,-886.5 614,-886.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-641.5C595.24,-638.69 485.1,-885.69 614,-888.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- W1--X2 -->
|
||||||
|
<g id="edge10" class="edge">
|
||||||
|
<title>W1:e--X2:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-562.5C533.88,-562.5 549.87,-561.5 614,-561.5"/>
|
||||||
|
<path fill="none" stroke="#ff66cc" stroke-width="2" d="M470,-564.5C534,-564.5 550,-563.5 614,-563.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-566.5C534.13,-566.5 550.12,-565.5 614,-565.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- W1--X2 -->
|
||||||
|
<g id="edge12" class="edge">
|
||||||
|
<title>W1:e--X2:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-587.5C547.47,-589.65 540.52,-679.65 614,-677.5"/>
|
||||||
|
<path fill="none" stroke="#999999" stroke-width="2" d="M470,-589.5C545.47,-589.5 538.53,-679.5 614,-679.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-591.5C543.48,-589.35 536.53,-679.35 614,-681.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- W1--X2 -->
|
||||||
|
<g id="edge14" class="edge">
|
||||||
|
<title>W1:e--X2:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-512.5C543.24,-514.65 536.77,-425.65 614,-423.5"/>
|
||||||
|
<path fill="none" stroke="#ff0000" stroke-width="2" d="M470,-514.5C545.24,-514.5 538.76,-425.5 614,-425.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-516.5C547.23,-514.35 540.76,-425.35 614,-427.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- W1--X2 -->
|
||||||
|
<g id="edge16" class="edge">
|
||||||
|
<title>W1:e--X2:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-537.5C534.13,-537.5 550.12,-538.5 614,-538.5"/>
|
||||||
|
<path fill="none" stroke="#0066ff" stroke-width="2" d="M470,-539.5C534,-539.5 550,-540.5 614,-540.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-541.5C533.88,-541.5 549.87,-542.5 614,-542.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- W1--X2 -->
|
||||||
|
<g id="edge18" class="edge">
|
||||||
|
<title>W1:e--X2:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-462.5C594.86,-465.31 485.48,-219.31 614,-216.5"/>
|
||||||
|
<path fill="none" stroke="#8000ff" stroke-width="2" d="M470,-464.5C596.69,-464.5 487.31,-218.5 614,-218.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-466.5C598.52,-463.69 489.14,-217.69 614,-220.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- W1--X2 -->
|
||||||
|
<g id="edge20" class="edge">
|
||||||
|
<title>W1:e--X2:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-487.5C562.43,-490.05 517.72,-334.05 614,-331.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-489.5C564.36,-489.5 519.64,-333.5 614,-333.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-491.5C566.28,-488.95 521.57,-332.95 614,-335.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- W1--X2 -->
|
||||||
|
<g id="edge22" class="edge">
|
||||||
|
<title>W1:e--X2:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-412.5C658.48,-415.51 422.07,-12.51 614,-9.5"/>
|
||||||
|
<path fill="none" stroke="#666600" stroke-width="2" d="M470,-414.5C660.2,-414.5 423.8,-11.5 614,-11.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-416.5C661.93,-413.49 425.52,-10.49 614,-13.5"/>
|
||||||
|
</g>
|
||||||
|
<!-- W1--X2 -->
|
||||||
|
<g id="edge24" class="edge">
|
||||||
|
<title>W1:e--X2:w</title>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-437.5C621.35,-440.42 459.1,-127.42 614,-124.5"/>
|
||||||
|
<path fill="none" stroke="#ffffff" stroke-width="2" d="M470,-439.5C623.13,-439.5 460.87,-126.5 614,-126.5"/>
|
||||||
|
<path fill="none" stroke="#000000" stroke-width="2" d="M470,-441.5C624.9,-438.58 462.65,-125.58 614,-128.5"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 33 KiB |
31
examples/ex09.yml
Normal file
@ -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
|
||||||
@ -39,3 +39,21 @@
|
|||||||
|
|
||||||
[Source](ex07.yml) - [Bill of Materials](ex07.bom.tsv)
|
[Source](ex07.yml) - [Bill of Materials](ex07.bom.tsv)
|
||||||
|
|
||||||
|
## Example 07
|
||||||
|

|
||||||
|
|
||||||
|
[Source](ex07.yml) - [Bill of Materials](ex07.bom.tsv)
|
||||||
|
|
||||||
|
|
||||||
|
## Example 08
|
||||||
|

|
||||||
|
|
||||||
|
[Source](ex08.yml) - [Bill of Materials](ex08.bom.tsv)
|
||||||
|
|
||||||
|
|
||||||
|
## Example 09
|
||||||
|

|
||||||
|
|
||||||
|
[Source](ex09.yml) - [Bill of Materials](ex09.bom.tsv)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
1
requirements.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
.
|
||||||
45
setup.py
Normal file
@ -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/formatc1702/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)',
|
||||||
|
],
|
||||||
|
|
||||||
|
)
|
||||||
@ -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 <sebastian.bank@uni-leipzig.de>'
|
|
||||||
__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
|
|
||||||
@ -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
|
|
||||||
@ -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)
|
|
||||||
@ -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 <attributes>`.
|
|
||||||
"""
|
|
||||||
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 <subgraphs>`.
|
|
||||||
|
|
||||||
.. 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
|
|
||||||
@ -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
|
|
||||||
@ -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<bs>(?:\\\\)*)'
|
|
||||||
r'\\?(?P<quote>")')
|
|
||||||
|
|
||||||
ESCAPE_UNESCAPED_QUOTES = functools.partial(QUOTE_OPTIONAL_BACKSLASHES.sub,
|
|
||||||
r'\g<bs>\\\g<quote>')
|
|
||||||
|
|
||||||
|
|
||||||
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('<<b>spam</b>>')
|
|
||||||
'<<b>spam</b>>'
|
|
||||||
|
|
||||||
>>> 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)
|
|
||||||
@ -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
|
|
||||||
<function func at 0x...>
|
|
||||||
"""
|
|
||||||
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
|
|
||||||
1
src/.gitignore → src/wireviz/.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
__pycache__/
|
__pycache__/
|
||||||
_test/
|
_test/
|
||||||
|
wv-env/
|
||||||
141
src/wireviz/DataClasses.py
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
#!/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_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
|
||||||
|
|
||||||
|
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'
|
||||||
|
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
|
||||||
331
src/wireviz/Harness.py
Normal file
@ -0,0 +1,331 @@
|
|||||||
|
#!/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, mm2_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'<TD BGCOLOR="{wv_colors.translate_color(connector.color, "HEX")}" BORDER="1" SIDES="LR" WIDTH="4"></TD>' if connector.color else ''
|
||||||
|
dot.node(key, shape='none',
|
||||||
|
style='filled',
|
||||||
|
margin='0',
|
||||||
|
orientation='0' if connector.ports_left else '180',
|
||||||
|
label='''<
|
||||||
|
|
||||||
|
<TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="2"><TR>
|
||||||
|
<TD PORT="p1l"> {infostring_l} </TD>
|
||||||
|
{colorbar}
|
||||||
|
<TD PORT="p1r"> {infostring_r} </TD>
|
||||||
|
</TR></TABLE>
|
||||||
|
|
||||||
|
|
||||||
|
>'''.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'<p{pinnumber}l>{pinnumber}')
|
||||||
|
if connector.ports_right:
|
||||||
|
pinouts[2].append(f'<p{pinnumber}r>{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:
|
||||||
|
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 = ''
|
||||||
|
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 '',
|
||||||
|
'+ S' if cable.shield else '',
|
||||||
|
f'{cable.length} m' if cable.length > 0 else '']
|
||||||
|
attributes = list(filter(None, attributes))
|
||||||
|
|
||||||
|
html = '<table border="0" cellspacing="0" cellpadding="0"><tr><td>' # main table
|
||||||
|
|
||||||
|
html = f'{html}<table border="0" cellspacing="0" cellpadding="3" cellborder="1">' # name+attributes table
|
||||||
|
if cable.show_name:
|
||||||
|
html = f'{html}<tr><td colspan="{len(attributes)}">{cable.name}</td></tr>'
|
||||||
|
html = f'{html}<tr>' # attribute row
|
||||||
|
for attrib in attributes:
|
||||||
|
html = f'{html}<td>{attrib}</td>'
|
||||||
|
html = f'{html}</tr>' # attribute row
|
||||||
|
html = f'{html}</table></td></tr>' # name+attributes table
|
||||||
|
|
||||||
|
html = f'{html}<tr><td> </td></tr>' # spacer between attributes and wires
|
||||||
|
|
||||||
|
html = f'{html}<tr><td><table border="0" cellspacing="0" cellborder="0">' # conductor table
|
||||||
|
|
||||||
|
for i, connection in enumerate(cable.colors, 1):
|
||||||
|
p = []
|
||||||
|
p.append(f'<!-- {i}_in -->')
|
||||||
|
p.append(wv_colors.translate_color(connection, self.color_mode))
|
||||||
|
p.append(f'<!-- {i}_out -->')
|
||||||
|
html = f'{html}<tr>'
|
||||||
|
for bla in p:
|
||||||
|
html = f'{html}<td>{bla}</td>'
|
||||||
|
html = f'{html}</tr>'
|
||||||
|
bgcolor = wv_colors.translate_color(connection, 'hex')
|
||||||
|
bgcolor = bgcolor if bgcolor != '' else '#ffffff'
|
||||||
|
html = f'{html}<tr><td colspan="{len(p)}" cellpadding="0" height="6" bgcolor="{bgcolor}" border="2" sides="tb" port="w{i}"></td></tr>'
|
||||||
|
|
||||||
|
if cable.shield:
|
||||||
|
p = ['<!-- s_in -->', 'Shield', '<!-- s_out -->']
|
||||||
|
html = f'{html}<tr><td> </td></tr>' # spacer
|
||||||
|
html = f'{html}<tr>'
|
||||||
|
for bla in p:
|
||||||
|
html = html + f'<td>{bla}</td>'
|
||||||
|
html = f'{html}</tr>'
|
||||||
|
html = f'{html}<tr><td colspan="{len(p)}" cellpadding="0" height="6" border="2" sides="b" port="ws"></td></tr>'
|
||||||
|
|
||||||
|
html = f'{html}<tr><td> </td></tr>' # spacer at the end
|
||||||
|
|
||||||
|
html = f'{html}</table>' # conductor table
|
||||||
|
|
||||||
|
html = f'{html}</td></tr>' # main table
|
||||||
|
if cable.notes:
|
||||||
|
html = f'{html}<tr><td cellpadding="3">{cable.notes}</td></tr>' # notes table
|
||||||
|
html = f'{html}<tr><td> </td></tr>' # spacer at the end
|
||||||
|
|
||||||
|
html = f'{html}</table>' # 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'
|
||||||
|
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'<!-- {connection.via_port}_in -->', from_string)
|
||||||
|
if connection.to_port is not None: # connect to right
|
||||||
|
to_ferrule = self.connectors[connection.to_name].category == 'ferrule'
|
||||||
|
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'<!-- {connection.via_port}_out -->', 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
|
||||||
|
graph = self.create_graph()
|
||||||
|
for f in fmt:
|
||||||
|
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:
|
||||||
|
file.write(tuplelist2tsv(bom_list))
|
||||||
|
# HTML output
|
||||||
|
with open(f'{filename}.html', 'w') as file:
|
||||||
|
file.write('<html><body style="font-family:Arial">')
|
||||||
|
|
||||||
|
file.write('<h1>Diagram</h1>')
|
||||||
|
with open(f'{filename}.svg') as svg:
|
||||||
|
for svgdata in svg:
|
||||||
|
file.write(svgdata)
|
||||||
|
|
||||||
|
file.write('<h1>Bill of Materials</h1>')
|
||||||
|
listy = flatten2d(bom_list)
|
||||||
|
file.write('<table style="border:1px solid #000000; font-size: 14pt; border-spacing: 0px">')
|
||||||
|
file.write('<tr>')
|
||||||
|
for item in listy[0]:
|
||||||
|
file.write(f'<th align="left" style="border:1px solid #000000; padding: 8px">{item}</th>')
|
||||||
|
file.write('</tr>')
|
||||||
|
for row in listy[1:]:
|
||||||
|
file.write('<tr>')
|
||||||
|
for i, item in enumerate(row):
|
||||||
|
align = 'align="right"' if listy[0][i] == 'Qty' else ''
|
||||||
|
file.write(f'<td {align} style="border:1px solid #000000; padding: 4px">{item}</td>')
|
||||||
|
file.write('</tr>')
|
||||||
|
file.write('</table>')
|
||||||
|
|
||||||
|
file.write('</body></html>')
|
||||||
|
|
||||||
|
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
|
||||||
0
src/wireviz/__init__.py
Normal file
57
src/wireviz/build_examples.py
Executable file
@ -0,0 +1,57 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
|
||||||
|
|
||||||
|
from wireviz import wireviz
|
||||||
|
|
||||||
|
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_file(fn, generate_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_file(fn, generate_bom=True)
|
||||||
|
|
||||||
|
file.write('## Example {:02d}\n'.format(i))
|
||||||
|
file.write('\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_file(fn, generate_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('\n\n'.format(i))
|
||||||
|
|
||||||
|
file.write('[Bill of Materials](tutorial{:02d}.bom.tsv)\n\n\n'.format(i))
|
||||||
239
src/wireviz/wireviz.py
Executable file
@ -0,0 +1,239 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
|
||||||
|
|
||||||
|
from wireviz.Harness import Harness
|
||||||
|
|
||||||
|
|
||||||
|
def parse(yaml_input, file_out=None, generate_bom=False):
|
||||||
|
|
||||||
|
yaml_data = yaml.safe_load(yaml_input)
|
||||||
|
|
||||||
|
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(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('-')))
|
||||||
|
if a < b:
|
||||||
|
for x in range(a, b + 1):
|
||||||
|
output.append(x)
|
||||||
|
elif a > b:
|
||||||
|
for x in range(a, b - 1, -1):
|
||||||
|
output.append(x)
|
||||||
|
elif a == b:
|
||||||
|
output.append(a)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
x = int(e)
|
||||||
|
except Exception:
|
||||||
|
x = e
|
||||||
|
output.append(x)
|
||||||
|
return output
|
||||||
|
|
||||||
|
def check_designators(what, where):
|
||||||
|
for i, x in enumerate(what):
|
||||||
|
if x not in yaml_data[where[i]]:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
harness = Harness()
|
||||||
|
|
||||||
|
# add items
|
||||||
|
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 key, o in yaml_data[sec].items():
|
||||||
|
if sec == 'connectors':
|
||||||
|
harness.add_connector(name=key, **o)
|
||||||
|
elif sec == 'cables':
|
||||||
|
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
|
||||||
|
if ty == dict:
|
||||||
|
yaml_data[sec] = {}
|
||||||
|
elif ty == list:
|
||||||
|
yaml_data[sec] = []
|
||||||
|
|
||||||
|
# add connections
|
||||||
|
ferrule_counter = 0
|
||||||
|
for connections in yaml_data['connections']:
|
||||||
|
if len(connections) == 3: # format: connector -- cable -- connector
|
||||||
|
|
||||||
|
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(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])
|
||||||
|
raise Exception('Bad connection definition (3)')
|
||||||
|
|
||||||
|
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):
|
||||||
|
harness.connect(from_name, from_pin, via_name, via_pin, to_name, to_pin)
|
||||||
|
|
||||||
|
elif len(connections) == 2:
|
||||||
|
|
||||||
|
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(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(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'))
|
||||||
|
|
||||||
|
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(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):
|
||||||
|
raise Exception('List length mismatch')
|
||||||
|
|
||||||
|
if con_cbl or cbl_con:
|
||||||
|
for (from_pin, to_pin) in zip(from_pins, to_pins):
|
||||||
|
if con_cbl:
|
||||||
|
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(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):
|
||||||
|
harness.loop(cocon_coname, from_pin, to_pin)
|
||||||
|
if fer_cbl or cbl_fer:
|
||||||
|
from_pins = expand(connections[0][from_name])
|
||||||
|
to_pins = expand(connections[1][to_name])
|
||||||
|
|
||||||
|
if fer_cbl:
|
||||||
|
ferrule_name = from_name
|
||||||
|
cable_name = to_name
|
||||||
|
cable_pins = to_pins
|
||||||
|
else:
|
||||||
|
ferrule_name = to_name
|
||||||
|
cable_name = from_name
|
||||||
|
cable_pins = from_pins
|
||||||
|
|
||||||
|
ferrule_params = yaml_data['ferrules'][ferrule_name]
|
||||||
|
for cable_pin in cable_pins:
|
||||||
|
ferrule_counter = ferrule_counter + 1
|
||||||
|
ferrule_id = f'_F{ferrule_counter}'
|
||||||
|
harness.add_connector(ferrule_id, category='ferrule', **ferrule_params)
|
||||||
|
|
||||||
|
if fer_cbl:
|
||||||
|
harness.connect(ferrule_id, 1, cable_name, cable_pin, None, None)
|
||||||
|
else:
|
||||||
|
harness.connect(None, None, cable_name, cable_pin, ferrule_id, 1)
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise Exception('Wrong number of connection parameters')
|
||||||
|
|
||||||
|
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:
|
||||||
|
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',
|
||||||
|
)
|
||||||
|
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()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
|
||||||
|
args = parse_cmdline()
|
||||||
|
|
||||||
|
if not os.path.exists(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:
|
||||||
|
yaml_input = fh.read()
|
||||||
|
|
||||||
|
if args.prepend_file:
|
||||||
|
if not os.path.exists(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()
|
||||||
|
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()
|
||||||
78
src/wireviz/wv_colors.py
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#!/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'],
|
||||||
|
}
|
||||||
|
|
||||||
|
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',
|
||||||
|
}
|
||||||
|
|
||||||
|
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',
|
||||||
|
}
|
||||||
|
|
||||||
|
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',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def translate_color(inp, color_mode):
|
||||||
|
if inp == '':
|
||||||
|
output = ''
|
||||||
|
else:
|
||||||
|
if color_mode == 'full':
|
||||||
|
output = color_full[inp].lower()
|
||||||
|
elif color_mode == 'FULL':
|
||||||
|
output = color_full[inp].upper()
|
||||||
|
elif color_mode == 'hex':
|
||||||
|
output = color_hex[inp].lower()
|
||||||
|
elif color_mode == 'HEX':
|
||||||
|
output = color_hex[inp].upper()
|
||||||
|
elif color_mode == 'ger':
|
||||||
|
output = color_ger[inp].lower()
|
||||||
|
elif color_mode == 'GER':
|
||||||
|
output = color_ger[inp].upper()
|
||||||
|
elif color_mode == 'short':
|
||||||
|
output = inp.lower()
|
||||||
|
elif color_mode == 'SHORT':
|
||||||
|
output = inp.upper()
|
||||||
|
else:
|
||||||
|
raise Exception('Unknown color mode')
|
||||||
|
return output
|
||||||
67
src/wireviz/wv_helper.py
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
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):
|
||||||
|
return awg_equiv_table.get(str(mm2), 'Unknown')
|
||||||
|
|
||||||
|
def mm2_equiv(awg):
|
||||||
|
return mm2_equiv_table.get(str(awg), 'Unknown')
|
||||||
|
|
||||||
|
def nested(inp):
|
||||||
|
l = []
|
||||||
|
for x in inp:
|
||||||
|
if isinstance(x, list):
|
||||||
|
if len(x) > 0:
|
||||||
|
n = nested(x)
|
||||||
|
if n != '':
|
||||||
|
l.append('{' + n + '}')
|
||||||
|
else:
|
||||||
|
if x is not None:
|
||||||
|
if x != '':
|
||||||
|
l.append(str(x))
|
||||||
|
return '|'.join(l)
|
||||||
|
|
||||||
|
|
||||||
|
def int2tuple(inp):
|
||||||
|
if isinstance(inp, tuple):
|
||||||
|
output = inp
|
||||||
|
else:
|
||||||
|
output = (inp,)
|
||||||
|
return output
|
||||||
|
|
||||||
|
|
||||||
|
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:
|
||||||
|
inp.insert(0, header)
|
||||||
|
inp = flatten2d(inp)
|
||||||
|
for row in inp:
|
||||||
|
output = output + '\t'.join(str(item) for item in row) + '\n'
|
||||||
|
return output
|
||||||
@ -1,59 +0,0 @@
|
|||||||
from typing import Any, 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,
|
|
||||||
}
|
|
||||||
k = str(mm2)
|
|
||||||
if k in awg_equiv_table:
|
|
||||||
return awg_equiv_table[k]
|
|
||||||
else:
|
|
||||||
return 'unknown'
|
|
||||||
|
|
||||||
def nested(input):
|
|
||||||
l = []
|
|
||||||
for x in input:
|
|
||||||
if isinstance(x, list):
|
|
||||||
if len(x) > 0:
|
|
||||||
n = nested(x)
|
|
||||||
if n != '':
|
|
||||||
l.append('{' + n + '}')
|
|
||||||
else:
|
|
||||||
if x is not None:
|
|
||||||
if x != '':
|
|
||||||
l.append(str(x))
|
|
||||||
s = '|'.join(l)
|
|
||||||
return s
|
|
||||||
|
|
||||||
def int2tuple(input):
|
|
||||||
if isinstance(input, tuple):
|
|
||||||
output = input
|
|
||||||
else:
|
|
||||||
output = (input,)
|
|
||||||
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):
|
|
||||||
output = ''
|
|
||||||
if header is not None:
|
|
||||||
input.insert(0, header)
|
|
||||||
input = flatten2d(input)
|
|
||||||
for row in input:
|
|
||||||
output = output + '\t'.join(str(item) for item in row) + '\n'
|
|
||||||
return output
|
|
||||||
@ -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)
|
|
||||||
|
|
||||||
@ -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
|
|
||||||
|
|
||||||
@ -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<year>[0-9][0-9][0-9][0-9])
|
|
||||||
-(?P<month>[0-9][0-9]?)
|
|
||||||
-(?P<day>[0-9][0-9]?)
|
|
||||||
(?:(?:[Tt]|[ \t]+)
|
|
||||||
(?P<hour>[0-9][0-9]?)
|
|
||||||
:(?P<minute>[0-9][0-9])
|
|
||||||
:(?P<second>[0-9][0-9])
|
|
||||||
(?:\.(?P<fraction>[0-9]*))?
|
|
||||||
(?:[ \t]*(?P<tz>Z|(?P<tz_sign>[-+])(?P<tz_hour>[0-9][0-9]?)
|
|
||||||
(?::(?P<tz_minute>[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
|
|
||||||
@ -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)
|
|
||||||
|
|
||||||
@ -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)
|
|
||||||
|
|
||||||
1137
src/yaml/emitter.py
@ -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)
|
|
||||||
|
|
||||||
@ -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
|
|
||||||
|
|
||||||
@ -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)
|
|
||||||
@ -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 = '<empty>'
|
|
||||||
# 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'
|
|
||||||
|
|
||||||
@ -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 '<document start>', 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 <block end>, 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 <block end>, 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)
|
|
||||||
|
|
||||||
@ -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 = "<unicode string>"
|
|
||||||
self.check_printable(stream)
|
|
||||||
self.buffer = stream+'\0'
|
|
||||||
elif isinstance(stream, bytes):
|
|
||||||
self.name = "<byte string>"
|
|
||||||
self.raw_buffer = stream
|
|
||||||
self.determine_encoding()
|
|
||||||
else:
|
|
||||||
self.stream = stream
|
|
||||||
self.name = getattr(stream, 'name', "<file>")
|
|
||||||
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
|
|
||||||
@ -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)
|
|
||||||
|
|
||||||
@ -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('!&*'))
|
|
||||||
|
|
||||||
1435
src/yaml/scanner.py
@ -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()
|
|
||||||
|
|
||||||
@ -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 = '<byte order mark>'
|
|
||||||
|
|
||||||
class DirectiveToken(Token):
|
|
||||||
id = '<directive>'
|
|
||||||
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 = '<document start>'
|
|
||||||
|
|
||||||
class DocumentEndToken(Token):
|
|
||||||
id = '<document end>'
|
|
||||||
|
|
||||||
class StreamStartToken(Token):
|
|
||||||
id = '<stream start>'
|
|
||||||
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 = '<stream end>'
|
|
||||||
|
|
||||||
class BlockSequenceStartToken(Token):
|
|
||||||
id = '<block sequence start>'
|
|
||||||
|
|
||||||
class BlockMappingStartToken(Token):
|
|
||||||
id = '<block mapping start>'
|
|
||||||
|
|
||||||
class BlockEndToken(Token):
|
|
||||||
id = '<block end>'
|
|
||||||
|
|
||||||
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 = '<alias>'
|
|
||||||
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 = '<anchor>'
|
|
||||||
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 = '<tag>'
|
|
||||||
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 = '<scalar>'
|
|
||||||
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
|
|
||||||
|
|
||||||
49
todo.md
@ -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
|
|
||||||
|
|
||||||
* Imrpove 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
|
|
||||||
* ...
|
|
||||||
@ -221,7 +221,7 @@ connections:
|
|||||||
- # attach ferrules
|
- # attach ferrules
|
||||||
- F1 # no need for list of connections; one ferrule per wire is auto-generated and attached
|
- 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
|
- 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]
|
- W1: [1-4]
|
||||||
- X1: [1-4]
|
- X1: [1-4]
|
||||||
```
|
```
|
||||||
@ -262,7 +262,7 @@ ferrules: # ferrules
|
|||||||
|
|
||||||
cables:
|
cables:
|
||||||
W1:
|
W1:
|
||||||
category: bundle # budnle
|
category: bundle # bundle
|
||||||
length: 0.3
|
length: 0.3
|
||||||
gauge: 0.5 mm2
|
gauge: 0.5 mm2
|
||||||
colors: [YE, BK, BK, RD] # custom colors, wirecount is implicit
|
colors: [YE, BK, BK, RD] # custom colors, wirecount is implicit
|
||||||
@ -271,7 +271,7 @@ connections:
|
|||||||
- # attach ferrules
|
- # attach ferrules
|
||||||
- F_05
|
- F_05
|
||||||
- W1: [1,4] # a new ferrule is auto-generated for each wire
|
- 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]
|
- W1: [1-4]
|
||||||
- X1: [1-4]
|
- X1: [1-4]
|
||||||
-
|
-
|
||||||
|
|||||||
@ -21,6 +21,6 @@ connections:
|
|||||||
- # attach ferrules
|
- # attach ferrules
|
||||||
- F1 # no need for list of connections; one ferrule per wire is auto-generated and attached
|
- 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
|
- 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]
|
- W1: [1-4]
|
||||||
- X1: [1-4]
|
- X1: [1-4]
|
||||||
|
|||||||
@ -17,7 +17,7 @@ ferrules: # ferrules
|
|||||||
|
|
||||||
cables:
|
cables:
|
||||||
W1:
|
W1:
|
||||||
category: bundle # budnle
|
category: bundle # bundle
|
||||||
length: 0.3
|
length: 0.3
|
||||||
gauge: 0.5 mm2
|
gauge: 0.5 mm2
|
||||||
colors: [YE, BK, BK, RD] # custom colors, wirecount is implicit
|
colors: [YE, BK, BK, RD] # custom colors, wirecount is implicit
|
||||||
@ -26,7 +26,7 @@ connections:
|
|||||||
- # attach ferrules
|
- # attach ferrules
|
||||||
- F_05
|
- F_05
|
||||||
- W1: [1,4] # a new ferrule is auto-generated for each wire
|
- 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]
|
- W1: [1-4]
|
||||||
- X1: [1-4]
|
- X1: [1-4]
|
||||||
-
|
-
|
||||||
|
|||||||