Validation and specification

We use self-made GeoDataFrame to validate and define data, used in classes and methods.

The GeoDataFrame class is inherited from:

  • geopandas.GeoDataFrame – so it behaves like typical GeoDataFrame.

  • Generic[T] – so you can define GeoDataFrame columns and types with BaseRow inherited class.

  • pydantic.BaseModel – so it can access class from [].

Meanwhile the BaseRow class defines the row of a GeoDataFrame and is inherited from:

  • pydantic.BaseModel – to automatically validate row data according to class fields.

  • ABC – the class is abstract, so it has to be inherited when you (we) define data.

[10]:
import geopandas as gpd
from shapely import Point

data = [
  {
    'some_int': 123,
    'some_str': 'foo',
    'geometry': Point(0,0)
  }
]

gdf = gpd.GeoDataFrame(data)
gdf
[10]:
some_int some_str geometry
0 123 foo POINT (0.00000 0.00000)

Let’s define our own BaseRow inherited class to see how it works.

[12]:
from blocksnet import GeoDataFrame, BaseRow

class SomeRow(BaseRow):
  some_int : int
  some_str : str
  geometry : Point

GeoDataFrame[SomeRow](gdf)
[12]:
geometry some_int some_str
0 POINT (0.00000 0.00000) 123 foo

But if data doesn’t match defined specification, the error will appear and it’s ok.

[13]:
gdf.some_int = 'suddenly some string appears'
[14]:
GeoDataFrame[SomeRow](gdf)
---------------------------------------------------------------------------
ValidationError                           Traceback (most recent call last)
Cell In[14], line 1
----> 1 GeoDataFrame[SomeRow](gdf)

File ~/masterplanning/blocksnet/models/geodataframe.py:50, in GeoDataFrame.__init__(self, data, *args, **kwargs)
     48 for i in data.index:
     49     dict = data.loc[i].to_dict()
---> 50     rows.append(generic_class(index=i, **dict).__dict__)
     51 super().__init__(rows)
     52 # and finally return index to where it belongs

File ~/masterplanning/venv/lib/python3.10/site-packages/pydantic/main.py:150, in BaseModel.__init__(__pydantic_self__, **data)
    148 # `__tracebackhide__` tells pytest and some other tools to omit this function from tracebacks
    149 __tracebackhide__ = True
--> 150 __pydantic_self__.__pydantic_validator__.validate_python(data, self_instance=__pydantic_self__)

ValidationError: 1 validation error for SomeRow
some_int
  Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='suddenly some string appears', input_type=str]
    For further information visit https://errors.pydantic.dev/2.0.1/v/int_parsing