Git Product home page Git Product logo

pyonfleet's Introduction

Onfleet Python Wrapper

Build License Latest version Top language Downloads

Read this document in another language:
正體中文
Español

Visit our blog post on the API wrapper project to learn more about our initiatives.
If you have any questions, please reach us by submitting an issue here or contact [email protected].

Table of contents

Synopsis

The Onfleet Python library provides convenient access to the Onfleet API.

Installation

pip install pyonfleet

Usage

Before using the API wrapper, you will need to obtain an API key from one of your organization's admins.

Creation and integration of API keys are performed through the Onfleet dashboard.

To authenticate, you will also need to create a file named .auth.json under your working directory –this is where you will store your API credentials.

The format of .auth.json is shown below:

{
    "API_KEY": "<your_api_key>"
}

You can also opt in to not store your API key here and pass it as param to Onfleet:

from onfleet import Onfleet

# Option 1 - Recommended
onfleet_api = Onfleet()  # Using the .auth.json file

# Option 2
onfleet_api = Onfleet(api_key="<your_api_key>")  # Without the .auth.json file

Another optional parameter for Onfleet is custom_headers where you can pass in headers to be applied to all requests. For example:

onfleet_api = Onfleet(custom_headers={"<header_name>": "<header_value>"})

Once the Onfleet object is created, you will get access to all the API endpoints as documented in the Onfleet API documentation.

Unit testing using Docker

docker-compose up --build

Throttling

Rate limiting is enforced by the API with a threshold of 20 requests per second across all your organization's API keys. Learn more about it here.

Responses

Responses of this library are instances of Response from the requests library.

Supported CRUD operations

Here are the operations available for each entity:

Entity GET POST PUT DELETE
Admins/Administrators get() create(body={})
matchMetadata(body={})
update(id, body={}) deleteOne(id)
Containers get(workers=id)
get(teams=id)
get(organizations=id)
x update(id, body={}) x
Destinations get(id) create(body={})
matchMetadata(body={})
x x
Hubs get() create(body={}) update(id, body={}) x
Organization get()
get(id)
x insertTask(id, body={}) x
Recipients get(id)
get(name='')
get(phone='')
create(body={})
matchMetadata(body={})
update(id, body={}) x
Tasks get(queryParams={})
get(id)
get(shortId=id)
create(body={})
clone(id)
forceComplete(id)
batch(body={})
autoAssign(body={})
matchMetadata(body={})
update(id, body={}) deleteOne(id)
Teams get()
get(id)
getWorkerEta(id, queryParams={})
getTasks(id, queryParams={})
create(body={})
autoDispatch(id, body={})
update(id, body={})
insertTask(id, body={})
deleteOne(id)
Webhooks get() create(body={}) x deleteOne(id)
Workers get()
get(id)
get(queryParams={})
getByLocation(queryParams={})
getSchedule(id)
getTasks(id, queryParams={})
create(body={})
setSchedule(id, body={})
matchMetadata(body={})
update(id, body={})
insertTask(id, body={})
deleteOne(id)

GET Requests

To get all the documents within an endpoint:

get()
Examples of get()
onfleet_api.workers.get()
onfleet_api.workers.get(queryParams="")

Optionally you can use queryParams for some certain endpoints.
Refer back to API documentation for endpoints that support query parameters.

# Option 1
onfleet_api.workers.get(queryParams={"phones": "<phone_number>"})

# Option 2
onfleet_api.workers.get(queryParams="phones=<phone_number>")

To get one of the document within an endpoint, specify the param that you wish to search by:

get(param="<value>")
Examples of get(param)
onfleet_api.workers.get(id="<24_digit_ID>")
onfleet_api.workers.get(id="<24_digit_ID>", queryParams={"analytics": "true"})

onfleet_api.tasks.get(shortId="<shortId>")

onfleet_api.recipients.get(phone="<phone_number>")
onfleet_api.recipients.get(name="<name>")

onfleet_api.containers.get(workers="<worker_ID>")
onfleet_api.containers.get(teams="<team_ID>")
onfleet_api.containers.get(organizations="<organization_ID>")

Note: don't use Python-style True and False for boolean values - supply these as strings like "true" or "false".

