Python client for the iNaturalist APIs

Overview

pyinaturalist

Build Codecov Documentation

PyPI Conda PyPI - Python Versions

Run with Binder Open in VSCode


Introduction

iNaturalist is a community science platform that helps people get involved in the natural world by observing and identifying the living things around them. Collectively, the community produces a rich source of global biodiversity data that can be valuable to anyone from hobbyists to scientists.

pyinaturalist is an unofficial client for the iNaturalist API that aims to make these data easily accessible in the python programming language.

Features

  • Easier requests: Complete type annotations for request parameters, simplified create/update request formats, and easy pagination
  • Convenient responses: Type conversions to the things you would expect in python, and optional models for an object-oriented inteface to response data
  • Docs: Example requests, responses, scripts, and Jupyter notebooks to help get you started
  • Security: Keyring integration for secure credential storage
  • Server-friendly: Client-side rate-limiting that follows the API Recommended Practices, so you can be nice to the iNaturalist servers and not worry about rate-limiting errors
  • Test-friendly: A dry-run mode to preview your requests before potentially modifying data

Many of the most relevant API endpoints are supported, including:

  • annotations and observation fields
  • identifications
  • observations (multiple formats)
  • observation photos + sounds
  • observation observers, identifiers, histograms, life lists, and species counts
  • places
  • projects
  • species
  • users

Quickstart

Here are usage examples for some of the most commonly used features.

First, install with pip:

pip install pyinaturalist

Then, import the main API functions:

from pyinaturalist import *

Search observations

Let's start by searching for all your own observations. There are numerous fields you can search on, but we'll just use user_id for now:

>>> observations = get_observations(user_id='my_username')

The full response will be in JSON format, but we can just print out a few basic details:

>>> for obs in observations['results']:
>>>    pprint(obs)
[78242978] Species: Agelastica alni (Alder Leaf Beetle) observed by niconoe on 2021-05-10 18:45:38+01:00 at 1428 Braine-l'Alleud, Belgique
[78218860] Genus: Bradybatus observed by niconoe on 2021-05-10 15:22:49+01:00 at 1428 Braine-l'Alleud, Belgique
...

You can also get observation counts by species. On iNaturalist.org, this information can be found on the 'Species' tab of search results. For example, to get the counts of all your own research-grade observations:

>>> counts = get_observation_species_counts(user_id='my_username', quality_grade='research')
>>> pprint(counts, align=True)
[48473   ]: Species:          Ganoderma applanatum (Artist's bracket): 4
[50310   ]: Species:         Arisaema triphyllum (Jack-in-the-pulpit): 4
[50817   ]:   Genus:                     Auricularia (Wood ear fungi): 3
[81599   ]: Species:                 Silphium perfoliatum (Cup plant): 3
[120215  ]: Species:    Bombus griseocollis (Brown-belted Bumble Bee): 2
...

Another useful format is the observation histogram, which shows the number of observations over a given interval. The default is month_of_year:

>>> histogram = get_observation_histogram(user_id='my_username')
>>> print(histogram)
{
    1: 8,  # January
    2: 1,  # February
    3: 19, # March
    ...,   # etc.
}

Create and update observations

To create or modify observations, you will first need to log in. This requires creating an iNaturalist app, which will be used to get an access token.

token = get_access_token(
    username='my_username',
    password='my_password',
    app_id='my_app_id',
    app_secret='my_app_secret',
)

See Authentication for additional authentication options, including environment variables, keyrings, and password managers.

Now we can create a new observation:

from datetime import datetime

response = create_observation(
    taxon_id=54327,  # Vespa Crabro
    observed_on_string=datetime.now(),
    time_zone='Brussels',
    description='This is a free text comment for the observation',
    tag_list='wasp, Belgium',
    latitude=50.647143,
    longitude=4.360216,
    positional_accuracy=50,  # GPS accuracy in meters
    access_token=token,
    photos=['~/observations/wasp1.jpg', '~/observations/wasp2.jpg'],
)

# Save the new observation ID
new_observation_id = response[0]['id']

We can then update the observation information, photos, or sounds:

update_observation(
    17932425,
    access_token=token,
    description='updated description !',
    photos='~/observations/wasp_nest.jpg',
    sounds='~/observations/wasp_nest.mp3',
)

Search species

Let's say you partially remember either a genus or family name that started with 'vespi'-something. The taxa endpoint can be used to search by name, rank, and several other criteria

>>> response = get_taxa(q='vespi', rank=['genus', 'family'])

As with observations, there is a lot of information in the response, but we'll print just a few basic details:

>>> pprint(response)
[52747] Family: Vespidae (Hornets, Paper Wasps, Potter Wasps, and Allies)
[92786] Genus: Vespicula
[84737] Genus: Vespina
...

Next Steps

For more information, see:

  • User Guide: introduction and general features that apply to most endpoints
  • Endpoint Summary: a complete list of endpoints wrapped by pyinaturalist
  • Examples: data visualizations and other examples of things to do with iNaturalist data
  • Reference: Detailed API documentation
  • Contributing Guide: development details for anyone interested in contributing to pyinaturalist
  • History: details on past and current releases
  • Issues: planned & proposed features

Feedback

If you have any problems, suggestions, or questions about pyinaturalist, please let us know! Just create an issue. Also, PRs are welcome!

Note: pyinaturalist is developed by members of the iNaturalist community, and is not endorsed by iNaturalist.org or the California Academy of Sciences. If you have non-python-specific questions about iNaturalist, the iNaturalist Community Forum is the best place to start.

Related Projects

Other python projects related to iNaturalist:

Comments
  • Convert observation JSON to Darwin Core format

    Convert observation JSON to Darwin Core format

    First of all: congratulations and thanks for this amazing API! Not sure if what I want makes sense but and I am contacting here but I don't think is the case o a feature request... Any way:

    Is your feature request related to a problem? Please describe. I would like to download observations related to a project (get_observations(project_id=XXXX) from node_api) but I am a bit lost on mapping the results on DWC fields. I have saw that using rest_api is is possible to use request_format='dwc', but it is not possible to use project_id parameter.

    Describe the solution you'd like Doesn't need to be a implementation, or a enhancement in the API. I am just wondering if there is any material with field matching between the get_observetions's results from node_api and DWC. Or any suggestion in this way.

    Thanks in advance felipe

    enhancement question 
    opened by FelipeSBarros 22
  • Add a project logo

    Add a project logo

    I think the docs would look a little nicer if we had a project logo. Of course this isn't a necessity, but I think it would be fun.

    Python logo usage

    I believe this is acceptable use of the python logo according to the Python Software Foundation's guidelines and trademark usage policy: specifically, it doesn't modify the shape of the logo, and isn't misleadingly applied to something that's not the python language. The guidelines do specifically say that modified colors ("derived logos") are allowed, and:

    Use of derived logos for user groups and conferences... and freely distributed 3rd-party modules or tools -- Allowed if for the Python programming language.

    iNaturalist logo usage

    I believe this is also acceptable use of the iNat logo (from the press kit). From the FAQ:

    Can I use the iNaturalist logo when linking to iNaturalist? Yes, with the caveat that its use in context should not imply endorsement by iNaturalist, the California Academy of Sciences, or National Geographic, and sale of items with the iNaturalist logo is not permitted. In general, if you're linking to iNaturalist because you're encouraging people to contribute to a project, are writing more generally about iNaturalist, or otherwise directing people to iNaturalist (e.g. via a flyer encouraging people to download the app and post while they visit a park), you can include the logo.

    I'm fairly certain pyinaturalist meets these criteria. I would like to get confirmation from a staff member just to be sure, though. I also added a note to the Readme to clarify that this isn't an official project endorsed by iNaturalist.org. I don't think that would be a point of confusion, but you never know!

    Ideas

    ~~Here are a few initial attempts:~~

    Edit: Based on feeback from Cal Academy Legal, these aren't usable.

    docs 
    opened by JWCook 20
  • Add GET /observations/observers endpoint from v1 API

    Add GET /observations/observers endpoint from v1 API

    Add the /observations/observers endpoint from Node API.

    My selfish motivation behind this: I'd like to be able to ask questions related to user engagement in a project, for instance "how many users have made 10+ observations in project X?," and this endpoint seems to be the place to do it.

    It seems pretty straightforward and could be coupled with adding the /observations/identifiers endpoint as well.

    • [x] /observations/observers
    • [x] /observations/identifiers
    • [x] Doctrings + type annotation
    • [x] Usage examples
    • [x] Sample response data
    • [x] Unit tests

    If you're ok with this, I'll start working on it over the next few weeks.

    new endpoint 
    opened by willkuhn 20
  • Add sound file upload

    Add sound file upload

    Is your feature request related to a problem? Please describe. I'd like to add sound files to observations, in the same way that is supported for photos

    Describe the solution you'd like An analogue of add_photo_to_observation

    enhancement new endpoint 
    opened by AugustT 18
  • Add basic structure for API client class

    Add basic structure for API client class

    The data models (#145) are mostly complete. The next step is to add support for API requests that return model objects instead of JSON. For backwards-compatibility, this should be an optional feature, not a replacement for the existing API functions.

    Update: Decided to go with a compromise between options 2 and 3, described in comments below. This will involve an API client class and one controller class per resource type.

    Options

    There are at least two ways to go about this:

    Option 1: Add a keyword arg to existing functions to specify return format

    Example:

    observations = get_observations(user_id='my_username', format='model')
    

    Pros:

    • This could work nicely with other possible return formats, if we add optional integration with pyinaturalist-convert later on. format could be used to specify any other supported format, for example format='csv'.
    • No new functions for users to learn

    Cons:

    • Adding multiple return types for the same function generally isn't good practice
      • For other readers of client code that uses these functions, it can take a bit longer to understand what's going on
      • A long Union[x, y, z] isn't very useful as a return type annotation

    Option 2: Add wrapper @classmethods to model objects

    Example:

    observations = Observation.search(user_id='my_username')
    

    Pros:

    • Results in more readable client code
    • Makes a more obvious separation between the "low-level" API (raw JSON) and "high-level" API (model objects)

    Cons:

    • Mixes data with logic
      • It can be nice to keep those separate (as in MVC patterns), but not totally necessary
    • Requires addling slightly more code to implement
      • This can be mitigated somewhat by using forge to reuse existing function signatures & docstrings

    Examples in other API clients:

    • Service resources in boto3, and other service-specific interfaces like S3.Bucket
    enhancement 
    opened by JWCook 15
  • TypeError when using local_photos parameter in create_observation(): Object of type BytesIO is not JSON serializable

    TypeError when using local_photos parameter in create_observation(): Object of type BytesIO is not JSON serializable

    Hi folks. I've been playing with pyinaturalist with the intention of using it to streamline the upload of a database of observation records and associated photographs.

    However, I've run into a problem. The following works brilliantly:

    response = create_observation(
        species_guess='Mallard',
        observed_on_string='2020-05-03',
        time_zone='Brussels',
        description='Test observation, will be deleted shortly',
        tag_list='test, API',
        latitude=-53.186881, 
        longitude=-134.823015,
        positional_accuracy=50, # GPS accuracy in meters
        access_token=token,
    )
    
    new_observation_id = response[0]['id']
    
    add_photo_to_observation(
        new_observation_id,
        access_token=token,
        photo='H:\My Documents\iNaturalist\inaturalistTest3.jpg',
    )
    

    However, when I try to combine it all into a single step using the local_photos parameter I get an error:

    response = create_observation(
        species_guess='Mallard',
        observed_on_string='2020-05-03',
        time_zone='Brussels',
        description='Test observation, will be deleted shortly',
        tag_list='test, API',
        latitude=-53.186881, 
        longitude=-134.823015,
        positional_accuracy=50, # GPS accuracy in meters
        access_token=token,
        local_photos='H:\My Documents\iNaturalist\inaturalistTest3.jpg',
    )
    
    TypeError: Object of type BytesIO is not JSON serializable
    

    Unfortunately, I'm not yet competent enough with python to know whether this is a problem on my end, or if it's an issue deeper in the package. In either case, your advice and guidance would be much appreciated.

    bug 
    opened by sdjbrown 15
  • observed_on_string not working

    observed_on_string not working

    Describe the bug I'm using observed_on_string but the value entered does not appear on the record once uploaded

    To Reproduce

    # Getting started
    install.packages('reticulate')
    library(reticulate)
    
    # This will tell you where your python is
    # If you dont have python you will need to install it
    Sys.which("python") 
    
    # Install the iNat python package https://pypi.org/project/pyinaturalist/
    py_install("pyinaturalist==0.14.0dev356", pip = TRUE)
    
    # Create an app on iNat here: https://www.inaturalist.org/oauth/applications/new
    # save out id and secret to an object and dont share with others
    load('token.rdata')
    
    # Start using the package
    pynat <- import('pyinaturalist')
    
    # get token
    token <- pynat$get_access_token(token[[1]],
                                    token[[2]],
                                    token[[3]],
                                    token[[4]])
    
    # Submit an observation
    response <- pynat$create_observation(
      species_guess = 'daubentons bat',
      observed_on_string = '2021-05-02',
      description='This is a bat auto upload',
      latitude = 51.599840854449226, 
      longitude = -1.130838820690541,
      positional_accuracy = 23, # GPS accuracy in meters
      access_token = token
    )
    
    bug 
    opened by AugustT 14
  • Feature request: Possibility to fetch observations with obscured coordinates

    Feature request: Possibility to fetch observations with obscured coordinates

    Feature description

    In some case observation can have obscured coordinates (for ex. when the species is endangered). It would be nice to still be able to fetch all remaining information except the precise geolocation, without authenticating.

    Use case

    I need to fetch all observation from a project but I can't because some have their geolocation obscured by iNaturalist. Only "The person who made the observation, Individuals who the observer has trusted with their hidden coordinates and Curators of the projects" can fetch it.

    Workarounds

    • Logging at iNaturalist and use the https://www.inaturalist.org/observations/export functions.
    • Authenticating https://pyinaturalist.readthedocs.io/en/stable/user_guide.html#authentication (didn't try at the moment because I didn't fulfil the requirements to build an app see screenshot)
    image enhancement 
    opened by oolonek 12
  • How to get projects information?

    How to get projects information?

    Hello,

    Thank you for the work done, is really useful. I would like to know how can I get all the projects information, Is it possible?

    Thank you in advance, Miriam

    question 
    opened by mcalvera 11
  • need help with get_access_token() parameters and inaturalist application urls

    need help with get_access_token() parameters and inaturalist application urls

    Is your feature request related to a problem? Please describe. I have succesfully installed the package. I have tested some of the examples, like get_observations() (which worked perfectly)

    But I want to upload my observations and I couldn't make authentication work:

    # this worked perfectly:
    observations = get_observations(user_id='myuserid')
    for obs in observations['results']:
        print(format_observations(obs))
    
    # this was filled in with real values, but didn't work:
    token = get_access_token(
        username='my_username',
        password='my_password',
        app_id='my_app_id',
        app_secret='my_app_secret',
    )
    

    I don't post the rest of code because I already got an error here:

    Traceback (most recent call last):
      File "pyinat.py", line 25, in <module>
        token = get_access_token(
      File "C:\...\Python38\lib\site-packages\pyinaturalist\auth.py", line 80, in get_access_token
        response.raise_for_status()
      File "C:\...\Python38\lib\site-packages\requests\models.py", line 943, in raise_for_status
        raise HTTPError(http_error_msg, response=self)
    requests.exceptions.HTTPError: 401 Client Error: Unauthorized for url: https://www.inaturalist.org/oauth/token
    

    Describe the solution you'd like I would like to have bit more explained example of the first two get_access_token() parameters:

    • Is 'username' the email used to login inaturalist website? (i.e. '[email protected]') Or is it, like in get_observations(user_id), the user shown in the inaturalist user page url? (i.e. 'niconoe'). I tried both, but no luck.
    • Is 'password' the one used for inaturalist web login? (it looks odd to me providing it to an application, but I did it)

    I would also like to have some hints about how to create the inaturalist application required to login using pyinaturalist:

    • When creating the inaturalist application, do we actually need to have a real web server Callback url, or is it something optional just in case we want to control our application usage? Or perhaps we have to fill in pyinaturalist github url here?
    • Some question for the Url outside inaturalist field. Is this just optional?

    Describe alternatives you've considered I wonder if it takes a while for the app to be aproved by inaturalist. But I don't think that's the problem because the interface says nothing about that

    Thanks a lot in advance

    question docs 
    opened by abubelinha 9
  • Add webhook for GitKraken Boards

    Add webhook for GitKraken Boards

    Hey @niconoe, one more thing I forgot to ask about: could you add a webhook to this repo for me so I can sync issues with GitKraken Boards? It should just take a couple minutes to set up.

    Now that I have a larger number of small projects, I wanted to be able to see all my issues in one place. GitHub Projects can do this, but requires transferring repos to a single owner or organization. It looks like GitKraken Boards can do this by just adding an OAuth application and webhooks.

    Steps

    1. Make an account and give it access to the pyinaturalist repo.

    2. Go to 'Create a synced board' in the lower left and add pyinaturalist: gk1 gk2

    3. Go to ⚙️-> Users in the upper right and add me to the board: gk3 gk4

    Back on the GitHub repo, you should then see at least one webhook for GitKraken under Settings -> Webhooks. You can remove those if you ever need to revoke access for some reason in he future. image

    Also let me know if you have any alternative suggestions for a free Kanban-style board that can sync with GitHub issues and PRs. Thanks!

    logistics 
    opened by JWCook 9
  • Bump rich from 12.6.0 to 13.0.0

    Bump rich from 12.6.0 to 13.0.0

    Bumps rich from 12.6.0 to 13.0.0.

    Release notes

    Sourced from rich's releases.

    Dropped Python3.6 support

    Some relatively minor fixes and improvements. The most significant update (and the reason for the major version bump) is that Rich has dropped Python3.6 support.

    If you are a Python3.6 user and can't upgrade for whatever reason, pin to version 12.6.0.

    [13.0.0] - 2022-12-30

    Fixed

    • Reversed pre and code tags in base HTML format Textualize/rich#2642
    • Improved detection of attrs library, that isn't confused by the presence of the attr library.
    • Fixed issue with locals_max_length parameter not being respected in Traceback Textualize/rich#2649
    • Handling of broken fileno made more robust. Fixes Textualize/rich#2645
    • Fixed missing fileno on FileProxy

    Changed

    • Bumped minimum Python version to 3.7 Textualize/rich#2567
    • Pretty-printing of "tagged" __repr__ results is now greedy when matching tags Textualize/rich#2565
    • progress.track now supports deriving total from __length_hint__

    Added

    Changelog

    Sourced from rich's changelog.

    [13.0.0] - 2022-12-30

    Fixed

    • Reversed pre and code tags in base HTML format Textualize/rich#2642
    • Improved detection of attrs library, that isn't confused by the presence of the attr library.
    • Fixed issue with locals_max_length parameter not being respected in Traceback Textualize/rich#2649
    • Handling of broken fileno made more robust. Fixes Textualize/rich#2645
    • Fixed missing fileno on FileProxy

    Changed

    • Bumped minimum Python version to 3.7 Textualize/rich#2567
    • Pretty-printing of "tagged" __repr__ results is now greedy when matching tags Textualize/rich#2565
    • progress.track now supports deriving total from __length_hint__

    Added

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies python 
    opened by dependabot[bot] 1
  • Bump pre-commit from 2.20.0 to 2.21.0

    Bump pre-commit from 2.20.0 to 2.21.0

    Bumps pre-commit from 2.20.0 to 2.21.0.

    Release notes

    Sourced from pre-commit's releases.

    pre-commit v2.21.0

    Features

    Fixes

    Changelog

    Sourced from pre-commit's changelog.

    2.21.0 - 2022-12-25

    Features

    Fixes

    Commits
    • 40c5bda v2.21.0
    • bb27ea3 Merge pull request #2642 from rkm/fix/dotnet-nuget-config
    • c38e0c7 dotnet: ignore nuget source during tool install
    • bce513f Merge pull request #2641 from rkm/fix/dotnet-tool-prefix
    • e904628 fix dotnet hooks with prefixes
    • d7b8b12 Merge pull request #2646 from pre-commit/pre-commit-ci-update-config
    • 94b6178 [pre-commit.ci] pre-commit autoupdate
    • b474a83 Merge pull request #2643 from pre-commit/pre-commit-ci-update-config
    • a179808 [pre-commit.ci] pre-commit autoupdate
    • 3aa6206 Merge pull request #2605 from lorenzwalthert/r/fix-exe
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies python 
    opened by dependabot[bot] 1
  • Bump keyring from 23.11.0 to 23.13.1

    Bump keyring from 23.11.0 to 23.13.1

    Bumps keyring from 23.11.0 to 23.13.1.

    Changelog

    Sourced from keyring's changelog.

    v23.13.1

    • #573: Fixed failure in macOS backend when attempting to set a password after previously setting a blank password, including a test applying to all backends.

    v23.13.0

    • #608: Added support for tab completion on the keyring command if the completion extra is installed (keyring[completion]).

    v23.12.1

    • #612: Prevent installation of pywin32-ctypes 0.1.2 with broken use2to3 directive.

    v23.12.0

    • #607: Removed PSF license as it was unused and confusing. Project remains MIT licensed as always.
    Commits
    • 372001b Update changelog. Ref #573.
    • aa2a9bd Delete the password even if blank. Fixes #573.
    • 22bcc9a Add test capturing failed expectation. Ref #573.
    • 1d76158 Merge pull request #611 from Freed-Wu/main
    • a588e65 Update changelog
    • dd7888a Update README to use imperative voice. Add consideration about macOS Homebrew...
    • ded09d9 Move zsh to its own file and load it using importlib resources.
    • 3d1129f Move all completion logic into a completion module.
    • 40af6de Fix #608
    • 5a263f3 Declare choices using choices keyword. Ref #611.
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies python 
    opened by dependabot[bot] 1
  • Bump furo from 2022.9.29 to 2022.12.7

    Bump furo from 2022.9.29 to 2022.12.7

    Bumps furo from 2022.9.29 to 2022.12.7.

    Changelog

    Sourced from furo's changelog.

    Changelog

    2022.12.07 -- Reverent Raspberry

    • ✨ Add support for Sphinx 6.
    • ✨ Improve footnote presentation with docutils 0.18+.
    • Drop support for Sphinx 4.
    • Improve documentation about what the edit button does.
    • Improve handling of empty-flexboxes for better print experience on Chrome.
    • Improve styling for inline signatures.
    • Replace the meta generator tag with a comment.
    • Tweak labels with icons to prevent users selecting icons as text on touch.

    2022.09.29 -- Quaint Quartz

    • Add ability to set arbitrary URLs for edit button.
    • Add support for aligning text in MyST-parser generated tables.

    2022.09.15 -- Pragmatic Pistachio

    • Add a minimum version constraint on pygments.
    • Add an explicit dependency on sass.
    • Change right sidebar title from "Contents" to "On this page".
    • Correctly position sidebars on small screens.
    • Correctly select only Furo's own svg in related pages nav.
    • Make numpy-style documentation headers consistent.
    • Retitle the reference section.
    • Update npm dependencies.

    2022.06.21 -- Opulent Opal

    • Fix docutils <= 0.17.x compatibility.
    • Bump to the latest Node.js LTS.

    2022.06.04.1 -- Naughty Nickel bugfix

    • Fix the URL used in the "Edit this page" for Read the Docs builds.

    2022.06.04 -- Naughty Nickel

    ... (truncated)

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies python 
    opened by dependabot[bot] 1
  • Reloading full record does not pass all_names parameter

    Reloading full record does not pass all_names parameter

    The problem

    When a taxon is reloaded to fetch its full record, if all names were originally requested, they won't be included on the taxon object after the reload.

    Expected behavior

    If I fetch a taxon via client.taxa.autocomplete() and then reload it with taxon.load_full_record(), I expect all_names=True passed on the original autocomplete request to be applied to the load_full_record request, and consequently taxon.names should contain all names, as requested. Instead, taxon.names is empty.

    Steps to reproduce the behavior

    >>> client = iNatClient()
    >>> taxon = client.taxa.autocomplete(q='Picoides pubescens', all_names=True).one()
    >>> taxon.names
    [
        {'is_valid': True, 'name': 'Dryobates pubescens', 'position': 0, 'locale': 'sci'},
        {'is_valid': True, 'name': 'Downy Woodpecker', 'position': 0, 'locale': 'en'},
        {'is_valid': True, 'name': 'Dunspett', 'position': 1, 'locale': 'sv'},
        {'is_valid': True, 'name': 'Donsspecht', 'position': 2, 'locale': 'nl'},
        {'is_valid': True, 'name': 'Dværgflagspætte', 'position': 3, 'locale': 'da'},
        {'is_valid': True, 'name': 'DOWO', 'position': 4, 'locale': 'und'},
        {'is_valid': True, 'name': 'Пушистый дятел', 'position': 8, 'locale': 'ru'},
        {'is_valid': True, 'name': 'Pica-pau-felpudo', 'position': 9, 'locale': 'pt'},
        {'is_valid': True, 'name': 'Carpintero velloso-menor', 'position': 12, 'locale': 'es'},
        {'is_valid': True, 'name': 'pic mineur', 'position': 13, 'locale': 'fr'},
        {'is_valid': True, 'name': 'Carpintero Albinegro Menor', 'position': 14, 'locale': 'es'},
        {'is_valid': True, 'name': 'Dunenspecht', 'position': 15, 'locale': 'de'},
        {'is_valid': True, 'name': 'keijutikka', 'position': 16, 'locale': 'fi'},
        {'is_valid': True, 'name': 'strakapoud osikový', 'position': 17, 'locale': 'cs'},
        {'is_valid': True, 'name': 'セジロコゲラ', 'position': 17, 'locale': 'ja'},
        {'is_valid': True, 'name': 'ďateľ ozdobný', 'position': 19, 'locale': 'sk'},
        {'is_valid': True, 'name': 'picchio lanuginoso', 'position': 20, 'locale': 'it'},
        {'is_valid': True, 'name': '绒啄木鸟', 'position': 21, 'locale': 'zh-CN'},
        {'is_valid': True, 'name': 'Dzięcioł kosmaty', 'position': 22, 'locale': 'pl'},
        {'is_valid': True, 'name': '絨啄木鳥', 'position': 23, 'locale': 'zh'},
        {'is_valid': True, 'name': 'Dunspett', 'position': 24, 'locale': 'nb'},
        {'is_valid': True, 'name': 'Дятел пухнастий', 'position': 25, 'locale': 'uk'},
        {'is_valid': False, 'name': 'Picoides pubescens', 'position': 5, 'locale': 'sci'},
        {'is_valid': False, 'name': 'Dendrocopos pubescens', 'position': 6, 'locale': 'sci'},
        {'is_valid': False, 'name': 'Dendrocopus pubescens', 'position': 7, 'locale': 'sci'},
        {'is_valid': False, 'name': 'Baapaase', 'position': 18, 'locale': 'oj'}
    ]
    >>> taxon.load_full_record()
    >>> taxon.names
    []
    >>> 
    

    Workarounds

    Either of these will do:

    1. Save the taxon.names before doing the taxon.load_full_record()

    OR

    1. Don't use taxon.load_full_record(). Instead, perform a client.taxa(taxon.id, all_names=True) to fetch the record with all names (my current workaround, but then I need to separately save anything from the original request that I need later, like taxon.matched_term).

    Environment

    • OS & version: Debian 10
    • Python version: 3.9
    • Pyinaturalist version or branch: main branch
    bug 
    opened by synrg 3
  • ConservationStatus model complete code to name mapping

    ConservationStatus model complete code to name mapping

    Feature description

    Please provide the same conservation status code to status name mapping in the ConservationStatus model for the full taxon record as iNaturalist itself provides in other endpoints (e.g. autocomplete & observations).

    Use case

    The use case is to show a taxon's local conservation status using the same name that a user is familiar with when they have specified their preferred place. For background, see this discussion on the iNaturalist forums: https://forum.inaturalist.org/t/establishment-means-in-two-v1-taxa-endpoints-either-not-complete-or-not-consistent/15099

    In that discussion, Kenichi suggested I should map the iucn code using a local table on the client side. For background (since the link to github that he gave no longer works), please see the inaturalist code here (this time using stable URLs):

    First, the iucn code to name mapping:

    https://github.com/inaturalist/inaturalist/blob/77f6bac2b25c1bf431395e5142bf8580722ecaf8/app/models/taxon.rb#L349-L389

    And then the authority-specific mappings:

    https://github.com/inaturalist/inaturalist/blob/039de2bc5fe2b5e6aefba0a5f057218f64199c24/app/models/conservation_status.rb#L42-L105

    So, for example, suppose a user's preferred place is Nova Scotia and the taxon they would like to look up is Cathartes aura (Turkey Vulture). To fully comprehend its status, they should be presented with the status name, the code, the place name for the status, and a link to the listed taxa record on the web where they can learn more:

    image

    Most of this info can be obtained from the full taxon record with client.taxa(4756, preferred_place_id=6853), but not the status name itself. If the ConservationStatus model provided this mapping via a local table lookup as Kenichi suggested, then the user would not have to worry about which API call the model was created from, or have to do a wasteful extra API call to obtain it.

    Workarounds

    Lookup the taxon using the /v1/taxa/autocomplete endpoint which sets the taxon.conservation_status.status_name to the expected value. For example, https://api.inaturalist.org/v1/taxa/autocomplete?q=turkey+vulture&preferred_place_id=6853 returns status_name: "imperiled".

    Note: if taxon.load_full_record() is called after this, the status_name is not returned, i.e. it will "walk" on the value that we just had before the call. I was originally going to ask for a workaround in pyinat wherein this field value is kept, but that's not a complete solution, and using a code-to-name mapping in the client seems better.

    enhancement 
    opened by synrg 1
Releases(v0.17.0)
Owner
Nicolas Noé
Nicolas Noé
Python linting made easy. Also a casual yet honorific way to address individuals who have entered an organization prior to you.

pysen What is pysen? pysen aims to provide a unified platform to configure and run day-to-day development tools. We envision the following scenarios i

Preferred Networks, Inc. 452 Jan 05, 2023
An enhanced discord.py, based off of the now-archived discord.py project

enhanced-discord.py A modern, maintained, easy to use, feature-rich, and async ready API wrapper for Discord written in Python. The Future of enhanced

Devision 2 Dec 21, 2022
HASOKI DDOS TOOL- powerful DDoS toolkit for penetration tests

DDoS Attack Panel includes CloudFlare Bypass (UAM, CAPTCHA, GS ,VS ,BFM, etc..) This is open source code. I am not responsible if you use it for malic

Rebyc 1 Dec 02, 2022
A bot that updates about the most subscribed artist' channels on YouTube

A bot that updates about the most subscribed artist' channels on YouTube. A weekly top chart report is provided every Monday. It posts updates on Twitter

Marco Fantauzzo 5 Dec 14, 2022
A bot which provides online/offline and player status for Thicc SMP, using Replit.

AlynaaStatus A bot which provides online/offline and player status for Thicc SMP. Currently being hosted on Replit. How to use? Create a repl on Repli

QuanTrieuPCYT 8 Dec 15, 2022
Disctopia-c2 - Windows Backdoor that is controlled through Discord

Disctopia Disctopia Command and Control What is Disctopia? Disctopia is an open

Dimitris Kalopisis 218 Dec 26, 2022
An API which returns random AOT quote everytime it's invoked

An API which returns random AOT quote everytime it's invoked

Nishant Sapkota 1 Feb 07, 2022
Tiktok BOT 1 link Vidio otomatis : - Nambah view - Nambah love - Nambah share - Nambah love komen (semua komen ke love)

Install Bahannya pip install selenium pip install pyfiglet==0.7.5 Cara Install dan Menjalankannya Git-clone this repo! Install selenium and pyfiglet u

Ahmad Ghozali 1 Mar 01, 2022
Utility for downloading fanfiction in bulk from the Archive of Our Own

What is this? This is a program intended to help you download fanfiction from the Archive of Our Own in bulk. This program is primarily intended to wo

73 Dec 30, 2022
WallAlley.bot is an open source and free to use financial discord bot originaly build for WallAlley server's community

WallAlley.bot About WallAlley.bot is an open source and free to use financial discord bot originaly build for WallAlley server's community. All data a

Mohammad KHADDAN 1 Jan 22, 2022
A wrapper for The Movie Database API v3 and v4 that only uses the read access token (not api key).

fulltmdb A wrapper for The Movie Database API v3 and v4 that only uses the read access token (not api key). Installation Use the package manager pip t

Jacob Hale 2 Sep 26, 2021
A python crypto trading bot on Binance using RSI in 25 Lines 🚀

RSI Crypto Trading Bot - Binance A Crypto Trading Bot on Binance trading BTCUSDT and ETHUSDT using RSI in 25 Lines of Code Getting Started Note Python

Blankly Finance 10 Dec 26, 2022
A python discord client interaction emulator for the DC29 badge code channel

dc29-discord-signalbot A python discord client interaction emulator for the DC29 badge code channel Prep Open Developer mode Open the developer mode f

8 Aug 23, 2021
Terraform Cloud CLI for Managing Workspace Terraform Versions

Terraform Cloud Version Manager This tiny script makes it easy to update the Terraform Version on all of the Workspaces inside Terraform Cloud. It wil

Robert Hafner 1 Jan 07, 2022
ETL for tononkira.serasera.org

python-tononkiramalagasy-api Api Endpoints: ### get artists - /artists/int:page [page_offset = 20] ### get artist's songs, index was given by

Titosy Manankasina 1 Dec 24, 2021
Command-line program to download videos from YouTube.com and other video sites

youtube-dl - download videos from youtube.com or other video platforms INSTALLATION DESCRIPTION OPTIONS CONFIGURATION OUTPUT TEMPLATE FORMAT SELECTION

youtube-dl 116.4k Jan 07, 2023
IACR Events Scraper

IACR Events Scraper This scrapes https://iacr.org/events/ and exports it as a calendar file. I host a version of this for myself under https://arrrr.c

Karolin Varner 6 May 28, 2022
🚀 A fast, flexible and lightweight Discord API wrapper for Python.

Krema A fast, flexible and lightweight Discord API wrapper for Python. Installation Unikorn unikorn add kremayard krema -no-confirmation Pip pip insta

Krema 20 Sep 04, 2022
Python wrapper for Gmailnator

Python wrapper for Gmailnator

h0nda 11 Mar 19, 2022
Monetize your apps with KivAds using Google AdMob api.

KivAds(WIP) Monetize your apps with KivAds using Google AdMob api. KivAds uses the latest version of Google AdMob sdk(version 20.0.0). KivAds exposes

Guhan Sensam 16 Nov 05, 2022