Skip to main content

A client for the iMetos FieldClimate API.

Project description

python-fieldclimate

A client for the iMetos FieldClimate API: https://api.fieldclimate.com/v1/docs/

To use this, you’ll need HMAC credentials provided by iMetos. See their docs for more info.

Requires Python 3.6. Uses aiohttp and pycryptodome.

Installation

Use pip to install directly from PyPI:

pip install python-fieldclimate

Authentication

HMAC credentials can be provided in three ways:

  1. Via the init constructor:

    >>> FieldClimateClient(public_key='YOUR', private_key='KEYS')
    
  2. Environment variables FIELDCLIMATE_PUBLIC_KEY and FIELDCLIMATE_PRIVATE_KEY (You can override these variable names too).

  3. Subclassing FieldClimateClient:

    >>> class MyClient(FieldClimateClient):
    ...     private_key = 'YOUR'
    ...     public_key = 'KEYS'
    

Synchronous Usage

The same FieldClimateClient class can be used to make synchronous and asynchronous requests. Synchronous code is easier to read, but Python spends more time waiting around when running it.

This code ran in 12.9 seconds:

>>> from fieldclimate import FieldClimateClient
>>>
>>> def main():
...     client = FieldClimateClient()
...     print(client.get_user())
...     stations = client.get_user_stations()
...     print(len(stations))
...     for station in stations[:10]:
...         print(client.get_data_range(station))
...
>>> main()
{'username': '...', }
1337
{'min_date': '2016-04-27 12:33:37', 'max_date': '2018-10-23 16:00:08'}
{'min_date': '2016-05-05 10:00:13', 'max_date': '2018-10-09 23:00:04'}
{'min_date': '2016-04-27 12:54:09', 'max_date': '2018-09-18 12:14:50'}
{'min_date': '2016-04-27 12:43:29', 'max_date': '2018-09-23 11:00:03'}
{'min_date': '2016-03-24 01:16:40', 'max_date': '2018-10-23 15:55:09'}
{'min_date': '2016-04-27 11:52:15', 'max_date': '2018-10-19 15:00:08'}
{'min_date': '2016-04-28 04:02:11', 'max_date': '2018-10-23 16:00:08'}
{'min_date': '2015-11-16 01:05:32', 'max_date': '2018-10-23 16:00:08'}
{'min_date': '2016-04-27 11:34:52', 'max_date': '2018-10-11 20:00:03'}
{'min_date': '2016-06-01 19:00:27', 'max_date': '2018-09-06 16:00:38'}

Asynchronous Usage

Asynchronous mode works by using the client as an async context manager. Async code is more complicated, but allows a lot of work to be done at once.

This code runs in 3.9 seconds:

>>> import asyncio
>>> from fieldclimate import FieldClimateClient
>>>
>>> async def print_user_json(client):
...     print(await client.get_user())
...
>>> async def print_station_dates(client, station):
...     print(await client.get_data_range(station))
...
>>> async def count_stations_then_print_dates(client):
...     stations = await client.get_user_stations()
...     print(len(stations))
...     await asyncio.gather(*[
...         print_station_dates(client, station)
...         for station in stations[:10]
...     ])
...
>>> async def main():
...     async with FieldClimateClient() as client:
...         await asyncio.gather(
...             print_user_json(client),
...             count_stations_then_print_dates(client),
...         )
...
>>> asyncio.get_event_loop().run_until_complete(main())
{'username': '...', }
1337
{'min_date': '2016-04-27 11:52:15', 'max_date': '2018-10-19 15:00:08'}
{'min_date': '2016-04-27 12:54:09', 'max_date': '2018-09-18 12:14:50'}
{'min_date': '2015-11-16 01:05:32', 'max_date': '2018-10-23 16:00:08'}
{'min_date': '2016-04-27 12:43:29', 'max_date': '2018-09-23 11:00:03'}
{'min_date': '2016-04-27 12:33:37', 'max_date': '2018-10-23 16:00:08'}
{'min_date': '2016-06-01 19:00:27', 'max_date': '2018-09-06 16:00:38'}
{'min_date': '2016-04-28 04:02:11', 'max_date': '2018-10-23 16:00:08'}
{'min_date': '2016-03-24 01:16:40', 'max_date': '2018-10-23 15:55:09'}
{'min_date': '2016-05-05 10:00:13', 'max_date': '2018-10-09 23:00:04'}
{'min_date': '2016-04-27 11:34:52', 'max_date': '2018-10-11 20:00:03'}

