python-frank-energie 5.2.0__tar.gz → 6.0.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-frank-energie
3
- Version: 5.2.0
3
+ Version: 6.0.0
4
4
  Summary: Asynchronous Python client for the Frank Energie
5
5
  Home-page: https://github.com/dcsbl/python-frank-energie
6
6
  License: Apache-2.0
@@ -15,6 +15,7 @@ Classifier: Programming Language :: Python :: 3.12
15
15
  Requires-Dist: PyJWT (>=2.8.0)
16
16
  Requires-Dist: aiohttp (>=3.8.0)
17
17
  Requires-Dist: python-dateutil (>=2.8.0)
18
+ Requires-Dist: syrupy (>=4.6.1,<5.0.0)
18
19
  Project-URL: Bug Tracker, https://github.com/dcsbl/python-frank-energie/issues
19
20
  Project-URL: Changelog, https://github.com/dcsbl/python-frank-energie/releases
20
21
  Project-URL: Documentation, https://github.com/dcsbl/python-frank-energie
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "python-frank-energie"
3
- version = "5.2.0"
3
+ version = "6.0.0"
4
4
  description = "Asynchronous Python client for the Frank Energie"
5
5
  authors = ["DCSBL"]
6
6
  maintainers = ["DCSBL"]
@@ -20,6 +20,7 @@ python = "^3.10"
20
20
  aiohttp = ">=3.8.0"
21
21
  python-dateutil = ">=2.8.0"
22
22
  PyJWT = ">=2.8.0"
23
+ syrupy = "^4.6.1"
23
24
 
24
25
  [tool.poetry.dev-dependencies]
25
26
  aresponses = "^2.1.6"
@@ -27,27 +28,27 @@ black = "^22.12"
27
28
  blacken-docs = "^1.15.0"
28
29
  flake8 = "^4.0.1"
29
30
  flake8-docstrings = "^1.5.0"
30
- isort = "^5.11.4"
31
- pre-commit = "^3.3.2"
31
+ isort = "^5.13.2"
32
+ pre-commit = "^3.6.0"
32
33
  pre-commit-hooks = "^4.4.0"
33
- pylint = "^3.0.2"
34
- pytest = "^7.4.0"
35
- pytest-asyncio = "^0.21.0"
34
+ pylint = "^3.0.3"
35
+ pytest = "^7.4.4"
36
+ pytest-asyncio = "^0.23.4"
36
37
  pytest-cov = "^4.1.0"
37
38
  pyupgrade = "^3.9.0"
38
- flake8-simplify = "^0.20.0"
39
- vulture = "^2.7"
39
+ flake8-simplify = "^0.21.0"
40
+ vulture = "^2.11"
40
41
  flake8-bandit = "^3.0.0"
41
42
  flake8-bugbear = "^23.3.12"
42
43
  flake8-builtins = "^2.1.0"
43
44
  flake8-comprehensions = "^3.14.0"
44
45
  flake8-eradicate = "^1.2.1"
45
46
  flake8-markdown = "^0.3.0"
46
- freezegun = "^1.2.2"
47
+ freezegun = "^1.4.0"
47
48
  darglint = "^1.8.1"
48
- safety = "^2.3.5"
49
+ safety = "^3.0.1"
49
50
  codespell = "^2.2.5"
50
- bandit = "^1.7.3"
51
+ bandit = "^1.7.7"
51
52
 
52
53
  [tool.poetry.urls]
53
54
  "Bug Tracker" = "https://github.com/dcsbl/python-frank-energie/issues"
@@ -9,7 +9,7 @@ from typing import Any
9
9
  from aiohttp.client import ClientError, ClientSession
10
10
 
11
11
  from .exceptions import AuthException, AuthRequiredException
12
- from .models import Authentication, Invoices, MarketPrices, MonthSummary, User
12
+ from .models import Authentication, Invoices, MarketPrices, Me, MonthSummary
13
13
 
14
14
 
15
15
  class FrankEnergie:
@@ -100,15 +100,30 @@ class FrankEnergie:
100
100
  self._auth = Authentication.from_dict(await self._query(query))
101
101
  return self._auth
102
102
 
103
- async def month_summary(self) -> MonthSummary:
104
- """Get month summary data."""
103
+ async def month_summary(self, site_reference: str) -> MonthSummary:
104
+ """Get month summary data.
105
+
106
+ Returns a MonthSummary object, containing the actual and expected costs until the last meter reading date.
107
+
108
+ Full query:
109
+ query MonthSummary($siteReference: String!) {
110
+ monthSummary(siteReference: $siteReference) {
111
+ _id
112
+ lastMeterReadingDate
113
+ expectedCostsUntilLastMeterReadingDate
114
+ actualCostsUntilLastMeterReadingDate
115
+ meterReadingDayCompleteness
116
+ gasExcluded
117
+ }
118
+ }
119
+ """
105
120
  if self._auth is None:
106
121
  raise AuthRequiredException
107
122
 
108
123
  query = {
109
124
  "query": """
110
- query MonthSummary {
111
- monthSummary {
125
+ query MonthSummary($siteReference: String!) {
126
+ monthSummary(siteReference: $siteReference) {
112
127
  actualCostsUntilLastMeterReadingDate
113
128
  expectedCostsUntilLastMeterReadingDate
114
129
  expectedCosts
@@ -117,23 +132,60 @@ class FrankEnergie:
117
132
  }
118
133
  """,
119
134
  "operationName": "MonthSummary",
120
- "variables": {},
135
+ "variables": {"siteReference": site_reference},
121
136
  }
122
137
 
123
138
  return MonthSummary.from_dict(await self._query(query))
124
139
 
125
- async def invoices(self) -> Invoices:
140
+ async def invoices(self, site_reference: str) -> Invoices:
126
141
  """Get invoices data.
127
142
 
128
143
  Returns a Invoices object, containing the previous, current and upcoming invoice.
144
+
145
+ Full query:
146
+ query Invoices($siteReference: String!) {
147
+ invoices(siteReference: $siteReference) {
148
+ _id
149
+ previousPeriodInvoice {
150
+ id
151
+ StartDate
152
+ PeriodDescription
153
+ TotalAmount
154
+ __typename
155
+ }
156
+ currentPeriodInvoice {
157
+ id
158
+ StartDate
159
+ PeriodDescription
160
+ TotalAmount
161
+ __typename
162
+ }
163
+ upcomingPeriodInvoice {
164
+ id
165
+ StartDate
166
+ PeriodDescription
167
+ TotalAmount
168
+ __typename
169
+ }
170
+ allInvoices {
171
+ id
172
+ StartDate
173
+ PeriodDescription
174
+ TotalAmount
175
+ __typename
176
+ }
177
+ __typename
178
+ }
179
+ }
180
+
129
181
  """
130
182
  if self._auth is None:
131
183
  raise AuthRequiredException
132
184
 
133
185
  query = {
134
186
  "query": """
135
- query Invoices {
136
- invoices {
187
+ query Invoices($siteReference: String!) {
188
+ invoices(siteReference: $siteReference) {
137
189
  previousPeriodInvoice {
138
190
  StartDate
139
191
  PeriodDescription
@@ -153,38 +205,187 @@ class FrankEnergie:
153
205
  }
154
206
  """,
155
207
  "operationName": "Invoices",
156
- "variables": {},
208
+ "variables": {"siteReference": site_reference},
157
209
  }
158
210
 
159
211
  return Invoices.from_dict(await self._query(query))
160
212
 
