pydmvl 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.
- pydmvl-0.1.0/.github/pull_request_template.md +18 -0
- pydmvl-0.1.0/.github/workflows/ci.yml +51 -0
- pydmvl-0.1.0/.github/workflows/publish.yml +46 -0
- pydmvl-0.1.0/.github/workflows/testpypi.yml +47 -0
- pydmvl-0.1.0/.gitignore +26 -0
- pydmvl-0.1.0/AGENTS.md +147 -0
- pydmvl-0.1.0/LICENSE +21 -0
- pydmvl-0.1.0/PKG-INFO +149 -0
- pydmvl-0.1.0/README.md +116 -0
- pydmvl-0.1.0/pyproject.toml +74 -0
- pydmvl-0.1.0/specs/0001-auth.md +113 -0
- pydmvl-0.1.0/specs/0002-documents.md +121 -0
- pydmvl-0.1.0/specs/0003-payments.md +73 -0
- pydmvl-0.1.0/specs/0004-client-api.md +96 -0
- pydmvl-0.1.0/specs/0005-api-surface.md +95 -0
- pydmvl-0.1.0/specs/0006-counters-read.md +83 -0
- pydmvl-0.1.0/src/pydmvl/__init__.py +38 -0
- pydmvl-0.1.0/src/pydmvl/_api.py +64 -0
- pydmvl-0.1.0/src/pydmvl/_logging.py +55 -0
- pydmvl-0.1.0/src/pydmvl/aclient.py +81 -0
- pydmvl-0.1.0/src/pydmvl/auth.py +32 -0
- pydmvl-0.1.0/src/pydmvl/client.py +82 -0
- pydmvl-0.1.0/src/pydmvl/errors.py +22 -0
- pydmvl-0.1.0/src/pydmvl/models.py +228 -0
- pydmvl-0.1.0/src/pydmvl/py.typed +0 -0
- pydmvl-0.1.0/tests/conftest.py +49 -0
- pydmvl-0.1.0/tests/fixtures/authentication.json +74 -0
- pydmvl-0.1.0/tests/fixtures/authentication_error.json +4 -0
- pydmvl-0.1.0/tests/test_async.py +34 -0
- pydmvl-0.1.0/tests/test_auth.py +120 -0
- pydmvl-0.1.0/tests/test_client.py +57 -0
- pydmvl-0.1.0/tests/test_documents.py +97 -0
- pydmvl-0.1.0/tests/test_live.py +29 -0
- pydmvl-0.1.0/tests/test_logging.py +41 -0
- pydmvl-0.1.0/tests/test_package.py +50 -0
- pydmvl-0.1.0/tests/test_payments.py +83 -0
- pydmvl-0.1.0/tests/test_transport.py +66 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
|
|
3
|
+
<!-- What does this PR change? Link the feature spec: specs/NNNN-slug.md -->
|
|
4
|
+
|
|
5
|
+
## Spec-driven checklist
|
|
6
|
+
|
|
7
|
+
- [ ] Feature spec exists (`specs/NNNN-slug.md`) and has status `approved`
|
|
8
|
+
- [ ] Tests written before implementation (TDD), failing first
|
|
9
|
+
- [ ] API responses covered by synthetic fixtures (no live API in unit tests)
|
|
10
|
+
- [ ] Live tests stay behind the `live` marker
|
|
11
|
+
- [ ] `ruff check .`, `ruff format --check .`, `mypy`, `pytest -m "not live"` pass
|
|
12
|
+
- [ ] Skeptic review completed: verdict `APPROVED` (or `NITS` only)
|
|
13
|
+
- [ ] No secrets committed (credentials, password hashes); placeholders only
|
|
14
|
+
- [ ] Logs never contain credentials or the password hash
|
|
15
|
+
|
|
16
|
+
## Commit style
|
|
17
|
+
|
|
18
|
+
Conventional Commits (`feat:`, `fix:`, `docs:`, `test:`, `chore:`, `refactor:`).
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
concurrency:
|
|
9
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
10
|
+
cancel-in-progress: true
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
strategy:
|
|
16
|
+
fail-fast: false
|
|
17
|
+
matrix:
|
|
18
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
- uses: actions/setup-python@v5
|
|
22
|
+
with:
|
|
23
|
+
python-version: ${{ matrix.python-version }}
|
|
24
|
+
- name: Install
|
|
25
|
+
run: |
|
|
26
|
+
python -m pip install --upgrade pip
|
|
27
|
+
pip install -e ".[dev]"
|
|
28
|
+
- name: Ruff lint
|
|
29
|
+
run: ruff check .
|
|
30
|
+
- name: Ruff format
|
|
31
|
+
run: ruff format --check .
|
|
32
|
+
- name: Mypy
|
|
33
|
+
run: mypy
|
|
34
|
+
- name: Tests
|
|
35
|
+
run: pytest -m "not live"
|
|
36
|
+
|
|
37
|
+
build:
|
|
38
|
+
runs-on: ubuntu-latest
|
|
39
|
+
steps:
|
|
40
|
+
- uses: actions/checkout@v4
|
|
41
|
+
- uses: actions/setup-python@v5
|
|
42
|
+
with:
|
|
43
|
+
python-version: "3.12"
|
|
44
|
+
- name: Install
|
|
45
|
+
run: |
|
|
46
|
+
python -m pip install --upgrade pip
|
|
47
|
+
pip install -e ".[release]"
|
|
48
|
+
- name: Build
|
|
49
|
+
run: python -m build
|
|
50
|
+
- name: Twine check
|
|
51
|
+
run: twine check dist/*
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Publishes to PyPI via Trusted Publishing (OIDC) when a GitHub Release is published.
|
|
2
|
+
name: Publish
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
release:
|
|
6
|
+
types: [published]
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
build:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- uses: actions/setup-python@v5
|
|
17
|
+
with:
|
|
18
|
+
python-version: "3.12"
|
|
19
|
+
- name: Install
|
|
20
|
+
run: |
|
|
21
|
+
python -m pip install --upgrade pip
|
|
22
|
+
pip install -U "build>=1.2" "twine>=5"
|
|
23
|
+
- name: Build
|
|
24
|
+
run: python -m build
|
|
25
|
+
- name: Twine check
|
|
26
|
+
run: twine check dist/*
|
|
27
|
+
- name: Upload artifacts
|
|
28
|
+
uses: actions/upload-artifact@v4
|
|
29
|
+
with:
|
|
30
|
+
name: dist
|
|
31
|
+
path: dist/
|
|
32
|
+
|
|
33
|
+
publish:
|
|
34
|
+
needs: build
|
|
35
|
+
runs-on: ubuntu-latest
|
|
36
|
+
environment: pypi
|
|
37
|
+
permissions:
|
|
38
|
+
id-token: write
|
|
39
|
+
steps:
|
|
40
|
+
- name: Download artifacts
|
|
41
|
+
uses: actions/download-artifact@v4
|
|
42
|
+
with:
|
|
43
|
+
name: dist
|
|
44
|
+
path: dist/
|
|
45
|
+
- name: Publish to PyPI
|
|
46
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Publishes to TestPyPI via Trusted Publishing (OIDC); manual dry run before a release.
|
|
2
|
+
name: TestPyPI
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
workflow_dispatch:
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
build:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
- uses: actions/setup-python@v5
|
|
16
|
+
with:
|
|
17
|
+
python-version: "3.12"
|
|
18
|
+
- name: Install
|
|
19
|
+
run: |
|
|
20
|
+
python -m pip install --upgrade pip
|
|
21
|
+
pip install -U "build>=1.2" "twine>=5"
|
|
22
|
+
- name: Build
|
|
23
|
+
run: python -m build
|
|
24
|
+
- name: Twine check
|
|
25
|
+
run: twine check dist/*
|
|
26
|
+
- name: Upload artifacts
|
|
27
|
+
uses: actions/upload-artifact@v4
|
|
28
|
+
with:
|
|
29
|
+
name: dist
|
|
30
|
+
path: dist/
|
|
31
|
+
|
|
32
|
+
publish:
|
|
33
|
+
needs: build
|
|
34
|
+
runs-on: ubuntu-latest
|
|
35
|
+
environment: testpypi
|
|
36
|
+
permissions:
|
|
37
|
+
id-token: write
|
|
38
|
+
steps:
|
|
39
|
+
- name: Download artifacts
|
|
40
|
+
uses: actions/download-artifact@v4
|
|
41
|
+
with:
|
|
42
|
+
name: dist
|
|
43
|
+
path: dist/
|
|
44
|
+
- name: Publish to TestPyPI
|
|
45
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
46
|
+
with:
|
|
47
|
+
repository-url: https://test.pypi.org/legacy/
|
pydmvl-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
dist/
|
|
6
|
+
build/
|
|
7
|
+
|
|
8
|
+
# Environments
|
|
9
|
+
.venv/
|
|
10
|
+
venv/
|
|
11
|
+
|
|
12
|
+
# Tooling caches
|
|
13
|
+
.mypy_cache/
|
|
14
|
+
.pytest_cache/
|
|
15
|
+
.ruff_cache/
|
|
16
|
+
.coverage
|
|
17
|
+
coverage.xml
|
|
18
|
+
htmlcov/
|
|
19
|
+
|
|
20
|
+
# Local secrets (never commit)
|
|
21
|
+
*.local.json
|
|
22
|
+
|
|
23
|
+
# Editors / OS
|
|
24
|
+
.DS_Store
|
|
25
|
+
.idea/
|
|
26
|
+
.vscode/
|
pydmvl-0.1.0/AGENTS.md
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# AGENTS.md — pydmvl
|
|
2
|
+
|
|
3
|
+
Working agreement for humans and AI agents contributing to this repository.
|
|
4
|
+
|
|
5
|
+
## 1. Role in the group
|
|
6
|
+
|
|
7
|
+
This repository is part of a group of projects that build a self-hosted
|
|
8
|
+
control stack for a residential utility account ("Domovladelets" / homeowner):
|
|
9
|
+
|
|
10
|
+
| Repository | Role | Visibility | Language |
|
|
11
|
+
|---|---|---|---|
|
|
12
|
+
| `pydmvl` (this repo) | Python client for a homeowner account API | public | English |
|
|
13
|
+
| `dmvl-ha-integration` | Home Assistant custom integration, consumes `pydmvl` from PyPI | public | English |
|
|
14
|
+
|
|
15
|
+
`pydmvl` is the producer: it encapsulates authentication and the account data
|
|
16
|
+
models. The Home Assistant integration depends on `pydmvl` as an external
|
|
17
|
+
package, does not duplicate client logic, and performs no authentication of its
|
|
18
|
+
own. Group identity: code name `dmvl`, package/import `pydmvl`, Home Assistant
|
|
19
|
+
domain `dmvl`.
|
|
20
|
+
|
|
21
|
+
## 2. Language
|
|
22
|
+
|
|
23
|
+
All repository text is English: code, comments, docstrings, documentation,
|
|
24
|
+
commit messages, and review notes. The only exceptions are a short bilingual
|
|
25
|
+
intro and disclaimer in this repository's `README.md` (the app audience is
|
|
26
|
+
Russian-speaking) and runtime translation of user-facing strings (e.g.
|
|
27
|
+
`translations/ru.json`) in the consumer integration, not in this library.
|
|
28
|
+
|
|
29
|
+
## 3. Stack and commands
|
|
30
|
+
|
|
31
|
+
- Python >= 3.11, hatchling, src-layout (`src/pydmvl/`), plain top-level
|
|
32
|
+
package (no PEP 420 namespace).
|
|
33
|
+
- Runtime dependency: `httpx>=0.27`; dev tools: pytest, pytest-asyncio, ruff,
|
|
34
|
+
mypy (strict for `src/`).
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
python3 -m venv .venv && .venv/bin/pip install -e ".[dev]"
|
|
38
|
+
.venv/bin/ruff check .
|
|
39
|
+
.venv/bin/ruff format --check .
|
|
40
|
+
.venv/bin/mypy
|
|
41
|
+
.venv/bin/pytest -m "not live"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Live tests (real account, real credentials) carry the `live` marker and are run
|
|
45
|
+
manually only: `.venv/bin/pytest -m live`. Credentials come from the
|
|
46
|
+
environment: `DMVL_USERNAME`, `DMVL_PASSWORD`.
|
|
47
|
+
|
|
48
|
+
## 4. Spec-driven development (SDD)
|
|
49
|
+
|
|
50
|
+
- Every feature starts with a spec in `specs/NNNN-slug.md` (zero-padded number,
|
|
51
|
+
short slug). Status lifecycle: `draft → approved → implemented →
|
|
52
|
+
superseded`.
|
|
53
|
+
- Implementation without an `approved` spec is forbidden. Specs marked
|
|
54
|
+
"implementation pending research" must not be implemented until they move to
|
|
55
|
+
`approved`.
|
|
56
|
+
- Spec template: Summary / Motivation / Requirements (MUST/SHOULD) / Design /
|
|
57
|
+
API / Test plan / Acceptance criteria / Out of scope / Status.
|
|
58
|
+
- Moving a spec from `draft` to `approved` is a reviewable change (PR or a
|
|
59
|
+
recorded decision in the conversation).
|
|
60
|
+
|
|
61
|
+
## 5. Test-driven development (TDD)
|
|
62
|
+
|
|
63
|
+
- Tests are written first and must fail before the implementation exists.
|
|
64
|
+
- API responses are covered by synthetic fixtures via an httpx mock transport;
|
|
65
|
+
unit tests never touch the real API.
|
|
66
|
+
- A merge requires a fully green run of all gate commands (§3).
|
|
67
|
+
|
|
68
|
+
## 6. Git process
|
|
69
|
+
|
|
70
|
+
- Default branch: `master`. Direct commits to `master` are forbidden (the
|
|
71
|
+
initial scaffold import is the only exception).
|
|
72
|
+
- One feature = one branch `feat/NNNN-slug` containing the spec, the tests, and
|
|
73
|
+
the implementation together.
|
|
74
|
+
- Commit messages follow Conventional Commits (`feat:`, `fix:`, `docs:`,
|
|
75
|
+
`test:`, `chore:`, `refactor:`).
|
|
76
|
+
- Merge into `master` only after the review gate (§7), squash-merge, then delete
|
|
77
|
+
the feature branch.
|
|
78
|
+
|
|
79
|
+
## 7. Review gate (mandatory)
|
|
80
|
+
|
|
81
|
+
A feature branch may merge into `master` only when both hold:
|
|
82
|
+
|
|
83
|
+
1. A full local run is green (§3/§5).
|
|
84
|
+
2. A skeptic review returns no `BLOCKING` findings. Invoke the skeptic agent
|
|
85
|
+
(Task tool, definition in `.kilo/agent/skeptic.md`) with a prompt such as:
|
|
86
|
+
|
|
87
|
+
> Review branch `feat/NNNN-slug` against its spec `specs/NNNN-slug.md`
|
|
88
|
+
> (diff base: `master`). Follow the checklist in `.kilo/agent/skeptic.md`
|
|
89
|
+
> and answer in the verdict format (`BLOCKING: ...` / `NITS: ...` /
|
|
90
|
+
> `APPROVED`).
|
|
91
|
+
|
|
92
|
+
`BLOCKING` findings forbid the merge; fix and re-review.
|
|
93
|
+
|
|
94
|
+
## 8. Secrets and safety
|
|
95
|
+
|
|
96
|
+
- Account credentials and account data are confidential: never include them in
|
|
97
|
+
this public repository — in code, docs, examples, fixtures, or commit
|
|
98
|
+
history. This covers logins, passwords, tokens (including the password hash
|
|
99
|
+
sent by the API), full names, addresses, personal account numbers, object and
|
|
100
|
+
payment identifiers, and receipt links. Use synthetic placeholders
|
|
101
|
+
(`<account>`, `<password>`); real values live only in environment variables
|
|
102
|
+
or gitignored `*.local.json` files.
|
|
103
|
+
- Authentication material is sent as request query parameters (an observed
|
|
104
|
+
property of the API). Never log request URLs, credentials, or the password
|
|
105
|
+
hash. The library installs a redaction filter on the `httpx` logger so
|
|
106
|
+
dependency-emitted request-URL records have `login` and `hash` replaced; do
|
|
107
|
+
not remove it.
|
|
108
|
+
- TLS verification defaults to `False` (`DEFAULT_VERIFY`) because the service
|
|
109
|
+
serves an incomplete certificate chain; the `verify` argument stays
|
|
110
|
+
overridable and the rationale is documented in the README and spec 0004 R8.
|
|
111
|
+
Do not remove the argument or change the default without updating both.
|
|
112
|
+
|
|
113
|
+
## 9. Publication policy (public repository)
|
|
114
|
+
|
|
115
|
+
- Do not copy text or material from non-public sources into this repo.
|
|
116
|
+
- Public documentation is an English description of observed API behavior.
|
|
117
|
+
Cite only this repository's own specs; do not name non-public or third-party
|
|
118
|
+
sources, and do not state or claim how the API was determined.
|
|
119
|
+
- Keep the disclaimers in place (unofficial, not affiliated with the service
|
|
120
|
+
operator, own account only).
|
|
121
|
+
|
|
122
|
+
## 10. Release runbook (new versions)
|
|
123
|
+
|
|
124
|
+
Ship a release only from a green `master`:
|
|
125
|
+
|
|
126
|
+
1. Bump the version in one change: `pyproject.toml` `[project].version` and
|
|
127
|
+
`src/pydmvl/__init__.py` `__version__`. A test enforces that they match; no
|
|
128
|
+
other source or test file pins the version. SemVer; `0.x` while the API is
|
|
129
|
+
unstable.
|
|
130
|
+
2. Feature branch `feat/NNNN-slug` (spec + tests + code **and the version
|
|
131
|
+
bump**), gate (§3), skeptic (§7), squash-merge into `master`.
|
|
132
|
+
3. Push `master`.
|
|
133
|
+
4. Create a GitHub Release with tag `vX.Y.Z` equal to the version. Publishing
|
|
134
|
+
the release triggers `publish.yml`, which builds and uploads to PyPI via
|
|
135
|
+
Trusted Publishing. A plain tag push does **not** publish.
|
|
136
|
+
5. Run the `testpypi.yml` dry run for every packaging/metadata change, and
|
|
137
|
+
always before the first production release.
|
|
138
|
+
6. Never reuse a published version; if a release is wrong, bump the patch
|
|
139
|
+
version and repeat. Verify with `pip install pydmvl==X.Y.Z`.
|
|
140
|
+
7. Keep the runtime dependency floor compatible with Home Assistant's pinned
|
|
141
|
+
`httpx`.
|
|
142
|
+
|
|
143
|
+
## 11. References
|
|
144
|
+
|
|
145
|
+
- Specs: `specs/` (0001 authentication is the first deliverable).
|
|
146
|
+
- Public API surface catalogue: `specs/0005-api-surface.md`.
|
|
147
|
+
- Versioning: SemVer, `0.x` while the API is unstable.
|
pydmvl-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 The pydmvl 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.
|
pydmvl-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: pydmvl
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Unofficial Python client for the Domovladelets (homeowner) account API
|
|
5
|
+
Project-URL: Homepage, https://github.com/buggy-shep/pydmvl
|
|
6
|
+
Project-URL: Repository, https://github.com/buggy-shep/pydmvl
|
|
7
|
+
Project-URL: Issues, https://github.com/buggy-shep/pydmvl/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/buggy-shep/pydmvl/releases
|
|
9
|
+
Author: The pydmvl contributors
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: domovladelets,home-automation,homeowner,utility-billing
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Home Automation
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: >=3.11
|
|
23
|
+
Requires-Dist: httpx>=0.27
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: mypy>=1.11; extra == 'dev'
|
|
26
|
+
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest>=8.2; extra == 'dev'
|
|
28
|
+
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
29
|
+
Provides-Extra: release
|
|
30
|
+
Requires-Dist: build>=1.2; extra == 'release'
|
|
31
|
+
Requires-Dist: twine>=5; extra == 'release'
|
|
32
|
+
Description-Content-Type: text/markdown
|
|
33
|
+
|
|
34
|
+
# pydmvl
|
|
35
|
+
|
|
36
|
+
[](https://pypi.org/project/pydmvl/)
|
|
37
|
+
[](https://github.com/buggy-shep/pydmvl/actions/workflows/ci.yml)
|
|
38
|
+
|
|
39
|
+
Unofficial Python client for the **"Domovladelets+"** ("Домовладелец+",
|
|
40
|
+
homeowner) account API. It implements the protocol used by the app
|
|
41
|
+
([Google Play](https://play.google.com/store/apps/details?id=com.homeowner)):
|
|
42
|
+
it authenticates with an account login and password and exposes the account
|
|
43
|
+
snapshot the service returns for its home screen: account aggregates,
|
|
44
|
+
per-period charges (documents), receipt links, and payment history.
|
|
45
|
+
|
|
46
|
+
Неофициальный Python-клиент API лицевого счёта приложения **«Домовладелец+»**.
|
|
47
|
+
Реализует протокол этого приложения
|
|
48
|
+
([Google Play](https://play.google.com/store/apps/details?id=com.homeowner)):
|
|
49
|
+
аутентифицируется по логину и паролю лицевого счёта и предоставляет снимок
|
|
50
|
+
счёта, который сервис возвращает для главного экрана: агрегаты по счёту,
|
|
51
|
+
начисления за период (документы), ссылки на квитанции и историю платежей.
|
|
52
|
+
|
|
53
|
+
> **Disclaimer.** This project is unofficial and is not affiliated with,
|
|
54
|
+
> endorsed by, or sponsored by the "Domovladelets+" application or its
|
|
55
|
+
> operators. It is built for interoperability with your own account. Use it at
|
|
56
|
+
> your own risk; only access accounts you are authorized to access.
|
|
57
|
+
|
|
58
|
+
> **Отказ от ответственности.** Проект неофициальный и не связан с
|
|
59
|
+
> приложением «Домовладелец+» или его операторами, не одобрен и не
|
|
60
|
+
> спонсируется ими. Он создан для взаимодействия с вашим собственным лицевым
|
|
61
|
+
> счётом. Используйте его на свой риск; получайте доступ только к тем счетам,
|
|
62
|
+
> на которые у вас есть разрешение.
|
|
63
|
+
|
|
64
|
+
## Install
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
pip install pydmvl
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Usage
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
from pydmvl import DmvlClient
|
|
74
|
+
|
|
75
|
+
with DmvlClient() as client:
|
|
76
|
+
session = client.login("user", "secret")
|
|
77
|
+
print(session.personal_account.amount_due)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## TLS verification (disabled by default)
|
|
81
|
+
|
|
82
|
+
The service presents an **incomplete certificate chain** (it does not serve the
|
|
83
|
+
intermediate CA), so standard verification fails against the real endpoint with
|
|
84
|
+
`certificate verify failed: unable to get local issuer certificate`. The
|
|
85
|
+
official client disables verification for this reason, and `pydmvl` matches
|
|
86
|
+
that observed behavior: `verify` defaults to `False`.
|
|
87
|
+
|
|
88
|
+
This is a deliberate, documented default, not a silent downgrade. Whenever you
|
|
89
|
+
can, turn verification back on — pass a CA bundle that includes the missing
|
|
90
|
+
intermediate, or `verify=True` if your trust store already chains the
|
|
91
|
+
certificate:
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
DmvlClient(verify="/path/to/ca-bundle.pem")
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Consumers that expose TLS settings to end users should present this as an
|
|
98
|
+
explicit opt-in control. See [spec 0004](specs/0004-client-api.md) R8.
|
|
99
|
+
|
|
100
|
+
## Status
|
|
101
|
+
|
|
102
|
+
Authentication, the account snapshot, documents (charges, receipts, unpaid
|
|
103
|
+
detection), and payment history are implemented (specs 0001–0004); `0.x` — the
|
|
104
|
+
API may still change. See [`specs/`](specs/) for the specifications and their
|
|
105
|
+
status.
|
|
106
|
+
|
|
107
|
+
Capabilities:
|
|
108
|
+
|
|
109
|
+
- Login with `login` + `hash` (MD5 of the password); stateless session, no
|
|
110
|
+
bearer token — [spec 0001](specs/0001-auth.md)
|
|
111
|
+
- Account snapshot with debt/charge/payment aggregates —
|
|
112
|
+
[spec 0002](specs/0002-documents.md)
|
|
113
|
+
- Per-period charges and receipt links — [spec 0002](specs/0002-documents.md)
|
|
114
|
+
- Payment history and the latest payment — [spec 0003](specs/0003-payments.md)
|
|
115
|
+
- Public sync + async client API — [spec 0004](specs/0004-client-api.md)
|
|
116
|
+
- Configurable TLS verification (default off; see below) — [spec 0004](specs/0004-client-api.md) R8
|
|
117
|
+
|
|
118
|
+
### Known API surface
|
|
119
|
+
|
|
120
|
+
The service exposes a single PHP `action` router. The catalogue of known
|
|
121
|
+
actions is [spec 0005](specs/0005-api-surface.md); only the read-only subset
|
|
122
|
+
needed for the account snapshot is implemented here — writing actions
|
|
123
|
+
(submitting meter readings, creating payments, opening doors, sending
|
|
124
|
+
messages, and similar) are out of scope.
|
|
125
|
+
|
|
126
|
+
## Requirements
|
|
127
|
+
|
|
128
|
+
- Python >= 3.11
|
|
129
|
+
- [httpx](https://pypi.org/project/httpx/) >= 0.27
|
|
130
|
+
|
|
131
|
+
## Development
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
python3 -m venv .venv
|
|
135
|
+
.venv/bin/pip install -e ".[dev]"
|
|
136
|
+
.venv/bin/ruff check .
|
|
137
|
+
.venv/bin/ruff format --check .
|
|
138
|
+
.venv/bin/mypy
|
|
139
|
+
.venv/bin/pytest -m "not live"
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Live tests against the real API stay behind the `live` marker and are run
|
|
143
|
+
manually only, with credentials from the environment (`DMVL_USERNAME`,
|
|
144
|
+
`DMVL_PASSWORD`). Account credentials are sent as request query parameters, so
|
|
145
|
+
do not enable request-URL logging while a live client is in use.
|
|
146
|
+
|
|
147
|
+
## License
|
|
148
|
+
|
|
149
|
+
[MIT](LICENSE)
|
pydmvl-0.1.0/README.md
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# pydmvl
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/pydmvl/)
|
|
4
|
+
[](https://github.com/buggy-shep/pydmvl/actions/workflows/ci.yml)
|
|
5
|
+
|
|
6
|
+
Unofficial Python client for the **"Domovladelets+"** ("Домовладелец+",
|
|
7
|
+
homeowner) account API. It implements the protocol used by the app
|
|
8
|
+
([Google Play](https://play.google.com/store/apps/details?id=com.homeowner)):
|
|
9
|
+
it authenticates with an account login and password and exposes the account
|
|
10
|
+
snapshot the service returns for its home screen: account aggregates,
|
|
11
|
+
per-period charges (documents), receipt links, and payment history.
|
|
12
|
+
|
|
13
|
+
Неофициальный Python-клиент API лицевого счёта приложения **«Домовладелец+»**.
|
|
14
|
+
Реализует протокол этого приложения
|
|
15
|
+
([Google Play](https://play.google.com/store/apps/details?id=com.homeowner)):
|
|
16
|
+
аутентифицируется по логину и паролю лицевого счёта и предоставляет снимок
|
|
17
|
+
счёта, который сервис возвращает для главного экрана: агрегаты по счёту,
|
|
18
|
+
начисления за период (документы), ссылки на квитанции и историю платежей.
|
|
19
|
+
|
|
20
|
+
> **Disclaimer.** This project is unofficial and is not affiliated with,
|
|
21
|
+
> endorsed by, or sponsored by the "Domovladelets+" application or its
|
|
22
|
+
> operators. It is built for interoperability with your own account. Use it at
|
|
23
|
+
> your own risk; only access accounts you are authorized to access.
|
|
24
|
+
|
|
25
|
+
> **Отказ от ответственности.** Проект неофициальный и не связан с
|
|
26
|
+
> приложением «Домовладелец+» или его операторами, не одобрен и не
|
|
27
|
+
> спонсируется ими. Он создан для взаимодействия с вашим собственным лицевым
|
|
28
|
+
> счётом. Используйте его на свой риск; получайте доступ только к тем счетам,
|
|
29
|
+
> на которые у вас есть разрешение.
|
|
30
|
+
|
|
31
|
+
## Install
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install pydmvl
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Usage
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
from pydmvl import DmvlClient
|
|
41
|
+
|
|
42
|
+
with DmvlClient() as client:
|
|
43
|
+
session = client.login("user", "secret")
|
|
44
|
+
print(session.personal_account.amount_due)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## TLS verification (disabled by default)
|
|
48
|
+
|
|
49
|
+
The service presents an **incomplete certificate chain** (it does not serve the
|
|
50
|
+
intermediate CA), so standard verification fails against the real endpoint with
|
|
51
|
+
`certificate verify failed: unable to get local issuer certificate`. The
|
|
52
|
+
official client disables verification for this reason, and `pydmvl` matches
|
|
53
|
+
that observed behavior: `verify` defaults to `False`.
|
|
54
|
+
|
|
55
|
+
This is a deliberate, documented default, not a silent downgrade. Whenever you
|
|
56
|
+
can, turn verification back on — pass a CA bundle that includes the missing
|
|
57
|
+
intermediate, or `verify=True` if your trust store already chains the
|
|
58
|
+
certificate:
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
DmvlClient(verify="/path/to/ca-bundle.pem")
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Consumers that expose TLS settings to end users should present this as an
|
|
65
|
+
explicit opt-in control. See [spec 0004](specs/0004-client-api.md) R8.
|
|
66
|
+
|
|
67
|
+
## Status
|
|
68
|
+
|
|
69
|
+
Authentication, the account snapshot, documents (charges, receipts, unpaid
|
|
70
|
+
detection), and payment history are implemented (specs 0001–0004); `0.x` — the
|
|
71
|
+
API may still change. See [`specs/`](specs/) for the specifications and their
|
|
72
|
+
status.
|
|
73
|
+
|
|
74
|
+
Capabilities:
|
|
75
|
+
|
|
76
|
+
- Login with `login` + `hash` (MD5 of the password); stateless session, no
|
|
77
|
+
bearer token — [spec 0001](specs/0001-auth.md)
|
|
78
|
+
- Account snapshot with debt/charge/payment aggregates —
|
|
79
|
+
[spec 0002](specs/0002-documents.md)
|
|
80
|
+
- Per-period charges and receipt links — [spec 0002](specs/0002-documents.md)
|
|
81
|
+
- Payment history and the latest payment — [spec 0003](specs/0003-payments.md)
|
|
82
|
+
- Public sync + async client API — [spec 0004](specs/0004-client-api.md)
|
|
83
|
+
- Configurable TLS verification (default off; see below) — [spec 0004](specs/0004-client-api.md) R8
|
|
84
|
+
|
|
85
|
+
### Known API surface
|
|
86
|
+
|
|
87
|
+
The service exposes a single PHP `action` router. The catalogue of known
|
|
88
|
+
actions is [spec 0005](specs/0005-api-surface.md); only the read-only subset
|
|
89
|
+
needed for the account snapshot is implemented here — writing actions
|
|
90
|
+
(submitting meter readings, creating payments, opening doors, sending
|
|
91
|
+
messages, and similar) are out of scope.
|
|
92
|
+
|
|
93
|
+
## Requirements
|
|
94
|
+
|
|
95
|
+
- Python >= 3.11
|
|
96
|
+
- [httpx](https://pypi.org/project/httpx/) >= 0.27
|
|
97
|
+
|
|
98
|
+
## Development
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
python3 -m venv .venv
|
|
102
|
+
.venv/bin/pip install -e ".[dev]"
|
|
103
|
+
.venv/bin/ruff check .
|
|
104
|
+
.venv/bin/ruff format --check .
|
|
105
|
+
.venv/bin/mypy
|
|
106
|
+
.venv/bin/pytest -m "not live"
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Live tests against the real API stay behind the `live` marker and are run
|
|
110
|
+
manually only, with credentials from the environment (`DMVL_USERNAME`,
|
|
111
|
+
`DMVL_PASSWORD`). Account credentials are sent as request query parameters, so
|
|
112
|
+
do not enable request-URL logging while a live client is in use.
|
|
113
|
+
|
|
114
|
+
## License
|
|
115
|
+
|
|
116
|
+
[MIT](LICENSE)
|