chellow 1731581146.0.0__py3-none-any.whl → 1733390302.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.

@@ -147,6 +147,7 @@ READ_TYPE_LOOKUP = {
147
147
  " ": "E",
148
148
  "E": "E",
149
149
  "N": "N",
150
+ "S": "N",
150
151
  }
151
152
 
152
153
 
@@ -4,7 +4,12 @@ from codecs import iterdecode
4
4
 
5
5
  from werkzeug.exceptions import BadRequest
6
6
 
7
- from chellow.utils import HH, parse_mpan_core, utc_datetime
7
+ from chellow.utils import HH, hh_format, parse_mpan_core, utc_datetime
8
+
9
+
10
+ def _append_new_message(messages, message):
11
+ if len(messages) == 0 or messages[-1] != message:
12
+ messages.append(message)
8
13
 
9
14
 
10
15
  def create_parser(reader, mpan_map, messages):
@@ -41,14 +46,6 @@ class StarkDf2HhParser:
41
46
  if lline.startswith("#O"):
42
47
  outstation_parts = lline[2:].split("-")
43
48
  self.core = parse_mpan_core(outstation_parts[0])
44
- if self.core in self.mpan_map and self.mpan_map[self.core] is None:
45
- msg = f"The MPAN core {self.core} has been ignored"
46
- if len(self.messages) == 0 or self.messages[-1] != msg:
47
- self.messages.append(
48
- f"The MPAN core {self.core} has been ignored"
49
- )
50
- self.core = None
51
- continue
52
49
 
53
50
  elif lline.startswith("#S"):
54
51
  sensor = int(lline[2:].strip())
@@ -87,11 +84,31 @@ class StarkDf2HhParser:
87
84
  raise BadRequest("Problem parsing the value: " + fields[2])
88
85
  status = fields[3][-1]
89
86
 
90
- if self.core is None:
91
- continue
87
+ mpan_core = self.core
88
+ if self.core in self.mpan_map:
89
+ mapping = self.mpan_map[self.core]
90
+ from_date = mapping["from"]
91
+ to_date = mapping["to"]
92
+ if from_date <= start_date <= to_date:
93
+ mpan_core = mapping["mpan"]
94
+
95
+ if mpan_core is None:
96
+ _append_new_message(
97
+ self.messages,
98
+ f"The MPAN core {self.core} is ignored from "
99
+ f"{hh_format(from_date)} to {hh_format(to_date)}",
100
+ )
101
+ continue
102
+ else:
103
+ _append_new_message(
104
+ self.messages,
105
+ f"The MPAN core {self.core} is changed to "
106
+ f"{mpan_core} from {hh_format(from_date)} to "
107
+ f"{hh_format(to_date)}",
108
+ )
92
109
 
