pybluecurrent 0.1.0__tar.gz → 0.2.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.
Files changed (39) hide show
  1. pybluecurrent-0.2.0/.github/workflows/publish.yaml +52 -0
  2. pybluecurrent-0.2.0/.github/workflows/test.yaml +51 -0
  3. {pybluecurrent-0.1.0 → pybluecurrent-0.2.0}/.gitignore +3 -0
  4. {pybluecurrent-0.1.0 → pybluecurrent-0.2.0}/.pre-commit-config.yaml +7 -16
  5. pybluecurrent-0.2.0/CHANGELOG.md +40 -0
  6. {pybluecurrent-0.1.0 → pybluecurrent-0.2.0}/PKG-INFO +30 -2
  7. {pybluecurrent-0.1.0 → pybluecurrent-0.2.0}/README.md +29 -1
  8. {pybluecurrent-0.1.0 → pybluecurrent-0.2.0}/pyproject.toml +6 -7
  9. pybluecurrent-0.2.0/src/pybluecurrent/_version.py +24 -0
  10. {pybluecurrent-0.1.0 → pybluecurrent-0.2.0}/src/pybluecurrent/client.py +132 -61
  11. pybluecurrent-0.2.0/src/pybluecurrent/utilities.py +51 -0
  12. {pybluecurrent-0.1.0 → pybluecurrent-0.2.0}/src/pybluecurrent.egg-info/PKG-INFO +30 -2
  13. {pybluecurrent-0.1.0 → pybluecurrent-0.2.0}/src/pybluecurrent.egg-info/SOURCES.txt +13 -1
  14. pybluecurrent-0.2.0/src/pybluecurrent.egg-info/scm_file_list.json +29 -0
  15. pybluecurrent-0.2.0/src/pybluecurrent.egg-info/scm_version.json +8 -0
  16. {pybluecurrent-0.1.0 → pybluecurrent-0.2.0}/tests/conftest.py +16 -1
  17. pybluecurrent-0.2.0/tests/fake_socket.py +130 -0
  18. pybluecurrent-0.2.0/tests/fixtures/account.json +12 -0
  19. pybluecurrent-0.2.0/tests/fixtures/charge_cards.json +15 -0
  20. pybluecurrent-0.2.0/tests/fixtures/charge_point_settings.json +50 -0
  21. pybluecurrent-0.2.0/tests/fixtures/charge_points.json +75 -0
  22. pybluecurrent-0.2.0/tests/fixtures/error_forbidden.json +5 -0
  23. pybluecurrent-0.2.0/tests/fixtures/grid_status.json +11 -0
  24. pybluecurrent-0.2.0/tests/fixtures/sustainability_status.json +5 -0
  25. {pybluecurrent-0.1.0 → pybluecurrent-0.2.0}/tests/test_client.py +16 -2
  26. pybluecurrent-0.2.0/tests/test_offline.py +225 -0
  27. {pybluecurrent-0.1.0 → pybluecurrent-0.2.0}/tests/test_utilities.py +12 -0
  28. pybluecurrent-0.1.0/.github/workflows/publish.yaml +0 -32
  29. pybluecurrent-0.1.0/.github/workflows/test.yaml +0 -31
  30. pybluecurrent-0.1.0/src/pybluecurrent/_version.py +0 -34
  31. pybluecurrent-0.1.0/src/pybluecurrent/utilities.py +0 -36
  32. {pybluecurrent-0.1.0 → pybluecurrent-0.2.0}/LICENSE +0 -0
  33. {pybluecurrent-0.1.0 → pybluecurrent-0.2.0}/setup.cfg +0 -0
  34. {pybluecurrent-0.1.0 → pybluecurrent-0.2.0}/src/pybluecurrent/__init__.py +0 -0
  35. {pybluecurrent-0.1.0 → pybluecurrent-0.2.0}/src/pybluecurrent/exceptions.py +0 -0
  36. {pybluecurrent-0.1.0 → pybluecurrent-0.2.0}/src/pybluecurrent/py.typed +0 -0
  37. {pybluecurrent-0.1.0 → pybluecurrent-0.2.0}/src/pybluecurrent.egg-info/dependency_links.txt +0 -0
  38. {pybluecurrent-0.1.0 → pybluecurrent-0.2.0}/src/pybluecurrent.egg-info/requires.txt +0 -0
  39. {pybluecurrent-0.1.0 → pybluecurrent-0.2.0}/src/pybluecurrent.egg-info/top_level.txt +0 -0
