G API Python Client
.. image:: https://badge.fury.io/py/gapipy.svg
:target: http://badge.fury.io/py/gapipy
A client for the G Adventures REST API (https://developers.gadventures.com)
Quick Start
.. code-block:: python
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)
_
.. code-block:: python
since 2.25.0 reference stubs that fail to fetch will return a
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 integer n
, then only the first n
results will be returned.
- A
TypeError
will be raised if limit is not None
or int
type - A
ValueError
will be raised if limit <= 0
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 the Query
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.
.. _webhooks: https://developers.gadventures.com/docs/webhooks.html
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.
gapipy.cache.DjangoCache
(requires Django)
A cache which uses Django's cache settings for configuration. Requires there
be a gapi
entry in settings.CACHES
.
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
to True
to enable pooling. Defaults to False
. - 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
to True
if the connection pool should block and wait
for a connection to be released when it has reached maxsize
. If
False
and the pool is already at maxsize
a new connection will
be created without blocking, but it will not be saved once it is used.
Defaults to False
.
See also:
Dependencies
The only dependency needed to use the client is requests_.
.. _requests: http://python-requests.org
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 <http://tox.testrun.org>
_. 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 <https://github.com/yyuu/pyenv>
_ to
ensure you have multiple versions of Python available on your machine for Tox to
use.
Fields
_model_fields
represent dictionary fields.
.. note::
_model_fields = [('address', Address)]
ANDAddress
subclasses BaseModel
.. code-block:: python
{
"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.
.. note::
_model_collection_fields = [('emails', AgencyEmail),]
ANDAgencyEmail
subclasses BaseModel
.. code-block:: python
{
"emails": [
{
"type": "ALLOCATIONS_RELEASE",
"address": "g@gadventures.com"
},
{
"type": "ALLOCATIONS_RELEASE",
"address": "g2@gadventures.com"
}
]
}
_resource_fields
refer to another Resource
Contributing
.. note:: Ensure a Python 2 environment
-
Clone the project
.. code-block:: sh
$ git clone git@github.com:gadventures/gapipy
-
Run pip install -r requirements-dev.txt
to setup dev dependencies.
-
Always make your changes in a branch and to submit a PR.
.. code-block:: sh
$ git checkout master
$ git pull
$ git checkout -b feature-branch-name
$ git push origin feature-branch-name
-
Once the PR has been accepted/merged into the master
branch, follow
these steps.
.. code-block:: sh
$ cd /path/to/gapipy
$ git checkout master
$ git pull origin master
Modify the following files:
-
Update gapipy/init.py
- increment the
__version__
variable
.. note::
* style ``major.minor.patch``
* update ``patch`` when adding new fields, fixing bugs introduced by a
minor release.
* update ``minor`` if there is some breaking change such as adding a new
resource, removing fields, adding new behaviour.
* update ``major`` when we switch to ``Python 3`` only support.
* See `semver.org <https://semver.org>`_ for more information.
-
Update HISTORY.rst
- update this file with the new
version
& date
- Add some brief notes describing the changes.
-
Use make dist
to check the generated long_description rST file is valid.
.. note::
- ignore
warning: no previously-included files matching
messages. - as long as you get a
Checking dist/gapipy-a.b.c.tar.gz: PASSED
message, you are good! - If not, fix the errors as dictated in the output, and repeat.
Example output when running make dist
:
.. code-block:: sh
$ make dist
warning: no previously-included files matching '' found under directory 'tests'
warning: no previously-included files matching 'pycache' found under directory ''
warning: no previously-included files matching '.eggs' found under directory ''
warning: no previously-included files matching '.py[co]' found under directory '*'
total 123
-rw-r--r-- 1 user group 76276 5 Feb 02:53 gapipy-a.b.c.tar.gz
Checking dist/gapipy-a.b.c.tar.gz: PASSED
-
Push the new Release commit
- Use Release a.b.c (YYYY-MM-DD) format for the commit title. Optionally
add a description that matches the changes made to HISTORY.rst.
-
Create a release on github with the following description (This will be
tagged to the Release
commit and not the PR/change commit)
.. code-block:: md
Release a.b.c (YYYY-MM-DD)
PR: #123
A brief description describing the changes
- bullet points
- make for easy reading
-
Release!
$ make release
Thanks for helping!
History
2.36.0 (2024-05-30)
- Add
contact_us
field to the AgenchChain
resource. This field can be
None
, however should a value be present, it will be an object with three
accessible attributes: email
, phone_number
, and website_url
. See
the PR #141
_ for more details.
.. _PR #141
: https://github.com/gadventures/gapipy/pull/141
2.35.0 (2022-04-18)
-
Add new Client
configuration value that will raise an error when an empty
partial update (PATCH) payload is computed by gapipy. See Issue #136
_ and
the corresponding PR #137
_ for more details.
-
The new Client configuration kwarg is raise_on_empty_update
, whose
default value is False
, and can also be set by passing it as an
environment variable GAPI_CLIENT_RAISE_ON_EMPTY_UPDATE
. If this config
value is set, then a call to Resource.save
with partial=True
will
raise the new EmptyPartialUpdateError
if an empty payload is computed.
.. code-block:: python
from gapipy import Client
gapi = Client(application_key="your_api_key", raise_on_empty_update=True)
departure_service = gapi.departure_services.get(123456)
we've changed nothing and are calling a partial save (PATCH)
NOTE: the new EmptyPartialUpdateError will be raised here
departure_service.save(partial=True)
.. _Issue #136
: https://github.com/gadventures/gapipy/issues/136
.. _PR #137
: https://github.com/gadventures/gapipy/pull/137
2.34.0 (2021-08-20)
- Add
travel_ready_policy
model field to the Departure
resource. - More details can be found in our developer documentation.
c.f.
Departure travel-ready-policy
_
.. _Departure travel-ready-policy
: https://developers.gadventures.com/docs/departure.html#travel-ready-policy
2.33.0 (2021-07-06)
- Add
online_preferences
field to the Agency Chain
resource.
2.32.0 (2021-06-18)
- Make
future
requirement more flexible. See PR #134
_ for more details.
.. _PR #134
: https://github.com/gadventures/gapipy/pull/134
2.31.1 (2021-05-14)
- Initialize the
DjangoCache
via the BaseCache
which exposes the
default_timeout
attribute to the class. Prior to this change, when using
the DjangoCache
, items would persist forever as no timeout would be set
on the entries. See PR #133
_ for more details.
.. note:: DjangoCache
was introduced in 2.30.0 (2021-02-08)
_
.. _PR #133
: https://github.com/gadventures/gapipy/pull/133
2.31.0 (2021-03-02)
-
Introduce gapipy.constants
module that holds common constants. See
PR #132
_ for more details.
-
Reintroduce the ability to enable old behaviour (pre 2.25.0 (2020-01-02)
)
for Resource.fetch
. It adds an optional httperrors_mapped_to_none
parameter to the method (default None
), where if a list of HTTP Status
codes is provided instead, will silently consume errors mapped to those
status codes and return a None
value instead of raising the HTTPError.
See PR #131
for more details.
.. _PR #131
: https://github.com/gadventures/gapipy/pull/131
.. _PR #132
: https://github.com/gadventures/gapipy/pull/132
2.30.1 (2021-02-08)
- Fix for
2.30.0 (2021-02-08)
_ Adds a guard against configuring Django
settings again as per the Django settings docs
. See PR #130
for more
details.
.. _Django settings docs
: https://docs.djangoproject.com/en/3.1/topics/settings/#either-configure-or-django-settings-module-is-required
.. _PR #130
: https://github.com/gadventures/gapipy/pull/130
2.30.0 (2021-02-08)
- Adds a new cache backend;
gapipy.cache.DjangoCache
. It requires Django
and a gapi
entry in settings.CACHES
. See PR #129
_ for more details.
.. _PR #129
: https://github.com/gadventures/gapipy/pull/129/
Usage:
- Set the
GAPI_CACHE_BACKEND
Env varible to gapipy.cache.DjangoCache
.
OR
.. code-block:: python
from gapipy import Client
gapi = Client(
application_key="live_your-secret-gapi-key",
cache_backend="gapipy.cache.DjangoCache",
)
2.29.0 (2021-02-05)
- Adds
Departure.relationships
field via DepartureRelationship
model - Adds
TourDossier.relationships
field via TourDossierRelationship
model
.. warning:: BREAKING!
-
Moves the gapipy.resources.tour.itinerary.ValidDuringRange
class over to
its own file gapipy.models.valid_duraing_range.ValidDuringRange
so that it can be reused by the TourDossierRelationship
model. Any code
importing the class directly will need to change the import path:
.. code-block:: python
# before
from gapipy.resources.tour.itinerary.ValidDuringRange
# now
from gapipy.models import ValidDuringRange
-
See PR #128
_ for more details.
.. _PR #128
: https://github.com/gadventures/gapipy/pull/128/
2.28.0 (2020-11-23)
-
Add a new Client
config option, global_http_headers
, a dict of HTTP
headers to add to each request made with that client.
This is similar to the headers=
kwargs available when making get
and
create
calls, except that the global_http_headers
set on a client
will apply on every request made by that client instance.
2.27.0 (2020-05-26)
.. warning:: BREAKING!
- Make
Customer.nationality
a resource field. This allows attribute style
access to the field values, whereas before they needed to be accessed using
dictionary accessor (d["key"]
) syntax.
.. code-block:: python
before
api.customers.get(123456).nationality["name"]
u'Canadian'
now
api.customers.get(123456).nationality.name
u'Canadian'
2.26.4 (2020-04-28)
- Fix
2.26.3 (2020-04-28) (Yanked)
_: Add missing CONTRIBUTING.rst
to the
manifest.
.. note:: Discovered when attempting to install gapipy
via pip
.
2.26.3 (2020-04-28) (Yanked)
- Fix py2 & py3 compatibility for
urlparse
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 in TourDossier
- Introducing the
_Parent
namedtuple in PR #123
_.
broke being able to Query-chain from Tour-Dossiers to departures - Buggy behaviour fixed from
2.26.1 (2020-04-20)
_
.. code-block:: python
>>> from gapipy import Client
>>> api = Client(application_key='MY_SECRET_KEY')
>>> api.tour_dossiers(24309).departures.count()
# AttributeError: 'tuple' object has no attribute 'uri'
.. _PR #125
: https://github.com/gadventures/gapipy/pull/125
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.
- New
env
value GAPI_CLIENT_MAX_RETRIES
. - The default value will be
0
, and if provided will override the retry
value on the requests.Session
. - This change will also always initialize a
requests.Session
value on
initialisation of the gapipy.Client
. - See
PR #124
_.
-
Add variation_id
field to the Image
resource.
-
Update the ActivityDossier
and AccommodationDossier
resources.
- Remove the
is_prepaid
field. - Adds the
has_costs
field. - See
Commit bd35531
_.
.. _Issue #113
: https://github.com/gadventures/gapipy/issues/113
.. _PR #123
: https://github.com/gadventures/gapipy/pull/123
.. _PR #124
: https://github.com/gadventures/gapipy/pull/124
.. _Commit edc8d9b
: https://github.com/gadventures/gapipy/commit/edc8d9b
.. _Commit bd35531
: https://github.com/gadventures/gapipy/commit/bd35531
2.26.0 (2020-04-14)
.. warning:: BREAKING!
- The
Query.filter
method will return a clone/copy of itself. This will
preserve the state of filters
on the original Query object. - The
Query.all
method will not clear the filters after returning. - The
Query.all
method will return a TypeError
if a type other than
an int
is passed to the limit
argument. - The
Query.count
method will not clear the filters after returning. - See
PR #121
_ for more details.
New behaviour with the Query.filter
method:
.. code-block:: python
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 of Agency
objects.
See Commit f34afd52
_.
.. _PR #121
: https://github.com/gadventures/gapipy/pull/121
.. _Commit f34afd52
: https://github.com/gadventures/gapipy/commit/f34afd52
2.25.1 (2020-01-02)
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 to gapipy.query.Query.get
with default value gapipy.query.HTTPERRORS_MAPPED_TO_NONE
- Modifies
gapipy.resources.base.Resource.fetch
to
pass httperrors_mapped_to_none=None
to Query.get
- This ensures that any underlying
requests.HTTPError
from Query.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 change Resource.fetch
would return a None
value resulting in an AttributeError
. 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
and compute_webhook_validation_key
utility methods. See PR #122
_.
.. _PR #122
: https://github.com/gadventures/gapipy/pull/122
2.24.1 (2019-12-12)
- Add
slug
field to TourDossier
resource. See PR #120
_.
.. _PR #120
: https://github.com/gadventures/gapipy/pull/120
2.24.0 (2019-11-05)
-
Add missing/new fields to the following resources. See PR #117
_.
- AccommodationDossier:
categories
, suggested_dossiers
, visited_countries
, visited_cities
- ActivityDossier:
suggested_dossiers
, visited_countries
, visited_cities
- Departure:
local_payments
- Itinerary:
publish_state
-
Add continent
and place
references to the Countries
resource. See
PR #115
_.
-
Accept additional_headers
optional kwarg on create
. See PR #114
_.
.. _PR #114
: https://github.com/gadventures/gapipy/pull/114
.. _PR #115
: https://github.com/gadventures/gapipy/pull/115
.. _PR #117
: https://github.com/gadventures/gapipy/pull/117
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 to Booking
resource
2.21.0 (2019-04-09)
- Add
ripple_score
to Itinerary
resource
2.20.1 (2019-02-20)
2.20.0 (2019-02-20)
- Add
Requirement
and RequirementSet
resources - Move
Checkin
resource to the resources.booking
module - The
Query
object will resolve to use the href
value when
returning the iterator to fetch all
of some resource. This is
needed because bookings/123456/requirements
actually returns a list
of RequirementSet
resources - See
Release tag 2.20.0
_ for more details.
.. _Release tag 2.20.0
: https://github.com/gadventures/gapipy/releases/tag/2.20.0
2.19.4 (2019-02-14)
- Add
get_category_name
helper method to TourDossier
resource
2.19.3 (2019-02-12)
- Attempt to fix rST formatting of
README
and HISTORY
on pypi
2.19.2 (2019-02-12)
2.19.1 (2019-02-12)
.. note:: HotFix for 2.19.0 (2019-02-12)
_.
- adds
requirements.txt
file to the distribution MANIFEST
2.19.0 (2019-02-12)
2.18.1 (2019-02-07)
- Add
customers
nested resource to bookings
2.18.0 (2018-12-14)
- Add
merchandise
resource - Add
merchandise_services
resources
2.17.0 (2018-11-12)
- Add
membership_programs
field to the Customer
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
- AccommodationDossier:
flags
, is_prepaid
, service_time
, show_on_reservation_sheet
- ActivityDossier:
is_prepaid
, service_time
, show_on_reservation_sheet
- CountryDossier:
flags
- PlaceDossier:
flags
- TransportDossier:
flags
-
Add valid_during_ranges
list field to the Itinerary resource. This field is
a list field of the newly added ValidDuringRange
model (described below)
-
Add ValidDuringRange
model. It consists of two date fields, start_date
,
and end_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 to datetime.date.today
is_valid_today
: Is it valid relative to datetime.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 to Nationality
resource. - Moved
resources/bookings/nationality.py
to resources/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 to save
. This is
needed due to the change introduced in 2.14.4, where we explicitly raise an
AttributeError when trying to access the id
attribute. - Added
service_code
field for Activty & Accommodation Dossier resources.
2.14.5 (2018-08-01)
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 from Departure
resource. - Add
costs
field to Accommodation
& ActivityDossier
resources.
2.13.0 (2018-03-31)
- Add
meal_budgets
list field to CountryDossier
resource. - Add
publish_state
field to DossierFeatures
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'})
. See
PR #91
_.
-
Add preferred_display_name
field to Agency
resource. See PR #92
_.
-
Add booking_companies
array field to all Product-type resources. See
PR #93
_.
- Accommodation
- Activity
- AgencyChain
- Departure
- SingleSupplement
- TourDossier
- Transport
.. _PR #91
: https://github.com/gadventures/gapipy/pull/91
.. _PR #92
: https://github.com/gadventures/gapipy/pull/92
.. _PR #93
: https://github.com/gadventures/gapipy/pull/93
2.11.4 (2018-01-29)
- Add
agency_chain
field to Booking
resource - Add
id
field as part of the DossierDetail
model See PR #89
_. - Add
agency_chains
field to the Agency
resource. See PR #90
_. - See
Release tag 2.11.3
_ for more details.
.. _PR #89
: https://github.com/gadventures/gapipy/pull/89
.. _PR #90
: https://github.com/gadventures/gapipy/pull/90
.. _Release tag 2.11.3
: https://github.com/gadventures/gapipy/releases/tag/2.11.3
2.11.0 (2017-12-18)
- The
Customer.address
field uses the Address
model, and is no longer a
dict. - Passing in
uuid=True
to Client
kwargs enables uuid
generation
for every request.
2.10.0 (2017-12-01)
- Add the
amount_pending
field to the Booking
resource - The
PricePromotion
model extends from the Promotion
resource (PR/85) - Update the
Agent
class to use BaseModel classes for the role
and phone_numbers
fields. - see
Release tag 2.10.0
_ for more details.
.. _Release tag 2.10.0
: https://github.com/gadventures/gapipy/releases/tag/2.10.0
2.9.3 (2017-11-23)
.. note:: We have skipped Release 2.9.2
due to pypi upload issues.
- Expose
requirement_set
for departure_services
& activity_services
.
2.9.1 (2017-11-22)
.. note:: * We have skipped Release 2.9.0
due to pypi upload issues.
- Adds the
options
method on the Resource Query object. See
Release tag 2.9.1
_ for more details.
.. _Release tag 2.9.1
: https://github.com/gadventures/gapipy/releases/tag/2.9.1
2.8.2 (2017-11-14)
- Adds fields
sale_start_datetime
and sale_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
and AgencyChain
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 added filter
values, and be used in subsequent
calls. Now the underlying filters are reset after a <resource>.all()
call
is made.
See Issue #76
_ and PR #77
_ for details and the resulting fix.
-
Adds missing fields to the Agency and Flight Service resources (PR/78)
.. _Issue #76
: https://github.com/gadventures/gapipy/issues/76
.. _PR #77
: https://github.com/gadventures/gapipy/pull/77
2.7.6 (2017-10-04)
- Add
agency
field to Booking
resource.
2.7.5 (2017-09-25)
- Add test fix for Accommodation. It is a 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
, and categories
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 to AgencyDocument
model - Add
structured_itinerary
model collection field to Departure
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 for checkins
resource - Add
date_cancelled
field for departures
resource
-
Fix broken UpdateCreateResource
tests
2.7.0 (2017-08-18)
- Remove
flight_statuses
and flight_segments
resources.
2.6.2 (2017-08-11)
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.
.. _Issue #65
: https://github.com/gadventures/gapipy/issues/65
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 a None
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)
2.4.6 (2016-10-19)
- Fix broken
Duration
init in ActivityDossier
(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 in Itinerary
and,
PlaceDossier
2.4.4 (2016-09-09)
- Added
date_last_modified
and date_created
to Promotion
.
2.4.3 (2016-09-06)
- Added
gender
to Customer
. - Added
places_of_interest
to Place
.
2.4.2 (2016-07-08)
- Added
departure
reference to DepartureComponent
2.4.1 (2016-07-06)
- Removed use of
.iteritems
wherever present in favour of .items
- Added
features
representation to ActivityDossier
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 the Itinerary
resource.
2.2.1 (2016-06-06)
- Added
audience
field to the Document
resource.
2.2.0 (2016-05-17)
- Added
transactional_email
, and emails
to Agency
resource.
2.1.2 (2016-05-17)
- Added
audience
to Invoice
resource.
2.1.1 (2016-04-29)
- Removed invalid field,
email
from AgencyChain
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 many changes in codebases that are
using gapipy
, since most resource interacation happens through a Client
instance (e.g. 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.
.. warning:: BREAKING!
- 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 a
query_key
method which generates the cache key sent to the cache
modules.
.. _Semantic Versioning
: http://semver.org/
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
to Itineraries
.
0.5.4 (2016-01-04)
- Added
associated_services
to SingleSupplementService
0.5.3 (2015-12-31)
- Added
name
to Departure
. - Happy New Year!
0.5.2 (2015-12-15)
- Added
variation_id
to BaseCache
to fix a TypeError
when using
the NullCache
0.5.1 (2015-12-14)
- Add
associated_agency
to bookings
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
and ItineraryMedia
resources. These are
sub resources of the Itinerary
0.4.6 (2015-12-09)
- Added connection pool caching to
RedisCache
. Instances of gapipy
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 the type
of an Itinerary
's listed
details
.
0.4.4 (2015-11-04)
- Added the
details
field to the Itinerary
resource -- a list of
textual details about an itinerary.
0.4.3 (2015-11-03)
- Added the
tour_dossier
field to the Itinerary
resource.
0.4.2 (2015-10-28)
- Fixed a bug that would cause
amount
when looking at Promotion
objects
in the Departure
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 within price_bands
on a
Departure
. It now correctly captures the amount
field.
0.2.0 (2015-09-15)
- Modified objects within
cache
module to handle variation_id
, which is
exposed within the Itinerary
object. Previously, the Itinerary
would
not be correctly stored in cache with its variant reference.
0.1.51 (2015-08-31)
- Added the
components
field to the Departure
resource.
0.1.50 (2015-07-28)
- Fixed an issue with the default
gapipy.cache.NullCache
when is_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 of
0
won't raise an Exception anymore.
0.1.46 (2015-06-10)
- Added
associated_services
and original_departure_service
to various
service resources and departure_services
model respectively.
0.1.45 (2015-05-27)
- Fixed
products
within the Promotion
resource to properly retain
type
and sub_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 <https://developers.gadventures.com/docs/departure_component.html>
_
for details.
0.1.40 (2015-04-06)
- Added
deposit
to DepartureService
resource.
0.1.39 (2015-03-31)
- Refactor
APIRequestor._request
. While this should not change existing
functionality, it is now possible to override specific methods on the class.
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 the promotions
object now works
as expected. Previously, accessing the products
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)
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 its
Itinerary
0.1.26 (2015-01-14)
- Normalize API request headers, to promote caching.
0.1.25 (2015-01-09)
- Added
ActivityDossier
and AccommodationDossier
resources, as well as
references to it from Activity
and Accommodation
.
0.1.24 (2015-01-07)
- Added
PlaceDossier
resource, as well as reference to it from Place
0.1.22 (2014-12-12)
- Added
advertised_departures
to TourDossier
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
, and documents
to the Agency
resource.
0.1.12 (2014-10-20)
date_created
on the Agency
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)
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.
.. code-block:: python
obj = {'name': {'legal_first_name': 'Pat', ...}, ...}
api.customers.create(obj)
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)