python-bsblan 5.1.4__py3-none-any.whl → 5.2.0__py3-none-any.whl
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.
- bsblan/__init__.py +4 -0
- bsblan/bsblan.py +88 -0
- bsblan/constants.py +28 -0
- bsblan/models.py +58 -16
- {python_bsblan-5.1.4.dist-info → python_bsblan-5.2.0.dist-info}/METADATA +39 -86
- python_bsblan-5.2.0.dist-info/RECORD +11 -0
- python_bsblan-5.1.4.dist-info/RECORD +0 -11
- {python_bsblan-5.1.4.dist-info → python_bsblan-5.2.0.dist-info}/WHEEL +0 -0
- {python_bsblan-5.1.4.dist-info → python_bsblan-5.2.0.dist-info}/licenses/LICENSE.md +0 -0
bsblan/__init__.py
CHANGED
|
@@ -17,6 +17,8 @@ from .models import (
|
|
|
17
17
|
DHWTimeSwitchPrograms,
|
|
18
18
|
EntityInfo,
|
|
19
19
|
EntityValue,
|
|
20
|
+
HeatingSchedule,
|
|
21
|
+
HeatingTimeSwitchPrograms,
|
|
20
22
|
HotWaterConfig,
|
|
21
23
|
HotWaterSchedule,
|
|
22
24
|
HotWaterState,
|
|
@@ -45,6 +47,8 @@ __all__ = [
|
|
|
45
47
|
"EntityValue",
|
|
46
48
|
"HVACActionCategory",
|
|
47
49
|
"HeatingCircuitStatus",
|
|
50
|
+
"HeatingSchedule",
|
|
51
|
+
"HeatingTimeSwitchPrograms",
|
|
48
52
|
"HotWaterConfig",
|
|
49
53
|
"HotWaterSchedule",
|
|
50
54
|
"HotWaterState",
|
bsblan/bsblan.py
CHANGED
|
@@ -22,6 +22,7 @@ from .constants import (
|
|
|
22
22
|
APIConfig,
|
|
23
23
|
CircuitConfig,
|
|
24
24
|
ErrorMsg,
|
|
25
|
+
HeatingScheduleParams,
|
|
25
26
|
HotWaterParams,
|
|
26
27
|
Validation,
|
|
27
28
|
)
|
|
@@ -38,6 +39,8 @@ from .models import (
|
|
|
38
39
|
DeviceTime,
|
|
39
40
|
DHWSchedule,
|
|
40
41
|
EntityInfo,
|
|
42
|
+
HeatingSchedule,
|
|
43
|
+
HeatingTimeSwitchPrograms,
|
|
41
44
|
HotWaterConfig,
|
|
42
45
|
HotWaterSchedule,
|
|
43
46
|
HotWaterState,
|
|
@@ -1380,6 +1383,91 @@ class BSBLAN:
|
|
|
1380
1383
|
include=include,
|
|
1381
1384
|
)
|
|
1382
1385
|
|
|
1386
|
+
async def heating_schedule(
|
|
1387
|
+
self,
|
|
1388
|
+
include: list[str] | None = None,
|
|
1389
|
+
circuit: int = 1,
|
|
1390
|
+
) -> HeatingTimeSwitchPrograms:
|
|
1391
|
+
"""Get heating time switch programs for a specific circuit.
|
|
1392
|
+
|
|
1393
|
+
Args:
|
|
1394
|
+
include: Optional list of day names to fetch. If None,
|
|
1395
|
+
fetches all schedule parameters. Valid names include:
|
|
1396
|
+
monday, tuesday, wednesday, thursday,
|
|
1397
|
+
friday, saturday, sunday, standard_values.
|
|
1398
|
+
circuit: The heating circuit number (1 or 2). Defaults to 1.
|
|
1399
|
+
|
|
1400
|
+
Returns:
|
|
1401
|
+
HeatingTimeSwitchPrograms: Heating schedule information.
|
|
1402
|
+
|
|
1403
|
+
"""
|
|
1404
|
+
self._validate_circuit(circuit)
|
|
1405
|
+
time_program_params = HeatingScheduleParams.TIME_PROGRAMS[circuit]
|
|
1406
|
+
|
|
1407
|
+
filtered_params = time_program_params
|
|
1408
|
+
if include is not None:
|
|
1409
|
+
if not include:
|
|
1410
|
+
raise BSBLANError(ErrorMsg.EMPTY_INCLUDE_LIST)
|
|
1411
|
+
filtered_params = {
|
|
1412
|
+
param_id: name
|
|
1413
|
+
for param_id, name in time_program_params.items()
|
|
1414
|
+
if name in include
|
|
1415
|
+
}
|
|
1416
|
+
if not filtered_params:
|
|
1417
|
+
raise BSBLANError(ErrorMsg.INVALID_INCLUDE_PARAMS)
|
|
1418
|
+
|
|
1419
|
+
params = self._extract_params_summary(filtered_params)
|
|
1420
|
+
data = await self._request(params={"Parameter": params["string_par"]})
|
|
1421
|
+
mapped_data = {
|
|
1422
|
+
name: data[param_id]
|
|
1423
|
+
for param_id, name in filtered_params.items()
|
|
1424
|
+
if param_id in data
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1427
|
+
if not mapped_data:
|
|
1428
|
+
raise BSBLANError(ErrorMsg.NO_HEATING_SCHEDULE_PARAMS)
|
|
1429
|
+
|
|
1430
|
+
return HeatingTimeSwitchPrograms.model_validate(mapped_data)
|
|
1431
|
+
|
|
1432
|
+
async def set_heating_schedule(
|
|
1433
|
+
self,
|
|
1434
|
+
schedule: HeatingSchedule,
|
|
1435
|
+
circuit: int = 1,
|
|
1436
|
+
) -> None:
|
|
1437
|
+
"""Set heating time switch programs for a specific circuit.
|
|
1438
|
+
|
|
1439
|
+
This method allows setting weekly heating schedules using a type-safe
|
|
1440
|
+
interface with TimeSlot and DaySchedule objects.
|
|
1441
|
+
|
|
1442
|
+
Args:
|
|
1443
|
+
schedule: HeatingSchedule object containing the weekly schedule.
|
|
1444
|
+
circuit: The heating circuit number (1 or 2). Defaults to 1.
|
|
1445
|
+
|
|
1446
|
+
Raises:
|
|
1447
|
+
BSBLANError: If no schedule is provided.
|
|
1448
|
+
|
|
1449
|
+
"""
|
|
1450
|
+
self._validate_circuit(circuit)
|
|
1451
|
+
|
|
1452
|
+
if not schedule.has_any_schedule():
|
|
1453
|
+
raise BSBLANError(ErrorMsg.NO_SCHEDULE)
|
|
1454
|
+
|
|
1455
|
+
day_param_map = {
|
|
1456
|
+
v: k
|
|
1457
|
+
for k, v in HeatingScheduleParams.TIME_PROGRAMS[circuit].items()
|
|
1458
|
+
if v != "standard_values"
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
for day_name, param_id in day_param_map.items():
|
|
1462
|
+
day_schedule: DaySchedule | None = getattr(schedule, day_name)
|
|
1463
|
+
if day_schedule is not None:
|
|
1464
|
+
state = {
|
|
1465
|
+
"Parameter": param_id,
|
|
1466
|
+
"Value": day_schedule.to_bsblan_format(),
|
|
1467
|
+
"Type": "1",
|
|
1468
|
+
}
|
|
1469
|
+
await self._set_device_state(state)
|
|
1470
|
+
|
|
1383
1471
|
async def set_hot_water(self, params: SetHotWaterParam) -> None:
|
|
1384
1472
|
"""Change the state of the hot water system through BSB-Lan.
|
|
1385
1473
|
|
bsblan/constants.py
CHANGED
|
@@ -491,6 +491,7 @@ class ErrorMsg:
|
|
|
491
491
|
EMPTY_INCLUDE_LIST = (
|
|
492
492
|
"Empty include list provided. Use None to fetch all parameters."
|
|
493
493
|
)
|
|
494
|
+
NO_HEATING_SCHEDULE_PARAMS = "No heating schedule parameters available"
|
|
494
495
|
|
|
495
496
|
|
|
496
497
|
# Handle both ASCII and Unicode degree symbols
|
|
@@ -655,3 +656,30 @@ class HotWaterParams:
|
|
|
655
656
|
"567": "sunday",
|
|
656
657
|
"576": "standard_values",
|
|
657
658
|
}
|
|
659
|
+
|
|
660
|
+
|
|
661
|
+
class HeatingScheduleParams:
|
|
662
|
+
"""Heating schedule parameter mappings per circuit."""
|
|
663
|
+
|
|
664
|
+
TIME_PROGRAMS: Final[dict[int, dict[str, str]]] = {
|
|
665
|
+
1: {
|
|
666
|
+
"501": "monday",
|
|
667
|
+
"502": "tuesday",
|
|
668
|
+
"503": "wednesday",
|
|
669
|
+
"504": "thursday",
|
|
670
|
+
"505": "friday",
|
|
671
|
+
"506": "saturday",
|
|
672
|
+
"507": "sunday",
|
|
673
|
+
"516": "standard_values",
|
|
674
|
+
},
|
|
675
|
+
2: {
|
|
676
|
+
"521": "monday",
|
|
677
|
+
"522": "tuesday",
|
|
678
|
+
"523": "wednesday",
|
|
679
|
+
"524": "thursday",
|
|
680
|
+
"525": "friday",
|
|
681
|
+
"526": "saturday",
|
|
682
|
+
"527": "sunday",
|
|
683
|
+
"536": "standard_values",
|
|
684
|
+
},
|
|
685
|
+
}
|
bsblan/models.py
CHANGED
|
@@ -141,23 +141,10 @@ class DaySchedule:
|
|
|
141
141
|
|
|
142
142
|
|
|
143
143
|
@dataclass
|
|
144
|
-
class
|
|
145
|
-
"""
|
|
144
|
+
class WeeklySchedule:
|
|
145
|
+
"""Base weekly schedule with optional day schedules.
|
|
146
146
|
|
|
147
|
-
|
|
148
|
-
Each day can have up to 3 time slots.
|
|
149
|
-
|
|
150
|
-
Example:
|
|
151
|
-
>>> schedule = DHWSchedule(
|
|
152
|
-
... monday=DaySchedule(slots=[
|
|
153
|
-
... TimeSlot(time(6, 0), time(8, 0)),
|
|
154
|
-
... TimeSlot(time(17, 0), time(21, 0)),
|
|
155
|
-
... ]),
|
|
156
|
-
... tuesday=DaySchedule(slots=[
|
|
157
|
-
... TimeSlot(time(6, 0), time(8, 0)),
|
|
158
|
-
... ])
|
|
159
|
-
... )
|
|
160
|
-
>>> await client.set_hot_water_schedule(schedule)
|
|
147
|
+
Each day can have up to 3 time slots (validated by DaySchedule).
|
|
161
148
|
|
|
162
149
|
"""
|
|
163
150
|
|
|
@@ -190,6 +177,38 @@ class DHWSchedule:
|
|
|
190
177
|
)
|
|
191
178
|
|
|
192
179
|
|
|
180
|
+
@dataclass
|
|
181
|
+
class DHWSchedule(WeeklySchedule):
|
|
182
|
+
"""Weekly hot water schedule for setting time programs.
|
|
183
|
+
|
|
184
|
+
Use this dataclass to set DHW time programs via set_hot_water_schedule().
|
|
185
|
+
Each day can have up to 3 time slots.
|
|
186
|
+
|
|
187
|
+
Example:
|
|
188
|
+
>>> schedule = DHWSchedule(
|
|
189
|
+
... monday=DaySchedule(slots=[
|
|
190
|
+
... TimeSlot(time(6, 0), time(8, 0)),
|
|
191
|
+
... TimeSlot(time(17, 0), time(21, 0)),
|
|
192
|
+
... ]),
|
|
193
|
+
... tuesday=DaySchedule(slots=[
|
|
194
|
+
... TimeSlot(time(6, 0), time(8, 0)),
|
|
195
|
+
... ])
|
|
196
|
+
... )
|
|
197
|
+
>>> await client.set_hot_water_schedule(schedule)
|
|
198
|
+
|
|
199
|
+
"""
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
@dataclass
|
|
203
|
+
class HeatingSchedule(WeeklySchedule):
|
|
204
|
+
"""Weekly heating schedule for setting time programs.
|
|
205
|
+
|
|
206
|
+
Use this dataclass to set heating time programs via set_heating_schedule().
|
|
207
|
+
Each day can have up to 3 time slots.
|
|
208
|
+
|
|
209
|
+
"""
|
|
210
|
+
|
|
211
|
+
|
|
193
212
|
@dataclass
|
|
194
213
|
class DHWTimeSwitchPrograms:
|
|
195
214
|
"""Dataclass for DHW time switch programs."""
|
|
@@ -554,6 +573,29 @@ class HotWaterSchedule(BaseModel):
|
|
|
554
573
|
dhw_time_program_standard_values: EntityInfo[int] | None = None
|
|
555
574
|
|
|
556
575
|
|
|
576
|
+
class HeatingTimeSwitchPrograms(BaseModel):
|
|
577
|
+
"""Heating time switch programs for a specific heating circuit (READ).
|
|
578
|
+
|
|
579
|
+
The daily time programs (Monday-Sunday) use BSB-LAN dataType 9
|
|
580
|
+
(TIMEPROG) and return schedule strings like
|
|
581
|
+
``"13:00-15:00 ##:##-##:## ##:##-##:##"`` where ``##:##`` marks
|
|
582
|
+
unused time slots.
|
|
583
|
+
|
|
584
|
+
``standard_values`` is a YESNO enum (0=No, 1=Yes) that resets
|
|
585
|
+
all daily schedules back to the controller's factory defaults.
|
|
586
|
+
|
|
587
|
+
"""
|
|
588
|
+
|
|
589
|
+
monday: EntityInfo[str | int] | None = None
|
|
590
|
+
tuesday: EntityInfo[str | int] | None = None
|
|
591
|
+
wednesday: EntityInfo[str | int] | None = None
|
|
592
|
+
thursday: EntityInfo[str | int] | None = None
|
|
593
|
+
friday: EntityInfo[str | int] | None = None
|
|
594
|
+
saturday: EntityInfo[str | int] | None = None
|
|
595
|
+
sunday: EntityInfo[str | int] | None = None
|
|
596
|
+
standard_values: EntityInfo[int] | None = None
|
|
597
|
+
|
|
598
|
+
|
|
557
599
|
class DeviceTime(BaseModel):
|
|
558
600
|
"""Object holds device time information."""
|
|
559
601
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-bsblan
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.2.0
|
|
4
4
|
Summary: Asynchronous Python client for BSBLAN API
|
|
5
5
|
Project-URL: Homepage, https://github.com/liudger/python-bsblan
|
|
6
6
|
Project-URL: Repository, https://github.com/liudger/python-bsblan
|
|
7
|
-
Project-URL: Documentation, https://github.
|
|
7
|
+
Project-URL: Documentation, https://liudger.github.io/python-bsblan
|
|
8
8
|
Project-URL: Bug Tracker, https://github.com/liudger/python-bsblan/issues
|
|
9
9
|
Project-URL: Changelog, https://github.com/liudger/python-bsblan/releases
|
|
10
10
|
Author-email: Willem-Jan van Rootselaar <liudgervr@gmail.com>
|
|
@@ -41,8 +41,9 @@ Description-Content-Type: text/markdown
|
|
|
41
41
|
[![Build Status][build-shield]][build]
|
|
42
42
|
[![Code Coverage][codecov-shield]][codecov]
|
|
43
43
|
[![Quality Gate Status][sonarcloud-shield]][sonarcloud]
|
|
44
|
-
|
|
45
|
-
[![
|
|
44
|
+
[![OpenSSF Scorecard][scorecard-shield]][scorecard]
|
|
45
|
+
[![OpenSSF Best Practices][bestpractices-shield]][bestpractices]
|
|
46
|
+
[![Documentation][docs-shield]][docs]
|
|
46
47
|
|
|
47
48
|
Asynchronous Python client for BSBLan.
|
|
48
49
|
|
|
@@ -52,97 +53,36 @@ This package allows you to control and monitor a BSBLan device
|
|
|
52
53
|
programmatically. It is mainly created to allow third-party programs to automate
|
|
53
54
|
the behavior of [BSBLan][bsblanmodule].
|
|
54
55
|
|
|
56
|
+
**[Full documentation](https://liudger.github.io/python-bsblan)**
|
|
57
|
+
|
|
55
58
|
## Installation
|
|
56
59
|
|
|
57
60
|
```bash
|
|
58
61
|
pip install python-bsblan
|
|
59
62
|
```
|
|
60
63
|
|
|
61
|
-
##
|
|
64
|
+
## Quick start
|
|
62
65
|
|
|
63
66
|
```python
|
|
64
|
-
# pylint: disable=W0621
|
|
65
|
-
"""Asynchronous Python client for BSBLan."""
|
|
66
|
-
|
|
67
67
|
import asyncio
|
|
68
|
-
import
|
|
69
|
-
|
|
70
|
-
from bsblan import BSBLAN, BSBLANConfig, Device, Info, Sensor, State, StaticState
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
async def print_state(state: State) -> None:
|
|
74
|
-
"""Print the current state of the BSBLan device."""
|
|
75
|
-
print(f"HVAC Action: {state.hvac_action.desc}")
|
|
76
|
-
print(f"HVAC Mode: {state.hvac_mode.desc}")
|
|
77
|
-
print(f"Current Temperature: {state.current_temperature.value}")
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
async def print_sensor(sensor: Sensor) -> None:
|
|
81
|
-
"""Print sensor information from the BSBLan device."""
|
|
82
|
-
print(f"Outside Temperature: {sensor.outside_temperature.value}")
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
async def print_device_info(device: Device, info: Info) -> None:
|
|
86
|
-
"""Print device and general information."""
|
|
87
|
-
print(f"Device Name: {device.name}")
|
|
88
|
-
print(f"Version: {device.version}")
|
|
89
|
-
print(f"Device Identification: {info.device_identification.value}")
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
async def print_static_state(static_state: StaticState) -> None:
|
|
93
|
-
"""Print static state information."""
|
|
94
|
-
print(f"Min Temperature: {static_state.min_temp.value}")
|
|
95
|
-
print(f"Max Temperature: {static_state.max_temp.value}")
|
|
96
|
-
|
|
68
|
+
from bsblan import BSBLAN, BSBLANConfig
|
|
97
69
|
|
|
98
70
|
async def main() -> None:
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
"""
|
|
106
|
-
# Create a configuration object
|
|
107
|
-
config = BSBLANConfig(
|
|
108
|
-
host="192.0.2.1",
|
|
109
|
-
passkey=None,
|
|
110
|
-
username=os.getenv("USERNAME"), # Compliant
|
|
111
|
-
password=os.getenv("PASSWORD"), # Compliant
|
|
112
|
-
)
|
|
113
|
-
|
|
114
|
-
# Initialize BSBLAN with the configuration object
|
|
115
|
-
async with BSBLAN(config) as bsblan:
|
|
116
|
-
# Get and print state
|
|
117
|
-
state: State = await bsblan.state()
|
|
118
|
-
await print_state(state)
|
|
71
|
+
config = BSBLANConfig(host="192.168.1.100")
|
|
72
|
+
async with BSBLAN(config) as client:
|
|
73
|
+
# Read current state
|
|
74
|
+
state = await client.state()
|
|
75
|
+
print(f"Current temperature: {state.current_temperature.value}")
|
|
119
76
|
|
|
120
77
|
# Set thermostat temperature
|
|
121
|
-
|
|
122
|
-
await bsblan.thermostat(target_temperature="18")
|
|
123
|
-
|
|
124
|
-
# Set HVAC mode (using raw integer: 0=off, 1=auto, 2=eco, 3=heat)
|
|
125
|
-
print("Setting HVAC mode to heat")
|
|
126
|
-
await bsblan.thermostat(hvac_mode=3)
|
|
127
|
-
|
|
128
|
-
# Get and print sensor information
|
|
129
|
-
sensor: Sensor = await bsblan.sensor()
|
|
130
|
-
await print_sensor(sensor)
|
|
131
|
-
|
|
132
|
-
# Get and print device and general info
|
|
133
|
-
device: Device = await bsblan.device()
|
|
134
|
-
info: Info = await bsblan.info()
|
|
135
|
-
await print_device_info(device, info)
|
|
136
|
-
|
|
137
|
-
# Get and print static state
|
|
138
|
-
static_state: StaticState = await bsblan.static_values()
|
|
139
|
-
await print_static_state(static_state)
|
|
78
|
+
await client.thermostat(target_temperature="21.5")
|
|
140
79
|
|
|
141
|
-
|
|
142
|
-
if __name__ == "__main__":
|
|
143
|
-
asyncio.run(main())
|
|
80
|
+
asyncio.run(main())
|
|
144
81
|
```
|
|
145
82
|
|
|
83
|
+
For more examples, including hot water control, multi-circuit support, and
|
|
84
|
+
authentication setup, see the [Getting Started][docs-getting-started] guide.
|
|
85
|
+
|
|
146
86
|
## Changelog & Releases
|
|
147
87
|
|
|
148
88
|
This repository keeps a change log using [GitHub's releases][releases]
|
|
@@ -190,12 +130,14 @@ make setup
|
|
|
190
130
|
A `Makefile` is provided for common development tasks. Run `make help` to
|
|
191
131
|
see all available targets:
|
|
192
132
|
|
|
193
|
-
| Command
|
|
194
|
-
|
|
195
|
-
| `make setup`
|
|
196
|
-
| `make lint`
|
|
197
|
-
| `make test`
|
|
198
|
-
| `make coverage`
|
|
133
|
+
| Command | Description |
|
|
134
|
+
|--------------------|--------------------------------------|
|
|
135
|
+
| `make setup` | Install dev dependencies & git hooks |
|
|
136
|
+
| `make lint` | Run all pre-commit hooks |
|
|
137
|
+
| `make test` | Run tests |
|
|
138
|
+
| `make coverage` | Run tests with coverage report |
|
|
139
|
+
| `make docs` | Build documentation |
|
|
140
|
+
| `make docs-serve` | Serve documentation locally |
|
|
199
141
|
|
|
200
142
|
As this repository uses [prek][prek] (a faster, Rust-based drop-in replacement
|
|
201
143
|
for pre-commit), all changes are linted and tested with each commit. You can
|
|
@@ -243,9 +185,16 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
243
185
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
244
186
|
SOFTWARE.
|
|
245
187
|
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
[![Buy me a coffee][buymeacoffee-shield]][buymeacoffee]
|
|
191
|
+
|
|
246
192
|
[bsblanmodule]: https://github.com/fredlcore/bsb_lan
|
|
247
193
|
[build-shield]: https://github.com/liudger/python-bsblan/actions/workflows/tests.yaml/badge.svg
|
|
248
194
|
[build]: https://github.com/liudger/python-bsblan/actions
|
|
195
|
+
[docs]: https://liudger.github.io/python-bsblan
|
|
196
|
+
[docs-getting-started]: https://liudger.github.io/python-bsblan/getting-started/
|
|
197
|
+
[docs-shield]: https://img.shields.io/badge/docs-GitHub%20Pages-blue
|
|
249
198
|
[buymeacoffee-shield]: https://www.buymeacoffee.com/assets/img/guidelines/download-assets-sm-2.svg
|
|
250
199
|
[buymeacoffee]: https://www.buymeacoffee.com/liudger
|
|
251
200
|
[codecov-shield]: https://codecov.io/gh/liudger/python-bsblan/branch/main/graph/badge.svg?token=ypos87GGxv
|
|
@@ -259,11 +208,15 @@ SOFTWARE.
|
|
|
259
208
|
[uv]: https://docs.astral.sh/uv/
|
|
260
209
|
[uv-install]: https://docs.astral.sh/uv/getting-started/installation/
|
|
261
210
|
[prek]: https://github.com/j178/prek
|
|
262
|
-
[project-stage-shield]: https://img.shields.io/badge/project%20stage-
|
|
211
|
+
[project-stage-shield]: https://img.shields.io/badge/project%20stage-stable-green.svg
|
|
263
212
|
[pypi]: https://pypi.org/project/python-bsblan/
|
|
264
213
|
[python-versions-shield]: https://img.shields.io/pypi/pyversions/python-bsblan
|
|
265
214
|
[releases-shield]: https://img.shields.io/github/v/release/liudger/python-bsblan.svg
|
|
266
215
|
[releases]: https://github.com/liudger/python-bsblan/releases
|
|
267
216
|
[semver]: http://semver.org/spec/v2.0.0.html
|
|
217
|
+
[scorecard-shield]: https://api.scorecard.dev/projects/github.com/liudger/python-bsblan/badge
|
|
218
|
+
[scorecard]: https://scorecard.dev/viewer/?uri=github.com/liudger/python-bsblan
|
|
219
|
+
[bestpractices-shield]: https://www.bestpractices.dev/projects/12561/badge
|
|
220
|
+
[bestpractices]: https://www.bestpractices.dev/projects/12561
|
|
268
221
|
[sonarcloud-shield]: https://sonarcloud.io/api/project_badges/measure?project=liudger_python-bsblan&metric=alert_status
|
|
269
222
|
[sonarcloud]: https://sonarcloud.io/summary/new_code?id=liudger_python-bsblan
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
bsblan/__init__.py,sha256=YD_edvxHL5ocUE2iLWhdinqpsRYWJkVrcds0b6aKp9U,1288
|
|
2
|
+
bsblan/bsblan.py,sha256=PCNForRgeJFHwZRE_mEcvySQxiYLA2JCIzMJu429Fq4,63034
|
|
3
|
+
bsblan/constants.py,sha256=LoMSrEdZj2zohDFxOQ2JT7J4jIH9clXh7sfkNnnjl5A,22864
|
|
4
|
+
bsblan/exceptions.py,sha256=jL7qohIMmuVTsdWBB_trKPg5Yzim6JxaOT13h6EJPlk,1770
|
|
5
|
+
bsblan/models.py,sha256=qEycc2eVkCK2CXWDXBSqtTyM-to6pH7jX6aKvXeH3R8,20705
|
|
6
|
+
bsblan/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
+
bsblan/utility.py,sha256=sS0wWJoqvLAHzwaSLIqQEQ-boHsYFLKAHw8KNTSmdX8,5772
|
|
8
|
+
python_bsblan-5.2.0.dist-info/METADATA,sha256=MjhQBz4cjiRwunT2OH4X-gRFsprNSIpLBMNu7kam24Y,8529
|
|
9
|
+
python_bsblan-5.2.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
10
|
+
python_bsblan-5.2.0.dist-info/licenses/LICENSE.md,sha256=Shv8HPcD1WbZjBPvfb5r3h_cwaPeVaUZMUqU_XQGwGw,1092
|
|
11
|
+
python_bsblan-5.2.0.dist-info/RECORD,,
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
bsblan/__init__.py,sha256=t_RF_90ManstXJBdoL8n98KK9tnTTvwezntJxk7GfBY,1180
|
|
2
|
-
bsblan/bsblan.py,sha256=Pn240e7BXjWGS60Zq8jYBlR_umXuiVYDxoGCu_Usdlk,59973
|
|
3
|
-
bsblan/constants.py,sha256=Q6lqnx1YFlPZZYpZrm8Ytx8HgmhTtO4U88EZmnPZTds,22089
|
|
4
|
-
bsblan/exceptions.py,sha256=jL7qohIMmuVTsdWBB_trKPg5Yzim6JxaOT13h6EJPlk,1770
|
|
5
|
-
bsblan/models.py,sha256=ZqztmI90aDODKJ06SHue2cU5AMqp0chjT8r_B1FUbxg,19409
|
|
6
|
-
bsblan/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
-
bsblan/utility.py,sha256=sS0wWJoqvLAHzwaSLIqQEQ-boHsYFLKAHw8KNTSmdX8,5772
|
|
8
|
-
python_bsblan-5.1.4.dist-info/METADATA,sha256=0SguR6h4-8P6HHJdzlCeZMsxJe36N7BC21MAMsfUtso,9728
|
|
9
|
-
python_bsblan-5.1.4.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
10
|
-
python_bsblan-5.1.4.dist-info/licenses/LICENSE.md,sha256=Shv8HPcD1WbZjBPvfb5r3h_cwaPeVaUZMUqU_XQGwGw,1092
|
|
11
|
-
python_bsblan-5.1.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|