Skip to content

Commit af7dc51

Browse files
committed
migrate to uv + fix #24
1 parent 693ab21 commit af7dc51

33 files changed

+264
-143
lines changed

.gitignore

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11

2-
3-
# DepHell stuff
4-
poetry.lock
2+
uv.lock
53

64
# Byte-compiled / optimized / DLL files
75
__pycache__/

.pre-commit-config.yaml

+27-9
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,42 @@
11
repos:
22
- repo: https://github.com/astral-sh/ruff-pre-commit
3-
rev: v0.2.2
3+
rev: v0.9.6
44
hooks:
55
- id: ruff
66
args: [ --fix ]
77
- id: ruff-format
88

99
- repo: https://github.com/RobertCraigie/pyright-python
10-
rev: v1.1.351
10+
rev: v1.1.394
1111
hooks:
1212
- id: pyright
1313

14-
- repo: https://github.com/Lucas-C/pre-commit-hooks-safety
15-
rev: v1.3.3
14+
- repo: local
1615
hooks:
17-
- id: python-safety-dependencies-check
18-
files: pyproject.toml
16+
- id: generate requirements
17+
name: generate requirements
18+
entry: uv export --no-hashes --no-dev -o requirements.txt
19+
language: system
20+
pass_filenames: false
21+
- id: safety
22+
name: safety
23+
entry: uv run safety
24+
language: system
25+
pass_filenames: false
26+
- id: make docs
27+
name: make docs
28+
entry: uv run handsdown --cleanup -o documentation/reference
29+
language: system
30+
pass_filenames: false
31+
- id: build package
32+
name: build package
33+
entry: uv build
34+
language: system
35+
pass_filenames: false
36+
1937

2038
- repo: https://github.com/pre-commit/pre-commit-hooks
21-
rev: v4.5.0
39+
rev: v5.0.0
2240
hooks:
2341
- id: trailing-whitespace
2442
- id: end-of-file-fixer
@@ -35,11 +53,11 @@ repos:
3553
- id: mixed-line-ending
3654

3755
- repo: https://github.com/boidolr/pre-commit-images
38-
rev: v1.5.2
56+
rev: v1.8.4
3957
hooks:
4058
- id: optimize-jpg
4159
- id: optimize-png
4260
- id: optimize-svg
4361
- id: optimize-webp
4462

45-
exclude: "tests|tests/data|documentation/reference"
63+
exclude: "tests/data|documentation/reference"

cli2gui/__init__.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
"""Entry point for the program.
2-
"""
1+
"""Entry point for the program."""
2+
33
from __future__ import annotations
44

55
from cli2gui.decorators import Cli2Gui, Click2Gui

cli2gui/application/application2args.py

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
"""Functions to create args from key/value pairs.
2-
"""
1+
"""Functions to create args from key/value pairs."""
2+
33
from __future__ import annotations
44

55
import argparse
@@ -18,8 +18,11 @@ def processValue(key: str, value: str) -> tuple[str, Any]:
1818
return key, None
1919
if _type == "ItemType.Bool":
2020
return key, bool(value)
21-
if _type == "ItemType.File":
22-
return key, open(value, encoding="utf-8")
21+
if "ItemType.File" in _type:
22+
_, mode, encoding = _type.split(";", maxsplit=2)
23+
if "b" in mode:
24+
return key, open(value, mode=mode)
25+
return key, open(value, mode=mode, encoding=encoding)
2326
if _type == "ItemType.Path":
2427
return key, Path(value)
2528
if _type == "ItemType.Int":

cli2gui/decorators.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
"""Decorator and entry point for the program.
2-
"""
1+
"""Decorator and entry point for the program."""
32

43
from __future__ import annotations
54