93
110
  local_datum = {
94
- "mpan_core": self.core,
111
+ "mpan_core": mpan_core,
95
112
  "channel_type": self.channel_type,
96
113
  "start_date": start_date,
97
114
  "value": value,
chellow/general_import.py CHANGED
@@ -1704,21 +1704,43 @@ for k in tuple(globals().keys()):
1704
1704
  typ_funcs[k[len(PREFIX) :]] = globals()[k]
1705
1705
 
1706
1706
 
1707
+ def _process_line(sess, hh_data, line, args):
1708
+
1709
+ action = add_arg(args, "action", line, 0).lower()
1710
+ if action not in ALLOWED_ACTIONS:
1711
+ raise BadRequest(f"The 'action' field must be one of {ALLOWED_ACTIONS}")
1712
+ typ = add_arg(args, "type", line, 1).lower()
1713
+ vals = line[2:]
1714
+ if typ == "hh_datum":
1715
+ if action == "insert":
1716
+ hh_data.append(
1717
+ {
1718
+ "mpan_core": parse_mpan_core(add_arg(args, "MPAN Core", vals, 0)),
1719
+ "start_date": parse_hh_start(add_arg(args, "Start Date", vals, 1)),
1720
+ "channel_type": parse_channel_type(
1721
+ add_arg(args, "Channel Type", vals, 2)
1722
+ ),
1723
+ "value": Decimal(add_arg(args, "Value", vals, 3)),
1724
+ "status": add_arg(args, "Status", vals, 4),
1725
+ }
1726
+ )
1727
+ else:
1728
+ try:
1729
+ typ_func = typ_funcs[typ]
1730
+ typ_func(sess, action, vals, args)
1731
+ except KeyError:
1732
+ raise BadRequest(f"The type {typ} is not recognized.")
1733
+
1734
+
1707
1735
  class GeneralImporter(threading.Thread):
1708
1736
  def __init__(self, f):
1709
1737
  threading.Thread.__init__(self)
1710
1738
  self.line_number = None
1711
1739
  self.f = f
1712
- self.rd_lock = threading.Lock()
1713
1740
  self.error_message = None
1714
1741
  self.args = []
1715
- self.hh_data = []
1716
-
1717
- def get_fields(self):
1718
- fields = {"line_number": self.line_number, "error_message": self.error_message}
1719
- if self.error_message is not None:
1720
- fields["csv_line"] = self.args
1721
- return fields
1742
+ self.failed_args = []
1743
+ self.failed_lines = []
1722
1744
 
1723
1745
  def run(self):
1724
1746
  try:
@@ -1735,63 +1757,32 @@ class GeneralImporter(threading.Thread):
1735
1757
  if len(line) > 0 and line[0].startswith("#"):
1736
1758
  continue
1737
1759
 
1738
- action = add_arg(self.args, "action", line, 0).lower()
1739
- if action not in ALLOWED_ACTIONS:
1740
- raise BadRequest(
1741
- f"The 'action' field must be one of {ALLOWED_ACTIONS}"
1742
- )
1743
- typ = add_arg(self.args, "type", line, 1).lower()
1744
- vals = line[2:]
1745
- if typ == "hh_datum":
1746
- if action == "insert":
1747
- hh_data.append(
1748
- {
1749
- "mpan_core": parse_mpan_core(
1750
- add_arg(self.args, "MPAN Core", vals, 0)
1751
- ),
1752
- "start_date": parse_hh_start(
1753
- add_arg(self.args, "Start Date", vals, 1)
1754
- ),
1755
- "channel_type": parse_channel_type(
1756
- add_arg(self.args, "Channel Type", vals, 2)
1757
- ),
1758
- "value": Decimal(
1759
- add_arg(self.args, "Value", vals, 3)
1760
- ),
1761
- "status": add_arg(self.args, "Status", vals, 4),
1762
- }
1763
- )
1764
- else:
1765
- try:
1766
- typ_func = typ_funcs[typ]
1767
- typ_func(sess, action, vals, self.args)
1768
- except KeyError:
1769
- raise BadRequest(f"The type {typ} is not recognized.")
1760
+ try:
1761
+ with sess.begin_nested():
1762
+ _process_line(sess, hh_data, line, self.args)
1763
+
1764
+ except BadRequest as e:
1765
+ self.args.insert(0, ("Error", e.description))
1766
+ self.failed_args.append(self.args)
1767
+ self.failed_lines.append(line)
1770
1768
 
1771
1769
  HhDatum.insert(sess, hh_data)
1772
- sess.commit()
1770
+
1771
+ if len(self.failed_lines) == 0:
1772
+ sess.commit()
1773
+ else:
1774
+ sess.rollback()
1773
1775
  except BadRequest as e:
1774
- try:
1775
- self.rd_lock.acquire()
1776
- self.error_message = e.description
1777
- finally:
1778
- self.rd_lock.release()
1776
+ self.error_message = e.description
1779
1777
  except BaseException:
1780
- try:
1781
- self.rd_lock.acquire()
1782
- self.error_message = traceback.format_exc()
1783
- finally:
1784
- self.rd_lock.release()
1778
+ self.error_message = traceback.format_exc()
1785
1779
 
1786
1780
 
1787
1781
  def start_process(f):
1788
- try:
1782
+ with process_lock:
1789
1783
  global process_id
1790
- process_lock.acquire()
1791
1784
  proc_id = process_id
1792
1785
  process_id += 1
1793
- finally:
1794
- process_lock.release()
1795
1786
 
1796
1787
  process = GeneralImporter(f)
1797
1788
  processes[proc_id] = process
@@ -1800,16 +1791,9 @@ def start_process(f):
1800
1791
 
1801
1792
 
1802
1793
  def get_process_ids():
1803
- try:
1804
- process_lock.acquire()
1794
+ with process_lock:
1805
1795
  return processes.keys()
1806
- finally:
1807
- process_lock.release()
1808
1796
 
1809
1797
 
1810
1798
  def get_process(id):
1811
- try:
1812
- process_lock.acquire()
1813
- return processes[id]
1814
- finally:
1815
- process_lock.release()
1799
+ return processes[id]
@@ -39,8 +39,17 @@
39
39
  "private_key": "private_key", /* Remove if using password */
40
40
  "directories": ["downloads1", "downloads2"],
41
41
  "mpan_map": { /* Optional */
42
- "99 0993 2821 985": null, /* Ignore MPAN */
43
- },
42
+ "99 0993 2821 985": {
43
+ "mpan": null, /* Ignore MPAN */
44
+ "from": 2024-12-04T10:00:00Z,
45
+ "to": 2025-01-12:00:00Z,
46
+ },
47
+ "99 0873 1942 952": {
48
+ "mpan": "99 7821 8541 389",
49
+ "from": 2024-11-16T22:00:00Z,
50
+ "to": 2025-02-18:00:00Z,
51
+ },
52
+ },
44
53
  }
