networkforge 1.4.1__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.
- networkforge/__init__.py +48 -0
- networkforge/__main__.py +7 -0
- networkforge/cli.py +681 -0
- networkforge/coverage.py +176 -0
- networkforge/edits.py +460 -0
- networkforge/errors.py +87 -0
- networkforge/export.py +1056 -0
- networkforge/inputs.py +256 -0
- networkforge/modes.py +336 -0
- networkforge/network.py +703 -0
- networkforge/osm.py +450 -0
- networkforge/paths.py +113 -0
- networkforge/points.py +290 -0
- networkforge/presets.py +50 -0
- networkforge/projection.py +81 -0
- networkforge/tags.py +132 -0
- networkforge/topology.py +1086 -0
- networkforge/traffic.py +905 -0
- networkforge/turns.py +308 -0
- networkforge/validation.py +642 -0
- networkforge-1.4.1.dist-info/METADATA +336 -0
- networkforge-1.4.1.dist-info/RECORD +25 -0
- networkforge-1.4.1.dist-info/WHEEL +4 -0
- networkforge-1.4.1.dist-info/entry_points.txt +2 -0
- networkforge-1.4.1.dist-info/licenses/LICENSE +674 -0
networkforge/errors.py
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Exceptions raised by NetworkForge.
|
|
3
|
+
|
|
4
|
+
Catch NetworkForgeError to handle anything the pipeline rejects. Every
|
|
5
|
+
error has a plain-language message; `guide` names the section of
|
|
6
|
+
docs/network-rules.md that explains the fix, where there is one.
|
|
7
|
+
|
|
8
|
+
NetworkForgeError
|
|
9
|
+
├── InputError (also a ValueError) bad arguments or input data
|
|
10
|
+
│ ├── InvalidTagsError custom feature tags break OSM rules
|
|
11
|
+
│ └── NoIntersectionError custom data doesn't touch the OSM network
|
|
12
|
+
├── OSMDownloadError the OSM download failed
|
|
13
|
+
└── NetworkIntegrityError the built network breaks a structural rule
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import math
|
|
17
|
+
|
|
18
|
+
DOCS = "docs"
|
|
19
|
+
GUIDE = "network-rules.md"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def feature_id(value):
|
|
23
|
+
"""A feature id (custom data index value) as a plain JSON-friendly value."""
|
|
24
|
+
if hasattr(value, "item"): # numpy scalar
|
|
25
|
+
value = value.item()
|
|
26
|
+
if isinstance(value, float) and not math.isfinite(value):
|
|
27
|
+
return None # a feature without an id: NaN is not JSON
|
|
28
|
+
return value if isinstance(value, int | float | str) or value is None else str(value)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class NetworkForgeError(Exception):
|
|
32
|
+
"""
|
|
33
|
+
Base class for every error NetworkForge raises on purpose.
|
|
34
|
+
|
|
35
|
+
`guide` is a section of the network rules ("presets", stored as
|
|
36
|
+
"network-rules.md#presets") or of another doc in docs/
|
|
37
|
+
("osm-data.md#getting-an-extract"): always "<file>.md[#anchor]".
|
|
38
|
+
|
|
39
|
+
`issues` pinpoints problems per custom feature, as a list of
|
|
40
|
+
{"feature": id, "message": text} (feature None for problems that
|
|
41
|
+
aren't about one feature). Feature ids are the custom data's index
|
|
42
|
+
values - set the index to an id column to get your own ids.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
def __init__(self, message: str, guide: str | None = None, issues: list | None = None):
|
|
46
|
+
super().__init__(message)
|
|
47
|
+
self.guide = guide if guide is None or ".md" in guide else f"{GUIDE}#{guide}"
|
|
48
|
+
self.issues = [{"feature": feature_id(i["feature"]), "message": i["message"]}
|
|
49
|
+
for i in issues or []]
|
|
50
|
+
|
|
51
|
+
def __str__(self) -> str:
|
|
52
|
+
message = super().__str__()
|
|
53
|
+
if self.guide:
|
|
54
|
+
message += f"\n(see {DOCS}/{self.guide})"
|
|
55
|
+
return message
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class InputError(NetworkForgeError, ValueError):
|
|
59
|
+
"""An argument or the input data can't be used."""
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class InvalidTagsError(InputError):
|
|
63
|
+
"""One or more custom features have tags that break OSM rules."""
|
|
64
|
+
|
|
65
|
+
def __init__(self, issues: list[tuple]):
|
|
66
|
+
"""issues: (feature id or None, message) pairs."""
|
|
67
|
+
self.problems = [
|
|
68
|
+
message if feature is None else f"feature {feature_id(feature)}: {message}"
|
|
69
|
+
for feature, message in issues
|
|
70
|
+
]
|
|
71
|
+
super().__init__(
|
|
72
|
+
f"{len(self.problems)} custom tag problem(s):\n - " + "\n - ".join(self.problems),
|
|
73
|
+
guide="fixing-tag-errors",
|
|
74
|
+
issues=[{"feature": feature, "message": message} for feature, message in issues],
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class NoIntersectionError(InputError):
|
|
79
|
+
"""The custom data doesn't touch the existing OSM network."""
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class OSMDownloadError(NetworkForgeError):
|
|
83
|
+
"""The OSM network couldn't be downloaded (network, Overpass or empty area)."""
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class NetworkIntegrityError(NetworkForgeError):
|
|
87
|
+
"""The built network breaks a structural rule (see validation.py)."""
|