pyinaturalist 0.19.0.dev2__tar.gz → 0.19.0.dev3__tar.gz
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.
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/HISTORY.md +8 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/PKG-INFO +19 -17
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/README.md +3 -3
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/conf.py +1 -1
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/endpoints.md +56 -55
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/user_guide.md +4 -7
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/Tutorial_2_Taxa.ipynb +10 -4
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/sample_data.py +2 -2
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinat/__init__.py +1 -1
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/__init__.py +2 -2
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/client.py +3 -5
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/constants.py +4 -5
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/controllers/__init__.py +3 -2
- pyinaturalist-0.19.0.dev2/pyinaturalist/controllers/controlled_term_controller.py → pyinaturalist-0.19.0.dev3/pyinaturalist/controllers/annotation_controller.py +52 -2
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/controllers/observation_controller.py +22 -3
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/converters.py +3 -18
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/docs/__init__.py +1 -1
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/docs/signatures.py +1 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/docs/templates.py +2 -1
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/formatters.py +65 -39
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/models/__init__.py +11 -4
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/models/base.py +1 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/models/checklist.py +2 -1
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/models/conservation_status.py +2 -1
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/models/controlled_term.py +2 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/models/identification.py +1 -1
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/models/observation.py +119 -23
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/models/taxon.py +221 -65
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/node_api.py +3 -3
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/request_params.py +37 -22
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/rest_api.py +3 -3
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/v0/__init__.py +1 -1
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/v0/observations.py +4 -2
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/v1/__init__.py +2 -1
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/v1/observations.py +12 -12
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/v1/taxa.py +32 -1
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/v2/__init__.py +1 -1
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyproject.toml +29 -15
- pyinaturalist-0.19.0.dev3/test/controllers/test_annotation_controller.py +84 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/controllers/test_observation_controller.py +36 -7
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/controllers/test_project_controller.py +1 -1
- pyinaturalist-0.19.0.dev3/test/sample_data/get_lifelist_metadata.json +82 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_taxonomy.json +11 -2
- pyinaturalist-0.19.0.dev3/test/sample_data/get_observation_taxonomy_by_genus.json +327 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_with_quality_metrics.json +26 -2
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data.py +33 -4
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/test_compat.py +1 -1
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/test_converters.py +4 -2
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/test_formatters.py +53 -11
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/test_models.py +267 -43
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/test_request_params.py +14 -6
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/v1/test_observations.py +16 -11
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/v1/test_taxa.py +24 -1
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/v2/test_observations_v2.py +2 -2
- pyinaturalist-0.19.0.dev2/pyinaturalist/models/life_list.py +0 -112
- pyinaturalist-0.19.0.dev2/test/controllers/test_controlled_terms_controller.py +0 -49
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/.readthedocs.yml +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/CONTRIBUTING.md +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/CONTRIBUTORS.md +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/LICENSE +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docker-compose.yml +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/_static/collapsible_container.css +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/_static/collapsible_container.js +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/_static/colors.css +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/_static/favicon.ico +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/_static/pyinaturalist_logo.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/_static/python-logo-green.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/_static/table.css +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/_templates/autosummary/module.rst_t +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/_templates/autosummary_core/class.rst +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/_templates/header.html +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/_templates/localtoc.html +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/_templates/module.rst_t +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/_templates/package.rst_t +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/automodapi.rst +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/code_of_conduct.md +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/contributing.md +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/contributors.md +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/examples.md +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/history.md +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/images/inat-new-application-complete.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/images/inat-new-application.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/images/inat-observation-identifiers.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/images/inat-observation-observers.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/images/inat-observation-page-annotated.odg +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/images/inat-observation-page-annotated.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/images/inat-observation-page.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/images/inat-observation-search-bar.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/images/inat-observation-search-filters.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/images/inat-observation-species-counts.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/images/inat-taxon-autocomplete.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/images/inat-taxon-page.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/images/inat-user-login.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/images/open-in-vscode.svg +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/images/password_manager_keying.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/images/pprint_table.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/images/pyinaturalist_logo.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/images/pyinaturalist_logo.xcf +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/images/pyinaturalist_logo_gh_preview.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/images/pyinaturalist_logo_gh_preview.xcf +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/images/pyinaturalist_logo_hex.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/images/pyinaturalist_logo_hex.xcf +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/images/pyinaturalist_logo_med.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/images/pyinaturalist_logo_stacked.xcf +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/images/pyinaturalist_logo_white.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/images/pyinaturalist_logo_white.xcf +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/images/python-logo-green.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/images/python-logo-green.xcf +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/index.md +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/pyinaturalist.controllers.rst +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/pyinaturalist.models.rst +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/docs/reference.md +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/Data Visualizations - Matplotlib.ipynb +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/Data Visualizations - Regional Activity Report.ipynb +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/Data Visualizations - Regional Observation Stats.ipynb +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/Data Visualizations - Seaborn.ipynb +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/README.md +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/Tutorial_1_Observations.ipynb +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/Tutorial_3_Data_Visualizations.ipynb +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/__init__.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/images/combined_activity_stats.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/images/histogram_by_iconic_taxon.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/images/identifiers_by_month.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/images/observation_image_grid.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/images/observation_map.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/images/observations_by_date_and_time.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/images/observations_by_month.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/images/observations_by_quality_grade.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/images/observations_by_year.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/images/observers_by_month.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/images/taxa_by_month.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/images/total_observations_by_iconic_taxon.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/images/total_taxa_by_iconic_taxon.png +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/observation_photo_metadata.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/observations_to_gpx.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/observations_to_tsp.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/sample_data/fips_to_inat_place_ids.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/sample_data/observation_fields.parquet +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/sample_data/observations.gpx +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/sample_data/observations.tsp +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/sample_data/photo_info.html +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/examples/sample_data/us_county_fips_codes.csv +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/auth.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/controllers/base_controller.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/controllers/place_controller.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/controllers/project_controller.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/controllers/taxon_controller.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/controllers/user_controller.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/docs/docstrings.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/docs/emoji.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/docs/model_docs.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/exceptions.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/models/lazy_property.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/models/media.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/models/message.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/models/observation_field.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/models/place.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/models/project.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/models/search.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/models/user.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/paginator.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/py.typed +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/session.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/v0/observation_fields.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/v1/controlled_terms.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/v1/identifications.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/v1/messages.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/v1/observation_fields.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/v1/places.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/v1/posts.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/v1/projects.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/v1/search.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/v1/users.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/v2/observations.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/__init__.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/conftest.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/controllers/test_place_controller.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/controllers/test_taxon_controller.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/controllers/test_user_controller.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/docs/test_docstrings.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/docs/test_signatures.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/add_project_observation.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/create_observation_fail.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/create_observation_result.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/create_observation_v1.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_access_token.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_access_token_401.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_all_observation_identifiers_ex_results.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_all_observation_observers_ex_results.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_all_observation_species_counts_ex_results.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_all_observation_species_counts_page1.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_all_observation_species_counts_page2.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_controlled_terms.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_controlled_terms_for_taxon.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_identifications.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_identifications.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_jwt.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_messages.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_nonexistent_observation.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_2.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_fields.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_fields_page1.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_fields_page2.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_histogram_day.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_histogram_day.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_histogram_hour.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_histogram_hour.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_histogram_month.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_histogram_month.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_histogram_month_of_year.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_histogram_month_of_year.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_histogram_week.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_histogram_week.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_histogram_week_of_year.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_histogram_week_of_year.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_identifiers_ex_results.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_identifiers_node_page1.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_identifiers_node_page2.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_observers_ex_results.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_observers_node_page1.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_observers_node_page2.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_popular_field_values.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_popular_field_values.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_species_counts.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_species_counts.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_taxon_summary.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_taxon_summary_conserved.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_taxon_summary_listed.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_with_ofvs.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observation_with_sounds.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observations.atom +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observations.csv +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observations.dwc +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observations.js +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observations.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observations.kml +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observations_by_id.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observations_by_id.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observations_node.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observations_node_page1.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observations_node_page2.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observations_v2_full.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observations_v2_full.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observations_v2_minimal.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_observations_v2_minimal.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_places_autocomplete.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_places_autocomplete.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_places_by_id.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_places_by_id.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_places_nearby.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_places_nearby.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_posts_login.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_posts_project.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_projects.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_projects.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_projects_by_id.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_projects_by_id.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_projects_obs_fields.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_search.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_search.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_taxa.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_taxa.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_taxa_autocomplete.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_taxa_autocomplete.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_taxa_autocomplete_minified.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_taxa_by_id.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_taxa_by_id.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_taxa_by_id_conservation_statuses.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_taxa_map_layers.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_taxa_with_all_names.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_taxa_with_preferred_place.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_user_by_id.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_user_by_id.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_users_autocomplete.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/get_users_autocomplete.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/obs_image.jpg +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/obs_sound.wav +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/post_observation_photos.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/post_observation_photos_list.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/post_observation_sounds.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/post_observation_sounds_list.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/post_put_observation_field_value.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/put_projects.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/update_observation_result.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/upload_photos.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/upload_photos_and_sounds.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/sample_data/upload_sounds.json +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/test_auth.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/test_client.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/test_paginator.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/test_session.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/v0/test_observation_fields_v0.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/v0/test_observations_v0.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/v1/test_controlled_terms.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/v1/test_identifications.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/v1/test_messages.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/v1/test_node_api.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/v1/test_observation_fields.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/v1/test_places.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/v1/test_posts.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/v1/test_projects.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/v1/test_search.py +0 -0
- {pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/test/v1/test_users.py +0 -0
|
@@ -15,9 +15,17 @@ Add support for searching observations by observation fields, using a new `obser
|
|
|
15
15
|
* `get_observation_species_counts()`
|
|
16
16
|
|
|
17
17
|
### Models
|
|
18
|
+
* Add `make_tree()` function to build a tree from `Taxon` objects or a `LifeList`
|
|
19
|
+
* Add `pprint_tree()` function to print a taxon tree on the console
|
|
20
|
+
* Add `Taxon.flatten()` method to return a taxon and its descendants as a flat list
|
|
18
21
|
* Add `Observation.ident_taxon_ids` dynamic property to get all identification taxon IDs (with ancestors)
|
|
19
22
|
* Add `Observation.cumulative_ids` dynamic property to calculate agreements/total community identifications
|
|
23
|
+
* Add `Application` model for `Observation.application` (for v2 API)
|
|
24
|
+
* Add `Fave` model for `Observation.faves`
|
|
25
|
+
* Add `Flag` model for `Observation.flags`
|
|
26
|
+
* Add `QualityMetric` model for `Observation.quality_metrics`
|
|
20
27
|
* Add `Sound` model for `Observation.sounds`
|
|
28
|
+
* Add `Vote` model for `Observation.votes`
|
|
21
29
|
* Fix initialization of `ListedTaxon.place`
|
|
22
30
|
|
|
23
31
|
## 0.18.0 (2023-02-27)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pyinaturalist
|
|
3
|
-
Version: 0.19.0.
|
|
3
|
+
Version: 0.19.0.dev3
|
|
4
4
|
Summary: iNaturalist API client for python
|
|
5
5
|
Home-page: https://github.com/pyinat/pyinaturalist
|
|
6
6
|
License: MIT
|
|
@@ -24,25 +24,27 @@ Classifier: Typing :: Typed
|
|
|
24
24
|
Provides-Extra: all
|
|
25
25
|
Provides-Extra: docs
|
|
26
26
|
Requires-Dist: attrs (>=21.2)
|
|
27
|
-
Requires-Dist: furo (>=2023.3,<2024.0) ; extra == "docs"
|
|
28
|
-
Requires-Dist: ipython (>=7.
|
|
27
|
+
Requires-Dist: furo (>=2023.3,<2024.0) ; (python_version >= "3.8") and (extra == "docs")
|
|
28
|
+
Requires-Dist: ipython (>=7.34,<8.0) ; (python_version >= "3.8") and (extra == "docs")
|
|
29
29
|
Requires-Dist: keyring (>=22.3)
|
|
30
|
-
Requires-Dist: linkify-it-py (>=
|
|
31
|
-
Requires-Dist:
|
|
32
|
-
Requires-Dist:
|
|
30
|
+
Requires-Dist: linkify-it-py (>=2.0,<3.0) ; (python_version >= "3.8") and (extra == "docs")
|
|
31
|
+
Requires-Dist: markdown-it-py (==2.2) ; python_version == "3.7"
|
|
32
|
+
Requires-Dist: markdown-it-py (>=2.2) ; python_version >= "3.8"
|
|
33
|
+
Requires-Dist: myst-parser (>=1.0) ; (python_version >= "3.8") and (extra == "docs")
|
|
34
|
+
Requires-Dist: nbsphinx (>=0.9,<0.10) ; (python_version >= "3.8") and (extra == "docs")
|
|
33
35
|
Requires-Dist: platformdirs (>=2.6)
|
|
34
36
|
Requires-Dist: python-dateutil (>=2.0)
|
|
35
37
|
Requires-Dist: python-forge (>=18.6)
|
|
36
|
-
Requires-Dist: requests (>=2.
|
|
37
|
-
Requires-Dist: requests-cache (>=1.
|
|
38
|
+
Requires-Dist: requests (>=2.25)
|
|
39
|
+
Requires-Dist: requests-cache (>=1.1)
|
|
38
40
|
Requires-Dist: requests-ratelimiter (>=0.3.2)
|
|
39
41
|
Requires-Dist: rich (>=10.9)
|
|
40
|
-
Requires-Dist: sphinx (>=
|
|
41
|
-
Requires-Dist: sphinx-autodoc-typehints (
|
|
42
|
-
Requires-Dist: sphinx-automodapi (>=0.
|
|
43
|
-
Requires-Dist: sphinx-copybutton (>=0.5) ; extra == "docs"
|
|
44
|
-
Requires-Dist: sphinx-design (>=0.
|
|
45
|
-
Requires-Dist: sphinxcontrib-apidoc (>=0.3,<0.4) ; extra == "docs"
|
|
42
|
+
Requires-Dist: sphinx (>=6.2,<7.0) ; (python_version >= "3.8") and (extra == "docs")
|
|
43
|
+
Requires-Dist: sphinx-autodoc-typehints (==1.20) ; (python_version >= "3.8") and (extra == "docs")
|
|
44
|
+
Requires-Dist: sphinx-automodapi (>=0.15,<0.16) ; (python_version >= "3.8") and (extra == "docs")
|
|
45
|
+
Requires-Dist: sphinx-copybutton (>=0.5) ; (python_version >= "3.8") and (extra == "docs")
|
|
46
|
+
Requires-Dist: sphinx-design (>=0.4) ; (python_version >= "3.8") and (extra == "docs")
|
|
47
|
+
Requires-Dist: sphinxcontrib-apidoc (>=0.3,<0.4) ; (python_version >= "3.8") and (extra == "docs")
|
|
46
48
|
Requires-Dist: ujson (>5.0) ; extra == "all"
|
|
47
49
|
Project-URL: Documentation, https://pyinaturalist.readthedocs.io
|
|
48
50
|
Project-URL: Repository, https://github.com/pyinat/pyinaturalist
|
|
@@ -99,10 +101,10 @@ Many of the most relevant API endpoints are supported, including:
|
|
|
99
101
|
* 💬 Messages
|
|
100
102
|
* 👀 Observations (multiple formats)
|
|
101
103
|
* 📷 Observation photos + sounds
|
|
102
|
-
* 📊 Observation observers, identifiers,
|
|
104
|
+
* 📊 Observation histograms, observers, identifiers, life lists, and species counts
|
|
103
105
|
* 📍 Places
|
|
104
106
|
* 👥 Projects
|
|
105
|
-
* 🐦Species
|
|
107
|
+
* 🐦 Species
|
|
106
108
|
* 👤 Users
|
|
107
109
|
|
|
108
110
|
## Quickstart
|
|
@@ -205,7 +207,7 @@ new_observation_id = response[0]['id']
|
|
|
205
207
|
We can then [update the observation](https://pyinaturalist.readthedocs.io/en/stable/modules/pyinaturalist.v1.observations.html#pyinaturalist.v1.observations.update_observation) information, photos, or sounds:
|
|
206
208
|
```python
|
|
207
209
|
update_observation(
|
|
208
|
-
|
|
210
|
+
new_observation_id,
|
|
209
211
|
access_token=token,
|
|
210
212
|
description='updated description !',
|
|
211
213
|
photos='~/observations/wasp_nest.jpg',
|
|
@@ -49,10 +49,10 @@ Many of the most relevant API endpoints are supported, including:
|
|
|
49
49
|
* 💬 Messages
|
|
50
50
|
* 👀 Observations (multiple formats)
|
|
51
51
|
* 📷 Observation photos + sounds
|
|
52
|
-
* 📊 Observation observers, identifiers,
|
|
52
|
+
* 📊 Observation histograms, observers, identifiers, life lists, and species counts
|
|
53
53
|
* 📍 Places
|
|
54
54
|
* 👥 Projects
|
|
55
|
-
* 🐦Species
|
|
55
|
+
* 🐦 Species
|
|
56
56
|
* 👤 Users
|
|
57
57
|
|
|
58
58
|
## Quickstart
|
|
@@ -155,7 +155,7 @@ new_observation_id = response[0]['id']
|
|
|
155
155
|
We can then [update the observation](https://pyinaturalist.readthedocs.io/en/stable/modules/pyinaturalist.v1.observations.html#pyinaturalist.v1.observations.update_observation) information, photos, or sounds:
|
|
156
156
|
```python
|
|
157
157
|
update_observation(
|
|
158
|
-
|
|
158
|
+
new_observation_id,
|
|
159
159
|
access_token=token,
|
|
160
160
|
description='updated description !',
|
|
161
161
|
photos='~/observations/wasp_nest.jpg',
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* Some CSS and JS adds collapsible drop-down container
|
|
15
15
|
* On Readthedocs, CSS and JS is automatically added for a version dropdown
|
|
16
16
|
"""
|
|
17
|
-
#
|
|
17
|
+
# ruff: noqa: E402
|
|
18
18
|
import sys
|
|
19
19
|
from importlib.metadata import version as pkg_version
|
|
20
20
|
from os import makedirs, symlink
|
|
@@ -1,79 +1,80 @@
|
|
|
1
1
|
(endpoints)=
|
|
2
2
|
# {fa}`table` Endpoint Summary
|
|
3
3
|
|
|
4
|
-
Below is a list of iNaturalist API endpoints that have either been added or
|
|
5
|
-
future, along with their corresponding functions in pyinaturalist.
|
|
4
|
+
Below is a list of iNaturalist API endpoints that have either been added or are likely be added in
|
|
5
|
+
the future, along with their corresponding functions in pyinaturalist.
|
|
6
6
|
|
|
7
7
|
## v1 API
|
|
8
8
|
For all available endpoints, see: <http://api.inaturalist.org/v1/docs/>
|
|
9
9
|
|
|
10
|
-
| Method | Endpoint | Function
|
|
11
|
-
| ------ |
|
|
10
|
+
| Method | Endpoint | Function |
|
|
11
|
+
| ------ | ---------------------------------- | ------------------------------------------------------------ |
|
|
12
12
|
| POST | /annotations |
|
|
13
13
|
| DELETE | /annotations/{id} |
|
|
14
14
|
| POST | /comments |
|
|
15
15
|
| DELETE | /comments/{id} |
|
|
16
16
|
| PUT | /comments/{id} |
|
|
17
|
-
| GET | /controlled_terms | {py:func}`.get_controlled_terms`
|
|
18
|
-
| GET | /controlled_terms/for_taxon | {py:func}`.get_controlled_terms`
|
|
19
|
-
| GET | /identifications | {py:func}`.get_identifications`
|
|
20
|
-
| GET | /identifications/{id} | {py:func}`.get_identifications_by_id`
|
|
17
|
+
| GET | /controlled_terms | {py:func}`.get_controlled_terms` |
|
|
18
|
+
| GET | /controlled_terms/for_taxon | {py:func}`.get_controlled_terms` |
|
|
19
|
+
| GET | /identifications | {py:func}`.get_identifications` |
|
|
20
|
+
| GET | /identifications/{id} | {py:func}`.get_identifications_by_id` |
|
|
21
21
|
| GET | /identifications/species_counts |
|
|
22
22
|
| GET | /identifications/identifiers |
|
|
23
23
|
| GET | /identifications/observers |
|
|
24
24
|
| GET | /identifications/similar_species |
|
|
25
|
-
| GET | /messages | {py:func}`.get_messages`
|
|
26
|
-
| GET | /messages/{id} | {py:func}`.get_message_by_id`
|
|
27
|
-
| GET | /messages/unread | {py:func}`.get_unread_meassage_count`
|
|
28
|
-
| DELETE | /observation_field_values/{id} | {py:func}`.delete_observation_field`
|
|
29
|
-
| PUT | /observation_field_values/{id} | {py:func}`.set_observation_field`
|
|
30
|
-
| POST | /observation_field_values | {py:func}`.set_observation_field`
|
|
31
|
-
| POST | /observation_photos | {py:func}`.upload`
|
|
32
|
-
| POST | /observation_sounds | {py:func}`.upload`
|
|
33
|
-
| DELETE | /observations/{id} | {py:func}`~pyinaturalist.v1.observations.delete_observation`
|
|
34
|
-
| GET | /observations/{id} | {py:func}`.get_observations_by_id`
|
|
35
|
-
| PUT | /observations/{id} | {py:func}`~pyinaturalist.v1.observations.update_observation`
|
|
36
|
-
| GET | /observations/{id}/taxon_summary | {py:func}`.get_observation_taxon_summary`
|
|
37
|
-
| GET | /observations | {py:func}`~pyinaturalist.v1.observations.get_observations`
|
|
38
|
-
| POST | /observations | {py:func}`~pyinaturalist.v1.observations.create_observation`
|
|
39
|
-
| GET | /observations/histogram | {py:func}`.get_observation_histogram`
|
|
40
|
-
| GET | /observations/identifiers | {py:func}`.get_observation_identifiers`
|
|
41
|
-
| GET | /observations/observers | {py:func}`.get_observation_observers`
|
|
42
|
-
| GET | /observations/popular_field_values | {py:func}`.get_observation_popular_field_values`
|
|
43
|
-
| GET | /observations/species_counts | {py:func}`.get_observation_species_counts`
|
|
44
|
-
| GET | /observations/taxonomy | {py:func}`.get_observation_taxonomy`
|
|
45
|
-
| GET | /places/{id} | {py:func}`.get_places_by_id`
|
|
46
|
-
| GET | /places/autocomplete | {py:func}`.get_places_autocomplete`
|
|
47
|
-
| GET | /places/nearby | {py:func}`.get_places_nearby`
|
|
48
|
-
| GET | /posts | {py:func}`.get_posts`
|
|
49
|
-
| GET | /projects | {py:func}`.get_projects`
|
|
50
|
-
| GET | /projects/{id} | {py:func}`.get_projects_by_id`
|
|
51
|
-
| PUT | /projects/{id} | {py:func}`.update_project`
|
|
25
|
+
| GET | /messages | {py:func}`.get_messages` |
|
|
26
|
+
| GET | /messages/{id} | {py:func}`.get_message_by_id` |
|
|
27
|
+
| GET | /messages/unread | {py:func}`.get_unread_meassage_count` |
|
|
28
|
+
| DELETE | /observation_field_values/{id} | {py:func}`.delete_observation_field` |
|
|
29
|
+
| PUT | /observation_field_values/{id} | {py:func}`.set_observation_field` |
|
|
30
|
+
| POST | /observation_field_values | {py:func}`.set_observation_field` |
|
|
31
|
+
| POST | /observation_photos | {py:func}`.upload` |
|
|
32
|
+
| POST | /observation_sounds | {py:func}`.upload` |
|
|
33
|
+
| DELETE | /observations/{id} | {py:func}`~pyinaturalist.v1.observations.delete_observation` |
|
|
34
|
+
| GET | /observations/{id} | {py:func}`.get_observations_by_id` |
|
|
35
|
+
| PUT | /observations/{id} | {py:func}`~pyinaturalist.v1.observations.update_observation` |
|
|
36
|
+
| GET | /observations/{id}/taxon_summary | {py:func}`.get_observation_taxon_summary` |
|
|
37
|
+
| GET | /observations | {py:func}`~pyinaturalist.v1.observations.get_observations` |
|
|
38
|
+
| POST | /observations | {py:func}`~pyinaturalist.v1.observations.create_observation` |
|
|
39
|
+
| GET | /observations/histogram | {py:func}`.get_observation_histogram` |
|
|
40
|
+
| GET | /observations/identifiers | {py:func}`.get_observation_identifiers` |
|
|
41
|
+
| GET | /observations/observers | {py:func}`.get_observation_observers` |
|
|
42
|
+
| GET | /observations/popular_field_values | {py:func}`.get_observation_popular_field_values` |
|
|
43
|
+
| GET | /observations/species_counts | {py:func}`.get_observation_species_counts` |
|
|
44
|
+
| GET | /observations/taxonomy | {py:func}`.get_observation_taxonomy` |
|
|
45
|
+
| GET | /places/{id} | {py:func}`.get_places_by_id` |
|
|
46
|
+
| GET | /places/autocomplete | {py:func}`.get_places_autocomplete` |
|
|
47
|
+
| GET | /places/nearby | {py:func}`.get_places_nearby` |
|
|
48
|
+
| GET | /posts | {py:func}`.get_posts` |
|
|
49
|
+
| GET | /projects | {py:func}`.get_projects` |
|
|
50
|
+
| GET | /projects/{id} | {py:func}`.get_projects_by_id` |
|
|
51
|
+
| PUT | /projects/{id} | {py:func}`.update_project` |
|
|
52
52
|
| GET | /projects/{id}/members |
|
|
53
53
|
| GET | /projects/{id}/subscriptions |
|
|
54
|
-
| POST | /projects/{id}/add | {py:func}`.add_project_observation`
|
|
55
|
-
| DELETE | /projects/{id}/remove | {py:func}`.delete_project_observation`
|
|
54
|
+
| POST | /projects/{id}/add | {py:func}`.add_project_observation` |
|
|
55
|
+
| DELETE | /projects/{id}/remove | {py:func}`.delete_project_observation` |
|
|
56
56
|
| GET | /projects/autocomplete |
|
|
57
|
-
| GET | /search | {py:func}`.search`
|
|
58
|
-
| GET | /taxa | {py:func}`.get_taxa`
|
|
59
|
-
| GET | /taxa/{id} | {py:func}`.get_taxa_by_id`
|
|
60
|
-
| GET | /taxa/{id}/map_layers | {py:func}`.get_taxa_map_layers`
|
|
61
|
-
| GET | /taxa/autocomplete | {py:func}`.get_taxa_autocomplete`
|
|
62
|
-
| GET | /
|
|
57
|
+
| GET | /search | {py:func}`.search` |
|
|
58
|
+
| GET | /taxa | {py:func}`.get_taxa` |
|
|
59
|
+
| GET | /taxa/{id} | {py:func}`.get_taxa_by_id` |
|
|
60
|
+
| GET | /taxa/{id}/map_layers | {py:func}`.get_taxa_map_layers` |
|
|
61
|
+
| GET | /taxa/autocomplete | {py:func}`.get_taxa_autocomplete` |
|
|
62
|
+
| GET | /taxa/lifelist_metadata | {py:func}`.get_lifelist_metadata` |
|
|
63
|
+
| GET | /users/{id} | {py:func}`.get_user_by_id` |
|
|
63
64
|
| GET | /users/{id}/projects |
|
|
64
|
-
| GET | /users/autocomplete | {py:func}`.get_users_autocomplete`
|
|
65
|
-
| GET | /users/me | {py:func}`.get_current_user`
|
|
65
|
+
| GET | /users/autocomplete | {py:func}`.get_users_autocomplete` |
|
|
66
|
+
| GET | /users/me | {py:func}`.get_current_user` |
|
|
66
67
|
|
|
67
68
|
## v0 API
|
|
68
69
|
For all available endpoints, see: <https://www.inaturalist.org/pages/api+reference>
|
|
69
70
|
|
|
70
|
-
| Method | Endpoint
|
|
71
|
-
| ------ |
|
|
72
|
-
| GET | /observations
|
|
73
|
-
| POST | /observations
|
|
74
|
-
| PUT | /observations/{id}
|
|
75
|
-
| DELETE | /observations/{id}
|
|
76
|
-
| GET | /observation_fields
|
|
77
|
-
| PUT | /observation_field_values/{id}
|
|
78
|
-
| POST | /observation_photos
|
|
79
|
-
| POST | /observation_sounds
|
|
71
|
+
| Method | Endpoint | Function |
|
|
72
|
+
| ------ | ------------------------------ | ------------------------------------------------------------ |
|
|
73
|
+
| GET | /observations | {py:func}`~pyinaturalist.v0.observations.get_observations` |
|
|
74
|
+
| POST | /observations | {py:func}`~pyinaturalist.v0.observations.create_observation` |
|
|
75
|
+
| PUT | /observations/{id} | {py:func}`~pyinaturalist.v0.observations.update_observation` |
|
|
76
|
+
| DELETE | /observations/{id} | {py:func}`~pyinaturalist.v0.observations.delete_observation` |
|
|
77
|
+
| GET | /observation_fields | {py:func}`.get_observation_fields` |
|
|
78
|
+
| PUT | /observation_field_values/{id} | {py:func}`.put_observation_field_values` |
|
|
79
|
+
| POST | /observation_photos | {py:func}`.upload_photos` |
|
|
80
|
+
| POST | /observation_sounds | {py:func}`.upload_sounds` |
|
|
@@ -32,13 +32,14 @@ See {ref}`contributing` for details on setup for local development.
|
|
|
32
32
|
:::{admonition} Python version compatibility
|
|
33
33
|
:class: toggle, tip
|
|
34
34
|
|
|
35
|
-
pyinaturalist currently requires **python 3.
|
|
35
|
+
pyinaturalist currently requires **python 3.7+**. If you need to use an older version
|
|
36
36
|
of python, here are the last compatible versions of pyinaturalist:
|
|
37
37
|
|
|
38
38
|
* **python 2.7:** pyinaturalist 0.1
|
|
39
39
|
* **python 3.4:** pyinaturalist 0.10
|
|
40
40
|
* **python 3.5:** pyinaturalist 0.11
|
|
41
|
-
* **python 3.6:**
|
|
41
|
+
* **python 3.6:** pyinaturalist 0.16
|
|
42
|
+
* **python 3.7:** still supported, but expected to be dropped in a future release
|
|
42
43
|
:::
|
|
43
44
|
|
|
44
45
|
## Imports
|
|
@@ -58,7 +59,6 @@ and [search URLs](https://forum.inaturalist.org/t/how-to-use-inaturalists-search
|
|
|
58
59
|
|
|
59
60
|
For example, if you wanted to search observations by user, these three requests are equivalent:
|
|
60
61
|
|
|
61
|
-
|
|
62
62
|
::::{tab-set}
|
|
63
63
|
:::{tab-item} search URL
|
|
64
64
|
```
|
|
@@ -111,12 +111,11 @@ And here is what that same observation looks like in JSON:
|
|
|
111
111
|
### Previewing Responses
|
|
112
112
|
These responses can contain large amounts of response attributes, making it somewhat cumbersome if you
|
|
113
113
|
just want to quickly preview results (for example, in a Jupyter notebook). For that purpose, the
|
|
114
|
-
{py:func}`~pyinaturalist.formatters.pprint` function is
|
|
114
|
+
{py:func}`~pyinaturalist.formatters.pprint` function is available to format response data as a
|
|
115
115
|
condensed, color-highlighted table.
|
|
116
116
|
|
|
117
117
|
**Examples:**
|
|
118
118
|
|
|
119
|
-
|
|
120
119
|
::::{tab-set}
|
|
121
120
|
:::{tab-item} Observations
|
|
122
121
|
```
|
|
@@ -182,7 +181,6 @@ To get all pages of results and combine them into a single response, use `page='
|
|
|
182
181
|
Note that this replaces the `get_all_*()` functions from pyinaturalist\<=0.12.
|
|
183
182
|
|
|
184
183
|
(auth)=
|
|
185
|
-
|
|
186
184
|
## Authentication
|
|
187
185
|
For any endpoints that create, update, or delete data, you will need to authenticate using an
|
|
188
186
|
OAuth2 access token. This requires both your iNaturalist username and password, and separate
|
|
@@ -491,7 +489,6 @@ $Env:DRY_RUN_ENABLED="true"
|
|
|
491
489
|
:::
|
|
492
490
|
::::
|
|
493
491
|
|
|
494
|
-
|
|
495
492
|
### Dry-run only write requests
|
|
496
493
|
If you would like to send real `GET` requests but mock out any requests that modify data
|
|
497
494
|
(`POST`, `PUT`, and `DELETE`), you can use the `DRY_RUN_WRITE_ONLY` variable instead:
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"cells": [
|
|
3
3
|
{
|
|
4
|
+
"attachments": {},
|
|
4
5
|
"cell_type": "markdown",
|
|
5
6
|
"id": "36ffdd0e",
|
|
6
7
|
"metadata": {},
|
|
@@ -36,14 +37,16 @@
|
|
|
36
37
|
]
|
|
37
38
|
},
|
|
38
39
|
{
|
|
40
|
+
"attachments": {},
|
|
39
41
|
"cell_type": "markdown",
|
|
40
42
|
"id": "3bd30a71",
|
|
41
43
|
"metadata": {},
|
|
42
44
|
"source": [
|
|
43
45
|
"## Basic taxon search\n",
|
|
44
|
-
"Let's say you partially remember either a genus or family name that started with **'vespi'**-something.\n",
|
|
45
46
|
"The [taxa endpoint](https://pyinaturalist.readthedocs.io/en/stable/modules/pyinaturalist.v1.taxa.html#pyinaturalist.v1.taxa.get_taxa)\n",
|
|
46
|
-
"can be used to search by name, rank, and several other criteria"
|
|
47
|
+
"can be used to search by name, rank, and several other criteria.\n",
|
|
48
|
+
"Let's say you partially remember either a genus or family name that started with **'vespi'**-something.\n",
|
|
49
|
+
"Use the `q` parameter to search by name:"
|
|
47
50
|
]
|
|
48
51
|
},
|
|
49
52
|
{
|
|
@@ -58,6 +61,7 @@
|
|
|
58
61
|
]
|
|
59
62
|
},
|
|
60
63
|
{
|
|
64
|
+
"attachments": {},
|
|
61
65
|
"cell_type": "markdown",
|
|
62
66
|
"id": "9dca3b13",
|
|
63
67
|
"metadata": {},
|
|
@@ -187,6 +191,7 @@
|
|
|
187
191
|
]
|
|
188
192
|
},
|
|
189
193
|
{
|
|
194
|
+
"attachments": {},
|
|
190
195
|
"cell_type": "markdown",
|
|
191
196
|
"id": "4020d25d",
|
|
192
197
|
"metadata": {},
|
|
@@ -238,13 +243,14 @@
|
|
|
238
243
|
]
|
|
239
244
|
},
|
|
240
245
|
{
|
|
246
|
+
"attachments": {},
|
|
241
247
|
"cell_type": "markdown",
|
|
242
248
|
"id": "b9767ea3",
|
|
243
249
|
"metadata": {},
|
|
244
250
|
"source": [
|
|
245
251
|
"## Searching by parent ID\n",
|
|
246
|
-
"Oh, that's right, it was **'Vespidae'**! Now let's find all of its subfamilies
|
|
247
|
-
"from the results above:"
|
|
252
|
+
"Oh, that's right, it was **'Vespidae'**! Now let's find all of its subfamilies.\n",
|
|
253
|
+
"We can run another search by parent ID, using the taxon ID from the results above:"
|
|
248
254
|
]
|
|
249
255
|
},
|
|
250
256
|
{
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env python
|
|
2
|
-
#
|
|
2
|
+
# ruff: noqa: E402, F401, F402, F403, F405
|
|
3
3
|
"""Sample response data of every type to experiment with"""
|
|
4
4
|
import sys
|
|
5
5
|
|
|
@@ -17,7 +17,7 @@ annotation = Annotation.from_json(j_annotation_1)
|
|
|
17
17
|
comment = Comment.from_json(j_comment_1)
|
|
18
18
|
controlled_term = ControlledTerm.from_json(j_controlled_term_1)
|
|
19
19
|
identification = Identification.from_json(j_identification_1)
|
|
20
|
-
life_list = LifeList.from_json(
|
|
20
|
+
life_list = LifeList.from_json(j_life_list_1)
|
|
21
21
|
observation = Observation.from_json(j_observation_1)
|
|
22
22
|
observation_with_ofvs = Observation.from_json(j_observation_3_ofvs)
|
|
23
23
|
observation_field = ObservationField.from_json(j_obs_field_1)
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
#
|
|
1
|
+
# ruff: noqa: F401, F403
|
|
2
2
|
# isort: skip_file
|
|
3
3
|
__version__ = '0.19.0'
|
|
4
4
|
|
|
5
5
|
from pyinaturalist.auth import get_access_token
|
|
6
6
|
from pyinaturalist.client import iNatClient
|
|
7
7
|
from pyinaturalist.constants import *
|
|
8
|
-
from pyinaturalist.formatters import enable_logging, format_table, pprint
|
|
8
|
+
from pyinaturalist.formatters import enable_logging, format_table, pprint, pprint_tree
|
|
9
9
|
from pyinaturalist.models import *
|
|
10
10
|
from pyinaturalist.paginator import Paginator, IDPaginator, WrapperPaginator
|
|
11
11
|
from pyinaturalist.request_params import get_interval_ranges
|
|
@@ -10,7 +10,7 @@ from requests import Session
|
|
|
10
10
|
from pyinaturalist.auth import get_access_token
|
|
11
11
|
from pyinaturalist.constants import RequestParams
|
|
12
12
|
from pyinaturalist.controllers import (
|
|
13
|
-
|
|
13
|
+
AnnotationController,
|
|
14
14
|
ObservationController,
|
|
15
15
|
PlaceController,
|
|
16
16
|
ProjectController,
|
|
@@ -93,7 +93,7 @@ class iNatClient:
|
|
|
93
93
|
tokens as needed. Using a keyring instead is recommended, though.
|
|
94
94
|
default_params: Default request parameters to pass to any applicable API requests
|
|
95
95
|
dry_run: Just log all requests instead of sending real requests
|
|
96
|
-
loop: An event loop to
|
|
96
|
+
loop: An event loop to run any executors used for async iteration
|
|
97
97
|
session: Session object to use instead of creating a new one
|
|
98
98
|
kwargs: Keyword arguments for :py:class:`.ClientSession`
|
|
99
99
|
"""
|
|
@@ -117,9 +117,7 @@ class iNatClient:
|
|
|
117
117
|
self._token_expires = None
|
|
118
118
|
|
|
119
119
|
# Controllers
|
|
120
|
-
self.
|
|
121
|
-
self
|
|
122
|
-
) #: Interface for controlled term/annotation requests
|
|
120
|
+
self.annotations = AnnotationController(self) #: Interface for annotation requests
|
|
123
121
|
self.observations = ObservationController(self) #: Interface for observation requests
|
|
124
122
|
self.places = PlaceController(self) #: Interface for project requests
|
|
125
123
|
self.projects = ProjectController(self) #: Interface for project requests
|
|
@@ -11,6 +11,7 @@ API_V0 = 'https://www.inaturalist.org'
|
|
|
11
11
|
API_V1 = 'https://api.inaturalist.org/v1'
|
|
12
12
|
API_V2 = 'https://api.inaturalist.org/v2'
|
|
13
13
|
EXPORT_URL = 'https://www.inaturalist.org/observations/export'
|
|
14
|
+
GBIF_TAXON_BASE_URL = 'https://www.gbif.org/species'
|
|
14
15
|
INAT_BASE_URL = API_V0
|
|
15
16
|
INAT_REPO = 'https://raw.githubusercontent.com/inaturalist/inaturalist/main'
|
|
16
17
|
ICONIC_TAXA_BASE_URL = f'{INAT_REPO}/app/assets/images/iconic_taxa'
|
|
@@ -103,6 +104,7 @@ ROOT_TAXON_ID = 48460
|
|
|
103
104
|
|
|
104
105
|
# Taxonomic ranks that can be filtered on, and numeric values for comparison
|
|
105
106
|
# Source: https://github.com/inaturalist/inaturalist/blob/main/app/models/taxon.rb
|
|
107
|
+
UNRANKED = 90 # Used for comparing unranked taxa
|
|
106
108
|
RANK_LEVELS = {
|
|
107
109
|
'infrahybrid': 5,
|
|
108
110
|
'form': 5,
|
|
@@ -138,18 +140,15 @@ RANK_LEVELS = {
|
|
|
138
140
|
'subphylum': 57,
|
|
139
141
|
'phylum': 60,
|
|
140
142
|
'kingdom': 70,
|
|
141
|
-
'unranked':
|
|
143
|
+
'unranked': UNRANKED,
|
|
142
144
|
'stateofmatter': 100,
|
|
143
145
|
}
|
|
144
146
|
RANKS = list(RANK_LEVELS.keys())[:-2]
|
|
145
147
|
|
|
146
|
-
#
|
|
148
|
+
# The main 7 taxonomic ranks, used for condensed display
|
|
147
149
|
COMMON_RANKS = [
|
|
148
|
-
'form',
|
|
149
|
-
'variety',
|
|
150
150
|
'species',
|
|
151
151
|
'genus',
|
|
152
|
-
'tribe',
|
|
153
152
|
'family',
|
|
154
153
|
'order',
|
|
155
154
|
'class',
|
{pyinaturalist-0.19.0.dev2 → pyinaturalist-0.19.0.dev3}/pyinaturalist/controllers/__init__.py
RENAMED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"""Controller classes for :py:class:`.iNatClient`"""
|
|
2
|
-
#
|
|
2
|
+
# ruff: noqa: F401
|
|
3
|
+
# isort: skip_file
|
|
3
4
|
from pyinaturalist.controllers.base_controller import BaseController
|
|
4
|
-
from pyinaturalist.controllers.
|
|
5
|
+
from pyinaturalist.controllers.annotation_controller import AnnotationController
|
|
5
6
|
from pyinaturalist.controllers.observation_controller import ObservationController
|
|
6
7
|
from pyinaturalist.controllers.place_controller import PlaceController
|
|
7
8
|
from pyinaturalist.controllers.project_controller import ProjectController
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
from typing import Dict, List
|
|
2
2
|
|
|
3
|
+
from pyinaturalist.constants import API_V2, IntOrStr
|
|
3
4
|
from pyinaturalist.controllers import BaseController
|
|
4
|
-
from pyinaturalist.docs import document_controller_params
|
|
5
|
+
from pyinaturalist.docs import document_common_args, document_controller_params
|
|
5
6
|
from pyinaturalist.models import Annotation, ControlledTerm
|
|
7
|
+
from pyinaturalist.session import delete, post
|
|
6
8
|
from pyinaturalist.v1 import get_controlled_terms, get_controlled_terms_for_taxon
|
|
7
9
|
|
|
8
10
|
|
|
9
|
-
class
|
|
11
|
+
class AnnotationController(BaseController):
|
|
10
12
|
""":fa:`tag` Controller for ControlledTerm and Annotation requests"""
|
|
11
13
|
|
|
12
14
|
def __init__(self, *args, **kwargs):
|
|
@@ -46,3 +48,51 @@ class ControlledTermController(BaseController):
|
|
|
46
48
|
annotation.controlled_attribute = term
|
|
47
49
|
annotation.controlled_value = term.get_value_by_id(annotation.controlled_value.id)
|
|
48
50
|
return annotations
|
|
51
|
+
|
|
52
|
+
# TODO: Allow passing labels instead of IDs
|
|
53
|
+
@document_common_args
|
|
54
|
+
def create(
|
|
55
|
+
self,
|
|
56
|
+
controlled_attribute_id: int,
|
|
57
|
+
controlled_value_id: int,
|
|
58
|
+
resource_id: IntOrStr,
|
|
59
|
+
resource_type: str = 'Observation',
|
|
60
|
+
**params,
|
|
61
|
+
) -> Annotation:
|
|
62
|
+
"""Create a new annotation on an observation.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
controlled_attribute_id: Annotation attribute ID
|
|
66
|
+
controlled_value_id: Annotation value ID
|
|
67
|
+
resource_id: Observation ID or UUID
|
|
68
|
+
resource_type: Resource type, if something other than an observation
|
|
69
|
+
|
|
70
|
+
Example:
|
|
71
|
+
|
|
72
|
+
Add a 'Plant phenology: Flowering' annotation to an observation:
|
|
73
|
+
|
|
74
|
+
>>> annotation = client.annotations.create(12, 13, 164609837)
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
The newly created Annotation object
|
|
78
|
+
"""
|
|
79
|
+
response = post(
|
|
80
|
+
f'{API_V2}/annotations',
|
|
81
|
+
controlled_attribute_id=controlled_attribute_id,
|
|
82
|
+
controlled_value_id=controlled_value_id,
|
|
83
|
+
resource_id=resource_id,
|
|
84
|
+
resource_type=resource_type,
|
|
85
|
+
**params,
|
|
86
|
+
)
|
|
87
|
+
return Annotation.from_json(response.json()['results'][0])
|
|
88
|
+
|
|
89
|
+
def delete(self, uuid: str, **params):
|
|
90
|
+
"""Delete an annotation
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
uuid: Annotation UUID
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
Nothing; success means the item has been deleted
|
|
97
|
+
"""
|
|
98
|
+
delete(f'{API_V2}/annotations/{uuid}', **params)
|
|
@@ -25,6 +25,7 @@ from pyinaturalist.request_params import validate_multiple_choice_param
|
|
|
25
25
|
from pyinaturalist.v1 import (
|
|
26
26
|
create_observation,
|
|
27
27
|
delete_observation,
|
|
28
|
+
get_life_list_metadata,
|
|
28
29
|
get_observation_histogram,
|
|
29
30
|
get_observation_identifiers,
|
|
30
31
|
get_observation_observers,
|
|
@@ -75,7 +76,7 @@ class ObservationController(BaseController):
|
|
|
75
76
|
_get_observations,
|
|
76
77
|
Observation,
|
|
77
78
|
cls=ObservationPaginator,
|
|
78
|
-
annotation_callback=self.client.
|
|
79
|
+
annotation_callback=self.client.annotations.lookup,
|
|
79
80
|
**params,
|
|
80
81
|
)
|
|
81
82
|
|
|
@@ -89,9 +90,27 @@ class ObservationController(BaseController):
|
|
|
89
90
|
response = self.client.request(get_observation_identifiers, **params)
|
|
90
91
|
return UserCounts.from_json(response)
|
|
91
92
|
|
|
92
|
-
@document_controller_params(get_observation_taxonomy
|
|
93
|
-
def life_list(
|
|
93
|
+
@document_controller_params(get_observation_taxonomy)
|
|
94
|
+
def life_list(
|
|
95
|
+
self, user_id: Optional[IntOrStr] = None, locale: Optional[str] = None, **params
|
|
96
|
+
) -> LifeList:
|
|
97
|
+
"""Get taxa from a user's dynamic life list
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
user_id: iNaturalist user ID or username
|
|
101
|
+
locale: Locale preference for taxon common names
|
|
102
|
+
"""
|
|
94
103
|
response = self.client.request(get_observation_taxonomy, user_id=user_id, **params)
|
|
104
|
+
|
|
105
|
+
# Add additional metadata to a life list response; requires a user ID
|
|
106
|
+
if user_id:
|
|
107
|
+
metadata = self.client.request(
|
|
108
|
+
get_life_list_metadata, user_id=user_id, locale=locale, **params
|
|
109
|
+
)
|
|
110
|
+
meta_by_id = {item['id']: item for item in metadata['results']}
|
|
111
|
+
for taxon in response['results']:
|
|
112
|
+
taxon.update(meta_by_id.get(taxon['id'], {}))
|
|
113
|
+
|
|
95
114
|
return LifeList.from_json(response)
|
|
96
115
|
|
|
97
116
|
@document_controller_params(get_observation_observers)
|