45
54
  </pre>
46
55
  </code>
@@ -1,47 +1,64 @@
1
1
  {% extends "base.html" %}
2
2
 
3
3
  {% block title %}
4
- &raquo; General Imports &raquo; {{process_id}}
4
+ &raquo; General Imports &raquo; {{import_id}}
5
5
  {% endblock %}
6
6
 
7
7
  {% block nav %}
8
8
  <a href="/general_imports">General Imports</a> &raquo;
9
- {{process_id}}
9
+ {{import_id}}
10
10
  {% endblock %}
11
11
 
12
12
  {% block content %}
13
- {% if line_number %}
14
- <p>Line number {{line_number}}.</p>
13
+ {% if importer.line_number %}
14
+ <p>Line number {{importer.line_number}}.</p>
15
15
  {% endif %}
16
16
 
17
- {% if is_alive %}
17
+ {% if importer.is_alive() %}
18
18
  <p>Still running. Refresh the page to see latest progress.</p>
19
19
  {% else %}
20
- {% if error_message %}
21
- <p>
22
- The import has failed and so the whole import has been rolled
23
- back. The reason for the failure is:</p>
24
- <pre>{{error_message}}</pre>
20
+ {% if importer.failed_args|length > 0 %}
21
+ <p>
22
+ The import has failed and so the whole import has been rolled back.
23
+ </p>
24
+
25
+ <h3>Failed Lines</h3>
26
+
27
+ {% for line in importer.failed_args %}
28
+
29
+ <table>
30
+ <tbody>
31
+ <tr>
32
+ {% for title, value in line %}
33
+ <th>{{title}}</th>
34
+ {% endfor %}
35
+ </tr>
36
+ <tr>
37
+ {% for title, value in line %}
38
+ <td>{{value}}</td>
39
+ {% endfor %}
40
+ </tr>
41
+ </tbody>
42
+ </table>
43
+ {% endfor %}
44
+
45
+ <h3>Failed Input</h3>
46
+
47
+ <table>
48
+ <tbody>
49
+ {% for line in importer.failed_lines %}
50
+ <tr>
51
+ {% for value in line %}
52
+ <td>{{value}}</td>
53
+ {% endfor %}
54
+ </tr>
55
+ {% endfor %}
56
+ </tbody>
57
+ </table>
58
+ {% elif importer.error_message %}
59
+ <p>{{importer.error_message}}</p>
25
60
  {% else %}
26
- <p>The file has been imported successfully.</p>
61
+ <p>The file has been imported successfully.</p>
27
62
  {% endif %}
28
63
  {% endif %}
