geojson-msgspec 1.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.
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Optional, Union
|
|
4
|
+
|
|
5
|
+
import msgspec
|
|
6
|
+
|
|
7
|
+
Position = tuple[float, float]
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# Define the 7 standard Geometry types.
|
|
11
|
+
# All types set `tag=True`, meaning that they'll make use of a `type` field to
|
|
12
|
+
# disambiguate between types when decoding.
|
|
13
|
+
class Point(msgspec.Struct, tag=True):
|
|
14
|
+
coordinates: Position
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class MultiPoint(msgspec.Struct, tag=True):
|
|
18
|
+
coordinates: list[Position]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class LineString(msgspec.Struct, tag=True):
|
|
22
|
+
coordinates: list[Position]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class MultiLineString(msgspec.Struct, tag=True):
|
|
26
|
+
coordinates: list[list[Position]]
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class Polygon(msgspec.Struct, tag=True):
|
|
30
|
+
coordinates: list[list[Position]]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class MultiPolygon(msgspec.Struct, tag=True):
|
|
34
|
+
coordinates: list[list[list[Position]]]
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class GeometryCollection(msgspec.Struct, tag=True):
|
|
38
|
+
geometries: list[Geometry]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
Geometry = Union[
|
|
42
|
+
Point,
|
|
43
|
+
MultiPoint,
|
|
44
|
+
LineString,
|
|
45
|
+
MultiLineString,
|
|
46
|
+
Polygon,
|
|
47
|
+
MultiPolygon,
|
|
48
|
+
GeometryCollection,
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
# Define the two Feature types
|
|
53
|
+
class Feature(msgspec.Struct, tag=True):
|
|
54
|
+
geometry: Optional[Geometry] = None
|
|
55
|
+
properties: Optional[dict] = None
|
|
56
|
+
id: Union[str, int, None] = None
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class FeatureCollection(msgspec.Struct, tag=True):
|
|
60
|
+
features: list[Feature]
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
# A union of all 9 GeoJSON types
|
|
64
|
+
GeoJSON = Union[Geometry, Feature, FeatureCollection]
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
# Create a decoder and an encoder to use for decoding & encoding GeoJSON types
|
|
68
|
+
loads = msgspec.json.Decoder(GeoJSON).decode
|
|
69
|
+
dumps = msgspec.json.Encoder().encode
|
geojson_msgspec/py.typed
ADDED
|
File without changes
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: geojson-msgspec
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: msgspec GeoJSON model
|
|
5
|
+
License-File: LICENSE
|
|
6
|
+
Requires-Python: >=3.9
|
|
7
|
+
Requires-Dist: msgspec<0.20,>=0.19
|
|
8
|
+
Description-Content-Type: text/x-rst
|
|
9
|
+
|
|
10
|
+
This project contains code published as an example in the `msgspec project <https://jcristharif.com/msgspec/>`
|
|
11
|
+
backported to python 3.8.
|
|
12
|
+
|
|
13
|
+
GeoJSON
|
|
14
|
+
=======
|
|
15
|
+
|
|
16
|
+
`GeoJSON <https://geojson.org>`__ is a popular format for encoding geographic
|
|
17
|
+
data. Its specification_ describes nine different types a message may take
|
|
18
|
+
(seven "geometry" types, plus two "feature" types). Here we provide one way of
|
|
19
|
+
implementing that specification using ``msgspec`` to handle the parsing and
|
|
20
|
+
validation.
|
|
21
|
+
|
|
22
|
+
The ``loads`` and ``dumps`` methods defined below work similar to the
|
|
23
|
+
standard library's ``json.loads``/``json.dumps``, but:
|
|
24
|
+
|
|
25
|
+
- Will result in high-level `msgspec.Struct` objects representing GeoJSON types
|
|
26
|
+
- Will error nicely if a field is missing or the wrong type
|
|
27
|
+
- Will fill in default values for optional fields
|
|
28
|
+
- Decodes and encodes *significantly faster* than the `json` module (as well as
|
|
29
|
+
most other ``json`` implementations in Python).
|
|
30
|
+
|
|
31
|
+
This example makes use `msgspec.Struct` types to define the different GeoJSON
|
|
32
|
+
types, and `struct-tagged-unions`_ to differentiate between them. See the
|
|
33
|
+
relevant docs for more information.
|
|
34
|
+
|
|
35
|
+
The original source code can be found `here
|
|
36
|
+
<https://github.com/jcrist/msgspec/blob/main/examples/geojson>`__.
|
|
37
|
+
|
|
38
|
+
Here we use the ``loads`` method defined above to read some `example GeoJSON`_.
|
|
39
|
+
|
|
40
|
+
.. code-block:: ipython3
|
|
41
|
+
|
|
42
|
+
In [1]: import msgspec_geojson
|
|
43
|
+
|
|
44
|
+
In [2]: with open("canada.json", "rb") as f:
|
|
45
|
+
...: data = f.read()
|
|
46
|
+
|
|
47
|
+
In [3]: canada = msgspec_geojson.loads(data)
|
|
48
|
+
|
|
49
|
+
In [4]: type(canada) # loaded as high-level, validated object
|
|
50
|
+
Out[4]: msgspec_geojson.FeatureCollection
|
|
51
|
+
|
|
52
|
+
In [5]: canada.features[0].properties
|
|
53
|
+
Out[5]: {'name': 'Canada'}
|
|
54
|
+
|
|
55
|
+
Comparing performance to:
|
|
56
|
+
|
|
57
|
+
- orjson_
|
|
58
|
+
- `json`
|
|
59
|
+
- geojson_ (another validating Python implementation)
|
|
60
|
+
|
|
61
|
+
.. code-block:: ipython3
|
|
62
|
+
|
|
63
|
+
In [6]: %timeit msgspec_geojson.loads(data) # benchmark msgspec
|
|
64
|
+
6.15 ms ± 13.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
|
|
65
|
+
|
|
66
|
+
In [7]: %timeit orjson.loads(data) # benchmark orjson
|
|
67
|
+
8.67 ms ± 20.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
|
|
68
|
+
|
|
69
|
+
In [8]: %timeit json.loads(data) # benchmark json
|
|
70
|
+
27.6 ms ± 102 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
|
|
71
|
+
|
|
72
|
+
In [9]: %timeit geojson.loads(data) # benchmark geojson
|
|
73
|
+
93.9 ms ± 88.1 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
This shows that the readable ``msgspec`` implementation above is 1.4x faster
|
|
77
|
+
than `orjson` (on this data), while also ensuring the loaded data is valid
|
|
78
|
+
GeoJSON. Compared to geojson_ (another validating geojson library for python),
|
|
79
|
+
loading the data using ``msgspec`` was **15.3x faster**.
|
|
80
|
+
|
|
81
|
+
.. _specification: https://datatracker.ietf.org/doc/html/rfc7946
|
|
82
|
+
.. _example GeoJSON: https://github.com/jcrist/msgspec/blob/main/examples/geojson/canada.json
|
|
83
|
+
.. _orjson: https://github.com/ijl/orjson
|
|
84
|
+
.. _geojson: https://github.com/jazzband/geojson
|
|
85
|
+
.. _struct-tagged-unions: https://jcristharif.com/msgspec/structs.html#tagged-unions
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
geojson_msgspec/__init__.py,sha256=hDml1Az1-gYSE4sq17RPeZ_nYq-FiTdmcF1VhYfaino,1516
|
|
2
|
+
geojson_msgspec/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
+
geojson_msgspec-1.0.0.dist-info/METADATA,sha256=a5H_4sswy30SK6LHoxN5Nk9R8l0NqrUV_lVSzLuyBFk,3201
|
|
4
|
+
geojson_msgspec-1.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
5
|
+
geojson_msgspec-1.0.0.dist-info/licenses/LICENSE,sha256=_nsuUQimpd3yN3sWXGdZazApGxJJvfgAproYa-LATfA,1548
|
|
6
|
+
geojson_msgspec-1.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
Copyright (c) 2021, Jim Crist-Harif
|
|
2
|
+
Copyright (c) 2024, Rafał Krupiński, öKlo GmbH
|
|
3
|
+
All rights reserved.
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its contributors
|
|
16
|
+
may be used to endorse or promote products derived from this software
|
|
17
|
+
without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|