arthexis 0.1.13__py3-none-any.whl → 0.1.15__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.
Files changed (108) hide show
  1. {arthexis-0.1.13.dist-info → arthexis-0.1.15.dist-info}/METADATA +224 -221
  2. arthexis-0.1.15.dist-info/RECORD +110 -0
  3. {arthexis-0.1.13.dist-info → arthexis-0.1.15.dist-info}/licenses/LICENSE +674 -674
  4. config/__init__.py +5 -5
  5. config/active_app.py +15 -15
  6. config/asgi.py +43 -43
  7. config/auth_app.py +7 -7
  8. config/celery.py +32 -32
  9. config/context_processors.py +67 -69
  10. config/horologia_app.py +7 -7
  11. config/loadenv.py +11 -11
  12. config/logging.py +59 -48
  13. config/middleware.py +25 -25
  14. config/offline.py +49 -49
  15. config/settings.py +691 -682
  16. config/settings_helpers.py +109 -109
  17. config/urls.py +171 -166
  18. config/wsgi.py +17 -17
  19. core/admin.py +3795 -2809
  20. core/admin_history.py +50 -50
  21. core/admindocs.py +151 -151
  22. core/apps.py +356 -272
  23. core/auto_upgrade.py +57 -57
  24. core/backends.py +265 -236
  25. core/changelog.py +342 -0
  26. core/entity.py +149 -133
  27. core/environment.py +61 -61
  28. core/fields.py +168 -168
  29. core/form_fields.py +75 -75
  30. core/github_helper.py +188 -25
  31. core/github_issues.py +178 -172
  32. core/github_repos.py +72 -0
  33. core/lcd_screen.py +78 -78
  34. core/liveupdate.py +25 -25
  35. core/log_paths.py +114 -100
  36. core/mailer.py +85 -85
  37. core/middleware.py +91 -91
  38. core/models.py +3637 -2795
  39. core/notifications.py +105 -105
  40. core/public_wifi.py +267 -227
  41. core/reference_utils.py +108 -108
  42. core/release.py +840 -368
  43. core/rfid_import_export.py +113 -0
  44. core/sigil_builder.py +149 -149
  45. core/sigil_context.py +20 -20
  46. core/sigil_resolver.py +315 -315
  47. core/system.py +952 -493
  48. core/tasks.py +408 -394
  49. core/temp_passwords.py +181 -181
  50. core/test_system_info.py +186 -139
  51. core/tests.py +2168 -1521
  52. core/tests_liveupdate.py +17 -17
  53. core/urls.py +11 -11
  54. core/user_data.py +641 -633
  55. core/views.py +2201 -1417
  56. core/widgets.py +213 -94
  57. core/workgroup_urls.py +17 -17
  58. core/workgroup_views.py +94 -94
  59. nodes/admin.py +1720 -1161
  60. nodes/apps.py +87 -85
  61. nodes/backends.py +160 -160
  62. nodes/dns.py +203 -203
  63. nodes/feature_checks.py +133 -133
  64. nodes/lcd.py +165 -165
  65. nodes/models.py +1764 -1597
  66. nodes/reports.py +411 -411
  67. nodes/rfid_sync.py +195 -0
  68. nodes/signals.py +18 -0
  69. nodes/tasks.py +46 -46
  70. nodes/tests.py +3830 -3116
  71. nodes/urls.py +15 -14
  72. nodes/utils.py +121 -105
  73. nodes/views.py +683 -619
  74. ocpp/admin.py +948 -948
  75. ocpp/apps.py +25 -25
  76. ocpp/consumers.py +1565 -1459
  77. ocpp/evcs.py +844 -844
  78. ocpp/evcs_discovery.py +158 -158
  79. ocpp/models.py +917 -917
  80. ocpp/reference_utils.py +42 -42
  81. ocpp/routing.py +11 -11
  82. ocpp/simulator.py +745 -745
  83. ocpp/status_display.py +26 -26
  84. ocpp/store.py +601 -541
  85. ocpp/tasks.py +31 -31
  86. ocpp/test_export_import.py +130 -130
  87. ocpp/test_rfid.py +913 -702
  88. ocpp/tests.py +4445 -4094
  89. ocpp/transactions_io.py +189 -189
  90. ocpp/urls.py +50 -50
  91. ocpp/views.py +1479 -1251
  92. pages/admin.py +769 -539
  93. pages/apps.py +10 -10
  94. pages/checks.py +40 -40
  95. pages/context_processors.py +127 -119
  96. pages/defaults.py +13 -13
  97. pages/forms.py +198 -198
  98. pages/middleware.py +209 -153
  99. pages/models.py +643 -426
  100. pages/tasks.py +74 -0
  101. pages/tests.py +3025 -2200
  102. pages/urls.py +26 -25
  103. pages/utils.py +23 -12
  104. pages/views.py +1176 -1128
  105. arthexis-0.1.13.dist-info/RECORD +0 -105
  106. nodes/actions.py +0 -70
  107. {arthexis-0.1.13.dist-info → arthexis-0.1.15.dist-info}/WHEEL +0 -0
  108. {arthexis-0.1.13.dist-info → arthexis-0.1.15.dist-info}/top_level.txt +0 -0