29
-
30
- {% if csv_line %}
31
- <table>
32
- <caption>Failed Line</caption>
33
- <tbody>
34
- <tr>
35
- {% for title, value in csv_line %}
36
- <th>{{title}}</th>
37
- {% endfor %}
38
- </tr>
39
- <tr>
40
- {% for title, value in csv_line %}
41
- <td>{{value}}</td>
42
- {% endfor %}
43
- </tr>
44
- </tbody>
45
- </table>
46
- {% endif %}
47
64
  {% endblock %}
chellow/views.py CHANGED
@@ -755,14 +755,13 @@ def general_imports_post():
755
755
  @home.route("/general_imports/<int:import_id>")
756
756
  def general_import_get(import_id):
757
757
  try:
758
- proc = chellow.general_import.get_process(import_id)
759
- fields = proc.get_fields()
760
- fields["is_alive"] = proc.is_alive()
761
- fields["process_id"] = import_id
762
- return render_template("general_import.html", **fields)
758
+ importer = chellow.general_import.get_process(import_id)
759
+ return render_template(
760
+ "general_import.html", import_id=import_id, importer=importer
761
+ )
763
762
  except BadRequest as e:
764
763
  flash(e.description)
765
- return render_template("general_import.html", process_id=import_id)
764
+ return render_template("general_import.html", import_id=import_id)
766
765
 
767
766
 
768
767
  @home.route("/edi_viewer")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: chellow
3
- Version: 1731581146.0.0
3
+ Version: 1733390302.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)
@@ -4,7 +4,7 @@ chellow/bank_holidays.py,sha256=T_utYMwe_g1dz5X-aOTdIPryg49SvB7QsWM1yphlqG8,4423
4
4
  chellow/commands.py,sha256=ESBe9ZWj1c3vdZgqMZ9gFvYAB3hRag2R1PzOwuw9yFo,1302
5
5
  chellow/dloads.py,sha256=dixp-O0MF2_mlwrnKx3D9DH09Qu05BjTo0rZfigTjR4,5534
6
6
  chellow/edi_lib.py,sha256=alu20x9ZX06iPfnNI9dEJzuP6RIf4We3Y_M_bl7RrcY,51789
7
- chellow/general_import.py,sha256=5kJszUnk3CVJclsW-mCjLF0z8lw7CaNNhIzUoaq20kY,65965
7
+ chellow/general_import.py,sha256=tcYZK2N7HOFJSkYyy3MMxVBEvMFjfB9pjF0ksujtkFA,65113
8
8
  chellow/models.py,sha256=9LLROzS6gXZGICk0ITXhCyTtKaIY7HW4bMqWg4Mc-xw,244221
9
9
  chellow/national_grid.py,sha256=czwIZqzJndSGhEMQ5YzI6hRBhvjkM6VRVYXybf4_KXg,4377
10
10
  chellow/proxy.py,sha256=cVXIktPlX3tQ1BYcwxq0nJXKE6r3DtFTtfFHPq55HaM,1351
@@ -12,7 +12,7 @@ chellow/rate_server.py,sha256=fg-Pf_9Hk3bXmC9riPQNGQxBvLvBa_WtNYdwDCjnCSg,5678
12
12
  chellow/rrun.py,sha256=1Kt2q_K9UoDG_nsZz-Q6XJiMNKroWqlqFdxn2M6Q8CA,2088
13
13
  chellow/testing.py,sha256=Od4HHH6pZrhJ_De118_F55RJEKmAvhUH2S24QE9qFQk,3635
14
14
  chellow/utils.py,sha256=32qPWEGzCPKPhSM7ztpzcR6ZG74sVZanScDIdK50Rq4,19308
15
- chellow/views.py,sha256=eb7WUqqu7LmAX5m_9ICJFVpo0i8WZ9GV89AkqRA3aac,84383
15
+ chellow/views.py,sha256=qJrvhVjb3KL_sHDQl5dLhi0aqUe_IUYhrjiPjdk4lQI,84317
16
16
  chellow/e/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  chellow/e/aahedc.py,sha256=d2usudp7KYWpU6Pk3fal5EQ47EbvkvKeaFGylnb3NWw,606