161
- async def user(self) -> User:
162
- """Get user data."""
213
+ async def me(self, site_reference: str | None = None) -> Me:
214
+ """Get 'Me' data.
215
+
216
+ Full query:
217
+ query Me($siteReference: String) {
218
+ me {
219
+ ...UserFields
220
+ }
221
+ }
222
+ fragment UserFields on User {
223
+ id
224
+ email
225
+ countryCode
226
+ advancedPaymentAmount(siteReference: $siteReference)
227
+ treesCount
228
+ hasInviteLink
229
+ hasCO2Compensation
230
+ notification
231
+ createdAt
232
+ InviteLinkUser {
233
+ id
234
+ fromName
235
+ slug
236
+ treesAmountPerConnection
237
+ discountPerConnection
238
+ }
239
+ connections(siteReference: $siteReference) {
240
+ id
241
+ connectionId
242
+ EAN
243
+ segment
244
+ status
245
+ contractStatus
246
+ estimatedFeedIn
247
+ firstMeterReadingDate
248
+ lastMeterReadingDate
249
+ meterType
250
+ externalDetails {
251
+ gridOperator
252
+ address {
253
+ street
254
+ houseNumber
255
+ houseNumberAddition
256
+ zipCode
257
+ city
258
+ }
259
+ }
260
+ }
261
+ externalDetails {
262
+ reference
263
+ person {
264
+ firstName
265
+ lastName
266
+ }
267
+ contact {
268
+ emailAddress
269
+ phoneNumber
270
+ mobileNumber
271
+ }
272
+ address {
273
+ street
274
+ houseNumber
275
+ houseNumberAddition
276
+ zipCode
277
+ city
278
+ }
279
+ debtor {
280
+ bankAccountNumber
281
+ preferredAutomaticCollectionDay
282
+ }
283
+ }
284
+ PushNotificationPriceAlerts {
285
+ id
286
+ isEnabled
287
+ type
288
+ weekdays
289
+ }
290
+ UserSettings {
291
+ id
292
+ disabledHapticFeedback
293
+ jedlixUserId
294
+ jedlixPushNotifications
295
+ smartPushNotifications
296
+ }
297
+ activePaymentAuthorization {
298
+ id
299
+ mandateId
300
+ signedAt
301
+ bankAccountNumber
302
+ }
303
+ meterReadingExportPeriods(siteReference: $siteReference) {
304
+ EAN
305
+ cluster
306
+ segment
307
+ from
308
+ till
309
+ period
310
+ type
311
+ }
312
+ deliverySites {
313
+ reference
314
+ segments
315
+ address {
316
+ street
317
+ houseNumber
318
+ houseNumberAddition
319
+ zipCode
320
+ city
321
+ }
322
+ addressHasMultipleSites
323
+ status
324
+ propositionType
325
+ deliveryStartDate
326
+ deliveryEndDate
327
+ firstMeterReadingDate
328
+ lastMeterReadingDate
329
+ }
330
+ smartCharging {
331
+ isActivated
332
+ provider
333
+ userCreatedAt
334
+ userId
335
+ isAvailableInCountry
336
+ needsSubscription
337
+ subscription {
338
+ startDate
339
+ endDate
340
+ id
341
+ proposition {
342
+ product
343
+ countryCode
344
+ }
345
+ }
346
+ }
347
+ websiteUrl
348
+ customerSupportEmail
349
+ }
350
+
351
+ """
163
352
  if self._auth is None:
164
353
  raise AuthRequiredException
165
354
 
166
355
  query = {
167
356
  "query": """
168
- query Me {
357
+ query Me($siteReference: String) {
169
358
  me {
170
359
  ...UserFields
171
360
  }
172
361
  }
173
362
  fragment UserFields on User {
174
363
  id
175
- connectionsStatus
176
- firstMeterReadingDate
177
- lastMeterReadingDate
178
- advancedPaymentAmount
364
+ email
365
+ countryCode
366
+ advancedPaymentAmount(siteReference: $siteReference)
179
367
  treesCount
368
+ hasInviteLink
180
369
  hasCO2Compensation
370
+ deliverySites {
371
+ reference
372
+ segments
373
+ address {
374
+ street
375
+ houseNumber
376
+ houseNumberAddition
377
+ zipCode
378
+ city
379
+ }
380
+ status
381
+ }
181
382
  }
182
383
  """,
183
384
  "operationName": "Me",
184
- "variables": {},
385
+ "variables": {"siteReference": site_reference},
185
386
  }
186
387
 
187
- return User.from_dict(await self._query(query))
388
+ return Me.from_dict(await self._query(query))
188
389
 
