harnice 0.3.0__tar.gz → 0.3.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {harnice-0.3.0 → harnice-0.3.1}/PKG-INFO +2 -1
- {harnice-0.3.0 → harnice-0.3.1}/pyproject.toml +3 -2
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/fileio.py +3 -2
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/lists/instances_list.py +41 -39
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/lists/rev_history.py +248 -38
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/products/harness.py +8 -8
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/products/part.py +1 -3
- harnice-0.3.1/src/harnice/products/system.py +297 -0
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/state.py +4 -0
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/utils/feature_tree_utils.py +1 -1
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/utils/formboard_utils.py +5 -11
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/utils/system_utils.py +40 -18
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice.egg-info/PKG-INFO +2 -1
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice.egg-info/requires.txt +1 -0
- harnice-0.3.0/src/harnice/products/system.py +0 -125
- {harnice-0.3.0 → harnice-0.3.1}/LICENSE +0 -0
- {harnice-0.3.0 → harnice-0.3.1}/README.md +0 -0
- {harnice-0.3.0 → harnice-0.3.1}/setup.cfg +0 -0
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/__init__.py +0 -0
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/__main__.py +0 -0
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/cli.py +0 -0
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/gui/launcher.py +0 -0
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/lists/channel_map.py +0 -0
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/lists/circuits_list.py +0 -0
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/lists/disconnect_map.py +0 -0
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/lists/formboard_graph.py +0 -0
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/lists/library_history.py +0 -0
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/lists/manifest.py +0 -0
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/lists/post_harness_instances_list.py +0 -0
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/lists/signals_list.py +0 -0
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/products/__init__.py +0 -0
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/products/cable.py +0 -0
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/products/chtype.py +0 -0
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/products/device.py +0 -0
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/products/disconnect.py +0 -0
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/products/flagnote.py +0 -0
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/products/macro.py +0 -0
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/products/tblock.py +0 -0
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/utils/appearance.py +0 -0
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/utils/circuit_utils.py +0 -0
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/utils/library_utils.py +0 -0
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/utils/note_utils.py +0 -0
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice/utils/svg_utils.py +0 -0
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice.egg-info/SOURCES.txt +0 -0
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice.egg-info/dependency_links.txt +0 -0
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice.egg-info/entry_points.txt +0 -0
- {harnice-0.3.0 → harnice-0.3.1}/src/harnice.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: harnice
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: Electrical System CAD
|
|
5
5
|
Author-email: Kenyon Shutt <harnice.io@gmail.com>
|
|
6
6
|
Project-URL: Documentation, https://harnice.io/
|
|
@@ -18,6 +18,7 @@ Requires-Dist: Pillow
|
|
|
18
18
|
Requires-Dist: PyYAML
|
|
19
19
|
Requires-Dist: xlwt
|
|
20
20
|
Requires-Dist: webcolors
|
|
21
|
+
Requires-Dist: prompt_toolkit
|
|
21
22
|
Dynamic: license-file
|
|
22
23
|
|
|
23
24
|
Harnice is a free, open source electrical system CAD tool.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "harnice"
|
|
3
|
-
version = "0.3.
|
|
3
|
+
version = "0.3.1"
|
|
4
4
|
authors = [
|
|
5
5
|
{ name="Kenyon Shutt", email="harnice.io@gmail.com" },
|
|
6
6
|
]
|
|
@@ -19,7 +19,8 @@ dependencies = [
|
|
|
19
19
|
"Pillow",
|
|
20
20
|
"PyYAML",
|
|
21
21
|
"xlwt",
|
|
22
|
-
"webcolors"
|
|
22
|
+
"webcolors",
|
|
23
|
+
"prompt_toolkit"
|
|
23
24
|
]
|
|
24
25
|
|
|
25
26
|
[project.urls]
|
|
@@ -209,12 +209,13 @@ def verify_revision_structure():
|
|
|
209
209
|
f"Harnice only renders revisions with a blank status."
|
|
210
210
|
)
|
|
211
211
|
|
|
212
|
-
print(f"
|
|
212
|
+
print(f"Rendering PN: {state.pn}, Rev: {state.rev}")
|
|
213
213
|
rev_history.update_datemodified()
|
|
214
214
|
|
|
215
215
|
|
|
216
216
|
def today():
|
|
217
|
-
|
|
217
|
+
d = datetime.date.today()
|
|
218
|
+
return f"{d.month}/{d.day}/{d.year % 100}"
|
|
218
219
|
|
|
219
220
|
|
|
220
221
|
def get_git_hash_of_harnice_src():
|
|
@@ -5,23 +5,25 @@ from threading import Lock
|
|
|
5
5
|
from harnice import fileio, state
|
|
6
6
|
|
|
7
7
|
COLUMNS = [
|
|
8
|
-
"net", #
|
|
9
|
-
"instance_name", #
|
|
10
|
-
"print_name", #
|
|
11
|
-
"bom_line_number", #
|
|
12
|
-
"mfg", #
|
|
13
|
-
"mpn", #
|
|
8
|
+
"net", # the physical harness (represented by a net in Kicad) that this instance is part of
|
|
9
|
+
"instance_name", # the unique name of this instance
|
|
10
|
+
"print_name", # the non-unique, human-readable name of this instance, used for printing on output documents
|
|
11
|
+
"bom_line_number", # if this instance represents a physical procurable good, it gets assigned a line number on a bill of materials
|
|
12
|
+
"mfg", # manufacturer of this instance
|
|
13
|
+
"mpn", # manufacturer part number
|
|
14
14
|
"item_type", # connector, backshell, whatever
|
|
15
15
|
"parent_instance", # general purpose reference
|
|
16
16
|
"location_type", # each instance is either better represented by one or ther other
|
|
17
17
|
"segment_group", # the group of segments that this instance is part of
|
|
18
18
|
"segment_order", # the sequential id of this item in its segment group
|
|
19
19
|
"connector_group", # a group of co-located parts (connectors, backshells, nodes)
|
|
20
|
-
"channel_group", #
|
|
20
|
+
"channel_group", # other instances associated with this one because they are part of the same channel will share this value
|
|
21
21
|
"circuit_id", # which signal this component is electrically connected to
|
|
22
22
|
"circuit_port_number", # the sequential id of this item in its signal chain
|
|
23
23
|
"node_at_end_a", # derived from formboard definition
|
|
24
24
|
"node_at_end_b", # derived from formboard definition
|
|
25
|
+
"print_name_at_end_a", # human-readable name of this instance if needed, associated with 'node_at_end_a'
|
|
26
|
+
"print_name_at_end_b", # human-readable name of this instance if needed, associated with 'node_at_end_b'
|
|
25
27
|
"parent_csys_instance_name", # the other instance upon which this instance's location is based
|
|
26
28
|
"parent_csys_outputcsys_name", # the specific output coordinate system of the parent that this instance's location is based
|
|
27
29
|
"translate_x", # derived from parent_csys and parent_csys_name
|
|
@@ -29,9 +31,9 @@ COLUMNS = [
|
|
|
29
31
|
"rotate_csys", # derived from parent_csys and parent_csys_name
|
|
30
32
|
"absolute_rotation", # manual add, not nominally used unless it's a flagnote, segment, or node
|
|
31
33
|
"csys_children", # imported csys children from library attributes file
|
|
32
|
-
"cable_group", #
|
|
33
|
-
"cable_container", #
|
|
34
|
-
"cable_identifier", #
|
|
34
|
+
"cable_group", # other instances associated with this one because they are part of the same cable will share this value
|
|
35
|
+
"cable_container", # which cable is this instance physically bundled inside of
|
|
36
|
+
"cable_identifier", # cable unique identifier
|
|
35
37
|
"length", # derived from formboard definition, the length of a segment
|
|
36
38
|
"diameter", # apparent diameter of a segment <---------- change to print_diameter
|
|
37
39
|
"appearance", # see harnice.utils.appearance for details
|
|
@@ -40,39 +42,39 @@ COLUMNS = [
|
|
|
40
42
|
"note_parent", # the instance the note applies to. typically don't use this in the instances list, just note_utils
|
|
41
43
|
"note_text", # the content of the note
|
|
42
44
|
"note_affected_instances", # list of instances that are affected by the note
|
|
43
|
-
"lib_repo", #
|
|
44
|
-
"lib_subpath", #
|
|
45
|
-
"lib_desc", #
|
|
46
|
-
"lib_latest_rev", #
|
|
47
|
-
"lib_rev_used_here", #
|
|
48
|
-
"lib_status", #
|
|
45
|
+
"lib_repo", # publically-traceable URL of the library this instance is from
|
|
46
|
+
"lib_subpath", # path to the instance within the library (directories between the product type and the part number)
|
|
47
|
+
"lib_desc", # description of the instance per the library's revision history
|
|
48
|
+
"lib_latest_rev", # the latest revision of the instance that exists in the remote library
|
|
49
|
+
"lib_rev_used_here", # the revision of the instance that is currently used in this project
|
|
50
|
+
"lib_status", # the status of the instance per the library's revision history
|
|
49
51
|
"lib_releaseticket", #documentation needed
|
|
50
|
-
"lib_datestarted", #
|
|
51
|
-
"lib_datemodified", #
|
|
52
|
-
"lib_datereleased", #
|
|
53
|
-
"lib_drawnby", #
|
|
54
|
-
"lib_checkedby", #
|
|
55
|
-
"project_editable_lib_modified", #
|
|
56
|
-
"lib_build_notes", #
|
|
57
|
-
"lib_tools", #
|
|
52
|
+
"lib_datestarted", # the date this instance was first added to the library
|
|
53
|
+
"lib_datemodified", # the date this instance was last modified in the library
|
|
54
|
+
"lib_datereleased", # the date this instance was released in the library, if applicable, per the library's revision history
|
|
55
|
+
"lib_drawnby", # the name of the person who drew the instance, per the library's revision history
|
|
56
|
+
"lib_checkedby", # the name of the person who checked the instance, per the library's revision history
|
|
57
|
+
"project_editable_lib_modified", # a flag to indicate if the imported contents do not match the library's version (it's been locally modified)
|
|
58
|
+
"lib_build_notes", # recommended build notes that come with the instance from the library
|
|
59
|
+
"lib_tools", # recommended tools that come with the instance from the library
|
|
58
60
|
"this_instance_mating_device_refdes", # if connector, refdes of the device it plugs into
|
|
59
61
|
"this_instance_mating_device_connector", # if connector, name of the connector it plugs into
|
|
60
62
|
"this_instance_mating_device_connector_mpn", # if connector, mpn of the connector it plugs into
|
|
61
|
-
"this_net_from_device_refdes", #
|
|
62
|
-
"this_net_from_device_channel_id", #
|
|
63
|
-
"this_net_from_device_connector_name", #
|
|
64
|
-
"this_net_to_device_refdes", #
|
|
65
|
-
"this_net_to_device_channel_id", #
|
|
66
|
-
"this_net_to_device_connector_name", #
|
|
67
|
-
"this_channel_from_device_refdes", # if channel, refdes of the device
|
|
68
|
-
"this_channel_from_device_channel_id", #
|
|
69
|
-
"this_channel_to_device_refdes", # if channel, refdes of the device
|
|
70
|
-
"this_channel_to_device_channel_id", #
|
|
71
|
-
"this_channel_from_channel_type", #
|
|
72
|
-
"this_channel_to_channel_type", #
|
|
73
|
-
"signal_of_channel_type", #
|
|
74
|
-
"debug", #
|
|
75
|
-
"debug_cutoff", #
|
|
63
|
+
"this_net_from_device_refdes", # if this instance is a channel, circuit, conductor, etc, the refdes of the device it interfaces with, just within this net
|
|
64
|
+
"this_net_from_device_channel_id", # if this instance is a channel, circuit, conductor, etc, the channel id in the device it interfaces with, just within this net
|
|
65
|
+
"this_net_from_device_connector_name", # if this instance is a channel, circuit, conductor, etc, the name of the connector it interfaces with, just within this net
|
|
66
|
+
"this_net_to_device_refdes", # if this instance is a channel, circuit, conductor, etc, the refdes of the device it plugs into just within this net
|
|
67
|
+
"this_net_to_device_channel_id", # if this instance is a channel, circuit, conductor, etc, the channel id in the device it plugs into, just within this net
|
|
68
|
+
"this_net_to_device_connector_name", # if this instance is a channel, circuit, conductor, etc, the name of the connector it plugs into, just within this net
|
|
69
|
+
"this_channel_from_device_refdes", # if this instance is a channel, circuit, conductor, etc, the refdes of the device it interfaces with, at the very end of the channel
|
|
70
|
+
"this_channel_from_device_channel_id", # if this instance is a channel, circuit, conductor, etc, the channel id in the device it interfaces with, at the very end of the channel
|
|
71
|
+
"this_channel_to_device_refdes", # if this instance is a channel, circuit, conductor, etc, the refdes of the device it plugs into, at the very end of the channel
|
|
72
|
+
"this_channel_to_device_channel_id", # if this instance is a channel, circuit, conductor, etc, the channel id in the device it plugs into, at the very end of the channel
|
|
73
|
+
"this_channel_from_channel_type", # if this instance is a channel, circuit, conductor, etc, the type of the channel it interfaces with, at the very end of the channel
|
|
74
|
+
"this_channel_to_channel_type", # if this instance is a channel, circuit, conductor, etc, the type of the channel it plugs into, at the very end of the channel
|
|
75
|
+
"signal_of_channel_type", # if this instance is a channel, circuit, conductor, etc, the signal of the channel it interfaces with, at the very end of the channel
|
|
76
|
+
"debug", # the call chain of the function that last modified this instance row
|
|
77
|
+
"debug_cutoff", # blank cell to visually cut off the previous column
|
|
76
78
|
]
|
|
77
79
|
|
|
78
80
|
|
|
@@ -6,27 +6,59 @@ from harnice import fileio, state
|
|
|
6
6
|
|
|
7
7
|
# === Global Columns Definition ===
|
|
8
8
|
COLUMNS = [
|
|
9
|
-
"product",
|
|
10
|
-
"mfg",
|
|
11
|
-
"pn",
|
|
12
|
-
"desc",
|
|
13
|
-
"rev",
|
|
14
|
-
"status",
|
|
15
|
-
"releaseticket",
|
|
16
|
-
"library_repo",
|
|
17
|
-
"library_subpath",
|
|
18
|
-
"datestarted",
|
|
19
|
-
"datemodified",
|
|
20
|
-
"datereleased",
|
|
21
|
-
"git_hash_of_harnice_src",
|
|
22
|
-
"drawnby",
|
|
23
|
-
"checkedby",
|
|
24
|
-
"revisionupdates",
|
|
25
|
-
"affectedinstances",
|
|
9
|
+
"product", # the harnice product type (e.g. "harness", "connector", "device", "system", "macro", "flagnote", "tblock")
|
|
10
|
+
"mfg", # who manufactures this product (blank ok)
|
|
11
|
+
"pn", # name, part number, other identifier of this part. mfg+mpn combination must be unique within the library.
|
|
12
|
+
"desc", # a brief description of this product
|
|
13
|
+
"rev", # the revision of the part
|
|
14
|
+
"status", # "released", "obsolete", etc. Harnice will not render a revision if the status has text in this field as a form of protection.
|
|
15
|
+
"releaseticket", # many companies do this, but it's not required.
|
|
16
|
+
"library_repo", # auto-filled on render if the current working directory is discovered to be a library repository.
|
|
17
|
+
"library_subpath", # auto-filled on render if in a library repository, this is the chain of directories between the product type and the part number
|
|
18
|
+
"datestarted", # auto-filled to be the date when this part was first intialized
|
|
19
|
+
"datemodified", # updates to today's date upon rendering
|
|
20
|
+
"datereleased", # up to user to fill in as needed
|
|
21
|
+
"git_hash_of_harnice_src", # auto-filled, git hash of the harnice source code during the latest render
|
|
22
|
+
"drawnby", # auto-filled, the person who created the part
|
|
23
|
+
"checkedby", # the person who checked the part, blank ok
|
|
24
|
+
"revisionupdates", # a brief description of the changes made to this revision
|
|
25
|
+
"affectedinstances", # the instance names of the instances that were affected by this revision. can be referenced later by PDF builders and more.
|
|
26
26
|
]
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
def overwrite(content_dict):
|
|
30
|
+
"""
|
|
31
|
+
Overwrite a revision history entry.
|
|
32
|
+
|
|
33
|
+
**Arguments:**
|
|
34
|
+
|
|
35
|
+
- `content_dict` (dict): The content to overwrite the revision history entry with.
|
|
36
|
+
- This should be a dictionary with the keys and values to overwrite.
|
|
37
|
+
- The keys should be the column names, and the values should be the new values.
|
|
38
|
+
- Some keys are protected and cannot be overwritten:
|
|
39
|
+
- `"product"`
|
|
40
|
+
- `"mfg"`
|
|
41
|
+
- `"pn"`
|
|
42
|
+
- `"rev"`
|
|
43
|
+
- `"releaseticket"`
|
|
44
|
+
- `"library_repo"`
|
|
45
|
+
- `"library_subpath"`
|
|
46
|
+
- `"datestarted"`
|
|
47
|
+
|
|
48
|
+
The function will update the revision history file as referenced by the current product file structure.
|
|
49
|
+
|
|
50
|
+
**Returns:**
|
|
51
|
+
|
|
52
|
+
- `None`
|
|
53
|
+
|
|
54
|
+
**Raises:**
|
|
55
|
+
|
|
56
|
+
- `KeyError`: If a key is provided that is not in the COLUMNS list.
|
|
57
|
+
- `KeyError`: If a protected key is provided.
|
|
58
|
+
- `ValueError`: If the revision history file is not found.
|
|
59
|
+
- `ValueError`: If the revision is not found in the revision history file.
|
|
60
|
+
- `RuntimeError`: If `state.rev` is not set.
|
|
61
|
+
"""
|
|
30
62
|
PROTECTED_KEYS = [
|
|
31
63
|
"product",
|
|
32
64
|
"mfg",
|
|
@@ -84,6 +116,31 @@ def overwrite(content_dict):
|
|
|
84
116
|
|
|
85
117
|
|
|
86
118
|
def info(rev=None, path=None, field=None, all=False):
|
|
119
|
+
"""
|
|
120
|
+
Get information about a revision history entry.
|
|
121
|
+
|
|
122
|
+
**Arguments:**
|
|
123
|
+
|
|
124
|
+
- `rev` (str): The revision to get information about.
|
|
125
|
+
- `path` (str): The path to the revision history file.
|
|
126
|
+
- If not provided, the function will use the default path: `"revision history"`.
|
|
127
|
+
- `field` (str): The field to get information about.
|
|
128
|
+
- If not provided, the function will return the entire row.
|
|
129
|
+
- If provided, the function will return the value of the field.
|
|
130
|
+
- `all` (bool): If `True`, return all rows.
|
|
131
|
+
- If not provided, the function will return the first row.
|
|
132
|
+
|
|
133
|
+
**Returns:**
|
|
134
|
+
|
|
135
|
+
- `dict`: The row of the revision history entry (when `field` is not provided).
|
|
136
|
+
- `list`: A list of all rows in the revision history file (when `all=True`).
|
|
137
|
+
- `str`: The value of the field (when `field` is provided).
|
|
138
|
+
|
|
139
|
+
**Raises:**
|
|
140
|
+
|
|
141
|
+
- `FileNotFoundError`: If the revision history file is not found.
|
|
142
|
+
- `ValueError`: If the revision is not found in the revision history file.
|
|
143
|
+
"""
|
|
87
144
|
if path is None:
|
|
88
145
|
path = fileio.path("revision history")
|
|
89
146
|
|
|
@@ -104,7 +161,6 @@ def info(rev=None, path=None, field=None, all=False):
|
|
|
104
161
|
|
|
105
162
|
for row in rows:
|
|
106
163
|
if row.get("rev") == rev:
|
|
107
|
-
|
|
108
164
|
# ------------------------------------------------------
|
|
109
165
|
# Field requested
|
|
110
166
|
# ------------------------------------------------------
|
|
@@ -142,6 +198,17 @@ def info(rev=None, path=None, field=None, all=False):
|
|
|
142
198
|
|
|
143
199
|
|
|
144
200
|
def initial_release_exists():
|
|
201
|
+
"""
|
|
202
|
+
Check if an initial release exists.
|
|
203
|
+
|
|
204
|
+
**Arguments:**
|
|
205
|
+
|
|
206
|
+
None
|
|
207
|
+
|
|
208
|
+
**Returns:**
|
|
209
|
+
|
|
210
|
+
- `bool`: `True` if a revision with the text `"INITIAL RELEASE"` in the `"revisionupdates"` field exists, `False` otherwise.
|
|
211
|
+
"""
|
|
145
212
|
try:
|
|
146
213
|
for row in fileio.read_tsv("revision history"):
|
|
147
214
|
if str(row.get("revisionupdates", "")).strip() == "INITIAL RELEASE":
|
|
@@ -153,12 +220,39 @@ def initial_release_exists():
|
|
|
153
220
|
|
|
154
221
|
|
|
155
222
|
def initial_release_desc():
|
|
223
|
+
"""
|
|
224
|
+
Get the description of the initial release.
|
|
225
|
+
|
|
226
|
+
**Arguments:**
|
|
227
|
+
|
|
228
|
+
None
|
|
229
|
+
|
|
230
|
+
**Returns:**
|
|
231
|
+
|
|
232
|
+
- `str`: The description of the revision which has `revisionupdates == 'INITIAL RELEASE'`.
|
|
233
|
+
"""
|
|
156
234
|
for row in fileio.read_tsv("revision history"):
|
|
157
235
|
if row.get("revisionupdates") == "INITIAL RELEASE":
|
|
158
236
|
return row.get("desc")
|
|
159
237
|
|
|
160
238
|
|
|
161
239
|
def update_datemodified():
|
|
240
|
+
"""
|
|
241
|
+
Update the `datemodified` field of the current revision with today's date.
|
|
242
|
+
|
|
243
|
+
**Arguments:**
|
|
244
|
+
|
|
245
|
+
None
|
|
246
|
+
|
|
247
|
+
**Returns:**
|
|
248
|
+
|
|
249
|
+
- `None`
|
|
250
|
+
|
|
251
|
+
**Raises:**
|
|
252
|
+
|
|
253
|
+
- `ValueError`: If the revision history file is not found.
|
|
254
|
+
- `ValueError`: If the revision is not found in the revision history file.
|
|
255
|
+
"""
|
|
162
256
|
target_rev = state.partnumber("R")
|
|
163
257
|
|
|
164
258
|
# Read all rows
|
|
@@ -182,42 +276,94 @@ def update_datemodified():
|
|
|
182
276
|
writer.writerows(rows)
|
|
183
277
|
|
|
184
278
|
|
|
185
|
-
def new():
|
|
279
|
+
def new(ignore_product=False, path=None):
|
|
280
|
+
"""
|
|
281
|
+
Create a new revision history file.
|
|
282
|
+
|
|
283
|
+
**Arguments:**
|
|
284
|
+
|
|
285
|
+
- `ignore_product` (bool):
|
|
286
|
+
- If `True`, the function will raise an error if `state.product` is not set first.
|
|
287
|
+
- If `False`, the function will prompt the user to select a product type.
|
|
288
|
+
|
|
289
|
+
**Returns:**
|
|
290
|
+
|
|
291
|
+
- `None`
|
|
292
|
+
|
|
293
|
+
**Raises:**
|
|
294
|
+
|
|
295
|
+
- `ValueError`: If attempting to create a new revision history file without a product type when `ignore_product=True`.
|
|
296
|
+
- `ValueError`: If attempting to overwrite an existing revision history file.
|
|
297
|
+
"""
|
|
186
298
|
columns = COLUMNS
|
|
187
|
-
from harnice.cli import select_product_type
|
|
188
299
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
300
|
+
if path is None:
|
|
301
|
+
path = fileio.path("revision history")
|
|
302
|
+
|
|
303
|
+
if not ignore_product:
|
|
304
|
+
from harnice.cli import select_product_type
|
|
305
|
+
|
|
306
|
+
state.set_product(select_product_type())
|
|
307
|
+
|
|
308
|
+
if ignore_product and not state.product:
|
|
309
|
+
raise ValueError(
|
|
310
|
+
"You tried to create a new revision history file without a product type. This is not allowed."
|
|
311
|
+
)
|
|
312
|
+
|
|
313
|
+
if not os.path.exists(path):
|
|
314
|
+
with open(path, "w", newline="", encoding="utf-8") as f:
|
|
315
|
+
writer = csv.DictWriter(f, fieldnames=columns, delimiter="\t")
|
|
316
|
+
writer.writeheader()
|
|
317
|
+
|
|
318
|
+
else:
|
|
319
|
+
raise ValueError(
|
|
320
|
+
"You tried to overwrite a revision history file- this is not allowed."
|
|
321
|
+
)
|
|
194
322
|
|
|
195
323
|
|
|
196
324
|
def append(next_rev=None):
|
|
197
|
-
|
|
325
|
+
"""
|
|
326
|
+
Append a new revision history entry to the current revision history file.
|
|
327
|
+
|
|
328
|
+
If the revision history file does not exist, the function will create it.
|
|
329
|
+
If the revision history file exists, the function will append a new entry to the file.
|
|
330
|
+
|
|
331
|
+
It will prompt the user for the following fields:
|
|
332
|
+
|
|
333
|
+
- `product`: The product type of the part.
|
|
334
|
+
- `desc`: The description of the part.
|
|
335
|
+
- `revisionupdates`: What is the purpose of this revision?
|
|
336
|
+
|
|
337
|
+
If the previous revision has a blank status, the function will prompt the user to obsolete it with a message.
|
|
338
|
+
|
|
339
|
+
**Arguments:**
|
|
340
|
+
|
|
341
|
+
- `next_rev` The next revision number to append.
|
|
342
|
+
|
|
343
|
+
**Returns:**
|
|
198
344
|
|
|
199
|
-
|
|
345
|
+
- `None`
|
|
346
|
+
"""
|
|
347
|
+
from harnice import cli
|
|
200
348
|
|
|
201
349
|
if not os.path.exists(fileio.path("revision history")):
|
|
202
350
|
new()
|
|
203
351
|
rows = fileio.read_tsv("revision history")
|
|
204
|
-
product_name = None
|
|
205
352
|
if rows:
|
|
206
353
|
for row in reversed(rows):
|
|
207
354
|
candidate = (row.get("product") or "").strip()
|
|
208
355
|
if candidate:
|
|
209
|
-
|
|
356
|
+
state.set_product(candidate)
|
|
210
357
|
break
|
|
211
|
-
if not
|
|
212
|
-
|
|
213
|
-
if not product_name:
|
|
214
|
-
product_name = cli.select_product_type()
|
|
215
|
-
product = product_name
|
|
358
|
+
if not state.product:
|
|
359
|
+
state.set_product(cli.select_product_type())
|
|
216
360
|
|
|
217
361
|
default_desc = ""
|
|
218
|
-
if
|
|
362
|
+
if state.product:
|
|
219
363
|
try:
|
|
220
|
-
product_module = importlib.import_module(
|
|
364
|
+
product_module = importlib.import_module(
|
|
365
|
+
f"harnice.products.{state.product}"
|
|
366
|
+
)
|
|
221
367
|
except ModuleNotFoundError:
|
|
222
368
|
product_module = None
|
|
223
369
|
else:
|
|
@@ -252,7 +398,7 @@ def append(next_rev=None):
|
|
|
252
398
|
|
|
253
399
|
if desc in [None, ""]:
|
|
254
400
|
desc = cli.prompt(
|
|
255
|
-
f"Enter a description of this {
|
|
401
|
+
f"Enter a description of this {state.product}",
|
|
256
402
|
default=default_desc,
|
|
257
403
|
)
|
|
258
404
|
|
|
@@ -305,7 +451,7 @@ def append(next_rev=None):
|
|
|
305
451
|
|
|
306
452
|
rows.append(
|
|
307
453
|
{
|
|
308
|
-
"product":
|
|
454
|
+
"product": state.product,
|
|
309
455
|
"pn": state.pn,
|
|
310
456
|
"rev": next_rev,
|
|
311
457
|
"desc": desc,
|
|
@@ -323,3 +469,67 @@ def append(next_rev=None):
|
|
|
323
469
|
writer = csv.DictWriter(f, fieldnames=columns, delimiter="\t")
|
|
324
470
|
writer.writeheader()
|
|
325
471
|
writer.writerows(rows)
|
|
472
|
+
|
|
473
|
+
|
|
474
|
+
def part_family_append(content_dict, rev_history_path):
|
|
475
|
+
"""
|
|
476
|
+
Append a new revision history entry to the part family revision history file.
|
|
477
|
+
|
|
478
|
+
Intended to be called by part family scripts only.
|
|
479
|
+
|
|
480
|
+
The function will automatically update the following fields in the content dictionary:
|
|
481
|
+
|
|
482
|
+
- `datemodified`: Set to today's date
|
|
483
|
+
- `drawnby`: Set to the current user's name
|
|
484
|
+
- `git_hash_of_harnice_src`: Set to the current git hash of the harnice source code
|
|
485
|
+
|
|
486
|
+
If the revision history file does not exist, the function will create it.
|
|
487
|
+
If an entry with the same revision number already exists, the function will update that entry.
|
|
488
|
+
Otherwise, the function will append a new entry to the file.
|
|
489
|
+
|
|
490
|
+
**Arguments:**
|
|
491
|
+
|
|
492
|
+
- `content_dict` (dict): The content to append to the part family revision history file.
|
|
493
|
+
- Should contain keys matching the `COLUMNS` list.
|
|
494
|
+
- The `rev` key is used to determine if an entry already exists.
|
|
495
|
+
- `rev_history_path` (str): The path to the part family revision history file.
|
|
496
|
+
|
|
497
|
+
**Returns:**
|
|
498
|
+
|
|
499
|
+
- `None`
|
|
500
|
+
|
|
501
|
+
**Raises:**
|
|
502
|
+
|
|
503
|
+
- `ValueError`: If the content dictionary contains invalid keys or missing required fields.
|
|
504
|
+
"""
|
|
505
|
+
actual_content_dict = content_dict
|
|
506
|
+
|
|
507
|
+
actual_content_dict["datemodified"] = fileio.today()
|
|
508
|
+
actual_content_dict["drawnby"] = fileio.drawnby()["name"]
|
|
509
|
+
actual_content_dict["git_hash_of_harnice_src"] = (
|
|
510
|
+
fileio.get_git_hash_of_harnice_src()
|
|
511
|
+
)
|
|
512
|
+
|
|
513
|
+
rev = content_dict.get("rev")
|
|
514
|
+
|
|
515
|
+
if os.path.exists(rev_history_path):
|
|
516
|
+
rows = fileio.read_tsv(rev_history_path)
|
|
517
|
+
else:
|
|
518
|
+
rows = []
|
|
519
|
+
|
|
520
|
+
found = False
|
|
521
|
+
for i, row in enumerate(rows):
|
|
522
|
+
if row.get("rev") == actual_content_dict.get("rev"):
|
|
523
|
+
rows[i] = actual_content_dict
|
|
524
|
+
found = True
|
|
525
|
+
break
|
|
526
|
+
|
|
527
|
+
if not found:
|
|
528
|
+
rows.append(actual_content_dict)
|
|
529
|
+
|
|
530
|
+
if not os.path.exists(rev_history_path):
|
|
531
|
+
new(path=rev_history_path, ignore_product=True)
|
|
532
|
+
with open(rev_history_path, "w", newline="", encoding="utf-8") as f:
|
|
533
|
+
writer = csv.DictWriter(f, fieldnames=COLUMNS, delimiter="\t")
|
|
534
|
+
writer.writeheader()
|
|
535
|
+
writer.writerows(rows)
|
|
@@ -162,7 +162,7 @@ for instance in instances:
|
|
|
162
162
|
if instance.get("item_type") == "circuit":
|
|
163
163
|
circuit_instance = instance
|
|
164
164
|
connector_at_end_a = instances_list.attribute_of(instance.get("node_at_end_a"), "connector_group")
|
|
165
|
-
new_instance_name = f"{{circuit_instance.get(
|
|
165
|
+
new_instance_name = f"{{circuit_instance.get('instance_name')}}-special_contact"
|
|
166
166
|
circuit_id = int(circuit_instance.get("circuit_id"))
|
|
167
167
|
instances_list.new_instance(
|
|
168
168
|
new_instance_name, {{
|
|
@@ -181,7 +181,7 @@ circuit_utils.squeeze_instance_between_ports_in_circuit(
|
|
|
181
181
|
# example: add a backshell
|
|
182
182
|
for instance in instances:
|
|
183
183
|
if instance.get("instance_name") in ["X1.B.conn", "PREAMP2.in2.conn"]:
|
|
184
|
-
instances_list.new_instance(f"{{instance.get(
|
|
184
|
+
instances_list.new_instance(f"{{instance.get('connector_group')}}.bs", {{
|
|
185
185
|
"bom_line_number": True,
|
|
186
186
|
"mpn": "M85049-90_9Z03",
|
|
187
187
|
"item_type": "backshell",
|
|
@@ -193,7 +193,7 @@ for instance in instances:
|
|
|
193
193
|
"lib_repo": "https://github.com/harnice/harnice"
|
|
194
194
|
}})
|
|
195
195
|
instances_list.modify(instance.get("instance_name"), {{
|
|
196
|
-
"parent_csys_instance_name": f"{{instance.get(
|
|
196
|
+
"parent_csys_instance_name": f"{{instance.get('connector_group')}}.bs",
|
|
197
197
|
"parent_csys_outputcsys_name": "connector",
|
|
198
198
|
}})
|
|
199
199
|
|
|
@@ -270,23 +270,23 @@ for x in range(2):
|
|
|
270
270
|
|
|
271
271
|
elif instance.get("item_type") in ["conductor", "conductor-segment"]:
|
|
272
272
|
instances_list.modify(instance.get("instance_name"), {{
|
|
273
|
-
"print_name": f"'{{instance.get(
|
|
273
|
+
"print_name": f"'{{instance.get('cable_identifier')}}' of '{{instances_list.attribute_of(instance.get('cable_group'), 'print_name')}}'"
|
|
274
274
|
}})
|
|
275
275
|
|
|
276
276
|
elif instance.get("item_type") == "net-channel":
|
|
277
|
-
print_name = f"'{{instance.get(
|
|
277
|
+
print_name = f"'{{instance.get('this_channel_from_device_channel_id')}}' of '{{instance.get('this_channel_from_device_refdes')}}' to '{{instance.get('this_channel_to_device_channel_id')}}' of '{{instance.get('this_channel_to_device_refdes')}}'"
|
|
278
278
|
instances_list.modify(instance.get("instance_name"), {{"print_name": print_name}})
|
|
279
279
|
|
|
280
280
|
elif instance.get("item_type") == "net-channel-segment":
|
|
281
|
-
print_name = f"'{{instances_list.attribute_of(instance.get(
|
|
281
|
+
print_name = f"'{{instances_list.attribute_of(instance.get('parent_instance'), 'this_channel_from_device_channel_id')}}' of '{{instances_list.attribute_of(instance.get('parent_instance'), 'this_channel_from_device_refdes')}}' to '{{instances_list.attribute_of(instance.get('parent_instance'), 'this_channel_to_device_channel_id')}}' of '{{instances_list.attribute_of(instance.get('parent_instance'), 'this_channel_to_device_refdes')}}'"
|
|
282
282
|
instances_list.modify(instance.get("instance_name"), {{"print_name": print_name}})
|
|
283
283
|
|
|
284
284
|
elif instance.get("item_type") == "connector":
|
|
285
|
-
print_name = f"{{instance.get(
|
|
285
|
+
print_name = f"{{instance.get('connector_group')}}"
|
|
286
286
|
instances_list.modify(instance.get("instance_name"), {{"print_name": print_name}})
|
|
287
287
|
|
|
288
288
|
elif instance.get("item_type") == "cable-segment":
|
|
289
|
-
print_name = f"{{instance.get(
|
|
289
|
+
print_name = f"{{instance.get('cable_group')}}"
|
|
290
290
|
instances_list.modify(instance.get("instance_name"), {{"print_name": print_name}})
|
|
291
291
|
|
|
292
292
|
elif instance.get("item_type") == "contact":
|