18
18
  chellow/e/bill_importer.py,sha256=7UcnqNlKbJc2GhW9gy8sDp9GuqambJVpZLvbafOZztA,7411
@@ -27,7 +27,7 @@ chellow/e/elexon.py,sha256=ALhXS9Es7PV0z9ukPbIramn3cf3iLyFi-PMWPSm5iOs,5487
27
27
  chellow/e/energy_management.py,sha256=aXC2qlGt3FAODlNl_frWzVYAQrJLP8FFOiNX3m-QE_Y,12388
28
28
  chellow/e/hh_importer.py,sha256=adfogJgPWsJurPOVSBLLQ7m68s1LhfQmDYpAFnGm0eM,21510
29
29
  chellow/e/hh_parser_bg_csv.py,sha256=W5SU2MSpa8BGA0VJw1JXF-IwbCNLFy8fe35yxLZ7gEw,2453
30
- chellow/e/hh_parser_df2.py,sha256=tRAoVUUoJDlfPopm6usEBnhJz7dXMc2_KEWbkW9Gyq4,4330
30
+ chellow/e/hh_parser_df2.py,sha256=nZT198EZWo_G26IfJZncI_kOo-UdsXzFYDmDf3qyEs8,5089
31
31
  chellow/e/hh_parser_edf_csv.py,sha256=CLkkL1Z6BPgVV_3uwS6McmtMzgXkoEIoJnH8FsQk1C8,2839
32
32
  chellow/e/hh_parser_schneider_csv.py,sha256=m8FHwXp1Tbas91RPS7TriCskSNRuSaFf1SD9v2HXfSk,2366
33
33
  chellow/e/hh_parser_schneider_xlsx.py,sha256=Vtq0TNz-oojoKJm4PeH4ZwBp2I-mjArB9-FL71ctCHs,3590
@@ -58,7 +58,7 @@ chellow/e/bill_parsers/gdf_csv.py,sha256=ZfK3Oc6oP28p_P9DIevLNB_zW2WLcEJ3Lvb1gL3
58
58
  chellow/e/bill_parsers/haven_csv.py,sha256=0uENq8IgVNqdxfBQMBxLTSZWCOuDHXZC0xzk52SbfyE,13652
59
59
  chellow/e/bill_parsers/haven_edi.py,sha256=YGPHRxPOhje9s32jqPHHELni2tooOYj3cMC_qaZVPq4,16107
60
60
  chellow/e/bill_parsers/haven_edi_tprs.py,sha256=ZVX9CCqUybsot_Z0BEOJPvl9x5kSr7fEWyuJXvZDcz4,11841
61
- chellow/e/bill_parsers/mm.py,sha256=zeNF5F8uduQeEFjYOm5lfMS-DO3JjTB7oarA3H_Si5s,10019
61
+ chellow/e/bill_parsers/mm.py,sha256=jFy5KlUnqfO0dsGgLMCEYAw0LPBIMBa9NDa-5ob2GwM,10033
62
62
  chellow/e/bill_parsers/nonsettlement_dc_stark_xlsx.py,sha256=yogXTuQHGRL7IiqvRWr2C9V24ez1j9Yx0128UygPE_k,4723
63
63
  chellow/e/bill_parsers/settlement_dc_stark_xlsx.py,sha256=PlEqCZuJ9DfQXeeYQ64jtf3ML7sUt_tt61QOOTnkE5c,6380
64
64
  chellow/e/bill_parsers/sse_edi.py,sha256=L85DOfNkqexeEIEr8pCBn_2sHJI-zEaw6cogpE3YyYM,15204
@@ -121,7 +121,7 @@ chellow/templates/chain.html,sha256=iOnSoDQOO_-1tfcxUHQKDAUnV4QbCYu5PPNmS4RkOg4,
121
121
  chellow/templates/csv_sites_monthly_duration.html,sha256=59gErG6KwA57z-qh2EJsVGvTUazqm85CSXefSfqPWcQ,486