@@ -70,7 +69,7 @@ def createFromParser(
7069
buildSpec.parser = input(
7170
f"!Custom parser selected! Choose one of: {[x.value for x in ParserType]}"
7271
)
73-
if buildSpec.parser not in ParserType._value2member_map_: # noqa: SLF001
72+
if buildSpec.parser not in ParserType._value2member_map_:
7473
msg = f"!Custom parser must be one of: {[x.value for x in ParserType]}"
7574
raise RuntimeError(msg)
7675

cli2gui/gui/dearpygui_wrapper.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ def addWidgetFromItem(self, item: Item) -> None:
8888
functionMap = {
8989
ItemType.Bool: self._helpFlagWidget,
9090
ItemType.File: self._helpFileWidget,
91+
ItemType.FileWrite: self._helpFileWidget,
9192
ItemType.Path: self._helpFileWidget,
9293
ItemType.Choice: self._helpDropdownWidget,
9394
ItemType.Int: self._helpIntCounterWidget,
@@ -111,7 +112,7 @@ def addItemsAndGroups(
111112
:return list[Item]: flattened list of items
112113
"""
113114
dpg.add_text(
114-
f'=== {helpers.stringTitlecase(section.name, " ")} ===',
115+
f"=== {helpers.stringTitlecase(section.name, ' ')} ===",
115116
color=hex_to_rgb(self.base24Theme[14]),
116117
)
117118

cli2gui/gui/pysimplegui_wrapper.py

+31-7
Original file line numberDiff line numberDiff line change
@@ -127,11 +127,35 @@ def _dropdown(self, key: str, argItems: list[str]) -> Any:
127127
)
128128

129129
def _fileBrowser(
130-
self, key: str, default: str | None = None, _type: ItemType = ItemType.File
130+
self,
131+
key: str,
132+
default: str | None = None,
133+
_type: ItemType = ItemType.File,
134+
additional_properties: dict | None = None,
131135
) -> list[Any]:
132136
"""Return a fileBrowser button and field."""
137+
additional_properties = additional_properties or {}
138+
133139
height = self.sizes["input_size"][1]
134140
width = self.sizes["input_size"][0]
141+
142+
key = f"{key}{SEP}{_type}"
143+
if _type in [ItemType.FileWrite, ItemType.File]:
144+
key += f";{additional_properties.get('file_mode')};{additional_properties.get('file_encoding')}"
145+
146+
browser = self.sg.FileBrowse(
147+
key="@@" + key,
148+
size=(int(width / 3), height),
149+
pad=(0, self.sizes["padding"][1]),
150+
)
151+
152+
if _type in [ItemType.FileWrite, ItemType.Path]:
153+
browser = self.sg.SaveAs(
154+
button_text="Select/Create",
155+
key="@@" + key,
156+
size=(int(width / 3), height),
157+
pad=(0, self.sizes["padding"][1]),
158+
)
135159
fb: list[Any] = [
136160
self.sg.InputText(
137161
default or "",
@@ -140,11 +164,7 @@ def _fileBrowser(
140164
key=key,
141165
font=("sans", self.sizes["text_size"]),
142166
),
143-
self.sg.FileBrowse(
144-
key=f"{key}{SEP}{_type}",
145-
size=(int(width / 3), height),
146-
pad=(0, self.sizes["padding"][1]),
147-
),
167+
browser,
148168
]
149169
return fb
150170

@@ -229,7 +249,10 @@ def _helpFileWidget(
229249
"""Return a set of self that make up an arg with a file."""
230250
return [
231251
self._helpArgNameAndHelp(item.commands, item.help, item.display_name),
232-
self.sg.Column([self._fileBrowser(item.dest, item.default, item.type)], pad=(0, 0)),
252+
self.sg.Column(
253+
[self._fileBrowser(item.dest, item.default, item.type, item.additional_properties)],
254+
pad=(0, 0),
255+
),
233256
]
234257

235258
def _helpDropdownWidget(
@@ -259,6 +282,7 @@ def addWidgetFromItem(self, item: Item) -> list[Any]:
259282
functionMap = {
260283
ItemType.Bool: self._helpFlagWidget,
261284
ItemType.File: self._helpFileWidget,
285+
ItemType.FileWrite: self._helpFileWidget,
262286
ItemType.Path: self._helpFileWidget,
263287
ItemType.Choice: self._helpDropdownWidget,
264288
ItemType.Int: self._helpCounterWidget,

cli2gui/tojson/argparse2json.py

+17-1
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,17 @@ def extractRawGroups(actionGroup: argparse._ArgumentGroup) -> ArgparseGroup:
108108
}
109109

110110

111+
def fileActionToJson(action: argparse.Action, widget: ItemType) -> Item:
112+
item = actionToJson(action=action, widget=widget)
113+
if isinstance(action.type, argparse.FileType):
114+
item.additional_properties = {
115+
**item.additional_properties,
116+
"file_mode": action.type._mode,
117+
"file_encoding": action.type._encoding,
118+
}
119+
return item
120+
121+
111122
def actionToJson(action: argparse.Action, widget: ItemType) -> Item:
112123
"""Generate json for an action and set the widget - used by the application."""
113124
choices = [str(choice) for choice in action.choices] if action.choices else []
@@ -149,10 +160,15 @@ def categorizeItems(
149160
yield actionToJson(action, ItemType.Int)
150161
elif action.choices:
151162
yield actionToJson(action, ItemType.Choice)
163+
164+
elif isinstance(action.type, argparse.FileType) and "w" in action.type._mode:
165+
yield fileActionToJson(action, ItemType.FileWrite)
166+
152167
elif isinstance(action.type, argparse.FileType):
153-
yield actionToJson(action, ItemType.File)
168+
yield fileActionToJson(action, ItemType.File)
154169
elif action.type == Path:
155170
yield actionToJson(action, ItemType.Path)
171+
156172
elif action.type == int:
157173
yield actionToJson(action, ItemType.Int)
158174
elif action.type == float:

cli2gui/tojson/docopt2json.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
"""Generate a dict for docopt.
2-
"""
1+
"""Generate a dict for docopt."""
2+
33
from __future__ import annotations
44

55
import re
@@ -86,7 +86,7 @@ def parse(optionDescription: str) -> tuple[str, str, int, Any, str]:
8686
else:
8787
argcount = 1
8888
if argcount > 0:
89-
matched = re.findall(r"\[default: (.*)\]", description, flags=re.I)
89+
matched = re.findall(r"\[default: (.*)\]", description, flags=re.IGNORECASE)
9090
value = matched[0] if matched else ""
9191
return (short, long, argcount, value, description.strip())
9292

cli2gui/tojson/getopt2json.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
"""Generate a dict for getopt.
2-
"""
1+
"""Generate a dict for getopt."""
2+
33
from __future__ import annotations
44

55
from collections.abc import Callable

cli2gui/types.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
"""Types for cli2gui.
2-
"""
1+
"""Types for cli2gui."""
32

43
from __future__ import annotations
54

@@ -49,6 +48,7 @@ class ItemType(Enum):
4948
RadioGroup = "RadioGroup"
5049
Bool = "Bool"
5150
File = "File"
51+
FileWrite = "FileWrite"
5252
Path = "Path"
5353
Choice = "Choice"
5454
Int = "Int"

documentation/reference/cli2gui/application/application2args.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
## argFormat
1717

18-
[Show source in application2args.py:86](../../../../cli2gui/application/application2args.py#L86)
18+
[Show source in application2args.py:89](../../../../cli2gui/application/application2args.py#L89)
1919

2020
Format the args for the desired parser.
2121

@@ -40,7 +40,7 @@ def argFormat(values: dict[str, Any], argumentParser: str | ParserType) -> Any:
4040

4141
## argparseFormat
4242

43-
[Show source in application2args.py:41](../../../../cli2gui/application/application2args.py#L41)
43+
[Show source in application2args.py:44](../../../../cli2gui/application/application2args.py#L44)
4444

4545
Format args for argparse.
4646

@@ -54,7 +54,7 @@ def argparseFormat(values: dict[str, Any]) -> argparse.Namespace: ...
5454

5555
## clickFormat
5656

57-
[Show source in application2args.py:75](../../../../cli2gui/application/application2args.py#L75)
57+
[Show source in application2args.py:78](../../../../cli2gui/application/application2args.py#L78)
5858

5959
Format args for click.
6060

@@ -68,7 +68,7 @@ def clickFormat(values: dict[str, Any]) -> list[Any]: ...
6868

6969
## docoptFormat
7070

71-
[Show source in application2args.py:64](../../../../cli2gui/application/application2args.py#L64)
71+
[Show source in application2args.py:67](../../../../cli2gui/application/application2args.py#L67)
7272

7373
Format args for docopt.
7474

@@ -82,7 +82,7 @@ def docoptFormat(values: dict[str, Any]) -> dict[str, Any]: ...
8282

8383
## getoptFormat
8484

85-
[Show source in application2args.py:59](../../../../cli2gui/application/application2args.py#L59)
85+
[Show source in application2args.py:62](../../../../cli2gui/application/application2args.py#L62)
8686

8787
Format args for getopt.
8888

@@ -96,7 +96,7 @@ def getoptFormat(values: dict[str, Any]) -> tuple[list[Any], list[Any]]: ...
9696

9797
## optparseFormat
9898

99-
[Show source in application2args.py:50](../../../../cli2gui/application/application2args.py#L50)
99+
[Show source in application2args.py:53](../../../../cli2gui/application/application2args.py#L53)
100100

101101
Format args for optparse.
102102

documentation/reference/cli2gui/decorators.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
## Cli2Gui
1313

14-
[Show source in decorators.py:172](../../../cli2gui/decorators.py#L172)
14+
[Show source in decorators.py:171](../../../cli2gui/decorators.py#L171)
1515

1616
Use this decorator in the function containing the argument parser.
1717
Serialises data to JSON and launches the Cli2Gui application.
@@ -73,7 +73,7 @@ def Cli2Gui(
7373

7474
## Click2Gui
7575

76-
[Show source in decorators.py:109](../../../cli2gui/decorators.py#L109)
76+
[Show source in decorators.py:108](../../../cli2gui/decorators.py#L108)
7777

7878
Use this decorator in the function containing the argument parser.
7979
Serializes data to JSON and launches the Cli2Gui application.
@@ -129,7 +129,7 @@ def Click2Gui(
129129

130130
## createFromParser
131131

132-
[Show source in decorators.py:30](../../../cli2gui/decorators.py#L30)
132+
[Show source in decorators.py:29](../../../cli2gui/decorators.py#L29)
133133

134134
Generate a buildSpec from a parser.
135135

documentation/reference/cli2gui/gui/dearpygui_wrapper.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class DearPyGuiWrapper(AbstractGUI):
3131

3232
### DearPyGuiWrapper().addItemsAndGroups
3333

34-
[Show source in dearpygui_wrapper.py:104](../../../../cli2gui/gui/dearpygui_wrapper.py#L104)
34+
[Show source in dearpygui_wrapper.py:105](../../../../cli2gui/gui/dearpygui_wrapper.py#L105)
3535

3636
Items and groups and return a list of these so we can get values from the dpg widgets.
3737

@@ -77,7 +77,7 @@ def addWidgetFromItem(self, item: Item) -> None: ...
7777

7878
### DearPyGuiWrapper().main
7979

80-
[Show source in dearpygui_wrapper.py:148](../../../../cli2gui/gui/dearpygui_wrapper.py#L148)
80+
[Show source in dearpygui_wrapper.py:149](../../../../cli2gui/gui/dearpygui_wrapper.py#L149)
8181

8282
Run the gui (dpg) with a given buildSpec, quit_callback, and run_callback.
8383

@@ -109,7 +109,7 @@ def main(
109109

110110
### DearPyGuiWrapper().open_menu_item
111111

112-
[Show source in dearpygui_wrapper.py:134](../../../../cli2gui/gui/dearpygui_wrapper.py#L134)
112+
[Show source in dearpygui_wrapper.py:135](../../../../cli2gui/gui/dearpygui_wrapper.py#L135)
113113

114114
Open a menu item.
115115

0 commit comments

Comments
 (0)