PyDMConverter 1.0.2__tar.gz → 1.0.3__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.
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/PKG-INFO +1 -1
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/PyDMConverter.egg-info/PKG-INFO +1 -1
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/PyDMConverter.egg-info/SOURCES.txt +4 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/docs/arguments.md +20 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/docs/user_guide.md +6 -1
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/pydmconverter/__main__.py +16 -10
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/pydmconverter/edm/converter.py +8 -4
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/pydmconverter/edm/converter_helpers.py +514 -394
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/pydmconverter/edm/menumux.py +4 -1
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/pydmconverter/edm/parser.py +14 -13
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/pydmconverter/edm/parser_helpers.py +3 -5
- pydmconverter-1.0.3/pydmconverter/exceptions.py +17 -0
- pydmconverter-1.0.3/pydmconverter/sites/__init__.py +12 -0
- pydmconverter-1.0.3/pydmconverter/sites/slac.py +2 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/pydmconverter/widgets.py +14 -4
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/pydmconverter/widgets_helpers.py +24 -29
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/tests/edm/test_converter.py +124 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/tests/edm/test_parser.py +5 -0
- pydmconverter-1.0.3/tests/test_sites.py +16 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/tests/test_widgets.py +64 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/.github/workflows/gh-pages.yml +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/.github/workflows/lint.yml +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/.github/workflows/pypi_release.yml +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/.github/workflows/tests.yml +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/.gitignore +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/.pre-commit-config.yaml +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/LICENSE +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/PyDMConverter.egg-info/dependency_links.txt +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/PyDMConverter.egg-info/entry_points.txt +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/PyDMConverter.egg-info/requires.txt +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/PyDMConverter.egg-info/top_level.txt +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/README.md +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/app/resources/file_minus.png +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/app/resources/file_plus.png +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/app/resources/file_x.png +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/app/resources/folder_plus.png +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/app/resources/folder_search.png +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/app/resources/play_circle_outline.png +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/app/resources/settings.png +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/app/src/model/__init__.py +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/app/src/model/app_model.py +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/app/src/model/options_model.py +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/app/src/view/__init__.py +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/app/src/view/file_select_widget.py +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/app/src/view/main_window.py +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/app/src/view/main_window.ui +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/app/src/view/options_window.py +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/app/src/view/output_select_dialog.py +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/docs/images/pydmconverter.png +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/docs/index.md +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/docs/reference/custom_types.md +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/docs/reference/edm/converter.md +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/docs/reference/edm/converter_helpers.md +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/docs/reference/edm/menumux.md +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/docs/reference/edm/parser.md +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/docs/reference/edm/parser_helpers.md +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/docs/reference/index.md +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/docs/reference/pydm-converter-tool.md +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/docs/reference/widgets.md +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/docs/reference/widgets_helpers.md +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/environment.yml +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/examples/TEM_mapping.edl +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/examples/all_bsy0_main.edl +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/examples/all_bsy0_main_with_groups.edl +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/examples/prosilica.edl +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/mkdocs.yml +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/pydmconverter/__init__.py +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/pydmconverter/custom_types.py +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/pydmconverter/edm/__init__.py +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/pydmconverter/launch_gui.sh +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/pyproject.toml +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/setup.cfg +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/tests/__init__.py +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/tests/edm/test_converter_helpers.py +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/tests/edm/test_parser_helpers.py +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/tests/test_main.py +0 -0
- {pydmconverter-1.0.2 → pydmconverter-1.0.3}/tests/test_widgets_helpers.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyDMConverter
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.3
|
|
4
4
|
Summary: converter to generate pydm .ui files from other display managers.
|
|
5
5
|
Author: Devan Agrawal, Zach Domke, Ryan McClanahan, Alexander Ng, Logan Somoza, Alexandria Ikuma
|
|
6
6
|
Author-email: Yekta Yazar <yazar@slac.stanford.edu>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyDMConverter
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.3
|
|
4
4
|
Summary: converter to generate pydm .ui files from other display managers.
|
|
5
5
|
Author: Devan Agrawal, Zach Domke, Ryan McClanahan, Alexander Ng, Logan Somoza, Alexandria Ikuma
|
|
6
6
|
Author-email: Yekta Yazar <yazar@slac.stanford.edu>
|
|
@@ -54,6 +54,7 @@ examples/prosilica.edl
|
|
|
54
54
|
pydmconverter/__init__.py
|
|
55
55
|
pydmconverter/__main__.py
|
|
56
56
|
pydmconverter/custom_types.py
|
|
57
|
+
pydmconverter/exceptions.py
|
|
57
58
|
pydmconverter/launch_gui.sh
|
|
58
59
|
pydmconverter/widgets.py
|
|
59
60
|
pydmconverter/widgets_helpers.py
|
|
@@ -63,8 +64,11 @@ pydmconverter/edm/converter_helpers.py
|
|
|
63
64
|
pydmconverter/edm/menumux.py
|
|
64
65
|
pydmconverter/edm/parser.py
|
|
65
66
|
pydmconverter/edm/parser_helpers.py
|
|
67
|
+
pydmconverter/sites/__init__.py
|
|
68
|
+
pydmconverter/sites/slac.py
|
|
66
69
|
tests/__init__.py
|
|
67
70
|
tests/test_main.py
|
|
71
|
+
tests/test_sites.py
|
|
68
72
|
tests/test_widgets.py
|
|
69
73
|
tests/test_widgets_helpers.py
|
|
70
74
|
tests/edm/test_converter.py
|
|
@@ -15,6 +15,26 @@ This argument allows users to override the output file if it already exists. Mos
|
|
|
15
15
|
|
|
16
16
|
This argument adds scroll bars to converted screens. It will ad a horizontal and vertical scroll bar. If this argument is not included, the screen will not contain a scroll bar.
|
|
17
17
|
|
|
18
|
+
## Site
|
|
19
|
+
|
|
20
|
+
`--site <name>`
|
|
21
|
+
|
|
22
|
+
This argument applies site-specific conversion rules during the conversion process. Some facilities have EDM widgets or patterns that have no equivalent in PyDM and should be skipped or handled differently. The `--site` flag lets you opt into these rules without affecting the default conversion behavior.
|
|
23
|
+
|
|
24
|
+
**Available sites:**
|
|
25
|
+
|
|
26
|
+
| Site | Rules Applied |
|
|
27
|
+
|--------|---------------|
|
|
28
|
+
| `slac` | Skips `activeExitButtonClass` (exit buttons present on every SLAC EDM screen that have no PyDM equivalent) |
|
|
29
|
+
|
|
30
|
+
**Usage:**
|
|
31
|
+
``` bash
|
|
32
|
+
pydmconverter /path/to/file.edl output.ui --site slac
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Adding a new site:**
|
|
36
|
+
To add conversion rules for a new site, create a new module in `pydmconverter/sites/` (e.g. `mysite.py`) that defines a `SKIP_WIDGETS` set, then register it in `pydmconverter/sites/__init__.py`.
|
|
37
|
+
|
|
18
38
|
## Help
|
|
19
39
|
|
|
20
40
|
`-h` or `--help`
|
|
@@ -69,5 +69,10 @@ pydmconverter /afs/slac/g/lcls/edm/file.edl file.ui`
|
|
|
69
69
|
```
|
|
70
70
|
To convert EDM files in a folder called "edm" to PYDM file in the current folder :
|
|
71
71
|
``` bash
|
|
72
|
-
pydmconverter /afs/slac/g/lcls/edm . .edl
|
|
72
|
+
pydmconverter /afs/slac/g/lcls/edm . .edl
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
To convert with SLAC-specific rules (e.g. skipping exit buttons):
|
|
76
|
+
``` bash
|
|
77
|
+
pydmconverter /afs/slac/g/lcls/edm/file.edl file.ui --site slac
|
|
73
78
|
```
|
|
@@ -7,7 +7,7 @@ from pydmconverter.edm.converter import convert
|
|
|
7
7
|
from pathlib import Path
|
|
8
8
|
import logging
|
|
9
9
|
|
|
10
|
-
logging.basicConfig(level=logging.
|
|
10
|
+
logging.basicConfig(level=logging.WARNING)
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
IMAGE_FILE_SUFFIXES = {".png", ".jpg", ".jpeg", ".gif"}
|
|
@@ -29,7 +29,7 @@ def run_gui() -> None:
|
|
|
29
29
|
subprocess.run(["bash", str(launch_script)], check=True)
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
def run(input_file, output_file, input_file_type=".edl", override=False, scrollable=False):
|
|
32
|
+
def run(input_file, output_file, input_file_type=".edl", override=False, scrollable=False, site=None):
|
|
33
33
|
input_path: Path = Path(input_file)
|
|
34
34
|
output_path: Path = Path(output_file)
|
|
35
35
|
|
|
@@ -39,7 +39,7 @@ def run(input_file, output_file, input_file_type=".edl", override=False, scrolla
|
|
|
39
39
|
if output_path.is_file() and not override:
|
|
40
40
|
raise FileExistsError(f"Output file '{output_path}' already exists. Use --override or -o to overwrite it.")
|
|
41
41
|
copy_img_files(input_path.parent, output_path.parent)
|
|
42
|
-
convert(str(input_path), str(output_path), scrollable)
|
|
42
|
+
convert(str(input_path), str(output_path), scrollable, site=site)
|
|
43
43
|
else:
|
|
44
44
|
if input_file_type[0] != ".": # prepending . so it will not pick up other file types with same suffix
|
|
45
45
|
input_file_type = "." + input_file_type
|
|
@@ -47,7 +47,7 @@ def run(input_file, output_file, input_file_type=".edl", override=False, scrolla
|
|
|
47
47
|
files_found: int
|
|
48
48
|
files_failed: list[str]
|
|
49
49
|
files_found, files_failed = convert_files_in_folder(
|
|
50
|
-
input_path, output_path, input_file_type, override, scrollable
|
|
50
|
+
input_path, output_path, input_file_type, override, scrollable, site=site
|
|
51
51
|
)
|
|
52
52
|
|
|
53
53
|
if files_found == 0:
|
|
@@ -76,7 +76,8 @@ def run_cli(args: argparse.Namespace) -> None:
|
|
|
76
76
|
input_file_type: str = args.output_type
|
|
77
77
|
override: bool = args.override
|
|
78
78
|
scrollable: bool = args.scrollable
|
|
79
|
-
|
|
79
|
+
site: str = args.site
|
|
80
|
+
run(input_file, output_file, input_file_type, override, scrollable, site=site)
|
|
80
81
|
|
|
81
82
|
|
|
82
83
|
"""
|
|
@@ -98,7 +99,7 @@ def run_cli(args: argparse.Namespace) -> None:
|
|
|
98
99
|
files_found: int
|
|
99
100
|
files_failed: list[str]
|
|
100
101
|
files_found, files_failed = convert_files_in_folder(
|
|
101
|
-
input_path, output_path, input_file_type, override, scrollable
|
|
102
|
+
input_path, output_path, input_file_type, override, scrollable, site=site
|
|
102
103
|
)
|
|
103
104
|
|
|
104
105
|
if files_found == 0:
|
|
@@ -125,7 +126,7 @@ def copy_img_files(input_path: Path, output_path: Path) -> None:
|
|
|
125
126
|
|
|
126
127
|
|
|
127
128
|
def convert_files_in_folder(
|
|
128
|
-
input_path: Path, output_path: Path, input_file_type: str, override: bool, scrollable: bool
|
|
129
|
+
input_path: Path, output_path: Path, input_file_type: str, override: bool, scrollable: bool, site=None
|
|
129
130
|
) -> tuple[int, list[str]]:
|
|
130
131
|
"""Recursively runs convert on files in directory and subdirectories
|
|
131
132
|
|
|
@@ -161,17 +162,16 @@ def convert_files_in_folder(
|
|
|
161
162
|
logging.warning(f"Skipped: {output_file_path} already exists. Use --override or -o to overwrite it.")
|
|
162
163
|
else:
|
|
163
164
|
try:
|
|
164
|
-
convert(file, output_file_path, scrollable)
|
|
165
|
+
convert(file, output_file_path, scrollable, site=site)
|
|
165
166
|
except Exception as e:
|
|
166
167
|
files_failed.append(str(file))
|
|
167
168
|
logging.warning(f"Failed to convert {file}: {e}")
|
|
168
|
-
breakpoint()
|
|
169
169
|
continue
|
|
170
170
|
|
|
171
171
|
subdirectories = [item for item in input_path.iterdir() if item.is_dir()]
|
|
172
172
|
for subdir in subdirectories:
|
|
173
173
|
sub_found, sub_failed = convert_files_in_folder(
|
|
174
|
-
subdir, output_path / subdir.name, input_file_type, override, scrollable
|
|
174
|
+
subdir, output_path / subdir.name, input_file_type, override, scrollable, site=site
|
|
175
175
|
)
|
|
176
176
|
files_found += sub_found
|
|
177
177
|
files_failed += sub_failed
|
|
@@ -227,6 +227,12 @@ def main() -> None:
|
|
|
227
227
|
action="store_true",
|
|
228
228
|
help="create scrollable pydm windows that replicate edm windows (may cause spacing issues for embedded displays)",
|
|
229
229
|
)
|
|
230
|
+
parser.add_argument(
|
|
231
|
+
"--site",
|
|
232
|
+
type=str,
|
|
233
|
+
default=None,
|
|
234
|
+
help="Apply site-specific conversion rules (e.g., slac)",
|
|
235
|
+
)
|
|
230
236
|
args: argparse.Namespace = parser.parse_args()
|
|
231
237
|
|
|
232
238
|
if args.input_file:
|
|
@@ -2,7 +2,7 @@ from pydmconverter.edm.parser import EDMFileParser, EDMObject
|
|
|
2
2
|
import xml.etree.ElementTree as ET
|
|
3
3
|
from pydmconverter.edm.converter_helpers import convert_edm_to_pydm_widgets
|
|
4
4
|
import logging
|
|
5
|
-
|
|
5
|
+
|
|
6
6
|
from pydmconverter.widgets_helpers import PageHeader
|
|
7
7
|
|
|
8
8
|
logger = logging.getLogger(__name__)
|
|
@@ -50,10 +50,9 @@ CUSTOM_WIDGET_DEFINITIONS = {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
|
|
53
|
-
def convert(input_path, output_path, scrollable=False):
|
|
53
|
+
def convert(input_path, output_path, scrollable=False, site=None):
|
|
54
54
|
try:
|
|
55
55
|
edm_parser = EDMFileParser(input_path, output_path)
|
|
56
|
-
pprint(edm_parser.ui, indent=2)
|
|
57
56
|
logger.info(f"Successfully parsed EDM file: {input_path}")
|
|
58
57
|
except FileNotFoundError:
|
|
59
58
|
logger.error("File Not Found")
|
|
@@ -61,7 +60,7 @@ def convert(input_path, output_path, scrollable=False):
|
|
|
61
60
|
|
|
62
61
|
# edm_parser.ui, _, _ = replace_calc_and_loc_in_edm_content(edm_parser.ui, input_path)
|
|
63
62
|
|
|
64
|
-
pydm_widgets, used_classes = convert_edm_to_pydm_widgets(edm_parser)
|
|
63
|
+
pydm_widgets, used_classes = convert_edm_to_pydm_widgets(edm_parser, site=site)
|
|
65
64
|
logger.info(f"Converted EDM objects to {len(pydm_widgets)} PyDM widgets.")
|
|
66
65
|
|
|
67
66
|
page_header = PageHeader()
|
|
@@ -87,10 +86,15 @@ def convert(input_path, output_path, scrollable=False):
|
|
|
87
86
|
tree.write(output_path, encoding="utf-8", xml_declaration=True)
|
|
88
87
|
|
|
89
88
|
|
|
89
|
+
QT_BASE_CLASSES = {"QPushButton", "QTabWidget", "QFrame", "QLabel", "QWidget", "QLineEdit", "QComboBox", "QTableWidget"}
|
|
90
|
+
|
|
91
|
+
|
|
90
92
|
def build_customwidgets_element(used_classes: set) -> ET.Element:
|
|
91
93
|
customwidgets_el = ET.Element("customwidgets")
|
|
92
94
|
|
|
93
95
|
for cls_name in sorted(used_classes):
|
|
96
|
+
if cls_name in QT_BASE_CLASSES:
|
|
97
|
+
continue
|
|
94
98
|
if cls_name not in CUSTOM_WIDGET_DEFINITIONS:
|
|
95
99
|
logger.warning(f"Could not find custom widget {cls_name} in CUSTOM_WIDGET_DEFINITIONS")
|
|
96
100
|
continue
|