chellow 1712909617.0.0__py3-none-any.whl → 1712929217.0.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.
Potentially problematic release.
This version of chellow might be problematic. Click here for more details.
- chellow/e/hh_importer.py +62 -32
- chellow/e/views.py +22 -7
- chellow/templates/e/dc_contract_properties.html +1 -1
- chellow/templates/e/dc_contract_properties_edit.html +6 -5
- {chellow-1712909617.0.0.dist-info → chellow-1712929217.0.0.dist-info}/METADATA +2 -2
- {chellow-1712909617.0.0.dist-info → chellow-1712929217.0.0.dist-info}/RECORD +7 -7
- {chellow-1712909617.0.0.dist-info → chellow-1712929217.0.0.dist-info}/WHEEL +0 -0
chellow/e/hh_importer.py
CHANGED
|
@@ -8,13 +8,13 @@ import traceback
|
|
|
8
8
|
from collections import defaultdict, deque
|
|
9
9
|
from datetime import datetime as Datetime, timedelta as Timedelta
|
|
10
10
|
from decimal import Decimal
|
|
11
|
-
from io import TextIOWrapper
|
|
11
|
+
from io import StringIO, TextIOWrapper
|
|
12
|
+
from pathlib import Path
|
|
12
13
|
|
|
13
14
|
import jinja2
|
|
14
15
|
|
|
15
|
-
import
|
|
16
|
+
from paramiko import AutoAddPolicy, RSAKey, SFTPError, SSHClient
|
|
16
17
|
|
|
17
|
-
import pysftp
|
|
18
18
|
|
|
19
19
|
import requests
|
|
20
20
|
|
|
@@ -174,7 +174,7 @@ class HhImportTask(threading.Thread):
|
|
|
174
174
|
self.log(f"Problem {e}")
|
|
175
175
|
sess.rollback()
|
|
176
176
|
self.is_error = True
|
|
177
|
-
except
|
|
177
|
+
except BaseException:
|
|
178
178
|
self.log(f"Unknown Exception {traceback.format_exc()}")
|
|
179
179
|
sess.rollback()
|
|
180
180
|
self.is_error = True
|
|
@@ -231,19 +231,19 @@ class HhImportTask(threading.Thread):
|
|
|
231
231
|
fl = None
|
|
232
232
|
|
|
233
233
|
for directory in directories:
|
|
234
|
-
self.log("Checking the directory '
|
|
234
|
+
self.log(f"Checking the directory '{directory}'.")
|
|
235
235
|
try:
|
|
236
236
|
last_import_key = last_import_keys[directory]
|
|
237
237
|
except KeyError:
|
|
238
238
|
last_import_key = last_import_keys[directory] = ""
|
|
239
239
|
|
|
240
240
|
dir_path = home_path + "/" + directory
|
|
241
|
-
ftp.
|
|
241
|
+
ftp.chdir(dir_path)
|
|
242
242
|
files = []
|
|
243
|
-
for fname in ftp.
|
|
243
|
+
for fname in ftp.listdir():
|
|
244
244
|
fpath = dir_path + "/" + fname
|
|
245
245
|
try:
|
|
246
|
-
ftp.
|
|
246
|
+
ftp.chdir(fpath)
|
|
247
247
|
continue # directory
|
|
248
248
|
except ftplib.error_perm:
|
|
249
249
|
pass
|
|
@@ -266,7 +266,7 @@ class HhImportTask(threading.Thread):
|
|
|
266
266
|
key, fpath = fl
|
|
267
267
|
self.log(f"Attempting to download {fpath} with key {key}.")
|
|
268
268
|
f = tempfile.TemporaryFile()
|
|
269
|
-
ftp.retrbinary("RETR "
|
|
269
|
+
ftp.retrbinary(f"RETR {fpath}", f.write)
|
|
270
270
|
self.log("File downloaded successfully.")
|
|
271
271
|
ftp.quit()
|
|
272
272
|
self.log("Logged out.")
|
|
@@ -290,25 +290,30 @@ class HhImportTask(threading.Thread):
|
|
|
290
290
|
contract = Contract.get_dc_by_id(sess, self.contract_id)
|
|
291
291
|
contract.update_state(state)
|
|
292
292
|
sess.commit()
|
|
293
|
-
self.log("Finished loading '"
|
|
293
|
+
self.log(f"Finished loading '{fpath}'")
|
|
294
294
|
return True
|
|
295
295
|
|
|
296
296
|
def sftp_handler(self, sess, properties, contract):
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
password = properties
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
297
|
+
hostname = properties["hostname"]
|
|
298
|
+
username = properties["username"]
|
|
299
|
+
password = properties.get("password")
|
|
300
|
+
private_key = properties.get("private_key")
|
|
301
|
+
pkey = None
|
|
302
|
+
if private_key is not None:
|
|
303
|
+
pkf = StringIO.StringIO(private_key)
|
|
304
|
+
pkf.seek(0)
|
|
305
|
+
pkey = RSAKey.from_private_key(pkf)
|
|
306
|
+
|
|
307
|
+
port = properties.get("port", 22)
|
|
304
308
|
file_type = properties["file_type"]
|
|
305
309
|
directories = properties["directories"]
|
|
310
|
+
known_hosts = properties["known_hosts"].strip()
|
|
306
311
|
state = contract.make_state()
|
|
307
312
|
|
|
308
313
|
try:
|
|
309
314
|
last_import_keys = state["last_import_keys"]
|
|
310
315
|
except KeyError:
|
|
311
|
-
last_import_keys = state["last_import_keys"] =
|
|
316
|
+
last_import_keys = state["last_import_keys"] = {}
|
|
312
317
|
|
|
313
318
|
ct_now = ct_datetime_now()
|
|
314
319
|
try:
|
|
@@ -323,36 +328,60 @@ class HhImportTask(threading.Thread):
|
|
|
323
328
|
latest_imports = state["latest_imports"] = []
|
|
324
329
|
|
|
325
330
|
sess.rollback()
|
|
326
|
-
self.log(f"Connecting to sftp server at {
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
+
self.log(f"Connecting to sftp server at {hostname}:{port}.")
|
|
332
|
+
|
|
333
|
+
client = SSHClient()
|
|
334
|
+
client.set_missing_host_key_policy(AutoAddPolicy)
|
|
335
|
+
|
|
336
|
+
client.connect(
|
|
337
|
+
hostname,
|
|
338
|
+
port=port,
|
|
339
|
+
username=username,
|
|
340
|
+
password=password,
|
|
341
|
+
pkey=pkey,
|
|
342
|
+
key_filename=None,
|
|
343
|
+
timeout=120,
|
|
344
|
+
banner_timeout=120,
|
|
345
|
+
auth_timeout=120,
|
|
346
|
+
channel_timeout=120,
|
|
347
|
+
look_for_keys=False,
|
|
331
348
|
)
|
|
332
|
-
|
|
333
|
-
|
|
349
|
+
host_keys = client.get_host_keys()
|
|
350
|
+
with tempfile.TemporaryDirectory() as tempdir:
|
|
351
|
+
td = Path(tempdir)
|
|
352
|
+
hfname = td / "hosts"
|
|
353
|
+
host_keys.save(hfname)
|
|
354
|
+
with hfname.open() as hf:
|
|
355
|
+
host_keys_str = hf.read().strip()
|
|
356
|
+
|
|
357
|
+
if host_keys_str != known_hosts:
|
|
358
|
+
raise BadRequest(
|
|
359
|
+
f"The returned host keys {host_keys_str} don't match the known "
|
|
360
|
+
f"hosts {known_hosts} property"
|
|
361
|
+
)
|
|
362
|
+
|
|
363
|
+
ftp = client.open_sftp()
|
|
334
364
|
|
|
335
365
|
f = None
|
|
336
366
|
|
|
337
367
|
for directory in directories:
|
|
338
|
-
self.log("Checking the directory '
|
|
368
|
+
self.log(f"Checking the directory '{directory}'.")
|
|
339
369
|
try:
|
|
340
370
|
last_import_key = last_import_keys[directory]
|
|
341
371
|
except KeyError:
|
|
342
372
|
last_import_key = last_import_keys[directory] = ""
|
|
343
373
|
|
|
344
|
-
|
|
345
|
-
ftp.cwd(dir_path)
|
|
374
|
+
ftp.chdir(directory)
|
|
346
375
|
files = []
|
|
347
376
|
for attr in ftp.listdir_attr():
|
|
348
|
-
fpath =
|
|
377
|
+
fpath = f"{directory}/{attr.filename}"
|
|
349
378
|
try:
|
|
350
|
-
ftp.
|
|
379
|
+
ftp.chdir(fpath)
|
|
351
380
|
continue # directory
|
|
352
|
-
except
|
|
381
|
+
except SFTPError:
|
|
353
382
|
pass
|
|
354
383
|
|
|
355
|
-
key =
|
|
384
|
+
key = f"{attr.st_mtime}_{attr.filename}"
|
|
356
385
|
if key > last_import_key:
|
|
357
386
|
files.append((key, fpath))
|
|
358
387
|
|
|
@@ -364,6 +393,7 @@ class HhImportTask(threading.Thread):
|
|
|
364
393
|
if f is None:
|
|
365
394
|
self.log("No new files found.")
|
|
366
395
|
ftp.close()
|
|
396
|
+
client.close()
|
|
367
397
|
self.log("Logged out.")
|
|
368
398
|
return False
|
|
369
399
|
else:
|
chellow/e/views.py
CHANGED
|
@@ -1093,13 +1093,28 @@ def dc_contract_properties_edit_get(dc_contract_id):
|
|
|
1093
1093
|
return render_template("dc_contract_properties_edit.html", dc_contract=dc_contract)
|
|
1094
1094
|
|
|
1095
1095
|
|
|
1096
|
-
@e.route("/dc_contracts/<int:
|
|
1097
|
-
def dc_contract_properties_edit_post(
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1096
|
+
@e.route("/dc_contracts/<int:dc_contract_id>/properties/edit", methods=["POST"])
|
|
1097
|
+
def dc_contract_properties_edit_post(dc_contract_id):
|
|
1098
|
+
dc_contract = None
|
|
1099
|
+
try:
|
|
1100
|
+
dc_contract = Contract.get_dc_by_id(g.sess, dc_contract_id)
|
|
1101
|
+
properties = req_zish("properties")
|
|
1102
|
+
dc_contract.update(
|
|
1103
|
+
dc_contract.name, dc_contract.party, dc_contract.charge_script, properties
|
|
1104
|
+
)
|
|
1105
|
+
g.sess.commit()
|
|
1106
|
+
return chellow_redirect(f"/dc_contracts/{dc_contract.id}/properties", 303)
|
|
1107
|
+
except BadRequest as e:
|
|
1108
|
+
flash(e.description)
|
|
1109
|
+
if dc_contract is None:
|
|
1110
|
+
raise e
|
|
1111
|
+
else:
|
|
1112
|
+
return make_response(
|
|
1113
|
+
render_template(
|
|
1114
|
+
"dc_contract_properties_edit.html", dc_contract=dc_contract
|
|
1115
|
+
),
|
|
1116
|
+
400,
|
|
1117
|
+
)
|
|
1103
1118
|
|
|
1104
1119
|
|
|
1105
1120
|
@e.route("/dc_contracts/<int:dc_contract_id>/edit")
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
{% block nav %}
|
|
8
8
|
<a href="/e/dc_contracts">DC Contracts</a> »
|
|
9
|
-
<a href="/e/dc_contracts/{{dc_contract.id}}">dc_contract.name</a> »
|
|
9
|
+
<a href="/e/dc_contracts/{{dc_contract.id}}">{{dc_contract.name}}</a> »
|
|
10
10
|
Properties [<a href="/e/dc_contracts/{{dc_contract.id}}/properties/edit">edit</a>]
|
|
11
11
|
{% endblock %}
|
|
12
12
|
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
<legend>Update Properties</legend>
|
|
19
19
|
|
|
20
20
|
<label>Properties</label>
|
|
21
|
-
{{ input_textarea('properties', dc_contract.properties, 40, 80) }}
|
|
21
|
+
{{ input_textarea('properties', dc_contract.properties, 40, 80, show_pos=True) }}
|
|
22
22
|
|
|
23
23
|
<input type="submit" value="Update">
|
|
24
24
|
</fieldset>
|
|
@@ -35,10 +35,11 @@
|
|
|
35
35
|
"file_type": ".df2",
|
|
36
36
|
"hostname": "example.com",
|
|
37
37
|
"username": "username",
|
|
38
|
-
"password": "password",
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
|
|
38
|
+
"password": "password", /* Remove if using private key */
|
|
39
|
+
"private_key": "private_key", /* Remove if using password */
|
|
40
|
+
"directories": ["downloads1", "downloads2"],
|
|
41
|
+
"mpan_map": { /* Optional */
|
|
42
|
+
"99 0993 2821 985": null, /* Ignore MPAN */
|
|
42
43
|
},
|
|
43
44
|
}
|
|
44
45
|
</pre>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: chellow
|
|
3
|
-
Version:
|
|
3
|
+
Version: 1712929217.0.0
|
|
4
4
|
Summary: Web Application for checking UK energy bills.
|
|
5
5
|
Project-URL: Homepage, https://github.com/WessexWater/chellow
|
|
6
6
|
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
|
@@ -11,13 +11,13 @@ Requires-Dist: flask-restx==1.2.0
|
|
|
11
11
|
Requires-Dist: flask==2.3.3
|
|
12
12
|
Requires-Dist: odio==0.0.22
|
|
13
13
|
Requires-Dist: openpyxl==3.1.2
|
|
14
|
+
Requires-Dist: paramiko==3.4.0
|
|
14
15
|
Requires-Dist: pep3143daemon==0.0.6
|
|
15
16
|
Requires-Dist: pg8000==1.31.1
|
|
16
17
|
Requires-Dist: pip>=9.0.1
|
|
17
18
|
Requires-Dist: psutil==5.9.5
|
|
18
19
|
Requires-Dist: pympler==1.0.1
|
|
19
20
|
Requires-Dist: pypdf==3.17.0
|
|
20
|
-
Requires-Dist: pysftp==0.2.9
|
|
21
21
|
Requires-Dist: python-dateutil==2.8.2
|
|
22
22
|
Requires-Dist: pytz==2022.6
|
|
23
23
|
Requires-Dist: requests==2.31.0
|
|
@@ -24,7 +24,7 @@ chellow/e/dno_rate_parser.py,sha256=5MYEbcYngh7n6Szn2h9zLTwQKXH-WHKy6c80PYwNLLQ,
|
|
|
24
24
|
chellow/e/duos.py,sha256=ISTcNqe9KNjVNM2Qs8IBoQxnmSXOt5W_G7tZxp4T78M,28870
|
|
25
25
|
chellow/e/elexon.py,sha256=ALhXS9Es7PV0z9ukPbIramn3cf3iLyFi-PMWPSm5iOs,5487
|
|
26
26
|
chellow/e/energy_management.py,sha256=aXC2qlGt3FAODlNl_frWzVYAQrJLP8FFOiNX3m-QE_Y,12388
|
|
27
|
-
chellow/e/hh_importer.py,sha256=
|
|
27
|
+
chellow/e/hh_importer.py,sha256=QBKdnT3Z4A6fsGqODE9bBGVdWde6Hu8OJfkXVhShQz0,21485
|
|
28
28
|
chellow/e/hh_parser_bg_csv.py,sha256=W5SU2MSpa8BGA0VJw1JXF-IwbCNLFy8fe35yxLZ7gEw,2453
|
|
29
29
|
chellow/e/hh_parser_df2.py,sha256=ynNNRMpLm9qs23tJjfm0vGSaAduXfPMw_7-WfQHXliQ,4209
|
|
30
30
|
chellow/e/hh_parser_simple_csv.py,sha256=RN4QOLvTQeoPrpvXvQ9hkOBZnR5piybLfjCiSJdjpjs,2112
|
|
@@ -38,7 +38,7 @@ chellow/e/system_price.py,sha256=3cPWohHmmBI9v7fENLBzXQkpAeC3r0s5xV29Nmr6k_E,583
|
|
|
38
38
|
chellow/e/tlms.py,sha256=kHAy2A2d1Mma7x4GdNDyrzscJd5DpJtDBYiZEg241Dw,8538
|
|
39
39
|
chellow/e/tnuos.py,sha256=KoMPJDIXfE4zwhSDuywGF1ooxjTYLVjtF7BkSFm6X24,4158
|
|
40
40
|
chellow/e/triad.py,sha256=S6LEMHvUKhAZe0-yfLIRciYDZ8IKMn1jh1TmmsbQD3s,13588
|
|
41
|
-
chellow/e/views.py,sha256=
|
|
41
|
+
chellow/e/views.py,sha256=8Rmm6XuNGXACFSSX_LpomyTC4oS2-nljRlisjEyUVJ4,213975
|
|
42
42
|
chellow/e/bill_parsers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
43
43
|
chellow/e/bill_parsers/activity_mop_stark_xlsx.py,sha256=UgWXDPzQkQghyj_lfgBqoSJpHB-t-qOdSaB8qY6GLog,4071
|
|
44
44
|
chellow/e/bill_parsers/annual_mop_stark_xlsx.py,sha256=-HMoIfa_utXYKA44RuC0Xqv3vd2HLeQU_4P0iBUd3WA,4219
|
|
@@ -187,8 +187,8 @@ chellow/templates/e/dc_contract.html,sha256=b6DLDrGdzN9Rri56pFvfpE7QZKYXGHib2veY
|
|
|
187
187
|
chellow/templates/e/dc_contract_edit.html,sha256=YraU0_MTBjmzBCMdsuvtIYm7K58hnDly5wUZ-6n8XzY,2148
|
|
188
188
|
chellow/templates/e/dc_contract_hh_import.html,sha256=UODiBFNohb60MjH1w-9JW1JE0O9GR2uKPGw-lD7Da5g,848
|
|
189
189
|
chellow/templates/e/dc_contract_hh_imports.html,sha256=eXFDGyzSgag4JRism81_p5yTzQOjCIXaVkQ8tl3dDcM,8172
|
|
190
|
-
chellow/templates/e/dc_contract_properties.html,sha256=
|
|
191
|
-
chellow/templates/e/dc_contract_properties_edit.html,sha256=
|
|
190
|
+
chellow/templates/e/dc_contract_properties.html,sha256=2EmA91gYWZcTOHQ3PxXQrpTOb8dm0OGjwRWsW6qNI9s,455
|
|
191
|
+
chellow/templates/e/dc_contract_properties_edit.html,sha256=TGYcHTlWbk5WmjZPkdbHhRVZcOpEfhowCp2penZcGiE,1704
|
|
192
192
|
chellow/templates/e/dc_contracts.html,sha256=v8czpEcMzndngfWNXIKXib6Xrz9OwJjQAmNQNrQ6Y08,1705
|
|
193
193
|
chellow/templates/e/dc_contracts_add.html,sha256=2lrGrNqAoKp16OiMoNDNlJxBMW3QdSPfgEFheSg826s,710
|
|
194
194
|
chellow/templates/e/dc_rate_script.html,sha256=gfKUHV2IMsTQT-cYfjl4aiEBqGEWSj3uW22UZpoyGq4,1219
|
|
@@ -363,6 +363,6 @@ chellow/templates/g/supply_note_edit.html,sha256=6UQf_qbhFDys3cVsTp-c7ABWZpggW9R
|
|
|
363
363
|
chellow/templates/g/supply_notes.html,sha256=WR3YwGh_qqTklSJ7JqWX6BKBc9rk_jMff4RiWZiF2CM,936
|
|
364
364
|
chellow/templates/g/unit.html,sha256=KouNVU0-i84afANkLQ_heJ0uDfJ9H5A05PuLqb8iCN8,438
|
|
365
365
|
chellow/templates/g/units.html,sha256=p5Nd-lAIboKPEOO6N451hx1bcKxMg4BDODnZ-43MmJc,441
|
|
366
|
-
chellow-
|
|
367
|
-
chellow-
|
|
368
|
-
chellow-
|
|
366
|
+
chellow-1712929217.0.0.dist-info/METADATA,sha256=y7dYnKInV3Z2jmy6Z1aKrqsJ-hwDU4ncat88dfZKzmo,12205
|
|
367
|
+
chellow-1712929217.0.0.dist-info/WHEEL,sha256=as-1oFTWSeWBgyzh0O_qF439xqBe6AbBgt4MfYe5zwY,87
|
|
368
|
+
chellow-1712929217.0.0.dist-info/RECORD,,
|
|
File without changes
|