Skip to main content
Help us improve Python packaging – donate today!

Python client for the G Adventures REST API

Project Description

https://travis-ci.org/gadventures/gapipy.svg?branch=master

A client for the G Adventures REST API (https://developers.gadventures.com)

Quick Start

>>> from gapipy import Client
>>> api = Client(application_key='MY_SECRET_KEY')

>>> # Get a resource by id
>>> tour = api.tours.get(24309)
>>> tour.product_line
u'AHEH'
>>> tour.departures.count()
134
>>> dossier = tour.tour_dossier
>>> dossier.name
u'Essential India'
>>> itinerary = 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()

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.
filter(field1=value1, [field2=value2, ...])
Filter resources on the provided fields and values. Calls to filter can be chained.
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 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.

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 another Resource

Thanks for helping!

History

2.13.0 (2018-03-31)

  • Add meal_budgets list field to Country Dossier resource
  • Add publish_state field to Dossier 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)

2.11.0 (2017-12-18)

  • The Customer Address uses 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 https://github.com/gadventures/gapipy/releases/2.10.0 for more details

2.9.3 (2017-11-23)

  • Expose requirement_set for departure_services and activity_services.
  • NOTE: We have skipped 2.9.2 due to pypi upload issues.

2.9.1 (2017-11-22)

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.

    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 to Booking 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, 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)

  • 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 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)

  • Added Checkin resource.

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 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 a query_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 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)

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 on APIRequestor 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 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)

  • Added TransportDossier and Itinerary resources.
  • The reference to the itinerary in a DepartureService is now a full-fledged Itinerary 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 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)

  • 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.

Release history Release notifications

This version
History Node

2.13.0

History Node

2.12.0

History Node

2.11.4

History Node

2.11.0

History Node

2.10.0

History Node

2.9.3

History Node

2.9.1

History Node

2.8.2

History Node

2.8.1

History Node

2.8.0

History Node

2.7.6

History Node

2.7.5

History Node

2.7.4

History Node

2.7.3

History Node

2.7.2

History Node

2.7.1

History Node

2.7.0

History Node

2.6.2

History Node

2.5.2

History Node

2.5.1

History Node

2.5.0

History Node

2.4.9

History Node

2.4.8

History Node

2.4.7

History Node

2.4.6

History Node

2.4.5

History Node

2.4.4

History Node

2.4.3

History Node

2.4.1

History Node

2.4.0

History Node

2.3.0

History Node

2.2.2

History Node

2.2.1

History Node

2.2.0

History Node

2.1.2

History Node

2.1.1

History Node

2.1.0

History Node

2.0.0

History Node

1.1.0

History Node

1.0.0

History Node

0.6.3

History Node

0.6.2

History Node

0.6.1

History Node

0.6.0

History Node

0.5.5

History Node

0.5.4

History Node

0.5.3

History Node

0.5.1

History Node

0.5.0

History Node

0.4.6

History Node

0.4.5

History Node

0.4.4

History Node

0.4.3

History Node

0.4.2

History Node

0.4.1

History Node

0.4.0

History Node

0.3.0

History Node

0.2.0

History Node

0.1.51

History Node

0.1.50

History Node

0.1.49

History Node

0.1.48

History Node

0.1.47

History Node

0.1.46

History Node

0.1.45

History Node

0.1.44

History Node

0.1.43

History Node

0.1.42

History Node

0.1.41

History Node

0.1.40

History Node

0.1.39

History Node

0.1.38

History Node

0.1.37

History Node

0.1.36

History Node

0.1.35

History Node

0.1.34

History Node

0.1.33

History Node

0.1.32

History Node

0.1.31

History Node

0.1.30

History Node

0.1.29

History Node

0.1.28

History Node

0.1.27

History Node

0.1.24

History Node

0.1.23

History Node

0.1.22

History Node

0.1.21

History Node

0.1.20

History Node

0.1.19

History Node

0.1.18

History Node

0.1.17

History Node

0.1.16

History Node

0.1.15

History Node

0.1.14

History Node

0.1.13

History Node

0.1.12

History Node

0.1.11

History Node

0.1.10

History Node

0.1.9

History Node

0.1.7

History Node

0.1.6

History Node

0.1.5

History Node

0.1.3

History Node

0.1.2

History Node

0.1.1

History Node

0.1.0

Download files

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

Filename, size & hash SHA256 hash help File type Python version Upload date
gapipy-2.13.0.tar.gz (67.3 kB) Copy SHA256 hash SHA256 Source None Apr 2, 2018

Supported by

Elastic Elastic Search Pingdom Pingdom Monitoring Google Google BigQuery Sentry Sentry Error logging CloudAMQP CloudAMQP RabbitMQ AWS AWS Cloud computing Fastly Fastly CDN DigiCert DigiCert EV certificate StatusPage StatusPage Status page