@@ -0,0 +1,52 @@
1
+ name: Build and Publish
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ release:
8
+ types: [published]
9
+
10
+ jobs:
11
+ build:
12
+ runs-on: ubuntu-latest
13
+ timeout-minutes: 10
14
+
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - name: Set up Python
19
+ uses: actions/setup-python@v5
20
+ with:
21
+ python-version: "3.x"
22
+
23
+ - name: Build
24
+ run: |
25
+ pip3 install build
26
+ python3 -m build
27
+
28
+ publish:
29
+ needs: build
30
+ if: startsWith(github.ref, 'refs/tags')
31
+ runs-on: ubuntu-latest
32
+ timeout-minutes: 10
33
+ environment: pypi
34
+ permissions:
35
+ id-token: write
36
+ contents: read
37
+
38
+ steps:
39
+ - uses: actions/checkout@v4
40
+
41
+ - name: Set up Python
42
+ uses: actions/setup-python@v5
43
+ with:
44
+ python-version: "3.x"
45
+
46
+ - name: Build
47
+ run: |
48
+ pip3 install build
49
+ python3 -m build
50
+
51
+ - name: Publish to PyPI
52
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,51 @@
1
+ name: Continuous Integration
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ pull_request:
6
+ push:
7
+ branches:
8
+ - main
9
+
10
+ jobs:
11
+ lint:
12
+ runs-on: ubuntu-latest
13
+ timeout-minutes: 10
14
+
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - name: Set up Python
19
+ uses: actions/setup-python@v5
20
+ with:
21
+ python-version: "3.x"
22
+
23
+ - name: Install Dependencies
24
+ run: |
25
+ pip3 install -e ".[dev]"
26
+
27
+ - name: Run pre-commit
28
+ run: pre-commit run --all-files
29
+
30
+ test:
31
+ runs-on: ubuntu-latest
32
+ timeout-minutes: 10
33
+ strategy:
34
+ fail-fast: false
35
+ matrix:
36
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
37
+
38
+ steps:
39
+ - uses: actions/checkout@v4
40
+
41
+ - name: Set up Python
42
+ uses: actions/setup-python@v5
43
+ with:
44
+ python-version: ${{ matrix.python-version }}
45
+
46
+ - name: Install Dependencies
47
+ run: |
48
+ pip3 install -e ".[dev]"
49
+
50
+ - name: Run Pytest
51
+ run: pytest
@@ -91,6 +91,9 @@ ipython_config.py
91
91
  # install all needed dependencies.
92
92
  #Pipfile.lock
93
93
 
94
+ # uv
95
+ uv.lock
96
+
94
97
  # PEP 582; used by e.g. github.com/David-OConnor/pyflow
95
98
  __pypackages__/
96
99
 
@@ -13,22 +13,13 @@ repos:
13
13
  - id: check-json
14
14
  - id: pretty-format-json
15
15
  args: [--autofix]
16
- - repo: https://github.com/ambv/black
17
- rev: 23.3.0
18
- hooks:
19
- - id: black
20
16
  - repo: https://github.com/astral-sh/ruff-pre-commit
21
- rev: v0.0.280
22
- hooks:
23
- - id: ruff
24
- - repo: https://github.com/pycqa/isort
25
- rev: 5.12.0
17
+ rev: v0.15.20
26
18
  hooks:
27
- - id: isort
28
- exclude: __init__.py
29
- - repo: https://github.com/pre-commit/mirrors-mypy
30
- rev: v1.18.2
19
+ - id: ruff-check
20
+ args: [--fix]
21
+ - id: ruff-format
22
+ - repo: https://github.com/astral-sh/ty-pre-commit
23
+ rev: v0.0.56
31
24
  hooks:
32
- - id: mypy
33
- additional_dependencies:
34
- - types-requests
25
+ - id: ty
@@ -0,0 +1,40 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
+ This project is pre-1.0: breaking changes may land in minor releases.
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.2.0] - 2026-07-11
11
+
12
+ ### Added
13
+
14
+ - API-token authentication: construct the client with `BlueCurrentClient(api_token=...)` instead of a username and password.
15
+ - `get_api_token()` and `generate_api_token()` to fetch or rotate your account's API token (home automation key).
16
+
17
+ ### Changed
18
+
19
+ - REST calls now use `api.bluecurrent.nl` instead of the legacy `bo.bluecurrent.nl` backoffice host (same `bc_api` v2.0 API and response shapes).
20
+ - REST requests now use a 30-second timeout instead of httpx's 5-second default, so occasional slow backend responses no longer raise `httpx.ReadTimeout`; override with the `http_timeout` attribute.
21
+ - Internal: added an offline websocket test harness (fake socket + recorded fixtures) so the auth/`_send`/`_receive`/`_handler` logic runs in CI without live credentials.
22
+
23
+ ### Fixed
24
+
25
+ - Concurrent websocket calls are now safe: calls awaiting the same response type are serialized so overlapping same-type calls can no longer receive each other's replies (different-type calls still run concurrently). Errors the backend tags with a request id are routed to the originating call rather than failing every in-flight call.
26
+
27
+ ## [0.1.1] - 2026-07-04
28
+
29
+ ### Fixed
30
+
31
+ - `get_account` no longer raises a `ValueError` on BlueCurrent's current date format; `first_login_app` now parses both the legacy (`01-JAN-20`) and ISO (`2020-01-15T13:33:52`) formats.
32
+
33
+ ### Changed
34
+
35
+ - `get_account` returns `first_login_app` as a `datetime` (previously a `date`).
36
+ - Internal: switched tooling to Ruff and ty, added a Python 3.10–3.13 CI matrix, and moved to PyPI trusted publishing (OIDC).
37
+
38
+ [Unreleased]: https://github.com/rogiervandergeer/pybluecurrent/compare/0.2.0...HEAD
39
+ [0.2.0]: https://github.com/rogiervandergeer/pybluecurrent/compare/0.1.1...0.2.0
40
+ [0.1.1]: https://github.com/rogiervandergeer/pybluecurrent/compare/0.1.0...0.1.1
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pybluecurrent
3
- Version: 0.1.0
3
+ Version: 0.2.0
4
4
  Summary: Python client for BlueCurrent charge points.
5
5
  Author-email: Rogier van der Geer <rogier@vander-geer.nl>
6
6
  License: MIT
@@ -52,6 +52,8 @@ async with client:
52
52
  The `BlueCurrentClient` exposes the following methods:
53
53
 
