s7datablock 0.0.1__tar.gz → 0.0.2__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.
Files changed (35) hide show
  1. {s7datablock-0.0.1 → s7datablock-0.0.2}/PKG-INFO +25 -26
  2. {s7datablock-0.0.1 → s7datablock-0.0.2}/README.md +24 -25
  3. s7datablock-0.0.2/docs/example.png +0 -0
  4. {s7datablock-0.0.1 → s7datablock-0.0.2}/examples/live_monitor.py +9 -5
  5. {s7datablock-0.0.1 → s7datablock-0.0.2}/examples/parse_file.py +1 -1
  6. {s7datablock-0.0.1 → s7datablock-0.0.2}/pyproject.toml +1 -1
  7. {s7datablock-0.0.1 → s7datablock-0.0.2}/src/s7datablock/mapping.py +3 -2
  8. {s7datablock-0.0.1 → s7datablock-0.0.2}/src/s7datablock/parser.py +5 -5
  9. {s7datablock-0.0.1 → s7datablock-0.0.2}/tests/test_dtl_struct.py +1 -1
  10. {s7datablock-0.0.1 → s7datablock-0.0.2}/tests/test_s7_parsing.py +8 -8
  11. {s7datablock-0.0.1 → s7datablock-0.0.2}/uv.lock +1 -1
  12. s7datablock-0.0.1/docs/example.png +0 -0
  13. {s7datablock-0.0.1 → s7datablock-0.0.2}/.coveragerc +0 -0
  14. {s7datablock-0.0.1 → s7datablock-0.0.2}/.github/workflows/ci.yml +0 -0
  15. {s7datablock-0.0.1 → s7datablock-0.0.2}/.gitignore +0 -0
  16. {s7datablock-0.0.1 → s7datablock-0.0.2}/.isort.cfg +0 -0
  17. {s7datablock-0.0.1 → s7datablock-0.0.2}/.pre-commit-config.yaml +0 -0
  18. {s7datablock-0.0.1 → s7datablock-0.0.2}/.readthedocs.yml +0 -0
  19. {s7datablock-0.0.1 → s7datablock-0.0.2}/AUTHORS.md +0 -0
  20. {s7datablock-0.0.1 → s7datablock-0.0.2}/LICENSE.txt +0 -0
  21. {s7datablock-0.0.1 → s7datablock-0.0.2}/examples/basic_usage.py +0 -0
  22. {s7datablock-0.0.1 → s7datablock-0.0.2}/examples/dtl_date.py +0 -0
  23. {s7datablock-0.0.1 → s7datablock-0.0.2}/src/s7datablock/__init__.py +0 -0
  24. {s7datablock-0.0.1 → s7datablock-0.0.2}/src/s7datablock/constants.py +0 -0
  25. {s7datablock-0.0.1 → s7datablock-0.0.2}/src/s7datablock/fields.py +0 -0
  26. {s7datablock-0.0.1 → s7datablock-0.0.2}/src/s7datablock/grammar.py +0 -0
  27. {s7datablock-0.0.1 → s7datablock-0.0.2}/src/s7datablock/py.typed +0 -0
  28. {s7datablock-0.0.1 → s7datablock-0.0.2}/test_buffer_mapping_extended.py +0 -0
  29. {s7datablock-0.0.1 → s7datablock-0.0.2}/tests/conftest.py +0 -0
  30. {s7datablock-0.0.1 → s7datablock-0.0.2}/tests/definitions/s7_1200_out.db +0 -0
  31. {s7datablock-0.0.1 → s7datablock-0.0.2}/tests/definitions/tester.db +0 -0
  32. {s7datablock-0.0.1 → s7datablock-0.0.2}/tests/test_buffer_mapping.py +0 -0
  33. {s7datablock-0.0.1 → s7datablock-0.0.2}/tests/test_buffer_mapping_extended.py +0 -0
  34. {s7datablock-0.0.1 → s7datablock-0.0.2}/tests/test_s7_connector.py +0 -0
  35. {s7datablock-0.0.1 → s7datablock-0.0.2}/tests/test_s7_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: s7datablock