To get a driver by location, use the getByLocation function:

getByLocation(queryParams="<location_params>")
Examples of getByLocation
location_params = {
    "longitude": "-122.4",
    "latitude": "37.7601983",
    "radius": "6000",
}

onfleet_api.workers.getByLocation(queryParams=location_params)

POST Requests

To create a document within an endpoint:

create(body="<data>")
Examples of create()
data = {
    "name": "John Driver",
    "phone": "+16173428853",
    "teams": ["<team_ID>", "<team_ID> (optional)", "..."],
    "vehicle": {
        "type": "CAR",
        "description": "Tesla Model S",
        "licensePlate": "FKNS9A",
        "color": "purple",
    },
}

onfleet_api.workers.create(body=data)

Extended POST requests include clone, forceComplete, batchCreate, autoAssign on the Tasks endpoint; setSchedule on the Workers endpoint; autoDispatch on the Teams endpoint; and matchMetadata on all supported entities. For instance:

onfleet_api.tasks.clone(id="<24_digit_ID>")
onfleet_api.tasks.forceComplete(id="<24_digit_ID>", body="<data>")
onfleet_api.tasks.batchCreate(body="<data>")
onfleet_api.tasks.autoAssign(body="<data>")

onfleet_api.workers.setSchedule(id="<24_digit_ID>", body="<data>")

onfleet_api.teams.autoDispatch(id="<24_digit_ID>", body="<data>")

onfleet_api.<entity_name_pluralized>.matchMetadata(body="<data>")

For more details, check our documentation on clone, forceComplete, batchCreate, autoAssign, setSchedule, matchMetadata, and autoDispatch.

PUT Requests

To update a document within an endpoint:

update(id="<24_digit_ID>", body="<data>")
Examples of update()
new_data = {
    "name": "Jack Driver",
}

onfleet_api.workers.update(id="<24_digit_ID>", body=new_data)
Examples of insertTask()
onfleet_api.workers.insertTask(id="<24_digit_ID>", body="<data>")

DELETE Requests

To delete a document within an endpoint:

deleteOne(id="<24_digit_ID>")
Examples of deleteOne()
onfleet_api.workers.deleteOne(id="<24_digit_ID>")

Go to top.

pyonfleet's People

Contributors

bbradshaw avatar cemead avatar dependabot[bot] avatar jamesliupenn avatar jcpmmx avatar kaiserawu avatar shuaitseng avatar threeethan avatar vic-onfleet avatar yokysantiago avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pyonfleet's Issues

[BUG] Some packaging issues with 1.0.2

Describe the bug
Users have reported that config file folder wasn't included in 1.0.2

To Reproduce
Steps to reproduce the behavior:

  1. Fresh install of pyonfleet 1.0.2
  2. FileNotFoundError: [Errno 2] No such file or directory: ‘config/config.json’

Expected behavior
config folder to be installed

Additional context
Add any other context about the problem here, including pyonfleet version and request ID that returned on your error response.

[BUG] I can't get tasks for all

I try to get all tasks
tasks = on_api.tasks.get(queryParams={"from":1455072025000,"state":0})
Error is
File "/home/webadm/dirct.us/phalapi/Python/NewTools/Tools_onfleet.py", line 811, in <module> API.check_task() File "/home/webadm/dirct.us/phalapi/Python/NewTools/Tools_onfleet.py", line 758, in check_task tasks = on_api.tasks.get(queryParams={"from":1455072025000,"state":0}) File "/usr/local/python/3.8/lib/python3.8/site-packages/backoff/_sync.py", line 94, in retry ret = target(*args, **kwargs) File "/usr/local/python/3.8/lib/python3.8/site-packages/ratelimit/decorators.py", line 80, in wrapper return func(*args, **kargs) File "/usr/local/python/3.8/lib/python3.8/site-packages/onfleet/request.py", line 69, in __call__ raise ValidationError(*exception_args) onfleet.error.ValidationError: ('The values of one or more parameters are invalid.', 1000, '1d6f8d4a-cca7-4106-b658-4b470d945255', 'From time was not provided or contains an invalid value')

[BUG] installation error

Hello, I'm getting this error when running pip install pyonfleet:

onfleet ❯ pip install pyonfleet                                                                                                 ⏎
DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support
Collecting pyonfleet
  Downloading https://files.pythonhosted.org/packages/31/1c/e8169cf6e2dc3b7a9d8bfb6480a27548d867c2297559da3c58b52bf13d82/pyonfleet-1.0.1.tar.gz
    ERROR: Command errored out with exit status 1:
     command: /usr/bin/python -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/private/var/folders/zb/36g7jk8d2t723_w5gv7f1kkjxccswy/T/pip-install-yBdMzx/pyonfleet/setup.py'"'"'; __file__='"'"'/private/var/folders/zb/36g7jk8d2t723_w5gv7f1kkjxccswy/T/pip-install-yBdMzx/pyonfleet/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /private/var/folders/zb/36g7jk8d2t723_w5gv7f1kkjxccswy/T/pip-install-yBdMzx/pyonfleet/pip-egg-info
         cwd: /private/var/folders/zb/36g7jk8d2t723_w5gv7f1kkjxccswy/T/pip-install-yBdMzx/pyonfleet/
    Complete output (5 lines):
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/private/var/folders/zb/36g7jk8d2t723_w5gv7f1kkjxccswy/T/pip-install-yBdMzx/pyonfleet/setup.py", line 2, in <module>
        import pathlib
    ImportError: No module named pathlib
    ----------------------------------------
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.

Add 'error cause' when raising HttpError exception on Request class

Actually, the Request class raises the exception HttpError with error_message, error_code, error_request but it's not returning the error cause. There is no way to know if the issue is the phone number of a geocoding error.

This information is on error["message"]["cause"] but it's not returned in the exception and it's not easy to know what should be fixed.

I should suggest adding the argument cause or reason into the HttpError class.

I can create a PR for that, but I would like to know your thoughts before.

[FREQ] Add support for tasks/batch-async endpoint

According to official docs, the batch create endpoint for tasks is being deprecated:
"Deprecation Notice

This endpoint will start to phase out soon. For any future developments, we recommend Create tasks in batch - async. For any legacy development, please consider migrating to the batch async endpoint as soon as possible to prevent any service interruptions."

I would love to see support for the tasks batch-async endpoint added to this API Wrapper library so that we can continue using the library and avoid deprecation woes.

Thanks!

[FREQ] It's difficult to mock API calls as endpoints are added using setattr

The following example raises an error because tasks and the subsequent API endpoints are added to the Onfleet class using setattr. Unless there's another way of mocking these types of functions that I'm not aware of.

AttributeError: type object 'Onfleet' has no attribute 'tasks'

def get_task(id):
    from onfleet import Onfleet
    api = Onfleet()
    return api.tasks.get(id=id)

with patch('onleet.Onfleet.tasks.get', return_value={}):
    task = get_task(id='...')

[BUG] Directory error due to backslashes used in Windows environment

Describe the bug
Microsoft Windows uses a backslash character between folder names while almost every other computer uses a forward slash, the pyonfleet package fails to fetch the config file due to that folder/directory problem.

To Reproduce
Steps to reproduce the behavior:

  1. Download the wrapper onto a Windows environment
  2. Attempt to use the wrapper

Expected behavior
Expect the wrapper to work as expected, but it throws a No such file or directory: <some_directory>\\config/config.json

[BUG] KeyError when batchCreate results in errors

Describe the bug
There's an uncaught KeyError when the batchCreate endpoint returns errors.

Traceback (most recent call last):
  File "/home/user/project/venv/lib/python3.7/site-packages/celery/app/trace.py", line 385, in trace_task
    R = retval = fun(*args, **kwargs)
  File "/home/user/project/venv/lib/python3.7/site-packages/celery/app/trace.py", line 650, in __protected_call__
    return self.run(*args, **kwargs)
  File "/home/user/project/dispatch/tasks.py", line 18, in create_onfleet_tasks_from_run
    create_count, error_list = models.RunStop.tasks.batch_create(stops)
  File "/home/user/project/_onfleet/models.py", line 45, in batch_create
    response = api.tasks.batchCreate(body=dict(tasks=task_list))
  File "/home/user/project/venv/lib/python3.7/site-packages/backoff/_sync.py", line 94, in retry
    ret = target(*args, **kwargs)
  File "/home/user/project/venv/lib/python3.7/site-packages/ratelimit/decorators.py", line 80, in wrapper
    return func(*args, **kargs)
  File "/home/user/project/venv/lib/python3.7/site-packages/onfleet/request.py", line 62, in __call__
    error_request = error['message']['request']