ocpp/evcs_discovery.py CHANGED
@@ -1,158 +1,158 @@
1
- from __future__ import annotations
2
-
3
- import subprocess
4
- from dataclasses import dataclass
5
- from ipaddress import IPv4Address
6
- from typing import Iterable, Sequence
7
-
8
- DEFAULT_TOP_PORTS = 200
9
- DEFAULT_CONSOLE_PORT = 8900
10
- PORT_PREFERENCES: Sequence[int] = (
11
- DEFAULT_CONSOLE_PORT,
12
- 8443,
13
- 9443,
14
- 443,
15
- 8080,
16
- 8800,
17
- 8000,
18
- 8001,
19
- 8880,
20
- 80,
21
- )
22
- HTTPS_PORTS = {443, 8443, 9443}
23
-
24
-
25
- @dataclass(frozen=True)
26
- class ConsoleEndpoint:
27
- host: str
28
- port: int
29
- secure: bool = False
30
-
31
- @property
32
- def url(self) -> str:
33
- return build_console_url(self.host, self.port, self.secure)
34
-
35
-
36
- def scan_open_ports(
37
- host: str,
38
- *,
39
- nmap_path: str = "nmap",
40
- full: bool = False,
41
- top_ports: int = DEFAULT_TOP_PORTS,
42
- ) -> list[int]:
43
- """Return the list of open TCP ports discovered with nmap.
44
-
45
- The function mirrors the behaviour of the ``evcs_discover`` shell script.
46
- It uses nmap's grepable output so the caller can avoid touching the
47
- filesystem and parse the results quickly.
48
- """
49
-
50
- port_args: list[str]
51
- if full:
52
- port_args = ["-p-"]
53
- else:
54
- if top_ports <= 0:
55
- raise ValueError("top_ports must be greater than zero")
56
- port_args = ["--top-ports", str(top_ports)]
57
-
58
- args = [
59
- nmap_path,
60
- "-sS",
61
- "-Pn",
62
- "-n",
63
- "-T4",
64
- "--open",
65
- *port_args,
66
- host,
67
- "-oG",
68
- "-",
69
- ]
70
-
71
- try:
72
- proc = subprocess.run(
73
- args,
74
- check=False,
75
- capture_output=True,
76
- text=True,
77
- )
78
- except FileNotFoundError:
79
- return []
80
- except subprocess.SubprocessError:
81
- return []
82
-
83
- if proc.returncode != 0:
84
- return []
85
-
86
- return _parse_nmap_open_ports(proc.stdout)
87
-
88
-
89
- def _parse_nmap_open_ports(output: str) -> list[int]:
90
- ports: list[int] = []
91
- for line in output.splitlines():
92
- if "Ports:" not in line:
93
- continue
94
- try:
95
- _, ports_section = line.split("Ports:", 1)
96
- except ValueError:
97
- continue
98
- for entry in ports_section.split(","):
99
- entry = entry.strip()
100
- if not entry:
101
- continue
102
- parts = entry.split("/")
103
- if len(parts) < 2:
104
- continue
105
- state = parts[1].strip().lower()
106
- if state != "open":
107
- continue
108
- try:
109
- port = int(parts[0])
110
- except ValueError:
111
- continue
112
- if port not in ports:
113
- ports.append(port)
114
- return ports
115
-
116
-
117
- def prioritise_ports(ports: Iterable[int]) -> list[int]:
118
- """Order ports so the most likely console endpoints are tried first."""
119
-
120
- unique = []
121
- seen = set()
122
- available = list(dict.fromkeys(ports))
123
- for preferred in PORT_PREFERENCES:
124
- if preferred in available and preferred not in seen:
125
- unique.append(preferred)
126
- seen.add(preferred)
127
- for port in available:
128
- if port not in seen:
129
- unique.append(port)
130
- seen.add(port)
131
- return unique
132
-
133
-
134
- def select_console_port(ports: Sequence[int]) -> ConsoleEndpoint | None:
135
- """Pick the best console port from a list of open ports."""
136
-
137
- if not ports:
138
- return None
139
- ordered = prioritise_ports(ports)
140
- if not ordered:
141
- return None
142
- port = ordered[0]
143
- secure = port in HTTPS_PORTS
144
- return ConsoleEndpoint(host="", port=port, secure=secure)
145
-
146
-
147
- def build_console_url(host: str, port: int, secure: bool) -> str:
148
- scheme = "https" if secure else "http"
149
- host_part = host
150
- if ":" in host and not host.startswith("["):
151
- host_part = f"[{host}]"
152
- return f"{scheme}://{host_part}:{port}"
153
-
154
-
155
- def normalise_host(host: str | IPv4Address) -> str:
156
- if isinstance(host, IPv4Address):
157
- return str(host)
158
- return str(host)
1
+ from __future__ import annotations
2
+
3
+ import subprocess
4
+ from dataclasses import dataclass
5
+ from ipaddress import IPv4Address
6
+ from typing import Iterable, Sequence
7
+
8
+ DEFAULT_TOP_PORTS = 200
9
+ DEFAULT_CONSOLE_PORT = 8900
10
+ PORT_PREFERENCES: Sequence[int] = (
11
+ DEFAULT_CONSOLE_PORT,
12
+ 8443,
13
+ 9443,
14
+ 443,
15
+ 8080,
16
+ 8800,
17
+ 8000,
18
+ 8001,
19
+ 8880,
20
+ 80,
21
+ )
22
+ HTTPS_PORTS = {443, 8443, 9443}
23
+
24
+
25
+ @dataclass(frozen=True)
26
+ class ConsoleEndpoint:
27
+ host: str
28
+ port: int
29
+ secure: bool = False
30
+
31
+ @property
32
+ def url(self) -> str:
33
+ return build_console_url(self.host, self.port, self.secure)
34
+
35
+
36
+ def scan_open_ports(
37
+ host: str,
38
+ *,
39
+ nmap_path: str = "nmap",
40
+ full: bool = False,
41
+ top_ports: int = DEFAULT_TOP_PORTS,
42
+ ) -> list[int]:
43
+ """Return the list of open TCP ports discovered with nmap.
44
+
45
+ The function mirrors the behaviour of the ``evcs_discover`` shell script.
46
+ It uses nmap's grepable output so the caller can avoid touching the
47
+ filesystem and parse the results quickly.
48
+ """
49
+
50
+ port_args: list[str]
51
+ if full:
52
+ port_args = ["-p-"]
53
+ else:
54
+ if top_ports <= 0:
55
+ raise ValueError("top_ports must be greater than zero")
56
+ port_args = ["--top-ports", str(top_ports)]
57
+
58
+ args = [
59
+ nmap_path,
60
+ "-sS",
61
+ "-Pn",
62
+ "-n",
63
+ "-T4",
64
+ "--open",
65
+ *port_args,
66
+ host,
67
+ "-oG",
68
+ "-",
69
+ ]
70
+
71
+ try:
72
+ proc = subprocess.run(
73
+ args,
74
+ check=False,
75
+ capture_output=True,
76
+ text=True,
77
+ )
78
+ except FileNotFoundError:
79
+ return []
80
+ except subprocess.SubprocessError:
81
+ return []
82
+
83
+ if proc.returncode != 0:
84
+ return []
85
+
86
+ return _parse_nmap_open_ports(proc.stdout)
87
+
88
+
89
+ def _parse_nmap_open_ports(output: str) -> list[int]:
90
+ ports: list[int] = []
91
+ for line in output.splitlines():
92
+ if "Ports:" not in line:
93
+ continue
94
+ try:
95
+ _, ports_section = line.split("Ports:", 1)
96
+ except ValueError:
97
+ continue
98
+ for entry in ports_section.split(","):
99
+ entry = entry.strip()
100
+ if not entry:
101
+ continue
102
+ parts = entry.split("/")
103
+ if len(parts) < 2:
104
+ continue
105
+ state = parts[1].strip().lower()
106
+ if state != "open":
107
+ continue
108
+ try:
109
+ port = int(parts[0])
110
+ except ValueError:
111
+ continue
112
+ if port not in ports:
113
+ ports.append(port)
114
+ return ports
115
+
116
+
117
+ def prioritise_ports(ports: Iterable[int]) -> list[int]:
118
+ """Order ports so the most likely console endpoints are tried first."""
119
+
120
+ unique = []
121
+ seen = set()
122
+ available = list(dict.fromkeys(ports))
123
+ for preferred in PORT_PREFERENCES:
124
+ if preferred in available and preferred not in seen:
125
+ unique.append(preferred)
126
+ seen.add(preferred)
127
+ for port in available:
128
+ if port not in seen:
129
+ unique.append(port)
130
+ seen.add(port)
131
+ return unique
132
+
133
+
134
+ def select_console_port(ports: Sequence[int]) -> ConsoleEndpoint | None:
135
+ """Pick the best console port from a list of open ports."""
136
+
137
+ if not ports:
138
+ return None
139
+ ordered = prioritise_ports(ports)
140
+ if not ordered:
141
+ return None
142
+ port = ordered[0]
143
+ secure = port in HTTPS_PORTS
144
+ return ConsoleEndpoint(host="", port=port, secure=secure)
145
+
146
+
147
+ def build_console_url(host: str, port: int, secure: bool) -> str:
148
+ scheme = "https" if secure else "http"
149
+ host_part = host
150
+ if ":" in host and not host.startswith("["):
151
+ host_part = f"[{host}]"
152
+ return f"{scheme}://{host_part}:{port}"
153
+
154
+
155
+ def normalise_host(host: str | IPv4Address) -> str:
156
+ if isinstance(host, IPv4Address):
157
+ return str(host)
158
+ return str(host)