pygazpar 1.2.8__py39-none-any.whl → 1.3.0a6__py39-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.
- pygazpar/datasource.py +535 -528
- pygazpar/excelparser.py +136 -138
- pygazpar/jsonparser.py +1 -1
- pygazpar/version.py +1 -1
- {pygazpar-1.2.8.dist-info → pygazpar-1.3.0a6.dist-info}/METADATA +6 -43
- {pygazpar-1.2.8.dist-info → pygazpar-1.3.0a6.dist-info}/RECORD +12 -12
- {pygazpar-1.2.8.dist-info → pygazpar-1.3.0a6.dist-info}/WHEEL +1 -1
- tests/test_client.py +145 -159
- tests/test_datasource.py +166 -166
- {pygazpar-1.2.8.dist-info → pygazpar-1.3.0a6.dist-info}/LICENSE.md +0 -0
- {pygazpar-1.2.8.dist-info → pygazpar-1.3.0a6.dist-info}/entry_points.txt +0 -0
- {pygazpar-1.2.8.dist-info → pygazpar-1.3.0a6.dist-info}/top_level.txt +0 -0
pygazpar/excelparser.py
CHANGED
@@ -1,138 +1,136 @@
|
|
1
|
-
import logging
|
2
|
-
from datetime import datetime
|
3
|
-
from pygazpar.enum import Frequency
|
4
|
-
from pygazpar.enum import PropertyName
|
5
|
-
from openpyxl.worksheet.worksheet import Worksheet
|
6
|
-
from openpyxl.cell.cell import Cell
|
7
|
-
from openpyxl import load_workbook
|
8
|
-
from typing import Any, List, Dict
|
9
|
-
|
10
|
-
|
11
|
-
FIRST_DATA_LINE_NUMBER = 10
|
12
|
-
|
13
|
-
Logger = logging.getLogger(__name__)
|
14
|
-
|
15
|
-
|
16
|
-
# ------------------------------------------------------------------------------------------------------------
|
17
|
-
class ExcelParser:
|
18
|
-
|
19
|
-
# ------------------------------------------------------
|
20
|
-
@staticmethod
|
21
|
-
def parse(dataFilename: str, dataReadingFrequency: Frequency) -> List[Dict[str, Any]]:
|
22
|
-
|
23
|
-
parseByFrequency = {
|
24
|
-
Frequency.HOURLY: ExcelParser.__parseHourly,
|
25
|
-
Frequency.DAILY: ExcelParser.__parseDaily,
|
26
|
-
Frequency.WEEKLY: ExcelParser.__parseWeekly,
|
27
|
-
Frequency.MONTHLY: ExcelParser.__parseMonthly
|
28
|
-
}
|
29
|
-
|
30
|
-
Logger.debug(f"Loading Excel data file '{dataFilename}'...")
|
31
|
-
|
32
|
-
workbook = load_workbook(filename=dataFilename)
|
33
|
-
|
34
|
-
worksheet = workbook.active
|
35
|
-
|
36
|
-
res = parseByFrequency[dataReadingFrequency](worksheet)
|
37
|
-
|
38
|
-
workbook.close()
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
minRowNum
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
ExcelParser.__fillRow(row, PropertyName.
|
78
|
-
ExcelParser.__fillRow(row, PropertyName.
|
79
|
-
ExcelParser.__fillRow(row, PropertyName.
|
80
|
-
ExcelParser.__fillRow(row, PropertyName.
|
81
|
-
ExcelParser.__fillRow(row, PropertyName.
|
82
|
-
ExcelParser.__fillRow(row, PropertyName.
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
minRowNum
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
ExcelParser.__fillRow(row, PropertyName.
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
minRowNum
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
ExcelParser.__fillRow(row, PropertyName.
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
return res
|
1
|
+
import logging
|
2
|
+
from datetime import datetime
|
3
|
+
from pygazpar.enum import Frequency
|
4
|
+
from pygazpar.enum import PropertyName
|
5
|
+
from openpyxl.worksheet.worksheet import Worksheet
|
6
|
+
from openpyxl.cell.cell import Cell
|
7
|
+
from openpyxl import load_workbook
|
8
|
+
from typing import Any, List, Dict
|
9
|
+
|
10
|
+
|
11
|
+
FIRST_DATA_LINE_NUMBER = 10
|
12
|
+
|
13
|
+
Logger = logging.getLogger(__name__)
|
14
|
+
|
15
|
+
|
16
|
+
# ------------------------------------------------------------------------------------------------------------
|
17
|
+
class ExcelParser:
|
18
|
+
|
19
|
+
# ------------------------------------------------------
|
20
|
+
@staticmethod
|
21
|
+
def parse(dataFilename: str, dataReadingFrequency: Frequency) -> List[Dict[str, Any]]:
|
22
|
+
|
23
|
+
parseByFrequency = {
|
24
|
+
Frequency.HOURLY: ExcelParser.__parseHourly,
|
25
|
+
Frequency.DAILY: ExcelParser.__parseDaily,
|
26
|
+
Frequency.WEEKLY: ExcelParser.__parseWeekly,
|
27
|
+
Frequency.MONTHLY: ExcelParser.__parseMonthly
|
28
|
+
}
|
29
|
+
|
30
|
+
Logger.debug(f"Loading Excel data file '{dataFilename}'...")
|
31
|
+
|
32
|
+
workbook = load_workbook(filename=dataFilename)
|
33
|
+
|
34
|
+
worksheet = workbook.active
|
35
|
+
|
36
|
+
res = parseByFrequency[dataReadingFrequency](worksheet)
|
37
|
+
|
38
|
+
workbook.close()
|
39
|
+
|
40
|
+
return res
|
41
|
+
|
42
|
+
# ------------------------------------------------------
|
43
|
+
@staticmethod
|
44
|
+
def __fillRow(row: Dict, propertyName: str, cell: Cell, isNumber: bool):
|
45
|
+
|
46
|
+
if cell.value is not None:
|
47
|
+
if isNumber:
|
48
|
+
if type(cell.value) is str:
|
49
|
+
if len(cell.value.strip()) > 0:
|
50
|
+
row[propertyName] = float(cell.value.replace(',', '.'))
|
51
|
+
else:
|
52
|
+
row[propertyName] = cell.value
|
53
|
+
else:
|
54
|
+
row[propertyName] = cell.value.strip() if type(cell.value) is str else cell.value
|
55
|
+
|
56
|
+
# ------------------------------------------------------
|
57
|
+
@staticmethod
|
58
|
+
def __parseHourly(worksheet: Worksheet) -> List[Dict[str, Any]]:
|
59
|
+
return []
|
60
|
+
|
61
|
+
# ------------------------------------------------------
|
62
|
+
@staticmethod
|
63
|
+
def __parseDaily(worksheet: Worksheet) -> List[Dict[str, Any]]:
|
64
|
+
|
65
|
+
res = []
|
66
|
+
|
67
|
+
# Timestamp of the data.
|
68
|
+
data_timestamp = datetime.now().isoformat()
|
69
|
+
|
70
|
+
minRowNum = FIRST_DATA_LINE_NUMBER
|
71
|
+
maxRowNum = len(worksheet['B'])
|
72
|
+
for rownum in range(minRowNum, maxRowNum + 1):
|
73
|
+
row = {}
|
74
|
+
if worksheet.cell(column=2, row=rownum).value is not None:
|
75
|
+
ExcelParser.__fillRow(row, PropertyName.TIME_PERIOD.value, worksheet.cell(column=2, row=rownum), False) # type: ignore
|
76
|
+
ExcelParser.__fillRow(row, PropertyName.START_INDEX.value, worksheet.cell(column=3, row=rownum), True) # type: ignore
|
77
|
+
ExcelParser.__fillRow(row, PropertyName.END_INDEX.value, worksheet.cell(column=4, row=rownum), True) # type: ignore
|
78
|
+
ExcelParser.__fillRow(row, PropertyName.VOLUME.value, worksheet.cell(column=5, row=rownum), True) # type: ignore
|
79
|
+
ExcelParser.__fillRow(row, PropertyName.ENERGY.value, worksheet.cell(column=6, row=rownum), True) # type: ignore
|
80
|
+
ExcelParser.__fillRow(row, PropertyName.CONVERTER_FACTOR.value, worksheet.cell(column=7, row=rownum), True) # type: ignore
|
81
|
+
ExcelParser.__fillRow(row, PropertyName.TEMPERATURE.value, worksheet.cell(column=8, row=rownum), True) # type: ignore
|
82
|
+
ExcelParser.__fillRow(row, PropertyName.TYPE.value, worksheet.cell(column=9, row=rownum), False) # type: ignore
|
83
|
+
row[PropertyName.TIMESTAMP.value] = data_timestamp
|
84
|
+
res.append(row)
|
85
|
+
|
86
|
+
Logger.debug(f"Daily data read successfully between row #{minRowNum} and row #{maxRowNum}")
|
87
|
+
|
88
|
+
return res
|
89
|
+
|
90
|
+
# ------------------------------------------------------
|
91
|
+
@staticmethod
|
92
|
+
def __parseWeekly(worksheet: Worksheet) -> List[Dict[str, Any]]:
|
93
|
+
|
94
|
+
res = []
|
95
|
+
|
96
|
+
# Timestamp of the data.
|
97
|
+
data_timestamp = datetime.now().isoformat()
|
98
|
+
|
99
|
+
minRowNum = FIRST_DATA_LINE_NUMBER
|
100
|
+
maxRowNum = len(worksheet['B'])
|
101
|
+
for rownum in range(minRowNum, maxRowNum + 1):
|
102
|
+
row = {}
|
103
|
+
if worksheet.cell(column=2, row=rownum).value is not None:
|
104
|
+
ExcelParser.__fillRow(row, PropertyName.TIME_PERIOD.value, worksheet.cell(column=2, row=rownum), False) # type: ignore
|
105
|
+
ExcelParser.__fillRow(row, PropertyName.VOLUME.value, worksheet.cell(column=3, row=rownum), True) # type: ignore
|
106
|
+
ExcelParser.__fillRow(row, PropertyName.ENERGY.value, worksheet.cell(column=4, row=rownum), True) # type: ignore
|
107
|
+
row[PropertyName.TIMESTAMP.value] = data_timestamp
|
108
|
+
res.append(row)
|
109
|
+
|
110
|
+
Logger.debug(f"Weekly data read successfully between row #{minRowNum} and row #{maxRowNum}")
|
111
|
+
|
112
|
+
return res
|
113
|
+
|
114
|
+
# ------------------------------------------------------
|
115
|
+
@staticmethod
|
116
|
+
def __parseMonthly(worksheet: Worksheet) -> List[Dict[str, Any]]:
|
117
|
+
|
118
|
+
res = []
|
119
|
+
|
120
|
+
# Timestamp of the data.
|
121
|
+
data_timestamp = datetime.now().isoformat()
|
122
|
+
|
123
|
+
minRowNum = FIRST_DATA_LINE_NUMBER
|
124
|
+
maxRowNum = len(worksheet['B'])
|
125
|
+
for rownum in range(minRowNum, maxRowNum + 1):
|
126
|
+
row = {}
|
127
|
+
if worksheet.cell(column=2, row=rownum).value is not None:
|
128
|
+
ExcelParser.__fillRow(row, PropertyName.TIME_PERIOD.value, worksheet.cell(column=2, row=rownum), False) # type: ignore
|
129
|
+
ExcelParser.__fillRow(row, PropertyName.VOLUME.value, worksheet.cell(column=3, row=rownum), True) # type: ignore
|
130
|
+
ExcelParser.__fillRow(row, PropertyName.ENERGY.value, worksheet.cell(column=4, row=rownum), True) # type: ignore
|
131
|
+
row[PropertyName.TIMESTAMP.value] = data_timestamp
|
132
|
+
res.append(row)
|
133
|
+
|
134
|
+
Logger.debug(f"Monthly data read successfully between row #{minRowNum} and row #{maxRowNum}")
|
135
|
+
|
136
|
+
return res
|
pygazpar/jsonparser.py
CHANGED
@@ -29,7 +29,7 @@ class JsonParser:
|
|
29
29
|
|
30
30
|
for releve in data[pceIdentifier]['releves']:
|
31
31
|
temperature = releve['temperature']
|
32
|
-
if temperature is None
|
32
|
+
if temperature is None:
|
33
33
|
temperature = temperatures.get(releve['journeeGaziere'])
|
34
34
|
|
35
35
|
item = {}
|
pygazpar/version.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
__version__ = "1.
|
1
|
+
__version__ = "1.3.0a6"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: pygazpar
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.3.0a6
|
4
4
|
Summary: Retrieve gas consumption from GrDF web site (French Gas Company)
|
5
5
|
Home-page: https://github.com/ssenart/pygazpar
|
6
6
|
Author: Stephane Senart
|
@@ -17,22 +17,19 @@ Platform: any
|
|
17
17
|
Classifier: Development Status :: 5 - Production/Stable
|
18
18
|
Classifier: Topic :: Software Development :: Libraries
|
19
19
|
Classifier: Operating System :: OS Independent
|
20
|
+
Classifier: Programming Language :: Python :: 3.7
|
21
|
+
Classifier: Programming Language :: Python :: 3.8
|
20
22
|
Classifier: Programming Language :: Python :: 3.9
|
21
23
|
Classifier: Programming Language :: Python :: 3.10
|
22
24
|
Classifier: Programming Language :: Python :: 3.11
|
23
|
-
|
24
|
-
Classifier: Programming Language :: Python :: 3.13
|
25
|
-
Requires-Python: >=3.9
|
25
|
+
Requires-Python: >=3.7
|
26
26
|
Description-Content-Type: text/markdown
|
27
27
|
License-File: LICENSE.md
|
28
|
-
Requires-Dist: openpyxl>=2.6.3
|
29
|
-
Requires-Dist: requests>=2.26.0
|
28
|
+
Requires-Dist: openpyxl >=2.6.3
|
29
|
+
Requires-Dist: requests >=2.26.0
|
30
30
|
Requires-Dist: pandas
|
31
31
|
|
32
32
|
# PyGazpar
|
33
|
-
|
34
|
-
## $\text{\color{green}{!!! This library is working again. CAPTCHA has been removed !!!}}$
|
35
|
-
|
36
33
|
PyGazpar is a Python library for getting natural gas consumption from GrDF French provider.
|
37
34
|
|
38
35
|
Their natural gas meter is called Gazpar. It is wireless and transmit the gas consumption once per day.
|
@@ -217,40 +214,6 @@ All notable changes to this project will be documented in this file.
|
|
217
214
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
218
215
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
219
216
|
|
220
|
-
## [1.2.8](https://github.com/ssenart/PyGazpar/compare/1.2.8...1.2.7) - 2025-01-11
|
221
|
-
|
222
|
-
### Added
|
223
|
-
- [#81](https://github.com/ssenart/PyGazpar/issues/81): Add meter/temperature debug log messages to help investigation in case of errors.
|
224
|
-
|
225
|
-
## [1.2.7](https://github.com/ssenart/PyGazpar/compare/1.2.7...1.2.6) - 2025-01-06
|
226
|
-
|
227
|
-
### Fixed
|
228
|
-
- [#79](https://github.com/ssenart/PyGazpar/issues/79): Fix some unittests that wrongly failed because of the new year.
|
229
|
-
|
230
|
-
## [1.2.6](https://github.com/ssenart/PyGazpar/compare/1.2.6...1.2.5) - 2025-01-03
|
231
|
-
|
232
|
-
### Fixed
|
233
|
-
- [#77](https://github.com/ssenart/PyGazpar/issues/77): Some error may occur while requesting data from GrDF API.
|
234
|
-
|
235
|
-
## [1.2.5](https://github.com/ssenart/PyGazpar/compare/1.2.5...1.2.4) - 2024-12-21
|
236
|
-
|
237
|
-
### Fixed
|
238
|
-
- [#75](https://github.com/ssenart/PyGazpar/issues/75): Fix an error when no temperature data is available.
|
239
|
-
|
240
|
-
## [1.2.4](https://github.com/ssenart/PyGazpar/compare/1.2.4...1.2.3) - 2024-10-09
|
241
|
-
|
242
|
-
### Fixed
|
243
|
-
- [#72](https://github.com/ssenart/PyGazpar/issues/72): Remove the warning message "UserWarning: Boolean Series key will be reindexed to match DataFrame index. df = pd.concat([df[(df["count"] >= 7)], df.tail(1)[df["count"] < 7]])".
|
244
|
-
|
245
|
-
## [1.2.3](https://github.com/ssenart/PyGazpar/compare/1.2.3...1.2.1) - 2024-10-05
|
246
|
-
|
247
|
-
### Added
|
248
|
-
- [#70](https://github.com/ssenart/PyGazpar/issues/70): Add Python 3.12 support.
|
249
|
-
|
250
|
-
## [1.2.2](https://github.com/ssenart/PyGazpar/compare/1.2.1...1.2.2) - 2024-05-08
|
251
|
-
|
252
|
-
### Fixed
|
253
|
-
- [#65](https://github.com/ssenart/PyGazpar/issues/65): [Bug] PermissionError happens when loading data from Excel file.
|
254
217
|
|
255
218
|
## [1.2.1](https://github.com/ssenart/PyGazpar/compare/1.2.0...1.2.1) - 2024-05-04
|
256
219
|
|
@@ -1,11 +1,11 @@
|
|
1
1
|
pygazpar/__init__.py,sha256=qshO_XZbDA2Wrt80ABDs0MoScqJytClAuIJjAnILglk,309
|
2
2
|
pygazpar/__main__.py,sha256=Pt3PInX7QiWcs0aBKZN90NTaU8KFnrQiZ5Hsow1eR5U,3177
|
3
3
|
pygazpar/client.py,sha256=JdVm0jZbeibwtTumcRbUSFadfXnCUClPMjL95_J6p5Y,2595
|
4
|
-
pygazpar/datasource.py,sha256=
|
4
|
+
pygazpar/datasource.py,sha256=gqOREo9OQaBmqWgaDIgShJrP1dZNVFJoIxUu9Rfxmec,21374
|
5
5
|
pygazpar/enum.py,sha256=3ZCk4SziXF6pxgP3MuQ1qxYfqB3X5DOV8Rtd0GHsK9w,898
|
6
|
-
pygazpar/excelparser.py,sha256=
|
7
|
-
pygazpar/jsonparser.py,sha256=
|
8
|
-
pygazpar/version.py,sha256=
|
6
|
+
pygazpar/excelparser.py,sha256=glWlbj22pxYjHGKurOFmhzcVAoWCvfOHn7_Y6GgHUPo,5915
|
7
|
+
pygazpar/jsonparser.py,sha256=AWdU3h7UohsOov8HpeP8GNuqcnDmM4r3I7-CI_crDvA,1804
|
8
|
+
pygazpar/version.py,sha256=rcyBYFWxUArZ5y56YkLypabOiwSZfCl48nXHK0ebB20,24
|
9
9
|
pygazpar/resources/daily_data_sample.json,sha256=YJovtrNUMs257magTfyxiewLmecySFypcelbGFUUeT8,199583
|
10
10
|
pygazpar/resources/hourly_data_sample.json,sha256=N1F-Xz3GaBn2H1p7uKzhkhKCQV8QVR0t76XD6wmFtXA,3
|
11
11
|
pygazpar/resources/monthly_data_sample.json,sha256=yrr4SqrB2MubeVU2HX_FRDZKHIhC0LXCqkO1iqnFWcg,3351
|
@@ -16,12 +16,12 @@ samples/excelSample.py,sha256=ltAl-bBz9-U9YI802JpcIswra-vDS7tR_KL5VNdxJ5c,765
|
|
16
16
|
samples/jsonSample.py,sha256=sYAIusdEJhZdwDAMgHqoWcwDR0FA2eWhSt_2gL_mJRk,736
|
17
17
|
samples/testSample.py,sha256=UeirdEtezHwfZDv_75oxul17YzGWn5yZuHfJYTF3Ez0,387
|
18
18
|
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
19
|
-
tests/test_client.py,sha256=
|
19
|
+
tests/test_client.py,sha256=OwYBeNC66WiykU1IUEf4eZacAU49xQJXsFQY6kYiXCQ,5111
|
20
20
|
tests/test_datafileparser.py,sha256=nAeUpOHtelblMpmbrrnf-2GuMjK5ai65veDoymceprE,818
|
21
|
-
tests/test_datasource.py,sha256=
|
22
|
-
pygazpar-1.
|
23
|
-
pygazpar-1.
|
24
|
-
pygazpar-1.
|
25
|
-
pygazpar-1.
|
26
|
-
pygazpar-1.
|
27
|
-
pygazpar-1.
|
21
|
+
tests/test_datasource.py,sha256=2BCrnUh9ZbR_dAdvKT9498u5a-jGnC4aZafP7V9iZn8,5983
|
22
|
+
pygazpar-1.3.0a6.dist-info/LICENSE.md,sha256=XsCJx_7_BC9tvmE0ZxS1cTNR7ekurog_ea9ybdZ-8tc,1073
|
23
|
+
pygazpar-1.3.0a6.dist-info/METADATA,sha256=EBrPJTTN7QVCXLQvvxcXiWH54BB7QRoHqTNXHthuktk,17766
|
24
|
+
pygazpar-1.3.0a6.dist-info/WHEEL,sha256=kG0f_S63jJ569yg8d_OdUrqQSrnKsZBVKN5Kb1RSnpA,93
|
25
|
+
pygazpar-1.3.0a6.dist-info/entry_points.txt,sha256=c_FMZPYlRv1w9EqfgWhlkdJOoje7FcglI0UMm2oRLoI,53
|
26
|
+
pygazpar-1.3.0a6.dist-info/top_level.txt,sha256=P7qn-XtanDPBLQsTvjvLV71wH8RK0DYbx8tzN_rDS70,23
|
27
|
+
pygazpar-1.3.0a6.dist-info/RECORD,,
|