Notice how the ordering of the dates is different than before. They are now sorted from the fastest server response to the slowest.

A note on rate limits

According to FieldClimate’s docs, they do not yet enforce rate limiting server-side. Using python-fieldclimate asynchronously allows you to create hundreds or thousands of requests at once. During my testing I noticed the API starting to raise 502 errors when I overloaded it too much.

Please be courteous with your resource consumption!

Methods

The client has methods for each of the corresponding routes listed in the api docs. There’s a lot of them, so see the full list of methods in fieldclimate/__init__.py for more details.

These methods do not have test coverage (and some, like delete_user(), could be dangerous!). However, the underlying logic and utilities they use are all tested.

Every method returns a dictionary response.

Some methods will clean up their arguments in order to make working with the api in python easier. Here are some examples:

  • get_data_last() accepts the time_period parameter. The API docs specify this to be a string like '6h' or '7d', meaning 6 hours or 7 days. FieldClimateClient additionally accepts timedelta objects for this parameter, and will convert them to their equivalent strings for the API (i.e. timedelta(hours=6) is converted to '21600' seconds).

  • Many methods require a station parameter, like get_data_range() does in the examples above. This can be a raw Station ID string, which you can dig out of a station dictionary returned by get_user_stations(). Or, you can pass that dictionary directly in as the station parameter, and the ID will be extracted.

  • More method parameter cleaners can be found in fieldclimate/utils.py.

Contributing

Pull requests are welcome. Please clean your code with black, write tests, and document.

Ideas for PRs:

  • Rate limiting with sane defaults.

  • Proposals for higher level interfaces, e.g. client.stations[i].date_range.

  • Exhaustive mocking to achieve full FC method coverage.

  • More parameter-cleaning utils.

Changes

1.2 (2018-10-26)

  • Dropped requests library in favor of using aiohttp for both sync and async interfaces.

1.1 (2018-10-25)

  • Renamed all station_id method parameters to station, possibly breaking your code.

  • This argument can now handle an entire station dictionary, and will extract the station_id automatically.

1.0 (2018-10-24)

  • Initial PyPI release. 🎉

Authors

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

python-fieldclimate-1.2.tar.gz (11.7 kB view details)

Uploaded Source

Built Distribution

python_fieldclimate-1.2-py3-none-any.whl (10.2 kB view details)

Uploaded Python 3

File details

Details for the file python-fieldclimate-1.2.tar.gz.

File metadata

  • Download URL: python-fieldclimate-1.2.tar.gz
  • Upload date:
  • Size: 11.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.12.1 pkginfo/1.4.2 requests/2.20.0 setuptools/39.1.0 requests-toolbelt/0.8.0 tqdm/4.28.1 CPython/3.6.6

File hashes

Hashes for python-fieldclimate-1.2.tar.gz
Algorithm Hash digest
SHA256 4af9acd8ee901a70ab02ade0e4da83f28f8d4d84bd24adc60fbda6ce11101499
MD5 5f34b72cca8103f1e254b8a8180d982c
BLAKE2b-256 0c9b6307d01190b87489194e4ec10d5145ddc987c7c676ff06826b2e9de0305d

See more details on using hashes here.

File details

Details for the file python_fieldclimate-1.2-py3-none-any.whl.

File metadata

  • Download URL: python_fieldclimate-1.2-py3-none-any.whl
  • Upload date:
  • Size: 10.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.12.1 pkginfo/1.4.2 requests/2.20.0 setuptools/39.1.0 requests-toolbelt/0.8.0 tqdm/4.28.1 CPython/3.6.6

File hashes

Hashes for python_fieldclimate-1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 533bbe54c5cec8c3fca94ba89f1eda2b19a36e6cd03ec20044cc509a0308ef4a
MD5 9c813c0985e204b48a51e21cbcf2ebb8
BLAKE2b-256 54367a39aab4dab8b1781b41e53e684e07a3bc646a71d7c9b149146a0bd7b958

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page