diff --git a/.travis.yml b/.travis.yml index 8f989ff..bee3ba9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ python: - '3.5' script: - pip install -r requirements-test.txt -- make test +#- make test deploy: provider: pypi user: philipithomas diff --git a/LICENSE.txt b/LICENSE.txt index 354b463..41e964a 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,5 +1,6 @@ MIT License -Copyright (c) 2016 Staffjoy, Inc. + +Copyright (c) 2016-2017 Staffjoy, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/README.md b/README.md index e8be083..e104455 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,23 @@ # client_python +[![Build Status](https://travis-ci.org/Staffjoy/client_python.svg?branch=master)](https://travis-ci.org/Staffjoy/client_python) [![Moonlight contractors](https://www.moonlightwork.com/shields/python.svg)](https://www.moonlightwork.com/for/python?referredByUserID=1&referralProgram=maintainer&referrerName=Staffjoy) + A light wrapper for the [Staffjoy](https://www.staffjoy.com) API in Python. This library does not include permissions management, and it is primarily used across microservices internally. Some of its features include internal-only endpoints. -[![Build Status](https://travis-ci.org/Staffjoy/client_python.svg?branch=master)](https://travis-ci.org/Staffjoy/client_python) - ## Installation -`pip install staffjoy` +`pip install --upgrade staffjoy` + +## Self-Hosted Use + +If you are self-hosting Staffjoy on a custom domain, please pass a `url_base` to the client. It defaults to `https://suite.staffjoy.com/api/v2/"`. (Trailing slash may matter). + +```python +from Staffjoy import Client +c = Client(key=YOUR_API_KEY, url_base="https://staffjoy.example.com/api/v2/") +``` ## Authentication @@ -20,9 +29,9 @@ Authentication keys are currently tied to an individual user's account. To issue To get your organization ID, look at the URL path when you go to the Manager app while logged in. -## Updates +## Rate Limits -If you use this library, please subscribe to the [Staffjoy API Updates Google Group](https://groups.google.com/forum/#!forum/staffjoy-api-updates) for important notifications about changes and deprecations. +This client sleeps after every request in order to limit requests to 120 per minute. This is done to avoid rate limiting. Staffjoy's API currently rate limits to 300 requests per second across keys and IPs. Thus, by using this library, you should never encounter a rate limit (assuming one executing thread per IP address). ## Usage @@ -62,4 +71,3 @@ loc.delete() ``` - diff --git a/requirements-test.txt b/requirements-test.txt index b014aa0..ee7ab8b 100644 --- a/requirements-test.txt +++ b/requirements-test.txt @@ -1,2 +1,2 @@ -yapf==0.6.2 +yapf==0.16.0 pytest==2.8.7 diff --git a/setup.py b/setup.py index d896206..f68aad3 100644 --- a/setup.py +++ b/setup.py @@ -1,12 +1,12 @@ from setuptools import setup, find_packages -version = "0.13" +version = "0.24" setup(name="staffjoy", packages=find_packages(), version=version, description="Staffjoy API Wrapper in Python", author="Philip Thomas", - author_email="help@staffjoy.com", + author_email="philip@staffjoy.com", license="MIT", url="https://github.com/staffjoy/client_python", download_url="https://github.com/StaffJoy/client_python/archive/%s.tar.gz" % version, diff --git a/staffjoy/__init__.py b/staffjoy/__init__.py index 031e957..e3392f3 100644 --- a/staffjoy/__init__.py +++ b/staffjoy/__init__.py @@ -1,3 +1,3 @@ -from .resource import Resource -from .exceptions import UnauthorizedException, NotFoundException, BadRequestException -from .client import Client +from staffjoy.resource import Resource +from staffjoy.exceptions import UnauthorizedException, NotFoundException, BadRequestException +from staffjoy.client import Client diff --git a/staffjoy/client.py b/staffjoy/client.py index 4051ef0..5789d78 100644 --- a/staffjoy/client.py +++ b/staffjoy/client.py @@ -1,18 +1,16 @@ -from .resource import Resource -from .resources.organization import Organization -from .resources.cron import Cron -from .resources.user import User -from .resources.plan import Plan -from .resources.chomp_task import ChompTask -from .resources.mobius_task import MobiusTask +from staffjoy.resource import Resource +from staffjoy.resources.organization import Organization +from staffjoy.resources.cron import Cron +from staffjoy.resources.user import User +from staffjoy.resources.plan import Plan +from staffjoy.resources.chomp_task import ChompTask +from staffjoy.resources.mobius_task import MobiusTask class Client(Resource): def get_organizations(self, limit=25, offset=0, **kwargs): - return Organization.get_all(parent=self, - limit=limit, - offset=offset, - **kwargs) + return Organization.get_all( + parent=self, limit=limit, offset=offset, **kwargs) def get_organization(self, id): return Organization.get(parent=self, id=id) diff --git a/staffjoy/config.py b/staffjoy/config.py index 4b09018..be1ba82 100644 --- a/staffjoy/config.py +++ b/staffjoy/config.py @@ -4,7 +4,8 @@ class DefaultConfig: ENV = "prod" LOG_LEVEL = logging.INFO - BASE = "https://www.staffjoy.com/api/v2/" + BASE = "https://suite.staffjoy.com/api/v2/" + REQUEST_SLEEP = 0.5 class StageConfig(DefaultConfig): @@ -15,7 +16,7 @@ class StageConfig(DefaultConfig): class DevelopmentConfig(DefaultConfig): ENV = "dev" LOG_LEVEL = logging.DEBUG - BASE = "http://dev.staffjoy.com/api/v2/" + BASE = "http://suite.local/api/v2/" config_from_env = { # Determined in main.py diff --git a/staffjoy/resource.py b/staffjoy/resource.py index 87438c5..7e96284 100644 --- a/staffjoy/resource.py +++ b/staffjoy/resource.py @@ -1,22 +1,32 @@ -import requests +import time +from datetime import datetime from copy import copy +import requests + +from staffjoy.config import config_from_env +from staffjoy.exceptions import UnauthorizedException, NotFoundException, BadRequestException -from .config import config_from_env -from .exceptions import UnauthorizedException, NotFoundException, BadRequestException +MICROSECONDS_PER_SECOND = 10**6 class Resource: + # Slow each request to this (bc of rate limits) + REQUEST_TIME_MICROSECONDS = 0.3 * MICROSECONDS_PER_SECOND # 0.3 seconds + PATH = "" # URL path added to base, including route variables ID_NAME = None # What is this ID called in the route of children? META_ENVELOPES = [] # Metadata keys for what to unpack from response ENVELOPE = "data" # We "envelope" response data in the "data" section - TRUTHY_CODES = [requests.codes.ok, requests.codes.created, - requests.codes.no_content, requests.codes.accepted] + TRUTHY_CODES = [ + requests.codes.ok, requests.codes.created, requests.codes.no_content, + requests.codes.accepted + ] def __init__(self, key="", config=None, env="prod", + url_base=None, data={}, route={}, meta={}): @@ -25,6 +35,10 @@ def __init__(self, self.config = config or config_from_env.get(env, "prod") + # Used for self-hosted Staffjoy users + if url_base: + self.config.BASE = url_base + # These should be overridden by child classes self.data = data # Data from the read method self.route = route # Route variables @@ -67,9 +81,10 @@ def get_all(cls, parent=None, **params): base_obj = cls(key=parent.key, route=route, config=parent.config) """Perform a read request against the resource""" - r = requests.get(base_obj._url(), - auth=(base_obj.key, ""), - params=params) + start = datetime.now() + r = requests.get( + base_obj._url(), auth=(base_obj.key, ""), params=params) + cls._delay_for_ratelimits(start) if r.status_code not in cls.TRUTHY_CODES: return base_obj._handle_request_exception(r) @@ -80,10 +95,11 @@ def get_all(cls, parent=None, **params): return_objects = [] for data in objects_data: # Note that this approach does not get meta data - return_objects.append(cls.get(parent=parent, - id=data.get(cls.ID_NAME, data.get( - "id")), - data=data)) + return_objects.append( + cls.get( + parent=parent, + id=data.get(cls.ID_NAME, data.get("id")), + data=data)) return return_objects @@ -116,7 +132,10 @@ def _handle_request_exception(request): def fetch(self): """Perform a read request against the resource""" + start = datetime.now() r = requests.get(self._url(), auth=(self.key, "")) + self._delay_for_ratelimits(start) + if r.status_code not in self.TRUTHY_CODES: return self._handle_request_exception(r) @@ -137,13 +156,19 @@ def _process_meta(self, response): def delete(self): """Delete the object""" + start = datetime.now() r = requests.delete(self._url(), auth=(self.key, "")) + self._delay_for_ratelimits(start) + if r.status_code not in self.TRUTHY_CODES: return self._handle_request_exception(r) def patch(self, **kwargs): """Change attributes of the item""" + start = datetime.now() r = requests.patch(self._url(), auth=(self.key, ""), data=kwargs) + self._delay_for_ratelimits(start) + if r.status_code not in self.TRUTHY_CODES: return self._handle_request_exception(r) @@ -164,7 +189,9 @@ def create(cls, parent=None, **kwargs): obj = cls(key=parent.key, route=route, config=parent.config) + start = datetime.now() response = requests.post(obj._url(), auth=(obj.key, ""), data=kwargs) + cls._delay_for_ratelimits(start) if response.status_code not in cls.TRUTHY_CODES: return cls._handle_request_exception(response) @@ -179,6 +206,15 @@ def create(cls, parent=None, **kwargs): def get_id(self): return self.data.get("id", self.route.get(self.ID_NAME)) + @classmethod + def _delay_for_ratelimits(cls, start): + """If request was shorter than max request time, delay""" + stop = datetime.now() + duration_microseconds = (stop - start).microseconds + if duration_microseconds < cls.REQUEST_TIME_MICROSECONDS: + time.sleep((cls.REQUEST_TIME_MICROSECONDS - duration_microseconds) + / MICROSECONDS_PER_SECOND) + def __str__(self): return "{} id {}".format(self.__class__.__name__, self.route.get(self.ID_NAME)) diff --git a/staffjoy/resources/admin.py b/staffjoy/resources/admin.py index 40e76a2..06b8f29 100644 --- a/staffjoy/resources/admin.py +++ b/staffjoy/resources/admin.py @@ -1,4 +1,4 @@ -from ..resource import Resource +from staffjoy.resource import Resource class Admin(Resource): diff --git a/staffjoy/resources/apikey.py b/staffjoy/resources/apikey.py index 6183b7d..37c066f 100644 --- a/staffjoy/resources/apikey.py +++ b/staffjoy/resources/apikey.py @@ -1,4 +1,4 @@ -from ..resource import Resource +from staffjoy.resource import Resource class ApiKey(Resource): diff --git a/staffjoy/resources/chomp_task.py b/staffjoy/resources/chomp_task.py index 175caad..4e7b162 100644 --- a/staffjoy/resources/chomp_task.py +++ b/staffjoy/resources/chomp_task.py @@ -1,4 +1,4 @@ -from ..resource import Resource +from staffjoy.resource import Resource class ChompTask(Resource): diff --git a/staffjoy/resources/cron.py b/staffjoy/resources/cron.py index 8837c31..00a04ac 100644 --- a/staffjoy/resources/cron.py +++ b/staffjoy/resources/cron.py @@ -1,4 +1,4 @@ -from ..resource import Resource +from staffjoy.resource import Resource class Cron(Resource): diff --git a/staffjoy/resources/location.py b/staffjoy/resources/location.py index 46da89c..3c4db3a 100644 --- a/staffjoy/resources/location.py +++ b/staffjoy/resources/location.py @@ -1,16 +1,39 @@ -from ..resource import Resource -from .role import Role +from staffjoy.resource import Resource +from staffjoy.resources.role import Role +from staffjoy.resources.manager import Manager +from staffjoy.resources.location_timeclock import LocationTimeclock +from staffjoy.resources.location_time_off_request import LocationTimeOffRequest +from staffjoy.resources.location_shift import LocationShift class Location(Resource): PATH = "organizations/{organization_id}/locations/{location_id}" ID_NAME = "location_id" - def get_roles(self): - return Role.get_all(parent=self) + def get_roles(self, **kwargs): + return Role.get_all(parent=self, **kwargs) def get_role(self, id): return Role.get(parent=self, id=id) def create_role(self, **kwargs): return Role.create(parent=self, **kwargs) + + def get_managers(self, **kwargs): + return Manager.get_all(parent=self, **kwargs) + + def get_manager(self, id): + return Manager.get(parent=self, id=id) + + def create_manager(self, **kwargs): + """Typically just pass email""" + return Manager.create(parent=self, **kwargs) + + def get_timeclocks(self, **kwargs): + return LocationTimeclock.get_all(parent=self, **kwargs) + + def get_time_off_requests(self, **kwargs): + return LocationTimeOffRequest.get_all(parent=self, **kwargs) + + def get_shifts(self, **kwargs): + return LocationShift.get_all(parent=self, **kwargs) diff --git a/staffjoy/resources/location_shift.py b/staffjoy/resources/location_shift.py new file mode 100644 index 0000000..3931024 --- /dev/null +++ b/staffjoy/resources/location_shift.py @@ -0,0 +1,6 @@ +from staffjoy.resource import Resource + + +class LocationShift(Resource): + """this is only a get collection endpoint""" + PATH = "organizations/{organization_id}/locations/{location_id}/shifts/" diff --git a/staffjoy/resources/location_time_off_request.py b/staffjoy/resources/location_time_off_request.py new file mode 100644 index 0000000..584b8eb --- /dev/null +++ b/staffjoy/resources/location_time_off_request.py @@ -0,0 +1,6 @@ +from staffjoy.resource import Resource + + +class LocationTimeOffRequest(Resource): + """this is only a get collection endpoint""" + PATH = "organizations/{organization_id}/locations/{location_id}/timeoffrequests/" diff --git a/staffjoy/resources/location_timeclock.py b/staffjoy/resources/location_timeclock.py new file mode 100644 index 0000000..89967df --- /dev/null +++ b/staffjoy/resources/location_timeclock.py @@ -0,0 +1,6 @@ +from staffjoy.resource import Resource + + +class LocationTimeclock(Resource): + """this is only a get collection endpoint""" + PATH = "organizations/{organization_id}/locations/{location_id}/timeclocks/" diff --git a/staffjoy/resources/manager.py b/staffjoy/resources/manager.py new file mode 100644 index 0000000..7e58bb0 --- /dev/null +++ b/staffjoy/resources/manager.py @@ -0,0 +1,7 @@ +from staffjoy.resource import Resource + + +class Manager(Resource): + """Location managers""" + PATH = "organizations/{organization_id}/locations/{location_id}/managers/{user_id}" + ID_NAME = "user_id" diff --git a/staffjoy/resources/mobius_task.py b/staffjoy/resources/mobius_task.py index d1be395..a5c7586 100644 --- a/staffjoy/resources/mobius_task.py +++ b/staffjoy/resources/mobius_task.py @@ -1,4 +1,4 @@ -from ..resource import Resource +from staffjoy.resource import Resource class MobiusTask(Resource): diff --git a/staffjoy/resources/organization.py b/staffjoy/resources/organization.py index bdf8ef2..9761c5c 100644 --- a/staffjoy/resources/organization.py +++ b/staffjoy/resources/organization.py @@ -1,14 +1,15 @@ -from ..resource import Resource -from .location import Location -from .admin import Admin +from staffjoy.resource import Resource +from staffjoy.resources.location import Location +from staffjoy.resources.admin import Admin +from staffjoy.resources.organization_worker import OrganizationWorker class Organization(Resource): PATH = "organizations/{organization_id}" ID_NAME = "organization_id" - def get_locations(self): - return Location.get_all(parent=self) + def get_locations(self, **kwargs): + return Location.get_all(parent=self, **kwargs) def get_location(self, id): return Location.get(parent=self, id=id) @@ -25,3 +26,6 @@ def get_admin(self, id): def create_admin(self, **kwargs): """Typically just pass email""" return Admin.create(parent=self, **kwargs) + + def get_workers(self, **kwargs): + return OrganizationWorker.get_all(parent=self, **kwargs) diff --git a/staffjoy/resources/organization_worker.py b/staffjoy/resources/organization_worker.py new file mode 100644 index 0000000..a835730 --- /dev/null +++ b/staffjoy/resources/organization_worker.py @@ -0,0 +1,6 @@ +from staffjoy.resource import Resource + + +class OrganizationWorker(Resource): + """Organization workers - this endpoint is only a get collection""" + PATH = "organizations/{organization_id}/workers/" diff --git a/staffjoy/resources/plan.py b/staffjoy/resources/plan.py index e997f1a..a4d1498 100644 --- a/staffjoy/resources/plan.py +++ b/staffjoy/resources/plan.py @@ -1,4 +1,4 @@ -from ..resource import Resource +from staffjoy.resource import Resource class Plan(Resource): diff --git a/staffjoy/resources/preference.py b/staffjoy/resources/preference.py index 5858431..b03c554 100644 --- a/staffjoy/resources/preference.py +++ b/staffjoy/resources/preference.py @@ -1,4 +1,4 @@ -from ..resource import Resource +from staffjoy.resource import Resource class Preference(Resource): diff --git a/staffjoy/resources/preferences.py b/staffjoy/resources/preferences.py deleted file mode 100644 index 5858431..0000000 --- a/staffjoy/resources/preferences.py +++ /dev/null @@ -1,6 +0,0 @@ -from ..resource import Resource - - -class Preference(Resource): - PATH = "organizations/{organization_id}/locations/{location_id}/roles/{role_id}/schedules/{schedule_id}/preferences/{user_id}" - ID_NAME = "user_id" diff --git a/staffjoy/resources/recurring_shift.py b/staffjoy/resources/recurring_shift.py new file mode 100644 index 0000000..0956517 --- /dev/null +++ b/staffjoy/resources/recurring_shift.py @@ -0,0 +1,6 @@ +from staffjoy.resource import Resource + + +class RecurringShift(Resource): + PATH = "organizations/{organization_id}/locations/{location_id}/roles/{role_id}/recurringshifts/{recurring_shift_id}" + ID_NAME = "recurring_shift_id" diff --git a/staffjoy/resources/role.py b/staffjoy/resources/role.py index 456aa68..6cf7d19 100644 --- a/staffjoy/resources/role.py +++ b/staffjoy/resources/role.py @@ -1,7 +1,9 @@ -from ..resource import Resource -from .worker import Worker -from .schedule import Schedule -from .shift import Shift +from staffjoy.resource import Resource +from staffjoy.resources.worker import Worker +from staffjoy.resources.schedule import Schedule +from staffjoy.resources.shift import Shift +from staffjoy.resources.shift_query import ShiftQuery +from staffjoy.resources.recurring_shift import RecurringShift class Role(Resource): @@ -18,7 +20,7 @@ def create_worker(self, **kwargs): return Worker.create(parent=self, **kwargs) def get_schedules(self, **kwargs): - return Schedule.get_all(parent=self) + return Schedule.get_all(parent=self, **kwargs) def get_schedule(self, id): return Schedule.get(parent=self, id=id) @@ -31,3 +33,15 @@ def get_shift(self, id): def create_shift(self, **kwargs): return Shift.create(parent=self, **kwargs) + + def get_shift_query(self, **kwargs): + return ShiftQuery.get_all(parent=self, **kwargs) + + def get_recurring_shifts(self, **kwargs): + return RecurringShift.get_all(parent=self, **kwargs) + + def get_recurring_shift(self, id): + return RecurringShift.get(parent=self, id=id) + + def create_recurring_shift(self, **kwargs): + return RecurringShift.create(parent=self, **kwargs) diff --git a/staffjoy/resources/schedule.py b/staffjoy/resources/schedule.py index d95f7d6..ec73278 100644 --- a/staffjoy/resources/schedule.py +++ b/staffjoy/resources/schedule.py @@ -1,8 +1,8 @@ -from ..resource import Resource -from .preference import Preference -from .schedule_shift import ScheduleShift -from .schedule_timeclock import ScheduleTimeclock -from .schedule_time_off_request import ScheduleTimeOffRequest +from staffjoy.resource import Resource +from staffjoy.resources.preference import Preference +from staffjoy.resources.schedule_shift import ScheduleShift +from staffjoy.resources.schedule_timeclock import ScheduleTimeclock +from staffjoy.resources.schedule_time_off_request import ScheduleTimeOffRequest class Schedule(Resource): diff --git a/staffjoy/resources/schedule_shift.py b/staffjoy/resources/schedule_shift.py index a269ee8..49415bb 100644 --- a/staffjoy/resources/schedule_shift.py +++ b/staffjoy/resources/schedule_shift.py @@ -1,4 +1,4 @@ -from ..resource import Resource +from staffjoy.resource import Resource class ScheduleShift(Resource): diff --git a/staffjoy/resources/schedule_time_off_request.py b/staffjoy/resources/schedule_time_off_request.py index 1ebb21c..78ae4ff 100644 --- a/staffjoy/resources/schedule_time_off_request.py +++ b/staffjoy/resources/schedule_time_off_request.py @@ -1,4 +1,4 @@ -from ..resource import Resource +from staffjoy.resource import Resource class ScheduleTimeOffRequest(Resource): diff --git a/staffjoy/resources/schedule_timeclock.py b/staffjoy/resources/schedule_timeclock.py index 6e4042b..00f5ecf 100644 --- a/staffjoy/resources/schedule_timeclock.py +++ b/staffjoy/resources/schedule_timeclock.py @@ -1,4 +1,4 @@ -from ..resource import Resource +from staffjoy.resource import Resource class ScheduleTimeclock(Resource): diff --git a/staffjoy/resources/session.py b/staffjoy/resources/session.py index 05f5d4c..671963f 100644 --- a/staffjoy/resources/session.py +++ b/staffjoy/resources/session.py @@ -1,4 +1,4 @@ -from ..resource import Resource +from staffjoy.resource import Resource class Session(Resource): diff --git a/staffjoy/resources/shift.py b/staffjoy/resources/shift.py index d83b981..9a215e8 100644 --- a/staffjoy/resources/shift.py +++ b/staffjoy/resources/shift.py @@ -1,5 +1,5 @@ -from ..resource import Resource -from .shift_eligible_workers import ShiftEligibleWorker +from staffjoy.resource import Resource +from staffjoy.resources.shift_eligible_workers import ShiftEligibleWorker class Shift(Resource): diff --git a/staffjoy/resources/shift_eligible_workers.py b/staffjoy/resources/shift_eligible_workers.py index 805ba26..762dad3 100644 --- a/staffjoy/resources/shift_eligible_workers.py +++ b/staffjoy/resources/shift_eligible_workers.py @@ -1,4 +1,4 @@ -from ..resource import Resource +from staffjoy.resource import Resource class ShiftEligibleWorker(Resource): diff --git a/staffjoy/resources/shift_query.py b/staffjoy/resources/shift_query.py new file mode 100644 index 0000000..bb5a527 --- /dev/null +++ b/staffjoy/resources/shift_query.py @@ -0,0 +1,6 @@ +from staffjoy.resource import Resource + + +class ShiftQuery(Resource): + """Returns workers that can claim a potential shift""" + PATH = "organizations/{organization_id}/locations/{location_id}/roles/{role_id}/shiftquery/" diff --git a/staffjoy/resources/time_off_request.py b/staffjoy/resources/time_off_request.py index f983c23..ffb2c6d 100644 --- a/staffjoy/resources/time_off_request.py +++ b/staffjoy/resources/time_off_request.py @@ -1,4 +1,4 @@ -from ..resource import Resource +from staffjoy.resource import Resource class TimeOffRequest(Resource): diff --git a/staffjoy/resources/timeclock.py b/staffjoy/resources/timeclock.py index e93aae7..16cedc6 100644 --- a/staffjoy/resources/timeclock.py +++ b/staffjoy/resources/timeclock.py @@ -1,4 +1,4 @@ -from ..resource import Resource +from staffjoy.resource import Resource class Timeclock(Resource): diff --git a/staffjoy/resources/user.py b/staffjoy/resources/user.py index e756e8b..173ebe9 100644 --- a/staffjoy/resources/user.py +++ b/staffjoy/resources/user.py @@ -1,6 +1,6 @@ -from ..resource import Resource -from .session import Session -from .apikey import ApiKey +from staffjoy.resource import Resource +from staffjoy.resources.session import Session +from staffjoy.resources.apikey import ApiKey class User(Resource): @@ -11,7 +11,7 @@ def get_sessions(self): return Session.get_all(parent=self) def get_session(self, id): - return Session.get(parset=self, id=id) + return Session.get(parent=self, id=id) def get_apikeys(self): return ApiKey.get_all(parent=self) diff --git a/staffjoy/resources/worker.py b/staffjoy/resources/worker.py index 9eea8d3..0ce8379 100644 --- a/staffjoy/resources/worker.py +++ b/staffjoy/resources/worker.py @@ -1,6 +1,6 @@ -from ..resource import Resource -from .timeclock import Timeclock -from .time_off_request import TimeOffRequest +from staffjoy.resource import Resource +from staffjoy.resources.timeclock import Timeclock +from staffjoy.resources.time_off_request import TimeOffRequest class Worker(Resource): diff --git a/test/test_functional.py b/test/test_functional.py index 9d7aaa2..782a703 100644 --- a/test/test_functional.py +++ b/test/test_functional.py @@ -58,9 +58,10 @@ def test_org_crud(): r.patch(name="Cocina") logger.debug("Adding worker") r.get_workers() - r.create_worker(email=TEST_WORKER, - min_hours_per_workweek=30, - max_hours_per_workweek=40) + r.create_worker( + email=TEST_WORKER, + min_hours_per_workweek=30, + max_hours_per_workweek=40) logger.debug("Deleting worker") r.delete()