KeyError: 'request'

To Reproduce
I had thought it was due to an error with the address but just retried the API call and it was completed successfully.

I've run into a similar problem with large batches but in this case the body only contained 10 tasks.

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
If applicable, add screenshots to help explain your problem.

Additional context
v1.2

[BUG] Sometimes backend doesn't send message

Certain types of errors, like 405 MethodNotAllowed, are incorrectly handled. The assumption is that the server will send a JSON encoded object with this shape:
{"code":"...","message":{error:"...", code: "..", "message"..."}}

But the backend is not consistent and this shape is sometimes found (actual response):
{"code":"MethodNotAllowed","message":"POST is not allowed"}'

This causes a TypeError in the error handling routine of request.py:56.

Exception has occurred: TypeError       (note: full exception trace is shown but execution is paused at: _run_module_as_main)
string indices must be integers
  File "/Users/ben/Documents/testing_scripts/test_venv/lib/python3.9/site-packages/onfleet/request.py", line 56, in __call__
    error_code = error["message"]["error"]
...

[BUG] Had to edit onfleet/request.py to get the OnFleet Python API Wrapper to work on AWS Lambda

I'm using the AWS Lambda Python 3.8 runtime, and my pip3 is Python3.8 (I'm using Mac OSX for my local work). I built the deployment package using:

pip3 install --target ./package pyonfleet

This installed:

backoff-1.10.0
certifi-2020.12.5
chardet-4.0.0
idna-2.10
pyonfleet-1.1.2
ratelimit-2.2.1
requests-2.25.1
urllib3-1.26.3

I zipped these libs with my own code, per AWS Lambda's instructions, and deployed the package to Lambda.

I got this error when trying to run my Lambda:

[ERROR] DistributionNotFound: The 'pyonfleet' distribution was not found and is required by the application
Traceback (most recent call last):
File "/var/lang/lib/python3.8/imp.py", line 234, in load_module
return load_source(name, filename, file)
File "/var/lang/lib/python3.8/imp.py", line 171, in load_source
module = _load(spec)
File "", line 702, in _load
File "", line 671, in _load_unlocked
File "", line 783, in exec_module
File "", line 219, in _call_with_frames_removed
File "/var/task/tp-api-onfleet.py", line 54, in
on = Onfleet(api_key=ONFLEET_API_TOKEN)
File "/var/task/onfleet/onfleet.py", line 22, in init
self._initialize_resources(self._session)
File "/var/task/onfleet/onfleet.py", line 33, in _initialize_resources
setattr(self, endpoint, Endpoint(http_methods, session))
File "/var/task/onfleet/endpoint.py", line 9, in init
self._generate_request(httpMethod, methodDict)
File "/var/task/onfleet/endpoint.py", line 18, in _generate_request
setattr(self, methodName, Request(http_method, uri, self.Session))
File "/var/task/onfleet/request.py", line 16, in init
"User-Agent": "pyonfleet-" + pkg_resources.require("pyonfleet")[0].version
File "/var/lang/lib/python3.8/site-packages/pkg_resources/init.py", line 899, in require
needed = self.resolve(parse_requirements(requirements))
File "/var/lang/lib/python3.8/site-packages/pkg_resources/init.py", line 785, in resolve
raise DistributionNotFound(req, requirers)

Some online research pointed to the fact that AWS Lambda doesn't have a package manager installed.

I happened upon this line in onfleet/requests.py, which uses the package manager to dynamically provide the version number:

        "User-Agent": "pyonfleet-" + pkg_resources.require("pyonfleet")[0].version

I changed this line to use a hard-coded version number, like this, and this fixed my issue, and everything worked as expected:

        "User-Agent": "pyonfleet-1.1.2"

I'm unblocked, but wanted to share this workaround with you, for the benefit of other AWS Lambda users. Maybe there is another way to determine this version number, without requiring the package manager to be installed?

-Dave

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.