Welcome to G API Python Client’s documentation!¶
Contents:
G API Python Client¶
A client for the G Adventures REST API (https://developers.gadventures.com)
- GitHub Repository: https://github.com/gadventures/gapipy/
- Documentation: http://gapipy.readthedocs.org.
- Free software: MIT license
Quick Start¶
>>> from gapipy import Client
>>> api = Client(application_key='MY_SECRET_KEY')
>>> # Get a resource by id
>>> tour_dossier = api.tour_dossiers.get(24309)
>>> tour_dossier.product_line
u'AHEH'
>>> tour_dossier.departures.count()
134
>>> tour_dossier.name
u'Essential India'
>>> itinerary = tour_dossier.structured_itineraries[0]
>>> {day.day: day.summary for day in itinerary.days[:3]}
{1: u'Arrive at any time. Arrival transfer included through the G Adventures-supported Women on Wheels project.',
2: u'Take a morning walk through the city with a young adult from the G Adventures-supported New Delhi Streetkids Project. Later, visit Old Delhi, explore the spice markets, and visit Jama Masjid and Connaught Place.',
3: u"Arrive in Jaipur and explore this gorgeous 'pink city'."}
>>> # Create a new resource
>>> booking = api.bookings.create({'currency': 'CAD', 'external_id': 'abc'})
>>> # Modify an existing resource
>>> booking.external_id = 'def'
>>> booking.save()
Since `2.25.0 (2020-01-02)`_
>>> # since 2.25.0 reference stubs that fail to fetch will return a
>>> # subclass of requests.HTTPError (See: https://github.com/gadventures/gapipy/pull/119)
>>> # This can also be done on Query.get by passing a Falsy value for the
>>> # httperrors_mapped_to_none kwarg.
>>>
>>> dep = api.departures.get('404_404', httperrors_mapped_to_none=None)
... # omitted stacktrace
HTTPError: 404 Client Error: {"http_status_code":404,"message":"Not found.","errors":[],"time":"2020-01-02T19:46:07Z","error_id":"gapi_asdf1234"} for url: https://rest.gadventures.com/departures/404_404
>>> dep = api.departures.get('404404')
>>> dep.start_address.country
<Country: BR (stub)>
>>> # lets have GAPI return a _404_ error here for the country stub `fetch`
>>> # when we attempt to retrieve the continent attribute
>>> dep.start_address.country.continent # reference/stub forces a fetch
>>> # pre 2.25.0 behaviour
... # omitted stacktrace
AttributeError: 'Country' has no field 'continent' available
>>> # post 2.25.0 behaviour
... # omitted stacktrace
HTTPError: 404 Client Error: {"http_status_code":404,"message":"Not found.","errors":[],"time":"2020-01-02T19:46:07Z","error_id":"gapi_qwer5678"} for url: https://rest.gadventures.com/countries/BR
Resources¶
Resource objects are instantiated from python dictionaries created from JSON data. The fields are parsed and converted to python objects as specified in the resource class.
A nested resource will only be instantiated when its corresponding attribute is
accessed in the parent resource. These resources may be returned as a stub
,
and upon access of an attribute not present, will internally call .fetch()
on the resource to populate it.
A field pointing to the URL for a collection of a child resources will hold a
Query
object for that resource. As for nested resources, it will only be
instantiated when it is first accessed.
Queries¶
A Query for a resource can be used to fetch resources of that type (either a single instance or an iterator over them, possibly filtered according to some conditions). Queries are roughly analogous to Django’s QuerySets.
An API client instance has a query object for each available resource (accessible by an attribute named after the resource name)
Methods on Query objects¶
All queries support the get
, create
and options
methods. The other methods are
only supported for queries whose resources are listable.
options()
- Get the options for a single resource
get(resource_id, [headers={}])
- Get a single resource; optionally passing in a dictionary of header values.
create(data)
- Create an instance of the query resource using the given data.
all([limit=n])
Generator over all resources in the current query. If
limit
is a positive integern
, then only the firstn
results will be returned.- A
TypeError
will be raised if limit is notNone
orint
type - A
ValueError
will be raised iflimit <= 0
>
- A
filter(field1=value1, [field2=value2, ...])
filter(**{"nested.field": "value"})
- Filter resources on the provided fields and values. Calls to
filter
can be chained. The method will return a clone of theQuery
object and must be stored in a separate variable in order to have access to stacked filters. count()
- Return the number of resources in the current query (by reading the
count
field on the response returned by requesting the list of resources in the current query).
Caching¶
gapipy
can be configured to use a cache to avoid having to send HTTP
requests for resources it has already seen. Cache invalidation is not
automatically handled: it is recommended to listen to G API webhooks to purge
resources that are outdated.
By default, gapipy
will use the cached data to instantiate a resource, but
a fresh copy can be fetched from the API by passing cached=False
to
Query.get
. This has the side-effect of recaching the resource with the
latest data, which makes this a convenient way to refresh cached data.
Caching can be configured through the cache_backend
and cache_options
settings. cached_backend
should be a string of the fully qualified path to
a cache backend, i.e. a subclass of gapipy.cache.BaseCache
. A handful of
cache backends are available out of the box:
gapipy.cache.SimpleCache
- A simple in-memory cache for single process environments and is not thread safe.
gapipy.cache.RedisCache
- A key-value cache store using Redis as a backend.
gapipy.cache.NullCache
(Default)- A cache that doesn’t cache.
Since the cache backend is defined by a python module path, you are free to use a cache backend that is defined outside of this project.
Connection Pooling¶
We use the requests
library, and you can take advantage of the provided
connection pooling options by passing in a 'connection_pool_options'
dict
to your client.
Values inside the 'connection_pool_options'
dict of interest are as
follows:
- Set
enable
toTrue
to enable pooling. Defaults toFalse
. - Use
number
to set the number of connection pools to cache. Defaults to 10. - Use
maxsize
to set the max number of connections in each pool. Defaults to 10. - Set
block
toTrue
if the connection pool should block and wait for a connection to be released when it has reachedmaxsize
. IfFalse
and the pool is already atmaxsize
a new connection will be created without blocking, but it will not be saved once it is used. Defaults toFalse
.
See also:
Testing¶
Running tests is pretty simple. We use nose as the test runner. You can install all requirements for testing with the following:
$ pip install -r requirements-testing.txt
Once installed, run unit tests with:
$ nosetests -A integration!=1
Otherwise, you’ll want to include a GAPI Application Key so the integration tests can successfully hit the API:
$ export GAPI_APPLICATION_KEY=MY_SECRET_KEY; nosetests
In addition to running the test suite against your local Python interpreter, you
can run tests using Tox. Tox allows the test suite
to be run against multiple environments, or in this case, multiple versions of
Python. Install and run the tox
command from any place in the gapipy source
tree. You’ll want to export your G API application key as well:
$ export GAPI_APPLICATION_KEY=MY_SECRET_KEY
$ pip install tox
$ tox
Tox will attempt to run against all environments defined in the tox.ini
. It
is recommended to use a tool like pyenv to
ensure you have multiple versions of Python available on your machine for Tox to
use.
Fields¶
_model_fields
represent dictionary fields like so:
Note: _model_fields = [('address', Address)]
and Address
subclasses BaseModel
"address": {
"street": "19 Charlotte St",
"city": "Toronto",
"state": {
"id": "CA-ON",
"href": "https://rest.gadventures.com/states/CA-ON",
"name": "Ontario"
},
"country": {
"id": "CA",
"href": "https://rest.gadventures.com/countries/CA",
"name": "Canada"
},
"postal_zip": "M5V 2H5"
}
_model_collection_fields
represent a list of dictionary fields like so:
Note: _model_collection_fields = [('emails', AgencyEmail),]
and AgencyEmail
subclasses BaseModel
"emails": [
{
"type": "ALLOCATIONS_RELEASE",
"address": "g@gadventures.com"
},
{
"type": "ALLOCATIONS_RELEASE",
"address": "g2@gadventures.com"
}
]
_resource_fields
refer to anotherResource
Contributing¶
- Run
pip install -r requirements-dev.txt
to setup dev dependencies - Always make your changes in a branch and submit a PR
- Once the PR has been accepted/merged into the
master
branch, follow these steps on your local box
$> cd /path/to/gapipy
$> git checkout master
$> git pull origin master
Then, modify the following files:
gapipy/__init__.py
- update the
__version__
variable - NOTES on incrementing the version:
major.minor.patch
- update
major
when we switch topython3
only support - update
minor
if there is some breaking change or adding a New resource - update
patch
when adding new fields, fixing bugs introduced by a minor release - See semver.org for more information.
- update the
HISTORY.rst
- update this file with the new
version
&date
- Add some brief notes describing the changes
- update this file with the new
- Check the generated long_description rST file is valid
$> python setup.py sdist
# this created `gapipy-a.b.c.tar.gz` in the `./dist` directory
# where a.b.c is the ``__version__`` value
$> twine check dist/gapipy-a.b.c.tar.gz
# checks the long-form rST file is valid
# if there are any errors fix, and repeat
# example success check
$> twine check dist/gapipy-a.b.c.tar.gz
Checking dist/gapipy-a.b.c.tar.gz: PASSED
- Push the new commit
- Use
Release a.b.c (YYYY-MM-DD)
format for the commit title. Optionally add a description that matches the changes toHISTORY.rst
- Create a release on github with the following description (This will be tagged to the
version bump
commit and not the PR commit)
# Version a.b.c
PR: #123
A brief description describing the changes
* bullet points
* make for easy reading
- Back to your local box
# build `gapipy-a.b.c.tar.gz` in the `./dist` directory
# where a.b.c is the ``__version__`` value
$> python setup.py sdist
# check the long-form rST file is valid
$> twine check dist/gapipy-a.b.c.tar.gz
$> twine upload dist/gapipy-a.b.c.tar.gz
# this will upload & create the release pypi
Thanks for helping!
History¶
2.26.2 (2020-04-20)¶
Fix for 2.26.1 (2020-04-20) and Issue #113. * See PR 125 * Remove the
_set_resource_collection_field
method inTourDossier
* Introducing the_Parent
namedtuple in PR 123 broke being able to Query-chain from Tour-Dossiers to departures * Buggy behaviour from2.26.1
below:>>> from gapipy import Client >>> api = Client(application_key='MY_SECRET_KEY') >>> api.tour_dossiers(24309).departures.count() # AttributeError: 'tuple' object has no attribute 'uri'
2.26.1 (2020-04-20)¶
- Fix for 2.26.0 (2020-04-14) and Issue #113.
* Calls to
APIRequestor.list_raw
will use initialised its parameters, unless the URI provides its own. * See PR 123. - Add the ability to define the
max_retries
values on the requestor. * Newenv
valueGAPI_CLIENT_MAX_RETRIES
. * The default value will be0
, and if provided will override theretry
value on therequests.Session
. * This change will also always initialize arequests.Session
value on initialisation of thegapipy.Client
. * See PR 124. - Add
variation_id
field to theImage
resource. * See Commit edc8d9b. - Update the
ActivityDossier
andAccommodationDossier
resources. * Remove theis_prepaid
field. * Adds thehas_costs
field. * See Commit bd35531.
2.26.0 (2020-04-14)¶
Breaking Changes
- The
Query.filter
method will return a clone/copy of itself. This will preserve the state offilters
on the original Query object. - The
Query.all
method will not clear the filters after returning. - The
Query.all
method will return aTypeError
if a type other than anint
is passed to thelimit
argument. - The
Query.count
method will not clear the filters after returning. - See PR 121
New behaviour with the Query.filter
method:
>>> from gapipy import Client
>>> api = Client(application_key='MY_SECRET_KEY')
# create a filter on the departures
>>> query = api.departures.filter(**{"tour_dossier.id": "24309"})
>>> query.count()
494
# we preserve the filter status of the current query
>>> query.filter(**{"availability.status": "AVAILABLE"}).count()
80
>>> query.count()
494
- The
AgencyChain.agencies
attribute returns a list ofAgency
objects * See Commit f34afd52
2.25.1 (2020-01-02)¶
- Improve contribution instructions to check long_description rST file in dist
- Dev Requirement updates:
* Add
readme_renderer==24.0
* Addtwine==1.15.0
fortwine check
command
2.25.0 (2020-01-02)¶
- Failing to fetch inlined Resource (from Stubs) will raise the underlying
requests.HTTPError instead of AttributeError resulting from a
None
. - Adds
httperrors_mapped_to_none
kwarg togapipy.query.Query.get
with default valuegapipy.query.HTTPERRORS_MAPPED_TO_NONE
- Modifies
gapipy.resources.base.Resource.fetch
to passhttperrors_mapped_to_none=None
toQuery.get
- This ensures that any underlying
requests.HTTPError
fromQuery.get
is bubbled up to the caller. It is most prevalent when reference Resource stubs fail to be retrieved from the G API. Prior to this changeResource.fetch
would return aNone
value resulting in anAttributeError
. Now, if the stub fails to fetch due to an HTTPError, that will be raised instead
2.24.3 (2019-12-12)¶
- Exclude the
tests
package from the package distribution
2.24.2 (2019-12-12)¶
- Adds the
compute_request_signature
andcompute_webhook_validation_key
utility methods * See https://github.com/gadventures/gapipy/pull/122
2.24.1 (2019-12-12)¶
- Add
slug
field toTourDossier
resource * See https://github.com/gadventures/gapipy/pull/120
2.24.0 (2019-11-05)¶
- Add missing/new fields to resources * Accommodation Dossier: categories, suggested_dossiers, visited_countries, and visited_cities * Activity Dossier: suggested_dossiers, visited_countries, and visited_cities * Departure: local_payments * Itinerary: publish_state * See https://github.com/gadventures/gapipy/pull/117
- Add
continent
andplace
references to theCountries
resource * See https://github.com/gadventures/gapipy/pull/115 - Accept
additional_headers
optional kwarg oncreate
* See https://github.com/gadventures/gapipy/pull/114
2.23.0 (2019-11-04)¶
- Remove deprecated
tour_dossiers.itineraries
field and related code
2.22.0 (2019-10-10)¶
- Add
booking_company
field toBooking
resource
2.21.0 (2019-04-09)¶
- Add
ripple_score
toItinerary
resource
2.20.1 (2019-02-20)¶
- HISTORY.rst doc fixes
2.20.0 (2019-02-20)¶
- Add
Requirement
andRequirementSet
resources - Move
Checkin
resource to theresources.booking
module - The
Query
object will resolve to use thehref
value when returning the iterator to fetchall
of some resource. This is needed becausebookings/123456/requirements
actually returns a list ofRequirementSet
resources - see https://github.com/gadventures/gapipy/releases/tag/2.20.0 for more details
2.19.4 (2019-02-14)¶
- Add
get_category_name
helper method toTourDossier
resource
2.19.3 (2019-02-12)¶
- Attempt to fix rST formatting of
README
andHISTORY
on pypi
2.19.2 (2019-02-12)¶
- Become agnostic between redis 2.x.x && 3.x.x versions
- the
setex
method argument order changes between the major versions
- the
2.19.1 (2019-02-12)¶
- HotFix for
2.19.0
– addsrequirements.txt
file to the distributionMANIFEST
2.19.0 (2019-02-12)¶
- Add
booking_companies
field toItinerary
resource - Pin our requirement/dependency versions
- pin
future == 0.16.0
- pin
requests >= 2.18.4, < 3.0.0
- read
setup.py
requirements fromrequirements.txt
- pin
2.18.1 (2019-02-07)¶
- Add
customers
nested resource tobookings
2.18.0 (2018-12-14)¶
- Add
merchandise
resource - Add
merchandise_services
resources
2.17.0 (2018-11-12)¶
- Add
membership_programs
field to theCustomer
resource
2.16.0 (2018-11-07)¶
- Completely remove the deprecated
add_ons
field from the Departure resource - Add missing fields to various Dossier resources
- Accommodation Dossier:
flags
,is_prepaid
,service_time
,show_on_reservation_sheet
- Activity Dossier:
is_prepaid
,service_time
,show_on_reservation_sheet
- Country Dossier:
flags
- Place Dossier:
flags
- Transport Dossier:
flags
- Accommodation Dossier:
- Add
valid_during_ranges
list field to the Itinerary resource. This field is a list field of the newly addedValidDuringRange
model (described below) - Add
ValidDuringRange
model. It consists of two date fields,start_date
, andend_date
. It also provides a number of convenience methods to determine if the date range provided is valid, or relative to some date.is_expired
: Is it expired relative todatetime.date.today
(occurs in the past)is_valid_today
: Is it valid relative todatetime.date.today
is_valid_during_range
: Is it valid for some give start/end date rangeis_valid_on_or_after_date
: Is it valid on or after some dateis_valid_on_or_before_date
: Is it valid on or before some dateis_valid_on_date
: Is it valid on some dateis_valid_sometime
: Is it valid at all
2.15.0 (2018-10-10)¶
- Add
country
reference toNationality
resource - Moved
resources/bookings/nationality.py
toresources/geo/*
2.14.6 (2018-08-01)¶
- Check for presence of
id
field directly in the Resource__dict__
in order to prevent a chicken/egg situation when attempting tosave
. This is needed due to the change introduced in 2.14.4, where we explicitly raise an AttributeError when trying to access theid
attribute. - Added
service_code
field for Activty & Accommodation Dossier resources
2.14.5 (2018-08-01)¶
- deleted
2.14.4 (2018-07-13)¶
- Raise an AttributeError when trying to access id on Resource.__getattr__
- Don’t send duplicate params when paginating through list results
- Implement first() method for Query
2.14.3 (2018-05-29)¶
- Expose Linked Bookings via the API
2.14.1 (2018-05-15)¶
- Add
booking_companies
field to Agency resource - Remove
bookings
field from Agency resource - Add
requirements
as_is field to Departure Service resource - Add
policy_emergency_phone_number
field to Insurance Service resource
2.14.0 (2018-05-15)¶
- Remove deprecated
add_ons
field fromDeparture
resource - Add
costs
field toAccommodation & Activity Dossier
resources
2.13.0 (2018-03-31)¶
- Add
meal_budgets
list field toCountry Dossier
resource - Add
publish_state
field toDossier Features
resource
2.12.0 (2018-02-14)¶
- Add optional
headers
parameter to Query.get to allow HTTP-Headers to be passed. e.g.client.<resource>.get(1234, headers={'A':'a'})
(PR/91) - Add
preferred_display_name
field to Agency resource (#92) - Add
booking_companies
array field to all Product-type Resources. (PR/93)- Accommodation
- Activity
- AgencyChain
- Departure
- SingleSupplement
- TourDossier
- Transport
2.11.4 (2018-01-29)¶
- Add
agency_chain
field toBooking
resource - Add
id
field as part of theDossierDetail
model (PR/89) - Add
agency_chains
field to theAgency
resource (PR/90) - see https://github.com/gadventures/gapipy/releases/tag/2.11.3 for more details
2.11.0 (2017-12-18)¶
- The Customer Address uses
Address
model, and is no longer a dict. - Passing in
uuid=True
toClient
kwargs enablesuuid
generation for every request.
2.10.0 (2017-12-01)¶
- Add the
amount_pending
field to theBooking
resource - The
PricePromotion
model extends from thePromotion
resource (PR/85) - Update the
Agent
class to use BaseModel classes for therole
andphone_numbers
fields. - see https://github.com/gadventures/gapipy/releases/tag/2.10.0 for more details
2.9.3 (2017-11-23)¶
- Expose
requirement_set
fordeparture_services
andactivity_services
. - NOTE: We have skipped
2.9.2
due to pypi upload issues.
2.9.1 (2017-11-22)¶
- Adds the
options
method on the Resource Query object. A more detailed description of the issue can be found at: https://github.com/gadventures/gapipy/releases/tag/2.9.1 - NOTE: We have skipped
2.9.0
due to pypi upload issues
2.8.2 (2017-11-14)¶
- Adds fields
sale_start_datetime
andsale_finish_datetime
to the Promotion resource. The fields mark the start/finish date-time values for when a Promotion is applicable. The values represented are in UTC.
2.8.1 (2017-10-25)¶
- Add new fields to the
Agency
andAgencyChain
resources
2.8.0 (2017-10-23)¶
This release adds a behaviour change to the
.all()
method on resource Query objects. Prior to this release, the base Resource Query object would retain any previously addedfilter
values, and be used in subsequent calls. Now the underlying filters are reset after a<resource>.all()
call is made.A more detailed description of the issue and fix can be found at:
Adds missing fields to the Agency and Flight Service resources (PR/78)
2.7.6 (2017-10-04)¶
- Add
agency
field toBooking
resource.
2.7.5 (2017-09-25)¶
- Add test fix for Accommodation. It is listable resource as of
2.7.4
- Add regression test for departures.addon.product model
* Ensure Addon’s are instantiated to the correct underlying model.
* Prior to this release, all Addon.product resources were instantiated as
Accommodation
.
2.7.4 (2017-09-20)¶
- Add
videos
,images
, andcategories
to Activity, Transport, Place, and, Accommodation Dossier resources. - Add
flags
to Itinerary resource - Add list view of
Accommodations
resource
2.7.3 (2017-09-06)¶
- Add
type
field toAgencyDocument
model - Add
structured_itinerary
model collection field toDeparture
resource
2.7.2 (2017-08-18)¶
- Fix flight_status Reference value in FlightService resource
2.7.1 (2017-08-18)¶
- Fix: remove FlightStatus import reference for FlightService resource
- Add fields (fixes two broken Resource tests)
- Add
href
field forcheckins
resource - Add
date_cancelled
field fordepartures
resource
- Add
- Fix broken UpdateCreateResource tests
2.7.0 (2017-08-18)¶
- Remove
flight_statuses
andflight_segments
resources.
2.6.2 (2017-08-11)¶
- Version bump
2.6.1 (2017-08-11)¶
- Adds a Deprecation warning when using the
tours
resource.
2.6.0 (2017-08-11)¶
- Fixed issue 65: only write data into the local cache after a fetch from the API, do not write data into the local cache when fetching from the local cache.
2.5.2 (2017-04-26)¶
- Added
future
dependency to setup.py
2.5.1 (2017-02-08)¶
- Fixed an issue in which modifying a nested dictionary caused gapipy to not identify a change in the data.
- Added
tox.ini
for testing across Python platforms. - Capture
403
Status Codes as aNone
object.
2.5.0 (2017-01-20)¶
- Provided Python 3 functionality (still Python 2 compatible)
- Removed Python 2 only tests
- Installed
future
module for smooth Python 2 to Python 3 migration - Remove
DictToModel
class and the associated tests - Add
Dossier
Resource(s) - Minor field updates to:
Customer
,InsuranceService
,DepartureService
,Booking
,FlightStatus
,State
2.4.9 (2016-11-22)¶
- Fixed a bug with internal
_get_uri
function.
2.4.8 (2016-11-11)¶
- Adjusted
Checkin
resource to meet updated spec.
2.4.7 (2016-10-25)¶
- Added
Checkin
resource.
2.4.6 (2016-10-19)¶
- Fix broken
Duration
init inActivityDossier
(likely broke due to changes that happened in 2.0.0)
2.4.5 (2016-10-13)¶
- Added
Image
resource definition and put it to use inItinerary
and,PlaceDossier
2.4.4 (2016-09-09)¶
- Added
date_last_modified
anddate_created
toPromotion
.
2.4.3 (2016-09-06)¶
- Added
gender
toCustomer
. - Added
places_of_interest
toPlace
.
2.4.2 (2016-07-08)¶
- Added
departure
reference toDepartureComponent
2.4.1 (2016-07-06)¶
- Removed use of
.iteritems
wherever present in favour of.items
- Added
features
representation toActivityDossier
and,TransportDossier
2.4.0 (2016-06-29)¶
- Added
CountryDossier
resource.
2.3.0 (2016-06-28)¶
- Added
DossierSegment
resource. - Added
ServiceLevel
resource.
2.2.2 (2016-06-08)¶
- Added day
label
field to theItinerary
resource.
2.2.1 (2016-06-06)¶
- Added
audience
field to theDocument
resource.
2.2.0 (2016-05-17)¶
- Added
transactional_email
, andemails
toAgency
resource.
2.1.2 (2016-05-17)¶
- Added
audience
toInvoice
resource.
2.1.1 (2016-04-29)¶
- Removed invalid field,
email
fromAgencyChain
2.1.0 (2016-04-25)¶
- Added new resource,
AgencyChain
2.0.0 (2016-03-11)¶
The global reference to the last instantiated Client has been removed. It is now mandatory to pass in a Client instance when instantiating a Model or Resource.
In practice, this should not introduce too much changes in codebases that are
using gapipy
, since resources are mostly interacted with through a Client
instance (for example, api.tours.get(123)
, or
api.customers.create({...})
), instead of being instantiated independently.
The one possible exception is unit testing: in that case, Client.build
can
be useful.
The global variable was causing issues with connection pooling when multiple client with different configurations were used at the same time.
1.1.0 (2016-03-11)¶
- Added new resource,
DossierFeature
1.0.0 (2016-02-29)¶
- Adopted Semantic Versioning for this project.
- Refactored how the cache key is set. This is a breaking change for any
modules that implemented their own cache interface. The cache modules are
no longer responsible for defining the cache value, but simply storing
whatever it is given into cache. The
Query
object now introduces aquery_key
function which generates the cache key sent to the cache modules.
0.6.3 (2016-01-21)¶
- Added better error handling to Client.build. An AttributeError raised when instantiating a resource won’t be shadowed by the except block anymore.
0.6.2 (2016-01-20)¶
- Fixed a regression bug when initializing DepartureServiceRoom model.
0.6.1 (2016-01-20)¶
- Fixed a regression bug when initializing services.
0.6.0 (2016-01-20)¶
- Fixed a bug when initializing list of resources.
0.5.5 (2016-01-08)¶
- Added a component of type
ACCOMMODATION
toItineraries
.
0.5.4 (2016-01-04)¶
- Added
associated_services
toSingleSupplementService
0.5.3 (2015-12-31)¶
- Added
name
toDeparture
. - Happy New Year!
0.5.2 (2015-12-15)¶
- Added
variation_id
toBaseCache
to fix aTypeError
when using theNullCache
0.5.1 (2015-12-14)¶
- Add
associated_agency
tobookings
resource
0.5.0 (2015-12-10)¶
- Minor adjusted in Query internals to ensure the
variation_id
of an Itinerary is handled properly. - Added
ItineraryHighlights
andItineraryMedia
resources. These are sub resources of theItinerary
0.4.6 (2015-12-09)¶
- Added connection pool caching to
RedisCache
. Instances ofgapipy
with the same cache settings (in the same Python process) will share a connection pool.
0.4.5 (2015-11-05)¶
- Added
code
field to thetype
of anItinerary
’s listeddetails
.
0.4.4 (2015-11-04)¶
- Added the
details
field to theItinerary
resource – a list of textual details about an itinerary.
0.4.3 (2015-11-03)¶
- Added the
tour_dossier
field to theItinerary
resource.
0.4.2 (2015-10-28)¶
- Fixed a bug that would cause
amount
when looking atPromotion
objects in theDeparture
to be removed from the data dict.
0.4.1 (2015-10-16)¶
- Moved an import of
requests
down from the module level. Fixes issues in CI environments.
0.4.0 (2015-10-13)¶
- Added connection pooling options, see docs for details on
connection_pool_options
.
0.3.0 (2015-09-24)¶
- Modified how the
Promotion
object is loaded withinprice_bands
on aDeparture
. It now correctly captures theamount
field.
0.2.0 (2015-09-15)¶
- Modified objects within
cache
module to handlevariation_id
, which is exposed within theItinerary
object. Previously, theItinerary
would not be correctly stored in cache with its variant reference.
0.1.51 (2015-08-31)¶
- Added the
components
field to theDeparture
resource.
0.1.50 (2015-07-28)¶
- Fixed an issue with the default
gapipy.cache.NullCache
whenis_cached
was used.
0.1.49 (2015-07-23)¶
- Added new fields to
Itinerary
revolving around variations. - Added
declined_reason
to all service resources.
0.1.48 (2015-07-15)¶
- Add DeclinedReason resource
0.1.47 (2015-07-08)¶
- Fixed a bug in
APIRequestor.get
. Requesting a resource with with an id of0
won’t raise an Exception anymore.
0.1.46 (2015-06-10)¶
- Added
associated_services
andoriginal_departure_service
to various service resources anddeparture_services
model respectively.
0.1.45 (2015-05-27)¶
- Fixed
products
within thePromotion
resource to properly retaintype
andsub_type
fields after being parsed into a dictionary.
0.1.44 (2015-05-22)¶
- Changed default cache_backend to use gapipy.cache.NullCache. Previously, SimpleCache was the default and led to confusion in production environments, specifically as to why resources were not matching the API output. Now, by default, to get any caching from gapipy you must explicitly set it.
0.1.43 (2015-04-29)¶
- Fixed Place init with empty admin_divisions
0.1.42 (2015-04-29)¶
- Added description to TourCategory resource.
0.1.41 (2015-04-14)¶
- Added DepartureComponent resource. See the [official G API documentation for details](https://developers.gadventures.com/docs/departure_component.html)
0.1.40 (2015-04-06)¶
- Added deposit to DepartureService model
0.1.39 (2015-03-31)¶
- Refactor
APIRequestor._request
. While this should not change existing functionality, it is now possible to override specific methods onAPIRequestor
if needed.
0.1.38 (2015-03-23)¶
- Fixed: Due to inconsistencies in the G API with regards to nested resources, the fetch function was modified to use the raw data from the API, rather than a specific set of allowed fields.
0.1.37 (2015-03-23)¶
- Fixed: Iterating over
products
within thepromotions
object now works as expected. Previously, accessing theproducts
attribute would result in a Query object with incorrect parameters.
0.1.36 (2015-03-17)¶
- Support free to amount price range formatting (e.g. Free-10CAD)
0.1.35 (2015-03-12)¶
- Added duration_min & duration_max to ActivityDossier model
0.1.34 (2015-03-11)¶
- Added OptionalActivity model
- All Dossiers with details: * Now represented as list of DossierDetail models * Added convenience methods for retrieving specific details
- ItineraryComponent and ActivityDossier use new Duration model for their duration field/property
- Added duration_label and location_label to ItineraryComponent
- Added duration_label, price_per_person_label, and price_per_group_label to ActivityDossier
0.1.33 (2015-03-02)¶
- Added name field to the Itinerary resource.
0.1.32 (2015-02-18)¶
- Changed cache key creation to account for GAPI_LANGUAGE when the environment variable is set.
0.1.31 (2015-02-18)¶
- Fixed a bug when setting _resource_fields in
DepartureService
resource
0.1.30 (2015-02-11)¶
TourDossier.structured_itineraries
now refers to a list of Itinerary resources
0.1.29 (2015-02-10)¶
- Added
TransportDossier
andItinerary
resources. - The reference to the itinerary in a
DepartureService
is now a full-fledgedItinerary
resource.
0.1.28 (2015-01-22)¶
- Bug fix to correctly send
Content-Type: application/json
in POST, PUT, or PATCH.
0.1.27 (2015-01-19)¶
- Update
DepartureService
object to contain a reference to itsItinerary
0.1.26 (2015-01-14)¶
- Normalize API request headers, to promote caching.
0.1.25 (2015-01-09)¶
- Added
ActivityDossier
andAccommodationDossier
resources, as well as references to it fromActivity
andAccommodation
.
0.1.24 (2015-01-07)¶
- Added
PlaceDossier
resource, as well as reference to it fromPlace
0.1.22 (2014-12-12)¶
- Added
advertised_departures
toTourDossier
0.1.21 (2014-11-26)¶
- Fixed a bug with promotions on a Price object. When promotions were accessed, gapipy would query for all promotions, rather than returning the inline list.
0.1.20 (2014-11-20)¶
- Departure resource is now listable via filters.
0.1.19 (2014-11-17)¶
- Fixed a bug with RedisCache.is_cached where it would not use the set key_prefix when checking for existence in cache. Effectively, it would always return False
0.1.18 (2014-11-12)¶
- When setting a date_field, initiate it as a datetime.date type.
0.1.17 (2014-11-07)¶
- Deprecated RedisHashCache from cache backends available by default. Was not well tested or reliable.
0.1.16 (2014-10-28)¶
- Fixed a bug where if a model field received null as a value, it would fail. Now, if the result is null, the model field will have an appropriate None value.
0.1.15 (2014-10-23)¶
- Fix a bug in the DepartureRoom model. The price_bands attribute is now properly set.
0.1.14 (2014-10-22)¶
- Fixed a bug where AgencyDocument was not included in the code base.
0.1.13 (2014-10-21)¶
- Add
latitude
,longitude
, anddocuments
to theAgency
resource.
0.1.12 (2014-10-20)¶
date_created
on theAgency
resource is correctly parsed as a local time.
0.1.11 (2014-10-15)¶
- Improve the performance of
Resource.fetch
by handling cache get/set.
0.1.10 (2014-10-09)¶
- Fix a bug in AccommodationRoom price bands. The season_dates and blackout_dates attributes are now properly set.
0.1.9 (2014-09-23)¶
- Add iso_639_3 and iso_639_1 to Language
0.1.8 (2014-09-17)¶
- Remove the add_ons field in Departure, and add addons.
0.1.7 (2014-08-22)¶
- Fix a bug when initializing AccommodationRoom from cached data.
0.1.6 (2014-08-19)¶
- Add Query.purge_cached
0.1.5 (2014-07-29)¶
- Add details field to the list of incomplete_requirements in a DepartureService.
0.1.4 (2014-07-21)¶
- Removed sending of header X-HTTP-Method-Override: PATCH when the update command is called. Now, when .save(partial=True) is called, the correct PATCH HTTP method will be sent with the request.
0.1.3 (2014-07-18)¶
- Return
None
instead of raising a HTTPError 404 exception when fetching a non-existing resource by id. - Added ability to create resources from the Query objects on the client
instance.
e.g.:
api.customers.create({'name': {'legal_first_name': 'Pat', ...}, ...})
0.1.2 (2014-07-14)¶
- Added Query.is_cached
- Added cache options
0.1.1 (2014-06-27)¶
- Use setuptools find_packages
0.1.0 (2014-06-20)¶
- First release on PyPI.