udsxml2tex 0.1.0__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.
- udsxml2tex-0.1.0/LICENSE +21 -0
- udsxml2tex-0.1.0/PKG-INFO +147 -0
- udsxml2tex-0.1.0/README.md +117 -0
- udsxml2tex-0.1.0/pyproject.toml +54 -0
- udsxml2tex-0.1.0/setup.cfg +4 -0
- udsxml2tex-0.1.0/src/udsxml2tex/__init__.py +33 -0
- udsxml2tex-0.1.0/src/udsxml2tex/__main__.py +7 -0
- udsxml2tex-0.1.0/src/udsxml2tex/cli.py +126 -0
- udsxml2tex-0.1.0/src/udsxml2tex/generator.py +165 -0
- udsxml2tex-0.1.0/src/udsxml2tex/models.py +235 -0
- udsxml2tex-0.1.0/src/udsxml2tex/parser.py +706 -0
- udsxml2tex-0.1.0/src/udsxml2tex/templates/uds_spec.tex.j2 +354 -0
- udsxml2tex-0.1.0/src/udsxml2tex.egg-info/PKG-INFO +147 -0
- udsxml2tex-0.1.0/src/udsxml2tex.egg-info/SOURCES.txt +17 -0
- udsxml2tex-0.1.0/src/udsxml2tex.egg-info/dependency_links.txt +1 -0
- udsxml2tex-0.1.0/src/udsxml2tex.egg-info/entry_points.txt +2 -0
- udsxml2tex-0.1.0/src/udsxml2tex.egg-info/requires.txt +6 -0
- udsxml2tex-0.1.0/src/udsxml2tex.egg-info/top_level.txt +1 -0
- udsxml2tex-0.1.0/tests/test_udsxml2tex.py +248 -0
udsxml2tex-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 udsxml2tex contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: udsxml2tex
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Convert AUTOSAR DCM arxml to LaTeX UDS specification documents
|
|
5
|
+
Author: udsxml2tex contributors
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/udsxml2tex/udsxml2tex
|
|
8
|
+
Project-URL: Repository, https://github.com/udsxml2tex/udsxml2tex
|
|
9
|
+
Keywords: autosar,arxml,uds,dcm,latex,tex,diagnostics
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Software Development :: Documentation
|
|
20
|
+
Classifier: Topic :: Text Processing :: Markup :: LaTeX
|
|
21
|
+
Requires-Python: >=3.9
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
License-File: LICENSE
|
|
24
|
+
Requires-Dist: lxml>=4.9.0
|
|
25
|
+
Requires-Dist: Jinja2>=3.1.0
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
28
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
29
|
+
Dynamic: license-file
|
|
30
|
+
|
|
31
|
+
# udsxml2tex
|
|
32
|
+
|
|
33
|
+
**Convert AUTOSAR DCM arxml to LaTeX UDS specification documents**
|
|
34
|
+
|
|
35
|
+
A Python library that parses AUTOSAR DCM (Diagnostic Communication Manager) arxml configuration files and automatically generates ISO 14229 (UDS: Unified Diagnostic Services) specification documents in LaTeX format.
|
|
36
|
+
|
|
37
|
+
## Features
|
|
38
|
+
|
|
39
|
+
- Automatically extracts UDS specification data from DCM arxml files
|
|
40
|
+
- Diagnostic sessions
|
|
41
|
+
- Security access levels
|
|
42
|
+
- UDS service list (SID, supported sessions, NRCs, etc.)
|
|
43
|
+
- DID (Data Identifier) definitions
|
|
44
|
+
- Routine Control definitions
|
|
45
|
+
- Generates professional LaTeX specification documents
|
|
46
|
+
- Customizable via Jinja2 templates
|
|
47
|
+
- Available as both a CLI command and a Python API
|
|
48
|
+
- Supports merging multiple arxml files
|
|
49
|
+
|
|
50
|
+
## Installation
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install udsxml2tex
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
From source (for development):
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
git clone https://github.com/udsxml2tex/udsxml2tex.git
|
|
60
|
+
cd udsxml2tex
|
|
61
|
+
pip install -e ".[dev]"
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Usage
|
|
65
|
+
|
|
66
|
+
### CLI
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# Basic conversion
|
|
70
|
+
udsxml2tex input.arxml
|
|
71
|
+
|
|
72
|
+
# Specify output file
|
|
73
|
+
udsxml2tex input.arxml -o output.tex
|
|
74
|
+
|
|
75
|
+
# Override ECU name
|
|
76
|
+
udsxml2tex input.arxml --ecu-name "MyECU"
|
|
77
|
+
|
|
78
|
+
# Merge and convert multiple files
|
|
79
|
+
udsxml2tex dcm_config.arxml dcm_dids.arxml -o merged_spec.tex
|
|
80
|
+
|
|
81
|
+
# Verbose logging
|
|
82
|
+
udsxml2tex input.arxml -v
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Python API
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
from udsxml2tex import ArxmlParser, TexGenerator
|
|
89
|
+
|
|
90
|
+
# Parse ARXML
|
|
91
|
+
parser = ArxmlParser()
|
|
92
|
+
spec = parser.parse("path/to/dcm_config.arxml")
|
|
93
|
+
|
|
94
|
+
# Generate LaTeX
|
|
95
|
+
generator = TexGenerator()
|
|
96
|
+
generator.generate(spec, "output/uds_spec.tex")
|
|
97
|
+
|
|
98
|
+
# Get as string
|
|
99
|
+
tex_content = generator.generate_string(spec)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Custom Templates
|
|
103
|
+
|
|
104
|
+
You can use your own LaTeX templates:
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
generator = TexGenerator(template_dir="my_templates/")
|
|
108
|
+
generator.generate(spec, "output.tex", template_name="custom.tex.j2")
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
udsxml2tex input.arxml --template-dir my_templates/ --template custom.tex.j2
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Generated Document Structure
|
|
116
|
+
|
|
117
|
+
1. **Title Page** — ECU name, date
|
|
118
|
+
2. **Table of Contents**
|
|
119
|
+
3. **Document Overview** — Protocol information, CAN IDs
|
|
120
|
+
4. **Diagnostic Sessions** — Session list (ID, P2/P2* timers)
|
|
121
|
+
5. **Security Access** — Security level list
|
|
122
|
+
6. **UDS Services** — Service overview + detailed per-service info (including NRCs)
|
|
123
|
+
7. **DID Definitions** — DID overview + data element details
|
|
124
|
+
8. **Routine Control** — Routine overview + parameter details
|
|
125
|
+
|
|
126
|
+
## Supported arxml Structure
|
|
127
|
+
|
|
128
|
+
The following AUTOSAR DCM configuration elements are parsed:
|
|
129
|
+
|
|
130
|
+
| Element | Description |
|
|
131
|
+
|---------|-------------|
|
|
132
|
+
| `DcmDsl` | Diagnostic Session Layer (protocol, timing) |
|
|
133
|
+
| `DcmDsp` | Diagnostic Service Processing (sessions, security, DIDs, routines) |
|
|
134
|
+
| `DcmDsd` | Diagnostic Service Dispatcher (service table) |
|
|
135
|
+
|
|
136
|
+
Supports AUTOSAR R4.x arxml format.
|
|
137
|
+
|
|
138
|
+
## Requirements
|
|
139
|
+
|
|
140
|
+
- Python >= 3.9
|
|
141
|
+
- lxml >= 4.9.0
|
|
142
|
+
- Jinja2 >= 3.1.0
|
|
143
|
+
- LaTeX distribution (for compiling the generated .tex files)
|
|
144
|
+
|
|
145
|
+
## License
|
|
146
|
+
|
|
147
|
+
MIT License
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# udsxml2tex
|
|
2
|
+
|
|
3
|
+
**Convert AUTOSAR DCM arxml to LaTeX UDS specification documents**
|
|
4
|
+
|
|
5
|
+
A Python library that parses AUTOSAR DCM (Diagnostic Communication Manager) arxml configuration files and automatically generates ISO 14229 (UDS: Unified Diagnostic Services) specification documents in LaTeX format.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- Automatically extracts UDS specification data from DCM arxml files
|
|
10
|
+
- Diagnostic sessions
|
|
11
|
+
- Security access levels
|
|
12
|
+
- UDS service list (SID, supported sessions, NRCs, etc.)
|
|
13
|
+
- DID (Data Identifier) definitions
|
|
14
|
+
- Routine Control definitions
|
|
15
|
+
- Generates professional LaTeX specification documents
|
|
16
|
+
- Customizable via Jinja2 templates
|
|
17
|
+
- Available as both a CLI command and a Python API
|
|
18
|
+
- Supports merging multiple arxml files
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install udsxml2tex
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
From source (for development):
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
git clone https://github.com/udsxml2tex/udsxml2tex.git
|
|
30
|
+
cd udsxml2tex
|
|
31
|
+
pip install -e ".[dev]"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Usage
|
|
35
|
+
|
|
36
|
+
### CLI
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# Basic conversion
|
|
40
|
+
udsxml2tex input.arxml
|
|
41
|
+
|
|
42
|
+
# Specify output file
|
|
43
|
+
udsxml2tex input.arxml -o output.tex
|
|
44
|
+
|
|
45
|
+
# Override ECU name
|
|
46
|
+
udsxml2tex input.arxml --ecu-name "MyECU"
|
|
47
|
+
|
|
48
|
+
# Merge and convert multiple files
|
|
49
|
+
udsxml2tex dcm_config.arxml dcm_dids.arxml -o merged_spec.tex
|
|
50
|
+
|
|
51
|
+
# Verbose logging
|
|
52
|
+
udsxml2tex input.arxml -v
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Python API
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
from udsxml2tex import ArxmlParser, TexGenerator
|
|
59
|
+
|
|
60
|
+
# Parse ARXML
|
|
61
|
+
parser = ArxmlParser()
|
|
62
|
+
spec = parser.parse("path/to/dcm_config.arxml")
|
|
63
|
+
|
|
64
|
+
# Generate LaTeX
|
|
65
|
+
generator = TexGenerator()
|
|
66
|
+
generator.generate(spec, "output/uds_spec.tex")
|
|
67
|
+
|
|
68
|
+
# Get as string
|
|
69
|
+
tex_content = generator.generate_string(spec)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Custom Templates
|
|
73
|
+
|
|
74
|
+
You can use your own LaTeX templates:
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
generator = TexGenerator(template_dir="my_templates/")
|
|
78
|
+
generator.generate(spec, "output.tex", template_name="custom.tex.j2")
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
udsxml2tex input.arxml --template-dir my_templates/ --template custom.tex.j2
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Generated Document Structure
|
|
86
|
+
|
|
87
|
+
1. **Title Page** — ECU name, date
|
|
88
|
+
2. **Table of Contents**
|
|
89
|
+
3. **Document Overview** — Protocol information, CAN IDs
|
|
90
|
+
4. **Diagnostic Sessions** — Session list (ID, P2/P2* timers)
|
|
91
|
+
5. **Security Access** — Security level list
|
|
92
|
+
6. **UDS Services** — Service overview + detailed per-service info (including NRCs)
|
|
93
|
+
7. **DID Definitions** — DID overview + data element details
|
|
94
|
+
8. **Routine Control** — Routine overview + parameter details
|
|
95
|
+
|
|
96
|
+
## Supported arxml Structure
|
|
97
|
+
|
|
98
|
+
The following AUTOSAR DCM configuration elements are parsed:
|
|
99
|
+
|
|
100
|
+
| Element | Description |
|
|
101
|
+
|---------|-------------|
|
|
102
|
+
| `DcmDsl` | Diagnostic Session Layer (protocol, timing) |
|
|
103
|
+
| `DcmDsp` | Diagnostic Service Processing (sessions, security, DIDs, routines) |
|
|
104
|
+
| `DcmDsd` | Diagnostic Service Dispatcher (service table) |
|
|
105
|
+
|
|
106
|
+
Supports AUTOSAR R4.x arxml format.
|
|
107
|
+
|
|
108
|
+
## Requirements
|
|
109
|
+
|
|
110
|
+
- Python >= 3.9
|
|
111
|
+
- lxml >= 4.9.0
|
|
112
|
+
- Jinja2 >= 3.1.0
|
|
113
|
+
- LaTeX distribution (for compiling the generated .tex files)
|
|
114
|
+
|
|
115
|
+
## License
|
|
116
|
+
|
|
117
|
+
MIT License
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "udsxml2tex"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Convert AUTOSAR DCM arxml to LaTeX UDS specification documents"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
requires-python = ">=3.9"
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "udsxml2tex contributors"},
|
|
14
|
+
]
|
|
15
|
+
keywords = ["autosar", "arxml", "uds", "dcm", "latex", "tex", "diagnostics"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 3 - Alpha",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.9",
|
|
22
|
+
"Programming Language :: Python :: 3.10",
|
|
23
|
+
"Programming Language :: Python :: 3.11",
|
|
24
|
+
"Programming Language :: Python :: 3.12",
|
|
25
|
+
"Programming Language :: Python :: 3.13",
|
|
26
|
+
"Topic :: Software Development :: Documentation",
|
|
27
|
+
"Topic :: Text Processing :: Markup :: LaTeX",
|
|
28
|
+
]
|
|
29
|
+
dependencies = [
|
|
30
|
+
"lxml>=4.9.0",
|
|
31
|
+
"Jinja2>=3.1.0",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[project.optional-dependencies]
|
|
35
|
+
dev = [
|
|
36
|
+
"pytest>=7.0",
|
|
37
|
+
"pytest-cov>=4.0",
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
[project.scripts]
|
|
41
|
+
udsxml2tex = "udsxml2tex.cli:main"
|
|
42
|
+
|
|
43
|
+
[project.urls]
|
|
44
|
+
Homepage = "https://github.com/udsxml2tex/udsxml2tex"
|
|
45
|
+
Repository = "https://github.com/udsxml2tex/udsxml2tex"
|
|
46
|
+
|
|
47
|
+
[tool.setuptools.packages.find]
|
|
48
|
+
where = ["src"]
|
|
49
|
+
|
|
50
|
+
[tool.setuptools.package-data]
|
|
51
|
+
udsxml2tex = ["templates/*.tex.j2"]
|
|
52
|
+
|
|
53
|
+
[tool.pytest.ini_options]
|
|
54
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""udsxml2tex - Convert AUTOSAR DCM arxml to LaTeX UDS specification documents."""
|
|
2
|
+
|
|
3
|
+
__version__ = "0.1.0"
|
|
4
|
+
|
|
5
|
+
from udsxml2tex.generator import TexGenerator
|
|
6
|
+
from udsxml2tex.models import (
|
|
7
|
+
DataElement,
|
|
8
|
+
DiagSession,
|
|
9
|
+
Did,
|
|
10
|
+
NrcEntry,
|
|
11
|
+
Routine,
|
|
12
|
+
RoutineParameter,
|
|
13
|
+
SecurityLevel,
|
|
14
|
+
SubFunction,
|
|
15
|
+
UdsService,
|
|
16
|
+
UdsSpecification,
|
|
17
|
+
)
|
|
18
|
+
from udsxml2tex.parser import ArxmlParser
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"ArxmlParser",
|
|
22
|
+
"TexGenerator",
|
|
23
|
+
"UdsSpecification",
|
|
24
|
+
"UdsService",
|
|
25
|
+
"DiagSession",
|
|
26
|
+
"SecurityLevel",
|
|
27
|
+
"Did",
|
|
28
|
+
"DataElement",
|
|
29
|
+
"Routine",
|
|
30
|
+
"RoutineParameter",
|
|
31
|
+
"SubFunction",
|
|
32
|
+
"NrcEntry",
|
|
33
|
+
]
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"""Command-line interface for udsxml2tex."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import logging
|
|
7
|
+
import sys
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
from udsxml2tex.generator import TexGenerator
|
|
11
|
+
from udsxml2tex.parser import ArxmlParser
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _build_parser() -> argparse.ArgumentParser:
|
|
15
|
+
parser = argparse.ArgumentParser(
|
|
16
|
+
prog="udsxml2tex",
|
|
17
|
+
description="Convert AUTOSAR DCM arxml to LaTeX UDS specification documents.",
|
|
18
|
+
)
|
|
19
|
+
parser.add_argument(
|
|
20
|
+
"input",
|
|
21
|
+
nargs="+",
|
|
22
|
+
help="Input ARXML file(s). Multiple files will be merged.",
|
|
23
|
+
)
|
|
24
|
+
parser.add_argument(
|
|
25
|
+
"-o",
|
|
26
|
+
"--output",
|
|
27
|
+
default=None,
|
|
28
|
+
help="Output .tex file path. Default: <input_stem>_uds_spec.tex",
|
|
29
|
+
)
|
|
30
|
+
parser.add_argument(
|
|
31
|
+
"--ecu-name",
|
|
32
|
+
default=None,
|
|
33
|
+
help="Override ECU name in the generated document.",
|
|
34
|
+
)
|
|
35
|
+
parser.add_argument(
|
|
36
|
+
"--template-dir",
|
|
37
|
+
default=None,
|
|
38
|
+
help="Directory containing custom Jinja2 LaTeX templates.",
|
|
39
|
+
)
|
|
40
|
+
parser.add_argument(
|
|
41
|
+
"--template",
|
|
42
|
+
default="uds_spec.tex.j2",
|
|
43
|
+
help="Template file name (default: uds_spec.tex.j2).",
|
|
44
|
+
)
|
|
45
|
+
parser.add_argument(
|
|
46
|
+
"-v",
|
|
47
|
+
"--verbose",
|
|
48
|
+
action="store_true",
|
|
49
|
+
help="Enable verbose logging output.",
|
|
50
|
+
)
|
|
51
|
+
parser.add_argument(
|
|
52
|
+
"--version",
|
|
53
|
+
action="version",
|
|
54
|
+
version="%(prog)s 0.1.0",
|
|
55
|
+
)
|
|
56
|
+
return parser
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def main(argv: list[str] | None = None) -> int:
|
|
60
|
+
"""Main entry point for the CLI.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
argv: Command-line arguments. Defaults to sys.argv[1:].
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
Exit code (0 for success).
|
|
67
|
+
"""
|
|
68
|
+
parser = _build_parser()
|
|
69
|
+
args = parser.parse_args(argv)
|
|
70
|
+
|
|
71
|
+
# Configure logging
|
|
72
|
+
level = logging.DEBUG if args.verbose else logging.INFO
|
|
73
|
+
logging.basicConfig(
|
|
74
|
+
level=level,
|
|
75
|
+
format="%(levelname)s: %(message)s",
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
# Validate input files
|
|
79
|
+
input_paths = [Path(p) for p in args.input]
|
|
80
|
+
for p in input_paths:
|
|
81
|
+
if not p.exists():
|
|
82
|
+
logging.error("Input file not found: %s", p)
|
|
83
|
+
return 1
|
|
84
|
+
if not p.suffix.lower() == ".arxml":
|
|
85
|
+
logging.warning(
|
|
86
|
+
"File does not have .arxml extension: %s", p
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
# Determine output path
|
|
90
|
+
if args.output:
|
|
91
|
+
output_path = Path(args.output)
|
|
92
|
+
else:
|
|
93
|
+
stem = input_paths[0].stem
|
|
94
|
+
output_path = input_paths[0].parent / f"{stem}_uds_spec.tex"
|
|
95
|
+
|
|
96
|
+
# Parse ARXML
|
|
97
|
+
arxml_parser = ArxmlParser()
|
|
98
|
+
try:
|
|
99
|
+
if len(input_paths) == 1:
|
|
100
|
+
spec = arxml_parser.parse(input_paths[0])
|
|
101
|
+
else:
|
|
102
|
+
spec = arxml_parser.parse_multi(input_paths)
|
|
103
|
+
except Exception as e:
|
|
104
|
+
logging.error("Failed to parse ARXML: %s", e)
|
|
105
|
+
return 1
|
|
106
|
+
|
|
107
|
+
# Override ECU name if specified
|
|
108
|
+
if args.ecu_name:
|
|
109
|
+
spec.ecu_name = args.ecu_name
|
|
110
|
+
|
|
111
|
+
# Generate LaTeX
|
|
112
|
+
try:
|
|
113
|
+
tex_gen = TexGenerator(template_dir=args.template_dir)
|
|
114
|
+
result = tex_gen.generate(
|
|
115
|
+
spec, output_path, template_name=args.template
|
|
116
|
+
)
|
|
117
|
+
logging.info("Output written to: %s", result)
|
|
118
|
+
except Exception as e:
|
|
119
|
+
logging.error("Failed to generate LaTeX: %s", e)
|
|
120
|
+
return 1
|
|
121
|
+
|
|
122
|
+
return 0
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
if __name__ == "__main__":
|
|
126
|
+
sys.exit(main())
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"""LaTeX generator for UDS specification documents."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Optional
|
|
8
|
+
|
|
9
|
+
from jinja2 import Environment, FileSystemLoader, select_autoescape
|
|
10
|
+
|
|
11
|
+
from udsxml2tex.models import UdsSpecification
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
# Characters that need escaping in LaTeX
|
|
16
|
+
_LATEX_ESCAPE_MAP = {
|
|
17
|
+
"&": r"\&",
|
|
18
|
+
"%": r"\%",
|
|
19
|
+
"$": r"\$",
|
|
20
|
+
"#": r"\#",
|
|
21
|
+
"_": r"\_",
|
|
22
|
+
"{": r"\{",
|
|
23
|
+
"}": r"\}",
|
|
24
|
+
"~": r"\textasciitilde{}",
|
|
25
|
+
"^": r"\textasciicircum{}",
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _latex_escape(text: str) -> str:
|
|
30
|
+
"""Escape special LaTeX characters in text."""
|
|
31
|
+
if not text:
|
|
32
|
+
return ""
|
|
33
|
+
# Don't escape backslashes that are already LaTeX commands
|
|
34
|
+
result = []
|
|
35
|
+
i = 0
|
|
36
|
+
while i < len(text):
|
|
37
|
+
ch = text[i]
|
|
38
|
+
if ch == "\\" and i + 1 < len(text) and text[i + 1].isalpha():
|
|
39
|
+
# Likely a LaTeX command, don't escape
|
|
40
|
+
result.append(ch)
|
|
41
|
+
elif ch in _LATEX_ESCAPE_MAP:
|
|
42
|
+
result.append(_LATEX_ESCAPE_MAP[ch])
|
|
43
|
+
else:
|
|
44
|
+
result.append(ch)
|
|
45
|
+
i += 1
|
|
46
|
+
return "".join(result)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class TexGenerator:
|
|
50
|
+
"""Generate LaTeX documents from UDS specification data."""
|
|
51
|
+
|
|
52
|
+
def __init__(self, template_dir: Optional[str | Path] = None) -> None:
|
|
53
|
+
"""Initialize the TeX generator.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
template_dir: Directory containing Jinja2 templates.
|
|
57
|
+
Defaults to the built-in templates directory.
|
|
58
|
+
"""
|
|
59
|
+
if template_dir is None:
|
|
60
|
+
template_dir = Path(__file__).parent / "templates"
|
|
61
|
+
else:
|
|
62
|
+
template_dir = Path(template_dir)
|
|
63
|
+
|
|
64
|
+
self.template_dir = template_dir
|
|
65
|
+
self.env = Environment(
|
|
66
|
+
loader=FileSystemLoader(str(template_dir)),
|
|
67
|
+
block_start_string=r"\BLOCK{",
|
|
68
|
+
block_end_string="}",
|
|
69
|
+
variable_start_string=r"\VAR{",
|
|
70
|
+
variable_end_string="}",
|
|
71
|
+
comment_start_string=r"\#{",
|
|
72
|
+
comment_end_string="}",
|
|
73
|
+
autoescape=False,
|
|
74
|
+
trim_blocks=True,
|
|
75
|
+
lstrip_blocks=True,
|
|
76
|
+
)
|
|
77
|
+
# Register custom filters
|
|
78
|
+
self.env.filters["latex_escape"] = _latex_escape
|
|
79
|
+
|
|
80
|
+
def generate(
|
|
81
|
+
self,
|
|
82
|
+
spec: UdsSpecification,
|
|
83
|
+
output_path: str | Path,
|
|
84
|
+
template_name: str = "uds_spec.tex.j2",
|
|
85
|
+
) -> Path:
|
|
86
|
+
"""Generate a LaTeX document from the UDS specification.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
spec: The UDS specification data.
|
|
90
|
+
output_path: Path for the output .tex file.
|
|
91
|
+
template_name: Name of the Jinja2 template to use.
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
Path to the generated .tex file.
|
|
95
|
+
"""
|
|
96
|
+
output_path = Path(output_path)
|
|
97
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
98
|
+
|
|
99
|
+
template = self.env.get_template(template_name)
|
|
100
|
+
|
|
101
|
+
# Sort data for consistent output
|
|
102
|
+
services = sorted(spec.services, key=lambda s: s.service_id)
|
|
103
|
+
dids = sorted(spec.dids, key=lambda d: d.did_id)
|
|
104
|
+
routines = sorted(spec.routines, key=lambda r: r.routine_id)
|
|
105
|
+
sessions = sorted(spec.sessions, key=lambda s: s.session_id)
|
|
106
|
+
security_levels = sorted(spec.security_levels, key=lambda s: s.security_level)
|
|
107
|
+
|
|
108
|
+
context = {
|
|
109
|
+
"ecu_name": spec.ecu_name,
|
|
110
|
+
"description": spec.description,
|
|
111
|
+
"protocol_name": spec.protocol_name,
|
|
112
|
+
"can_rx_id": spec.can_rx_id,
|
|
113
|
+
"can_tx_id": spec.can_tx_id,
|
|
114
|
+
"can_functional_id": spec.can_functional_id,
|
|
115
|
+
"sessions": sessions,
|
|
116
|
+
"security_levels": security_levels,
|
|
117
|
+
"services": services,
|
|
118
|
+
"dids": dids,
|
|
119
|
+
"routines": routines,
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
rendered = template.render(**context)
|
|
123
|
+
|
|
124
|
+
output_path.write_text(rendered, encoding="utf-8")
|
|
125
|
+
logger.info("Generated LaTeX document: %s", output_path)
|
|
126
|
+
|
|
127
|
+
return output_path
|
|
128
|
+
|
|
129
|
+
def generate_string(
|
|
130
|
+
self,
|
|
131
|
+
spec: UdsSpecification,
|
|
132
|
+
template_name: str = "uds_spec.tex.j2",
|
|
133
|
+
) -> str:
|
|
134
|
+
"""Generate LaTeX content as a string.
|
|
135
|
+
|
|
136
|
+
Args:
|
|
137
|
+
spec: The UDS specification data.
|
|
138
|
+
template_name: Name of the Jinja2 template to use.
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
Rendered LaTeX content.
|
|
142
|
+
"""
|
|
143
|
+
template = self.env.get_template(template_name)
|
|
144
|
+
|
|
145
|
+
services = sorted(spec.services, key=lambda s: s.service_id)
|
|
146
|
+
dids = sorted(spec.dids, key=lambda d: d.did_id)
|
|
147
|
+
routines = sorted(spec.routines, key=lambda r: r.routine_id)
|
|
148
|
+
sessions = sorted(spec.sessions, key=lambda s: s.session_id)
|
|
149
|
+
security_levels = sorted(spec.security_levels, key=lambda s: s.security_level)
|
|
150
|
+
|
|
151
|
+
context = {
|
|
152
|
+
"ecu_name": spec.ecu_name,
|
|
153
|
+
"description": spec.description,
|
|
154
|
+
"protocol_name": spec.protocol_name,
|
|
155
|
+
"can_rx_id": spec.can_rx_id,
|
|
156
|
+
"can_tx_id": spec.can_tx_id,
|
|
157
|
+
"can_functional_id": spec.can_functional_id,
|
|
158
|
+
"sessions": sessions,
|
|
159
|
+
"security_levels": security_levels,
|
|
160
|
+
"services": services,
|
|
161
|
+
"dids": dids,
|
|
162
|
+
"routines": routines,
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return template.render(**context)
|