-
Notifications
You must be signed in to change notification settings - Fork 229
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Invoke WireViz within a Python program? #231
Comments
I realize this reply took a while, but better late than never ;-) Indeed, you can run: from wireviz import wireviz
yaml_data = """
metadata:
title: Test
connectors:
X1:
pincount: 4
"""
my_harness, my_png, my_svg = wireviz.parse(yaml_data, return_types=("harness", "png", "svg")) to receive raw PNG and SVG data, as well as a If this feature is of interest to you, I encourage you to try the |
Well, two years later, I'm wondering again about this. I've been mostly content to just use yaml, but there are some situations where using Wireviz via Python would be helpful. Is there a more Pythonic way to build the inputs rather than just mimicking the yaml text file as a big honkin' string? Notionally, for example,
|
All code from the meta_dict = {
"title": "My title",
}
connectors_dict = {
"X1": x1_dict,
...
}
cables_dict = {
...
}
connections_list = [
...
]
harness_dict = {
"metadata": meta_dict,
"connectors": connectors_dict,
"cables": cables_dict,
"connections": connections_list,
}
parse(harness_dict, ...) The code above is not tested. The syntax is from my memory, and might contain errors. It is also possible to create function wrappers around each dict to make the syntax closer to your code example. |
Well, decided to play around with this a little and see if I could make any progress. But, when I got to the connections, I became lost. Those seem a little more awkward to define as compared to connectors and cables. My first attempt to do this is in the file Am I getting close? Or getting derailed? |
Maybe it is not polite to link to another repository... here are a couple of extracts to show what I'm doing. First is an example of a particular connector, something carried over from my original
Next is an example of a particular cable, again taken from my
Finally, in the top level python file where I define a particular cable assembly, I build it like this:
But this is where I reach a dead end.
Well, not the title bit. I mean, how to I make the list of connections? The example shows working with dictionaries, but I have reached into WireViz and used the native classes to build the objects directly. Is that a boneheaded move? |
Maybe this example might help you (it's tested with v0.4.1): from pathlib import Path
from wireviz import wireviz
yaml_data = { # Contents copied from ex01.yml
'connectors': {
'X1': {
'type': 'Molex KK 254',
'subtype': 'female',
'pinlabels': ['GND', 'VCC', 'RX', 'TX']
},
'X2': {
'type': 'Molex KK 254',
'subtype': 'female',
'pinlabels': ['GND', 'VCC', 'RX', 'TX']
}
},
'cables': {
'W1': {
'color_code': 'IEC',
'wirecount': 4,
'gauge': '0.25 mm2',
'show_equiv': True,
'length': 0.2,
'shield': True,
'type': 'Serial'
}
},
'connections': [
[
{'X1': ['1-4']},
{'W1': ['1-4']},
{'X2': [1, 2, 4, 3]}
],
[
{'X1': 1},
{'W1': 's'}
]
]
}
my_harness, my_png, my_svg = wireviz.parse(yaml_data, return_types=("harness", "png", "svg"))
print(my_harness)
Path("my_png.png").write_bytes(my_png)
Path("my_svg.svg").write_text(my_svg, encoding="utf-8") |
@thestumbler wrote:
I don't mind looking into another repository, but large ones might be a bit time consuming to investigate, so direct links pointing into the files and line numbers of interest are normally preferred.
See my latest example above.
I've never tried sub-classing the internal WireViz dataclasses for such a purpose, so I don't know for sure, but I doubt it'll work easily. There are some pre-processing done using the dict/list representation before creating the internal dataclasses that you might need to re-implement in that case, and it probably also will require more work adapting to new versions in the future. It probably is safer to use the dict/list structure as in my latest example above. This is identical to the output from the YAML parsing library we use, and is a direct translation from YAML to native Python types.
yaml_data = dict( # Contents copied from ex01.yml
connectors = dict(
X1 = dict(
type = 'Molex KK 254',
subtype = 'female',
pinlabels = ['GND', 'VCC', 'RX', 'TX']
),
X2 = dict(
type = 'Molex KK 254',
subtype = 'female',
pinlabels = ['GND', 'VCC', 'RX', 'TX']
)
),
cables = dict(
W1 = dict(
color_code = 'IEC',
wirecount = 4,
gauge = '0.25 mm2',
show_equiv = True,
length = 0.2,
shield = True,
type = 'Serial'
)
),
connections = [
[
dict(X1 = ['1-4']),
dict(W1 = ['1-4']),
dict(X2 = [1, 2, 4, 3])
],
[
dict(X1 = 1),
dict(W1 = 's')
]
]
) |
Thanks. Let me ponder that. So I began with the idea of making my own classes / dictionaries, not even imagining reaching into the library like above. Because of the repetitive nature of a lot of my data, and I saw this information as a perfect match for classes, I decided to make things as classes. I was trying to reproduce the overall structure of my yaml files where I use the include feature quite a lot (again because so much is repetitive). As I got half way through that approach, I kept referring to the WV source code to check whether various parameters were just strings or numbers or other WV classes. I was copying and pasting big chunks of code, and I then realized, "I'm just duplicating the Connector class here, and that seems unnecessary". I then realized that I could just use the Connector class directly, and get the desired effect by using class inheritance. This let me create a bunch of commonly used Connectors / Cables etc, just like my common yaml file, and in a Pythonic manner. That turned out to be very easy. As I was wrapping that up, I realized I didn't understand how to map the connections into a dictionary, and there really wasn't a corresponding Connections class inside WV like I found with Connector and Cable. Seemed like connections were build using a lot of loops and code, not surprisingly, and it wasn't as simple as the other classes I was commandeering. So, having just woken up and unencumbered by the thought process ... (1) If there's no way to conveniently pass a class to the harness / parse functions, seems like I could keep doing it this way but make a dictionary from the class when passing to harness. Either build it using built in Python functions, like looping over all class members, ditching functions and such, or attach a (2) I wonder why my brain keeps rejecting the dictionary approach. Seems like I can do all this with dictionaries as you keep suggesting. Dealing with common information is just as easy, just add together two dictionaries. I'm pretty sure dictionaries can have member functions if I wanted to add stuff like a formatted print (maybe I'm getting that confused with C++) Anyway thanks for the feedback and I'll keep experimenting. I'll get there eventually, it's only been three years or so. I do think there is some value in this idea, but I'm hard pressed to say exactly why. |
|
Tried the It seems to be working now. What I needed to do was to prevent the wireviz Cable and Connector classes from invoking their I add a short The subclassed have a bunch of predefined fields in a Finally, I realized it was going to be annoying to keep typing all this boilerplate code for each and every cable and connector I wanted to define, so I taught myself to make a class decorator function that is applied in top of the
I think this exercise is substantially complete, just need a few more cleanup tasks:
|
Now that it's working, I find myself circling back to the original premise of the exercise, does it make sense to manage all this data from Python vs yaml? Maybe. In these stand-alone examples of building cable drawings by hand, I'm not sure the Python approach is any easier, perhaps a little more difficult. I cannot even remember why I started this a few years ago, but I think it was because I wanted the ability to export a netlist from a KiCad cable schematic and use it to make a WireViz cable diagram. There might be some other advantages of having the information in Python as well. I noticed that the parse function was deeper in the hierarchy than the examples above. I had to go three levels deep to get it. Was that the intended resting place for the parse function?
I didn't see how to make pdf output files, but upon reviewing my bash script I see that I make pdf files outside of wireviz, using
Have either of these abilities been integrated into wireviz, or we should still do post processing? |
|
Just curious, is there a mechanism to import WireViz and drive it from a Python script instead of the YAML files from the command line? I searched briefly and it wasn't obvious to me.
I'm not sure this would be useful, but I can imagine a situation where the cabling information is stored somewhere that is easily accessible by Python. Worse case, you could use a Python script to automatically generate the YAML files.
The text was updated successfully, but these errors were encountered: