s7datablock 0.0.0a0__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 (46) hide show
  1. s7datablock-0.0.2/PKG-INFO +150 -0
  2. s7datablock-0.0.2/README.md +128 -0
  3. s7datablock-0.0.2/docs/example.png +0 -0
  4. {s7datablock-0.0.0a0 → s7datablock-0.0.2}/examples/basic_usage.py +0 -4
  5. s7datablock-0.0.2/examples/live_monitor.py +52 -0
  6. {s7datablock-0.0.0a0 → s7datablock-0.0.2}/examples/parse_file.py +1 -1
  7. {s7datablock-0.0.0a0 → s7datablock-0.0.2}/pyproject.toml +4 -4
  8. {s7datablock-0.0.0a0 → s7datablock-0.0.2}/src/s7datablock/mapping.py +23 -17
  9. {s7datablock-0.0.0a0 → s7datablock-0.0.2}/src/s7datablock/parser.py +5 -5
  10. {s7datablock-0.0.0a0 → s7datablock-0.0.2}/tests/test_dtl_struct.py +1 -1
  11. {s7datablock-0.0.0a0 → s7datablock-0.0.2}/tests/test_s7_parsing.py +8 -8
  12. {s7datablock-0.0.0a0 → s7datablock-0.0.2}/uv.lock +1 -1
  13. s7datablock-0.0.0a0/PKG-INFO +0 -136
  14. s7datablock-0.0.0a0/README.md +0 -114
  15. s7datablock-0.0.0a0/docs/Makefile +0 -29
  16. s7datablock-0.0.0a0/docs/_static/.gitignore +0 -1
  17. s7datablock-0.0.0a0/docs/authors.md +0 -4
  18. s7datablock-0.0.0a0/docs/changelog.md +0 -4
  19. s7datablock-0.0.0a0/docs/conf.py +0 -299
  20. s7datablock-0.0.0a0/docs/contributing.md +0 -4
  21. s7datablock-0.0.0a0/docs/index.md +0 -39
  22. s7datablock-0.0.0a0/docs/license.md +0 -5
  23. s7datablock-0.0.0a0/docs/readme.md +0 -4
  24. s7datablock-0.0.0a0/docs/requirements.txt +0 -6
  25. {s7datablock-0.0.0a0 → s7datablock-0.0.2}/.coveragerc +0 -0
  26. {s7datablock-0.0.0a0 → s7datablock-0.0.2}/.github/workflows/ci.yml +0 -0
  27. {s7datablock-0.0.0a0 → s7datablock-0.0.2}/.gitignore +0 -0
  28. {s7datablock-0.0.0a0 → s7datablock-0.0.2}/.isort.cfg +0 -0
  29. {s7datablock-0.0.0a0 → s7datablock-0.0.2}/.pre-commit-config.yaml +0 -0
  30. {s7datablock-0.0.0a0 → s7datablock-0.0.2}/.readthedocs.yml +0 -0
  31. {s7datablock-0.0.0a0 → s7datablock-0.0.2}/AUTHORS.md +0 -0
  32. {s7datablock-0.0.0a0 → s7datablock-0.0.2}/LICENSE.txt +0 -0
  33. {s7datablock-0.0.0a0 → s7datablock-0.0.2}/examples/dtl_date.py +0 -0
  34. {s7datablock-0.0.0a0 → s7datablock-0.0.2}/src/s7datablock/__init__.py +0 -0
  35. {s7datablock-0.0.0a0 → s7datablock-0.0.2}/src/s7datablock/constants.py +0 -0
  36. {s7datablock-0.0.0a0 → s7datablock-0.0.2}/src/s7datablock/fields.py +0 -0
  37. {s7datablock-0.0.0a0 → s7datablock-0.0.2}/src/s7datablock/grammar.py +0 -0
  38. {s7datablock-0.0.0a0 → s7datablock-0.0.2}/src/s7datablock/py.typed +0 -0
  39. {s7datablock-0.0.0a0 → s7datablock-0.0.2}/test_buffer_mapping_extended.py +0 -0
  40. {s7datablock-0.0.0a0 → s7datablock-0.0.2}/tests/conftest.py +0 -0
  41. {s7datablock-0.0.0a0 → s7datablock-0.0.2}/tests/definitions/s7_1200_out.db +0 -0
  42. {s7datablock-0.0.0a0 → s7datablock-0.0.2}/tests/definitions/tester.db +0 -0
  43. {s7datablock-0.0.0a0 → s7datablock-0.0.2}/tests/test_buffer_mapping.py +0 -0
  44. {s7datablock-0.0.0a0 → s7datablock-0.0.2}/tests/test_buffer_mapping_extended.py +0 -0
  45. {s7datablock-0.0.0a0 → s7datablock-0.0.2}/tests/test_s7_connector.py +0 -0
  46. {s7datablock-0.0.0a0 → s7datablock-0.0.2}/tests/test_s7_utils.py +0 -0
@@ -0,0 +1,150 @@
1
+ Metadata-Version: 2.4
2
+ Name: s7datablock
3
+ Version: 0.0.2
4
+ Summary: A Python library for interacting with Siemens S7 PLC datablocks
5
+ Project-URL: Homepage, https://github.com/CEAD-group/s7datablock
6
+ Project-URL: Documentation, https://github.com/CEAD-group/s7datablock
7
+ Author-email: Thijs Damsma <thijs@damsma.net>
8
+ License: MIT
9
+ License-File: AUTHORS.md
10
+ License-File: LICENSE.txt
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Programming Language :: Python
13
+ Requires-Python: >=3.11
14
+ Requires-Dist: pyparsing
15
+ Requires-Dist: python-snap7
16
+ Requires-Dist: rich
17
+ Provides-Extra: testing
18
+ Requires-Dist: pytest; extra == 'testing'
19
+ Requires-Dist: pytest-cov; extra == 'testing'
20
+ Requires-Dist: ruff; extra == 'testing'
21
+ Description-Content-Type: text/markdown
22
+
23
+ # S7DataBlock
24
+
25
+ - [S7DataBlock](#s7datablock)
26
+ - [Key Features](#key-features)
27
+ - [Data Transfer](#data-transfer)
28
+ - [Live Monitoring PLC Values](#live-monitoring-plc-values)
29
+ - [Installation](#installation)
30
+ - [Contributing and Issues](#contributing-and-issues)
31
+
32
+ **A Python library for parsing Siemens S7 PLC data blocks, in conjunction with Snap7.**
33
+
34
+ `s7datablock` is a Python utility designed to parse and interpret Siemens S7 PLC data blocks using structured data definitions exported from the TIA Portal. It works seamlessly with the excellent [python-snap7](https://github.com/gijzelaerr/python-snap7) library to enable high-level, dictionary-like access to binary PLC data.
35
+
36
+ Instead of manually mapping byte offsets and types, you can use `.db` definition files exported from TIA Portal to generate a clean, versionable Python representation of your data block structures.
37
+
38
+ ---
39
+
40
+ ## Key Features
41
+
42
+ - Uses exported TIA Portal `*.db` files for accurate structure mapping
43
+ - Read and write entire PLC data blocks with `.GET()` and `.SET()` (or the more pythonic `pull()` and `push()`)
44
+ - Structure and sub-structure access via dot notation
45
+ - Clean terminal output using [Rich](https://github.com/Textualize/rich)
46
+ - Easy integration into polling and monitoring loops
47
+
48
+ ![example.png](https://github.com/CEAD-group/s7datablock/raw/main/docs/example.png)
49
+
50
+ ---
51
+
52
+ ## Data Transfer
53
+
54
+ This library deliberately uses manual .GET() and .SET() calls instead of automatic syncing to prioritize:
55
+ - **Clarity** – Developers control exactly when data is transferred
56
+ - **Performance** – Avoid unnecessary communication overhead
57
+ - **Atomicity** – Batch multiple updates into one write
58
+
59
+ ## Live Monitoring PLC Values
60
+
61
+ You can monitor PLC values by creating a polling loop. Here's an example using Rich for clean terminal output:
62
+
63
+ ```python
64
+ from time import sleep
65
+ from rich.live import Live
66
+ from datetime import datetime
67
+ from io import StringIO
68
+
69
+ from s7datablock.mapping import S7DataBlock
70
+
71
+ # Example in-line definition file contents. Alternatively, you can pass a PAth to a *.db file.
72
+ df_file_contents = StringIO(
73
+ """
74
+ TYPE "my_udt"
75
+ VERSION : 0.1
76
+ STRUCT
77
+ PLC_DQ_0 : Bool;
78
+ PLC_DQ_1 : Bool;
79
+ WHEN : DTL;
80
+ Value1 : Int;
81
+ Value2 : Real;
82
+ END_STRUCT;
83
+ END_TYPE
84
+ DATA_BLOCK "my_udt"
85
+ VERSION : 0.1
86
+ "my_udt"
87
+ BEGIN
88
+ END_DATA_BLOCK
89
+ """
90
+ )
91
+
92
+ db = S7DataBlock.from_definition_file(df_file_contents, db_number=1200)
93
+ print(db) # This will print the structure of the data block as a table
94
+
95
+ print(repr(db)) # Print the raw representation of the data block
96
+ # In a real application, you would create a snap7 client and connect to the PLC
97
+
98
+ # client = snap7.client.Client()
99
+ # client.connect('192.168.0.1', 0, 1)
100
+
101
+ with Live(db.to_table(), refresh_per_second=10) as live:
102
+ while True:
103
+ # In a real application, you would call GET() here
104
+ # db.GET(client)
105
+
106
+ # For demo, we'll just modify some values
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
111
+
112
+ # Update the display with current values
113
+ live.update(db.to_table())
114
+ sleep(0.2)
115
+ ```
116
+
117
+ Running this code should render a live table in your terminal
118
+ ```text
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
+ └───────────────────┴─────────────┴──────────┴─────────────────────┘
137
+ ```
138
+
139
+
140
+
141
+ ## Installation
142
+
143
+ ```bash
144
+ pip install s7datablock
145
+ ```
146
+
147
+
148
+ ## Contributing and Issues
149
+
150
+ The library is in its early stages, and contributions are welcome. Feel free to submit a pull request or open an issue on GitHub.
@@ -0,0 +1,128 @@
1
+ # S7DataBlock
2
+
3
+ - [S7DataBlock](#s7datablock)
4
+ - [Key Features](#key-features)
5
+ - [Data Transfer](#data-transfer)
6
+ - [Live Monitoring PLC Values](#live-monitoring-plc-values)
7
+ - [Installation](#installation)
8
+ - [Contributing and Issues](#contributing-and-issues)
9
+
10
+ **A Python library for parsing Siemens S7 PLC data blocks, in conjunction with Snap7.**
11
+
12
+ `s7datablock` is a Python utility designed to parse and interpret Siemens S7 PLC data blocks using structured data definitions exported from the TIA Portal. It works seamlessly with the excellent [python-snap7](https://github.com/gijzelaerr/python-snap7) library to enable high-level, dictionary-like access to binary PLC data.
13
+
14
+ Instead of manually mapping byte offsets and types, you can use `.db` definition files exported from TIA Portal to generate a clean, versionable Python representation of your data block structures.
15
+
16
+ ---
17
+
18
+ ## Key Features
19
+
20
+ - Uses exported TIA Portal `*.db` files for accurate structure mapping
21
+ - Read and write entire PLC data blocks with `.GET()` and `.SET()` (or the more pythonic `pull()` and `push()`)
22
+ - Structure and sub-structure access via dot notation
23
+ - Clean terminal output using [Rich](https://github.com/Textualize/rich)
24
+ - Easy integration into polling and monitoring loops
25
+
26
+ ![example.png](https://github.com/CEAD-group/s7datablock/raw/main/docs/example.png)
27
+
28
+ ---
29
+
30
+ ## Data Transfer
31
+
32
+ This library deliberately uses manual .GET() and .SET() calls instead of automatic syncing to prioritize:
33
+ - **Clarity** – Developers control exactly when data is transferred
34
+ - **Performance** – Avoid unnecessary communication overhead
35
+ - **Atomicity** – Batch multiple updates into one write
36
+
37
+ ## Live Monitoring PLC Values
38
+
39
+ You can monitor PLC values by creating a polling loop. Here's an example using Rich for clean terminal output:
40
+
41
+ ```python
42
+ from time import sleep
43
+ from rich.live import Live
44
+ from datetime import datetime
45
+ from io import StringIO
46
+
47
+ from s7datablock.mapping import S7DataBlock
48
+
49
+ # Example in-line definition file contents. Alternatively, you can pass a PAth to a *.db file.
50
+ df_file_contents = StringIO(
51
+ """
52
+ TYPE "my_udt"
53
+ VERSION : 0.1
54
+ STRUCT
55
+ PLC_DQ_0 : Bool;
56
+ PLC_DQ_1 : Bool;
57
+ WHEN : DTL;
58
+ Value1 : Int;
59
+ Value2 : Real;
60
+ END_STRUCT;
61
+ END_TYPE
62
+ DATA_BLOCK "my_udt"
63
+ VERSION : 0.1
64
+ "my_udt"
65
+ BEGIN
66
+ END_DATA_BLOCK
67
+ """
68
+ )
69
+
70
+ db = S7DataBlock.from_definition_file(df_file_contents, db_number=1200)
71
+ print(db) # This will print the structure of the data block as a table
72
+
73
+ print(repr(db)) # Print the raw representation of the data block
74
+ # In a real application, you would create a snap7 client and connect to the PLC
75
+
76
+ # client = snap7.client.Client()
77
+ # client.connect('192.168.0.1', 0, 1)
78
+
79
+ with Live(db.to_table(), refresh_per_second=10) as live:
80
+ while True:
81
+ # In a real application, you would call GET() here
82
+ # db.GET(client)
83
+
84
+ # For demo, we'll just modify some values
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
89
+
90
+ # Update the display with current values
91
+ live.update(db.to_table())
92
+ sleep(0.2)
93
+ ```
94
+
95
+ Running this code should render a live table in your terminal
96
+ ```text
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
+ └───────────────────┴─────────────┴──────────┴─────────────────────┘
115
+ ```
116
+
117
+
118
+
119
+ ## Installation
120
+
121
+ ```bash
122
+ pip install s7datablock
123
+ ```
124
+
125
+
126
+ ## Contributing and Issues
127
+
128
+ The library is in its early stages, and contributions are welcome. Feel free to submit a pull request or open an issue on GitHub.
Binary file
@@ -24,10 +24,6 @@ def main():
24
24
  buffered_vars["setpointHz2"] = 23.5
25
25
  print("Buffer after setting setpointHz2 (hex):", " ".join(f"{b:02X}" for b in buffered_vars.buffer))
26
26
 
27
- # Display the full structure with values
28
- print("\nFull structure:")
29
- print(buffered_vars)
30
-
31
27
 
32
28
  if __name__ == "__main__":
33
29
  main()
@@ -0,0 +1,52 @@
1
+ from datetime import datetime
2
+ from io import StringIO
3
+ from time import sleep
4
+
5
+ from rich.live import Live
6
+
7
+ from s7datablock.mapping import S7DataBlock
8
+
9
+ # Example in-line definition file contents. Alternatively, you can pass a PAth to a *.db file.
10
+ df_file_contents = StringIO(
11
+ """
12
+ TYPE "my_udt"
13
+ VERSION : 0.1
14
+ STRUCT
15
+ PLC_DQ_0 : Bool;
16
+ PLC_DQ_1 : Bool;
17
+ WHEN : DTL;
18
+ Value1 : Int;
19
+ Value2 : Real;
20
+ END_STRUCT;
21
+ END_TYPE
22
+ DATA_BLOCK "my_udt"
23
+ VERSION : 0.1
24
+ "my_udt"
25
+ BEGIN
26
+ END_DATA_BLOCK
27
+ """
28
+ )
29
+
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
32
+
33
+ print(repr(db)) # Print the raw representation of the data block
34
+ # In a real application, you would create a snap7 client and connect to the PLC
35
+
36
+ # client = snap7.client.Client()
37
+ # client.connect('192.168.0.1', 0, 1)
38
+
39
+ with Live(db.to_table(), refresh_per_second=10) as live:
40
+ while True:
41
+ # In a real application, you would call GET() here
42
+ # db.GET(client)
43
+
44
+ # For demo, we'll just modify some values
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
49
+
50
+ # Update the display with current values
51
+ live.update(db.to_table())
52
+ sleep(0.2)
@@ -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,7 +1,7 @@
1
1
  [project]
2
2
  name = "s7datablock"
3
- version = "0.0.0-alpha"
4
- description = "A Python library interacting with Siemens S7 PLC datablocks"
3
+ version = "0.0.2"
4
+ description = "A Python library for interacting with Siemens S7 PLC datablocks"
5
5
  readme = "README.md"
6
6
  authors = [
7
7
  { name = "Thijs Damsma", email = "thijs@damsma.net" }
@@ -36,8 +36,8 @@ line-length = 120
36
36
 
37
37
 
38
38
  [project.urls]
39
- Homepage = "https://github.com/pyscaffold/pyscaffold/"
40
- Documentation = "https://pyscaffold.org/"
39
+ Homepage = "https://github.com/CEAD-group/s7datablock"
40
+ Documentation = "https://github.com/CEAD-group/s7datablock"
41
41
 
42
42
  [project.optional-dependencies]
43
43
  testing = [
@@ -68,6 +68,21 @@ class BufferMapping(MutableMapping[str, ElementalType]):
68
68
  Returns a formatted string showing field names, data types, offsets, and current values
69
69
  with proper hierarchical indentation.
70
70
  """
71
+ total_size = self.total_size()
72
+ table = self.to_table()
73
+
74
+ console = Console(record=True, width=120)
75
+ with console.capture() as capture:
76
+ console.print() # Empty line before table
77
+ for _ in range(17):
78
+ console.print(" ", end="")
79
+ console.print(table)
80
+ console.print(f" Total size: {total_size} bytes")
81
+ console.print() # Empty line after
82
+
83
+ return capture.get()
84
+
85
+ def to_table(self) -> Table:
71
86
  table = Table(
72
87
  show_edge=True,
73
88
  show_header=True,
@@ -112,22 +127,12 @@ class BufferMapping(MutableMapping[str, ElementalType]):
112
127
  table.add_row(*field.get_table_row(name=name, indent_level=indent_level, buffer=self.buffer))
113
128
  prev_sub = sub
114
129
 
115
- # Calculate total size
116
- total_size = max(
117
- field.offset[0] + 2 if isinstance(field.offset, tuple) else field.offset + field.struct_width
118
- for field in self.mapping.values()
119
- )
130
+ return table
120
131
 
121
- console = Console(record=True, width=120)
122
- with console.capture() as capture:
123
- console.print() # Empty line before table
124
- for _ in range(17):
125
- console.print(" ", end="")
126
- console.print(table)
127
- console.print(f" Total size: {total_size} bytes")
128
- console.print() # Empty line after
129
-
130
- return capture.get()
132
+ def total_size(self) -> int:
133
+ """Calculate the total size of the buffer based on the maximum offset of all fields."""
134
+ total_size = max(field.offset + field.struct_width for field in self.mapping.values())
135
+ return total_size
131
136
 
132
137
  def keys(self):
133
138
  """Returns a view of the field names in the mapping."""
@@ -167,17 +172,18 @@ class S7DataBlock(BufferMapping):
167
172
  self.db_size = db_size
168
173
 
169
174
  @classmethod
170
- 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":
171
176
  """Create an S7DataBlock from a TIA Portal export file.
172
177
 
173
178
  Args:
174
179
  path: Path to the TIA Portal export file
175
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.
176
182
 
177
183
  Returns:
178
184
  S7DataBlock: The created datablock
179
185
  """
180
- 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)
181
187
  return cls(buffer=bytearray(size), mapping=mapping, db_number=db_number, db_size=size)
182
188
 
183
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.0a0"
221
+ version = "0.0.2"
222
222
  source = { editable = "." }
223
223
  dependencies = [
224
224
  { name = "pyparsing" },
@@ -1,136 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: s7datablock
3
- Version: 0.0.0a0
4
- Summary: A Python library interacting with Siemens S7 PLC datablocks
5
- Project-URL: Homepage, https://github.com/pyscaffold/pyscaffold/
6
- Project-URL: Documentation, https://pyscaffold.org/
7
- Author-email: Thijs Damsma <thijs@damsma.net>
8
- License: MIT
9
- License-File: AUTHORS.md
10
- License-File: LICENSE.txt
11
- Classifier: Development Status :: 4 - Beta
12
- Classifier: Programming Language :: Python
13
- Requires-Python: >=3.11
14
- Requires-Dist: pyparsing
15
- Requires-Dist: python-snap7
16
- Requires-Dist: rich
17
- Provides-Extra: testing
18
- Requires-Dist: pytest; extra == 'testing'
19
- Requires-Dist: pytest-cov; extra == 'testing'
20
- Requires-Dist: ruff; extra == 'testing'
21
- Description-Content-Type: text/markdown
22
-
23
- # S7DataBlock
24
-
25
- - [S7DataBlock](#s7datablock)
26
- - [Introduction](#introduction)
27
- - [Installation](#installation)
28
- - [Parsing Data Blocks](#parsing-data-blocks)
29
- - [Contributing and Issues](#contributing-and-issues)
30
-
31
- ## Introduction
32
-
33
- > A Python library for parsing Siemens S7 PLC data blocks, in conjunction with Snap7.
34
-
35
- `s7datablock` is a Python library designed to parse and interpret Siemens S7 PLC data blocks. It works in conjunction with the [python-snap7](https://github.com/gijzelaerr/python-snap7) library, providing a set of tools and utilities to read and write the bytes in a PLC datablock as structured data, using the DB definitions as exported from a TIA Portal project. This makes it easier for developers and engineers to work with Siemens S7 PLCs in their Python applications.
36
-
37
- Instead of manually mapping bytes, the dataformat defined in Tia Portal can be used to generate the appropriate Python mapping. The configuration file can be kept separate from the code, making it easier to track versions and support complicated data structures.
38
-
39
- ## Installation
40
-
41
- ```bash
42
- pip install s7datablock
43
- ```
44
-
45
- ### Parsing Data Blocks
46
-
47
- In this example, we will demonstrate how to use the `s7datablock` library to parse and interpret Siemens S7 PLC data blocks.
48
-
49
- First, we define a s7_1200_out user-defined type (UDT) and a data block in Structured Control Language (SCL). The UDT, named "s7_1200_out_udt", consists of five boolean variables and one integer variable. The data block, named "s7_1200_out", uses this UDT. This file was defined in and exported from Tia Portal, using the `generate source from blocks, including all dependent blocks` option.
50
-
51
- ```scl
52
- # s7_1200_out.db
53
- TYPE "s7_1200_out_udt"
54
- VERSION : 0.1
55
- STRUCT
56
- PLC_DQ_0 : Bool; # Boolean variable
57
- PLC_DQ_1 : Bool; # Boolean variable
58
- PLC_DQ_2 : Bool; # Boolean variable
59
- PLC_DQ_3 : Bool; # Boolean variable
60
- PLC_DQ_4 : Bool; # Boolean variable
61
- SB_AQ_0 : Int; # Integer variable
62
- END_STRUCT;
63
- END_TYPE
64
-
65
- DATA_BLOCK "s7_1200_out"
66
- { S7_Optimized_Access := 'FALSE' }
67
- VERSION : 0.1
68
- NON_RETAIN
69
- "s7_1200_out_udt"
70
-
71
- BEGIN
72
-
73
- END_DATA_BLOCK
74
- ```
75
-
76
- Next, we use the `S7DataBlock` class from the `s7datablock` library to parse the data block definition file. We then display the parsed data block and its initial buffer state. Finally, we modify one of the boolean variables in the data block and display the updated buffer state.
77
-
78
- ```python
79
- # Import necessary modules
80
- from s7datablock.mapping import S7DataBlock
81
- from pathlib import Path
82
-
83
- # Parse the data block definition file
84
- db1200 = S7DataBlock.from_definition_file(
85
- Path("tests/definitions/s7_1200_out.db"),
86
- db_number=1200
87
- )
88
-
89
- # The printing the db1200 datasrutcure produces a nicely formatted output
90
- print(db1200)
91
- ```
92
-
93
- ```raw
94
- Data Block Structure
95
- ┏━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━┓
96
- ┃ Name ┃ Data type ┃ Offset ┃ Value ┃
97
- ┡━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━┩
98
- │ PLC_DQ_0 │ Bool │ 0.0 │ False │
99
- │ PLC_DQ_1 │ Bool │ 0.1 │ False │
100
- │ PLC_DQ_2 │ Bool │ 0.2 │ False │
101
- │ PLC_DQ_3 │ Bool │ 0.3 │ False │
102
- │ PLC_DQ_4 │ Bool │ 0.4 │ False │
103
- │ SB_AQ_0 │ Int │ 2.0 │ 0 │
104
- │ TIMEFIELD │ DTL │ 4.0 │ None │
105
- │ YEAR │ UInt │ 4.0 │ 0 │
106
- │ MONTH │ USInt │ 6.0 │ 0 │
107
- │ DAY │ USInt │ 7.0 │ 0 │
108
- │ WEEKDAY │ USInt │ 8.0 │ 0 │
109
- │ HOUR │ USInt │ 9.0 │ 0 │
110
- │ MINUTE │ USInt │ 10.0 │ 0 │
111
- │ SECOND │ USInt │ 11.0 │ 0 │
112
- │ NANOSECOND │ UDInt │ 12.0 │ 0 │
113
- └──────────────────┴─────────────┴──────────┴─────────────┘
114
- Total size: 16 bytes
115
- ```
116
-
117
- ```python
118
- # db1200 maps the data like a dictionary but the hood it stores the data in a continuous buffer,
119
- # using the same format and byte ordering as the PLC
120
- # Initially the buffer is only zeros
121
- print(db1200.buffer)
122
- # Output: bytearray(b'\x00\x00\x00\x00')
123
-
124
- # Modify one of the boolean variables
125
- db1200["PLC_DQ_3"] = True
126
-
127
- # Now one bit has changed
128
- print(db1200.buffer)
129
- # Output: bytearray(b'\x08\x00\x00\x00')
130
- ```
131
-
132
-
133
-
134
- ## Contributing and Issues
135
-
136
- The library is in its early stages, and contributions are welcome. Feel free to submit a pull request or open an issue on GitHub.
@@ -1,114 +0,0 @@
1
- # S7DataBlock
2
-
3
- - [S7DataBlock](#s7datablock)
4
- - [Introduction](#introduction)
5
- - [Installation](#installation)
6
- - [Parsing Data Blocks](#parsing-data-blocks)
7
- - [Contributing and Issues](#contributing-and-issues)
8
-
9
- ## Introduction
10
-
11
- > A Python library for parsing Siemens S7 PLC data blocks, in conjunction with Snap7.
12
-
13
- `s7datablock` is a Python library designed to parse and interpret Siemens S7 PLC data blocks. It works in conjunction with the [python-snap7](https://github.com/gijzelaerr/python-snap7) library, providing a set of tools and utilities to read and write the bytes in a PLC datablock as structured data, using the DB definitions as exported from a TIA Portal project. This makes it easier for developers and engineers to work with Siemens S7 PLCs in their Python applications.
14
-
15
- Instead of manually mapping bytes, the dataformat defined in Tia Portal can be used to generate the appropriate Python mapping. The configuration file can be kept separate from the code, making it easier to track versions and support complicated data structures.
16
-
17
- ## Installation
18
-
19
- ```bash
20
- pip install s7datablock
21
- ```
22
-
23
- ### Parsing Data Blocks
24
-
25
- In this example, we will demonstrate how to use the `s7datablock` library to parse and interpret Siemens S7 PLC data blocks.
26
-
27
- First, we define a s7_1200_out user-defined type (UDT) and a data block in Structured Control Language (SCL). The UDT, named "s7_1200_out_udt", consists of five boolean variables and one integer variable. The data block, named "s7_1200_out", uses this UDT. This file was defined in and exported from Tia Portal, using the `generate source from blocks, including all dependent blocks` option.
28
-
29
- ```scl
30
- # s7_1200_out.db
31
- TYPE "s7_1200_out_udt"
32
- VERSION : 0.1
33
- STRUCT
34
- PLC_DQ_0 : Bool; # Boolean variable
35
- PLC_DQ_1 : Bool; # Boolean variable
36
- PLC_DQ_2 : Bool; # Boolean variable
37
- PLC_DQ_3 : Bool; # Boolean variable
38
- PLC_DQ_4 : Bool; # Boolean variable
39
- SB_AQ_0 : Int; # Integer variable
40
- END_STRUCT;
41
- END_TYPE
42
-
43
- DATA_BLOCK "s7_1200_out"
44
- { S7_Optimized_Access := 'FALSE' }
45
- VERSION : 0.1
46
- NON_RETAIN
47
- "s7_1200_out_udt"
48
-
49
- BEGIN
50
-
51
- END_DATA_BLOCK
52
- ```
53
-
54
- Next, we use the `S7DataBlock` class from the `s7datablock` library to parse the data block definition file. We then display the parsed data block and its initial buffer state. Finally, we modify one of the boolean variables in the data block and display the updated buffer state.
55
-
56
- ```python
57
- # Import necessary modules
58
- from s7datablock.mapping import S7DataBlock
59
- from pathlib import Path
60
-
61
- # Parse the data block definition file
62
- db1200 = S7DataBlock.from_definition_file(
63
- Path("tests/definitions/s7_1200_out.db"),
64
- db_number=1200
65
- )
66
-
67
- # The printing the db1200 datasrutcure produces a nicely formatted output
68
- print(db1200)
69
- ```
70
-
71
- ```raw
72
- Data Block Structure
73
- ┏━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━┓
74
- ┃ Name ┃ Data type ┃ Offset ┃ Value ┃
75
- ┡━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━┩
76
- │ PLC_DQ_0 │ Bool │ 0.0 │ False │
77
- │ PLC_DQ_1 │ Bool │ 0.1 │ False │
78
- │ PLC_DQ_2 │ Bool │ 0.2 │ False │
79
- │ PLC_DQ_3 │ Bool │ 0.3 │ False │
80
- │ PLC_DQ_4 │ Bool │ 0.4 │ False │
81
- │ SB_AQ_0 │ Int │ 2.0 │ 0 │
82
- │ TIMEFIELD │ DTL │ 4.0 │ None │
83
- │ YEAR │ UInt │ 4.0 │ 0 │
84
- │ MONTH │ USInt │ 6.0 │ 0 │
85
- │ DAY │ USInt │ 7.0 │ 0 │
86
- │ WEEKDAY │ USInt │ 8.0 │ 0 │
87
- │ HOUR │ USInt │ 9.0 │ 0 │
88
- │ MINUTE │ USInt │ 10.0 │ 0 │
89
- │ SECOND │ USInt │ 11.0 │ 0 │
90
- │ NANOSECOND │ UDInt │ 12.0 │ 0 │
91
- └──────────────────┴─────────────┴──────────┴─────────────┘
92
- Total size: 16 bytes
93
- ```
94
-
95
- ```python
96
- # db1200 maps the data like a dictionary but the hood it stores the data in a continuous buffer,
97
- # using the same format and byte ordering as the PLC
98
- # Initially the buffer is only zeros
99
- print(db1200.buffer)
100
- # Output: bytearray(b'\x00\x00\x00\x00')
101
-
102
- # Modify one of the boolean variables
103
- db1200["PLC_DQ_3"] = True
104
-
105
- # Now one bit has changed
106
- print(db1200.buffer)
107
- # Output: bytearray(b'\x08\x00\x00\x00')
108
- ```
109
-
110
-
111
-
112
- ## Contributing and Issues
113
-
114
- The library is in its early stages, and contributions are welcome. Feel free to submit a pull request or open an issue on GitHub.
@@ -1,29 +0,0 @@
1
- # Makefile for Sphinx documentation
2
- #
3
-
4
- # You can set these variables from the command line, and also
5
- # from the environment for the first two.
6
- SPHINXOPTS ?=
7
- SPHINXBUILD ?= sphinx-build
8
- SOURCEDIR = .
9
- BUILDDIR = _build
10
- AUTODOCDIR = api
11
-
12
- # User-friendly check for sphinx-build
13
- ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $?), 1)
14
- $(error "The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from https://sphinx-doc.org/")
15
- endif
16
-
17
- .PHONY: help clean Makefile
18
-
19
- # Put it first so that "make" without argument is like "make help".
20
- help:
21
- @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
22
-
23
- clean:
24
- rm -rf $(BUILDDIR)/* $(AUTODOCDIR)
25
-
26
- # Catch-all target: route all unknown targets to Sphinx using the new
27
- # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
28
- %: Makefile
29
- @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
@@ -1 +0,0 @@
1
- # Empty directory
@@ -1,4 +0,0 @@
1
- ```{include} ../AUTHORS.md
2
- :relative-docs: docs/
3
- :relative-images:
4
- ```
@@ -1,4 +0,0 @@
1
- ```{include} ../CHANGELOG.md
2
- :relative-docs: docs/
3
- :relative-images:
4
- ```
@@ -1,299 +0,0 @@
1
- # This file is execfile()d with the current directory set to its containing dir.
2
- #
3
- # This file only contains a selection of the most common options. For a full
4
- # list see the documentation:
5
- # https://www.sphinx-doc.org/en/master/usage/configuration.html
6
- #
7
- # All configuration values have a default; values that are commented out
8
- # serve to show the default.
9
-
10
- import os
11
- import sys
12
- import shutil
13
-
14
- # -- Path setup --------------------------------------------------------------
15
-
16
- __location__ = os.path.dirname(__file__)
17
-
18
- # If extensions (or modules to document with autodoc) are in another directory,
19
- # add these directories to sys.path here. If the directory is relative to the
20
- # documentation root, use os.path.abspath to make it absolute, like shown here.
21
- sys.path.insert(0, os.path.join(__location__, "../src"))
22
-
23
- # -- Run sphinx-apidoc -------------------------------------------------------
24
- # This hack is necessary since RTD does not issue `sphinx-apidoc` before running
25
- # `sphinx-build -b html . _build/html`. See Issue:
26
- # https://github.com/readthedocs/readthedocs.org/issues/1139
27
- # DON'T FORGET: Check the box "Install your project inside a virtualenv using
28
- # setup.py install" in the RTD Advanced Settings.
29
- # Additionally it helps us to avoid running apidoc manually
30
-
31
- try: # for Sphinx >= 1.7
32
- from sphinx.ext import apidoc
33
- except ImportError:
34
- from sphinx import apidoc
35
-
36
- output_dir = os.path.join(__location__, "api")
37
- module_dir = os.path.join(__location__, "../src/s7datablock")
38
- try:
39
- shutil.rmtree(output_dir)
40
- except FileNotFoundError:
41
- pass
42
-
43
- try:
44
- import sphinx
45
-
46
- cmd_line = f"sphinx-apidoc --implicit-namespaces -f -o {output_dir} {module_dir}"
47
-
48
- args = cmd_line.split(" ")
49
- if tuple(sphinx.__version__.split(".")) >= ("1", "7"):
50
- # This is a rudimentary parse_version to avoid external dependencies
51
- args = args[1:]
52
-
53
- apidoc.main(args)
54
- except Exception as e:
55
- print("Running `sphinx-apidoc` failed!\n{}".format(e))
56
-
57
- # -- General configuration ---------------------------------------------------
58
-
59
- # If your documentation needs a minimal Sphinx version, state it here.
60
- # needs_sphinx = '1.0'
61
-
62
- # Add any Sphinx extension module names here, as strings. They can be extensions
63
- # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
64
- extensions = [
65
- "sphinx.ext.autodoc",
66
- "sphinx.ext.intersphinx",
67
- "sphinx.ext.todo",
68
- "sphinx.ext.autosummary",
69
- "sphinx.ext.viewcode",
70
- "sphinx.ext.coverage",
71
- "sphinx.ext.doctest",
72
- "sphinx.ext.ifconfig",
73
- "sphinx.ext.mathjax",
74
- "sphinx.ext.napoleon",
75
- ]
76
-
77
- # Add any paths that contain templates here, relative to this directory.
78
- templates_path = ["_templates"]
79
-
80
-
81
- # Enable markdown
82
- extensions.append("myst_parser")
83
-
84
- # Configure MyST-Parser
85
- myst_enable_extensions = [
86
- "amsmath",
87
- "colon_fence",
88
- "deflist",
89
- "dollarmath",
90
- "html_image",
91
- "linkify",
92
- "replacements",
93
- "smartquotes",
94
- "substitution",
95
- "tasklist",
96
- ]
97
-
98
- # The suffix of source filenames.
99
- source_suffix = [".rst", ".md"]
100
-
101
- # The encoding of source files.
102
- # source_encoding = 'utf-8-sig'
103
-
104
- # The master toctree document.
105
- master_doc = "index"
106
-
107
- # General information about the project.
108
- project = "s7datablock"
109
- copyright = "2023, Thijs Damsma"
110
-
111
- # The version info for the project you're documenting, acts as replacement for
112
- # |version| and |release|, also used in various other places throughout the
113
- # built documents.
114
- #
115
- # version: The short X.Y version.
116
- # release: The full version, including alpha/beta/rc tags.
117
- # If you don’t need the separation provided between version and release,
118
- # just set them both to the same value.
119
- try:
120
- from s7datablock import __version__ as version
121
- except ImportError:
122
- version = ""
123
-
124
- if not version or version.lower() == "unknown":
125
- version = os.getenv("READTHEDOCS_VERSION", "unknown") # automatically set by RTD
126
-
127
- release = version
128
-
129
- # The language for content autogenerated by Sphinx. Refer to documentation
130
- # for a list of supported languages.
131
- # language = None
132
-
133
- # There are two options for replacing |today|: either, you set today to some
134
- # non-false value, then it is used:
135
- # today = ''
136
- # Else, today_fmt is used as the format for a strftime call.
137
- # today_fmt = '%B %d, %Y'
138
-
139
- # List of patterns, relative to source directory, that match files and
140
- # directories to ignore when looking for source files.
141
- exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", ".venv"]
142
-
143
- # The reST default role (used for this markup: `text`) to use for all documents.
144
- # default_role = None
145
-
146
- # If true, '()' will be appended to :func: etc. cross-reference text.
147
- # add_function_parentheses = True
148
-
149
- # If true, the current module name will be prepended to all description
150
- # unit titles (such as .. function::).
151
- # add_module_names = True
152
-
153
- # If true, sectionauthor and moduleauthor directives will be shown in the
154
- # output. They are ignored by default.
155
- # show_authors = False
156
-
157
- # The name of the Pygments (syntax highlighting) style to use.
158
- pygments_style = "sphinx"
159
-
160
- # A list of ignored prefixes for module index sorting.
161
- # modindex_common_prefix = []
162
-
163
- # If true, keep warnings as "system message" paragraphs in the built documents.
164
- # keep_warnings = False
165
-
166
- # If this is True, todo emits a warning for each TODO entries. The default is False.
167
- todo_emit_warnings = True
168
-
169
-
170
- # -- Options for HTML output -------------------------------------------------
171
-
172
- # The theme to use for HTML and HTML Help pages. See the documentation for
173
- # a list of builtin themes.
174
- html_theme = "alabaster"
175
-
176
- # Theme options are theme-specific and customize the look and feel of a theme
177
- # further. For a list of options available for each theme, see the
178
- # documentation.
179
- html_theme_options = {"sidebar_width": "300px", "page_width": "1200px"}
180
-
181
- # Add any paths that contain custom themes here, relative to this directory.
182
- # html_theme_path = []
183
-
184
- # The name for this set of Sphinx documents. If None, it defaults to
185
- # "<project> v<release> documentation".
186
- # html_title = None
187
-
188
- # A shorter title for the navigation bar. Default is the same as html_title.
189
- # html_short_title = None
190
-
191
- # The name of an image file (relative to this directory) to place at the top
192
- # of the sidebar.
193
- # html_logo = ""
194
-
195
- # The name of an image file (within the static path) to use as favicon of the
196
- # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
197
- # pixels large.
198
- # html_favicon = None
199
-
200
- # Add any paths that contain custom static files (such as style sheets) here,
201
- # relative to this directory. They are copied after the builtin static files,
202
- # so a file named "default.css" will overwrite the builtin "default.css".
203
- html_static_path = ["_static"]
204
-
205
- # If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
206
- # using the given strftime format.
207
- # html_last_updated_fmt = '%b %d, %Y'
208
-
209
- # If true, SmartyPants will be used to convert quotes and dashes to
210
- # typographically correct entities.
211
- # html_use_smartypants = True
212
-
213
- # Custom sidebar templates, maps document names to template names.
214
- # html_sidebars = {}
215
-
216
- # Additional templates that should be rendered to pages, maps page names to
217
- # template names.
218
- # html_additional_pages = {}
219
-
220
- # If false, no module index is generated.
221
- # html_domain_indices = True
222
-
223
- # If false, no index is generated.
224
- # html_use_index = True
225
-
226
- # If true, the index is split into individual pages for each letter.
227
- # html_split_index = False
228
-
229
- # If true, links to the reST sources are added to the pages.
230
- # html_show_sourcelink = True
231
-
232
- # If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
233
- # html_show_sphinx = True
234
-
235
- # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
236
- # html_show_copyright = True
237
-
238
- # If true, an OpenSearch description file will be output, and all pages will
239
- # contain a <link> tag referring to it. The value of this option must be the
240
- # base URL from which the finished HTML is served.
241
- # html_use_opensearch = ''
242
-
243
- # This is the file name suffix for HTML files (e.g. ".xhtml").
244
- # html_file_suffix = None
245
-
246
- # Output file base name for HTML help builder.
247
- htmlhelp_basename = "s7datablock-doc"
248
-
249
-
250
- # -- Options for LaTeX output ------------------------------------------------
251
-
252
- latex_elements = {
253
- # The paper size ("letterpaper" or "a4paper").
254
- # "papersize": "letterpaper",
255
- # The font size ("10pt", "11pt" or "12pt").
256
- # "pointsize": "10pt",
257
- # Additional stuff for the LaTeX preamble.
258
- # "preamble": "",
259
- }
260
-
261
- # Grouping the document tree into LaTeX files. List of tuples
262
- # (source start file, target name, title, author, documentclass [howto/manual]).
263
- latex_documents = [("index", "user_guide.tex", "s7datablock Documentation", "Thijs Damsma", "manual")]
264
-
265
- # The name of an image file (relative to this directory) to place at the top of
266
- # the title page.
267
- # latex_logo = ""
268
-
269
- # For "manual" documents, if this is true, then toplevel headings are parts,
270
- # not chapters.
271
- # latex_use_parts = False
272
-
273
- # If true, show page references after internal links.
274
- # latex_show_pagerefs = False
275
-
276
- # If true, show URL addresses after external links.
277
- # latex_show_urls = False
278
-
279
- # Documents to append as an appendix to all manuals.
280
- # latex_appendices = []
281
-
282
- # If false, no module index is generated.
283
- # latex_domain_indices = True
284
-
285
- # -- External mapping --------------------------------------------------------
286
- python_version = ".".join(map(str, sys.version_info[0:2]))
287
- intersphinx_mapping = {
288
- "sphinx": ("https://www.sphinx-doc.org/en/master", None),
289
- "python": ("https://docs.python.org/" + python_version, None),
290
- "matplotlib": ("https://matplotlib.org", None),
291
- "numpy": ("https://numpy.org/doc/stable", None),
292
- "sklearn": ("https://scikit-learn.org/stable", None),
293
- "pandas": ("https://pandas.pydata.org/pandas-docs/stable", None),
294
- "scipy": ("https://docs.scipy.org/doc/scipy/reference", None),
295
- "setuptools": ("https://setuptools.pypa.io/en/stable/", None),
296
- "pyscaffold": ("https://pyscaffold.org/en/stable", None),
297
- }
298
-
299
- print(f"loading configurations for {project} {version} ...", file=sys.stderr)
@@ -1,4 +0,0 @@
1
- ```{include} ../CONTRIBUTING.md
2
- :relative-docs: docs/
3
- :relative-images:
4
- ```
@@ -1,39 +0,0 @@
1
- # s7datablock
2
-
3
- Add a short description here!
4
-
5
-
6
- ## Note
7
-
8
- > This is the main page of your project's [Sphinx] documentation. It is
9
- > formatted in [Markdown]. Add additional pages by creating md-files in
10
- > `docs` or rst-files (formatted in [reStructuredText]) and adding links to
11
- > them in the `Contents` section below.
12
- >
13
- > Please check [Sphinx] and [MyST] for more information
14
- > about how to document your project and how to configure your preferences.
15
-
16
-
17
- ## Contents
18
-
19
- ```{toctree}
20
- :maxdepth: 2
21
-
22
- Overview <readme>
23
- Contributions & Help <contributing>
24
- License <license>
25
- Authors <authors>
26
- Changelog <changelog>
27
- Module Reference <api/modules>
28
- ```
29
-
30
- ## Indices and tables
31
-
32
- * {ref}`genindex`
33
- * {ref}`modindex`
34
- * {ref}`search`
35
-
36
- [Sphinx]: http://www.sphinx-doc.org/
37
- [Markdown]: https://daringfireball.net/projects/markdown/
38
- [reStructuredText]: http://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html
39
- [MyST]: https://myst-parser.readthedocs.io/en/latest/
@@ -1,5 +0,0 @@
1
- # License
2
-
3
- ```{literalinclude} ../LICENSE.txt
4
- :language: text
5
- ```
@@ -1,4 +0,0 @@
1
- ```{include} ../README.md
2
- :relative-docs: docs/
3
- :relative-images:
4
- ```
@@ -1,6 +0,0 @@
1
- # Requirements file for ReadTheDocs, check .readthedocs.yml.
2
- # To build the module reference correctly, make sure every external package
3
- # under `install_requires` in `setup.cfg` is also listed here!
4
- # sphinx_rtd_theme
5
- myst-parser[linkify]
6
- sphinx>=3.2.1
File without changes
File without changes
File without changes
File without changes
File without changes