189
390
  async def prices(
190
391
  self, start_date: date, end_date: date | None = None
@@ -217,15 +418,45 @@ class FrankEnergie:
217
418
 
218
419
  return MarketPrices.from_dict(await self._query(query_data))
219
420
 
220
- async def user_prices(self, start_date: date) -> MarketPrices:
221
- """Get customer market prices."""
421
+ async def user_prices(self, start_date: date, site_reference: str) -> MarketPrices:
422
+ """Get customer market prices.
423
+
424
+ Full query:
425
+ query MarketPrices($date: String!, $siteReference: String!) {
426
+ customerMarketPrices(date: $date, siteReference: $siteReference) {
427
+ id
428
+ electricityPrices {
429
+ id
430
+ from
431
+ till
432
+ date
433
+ marketPrice
434
+ marketPriceTax
435
+ consumptionSourcingMarkupPrice
436
+ energyTax
437
+ perUnit
438
+ }
439
+ gasPrices {
440
+ id
441
+ from
442
+ till
443
+ date
444
+ marketPrice
445
+ marketPriceTax
446
+ consumptionSourcingMarkupPrice
447
+ energyTax
448
+ perUnit
449
+ }
450
+ }
451
+ }
452
+ """
222
453
  if self._auth is None:
223
454
  raise AuthRequiredException
224
455
 
225
456
  query_data = {
226
457
  "query": """
227
- query CustomerMarketPrices($date: String!) {
228
- customerMarketPrices(date: $date) {
458
+ query MarketPrices($date: String!, $siteReference: String!) {
459
+ customerMarketPrices(date: $date, siteReference: $siteReference) {
229
460
  electricityPrices {
230
461
  from
231
462
  till
@@ -245,8 +476,8 @@ class FrankEnergie:
245
476
  }
246
477
  }
247
478
  """,
248
- "variables": {"date": str(start_date)},
249
- "operationName": "CustomerMarketPrices",
479
+ "variables": {"date": str(start_date), "siteReference": site_reference},
480
+ "operationName": "MarketPrices",
250
481
  }
251
482
 
252
483
  return MarketPrices.from_userprices_dict(await self._query(query_data))
@@ -114,18 +114,74 @@ class Invoices:
114
114
 
115
115
 
116
116
  @dataclass
117
- class User:
118
- """User data, including the current status of the connection."""
117
+ class Me:
118
+ """Me data, including the current status of the connection."""
119
119
 
120
120
  id: str
121
- connectionsStatus: str
122
- firstMeterReadingDate: str
123
- lastMeterReadingDate: str
121
+ email: str
122
+ countryCode: str
124
123
  advancedPaymentAmount: float
124
+ treesCount: int
125
+ hasInviteLink: bool
125
126
  hasCO2Compensation: bool
127
+ deliverySites: list[DeliverySites]
128
+
129
+ @dataclass
130
+ class DeliverySites:
131
+ """Delivery sites data, including the address and delivery status.
132
+
133
+ {
134
+ "reference": "1082MK 10",
135
+ "segments": [
136
+ "ELECTRICITY",
137
+ "GAS"
138
+ ],
139
+ "address": {
140
+ "street": "Gustav Mahlerlaan",
141
+ "houseNumber": "1025",
142
+ "houseNumberAddition": null,
143
+ "zipCode": "1082 MK",
144
+ "city": "AMSTERDAM"
145
+ },
146
+ "addressHasMultipleSites": false,
147
+ "status": "DELIVERY_ENDED",
148
+ "propositionType": null,
149
+ "deliveryStartDate": "2023-01-05",
150
+ "deliveryEndDate": "2024-02-09",
151
+ "firstMeterReadingDate": "2023-01-05",
152
+ "lastMeterReadingDate": "2024-02-08"
153
+ },
154
+ """
155
+
156
+ reference: str
157
+ segments: list[str]
158
+ address_street: str
159
+ address_houseNumber: str
160
+ address_houseNumberAddition: str | None
161
+ address_zipCode: str
162
+ address_city: str
163
+ status: str
164
+
165
+ @staticmethod
166
+ def from_dict(payload: dict[str, str]) -> Me.DeliverySites:
167
+ """Parse the response from the me query."""
168
+ _LOGGER.debug("DeliverySites %s", payload)
169
+
170
+ return Me.DeliverySites(
171
+ reference=payload.get("reference"),
172
+ segments=payload.get("segments"),
173
+ address_street=payload.get("address").get("street"),
174
+ address_houseNumber=payload.get("address").get("houseNumber"),
175
+ address_houseNumberAddition=payload.get("address").get(
176
+ "houseNumberAddition"
177
+ ),
178
+ address_zipCode=payload.get("address").get("zipCode"),
179
+ address_city=payload.get("address").get("city"),
180
+ status=payload.get("status"),
181
+ )
126
182
 
127
183
  @staticmethod
128
- def from_dict(data: dict[str, str]) -> User:
184
+ def from_dict(data: dict[str, str]) -> Me:
129
185
  """Parse the response from the me query."""
130
186
  _LOGGER.debug("User %s", data)
131
187
 
@@ -136,13 +192,18 @@ class User:
136
192
  if not payload:
137
193
  raise RequestException("Unexpected response")
138
194
 
139
- return User(
195
+ return Me(
140
196
  id=payload.get("id"),
141
- connectionsStatus=payload.get("connectionsStatus"),
142
- firstMeterReadingDate=payload.get("firstMeterReadingDate"),
143
- lastMeterReadingDate=payload.get("lastMeterReadingDate"),
197
+ email=payload.get("email"),
198
+ countryCode=payload.get("countryCode"),
144
199
  advancedPaymentAmount=payload.get("advancedPaymentAmount"),
200
+ treesCount=payload.get("treesCount"),
201
+ hasInviteLink=payload.get("hasInviteLink"),
145
202
  hasCO2Compensation=payload.get("hasCO2Compensation"),
203
+ deliverySites=[
204
+ Me.DeliverySites.from_dict(site)
205
+ for site in payload.get("deliverySites")
206
+ ],
146
207
  )
147
208
 
148
209