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é
A continued fork of Disco

Orca Orca is an extensive and extendable Python 3.x library for the Discord API. orca boasts the following major features: Expressive, functional inte

RPS 4 Apr 03, 2022
Asynchronous wrapper for wttr.in weather forecast.

aiopywttr Asynchronous wrapper for wttr.in weather forecast. Synchronous version here. Installation pip install aiopywttr Example This example prints

Almaz 4 Dec 24, 2022
A Open source Discord Token Grabber with several very useful features coded in python 3.9

Kiwee-Grabber A Open source Discord Token Grabber with several very useful features coded in python 3.9 This only works on any python 3.9 versions. re

Vesper 40 Jan 01, 2023
Small Python Tracker clone of Electra

Discord Bot Tracker - Python Simply Track your Bots (Status) to get notified when one of those go offline/online. Paste IDs into the config.py files,

Koni 2 Nov 23, 2021
⚡ PoC: Hide a c&c botnet in the discord client. (Proof Of Concept)

👨‍💻 Discord Self Bot 👨‍💻 A Discord Self-Bot in Python by natrix Installation Run: selfbot.bat Python: version : 3.8 Modules

0хVιcнy#1337 37 Oct 21, 2022
Discord bot that performs various functions.

rikka-bot A Discord bot that performs various functions. Table of Contents Commands Main Commands Utility Commands Admin Commands Self-Assignable Role

Carlos Saucedo 7 Aug 27, 2021
A community made discord bot coded in Python and running on AWS.

Pogbot Project Open Group Discord This is an open source community ran project. Join the discord for more information on how to participate. Coded in

Project Open Group 2 Jul 27, 2022
A simple, multipurpose Discord bot.

EpicBot 🏅 A simple, multipurpose Discord bot. • Info EpicBot is a multipurpose Discord bot that was designed to make your Discord life easier and coo

Nirlep_5252_ 130 Dec 29, 2022
Binance Futures Client

Binance Futures Client

4 Aug 02, 2022
An automated bot for twitter using Tweepy!

Tweeby An automated bot for twitter using Tweepy! About This bot will look for tweets that contain certain hashtags, if found. It'll send them a messa

Ori 1 Dec 06, 2021
Бот для скачивания треков с Deezer используя ISRC и UPC коды

deez_robot Запуск Установите необходимые библиотеки pip install -r requirements.txt Создайте файл config.py и поместите туда токен бота и ARL-токен De

Max 4 Jul 31, 2022
Generate visualizations of GitHub user and repository statistics using GitHubActions

GitHub Stats Visualization Generate visualizations of GitHub user and repository

Jun Shi 3 Dec 15, 2022
ThetaGang is an IBKR bot for collecting money

💬 Join the Matrix chat, we can get money together. Θ ThetaGang Θ Beat the capitalists at their own game with ThetaGang 📈 ThetaGang is an IBKR tradin

Brenden Matthews 1.5k Jan 08, 2023
light wrapper for indeed.com api

Simple wrapper for indeed api. go to indeed.com - register for api publisher token example from indeed import IndeedApi token = 'your token' api =

16 Sep 21, 2022
A discord bot that utilizes Google's Rest API for Calendar, Drive, and Sheets

Bott This is a discord bot that utilizes Google's Rest API for Calendar, Drive, and Sheets. The bot first takes the sheet from the schedule manager in

1 Dec 04, 2021
A python based all-in-one tool for Google Drive

gdrive-tools A python based all-in-one tool for Google Drive Uses For Gdrive-Tools ✓ generate SA ✓ Add the SA and Add them to TD automatically ✓ Gener

XcodersHub 32 Feb 09, 2022
A Python 2.7/3.x module for Amcrest Cameras using the SDK HTTP API.

A Python 2.7/3.x module for Amcrest Cameras using the SDK HTTP API. Amcrest and Dahua devices share similar firmwares. Dahua Cameras and NVRs also work with this module.

Marcelo Moreira de Mello 176 Dec 21, 2022
Github Workflows üzerinde Çalışan A101 Aktüel Telegam Bot

A101AktuelRobot Github Workflows üzerinde Çalışan A101 Aktüel Telegam Bot @A101AktuelRobot 💸 Bağış Yap ☕️ Kahve Ismarla 🌐 Telif Hakkı ve Lisans Copy

Ömer Faruk Sancak 10 Nov 02, 2022
A simple python oriented telegram bot to give out creative font style's

Font-Bot A simple python oriented telegram bot to give out creative font style's REQUIREMENTS tgcrypto pyrogram==1.2.9 Installation Fork this reposito

BL4CK H47 4 Jan 30, 2022
PRAW, an acronym for "Python Reddit API Wrapper", is a python package that allows for simple access to Reddit's API.

PRAW: The Python Reddit API Wrapper PRAW, an acronym for "Python Reddit API Wrapper", is a Python package that allows for simple access to Reddit's AP

Python Reddit API Wrapper Development 3k Dec 29, 2022