122
122
  chellow/templates/downloads.html,sha256=R9QPcFz-PLJOX7rDlmquIk-Hp9Iq-thzWCTfOexSpXg,937
123
123
  chellow/templates/edi_viewer.html,sha256=szUthgHOdph6Of-7f_1LeC_zYlNJaMeS5ctn6xTAeiM,1437
124
- chellow/templates/general_import.html,sha256=SMemHGu466Be3_cAWSS6Hn-Kv-1psbEMDD6NQG6bfbI,1013
124
+ chellow/templates/general_import.html,sha256=9ezzieDjaPBZ0nUJkMkzoDxWVzYtr4D-Dr2UCA5xV8U,1370
125
125
  chellow/templates/general_imports.html,sha256=VRmBqYsXsirm880WiFrJ3CknAXAoLR9Mnpz9cKjIeM8,13069
126
126
  chellow/templates/home.html,sha256=illtSabepcScYwmKss0o2gwvjXGBtr6LkfwmeL6ezSA,5655
127
127
  chellow/templates/input_date.html,sha256=rpgB5n0LfN8Y5djN_ZiuSxqdskxzCoKrEqI7hyJkVQo,1248
@@ -202,7 +202,7 @@ chellow/templates/e/dc_contract_edit.html,sha256=IObmbHQmeZ_LSpnYgabmhoSNUR3aPmm
202
202
  chellow/templates/e/dc_contract_hh_import.html,sha256=JncR3L6cOK4jghsGyr-itEqlIemXBXt3kL09wpqnQSE,856
203
203
  chellow/templates/e/dc_contract_hh_imports.html,sha256=eXFDGyzSgag4JRism81_p5yTzQOjCIXaVkQ8tl3dDcM,8172
204
204
  chellow/templates/e/dc_contract_properties.html,sha256=2EmA91gYWZcTOHQ3PxXQrpTOb8dm0OGjwRWsW6qNI9s,455
205
- chellow/templates/e/dc_contract_properties_edit.html,sha256=TGYcHTlWbk5WmjZPkdbHhRVZcOpEfhowCp2penZcGiE,1704
205
+ chellow/templates/e/dc_contract_properties_edit.html,sha256=YWmG0dnzD6hf2kAFWCAjQWkHDPVRDi0jaUdLSLw-tfw,1901
206
206
  chellow/templates/e/dc_contracts.html,sha256=FPZUM7fkw-R6sRELHZCQTUkKSRqad8HOLHnyyYhQEEw,1819
207
207
  chellow/templates/e/dc_contracts_add.html,sha256=2lrGrNqAoKp16OiMoNDNlJxBMW3QdSPfgEFheSg826s,710
208
208
  chellow/templates/e/dc_rate_script.html,sha256=gfKUHV2IMsTQT-cYfjl4aiEBqGEWSj3uW22UZpoyGq4,1219
@@ -377,6 +377,6 @@ chellow/templates/g/supply_note_edit.html,sha256=b8mB6_ucBwoljp03iy6AgVaZUhGw3-1
377
377
  chellow/templates/g/supply_notes.html,sha256=6epNmZ3NKdXZz27fvmRUGeffg_oc1kmwuBeyRzQe3Rg,854
378
378
  chellow/templates/g/unit.html,sha256=KouNVU0-i84afANkLQ_heJ0uDfJ9H5A05PuLqb8iCN8,438
379
379
  chellow/templates/g/units.html,sha256=p5Nd-lAIboKPEOO6N451hx1bcKxMg4BDODnZ-43MmJc,441
380
- chellow-1731581146.0.0.dist-info/METADATA,sha256=nVYIrIIfi0Wd791y4tLcCZoJMu9CQO31xsJCB77Pqfc,12204
381
- chellow-1731581146.0.0.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
382
- chellow-1731581146.0.0.dist-info/RECORD,,
380
+ chellow-1733390302.0.0.dist-info/METADATA,sha256=gaYBOwq3UhXxTCphDMWhGc0rFvubI80XXISsocq3EK0,12204
381
+ chellow-1733390302.0.0.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
382
+ chellow-1733390302.0.0.dist-info/RECORD,,