regkit 0.3.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.
@@ -0,0 +1,53 @@
1
+ # Copilot Instructions for regkit
2
+
3
+ ## Project context
4
+ - `regkit` is a small Python library around Windows Registry operations.
5
+ - Main implementation lives in `src/regkit/`.
6
+ - Tests rely heavily on `tests/fakewinreg.py` to validate behavior on non-Windows and to compare against real `winreg` when available.
7
+
8
+ ## Tech and tooling
9
+ - Python version target: **3.11+**.
10
+ - Packaging/build: `hatchling` (`pyproject.toml`).
11
+ - Environment/dependency workflow uses **uv**.
12
+ - Version management should use `uv version` (e.g. `uv version --bump patch`, `uv version 0.0.1rc1`) instead of manually editing `pyproject.toml`.
13
+ - Type checking uses **mypy strict mode** on `src/regkit`.
14
+ - Linting/import order uses **ruff** with import sorting (`I`).
15
+
16
+ ## Code style and implementation rules
17
+ - Keep changes minimal and focused; do not refactor unrelated code.
18
+ - Preserve existing API shape and naming unless explicitly asked.
19
+ - Prefer explicit type annotations that satisfy strict mypy.
20
+ - Follow existing patterns:
21
+ - `Key` methods raise `KeyError` for missing values/keys where the library API currently does so.
22
+ - Low-level backend exceptions (`FileNotFoundError`, `OSError`, `PermissionError`) are translated only where the current code already translates them.
23
+ - Keep compatibility with both real `winreg` and `tests.fakewinreg` behavior.
24
+ - Avoid platform-specific assumptions that would break tests on non-Windows.
25
+
26
+ ## Testing expectations
27
+ - Run targeted tests first for touched behavior, then broader tests.
28
+ - Typical commands:
29
+ - `uv sync --dev`
30
+ - `pytest`
31
+ - If type-significant code is changed, also run:
32
+ - `uv run mypy src/regkit`
33
+
34
+ ## File-specific guidance
35
+ - `src/regkit/registry.py` is the core behavior surface; changes here should preserve context-manager and handle lifecycle semantics (`open`, `close`, `opened`, `create`, `delete`).
36
+ - `tests/fakewinreg.py` is a behavioral compatibility shim. If production behavior changes, update tests and shim only when required by the requested change.
37
+ - CLI (`src/regkit/cli.py`) is intentionally minimal currently; do not expand it unless requested.
38
+
39
+ ## When adding or changing code
40
+ - Add/adjust tests in `tests/` for any behavior change.
41
+ - Keep imports sorted and remove unused imports.
42
+ - Keep docstrings concise and consistent with existing style.
43
+ - Prefer straightforward implementations over abstractions.
44
+ - Update `CHANGELOG.md` for release-worthy changes (including `rc`/pre-release tags).
45
+ - Keep changelog entries concise and user-facing; avoid listing individual development bug-fix details.
46
+
47
+ ## Things to double-check before finishing
48
+ - No accidental public API breaks in `regkit.__init__` exports.
49
+ - Tests pass locally.
50
+ - New code passes strict typing.
51
+ - Run `uvx ruff check` and `uvx ruff format --check` before pushing.
52
+ - For any version bump via `uv version`, ensure `uv.lock` is updated, committed, and pushed with the release changes.
53
+ - No unrelated formatting-only churn.
@@ -0,0 +1,53 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+ - main
8
+ tags:
9
+ - "v*"
10
+ pull_request:
11
+
12
+ jobs:
13
+ test:
14
+ name: ${{ matrix.os }} / py${{ matrix.python-version }}
15
+ runs-on: ${{ matrix.os }}
16
+ strategy:
17
+ fail-fast: false
18
+ matrix:
19
+ os: [ubuntu-latest, windows-latest]
20
+ python-version: ["3.11", "3.12", "3.13", "3.14"]
21
+ exclude:
22
+ - os: windows-latest
23
+ python-version: "3.11"
24
+ - os: windows-latest
25
+ python-version: "3.12"
26
+ - os: windows-latest
27
+ python-version: "3.13"
28
+
29
+ steps:
30
+ - name: Checkout
31
+ uses: actions/checkout@v4
32
+
33
+ - name: Install uv
34
+ uses: astral-sh/setup-uv@v7
35
+ with:
36
+ python-version: ${{ matrix.python-version }}
37
+ enable-cache: true
38
+
39
+ - name: Lint (ruff)
40
+ run: uvx ruff check
41
+
42
+ - name: Format check (ruff)
43
+ run: uvx ruff format --check
44
+
45
+ - name: Sync dependencies
46
+ run: uv sync --locked --dev
47
+
48
+ - name: Run tests
49
+ run: uv run pytest
50
+
51
+ - name: Type check (mypy)
52
+ if: runner.os == 'Windows'
53
+ run: uv run mypy src/regkit
@@ -0,0 +1,59 @@
1
+ name: Docs
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+ - main
8
+ workflow_dispatch:
9
+
10
+ permissions:
11
+ contents: read
12
+ pages: write
13
+ id-token: write
14
+
15
+ concurrency:
16
+ group: pages
17
+ cancel-in-progress: true
18
+
19
+ jobs:
20
+ build:
21
+ runs-on: ubuntu-latest
22
+
23
+ steps:
24
+ - name: Checkout
25
+ uses: actions/checkout@v4
26
+
27
+ - name: Set up Python
28
+ uses: actions/setup-python@v5
29
+ with:
30
+ python-version: "3.12"
31
+
32
+ - name: Install uv
33
+ uses: astral-sh/setup-uv@v7
34
+ with:
35
+ python-version: "3.12"
36
+ enable-cache: true
37
+
38
+ - name: Sync docs dependencies
39
+ run: uv sync --group docs
40
+
41
+ - name: Build docs
42
+ run: uv run mkdocs build --strict
43
+
44
+ - name: Upload Pages artifact
45
+ uses: actions/upload-pages-artifact@v3
46
+ with:
47
+ path: site
48
+
49
+ deploy:
50
+ environment:
51
+ name: github-pages
52
+ url: ${{ steps.deployment.outputs.page_url }}
53
+ runs-on: ubuntu-latest
54
+ needs: build
55
+
56
+ steps:
57
+ - name: Deploy to GitHub Pages
58
+ id: deployment
59
+ uses: actions/deploy-pages@v4
@@ -0,0 +1,85 @@
1
+ name: Publish
2
+
3
+ on:
4
+ workflow_run:
5
+ workflows:
6
+ - CI
7
+ types:
8
+ - completed
9
+
10
+ jobs:
11
+ detect-tag:
12
+ if: github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'push'
13
+ runs-on: ubuntu-latest
14
+ outputs:
15
+ publish_tag: ${{ steps.tag.outputs.publish_tag }}
16
+ commit_sha: ${{ steps.sha.outputs.commit_sha }}
17
+
18
+ steps:
19
+ - name: Checkout
20
+ uses: actions/checkout@v4
21
+ with:
22
+ fetch-depth: 0
23
+
24
+ - name: Capture CI commit SHA
25
+ id: sha
26
+ run: echo "commit_sha=${{ github.event.workflow_run.head_sha }}" >> "$GITHUB_OUTPUT"
27
+
28
+ - name: Detect version tag at CI commit
29
+ id: tag
30
+ run: |
31
+ git fetch --tags --force
32
+ TAG=$(git tag --points-at "${{ github.event.workflow_run.head_sha }}" | grep '^v' | head -n 1 || true)
33
+ echo "publish_tag=$TAG" >> "$GITHUB_OUTPUT"
34
+
35
+ publish:
36
+ needs: detect-tag
37
+ if: needs.detect-tag.outputs.publish_tag != ''
38
+ runs-on: ubuntu-latest
39
+ permissions:
40
+ id-token: write
41
+ contents: write
42
+
43
+ environment:
44
+ name: pypi
45
+
46
+ steps:
47
+ - name: Checkout
48
+ uses: actions/checkout@v4
49
+ with:
50
+ ref: ${{ needs.detect-tag.outputs.commit_sha }}
51
+
52
+ - name: Install uv
53
+ uses: astral-sh/setup-uv@v7
54
+ with:
55
+ python-version: "3.12"
56
+ enable-cache: true
57
+
58
+ - name: Build distributions
59
+ run: uv build
60
+
61
+ - name: Verify built artifacts
62
+ run: ls -la dist
63
+
64
+ - name: Publish to PyPI
65
+ run: uv publish
66
+
67
+ - name: Create GitHub Release
68
+ env:
69
+ GH_TOKEN: ${{ github.token }}
70
+ TAG: ${{ needs.detect-tag.outputs.publish_tag }}
71
+ run: |
72
+ gh release view "$TAG" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1 && exit 0
73
+
74
+ PRERELEASE_FLAG=""
75
+ case "$TAG" in
76
+ *a*|*b*|*rc*|*dev*) PRERELEASE_FLAG="--prerelease" ;;
77
+ esac
78
+
79
+ gh release create "$TAG" dist/* \
80
+ --repo "$GITHUB_REPOSITORY" \
81
+ --verify-tag \
82
+ --title "$TAG" \
83
+ --generate-notes \
84
+ --notes "See CHANGELOG.md for curated release details." \
85
+ $PRERELEASE_FLAG
@@ -0,0 +1,66 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.pyo
5
+ *.pyd
6
+ *.pyc
7
+
8
+ # Distribution / packaging
9
+ .Python
10
+ build/
11
+ dist/
12
+ site/
13
+ *.egg-info/
14
+ .eggs/
15
+ *.egg
16
+
17
+ # Installer logs
18
+ pip-log.txt
19
+ pip-delete-this-directory.txt
20
+
21
+ # Unit test / coverage reports
22
+ htmlcov/
23
+ .tox/
24
+ .nox/
25
+ .coverage
26
+ .coverage.*
27
+ .cache
28
+ nosetests.xml
29
+ coverage.xml
30
+ *.cover
31
+ *.py,cover
32
+ .hypothesis/
33
+ .pytest_cache/
34
+
35
+ # Jupyter Notebook
36
+ .ipynb_checkpoints
37
+
38
+ # VS Code
39
+ .vscode/
40
+
41
+ # Environments
42
+ .env
43
+ .venv
44
+ env/
45
+ venv/
46
+ ENV/
47
+
48
+ # mypy
49
+ .mypy_cache/
50
+ .dmypy.json
51
+
52
+ # Ruff
53
+ .ruff_cache/
54
+
55
+ # Other
56
+ *.log
57
+ *.pot
58
+ *.mo
59
+ *.swp
60
+ *.swo
61
+
62
+ # Mac
63
+ .DS_Store
64
+
65
+ # Windows
66
+ Thumbs.db
@@ -0,0 +1 @@
1
+ 3.14
@@ -0,0 +1,78 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## Unreleased
6
+
7
+ No tracked entries yet.
8
+
9
+ ## 0.3.0 - 2026-02-24
10
+
11
+ Minor release for package and project rename.
12
+
13
+ - Renamed package distribution from `winregkit` to `regkit`.
14
+ - Renamed source package path from `src/winregkit` to `src/regkit`.
15
+ - Updated docs, CI, tests, and project metadata references to `regkit`.
16
+ - Updated repository/docs URLs to `kristjanvalur/regkit`.
17
+
18
+ ## 0.2.1 - 2026-02-22
19
+
20
+ Patch release refining canonical path identity semantics.
21
+
22
+ - Canonical comparison/hashing now always derives the root label from the root handle.
23
+ - Root-node lexical labels are normalized away for canonical identity (for example, `Key(100, "foo")` and `Key(100, "bar")` now compare/hash the same at root level).
24
+
25
+ ## 0.2.0 - 2026-02-22
26
+
27
+ Minor release extending pathlib-style key path ergonomics.
28
+
29
+ - Added `Key.parent` and `Key.parents()` for lexical ancestor navigation.
30
+ - Added `Key.parts` plus `Key.from_parts(...)` / `Key.from_path(...)` for path round-tripping.
31
+ - Simplified rooted-key construction internals (`from_parts(...)` now uses direct rooted construction).
32
+ - **Breaking:** `Key.name` now returns only the final lexical segment; internal full relative path storage is kept private.
33
+ - Added `Key.iterdir()`, `Key.joinpath(...)`, `/` operator composition, and `Key.walk(...)` traversal (`os.walk`-like).
34
+
35
+ ## 0.1.3 - 2026-02-22
36
+
37
+ Patch release adding traversal and pathlib-style path ergonomics.
38
+
39
+ - Added `Key.walk(...)` with `os.walk`-like semantics for key-tree traversal.
40
+ - Added `Key.iterdir()` as a pathlib-style alias for subkey iteration.
41
+ - Added `Key.joinpath(...)` and `/` operator support for key path composition.
42
+ - Expanded README method reference and examples for new traversal/path APIs.
43
+
44
+ ## 0.1.2 - 2026-02-21
45
+
46
+ Patch release adding typing metadata for downstream type checkers.
47
+
48
+ - Added `py.typed` marker to declare inline typing support in `regkit` (PEP 561).
49
+
50
+ ## 0.1.1 - 2026-02-21
51
+
52
+ Patch release to validate automated GitHub Release notes.
53
+
54
+ - Publish workflow now uses GitHub-generated release notes for tag releases.
55
+
56
+ ## 0.1.0 - 2026-02-21
57
+
58
+ First stable 0.1 release.
59
+
60
+ - Finalizes the 0.1 API surface for key traversal, typed value operations, and path-based key construction.
61
+ - Strengthens test coverage across fake and real backends, with backend-selective test flags for CI and local runs.
62
+ - Enforces formatting checks in CI alongside linting, tests, and Windows mypy checks.
63
+
64
+ ## 0.1.0rc2 - 2026-02-21
65
+
66
+ Second release candidate for the 0.1 line.
67
+
68
+ - Publish workflow now creates a basic GitHub Release alongside PyPI publication.
69
+ - Release automation now avoids duplicate publish attempts from branch-triggered CI runs.
70
+
71
+ ## 0.1.0rc1 - 2026-02-21
72
+
73
+ Initial release candidate for the 0.1 line.
74
+
75
+ - API surface refined for clearer typed value access and iteration naming.
76
+ - Cross-platform test strategy stabilized for real Windows `winreg` and fake backend coverage.
77
+ - CI and publish workflows aligned around `uv` tooling with release-tag-driven publishing.
78
+ - Project release/version workflow standardized on `uv version`.
regkit-0.3.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Kristján Valur Jónsson
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.
regkit-0.3.0/PKG-INFO ADDED
@@ -0,0 +1,178 @@
1
+ Metadata-Version: 2.4
2
+ Name: regkit
3
+ Version: 0.3.0
4
+ Summary: A modern, pythonic interface to the Windows registry.
5
+ Project-URL: Homepage, https://github.com/kristjanvalur/regkit
6
+ Project-URL: Repository, https://github.com/kristjanvalur/regkit
7
+ Project-URL: Documentation, https://kristjanvalur.github.io/regkit/
8
+ Project-URL: Changelog, https://github.com/kristjanvalur/regkit/blob/main/CHANGELOG.md
9
+ License-File: LICENSE
10
+ Classifier: Operating System :: Microsoft :: Windows
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Programming Language :: Python :: 3.14
16
+ Requires-Python: >=3.11
17
+ Description-Content-Type: text/markdown
18
+
19
+ # regkit
20
+
21
+ [![CI](https://github.com/kristjanvalur/regkit/actions/workflows/ci.yml/badge.svg)](https://github.com/kristjanvalur/regkit/actions/workflows/ci.yml)
22
+
23
+ A modern, pythonic interface to the Windows registry.
24
+
25
+ ## Introduction
26
+
27
+ Python comes with `winreg` for registry operations, but it is a thin wrapper over
28
+ Win32 APIs and can be cumbersome for day-to-day usage.
29
+
30
+ `regkit` provides a higher-level, object-oriented interface with simple tree
31
+ navigation, dict-like value access, and context-manager support.
32
+
33
+ ## Features
34
+ - Easy-to-use API for reading and writing Windows Registry keys
35
+ - Python 3.11+
36
+ - Windows platform
37
+ - MIT License
38
+ - Managed and built with [uv](https://github.com/astral-sh/uv)
39
+
40
+
41
+ ## Installation
42
+
43
+ ```sh
44
+ pip install regkit
45
+ ```
46
+
47
+ Or the equivalent command in your preferred package manager.
48
+
49
+ ## Usage
50
+
51
+ ### Library
52
+ ```python
53
+ from regkit import current_user
54
+ import winreg
55
+
56
+
57
+ # open for read
58
+ with current_user.subkey("Software", "MyApp").open() as key:
59
+ print(key["name"])
60
+ print(key.get("missing", "default"))
61
+
62
+ # open for write (subkeys can be passed directly to open as a convenience)
63
+ with current_user.open("Software", "MyApp", write=True) as key:
64
+ key["name"] = "regkit"
65
+ key["enabled"] = 1
66
+
67
+ # pathlib-style path concatenation is also supported via "/"
68
+ with (current_user / "Software" / "MyApp").open(write=True) as key:
69
+ key["theme"] = "dark"
70
+
71
+ # create/open for write (create is shorthand for open(create=True, write=True))
72
+ with current_user.create("Software", "MyApp") as key:
73
+ key["name"] = "regkit"
74
+ key["enabled"] = 1
75
+
76
+ # the Key object provides dict access and values can be iterated over:
77
+ with current_user.open("Software", "MyApp") as key:
78
+ for name, value in key.items():
79
+ print(name, value)
80
+
81
+ # the underlying type of a value can be retrieved, and a custom type can be
82
+ # set, overriding default conversions:
83
+ with current_user.open("Software", "MyApp", write=True) as key:
84
+ value, value_type = key.get_typed("enabled")
85
+ print(value, value_type)
86
+
87
+ key.set_typed("payload", b"\x00\x01\x02", winreg.REG_BINARY)
88
+
89
+ # existence checks are available on keys:
90
+ app_key = current_user.subkey("Software", "MyApp")
91
+ print(app_key.exists())
92
+
93
+ ```
94
+
95
+ `subkey(...)` is optional convenience for pre-building a path. You can either
96
+ chain with `subkey(...)` first, or pass subkeys directly to `open(...)` / `create(...)`.
97
+
98
+ ### Typical workflow
99
+ - Use root factories (`current_user`, `local_machine`, etc.)
100
+ - Navigate with `subkey(...)` (optional)
101
+ - Open with `open(...)` or `create(...)` and a context manager
102
+ - Use dict-style value access (`key[name]`, `key[name] = value`)
103
+ - Use `get_typed` / `set_typed` only when explicit registry types are needed
104
+
105
+ ### Using registry paths
106
+ `Key` supports constructing and round-tripping full registry paths.
107
+
108
+ ```python
109
+ from regkit import Key
110
+
111
+ # Construct from explicit path parts
112
+ key = Key.from_parts(("HKCU", "Software", "MyApp"))
113
+
114
+ # Construct from a full path string (either HKCU or HKEY_CURRENT_USER style)
115
+ same_key = Key.from_path(r"HKEY_CURRENT_USER\Software\MyApp")
116
+
117
+ # Read parts back (root token + subkey parts)
118
+ assert key.parts == ("HKCU", "Software", "MyApp")
119
+
120
+ # name is the final lexical segment
121
+ assert key.name == "MyApp"
122
+
123
+ # parents() returns lexical ancestors from nearest parent upward
124
+ assert [ancestor.name for ancestor in key.parents()] == ["Software", "HKCU"]
125
+ ```
126
+
127
+ Use `from_parts(...)` when you already have tokenized components, and
128
+ `from_path(...)` when parsing user-provided registry path strings.
129
+
130
+ ### `Key` methods at a glance
131
+ - `subkey(*parts)`: build a child key path without opening it
132
+ - `open(...)`: return a new opened key for read/write access
133
+ - `create(*parts)`: shorthand for creating/opening a key for writing
134
+ - `exists()`: check whether a key exists
135
+ - `walk(...)`: traverse a key tree, yielding `(key, subkey_names, value_names)` (similar to `os.walk()`)
136
+ - `keys()`, `values()`, `items()`: iterate value names, values, or `(name, value)` pairs
137
+ - `name`: final lexical path segment for this key
138
+ - `parts`: tuple of key path components, including root token when present
139
+ - `parent`: lexical parent key (or `None` at registry root)
140
+ - `parents()`: tuple of lexical ancestors from immediate parent up to root
141
+ - `get(name, ...)`: read a value with fallback default
142
+ - `get_typed(...)` / `set_typed(...)`: read/write values with explicit registry type
143
+ - `value_del(name)` or `del key[name]`: delete a value
144
+ - `delete(...)`: delete a key (optionally recursively)
145
+ - `as_dict()` / `from_dict(data)`: export/import a subtree structure
146
+
147
+ ### Default value name
148
+ The registry's default (unnamed) value is represented by the empty string (`""`).
149
+
150
+ - Iteration methods (`items()`, `items_typed()`, `keys()`) return `""` for the default value name.
151
+ - Set/delete helpers also accept `None` as an equivalent.
152
+
153
+ ## Development
154
+
155
+ This project uses the [uv](https://docs.astral.sh/uv/) package manager.
156
+
157
+ - Install uv, e.g. using `pip install uv`
158
+
159
+ - Install dev dependencies:
160
+ ```sh
161
+ uv sync --dev
162
+ ```
163
+ - Run tests:
164
+ ```sh
165
+ uv run pytest
166
+ ```
167
+
168
+ - Build docs:
169
+ ```sh
170
+ uv sync --group docs
171
+ uv run mkdocs build --strict
172
+ ```
173
+
174
+ ## License
175
+ MIT License. See `LICENSE` for details.
176
+
177
+ ## Changelog
178
+ See `CHANGELOG.md` for release history and policy.