diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index f00be31..55d41e7 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -10,10 +10,9 @@ runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Extract branch name + - name: Extract version from tag shell: bash - run: | - echo "##[set-output name=ver;]$(echo ${GITHUB_REF#refs/*/})" + run: echo "ver=${GITHUB_REF#refs/*/}" >> "$GITHUB_OUTPUT" id: extract_name_and_version - run: sed -i 's/0.0.0/'"${{ steps.extract_name_and_version.outputs.ver }}"'/' pyproject.toml - run: head -n 10 pyproject.toml diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..5e5b8ab --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,35 @@ +# AGENTS.md + +## Project overview + +`winregistry` is a single-file Python library (`winregistry.py`) that wraps the Windows `winreg` module with a Pythonic API. It also provides Robot Framework keywords via the `robot` class. The package is Windows-only. + +## Tech stack + +- Python 3.8+ +- Linter/formatter: ruff +- Tests: Robot Framework (`winregistry_tests.robot`) +- Task runner: just (Justfile) +- Package manager: uv + +## After every code change + +Run the following commands and fix any issues before committing: + +```sh +just fmt lint tests +``` + +- `just fmt` — format code with ruff +- `just lint` — lint with ruff (strict rule set, see `pyproject.toml`) +- `just tests` — run Robot Framework tests (requires Windows) + +If tests cannot run (e.g. on macOS/Linux), at minimum run `just fmt lint`. + +## Code style + +- Single source file: all library code lives in `winregistry.py` +- Line length limit: 120 characters +- Use type annotations everywhere +- Follow existing patterns — do not introduce new abstractions without need +- Commit messages: conventional commits (`fix:`, `feat:`, `chore:`, etc.) diff --git a/winregistry.py b/winregistry.py index 3bb0143..a0a25b2 100644 --- a/winregistry.py +++ b/winregistry.py @@ -131,7 +131,7 @@ class RegistryValueData(TypedDict): } KeyInfo = namedtuple("KeyInfo", ["child_keys_count", "values_count", "modified_at"]) -ValueInfo = namedtuple("RawValueInfo", ["data", "type"]) +ValueInfo = namedtuple("ValueInfo", ["data", "type"]) class RegEntity( @@ -815,8 +815,6 @@ def open_value( class robot: # noqa: N801 - ROBOT_LIBRARY_DOC_FORMAT = "ROBOT" - """Robot Framework library for Windows Registry operations. = Usage = @@ -841,6 +839,8 @@ class robot: # noqa: N801 """ + ROBOT_LIBRARY_DOC_FORMAT = "ROBOT" + @staticmethod def registry_key_should_exist( key_name: str, @@ -975,19 +975,16 @@ def create_registry_key( | ${items}= Get Registry Key Sub Keys HKEY_LOCAL_MACHINE\\SOFTWARE | List Should Contain Value ${items} _ROBOT_TESTS_ """ - sub_key_name = None - if "\\" in key_name: - key_name, sub_key_name = key_name.split("\\", maxsplit=1) - if sub_key_name and "\\" in sub_key_name: - sub_key_name, new_key_name = sub_key_name.rsplit("\\", maxsplit=1) + if "\\" not in key_name: + raise ValueError(f"Cannot create a root key: {key_name}") + key_name, sub_key_name = key_name.rsplit("\\", maxsplit=1) with open_key( key_name, - sub_key=sub_key_name, sub_key_ensure=True, sub_key_access=winreg.KEY_ALL_ACCESS, auto_refresh=False, ) as client: - client.create_key(new_key_name) + client.create_key(sub_key_name) @staticmethod def delete_registry_key( @@ -1012,6 +1009,8 @@ def delete_registry_key( | Delete Registry Key HKEY_LOCAL_MACHINE\\SOFTWARE\\_ROBOT_TESTS_\\FOO\\BAR\\BAZ recursive=True | Registry Key Should Not Exist HKEY_LOCAL_MACHINE\\SOFTWARE\\_ROBOT_TESTS_\\FOO\\BAR\\BAZ """ + if "\\" not in key_name: + raise ValueError(f"Cannot delete a root key: {key_name}") key_name, sub_key_name = key_name.rsplit("\\", maxsplit=1) with open_key( key_name,