I would like to add models for all of our API response objects, as an alternative to working with just JSON. This would be a big improvement toward making this a fully-featured python API client.
To do this I'd like to use the attrs library. It's lightweight, fast, used everywhere (with a subset of very similar features added to the stdlib in 3.7 as dataclasses), integrated with python type annotations and mypy, and makes for super clean code.
That gives you a ton of features that make responses easier to work with interactively, for example a nice default __str__ method and tab-completion:
More benefits:
The type hints make it easier to spot bugs in client code (compared to consuming JSON)
The type hints can also potentially be used to convert to other data formats (via cattrs); also see the recently started pyinaturalist-convert repo
Models could potentially be reused to create objects to submit to POST and PUT endpoints (which would mean a lot less referring to the docs to figure out what format it needs to be in).
attrs can generate slotted classes, which are faster and more memory-efficient than dicts (maybe only noticeable when working with larger datasets, though).
The features for defaults, validators, and converters would simplify and/or replace many of the functions currently in the request_params and response_format modules.
Integrating with API functions
This issue will just be for creating the models. Integrating them with the API can be a separate issue. I imagine that can work by either:
Adding an option to pass to existing API functions
Adding wrappers for the API functions to the models (e.g., Observation.search(...))
Tasks
Models:
[x] Base
[x] ControlledTerm
[x] ControlledTermValue
[x] Annotation
[x] Comment
[x] Identification
[x] LifeList
[x] LifeListTaxon
[x] Observation
[x] ObservationField
[x] ObservationFieldValue
[x] Photo
[x] Place
[x] Project
[x] ProjectObservation
[x] ProjectObservationField
[x] ProjectUser
[x] SearchResult
[x] Taxon
[x] ConservationStatus
[x] EstablishmentMeans
[x] TaxonCount
[x] TaxonCounts
[x] User
Other tasks:
[x] Apply type conversions (using response_format methods as attrs converters)
[x] Customize generated str and repr methods to include nested model objects
[x] Lazy-load nested model objects (like Observation.taxon) for better performance
I would like to add models for all of our API response objects, as an alternative to working with just JSON. This would be a big improvement toward making this a fully-featured python API client.
To do this I'd like to use the attrs library. It's lightweight, fast, used everywhere (with a subset of very similar features added to the stdlib in 3.7 as
dataclasses
), integrated with python type annotations and mypy, and makes for super clean code.Update: see pyinaturalist/models for what I've added so far.
Example
Quick example model for observation comments:
Some more examples here: naturtag/models.
Benefits
That gives you a ton of features that make responses easier to work with interactively, for example a nice default
__str__
method and tab-completion:More benefits:
POST
andPUT
endpoints (which would mean a lot less referring to the docs to figure out what format it needs to be in).attrs
can generate slotted classes, which are faster and more memory-efficient than dicts (maybe only noticeable when working with larger datasets, though).request_params
andresponse_format
modules.Integrating with API functions
This issue will just be for creating the models. Integrating them with the API can be a separate issue. I imagine that can work by either:
Tasks
Models:
Other tasks:
Observation.taxon
) for better performanceFigure out how to auto-document(see https://github.com/python-attrs/attrs/issues/357)attrs.field
s in Sphinx docs