54
54
  - [`get_account`](#getaccount---get-your-account-information)
55
+ - [`get_api_token`](#getapitoken---get-your-api-token)
56
+ - [`generate_api_token`](#generateapitoken---generate-a-new-api-token)
55
57
  - [`get_charge_cards`](#getchargecards---get-your-charge-cards)
56
58
  - [`get_charge_points`](#getchargepoints---get-your-charge-points)
57
59
  - [`get_charge_point_settings`](#getchargepointsettings---get-the-settings-of-a-charge-point)
@@ -76,6 +78,14 @@ async with client:
76
78
  ```
77
79
  Entering the async context will automatically login.
78
80
 
81
+ Instead of a username and password, you can authenticate with an API token:
82
+ ```python
83
+ client = BlueCurrentClient(api_token="your_api_token")
84
+ ```
85
+ Retrieve or rotate the token with [`get_api_token`](#getapitoken---get-your-api-token) and
86
+ [`generate_api_token`](#generateapitoken---generate-a-new-api-token), or from the
87
+ [BlueCurrent website](https://my.bluecurrent.nl).
88
+
79
89
  #### `get_account` - Get your account information.
80
90
 
81
91
  ```python
@@ -94,11 +104,29 @@ A dictionary describing your account:
94
104
  "developer_mode_enabled": False,
95
105
  "tel": "",
96
106
  "marketing_target": "bluecurrent",
97
- "first_login_app": date(2020, 1, 1),
107
+ "first_login_app": datetime(2020, 1, 15, 13, 33, 52),
98
108
  "hubspot_user_identity": "a_very_long_string"
99
109
  }
100
110
  ```
101
111
 
112
+ #### `get_api_token` - Get your API token.
113
+
114
+ ```python
115
+ async def get_api_token(self) -> str
116
+ ```
117
+
118
+ Returns the API token (home automation key) for your account. This token can be used to authenticate
119
+ instead of a username and password, by constructing the client with `BlueCurrentClient(api_token=...)`.
120
+
121
+ #### `generate_api_token` - Generate a new API token.
122
+
123
+ ```python
124
+ async def generate_api_token(self) -> str
125
+ ```
126
+
127
+ Generates a new API token and returns it. **Warning:** this rotates the token — any previously issued
128
+ token is invalidated, which will break anything still using the old one (for example a Home Assistant integration).
129
+
102
130
  #### `get_charge_cards` - Get your charge cards.
103
131
 
104
132
  ```python
@@ -25,6 +25,8 @@ async with client:
25
25
  The `BlueCurrentClient` exposes the following methods:
26
26
 
27
27
  - [`get_account`](#getaccount---get-your-account-information)
28
+ - [`get_api_token`](#getapitoken---get-your-api-token)
29
+ - [`generate_api_token`](#generateapitoken---generate-a-new-api-token)
28
30
  - [`get_charge_cards`](#getchargecards---get-your-charge-cards)
29
31
  - [`get_charge_points`](#getchargepoints---get-your-charge-points)
30
32
  - [`get_charge_point_settings`](#getchargepointsettings---get-the-settings-of-a-charge-point)
@@ -49,6 +51,14 @@ async with client:
49
51
  ```
50
52
  Entering the async context will automatically login.
51
53
 
54
+ Instead of a username and password, you can authenticate with an API token:
55
+ ```python
56
+ client = BlueCurrentClient(api_token="your_api_token")
57
+ ```
58
+ Retrieve or rotate the token with [`get_api_token`](#getapitoken---get-your-api-token) and
59
+ [`generate_api_token`](#generateapitoken---generate-a-new-api-token), or from the
60
+ [BlueCurrent website](https://my.bluecurrent.nl).
61
+
52
62
  #### `get_account` - Get your account information.
53
63
 
54
64
  ```python
@@ -67,11 +77,29 @@ A dictionary describing your account:
67
77
  "developer_mode_enabled": False,
68
78
  "tel": "",
69
79
  "marketing_target": "bluecurrent",
70
- "first_login_app": date(2020, 1, 1),
80
+ "first_login_app": datetime(2020, 1, 15, 13, 33, 52),
71
81
  "hubspot_user_identity": "a_very_long_string"
72
82
  }
73
83
  ```
74
84
 
85
+ #### `get_api_token` - Get your API token.
86
+
87
+ ```python
88
+ async def get_api_token(self) -> str
89
+ ```
90
+
91
+ Returns the API token (home automation key) for your account. This token can be used to authenticate
92
+ instead of a username and password, by constructing the client with `BlueCurrentClient(api_token=...)`.
93
+
94
+ #### `generate_api_token` - Generate a new API token.
95
+
96
+ ```python
97
+ async def generate_api_token(self) -> str
98
+ ```
99
+
100
+ Generates a new API token and returns it. **Warning:** this rotates the token — any previously issued
101
+ token is invalidated, which will break anything still using the old one (for example a Home Assistant integration).
102
+
75
103
  #### `get_charge_cards` - Get your charge cards.
76
104
 
77
105
  ```python
@@ -43,17 +43,16 @@ pybluecurrent = ["py.typed"]
43
43
  [tool.setuptools_scm]
44
44
  write_to = "src/pybluecurrent/_version.py"
45
45
 
46
- [tool.black]
47
- line-length = 120
48
- target-version = ["py310"]
49
-
50
- [tool.isort]
51
- profile = "black"
52
-
53
46
  [tool.ruff]
54
47
  line-length = 120
55
48
  target-version = "py310"
56
49
 
50
+ [tool.ruff.lint]
51
+ select = ["E", "F", "I"]
52
+
53
+ [tool.ty.src]
54
+ include = ["src"]
55
+
57
56
  [tool.pytest.ini_options]
58
57
  asyncio_mode = "auto"
59
58
  asyncio_default_fixture_loop_scope = "session"
@@ -0,0 +1,24 @@
1
+ # file generated by vcs-versioning
2
+ # don't change, don't track in version control
3
+ from __future__ import annotations
4
+
5
+ __all__ = [
6
+ "__version__",
7
+ "__version_tuple__",
8
+ "version",
9
+ "version_tuple",
10
+ "__commit_id__",
11
+ "commit_id",
12
+ ]
13
+
14
+ version: str
15
+ __version__: str
16
+ __version_tuple__: tuple[int | str, ...]
17
+ version_tuple: tuple[int | str, ...]
18
+ commit_id: str | None
19
+ __commit_id__: str | None
20
+
21
+ __version__ = version = '0.2.0'
22
+ __version_tuple__ = version_tuple = (0, 2, 0)
23
+
24
+ __commit_id__ = commit_id = 'ge8d24aba3'