Name | fudgeo JSON |
Version |
0.8.1
JSON |
| download |
home_page | None |
Summary | GeoPackage support from Python. fudgeo is a lightweight package for creating OGC GeoPackages, Feature Classes, and Tables. Easily read and write geometries and attributes to Feature Classes and Tables using regular Python objects and SQLite syntax. |
upload_time | 2024-10-19 17:44:53 |
maintainer | None |
docs_url | None |
author | None |
requires_python | >=3.9 |
license | MIT License Copyright (c) 2021-2024 Integrated Informatics Inc Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
keywords |
geopackage
|
VCS |
|
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# fudgeo
`fudgeo` removes the *fear uncertainty doubt* from using GeoPackages with
`Python`. `fudgeo` is a lightweight package for creating OGC GeoPackages, Feature
Classes, and Tables. Easily read and write geometries and attributes to
Feature Classes and Tables using regular `Python` objects and `SQLite` syntax.
For details on OGC GeoPackages, please see the [OGC web page](http://www.geopackage.org/).
## Installation
`fudgeo` is available from the [Python Package Index](https://pypi.org/project/fudgeo/).
## Python Compatibility
The `fudgeo` library is compatible with Python 3.7 to 3.12. Developed and
tested on **macOS** and **Windows**, should be fine on **Linux** too.
## Usage
`fudgeo` can be used to:
* Create a new empty `GeoPackage` or open an existing `GeoPackage`
* Create new `FeatureClass` or `Table` with optional overwrite
* Create `SpatialReferenceSystem` for a `FeatureClass`
* Build geometry objects from lists of coordinate values
* Work with data in `Table` or `FeatureClass` in a normal `SQLite` manner (e.g. `SELECT`, `INSERT`, `UPDATE`, `DELETE`)
* Retrieve fields from a `FeatureClass` or `Table`
* Access primary key field of `FeatureClass` or `Table`
* Access geometry column name and geometry type for `FeatureClass`
* Add spatial index on `FeatureClass`
* Drop `FeatureClass` or `Table`
* Add metadata and schema details
### Create an Empty GeoPackage / Open GeoPackage
```python
from fudgeo.geopkg import GeoPackage
# Creates an empty geopackage
gpkg: GeoPackage = GeoPackage.create('../data/example.gpkg')
# Opens an existing Geopackage (no validation)
gpkg: GeoPackage = GeoPackage('../data/example.gpkg')
```
`GeoPackage`s are created with *three* default Spatial References defined
automatically, a pair of Spatial References to handle **undefined** cases,
and a **WGS 84** entry.
The definition of the WGS84 entry is flexible - meaning that the
*WKT for WGS84* can be setup per the users liking. As an example,
use with Esri's ArcGIS means either using the *EPSG WKT* or the *ESRI WKT*. By
default the *ESRI WKT* is used - However, if *EPSG WKT* is desired, you
may provide a ``flavor`` parameter to the create method specifying EPSG.
```python
from fudgeo.geopkg import GeoPackage
# Creates an empty geopackage using EPSG definitions
gpkg: GeoPackage = GeoPackage.create('../temp/test.gpkg', flavor='EPSG')
```
### Create a Feature Class
Use the `create_feature_class` method of a GeoPackage to make
a new feature class. Feature classes require a name and a Spatial
Reference, the name must follow SQLite naming requirements. Each
feature class is defined with `fid` and `SHAPE` fields, additional
fields can be defined during creation. `SHAPE` is the default geometry
column name however it can be specified during feature class creation.
A Feature Class can be created with *Z* or *M* (or both) enabled. If
either of these options are enabled, the geometry inserted into the
Feature Class **must** include a value for the option specified.
```python
from fudgeo.enumeration import GeometryType, SQLFieldType
from fudgeo.geopkg import FeatureClass, Field, GeoPackage, SpatialReferenceSystem
SRS_WKT: str = (
'PROJCS["WGS_1984_UTM_Zone_23N",'
'GEOGCS["GCS_WGS_1984",'
'DATUM["D_WGS_1984",'
'SPHEROID["WGS_1984",6378137.0,298.257223563]],'
'PRIMEM["Greenwich",0.0],'
'UNIT["Degree",0.0174532925199433]],'
'PROJECTION["Transverse_Mercator"],'
'PARAMETER["False_Easting",500000.0],'
'PARAMETER["False_Northing",0.0],'
'PARAMETER["Central_Meridian",-45.0],'
'PARAMETER["Scale_Factor",0.9996],'
'PARAMETER["Latitude_Of_Origin",0.0],'
'UNIT["Meter",1.0]]')
SRS: SpatialReferenceSystem = SpatialReferenceSystem(
name='WGS_1984_UTM_Zone_23N', organization='EPSG',
org_coord_sys_id=32623, definition=SRS_WKT)
fields: tuple[Field, ...] = (
Field('road_id', SQLFieldType.integer),
Field('name', SQLFieldType.text, size=100),
Field('begin_easting', SQLFieldType.double),
Field('begin_northing', SQLFieldType.double),
Field('end_easting', SQLFieldType.double),
Field('end_northing', SQLFieldType.double),
Field('begin_longitude', SQLFieldType.double),
Field('begin_latitude', SQLFieldType.double),
Field('end_longitude', SQLFieldType.double),
Field('end_latitude', SQLFieldType.double),
Field('is_one_way', SQLFieldType.boolean))
gpkg: GeoPackage = GeoPackage.create('../temp/test.gpkg')
fc: FeatureClass = gpkg.create_feature_class(
'road_l', srs=SRS, fields=fields, shape_type=GeometryType.linestring,
m_enabled=True, overwrite=True, spatial_index=True)
```
### About Spatial References For GeoPackages
Spatial References in GeoPackages can use any definition from any
authority - be that `EPSG`, `ESRI`, or another authority. `fudgeo` imposes no
restriction and performs no checks on the definitions provided. Take care
to ensure that the definitions are compatible with the platform / software
you intend to utilize with the `GeoPackage`.
### Insert Features into a Feature Class (SQL)
Features can be inserted into a Feature Class using SQL.
This example shows the creation of a random point Feature Class and
builds upon the code from previous examples. Note that the create Feature Class
portion of the code is omitted...
```python
from random import choice, randint
from string import ascii_uppercase, digits
from fudgeo.geometry import LineStringM
from fudgeo.geopkg import GeoPackage
# Generate some random points and attributes
rows: list[tuple[LineStringM, int, str, float, float, float, float, bool]] = []
for i in range(10000):
name = ''.join(choice(ascii_uppercase + digits) for _ in range(10))
road_id = randint(0, 1000)
eastings = [randint(300000, 600000) for _ in range(20)]
northings = [randint(1, 100000) for _ in range(20)]
coords = [(x, y, m) for m, (x, y) in enumerate(zip(eastings, northings))]
road = LineStringM(coords, srs_id=32623)
rows.append((road, road_id, name, eastings[0], northings[0],
eastings[-1], northings[-1], False))
# NOTE Builds from previous examples
gpkg: GeoPackage = GeoPackage('../data/example.gpkg')
with gpkg.connection as conn:
conn.executemany("""
INSERT INTO road_l (SHAPE, road_id, name, begin_easting, begin_northing,
end_easting, end_northing, is_one_way)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)""", rows)
```
### Geometry Examples
Review the tests for `fudgeo` for a comprehensive look into
creating geometries, below are some examples showing the simplicity
of this package.
```python
from fudgeo.geometry import LineStringZM, Point, Polygon
# Point in WGS 84
pt: Point = Point(x=-119, y=34)
# Line with ZM Values for use with UTM Zone 23N (WGS 84)
coords: list[tuple[float, float, float, float]] = [
(300000, 1, 10, 0), (300000, 4000000, 20, 1000),
(700000, 4000000, 30, 2000), (700000, 1, 40, 3000)]
line: LineStringZM = LineStringZM(coords, srs_id=32623)
# list of rings where a ring is simply the list of points it contains.
rings: list[list[tuple[float, float]]] = [
[(300000, 1), (300000, 4000000), (700000, 4000000), (700000, 1), (300000, 1)]]
poly: Polygon = Polygon(rings, srs_id=32623)
```
### Select Features from GeoPackage
When selecting features from a GeoPackage feature class use SQL or use the
helper method `select`.
For simple geometries (e.g. those without *Z* or *M*) this can be done via a
basic `SELECT` statement or the `select` method.
```python
from fudgeo.geometry import Point
from fudgeo.geopkg import FeatureClass, GeoPackage
gpkg = GeoPackage(...)
# NOTE for fudgeo version v0.8.0 and above use helper method
fc = FeatureClass(geopackage=gpkg, name='point_fc')
cursor = fc.select(fields=('example_id',), include_geometry=True)
features: list[tuple[Point, int]] = cursor.fetchall()
# NOTE for fudgeo prior to v0.8.0
cursor = gpkg.connection.execute("""SELECT SHAPE, example_id FROM point_fc""")
features: list[tuple[Point, int]] = cursor.fetchall()
```
When using SQL with extended geometry types (e.g. those with *Z* and/or *M*)
then ensure `SQLite` knows how to convert the geopackage stored geometry to a
`fudgeo` geometry by including the converter, this is done like so:
```python
from fudgeo.geometry import LineStringM
from fudgeo.geopkg import FeatureClass, GeoPackage
gpkg = GeoPackage('../data/example.gpkg')
# NOTE for fudgeo version v0.8.0 and above use helper method
fc = FeatureClass(geopackage=gpkg, name='test')
cursor = fc.select(fields=('road_id',), include_geometry=True)
features: list[tuple[LineStringM, int]] = cursor.fetchall()
# NOTE for fudgeo prior to v0.8.0
cursor = gpkg.connection.execute(
"""SELECT SHAPE "[LineStringM]", road_id FROM test""")
features: list[tuple[LineStringM, int]] = cursor.fetchall()
```
## Extensions
### Spatial Index Extension
Spatial Index Extension implementation based on section [F.3. RTree Spatial Indexes](http://www.geopackage.org/spec131/index.html#extension_rtree)
of the **GeoPackage Encoding Standard**.
Spatial Indexes apply to individual feature classes. A spatial index can be
added at create time or added on an existing feature class.
```python
from fudgeo.enumeration import SQLFieldType
from fudgeo.geopkg import FeatureClass, Field, GeoPackage, SpatialReferenceSystem
SRS_WKT: str = (
'PROJCS["WGS_1984_UTM_Zone_23N",'
'GEOGCS["GCS_WGS_1984",'
'DATUM["D_WGS_1984",'
'SPHEROID["WGS_1984",6378137.0,298.257223563]],'
'PRIMEM["Greenwich",0.0],'
'UNIT["Degree",0.0174532925199433]],'
'PROJECTION["Transverse_Mercator"],'
'PARAMETER["False_Easting",500000.0],'
'PARAMETER["False_Northing",0.0],'
'PARAMETER["Central_Meridian",-45.0],'
'PARAMETER["Scale_Factor",0.9996],'
'PARAMETER["Latitude_Of_Origin",0.0],'
'UNIT["Meter",1.0]]')
SRS: SpatialReferenceSystem = SpatialReferenceSystem(
name='WGS_1984_UTM_Zone_23N', organization='EPSG',
org_coord_sys_id=32623, definition=SRS_WKT)
fields: tuple[Field, ...] = (
Field('id', SQLFieldType.integer),
Field('name', SQLFieldType.text, size=100))
gpkg: GeoPackage = GeoPackage.create('../temp/spatial_index.gpkg')
# add spatial index at create time
event: FeatureClass = gpkg.create_feature_class(
'event_p', srs=SRS, fields=fields, spatial_index=True)
assert event.has_spatial_index is True
# add spatial index on an existing feature class / post create
signs: FeatureClass = gpkg.create_feature_class(
'signs_p', srs=SRS, fields=fields)
# no spatial index
assert signs.has_spatial_index is False
signs.add_spatial_index()
# spatial index now present
assert signs.has_spatial_index is True
```
Refer to **SQLite** [documentation](https://www.sqlite.org/rtree.html#using_r_trees_effectively)
on how to use these indexes for faster filtering / querying. Also note
how to handle [round off error](https://www.sqlite.org/rtree.html#roundoff_error)
when querying.
### Metadata Extension
Metadata Extension implementation based on [F.8. Metadata](http://www.geopackage.org/spec131/index.html#extension_metadata)
of the **GeoPackage Encoding Standard**.
The metadata extension is enabled at the GeoPackage level applying to all
tables and feature classes. That said, not every table and feature class is
required to have metadata.
Metadata extension can be enabled at create time for a GeoPackage or
can be enabled on an existing GeoPackage.
```python
from fudgeo.geopkg import GeoPackage
# enable metadata at create time
gpkg: GeoPackage = GeoPackage.create('../data/metadata.gpkg', enable_metadata=True)
assert gpkg.is_metadata_enabled is True
# enable metadata on an existing GeoPackage
gpkg: GeoPackage = GeoPackage('../data/example.gpkg')
assert gpkg.is_metadata_enabled is False
gpkg.enable_metadata_extension()
assert gpkg.is_metadata_enabled is True
```
```python
from fudgeo.enumeration import MetadataScope
from fudgeo.extension.metadata import TableReference
from fudgeo.geopkg import GeoPackage
# open GeoPackage with metadata extension enabled
gpkg: GeoPackage = GeoPackage('../data/example.gpkg')
# open a metadata xml file and add it to the GeoPackage
with open(...) as fin:
id_ = gpkg.metadata.add_metadata(
uri='https://www.isotc211.org/2005/gmd',
scope=MetadataScope.dataset, metadata=fin.read()
)
# apply the metadata to a feature class
reference = TableReference(table_name='road_l', file_id=id_)
gpkg.metadata.add_references(reference)
```
Support provided for the following reference types:
* `GeoPackageReference` -- used for `GeoPackage` level metadata
* `TableReference` -- used for `Table` and `FeatureClass` level metadata
* `ColumnReference` -- used for a **column** in a `Table` or `FeatureClass`
* `RowReference` -- used for a **row** in a `Table` or `FeatureClass`
* `RowColumnReference` -- used for **row / column** combination in a `Table` or `FeatureClass`
### Schema Extension
Schema Extension implementation based on [F.9. Schema](http://www.geopackage.org/spec131/index.html#extension_schema)
of the **GeoPackage Encoding Standard**.
The schema extension is enabled at the GeoPackage level and allows for extended
definitions on column names (e.g. name, title, description) and for constraints
to be defined for columns. Constraints definitions are intended for
applications usage and, while similar, are not the same as database constraints.
Schema extension can be enabled at create time for a GeoPackage or
can be enabled on an existing GeoPackage.
```python
from fudgeo.geopkg import GeoPackage
# enable schema at create time
gpkg: GeoPackage = GeoPackage.create('../data/schema.gpkg', enable_schema=True)
assert gpkg.is_schema_enabled is True
# enable schema on an existing GeoPackage
gpkg: GeoPackage = GeoPackage('../data/example.gpkg')
assert gpkg.is_schema_enabled is False
gpkg.enable_schema_extension()
assert gpkg.is_schema_enabled is True
```
```python
from fudgeo.extension.schema import (
EnumerationConstraint, GlobConstraint, RangeConstraint)
from fudgeo.geopkg import GeoPackage
# open GeoPackage with schema extension enabled
gpkg: GeoPackage = GeoPackage('../data/example.gpkg')
# add constraints for use with column definitions
constraints = [
EnumerationConstraint(name='odds', values=[1, 3, 5, 7, 9]),
EnumerationConstraint(name='colors', values=['red', 'yellow', 'blue']),
GlobConstraint(name='pin', pattern='[0-9][0-9][0-9][0-9]'),
RangeConstraint(name='exertion', min_value=6, max_value=20),
RangeConstraint(name='longitude', min_value=-180, max_value=180),
RangeConstraint(name='latitude', min_value=90, max_value=90),
]
gpkg.schema.add_constraints(constraints)
# use constrains and set some additional details for column name
gpkg.schema.add_column_definition(
table_name='road_l', column_name='begin_longitude',
name='Beginning Longitude for Road', title='Begin Longitude',
constraint_name='longitude')
gpkg.schema.add_column_definition(
table_name='road_l', column_name='begin_latitude',
name='Beginning Latitude for Road', title='Begin Latitude',
constraint_name='latitude')
gpkg.schema.add_column_definition(
table_name='road_l', column_name='end_longitude',
name='Ending Longitude for Road', title='End Longitude',
constraint_name='longitude')
gpkg.schema.add_column_definition(
table_name='road_l', column_name='end_latitude',
name='Ending Latitude for Road', title='End Latitude',
constraint_name='latitude')
```
Support provided for the following constraint types:
* `EnumerationConstraint` -- restrict to one or more values
* `GlobConstraint` -- pattern match based constraint
* `RangeConstraint` -- value constrained within a range, optionally including the bounds
## License
[MIT](https://choosealicense.com/licenses/mit/)
## Release History
### v0.8.1
* add support for creating feature classes with a geometry column name other than `SHAPE`
* ensure support for Python 3.13 and update documentation / configuration
### v0.8.0
* drop support for Python 3.7 and 3.8
* modernize type hinting
* add `select` method to `FeatureClass` and `Table` objects
### v0.7.2
* bump `user_version` to reflect adopted version 1.4.0 of OGC GeoPackage
* updated r-tree triggers based on changes made in 1.4.0
### v0.7.1
* ensure support for Python 3.12 and update documentation / configuration
### v0.7.0
* add support for **schema** extension
* add support for **metadata** extension
* add `__geo_interface__` to geometry classes
* introduce `bounding_box` property on `Envelope` class
* introduce `as_tuple` method on `Point` classes
* add `extension` sub-package, move `spatial` module into `extension`
* add `spatial_index_name` property on `FeatureClass`, returns the index table name
* enable enforcement of foreign key constraints
* reorganize code to handle OGR contents like an extension
* move protected functions from `geopkg` module into `util` module and rename
* add type hinting to `enumerations` module
* move `EnvelopeCode` into `enumerations`
### v0.6.0
* change `ogr_contents` default value to `False` (breaking change)
* add `spatial_index` option to `FeatureClass` creation, default to `False`
* add `add_spatial_index` method to `FeatureClass` for adding spatial index post creation
* add `has_spatial_index` property to `FeatureClass`
* add `count` property to `Table` and `FeatureClass`
* add `primary_key_field` property to `Table` and `FeatureClass`
* small speed-up to `Point` unpacking
* update `is_empty` to rely on internal attribute data type
* improvements to SQL statements to handle names that must be escaped
* bump `user_version` to reflect adopted version 1.3.1 of OGC GeoPackage
* add optional views for geometry columns and spatial references
### v0.5.2
* store empty state on the instance during geometry read
* introduce base classes for common capability and parametrize via class attributes
* add stub files to provide type hinting specialization
### v0.5.1
* small performance improvements by reducing `bytes` concatenation and building up `bytearray`
### v0.5.0
* performance improvements for geometry reading (especially for geometries with large numbers of points / parts)
* performance improvements for geometry writing
* incorporated `numpy` and `bottleneck` as dependencies
### v0.4.2
* only unpack header and delay unpacking coordinates until needed
* write envelope to geometry header
### v0.4.1
* unpack envelope from header (when available)
* add `envelope` property to 2D, 3D, and 4D geometry
* derive envelope from underlying coordinates / geometries if not set from header
### v0.4.0
* add string representations to `GeoPackage`, `Table`, and `FeatureClass`
* allow optional creation of the `gpkg_ogr_contents`, defaults to True (create)
* split `geometry` module into a sub-package
### v0.3.10
* add `escaped_name` property to `BaseTable`, applies to `Table` and `FeatureClass`
* escape the name of input table / feature class during `create`
### v0.3.9
* quote reversal, doubles inside of singles for `escaped_name`
### v0.3.8
* add `fields` property to `BaseTable`, applies to `Table` and `FeatureClass`
* add `field_names` property to `BaseTable`, applies to `Table` and `FeatureClass`
* add `escaped_name` property to `Field` to return name valid for use in queries
* add type hinting to embedded sql statements and supporting values
### v0.3.7
* add `is_empty` property to geometries, improved handling for empty geometries
* update `user_version` to `10300`
* add handling for geometry headers with envelopes (skipping content)
* add type hinting to constants
### v0.3.6
* add `srs_id` (optional) to `SpatialReferenceSystem` instantiation, default to `org_coord_sys_id` if not specified
### v0.3.5
* store `coordinates` in attribute on 2D, 3D, and 4D geometry
* avoid creating points on instantiation of geometry
* expose `points` property to return point objects for 2D, 3D, and 4D geometry
### v0.3.4
* add `from_tuple` class methods to `Point`, `PointZ`, `PointM`, and `PointZM`
### v0.3.3
* catch possible exception when parsing microseconds from time
* add converter for `timestamp` to use same converter as `datetime`
* use lower case table names in queries
### v0.3.2
* include `PolygonM`, `PolygonZM`, `MultiPolygonM`, and `MultiPolygonZM` in geometry registration
### v0.3.1
* delay opening a `GeoPackage` connection until `connection` property is accessed
### v0.3.0
* add support for `PolygonM`, `PolygonZM`, `MultiPolygonM`, and `MultiPolygonZM`
* add `geometry_column_name` and `geometry_type` properties to `FeatureClass`
* simplify query used by `has_z` and `has_m`
### v0.2.1
* improve `_convert_datetime` to handle different formats for timestamp (contributed by [@alexeygribko](https://github.com/alexeygribko))
### v0.2.0
* improve `_convert_datetime` to handle timezone
* add `DATETIME` tp `SQLFieldType`
### v0.1.2
* add option to overwrite feature classes and tables in `create_feature_class` and `create_table` methods
* add option to overwrite in `create` method on `FeatureClass` and `Table` classes
* add `drop` method on `FeatureClass` and `Table` classes
### v0.1.1
* make compatible with Python 3.7 and up (update type hints, remove walrus)
* add support for OGR contents table (`gpkg_ogr_contents`) and triggers
* add `tables` and `feature_classes` properties to `GeoPackage` class
* include `application_id` and `user_version` in SQL definition
* fix timestamp format (was missing seconds)
### v0.1.0
* initial release, basic port of legacy `pygeopkg` package
Raw data
{
"_id": null,
"home_page": null,
"name": "fudgeo",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.9",
"maintainer_email": null,
"keywords": "geopackage",
"author": null,
"author_email": "\"Integrated Informatics Inc.\" <contact@integrated-informatics.com>",
"download_url": null,
"platform": null,
"description": "# fudgeo\n\n`fudgeo` removes the *fear uncertainty doubt* from using GeoPackages with \n`Python`. `fudgeo` is a lightweight package for creating OGC GeoPackages, Feature \nClasses, and Tables. Easily read and write geometries and attributes to\nFeature Classes and Tables using regular `Python` objects and `SQLite` syntax.\n\nFor details on OGC GeoPackages, please see the [OGC web page](http://www.geopackage.org/).\n\n\n## Installation\n\n`fudgeo` is available from the [Python Package Index](https://pypi.org/project/fudgeo/).\n\n\n## Python Compatibility\n\nThe `fudgeo` library is compatible with Python 3.7 to 3.12. Developed and \ntested on **macOS** and **Windows**, should be fine on **Linux** too.\n\n\n## Usage\n\n`fudgeo` can be used to: \n* Create a new empty `GeoPackage` or open an existing `GeoPackage`\n* Create new `FeatureClass` or `Table` with optional overwrite\n* Create `SpatialReferenceSystem` for a `FeatureClass`\n* Build geometry objects from lists of coordinate values\n* Work with data in `Table` or `FeatureClass` in a normal `SQLite` manner (e.g. `SELECT`, `INSERT`, `UPDATE`, `DELETE`)\n* Retrieve fields from a `FeatureClass` or `Table`\n* Access primary key field of `FeatureClass` or `Table` \n* Access geometry column name and geometry type for `FeatureClass`\n* Add spatial index on `FeatureClass`\n* Drop `FeatureClass` or `Table`\n* Add metadata and schema details\n\n\n### Create an Empty GeoPackage / Open GeoPackage\n\n```python\nfrom fudgeo.geopkg import GeoPackage\n\n# Creates an empty geopackage\ngpkg: GeoPackage = GeoPackage.create('../data/example.gpkg')\n\n# Opens an existing Geopackage (no validation)\ngpkg: GeoPackage = GeoPackage('../data/example.gpkg')\n```\n\n`GeoPackage`s are created with *three* default Spatial References defined\nautomatically, a pair of Spatial References to handle **undefined** cases,\nand a **WGS 84** entry. \n\nThe definition of the WGS84 entry is flexible - meaning that the \n*WKT for WGS84* can be setup per the users liking. As an example, \nuse with Esri's ArcGIS means either using the *EPSG WKT* or the *ESRI WKT*. By\ndefault the *ESRI WKT* is used - However, if *EPSG WKT* is desired, you\nmay provide a ``flavor`` parameter to the create method specifying EPSG.\n\n```python\nfrom fudgeo.geopkg import GeoPackage\n\n# Creates an empty geopackage using EPSG definitions\ngpkg: GeoPackage = GeoPackage.create('../temp/test.gpkg', flavor='EPSG')\n```\n\n### Create a Feature Class\n\nUse the `create_feature_class` method of a GeoPackage to make\na new feature class. Feature classes require a name and a Spatial \nReference, the name must follow SQLite naming requirements. Each\nfeature class is defined with `fid` and `SHAPE` fields, additional\nfields can be defined during creation. `SHAPE` is the default geometry\ncolumn name however it can be specified during feature class creation.\n\nA Feature Class can be created with *Z* or *M* (or both) enabled. If \neither of these options are enabled, the geometry inserted into the \nFeature Class **must** include a value for the option specified.\n\n```python\nfrom fudgeo.enumeration import GeometryType, SQLFieldType\nfrom fudgeo.geopkg import FeatureClass, Field, GeoPackage, SpatialReferenceSystem\n\nSRS_WKT: str = (\n 'PROJCS[\"WGS_1984_UTM_Zone_23N\",'\n 'GEOGCS[\"GCS_WGS_1984\",'\n 'DATUM[\"D_WGS_1984\",'\n 'SPHEROID[\"WGS_1984\",6378137.0,298.257223563]],'\n 'PRIMEM[\"Greenwich\",0.0],'\n 'UNIT[\"Degree\",0.0174532925199433]],'\n 'PROJECTION[\"Transverse_Mercator\"],'\n 'PARAMETER[\"False_Easting\",500000.0],'\n 'PARAMETER[\"False_Northing\",0.0],'\n 'PARAMETER[\"Central_Meridian\",-45.0],'\n 'PARAMETER[\"Scale_Factor\",0.9996],'\n 'PARAMETER[\"Latitude_Of_Origin\",0.0],'\n 'UNIT[\"Meter\",1.0]]')\n\nSRS: SpatialReferenceSystem = SpatialReferenceSystem(\n name='WGS_1984_UTM_Zone_23N', organization='EPSG',\n org_coord_sys_id=32623, definition=SRS_WKT)\nfields: tuple[Field, ...] = (\n Field('road_id', SQLFieldType.integer),\n Field('name', SQLFieldType.text, size=100),\n Field('begin_easting', SQLFieldType.double),\n Field('begin_northing', SQLFieldType.double),\n Field('end_easting', SQLFieldType.double),\n Field('end_northing', SQLFieldType.double),\n Field('begin_longitude', SQLFieldType.double),\n Field('begin_latitude', SQLFieldType.double),\n Field('end_longitude', SQLFieldType.double),\n Field('end_latitude', SQLFieldType.double),\n Field('is_one_way', SQLFieldType.boolean))\n\ngpkg: GeoPackage = GeoPackage.create('../temp/test.gpkg')\nfc: FeatureClass = gpkg.create_feature_class(\n 'road_l', srs=SRS, fields=fields, shape_type=GeometryType.linestring,\n m_enabled=True, overwrite=True, spatial_index=True)\n```\n\n### About Spatial References For GeoPackages\n\nSpatial References in GeoPackages can use any definition from any \nauthority - be that `EPSG`, `ESRI`, or another authority. `fudgeo` imposes no \nrestriction and performs no checks on the definitions provided. Take care \nto ensure that the definitions are compatible with the platform / software \nyou intend to utilize with the `GeoPackage`.\n\n### Insert Features into a Feature Class (SQL)\n\nFeatures can be inserted into a Feature Class using SQL.\n\nThis example shows the creation of a random point Feature Class and\nbuilds upon the code from previous examples. Note that the create Feature Class\nportion of the code is omitted...\n\n```python\nfrom random import choice, randint\nfrom string import ascii_uppercase, digits\n\nfrom fudgeo.geometry import LineStringM\nfrom fudgeo.geopkg import GeoPackage\n\n# Generate some random points and attributes\nrows: list[tuple[LineStringM, int, str, float, float, float, float, bool]] = []\nfor i in range(10000):\n name = ''.join(choice(ascii_uppercase + digits) for _ in range(10))\n road_id = randint(0, 1000)\n eastings = [randint(300000, 600000) for _ in range(20)]\n northings = [randint(1, 100000) for _ in range(20)]\n coords = [(x, y, m) for m, (x, y) in enumerate(zip(eastings, northings))]\n road = LineStringM(coords, srs_id=32623)\n rows.append((road, road_id, name, eastings[0], northings[0],\n eastings[-1], northings[-1], False))\n\n# NOTE Builds from previous examples\ngpkg: GeoPackage = GeoPackage('../data/example.gpkg') \nwith gpkg.connection as conn:\n conn.executemany(\"\"\"\n INSERT INTO road_l (SHAPE, road_id, name, begin_easting, begin_northing, \n end_easting, end_northing, is_one_way) \n VALUES (?, ?, ?, ?, ?, ?, ?, ?)\"\"\", rows)\n```\n\n### Geometry Examples\n\nReview the tests for `fudgeo` for a comprehensive look into \ncreating geometries, below are some examples showing the simplicity\nof this package.\n\n\n```python\nfrom fudgeo.geometry import LineStringZM, Point, Polygon\n\n# Point in WGS 84\npt: Point = Point(x=-119, y=34)\n\n# Line with ZM Values for use with UTM Zone 23N (WGS 84)\ncoords: list[tuple[float, float, float, float]] = [\n (300000, 1, 10, 0), (300000, 4000000, 20, 1000),\n (700000, 4000000, 30, 2000), (700000, 1, 40, 3000)]\nline: LineStringZM = LineStringZM(coords, srs_id=32623)\n\n# list of rings where a ring is simply the list of points it contains.\nrings: list[list[tuple[float, float]]] = [\n [(300000, 1), (300000, 4000000), (700000, 4000000), (700000, 1), (300000, 1)]]\npoly: Polygon = Polygon(rings, srs_id=32623)\n```\n\n### Select Features from GeoPackage\n\nWhen selecting features from a GeoPackage feature class use SQL or use the\nhelper method `select`. \n\nFor simple geometries (e.g. those without *Z* or *M*) this can be done via a \nbasic `SELECT` statement or the `select` method.\n\n```python\nfrom fudgeo.geometry import Point\nfrom fudgeo.geopkg import FeatureClass, GeoPackage\n\ngpkg = GeoPackage(...)\n\n# NOTE for fudgeo version v0.8.0 and above use helper method\nfc = FeatureClass(geopackage=gpkg, name='point_fc')\ncursor = fc.select(fields=('example_id',), include_geometry=True)\nfeatures: list[tuple[Point, int]] = cursor.fetchall()\n\n# NOTE for fudgeo prior to v0.8.0\ncursor = gpkg.connection.execute(\"\"\"SELECT SHAPE, example_id FROM point_fc\"\"\")\nfeatures: list[tuple[Point, int]] = cursor.fetchall()\n```\n\nWhen using SQL with extended geometry types (e.g. those with *Z* and/or *M*) \nthen ensure `SQLite` knows how to convert the geopackage stored geometry to a \n`fudgeo` geometry by including the converter, this is done like so:\n\n\n```python\nfrom fudgeo.geometry import LineStringM\nfrom fudgeo.geopkg import FeatureClass, GeoPackage\n\ngpkg = GeoPackage('../data/example.gpkg')\n# NOTE for fudgeo version v0.8.0 and above use helper method\nfc = FeatureClass(geopackage=gpkg, name='test')\ncursor = fc.select(fields=('road_id',), include_geometry=True)\nfeatures: list[tuple[LineStringM, int]] = cursor.fetchall()\n\n# NOTE for fudgeo prior to v0.8.0\ncursor = gpkg.connection.execute(\n \"\"\"SELECT SHAPE \"[LineStringM]\", road_id FROM test\"\"\")\nfeatures: list[tuple[LineStringM, int]] = cursor.fetchall()\n```\n\n\n## Extensions\n### Spatial Index Extension\nSpatial Index Extension implementation based on section [F.3. RTree Spatial Indexes](http://www.geopackage.org/spec131/index.html#extension_rtree)\nof the **GeoPackage Encoding Standard**.\n\nSpatial Indexes apply to individual feature classes. A spatial index can be\nadded at create time or added on an existing feature class.\n\n```python\nfrom fudgeo.enumeration import SQLFieldType\nfrom fudgeo.geopkg import FeatureClass, Field, GeoPackage, SpatialReferenceSystem\n\n\nSRS_WKT: str = (\n 'PROJCS[\"WGS_1984_UTM_Zone_23N\",'\n 'GEOGCS[\"GCS_WGS_1984\",'\n 'DATUM[\"D_WGS_1984\",'\n 'SPHEROID[\"WGS_1984\",6378137.0,298.257223563]],'\n 'PRIMEM[\"Greenwich\",0.0],'\n 'UNIT[\"Degree\",0.0174532925199433]],'\n 'PROJECTION[\"Transverse_Mercator\"],'\n 'PARAMETER[\"False_Easting\",500000.0],'\n 'PARAMETER[\"False_Northing\",0.0],'\n 'PARAMETER[\"Central_Meridian\",-45.0],'\n 'PARAMETER[\"Scale_Factor\",0.9996],'\n 'PARAMETER[\"Latitude_Of_Origin\",0.0],'\n 'UNIT[\"Meter\",1.0]]')\nSRS: SpatialReferenceSystem = SpatialReferenceSystem(\n name='WGS_1984_UTM_Zone_23N', organization='EPSG',\n org_coord_sys_id=32623, definition=SRS_WKT)\nfields: tuple[Field, ...] = (\n Field('id', SQLFieldType.integer),\n Field('name', SQLFieldType.text, size=100))\n\ngpkg: GeoPackage = GeoPackage.create('../temp/spatial_index.gpkg')\n# add spatial index at create time\nevent: FeatureClass = gpkg.create_feature_class(\n 'event_p', srs=SRS, fields=fields, spatial_index=True)\nassert event.has_spatial_index is True\n\n# add spatial index on an existing feature class / post create\nsigns: FeatureClass = gpkg.create_feature_class(\n 'signs_p', srs=SRS, fields=fields)\n# no spatial index\nassert signs.has_spatial_index is False\nsigns.add_spatial_index()\n# spatial index now present\nassert signs.has_spatial_index is True\n```\n\nRefer to **SQLite** [documentation](https://www.sqlite.org/rtree.html#using_r_trees_effectively) \non how to use these indexes for faster filtering / querying. Also note\nhow to handle [round off error](https://www.sqlite.org/rtree.html#roundoff_error) \nwhen querying.\n\n\n### Metadata Extension\nMetadata Extension implementation based on [F.8. Metadata](http://www.geopackage.org/spec131/index.html#extension_metadata)\nof the **GeoPackage Encoding Standard**.\n\nThe metadata extension is enabled at the GeoPackage level applying to all\ntables and feature classes. That said, not every table and feature class is \nrequired to have metadata. \n\nMetadata extension can be enabled at create time for a GeoPackage or \ncan be enabled on an existing GeoPackage.\n\n```python\nfrom fudgeo.geopkg import GeoPackage\n\n# enable metadata at create time\ngpkg: GeoPackage = GeoPackage.create('../data/metadata.gpkg', enable_metadata=True)\nassert gpkg.is_metadata_enabled is True\n\n# enable metadata on an existing GeoPackage\ngpkg: GeoPackage = GeoPackage('../data/example.gpkg')\nassert gpkg.is_metadata_enabled is False\ngpkg.enable_metadata_extension()\nassert gpkg.is_metadata_enabled is True\n```\n\n```python\nfrom fudgeo.enumeration import MetadataScope\nfrom fudgeo.extension.metadata import TableReference\nfrom fudgeo.geopkg import GeoPackage\n\n# open GeoPackage with metadata extension enabled\ngpkg: GeoPackage = GeoPackage('../data/example.gpkg')\n\n# open a metadata xml file and add it to the GeoPackage\nwith open(...) as fin:\n id_ = gpkg.metadata.add_metadata(\n uri='https://www.isotc211.org/2005/gmd',\n scope=MetadataScope.dataset, metadata=fin.read()\n )\n# apply the metadata to a feature class\nreference = TableReference(table_name='road_l', file_id=id_)\ngpkg.metadata.add_references(reference)\n```\n\nSupport provided for the following reference types:\n* `GeoPackageReference` -- used for `GeoPackage` level metadata\n* `TableReference` -- used for `Table` and `FeatureClass` level metadata\n* `ColumnReference` -- used for a **column** in a `Table` or `FeatureClass`\n* `RowReference` -- used for a **row** in a `Table` or `FeatureClass`\n* `RowColumnReference` -- used for **row / column** combination in a `Table` or `FeatureClass`\n\n\n### Schema Extension\nSchema Extension implementation based on [F.9. Schema](http://www.geopackage.org/spec131/index.html#extension_schema)\nof the **GeoPackage Encoding Standard**.\n\nThe schema extension is enabled at the GeoPackage level and allows for extended\ndefinitions on column names (e.g. name, title, description) and for constraints\nto be defined for columns. Constraints definitions are intended for \napplications usage and, while similar, are not the same as database constraints.\n\nSchema extension can be enabled at create time for a GeoPackage or \ncan be enabled on an existing GeoPackage.\n\n\n```python\nfrom fudgeo.geopkg import GeoPackage\n\n# enable schema at create time\ngpkg: GeoPackage = GeoPackage.create('../data/schema.gpkg', enable_schema=True)\nassert gpkg.is_schema_enabled is True\n\n# enable schema on an existing GeoPackage\ngpkg: GeoPackage = GeoPackage('../data/example.gpkg')\nassert gpkg.is_schema_enabled is False\ngpkg.enable_schema_extension()\nassert gpkg.is_schema_enabled is True\n```\n\n```python\nfrom fudgeo.extension.schema import (\n EnumerationConstraint, GlobConstraint, RangeConstraint)\nfrom fudgeo.geopkg import GeoPackage\n\n# open GeoPackage with schema extension enabled\ngpkg: GeoPackage = GeoPackage('../data/example.gpkg')\n\n# add constraints for use with column definitions\nconstraints = [\n EnumerationConstraint(name='odds', values=[1, 3, 5, 7, 9]),\n EnumerationConstraint(name='colors', values=['red', 'yellow', 'blue']),\n GlobConstraint(name='pin', pattern='[0-9][0-9][0-9][0-9]'),\n RangeConstraint(name='exertion', min_value=6, max_value=20),\n RangeConstraint(name='longitude', min_value=-180, max_value=180),\n RangeConstraint(name='latitude', min_value=90, max_value=90),\n]\ngpkg.schema.add_constraints(constraints)\n\n# use constrains and set some additional details for column name\ngpkg.schema.add_column_definition(\n table_name='road_l', column_name='begin_longitude', \n name='Beginning Longitude for Road', title='Begin Longitude', \n constraint_name='longitude')\ngpkg.schema.add_column_definition(\n table_name='road_l', column_name='begin_latitude', \n name='Beginning Latitude for Road', title='Begin Latitude', \n constraint_name='latitude')\ngpkg.schema.add_column_definition(\n table_name='road_l', column_name='end_longitude', \n name='Ending Longitude for Road', title='End Longitude', \n constraint_name='longitude')\ngpkg.schema.add_column_definition(\n table_name='road_l', column_name='end_latitude', \n name='Ending Latitude for Road', title='End Latitude', \n constraint_name='latitude')\n```\n\nSupport provided for the following constraint types:\n* `EnumerationConstraint` -- restrict to one or more values\n* `GlobConstraint` -- pattern match based constraint\n* `RangeConstraint` -- value constrained within a range, optionally including the bounds\n\n\n## License\n\n[MIT](https://choosealicense.com/licenses/mit/)\n\n## Release History\n\n### v0.8.1\n* add support for creating feature classes with a geometry column name other than `SHAPE`\n* ensure support for Python 3.13 and update documentation / configuration\n\n### v0.8.0\n* drop support for Python 3.7 and 3.8\n* modernize type hinting\n* add `select` method to `FeatureClass` and `Table` objects\n\n### v0.7.2\n* bump `user_version` to reflect adopted version 1.4.0 of OGC GeoPackage\n* updated r-tree triggers based on changes made in 1.4.0\n\n### v0.7.1\n* ensure support for Python 3.12 and update documentation / configuration\n\n### v0.7.0\n* add support for **schema** extension\n* add support for **metadata** extension\n* add `__geo_interface__` to geometry classes\n* introduce `bounding_box` property on `Envelope` class\n* introduce `as_tuple` method on `Point` classes\n* add `extension` sub-package, move `spatial` module into `extension`\n* add `spatial_index_name` property on `FeatureClass`, returns the index table name\n* enable enforcement of foreign key constraints\n* reorganize code to handle OGR contents like an extension\n* move protected functions from `geopkg` module into `util` module and rename\n* add type hinting to `enumerations` module\n* move `EnvelopeCode` into `enumerations`\n\n### v0.6.0\n* change `ogr_contents` default value to `False` (breaking change)\n* add `spatial_index` option to `FeatureClass` creation, default to `False`\n* add `add_spatial_index` method to `FeatureClass` for adding spatial index post creation\n* add `has_spatial_index` property to `FeatureClass`\n* add `count` property to `Table` and `FeatureClass`\n* add `primary_key_field` property to `Table` and `FeatureClass`\n* small speed-up to `Point` unpacking\n* update `is_empty` to rely on internal attribute data type\n* improvements to SQL statements to handle names that must be escaped\n* bump `user_version` to reflect adopted version 1.3.1 of OGC GeoPackage\n* add optional views for geometry columns and spatial references\n\n### v0.5.2\n* store empty state on the instance during geometry read\n* introduce base classes for common capability and parametrize via class attributes\n* add stub files to provide type hinting specialization \n\n### v0.5.1\n* small performance improvements by reducing `bytes` concatenation and building up `bytearray`\n\n### v0.5.0\n* performance improvements for geometry reading (especially for geometries with large numbers of points / parts)\n* performance improvements for geometry writing\n* incorporated `numpy` and `bottleneck` as dependencies\n\n### v0.4.2\n* only unpack header and delay unpacking coordinates until needed\n* write envelope to geometry header\n\n### v0.4.1\n* unpack envelope from header (when available)\n* add `envelope` property to 2D, 3D, and 4D geometry\n* derive envelope from underlying coordinates / geometries if not set from header\n\n### v0.4.0\n* add string representations to `GeoPackage`, `Table`, and `FeatureClass`\n* allow optional creation of the `gpkg_ogr_contents`, defaults to True (create)\n* split `geometry` module into a sub-package\n\n### v0.3.10\n* add `escaped_name` property to `BaseTable`, applies to `Table` and `FeatureClass`\n* escape the name of input table / feature class during `create`\n\n### v0.3.9\n* quote reversal, doubles inside of singles for `escaped_name`\n\n### v0.3.8\n* add `fields` property to `BaseTable`, applies to `Table` and `FeatureClass`\n* add `field_names` property to `BaseTable`, applies to `Table` and `FeatureClass`\n* add `escaped_name` property to `Field` to return name valid for use in queries\n* add type hinting to embedded sql statements and supporting values\n\n### v0.3.7\n* add `is_empty` property to geometries, improved handling for empty geometries\n* update `user_version` to `10300`\n* add handling for geometry headers with envelopes (skipping content)\n* add type hinting to constants\n\n### v0.3.6\n* add `srs_id` (optional) to `SpatialReferenceSystem` instantiation, default to `org_coord_sys_id` if not specified\n\n### v0.3.5\n* store `coordinates` in attribute on 2D, 3D, and 4D geometry\n* avoid creating points on instantiation of geometry\n* expose `points` property to return point objects for 2D, 3D, and 4D geometry\n\n### v0.3.4\n* add `from_tuple` class methods to `Point`, `PointZ`, `PointM`, and `PointZM`\n\n### v0.3.3\n* catch possible exception when parsing microseconds from time\n* add converter for `timestamp` to use same converter as `datetime`\n* use lower case table names in queries\n\n### v0.3.2\n* include `PolygonM`, `PolygonZM`, `MultiPolygonM`, and `MultiPolygonZM` in geometry registration\n\n### v0.3.1\n* delay opening a `GeoPackage` connection until `connection` property is accessed \n\n### v0.3.0\n* add support for `PolygonM`, `PolygonZM`, `MultiPolygonM`, and `MultiPolygonZM`\n* add `geometry_column_name` and `geometry_type` properties to `FeatureClass`\n* simplify query used by `has_z` and `has_m`\n\n### v0.2.1\n* improve `_convert_datetime` to handle different formats for timestamp (contributed by [@alexeygribko](https://github.com/alexeygribko))\n\n### v0.2.0\n* improve `_convert_datetime` to handle timezone\n* add `DATETIME` tp `SQLFieldType`\n\n### v0.1.2\n* add option to overwrite feature classes and tables in `create_feature_class` and `create_table` methods \n* add option to overwrite in `create` method on `FeatureClass` and `Table` classes\n* add `drop` method on `FeatureClass` and `Table` classes\n\n### v0.1.1\n* make compatible with Python 3.7 and up (update type hints, remove walrus)\n* add support for OGR contents table (`gpkg_ogr_contents`) and triggers\n* add `tables` and `feature_classes` properties to `GeoPackage` class\n* include `application_id` and `user_version` in SQL definition\n* fix timestamp format (was missing seconds)\n\n### v0.1.0\n* initial release, basic port of legacy `pygeopkg` package\n",
"bugtrack_url": null,
"license": "MIT License Copyright (c) 2021-2024 Integrated Informatics Inc Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ",
"summary": "GeoPackage support from Python. fudgeo is a lightweight package for creating OGC GeoPackages, Feature Classes, and Tables. Easily read and write geometries and attributes to Feature Classes and Tables using regular Python objects and SQLite syntax.",
"version": "0.8.1",
"project_urls": {
"Homepage": "https://github.com/realiii/fudgeo"
},
"split_keywords": [
"geopackage"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "d01e7181b2176ae7b5a4bc9d2f061db3f137c37f9c88f2201530061ef69d0c10",
"md5": "bdbdb75341508662d2921a11d62b3e77",
"sha256": "742912bd6b6e38d72bf8944cffb716aa2d2dd19e411d6409b815fee8a6cbe1d1"
},
"downloads": -1,
"filename": "fudgeo-0.8.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "bdbdb75341508662d2921a11d62b3e77",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.9",
"size": 47346,
"upload_time": "2024-10-19T17:44:53",
"upload_time_iso_8601": "2024-10-19T17:44:53.001994Z",
"url": "https://files.pythonhosted.org/packages/d0/1e/7181b2176ae7b5a4bc9d2f061db3f137c37f9c88f2201530061ef69d0c10/fudgeo-0.8.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-10-19 17:44:53",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "realiii",
"github_project": "fudgeo",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "fudgeo"
}