3
- Version: 0.0.1
3
+ Version: 0.0.2
4
4
  Summary: A Python library for interacting with Siemens S7 PLC datablocks
5
5
  Project-URL: Homepage, https://github.com/CEAD-group/s7datablock
6
6
  Project-URL: Documentation, https://github.com/CEAD-group/s7datablock
@@ -45,7 +45,7 @@ Instead of manually mapping byte offsets and types, you can use `.db` definition
45
45
  - Clean terminal output using [Rich](https://github.com/Textualize/rich)
46
46
  - Easy integration into polling and monitoring loops
47
47
 
48
- ![example.png](docs/example.png)
48
+ ![example.png](https://github.com/CEAD-group/s7datablock/raw/main/docs/example.png)
49
49
 
50
50
  ---
51
51
 
@@ -92,6 +92,7 @@ df_file_contents = StringIO(
92
92
  db = S7DataBlock.from_definition_file(df_file_contents, db_number=1200)
93
93
  print(db) # This will print the structure of the data block as a table
94
94
 
95
+ print(repr(db)) # Print the raw representation of the data block
95
96
  # In a real application, you would create a snap7 client and connect to the PLC
96
97
 
97
98
  # client = snap7.client.Client()
@@ -103,10 +104,10 @@ with Live(db.to_table(), refresh_per_second=10) as live:
103
104
  # db.GET(client)
104
105
 
105
106
  # For demo, we'll just modify some values
106
- db["my_udt.WHEN"] = datetime.now()
107
- db["my_udt.PLC_DQ_0"] = not db["my_udt.PLC_DQ_0"] # Toggle the boolean
108
- db["my_udt.Value1"] = db["my_udt.Value1"] + 1 # Increment the integer value
109
- db["my_udt.Value2"] = db["my_udt.Value2"] + 0.1 # Increment the real value
107
+ db["WHEN"] = datetime.now()
108
+ db["PLC_DQ_0"] = not db["PLC_DQ_0"] # Toggle the boolean
109
+ db["Value1"] = db["Value1"] + 1 # Increment the integer value
110
+ db["Value2"] = db["Value2"] + 0.1 # Increment the real value
110
111
 
111
112
  # Update the display with current values
112
113
  live.update(db.to_table())
@@ -115,26 +116,24 @@ with Live(db.to_table(), refresh_per_second=10) as live:
115
116
 
116
117
  Running this code should render a live table in your terminal
117
118
  ```text
118
-
119
- Data Block Structure
120
- ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┓
121
- ┃ Name ┃ Data type ┃ Offset ┃ Value ┃
122
- ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━┩
123
- │ my_udt │ Struct │ │ │
124
- │ my_udt.PLC_DQ_0 │ Bool │ 0.0 │ False │
125
- │ my_udt.PLC_DQ_1 │ Bool │ 0.1 │ False │
126
- │ my_udt.WHEN │ DTL │ 2.0 │ 2025-07-14 16:06:06 │
127
- │ my_udt.WHEN.YEAR │ UInt │ 2.0 │ 2025 │
128
- │ my_udt.WHEN.MONTH │ USInt │ 4.0 │ 7 │
129
- │ my_udt.WHEN.DAY │ USInt │ 5.0 │ 14 │
130
- │ my_udt.WHEN.WEEKDAY │ USInt │ 6.0 │ 1 │
131
- │ my_udt.WHEN.HOUR │ USInt │ 7.0 │ 16 │
132
- │ my_udt.WHEN.MINUTE │ USInt │ 8.0 │ 6 │
133
- │ my_udt.WHEN.SECOND │ USInt │ 9.0 │ 6 │
134
- │ my_udt.WHEN.NANOSECOND │ UDInt │ 10.0 │ 195792000 │
135
- │ my_udt.Value1 │ Int │ 14.0 │ 44 │
136
- │ my_udt.Value2 │ Real │ 16.0 │ 4.400 │
137
- └────────────────────────────┴─────────────┴──────────┴─────────────────────┘
119
+ Data Block Structure
120
+ ┏━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┓
121
+ ┃ Name ┃ Data type ┃ Offset ┃ Value ┃
122
+ ┡━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━┩
123
+ │ PLC_DQ_0 │ Bool │ 0.0 │ True │
124
+ │ PLC_DQ_1 │ Bool │ 0.1 │ False │
125
+ │ WHEN │ DTL │ 2.0 │ 2025-07-14 17:08:40 │
126
+ │ WHEN.YEAR │ UInt │ 2.0 │ 2025 │
127
+ │ WHEN.MONTH │ USInt │ 4.0 │ 7 │
128
+ │ WHEN.DAY │ USInt │ 5.0 │ 14 │
129
+ │ WHEN.WEEKDAY │ USInt │ 6.0 │ 1 │
130
+ │ WHEN.HOUR │ USInt │ 7.0 │ 17 │
131
+ │ WHEN.MINUTE │ USInt │ 8.0 │ 8 │
132
+ │ WHEN.SECOND │ USInt │ 9.0 │ 40 │
133
+ │ WHEN.NANOSECOND │ UDInt │ 10.0 │ 568441000 │
134
+ │ Value1 │ Int │ 14.0 │ 757 │
135
+ │ Value2 │ Real │ 16.0 │ 75.699 │
136
+ └───────────────────┴─────────────┴──────────┴─────────────────────┘
138
137
  ```
139
138
 
140
139
 
@@ -23,7 +23,7 @@ Instead of manually mapping byte offsets and types, you can use `.db` definition
23
23
  - Clean terminal output using [Rich](https://github.com/Textualize/rich)
24
24
  - Easy integration into polling and monitoring loops
25
25
 
26
- ![example.png](docs/example.png)
26
+ ![example.png](https://github.com/CEAD-group/s7datablock/raw/main/docs/example.png)
27
27
 
28
28
  ---
29
29
 
@@ -70,6 +70,7 @@ df_file_contents = StringIO(
70
70
  db = S7DataBlock.from_definition_file(df_file_contents, db_number=1200)
71
71
  print(db) # This will print the structure of the data block as a table
72
72
 
73
+ print(repr(db)) # Print the raw representation of the data block
73
74
  # In a real application, you would create a snap7 client and connect to the PLC
74
75
 
75
76
  # client = snap7.client.Client()
@@ -81,10 +82,10 @@ with Live(db.to_table(), refresh_per_second=10) as live:
81
82
  # db.GET(client)
82
83
 
83
84
  # For demo, we'll just modify some values
84
- db["my_udt.WHEN"] = datetime.now()
85
- db["my_udt.PLC_DQ_0"] = not db["my_udt.PLC_DQ_0"] # Toggle the boolean
86
- db["my_udt.Value1"] = db["my_udt.Value1"] + 1 # Increment the integer value
87
- db["my_udt.Value2"] = db["my_udt.Value2"] + 0.1 # Increment the real value
85
+ db["WHEN"] = datetime.now()
86
+ db["PLC_DQ_0"] = not db["PLC_DQ_0"] # Toggle the boolean
87
+ db["Value1"] = db["Value1"] + 1 # Increment the integer value
88
+ db["Value2"] = db["Value2"] + 0.1 # Increment the real value
88
89
 
89
90
  # Update the display with current values
90
91
  live.update(db.to_table())
@@ -93,26 +94,24 @@ with Live(db.to_table(), refresh_per_second=10) as live:
93
94
 
94
95
  Running this code should render a live table in your terminal
95
96
  ```text
96
-
97
- Data Block Structure
98
- ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┓
99
- ┃ Name ┃ Data type ┃ Offset ┃ Value ┃
100
- ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━┩
101
- │ my_udt │ Struct │ │ │
102
- │ my_udt.PLC_DQ_0 │ Bool │ 0.0 │ False │
103
- │ my_udt.PLC_DQ_1 │ Bool │ 0.1 │ False │
104
- │ my_udt.WHEN │ DTL │ 2.0 │ 2025-07-14 16:06:06 │
105
- │ my_udt.WHEN.YEAR │ UInt │ 2.0 │ 2025 │
106
- │ my_udt.WHEN.MONTH │ USInt │ 4.0 │ 7 │
107
- │ my_udt.WHEN.DAY │ USInt │ 5.0 │ 14 │
108
- │ my_udt.WHEN.WEEKDAY │ USInt │ 6.0 │ 1 │
109
- │ my_udt.WHEN.HOUR │ USInt │ 7.0 │ 16 │
110
- │ my_udt.WHEN.MINUTE │ USInt │ 8.0 │ 6 │
111
- │ my_udt.WHEN.SECOND │ USInt │ 9.0 │ 6 │
112
- │ my_udt.WHEN.NANOSECOND │ UDInt │ 10.0 │ 195792000 │
113
- │ my_udt.Value1 │ Int │ 14.0 │ 44 │
114
- │ my_udt.Value2 │ Real │ 16.0 │ 4.400 │
115
- └────────────────────────────┴─────────────┴──────────┴─────────────────────┘
97
+ Data Block Structure
98
+ ┏━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┓
99
+ ┃ Name ┃ Data type ┃ Offset ┃ Value ┃
100
+ ┡━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━┩
101
+ │ PLC_DQ_0 │ Bool │ 0.0 │ True │
102
+ │ PLC_DQ_1 │ Bool │ 0.1 │ False │
103
+ │ WHEN │ DTL │ 2.0 │ 2025-07-14 17:08:40 │
104
+ │ WHEN.YEAR │ UInt │ 2.0 │ 2025 │
105
+ │ WHEN.MONTH │ USInt │ 4.0 │ 7 │
106
+ │ WHEN.DAY │ USInt │ 5.0 │ 14 │
107
+ │ WHEN.WEEKDAY │ USInt │ 6.0 │ 1 │
108
+ │ WHEN.HOUR │ USInt │ 7.0 │ 17 │
109
+ │ WHEN.MINUTE │ USInt │ 8.0 │ 8 │
110
+ │ WHEN.SECOND │ USInt │ 9.0 │ 40 │
111
+ │ WHEN.NANOSECOND │ UDInt │ 10.0 │ 568441000 │
112
+ │ Value1 │ Int │ 14.0 │ 757 │
113
+ │ Value2 │ Real │ 16.0 │ 75.699 │
114
+ └───────────────────┴─────────────┴──────────┴─────────────────────┘
116
115
  ```
117
116
 
118
117
 
Binary file
@@ -6,6 +6,7 @@ from rich.live import Live
6
6
 
7
7
  from s7datablock.mapping import S7DataBlock
8
8
 
9
+ # Example in-line definition file contents. Alternatively, you can pass a PAth to a *.db file.
9
10
  df_file_contents = StringIO(
10
11
  """
11
12
  TYPE "my_udt"
@@ -26,9 +27,12 @@ df_file_contents = StringIO(
26
27
  """
27
28
  )
28
29
 
29
- db = S7DataBlock.from_definition_file(df_file_contents, db_number=1200, nesting_depth_to_skip=0)
30
+ db = S7DataBlock.from_definition_file(df_file_contents, db_number=1200)
31
+ print(db) # This will print the structure of the data block as a table
30
32
 
33
+ print(repr(db)) # Print the raw representation of the data block
31
34
  # In a real application, you would create a snap7 client and connect to the PLC
35
+
32
36
  # client = snap7.client.Client()
33
37
  # client.connect('192.168.0.1', 0, 1)
34
38
 
@@ -38,10 +42,10 @@ with Live(db.to_table(), refresh_per_second=10) as live:
38
42
  # db.GET(client)
39
43
 
40
44
  # For demo, we'll just modify some values
41
- db["my_udt.WHEN"] = datetime.now()
42
- db["my_udt.PLC_DQ_0"] = not db["my_udt.PLC_DQ_0"] # Toggle the boolean
43
- db["my_udt.Value1"] = db["my_udt.Value1"] + 1 # Increment the integer value
44
- db["my_udt.Value2"] = db["my_udt.Value2"] + 0.1 # Increment the real value
45
+ db["WHEN"] = datetime.now()
46
+ db["PLC_DQ_0"] = not db["PLC_DQ_0"] # Toggle the boolean
47
+ db["Value1"] = db["Value1"] + 1 # Increment the integer value
48
+ db["Value2"] = db["Value2"] + 0.1 # Increment the real value
45
49
 
46
50
  # Update the display with current values
47
51
  live.update(db.to_table())
@@ -22,7 +22,7 @@ END_DATA_BLOCK
22
22
  """
23
23
  )
24
24
 
25
- db = S7DataBlock.from_definition_file(db_buff, db_number=1200, nesting_depth_to_skip=0)
25
+ db = S7DataBlock.from_definition_file(db_buff, db_number=1200, prefix_levels_to_skip=0)
26
26
 
27
27
  # Set initial datetime value
28
28
  now = datetime(2025, 7, 9, 14, 30, 45, 123456) # microseconds = 123456
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "s7datablock"
3
- version = "0.0.1"
3
+ version = "0.0.2"
4
4
  description = "A Python library for interacting with Siemens S7 PLC datablocks"
5
5
  readme = "README.md"
6
6
  authors = [
@@ -172,17 +172,18 @@ class S7DataBlock(BufferMapping):
172
172
  self.db_size = db_size
173
173
 
174
174
  @classmethod
175
- def from_definition_file(cls, path, db_number: int | None = None, nesting_depth_to_skip: int = 1) -> "S7DataBlock":
175
+ def from_definition_file(cls, path, db_number: int | None = None, prefix_levels_to_skip: int = 1) -> "S7DataBlock":
176
176
  """Create an S7DataBlock from a TIA Portal export file.
177
177
 
178
178
  Args:
179
179
  path: Path to the TIA Portal export file
180
180
  db_number: Optional DB number for PLC communication
181
+ prefix_levels_to_skip: How many prefix levels to skip when generating fieldnames. Default=1 skips the UDT name.
181
182
 
182
183
  Returns:
183
184
  S7DataBlock: The created datablock
184
185
  """
185
- mapping, size = parse_db_file(path, nesting_depth_to_skip=nesting_depth_to_skip)
186
+ mapping, size = parse_db_file(path, prefix_levels_to_skip=prefix_levels_to_skip)
186
187
  return cls(buffer=bytearray(size), mapping=mapping, db_number=db_number, db_size=size)
187
188
 
188
189
  def GET(self, client: snap7.client.Client):
@@ -20,12 +20,12 @@ def resolve_data_types(types: dict[str, Any], prefix: list[str], d: Any) -> Iter
20
20
  yield prefix, d
21
21
 
22
22
 
23
- def parse_db_file(p: Path | StringIO, nesting_depth_to_skip=1) -> DBParseResult:
23
+ def parse_db_file(p: Path | StringIO, prefix_levels_to_skip=1) -> DBParseResult:
24
24
  """Parse a DB file and return a S7Field mapping and total size.
25
25
 
26
26
  Args:
27
27
  p (Path): Path to the DB file
28
- nesting_depth_to_skip (int, optional): How many levels in the nested data to skip when generating the fieldnames for nested fields.
28
+ prefix_levels_to_skip (int, optional): How many prefix levels to skip when generating fieldnames. Default=1 skips the UDT name.
29
29
 
30
30
  Returns:
31
31
  tuple[dict[str, S7Field], int]: The S7Field mapping and total size in bytes
@@ -37,8 +37,8 @@ def parse_db_file(p: Path | StringIO, nesting_depth_to_skip=1) -> DBParseResult:
37
37
  else:
38
38
  raise TypeError("Input must be a Path or StringIO")
39
39
 
40
- if nesting_depth_to_skip < 0:
41
- raise ValueError("nesting_depth_to_skip must be a non-negative integer")
40
+ if prefix_levels_to_skip < 0:
41
+ raise ValueError("prefix_levels_to_skip must be a non-negative integer")
42
42
  result = program.parseString(string, parse_all=True).as_dict()
43
43
  types = result["TYPES"]
44
44
  data = result["DATA_BLOCK"]
@@ -53,7 +53,7 @@ def parse_db_file(p: Path | StringIO, nesting_depth_to_skip=1) -> DBParseResult:
53
53
  current_bools: list[str] = []
54
54
  prev_base_name = ""
55
55
  for i in name_types:
56
- name_parts = i.name[nesting_depth_to_skip:]
56
+ name_parts = i.name[prefix_levels_to_skip:]
57
57
  full_name = ".".join(name_parts)
58
58
  base_name = ".".join(name_parts[:-1])
59
59
  if current_bools and (base_name != prev_base_name or i.type != "Bool"):
@@ -26,7 +26,7 @@ BEGIN
26
26
  END_DATA_BLOCK
27
27
  """
28
28
  )
29
- return S7DataBlock.from_definition_file(db_buff, db_number=1200, nesting_depth_to_skip=0)
29
+ return S7DataBlock.from_definition_file(db_buff, db_number=1200, prefix_levels_to_skip=0)
30
30
 
31
31
 
32
32
  def test_db_structure(sample_dtl_db):
@@ -129,9 +129,9 @@ def test_parse_db_from_stringio():
129
129
  assert "PLC_DQ_0" in result.mapping
130
130
 
131
131
 
132
- def test_parse_db_no_nesting_depth_to_skip():
133
- """Test parsing with nesting_depth_to_skip=0 to keep full S7Field names."""
134
- result = parse_db_file(Path("tests/definitions/s7_1200_out.db"), nesting_depth_to_skip=0)
132
+ def test_parse_db_no_prefix_levels_to_skip():
133
+ """Test parsing with prefix_levels_to_skip=0 to keep full S7Field names."""
134
+ result = parse_db_file(Path("tests/definitions/s7_1200_out.db"), prefix_levels_to_skip=0)
135
135
 
136
136
  assert isinstance(result, DBParseResult)
137
137
  assert result.length == 16
@@ -154,9 +154,9 @@ def test_parse_db_no_nesting_depth_to_skip():
154
154
  }
155
155
 
156
156
 
157
- def test_parse_db_with_nesting_depth_to_skip():
158
- """Test parsing with nesting_depth_to_skip=1 to skip top-level UDT name."""
159
- result = parse_db_file(Path("tests/definitions/s7_1200_out.db"), nesting_depth_to_skip=1)
157
+ def test_parse_db_with_prefix_levels_to_skip():
158
+ """Test parsing with prefix_levels_to_skip=1 to skip top-level UDT name."""
159
+ result = parse_db_file(Path("tests/definitions/s7_1200_out.db"), prefix_levels_to_skip=1)
160
160
 
161
161
  assert isinstance(result, DBParseResult)
162
162
  assert result.length == 16
@@ -182,8 +182,8 @@ def test_parse_db_with_nesting_depth_to_skip():
182
182
  def test_parse_db_invalid_input(sample_db_file):
183
183
  """Test that invalid inputs raise appropriate exceptions."""
184
184
  # Test invalid nesting depth
185
- with pytest.raises(ValueError, match="nesting_depth_to_skip must be a non-negative integer"):
186
- parse_db_file(sample_db_file, nesting_depth_to_skip=-1)
185
+ with pytest.raises(ValueError, match="prefix_levels_to_skip must be a non-negative integer"):
186
+ parse_db_file(sample_db_file, prefix_levels_to_skip=-1)
187
187
 
188
188
  # Test invalid input type
189
189
  with pytest.raises(TypeError, match="Input must be a Path or StringIO"):
@@ -218,7 +218,7 @@ wheels = [
218
218
 
219
219
  [[package]]
220
220
  name = "s7datablock"
221
- version = "0.0.1"
221
+ version = "0.0.2"
222
222
  source = { editable = "." }
223
223
  dependencies = [
224
224
  { name = "pyparsing" },
Binary file
File without changes
File without changes
File without changes
File without changes
File without changes