msgspec-geojson 0.1.0__tar.gz
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.
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: msgspec-geojson
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: GeoJSON types for msgspec
|
|
5
|
+
Author: Stanis Trendelenburg
|
|
6
|
+
Author-email: Stanis Trendelenburg <st@trendels.name>
|
|
7
|
+
Requires-Dist: msgspec>=0.20.1
|
|
8
|
+
Requires-Python: >=3.13
|
|
9
|
+
Project-URL: Source, https://github.com/trendels/msgspec-geojson
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
|
|
12
|
+
# msgspec-geojson
|
|
13
|
+
|
|
14
|
+
A collection of [GeoJSON] types for [msgspec].
|
|
15
|
+
|
|
16
|
+
Inspired by the [msgspec GeoJSON example code][geojson_example] and [geojson-pydantic].
|
|
17
|
+
|
|
18
|
+
[GeoJSON]: https://geojson.org
|
|
19
|
+
[msgspec]: https://msgspec.dev/
|
|
20
|
+
[geojson_example]: https://jcristharif.com/msgspec/examples/geojson.html
|
|
21
|
+
[geojson-pydantic]: https://pypi.org/project/geojson-pydantic/
|
|
22
|
+
|
|
23
|
+
This lets you parse GeoJSON into type-safe objects, including propeties, and
|
|
24
|
+
serialize those objects back to GeoJSON:
|
|
25
|
+
|
|
26
|
+
~~~python
|
|
27
|
+
>>> import msgspec.json
|
|
28
|
+
>>> from msgspec import Struct
|
|
29
|
+
>>> from msgspec_geojson import Feature, Point
|
|
30
|
+
|
|
31
|
+
>>> class PoiProperties(Struct):
|
|
32
|
+
... name: str
|
|
33
|
+
... kind: str
|
|
34
|
+
|
|
35
|
+
>>> type PoiFeature = Feature[Point, PoiProperties]
|
|
36
|
+
|
|
37
|
+
>>> obj = msgspec.json.decode("""
|
|
38
|
+
... {"type": "Feature", "id": 1,
|
|
39
|
+
... "properties": {"name": "Zoo Zürich", "kind": "tourism/zoo"},
|
|
40
|
+
... "geometry": {"type": "Point", "coordinates": [8.574695, 47.384510]}}
|
|
41
|
+
... """, type=PoiFeature)
|
|
42
|
+
|
|
43
|
+
>>> obj.id
|
|
44
|
+
1
|
|
45
|
+
>>> obj.geometry
|
|
46
|
+
Point(coordinates=(8.574695, 47.38451))
|
|
47
|
+
>>> obj.properties
|
|
48
|
+
PoiProperties(name='Zoo Zürich', kind='tourism/zoo')
|
|
49
|
+
|
|
50
|
+
>>> feature = Feature(
|
|
51
|
+
... Point(coordinates=(7.5823576, 47.5489249)),
|
|
52
|
+
... PoiProperties(name="Zoo Basel", kind="tourism/zoo"),
|
|
53
|
+
... )
|
|
54
|
+
>>> msgspec.json.encode(feature)
|
|
55
|
+
b'{"type":"Feature","geometry":{"type":"Point","coordinates":[7.5823576,47.5489249]},"properties":{"name":"Zoo Basel","kind":"tourism/zoo"}}'
|
|
56
|
+
|
|
57
|
+
~~~
|
|
58
|
+
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# msgspec-geojson
|
|
2
|
+
|
|
3
|
+
A collection of [GeoJSON] types for [msgspec].
|
|
4
|
+
|
|
5
|
+
Inspired by the [msgspec GeoJSON example code][geojson_example] and [geojson-pydantic].
|
|
6
|
+
|
|
7
|
+
[GeoJSON]: https://geojson.org
|
|
8
|
+
[msgspec]: https://msgspec.dev/
|
|
9
|
+
[geojson_example]: https://jcristharif.com/msgspec/examples/geojson.html
|
|
10
|
+
[geojson-pydantic]: https://pypi.org/project/geojson-pydantic/
|
|
11
|
+
|
|
12
|
+
This lets you parse GeoJSON into type-safe objects, including propeties, and
|
|
13
|
+
serialize those objects back to GeoJSON:
|
|
14
|
+
|
|
15
|
+
~~~python
|
|
16
|
+
>>> import msgspec.json
|
|
17
|
+
>>> from msgspec import Struct
|
|
18
|
+
>>> from msgspec_geojson import Feature, Point
|
|
19
|
+
|
|
20
|
+
>>> class PoiProperties(Struct):
|
|
21
|
+
... name: str
|
|
22
|
+
... kind: str
|
|
23
|
+
|
|
24
|
+
>>> type PoiFeature = Feature[Point, PoiProperties]
|
|
25
|
+
|
|
26
|
+
>>> obj = msgspec.json.decode("""
|
|
27
|
+
... {"type": "Feature", "id": 1,
|
|
28
|
+
... "properties": {"name": "Zoo Zürich", "kind": "tourism/zoo"},
|
|
29
|
+
... "geometry": {"type": "Point", "coordinates": [8.574695, 47.384510]}}
|
|
30
|
+
... """, type=PoiFeature)
|
|
31
|
+
|
|
32
|
+
>>> obj.id
|
|
33
|
+
1
|
|
34
|
+
>>> obj.geometry
|
|
35
|
+
Point(coordinates=(8.574695, 47.38451))
|
|
36
|
+
>>> obj.properties
|
|
37
|
+
PoiProperties(name='Zoo Zürich', kind='tourism/zoo')
|
|
38
|
+
|
|
39
|
+
>>> feature = Feature(
|
|
40
|
+
... Point(coordinates=(7.5823576, 47.5489249)),
|
|
41
|
+
... PoiProperties(name="Zoo Basel", kind="tourism/zoo"),
|
|
42
|
+
... )
|
|
43
|
+
>>> msgspec.json.encode(feature)
|
|
44
|
+
b'{"type":"Feature","geometry":{"type":"Point","coordinates":[7.5823576,47.5489249]},"properties":{"name":"Zoo Basel","kind":"tourism/zoo"}}'
|
|
45
|
+
|
|
46
|
+
~~~
|
|
47
|
+
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "msgspec-geojson"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "GeoJSON types for msgspec"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [
|
|
7
|
+
{ name = "Stanis Trendelenburg", email = "st@trendels.name" }
|
|
8
|
+
]
|
|
9
|
+
requires-python = ">=3.13"
|
|
10
|
+
dependencies = [
|
|
11
|
+
"msgspec>=0.20.1",
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
[project.urls]
|
|
15
|
+
Source = "https://github.com/trendels/msgspec-geojson"
|
|
16
|
+
|
|
17
|
+
[build-system]
|
|
18
|
+
requires = ["uv_build>=0.11.32,<0.12.0"]
|
|
19
|
+
build-backend = "uv_build"
|
|
20
|
+
|
|
21
|
+
[dependency-groups]
|
|
22
|
+
dev = [
|
|
23
|
+
"coverage>=7.15.3",
|
|
24
|
+
"pyright>=1.1.411",
|
|
25
|
+
"pytest>=9.0.0",
|
|
26
|
+
"ruff>=0.16.0",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
[tool.ruff]
|
|
30
|
+
include = [
|
|
31
|
+
"pyproject.toml",
|
|
32
|
+
"src/**/*.py",
|
|
33
|
+
"tests/**/*.py",
|
|
34
|
+
"examples/**/*.py",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
[tool.ruff.format]
|
|
38
|
+
preview = true
|
|
39
|
+
|
|
40
|
+
[tool.ruff.lint]
|
|
41
|
+
|
|
42
|
+
[tool.pyright]
|
|
43
|
+
venvPath = "."
|
|
44
|
+
venv = ".venv"
|
|
45
|
+
include = ["src", "tests", "examples"]
|
|
46
|
+
strict = ["src", "tests", "examples"]
|
|
47
|
+
reportUnnecessaryTypeIgnoreComment = true
|
|
48
|
+
|
|
49
|
+
[tool.coverage.run]
|
|
50
|
+
branch = true
|
|
51
|
+
source = ["src"]
|
|
52
|
+
|
|
53
|
+
[tool.coverage.report]
|
|
54
|
+
exclude_also = [
|
|
55
|
+
"@overload$",
|
|
56
|
+
"raise NotImplementedError",
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
[tool.pytest]
|
|
60
|
+
testpaths = ["tests"]
|
|
61
|
+
verbosity_assertions = "2"
|
|
62
|
+
addopts = ["--import-mode=importlib"]
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from ._types import (
|
|
2
|
+
Feature,
|
|
3
|
+
FeatureCollection,
|
|
4
|
+
GeoJSON,
|
|
5
|
+
Geometry,
|
|
6
|
+
GeometryCollection,
|
|
7
|
+
LineString,
|
|
8
|
+
MultiLineString,
|
|
9
|
+
MultiPoint,
|
|
10
|
+
MultiPolygon,
|
|
11
|
+
Point,
|
|
12
|
+
Polygon,
|
|
13
|
+
Position,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"Feature",
|
|
18
|
+
"FeatureCollection",
|
|
19
|
+
"GeoJSON",
|
|
20
|
+
"Geometry",
|
|
21
|
+
"GeometryCollection",
|
|
22
|
+
"LineString",
|
|
23
|
+
"MultiLineString",
|
|
24
|
+
"MultiPoint",
|
|
25
|
+
"MultiPolygon",
|
|
26
|
+
"Point",
|
|
27
|
+
"Polygon",
|
|
28
|
+
"Position",
|
|
29
|
+
]
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from msgspec import UNSET, Struct, UnsetType
|
|
4
|
+
|
|
5
|
+
type Position = tuple[float, float]
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Point(Struct, tag=True):
|
|
9
|
+
"""A GeoJSON Point Geometry"""
|
|
10
|
+
|
|
11
|
+
coordinates: Position
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class MultiPoint(Struct, tag=True):
|
|
15
|
+
"""A GeoJSON MultiPoint Geometry"""
|
|
16
|
+
|
|
17
|
+
coordinates: list[Position]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class LineString(Struct, tag=True):
|
|
21
|
+
"""A GeoJSON LineString Geometry"""
|
|
22
|
+
|
|
23
|
+
coordinates: list[Position]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class MultiLineString(Struct, tag=True):
|
|
27
|
+
"""A GeoJSON MultiLineString Geometry"""
|
|
28
|
+
|
|
29
|
+
coordinates: list[list[Position]]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class Polygon(Struct, tag=True):
|
|
33
|
+
"""A GeoJSON Polygon Geometry"""
|
|
34
|
+
|
|
35
|
+
coordinates: list[list[Position]]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class MultiPolygon(Struct, tag=True):
|
|
39
|
+
"""A GeoJSON MultiPolygon Geometry"""
|
|
40
|
+
|
|
41
|
+
coordinates: list[list[list[Position]]]
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class GeometryCollection(Struct, tag=True):
|
|
45
|
+
"""A GeoJSON GeometryCollection"""
|
|
46
|
+
|
|
47
|
+
geometries: list["Geometry"]
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
type Geometry = (
|
|
51
|
+
Point
|
|
52
|
+
| MultiPoint
|
|
53
|
+
| LineString
|
|
54
|
+
| MultiLineString
|
|
55
|
+
| Polygon
|
|
56
|
+
| MultiPolygon
|
|
57
|
+
| GeometryCollection
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class Feature[G: Geometry | None, T](Struct, tag=True):
|
|
62
|
+
"""A GeoJSON Feature"""
|
|
63
|
+
|
|
64
|
+
geometry: G | None = None
|
|
65
|
+
properties: T | None = None
|
|
66
|
+
id: str | int | UnsetType = UNSET
|
|
67
|
+
bbox: tuple[float, float, float, float] | UnsetType = UNSET
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class FeatureCollection[G: Geometry | None, T](Struct, tag=True):
|
|
71
|
+
"""A GeoJSON FeatureCollection"""
|
|
72
|
+
|
|
73
|
+
features: list[Feature[G, T]]
|
|
74
|
+
bbox: tuple[float, float, float, float] | UnsetType = UNSET
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
type GeoJSON = Geometry | Feature[Geometry, Any] | FeatureCollection[Geometry, Any]
|
|
File without changes
|