Skip to content

Commit

Permalink
Give model classes a nice repr again (#1380)
Browse files Browse the repository at this point in the history
* Give model classes a nice repr again

Resolves #1379

* Limit representations of dicts

* Remove redundant methods, consolidating in base class

* Dict item access yields more dicts

* Use object access in topojson test
  • Loading branch information
sgillies authored Apr 23, 2024
1 parent a50e9fc commit 628e781
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 5 deletions.
7 changes: 7 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ Changes

All issue numbers are relative to https://github.com/Toblerity/Fiona/issues.

1.10b2 (TBD)
------------

Bug fixes:

- Fiona model objects have a informative, printable representation again (#).

1.10b1 (2024-04-16)
-------------------

Expand Down
26 changes: 24 additions & 2 deletions fiona/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,15 @@
from enum import Enum
import itertools
from json import JSONEncoder
import reprlib
from warnings import warn

from fiona.errors import FionaDeprecationWarning

_model_repr = reprlib.Repr()
_model_repr.maxlist = 1
_model_repr.maxdict = 5


class OGRGeometryType(Enum):
Unknown = 0
Expand Down Expand Up @@ -134,7 +139,10 @@ def _props(self):
}

def __getitem__(self, item):
props = self._props()
props = {
k: (dict(v) if isinstance(v, Object) else v)
for k, v in self._props().items()
}
props.update(**self._data)
return props[item]

Expand All @@ -146,6 +154,13 @@ def __len__(self):
props = self._props()
return len(props) + len(self._data)

def __repr__(self):
kvs = [
f"{k}={v!r}"
for k, v in itertools.chain(self._props().items(), self._data.items())
]
return "fiona.{}({})".format(self.__class__.__name__, ", ".join(kvs))

def __setitem__(self, key, value):
warn(
"instances of this class -- CRS, geometry, and feature objects -- will become immutable in fiona version 2.0",
Expand Down Expand Up @@ -197,6 +212,10 @@ def __init__(self, coordinates=None, type=None, geometries=None, **data):
)
super().__init__(**data)

def __repr__(self):
kvs = [f"{k}={_model_repr.repr(v)}" for k, v in self.items() if v is not None]
return "fiona.Geometry({})".format(", ".join(kvs))

@classmethod
def from_dict(cls, ob=None, **kwargs):
if ob is not None:
Expand Down Expand Up @@ -384,7 +403,10 @@ class ObjectEncoder(JSONEncoder):

def default(self, o):
if isinstance(o, Object):
o_dict = {k: self.default(v) for k, v in o.items()}
o_dict = {
k: self.default(v)
for k, v in itertools.chain(o._props().items(), o._data.items())
}
if isinstance(o, Geometry):
if o.type == "GeometryCollection":
_ = o_dict.pop("coordinates", None)
Expand Down
9 changes: 9 additions & 0 deletions tests/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,3 +333,12 @@ def test_geometry_collection_encoding():
assert "coordinates" not in ObjectEncoder().default(
Geometry(type="GeometryCollection", geometries=[])
)


def test_feature_repr():
feat = Feature(
id="1",
geometry=Geometry(type="LineString", coordinates=[(0, 0)] * 100),
properties=Properties(a=1, foo="bar"),
)
assert repr(feat) == "fiona.Feature(geometry=fiona.Geometry(coordinates=[(0, 0), ...], type='LineString'), id='1', properties=fiona.Properties(a=1, foo='bar'))"
6 changes: 3 additions & 3 deletions tests/test_topojson.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@ def test_read_topojson(data_dir):

assert len(features) == 3, "unexpected number of features"
for feature in features:
assert isinstance(feature["properties"], Properties)
assert len(feature["properties"]) > 0
assert feature["geometry"]["type"] in {"Point", "LineString", "Polygon"}
assert isinstance(feature.properties, Properties)
assert len(feature.properties) > 0
assert feature.geometry.type in {"Point", "LineString", "Polygon"}

0 comments on commit 628e781

Please sign in to comment.