Skip to content

Commit

Permalink
Python 3 (#59)
Browse files Browse the repository at this point in the history
* Python3 restructure

* Return Python 2 functionality

* Update tests

* Python 2 and 3 encodings

* Returend __future__ to agent Resource (needed for encoding)

* Return __future__ to Language

* Fix reversed comment logic

* Update .travis.yml

* Update base.py

* Migrates gapipy to Python 3 and maintains Python 2 functionality
* Identifies all changes with comments (`Python 2` present in all)

Trello: https://trello.com/c/f4N6pndU/972-make-gapipy-python-2-3-compatible
  • Loading branch information
annakovale committed Jan 20, 2017
1 parent c0c96af commit 7e1f2fa
Show file tree
Hide file tree
Showing 54 changed files with 180 additions and 104 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ language: python

python:
- "2.7"
- "3.6"

sudo: false

Expand Down
8 changes: 6 additions & 2 deletions gapipy/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@


try:
# Python 2
import cPickle as pickle
except ImportError:
import pickle
# Python 3
import pickle as pickle


class BaseCache(object):
Expand Down Expand Up @@ -138,7 +140,9 @@ def delete(self, key):

def clear(self):
cache_keys = self._client.keys('{}*'.format(self.key_prefix))
map(self._client.delete, cache_keys)
# Python 2 and 3
# inefficient on Python 2 to list a map
list(map(self._client.delete, cache_keys))

def info(self):
return self._client.info()
Expand Down
44 changes: 34 additions & 10 deletions gapipy/models/base.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import sys
from decimal import Decimal
from itertools import ifilterfalse
try:
# Python 2
from itertools import ifilterfalse as filterfalse
except ImportError:
# Python 3
from itertools import filterfalse
import datetime

from gapipy.query import Query
Expand All @@ -9,6 +15,7 @@
get_resource_class_from_resource_name,
)


DATE_FORMAT = '%Y-%m-%d'
DATE_TIME_UTC_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
DATE_TIME_LOCAL_FORMAT = "%Y-%m-%dT%H:%M:%S"
Expand Down Expand Up @@ -44,7 +51,8 @@ def _fill_fields(self, data):
# Initially we populate base fields, as model/resource fields may rely
# on these to be present.
remaining_data = {}
for field, value in data.items():
# list(dict.items()) inefficient on Python 2
for field, value in list(data.items()):
if field in self._as_is_fields:
self._set_as_is_field(field, value)
elif field in self._date_fields:
Expand All @@ -59,7 +67,8 @@ def _fill_fields(self, data):
remaining_data[field] = value

# Populate resource/model fields.
for field, value in remaining_data.items():
# list(dict.items()) inefficient on Python 2
for field, value in list(remaining_data.items()):
if field in first(self._model_fields):
self._set_model_field(field, value)
elif field in first(self._model_collection_fields):
Expand Down Expand Up @@ -103,7 +112,18 @@ def _model_cls(self, field):
model_cls = [cls for f, cls in fields if f == field][0]

# FIXME: This will not work for the model_*_fields.
if isinstance(model_cls, basestring):

# Python 2 has basestring, Python 3 str
str_or_base = False
if sys.version_info.major < 3:
# Python 2
if isinstance(model_cls, basestring):
str_or_base = True
else:
# Python 3
if isinstance(model_cls, str):
str_or_base = True
if str_or_base:
model_cls = get_resource_class_from_class_name(model_cls)
return model_cls

Expand Down Expand Up @@ -157,16 +177,18 @@ def _set_resource_collection_field(self, field, value):

def _allowed_fields(self):
first = lambda pair: pair[0]
# Python 2 and 3
# inefficient on Python 2 to list a map
return (
self._as_is_fields
+ self._date_fields
+ self._date_time_fields_utc
+ self._date_time_fields_local
+ map(first, self._model_fields)
+ map(first, self._model_collection_fields)
+ list(map(first, self._model_fields))
+ list(map(first, self._model_collection_fields))
+ self._price_fields
+ map(first, self._resource_fields)
+ map(first, self._resource_collection_fields)
+ list(map(first, self._resource_fields))
+ list(map(first, self._resource_collection_fields))
+ self._deprecated_fields
)

Expand All @@ -189,9 +211,11 @@ def _convert_from_resource_type(self, key, value):
return value

def to_dict(self):
properties = {k: v for k, v in self.__dict__.items() if k in self._allowed_fields()}
# Python 2 and 3
# inefficient on Python 2 to list .items
properties = {k: v for k, v in list(self.__dict__.items()) if k in self._allowed_fields()}
data = {}
for key, value in properties.items():
for key, value in list(properties.items()):
if isinstance(value, (list, tuple)):
data[key] = [self._convert_from_resource_type(key, a) for a in value]
else:
Expand Down
4 changes: 3 additions & 1 deletion gapipy/models/price_band.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ def _model_collection_fields(self):
return [('prices', Price)]

def available_currencies(self):
return self.prices.keys()
# Python 2 and 3
# inefficient on Python 2 to list keys()
return list(self.prices.keys())


class SeasonalPriceBand(PriceBand):
Expand Down
4 changes: 3 additions & 1 deletion gapipy/models/price_promotion.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ def __init__(self, data, **kwargs):
self._resource_name = 'promotions'

klass = get_resource_class_from_resource_name('promotions')
for k, v in klass.__dict__.items():
# Python 2 and 3
# inefficient on Python 2 to list items()
for k, v in list(klass.__dict__.items()):
if 'fields' in k and isinstance(v, list):
setattr(self, k, getattr(klass, k))

Expand Down
13 changes: 11 additions & 2 deletions gapipy/request.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import requests
import sys

from . import __title__, __version__

Expand Down Expand Up @@ -84,8 +85,16 @@ def _make_call(self, method, url, headers, data, params):
return response.raise_for_status()

def _get_uri(self):
if isinstance(self.resource, basestring):
return self.resource
# Python 2 has str, Python 3 basestring
# Python 2
if sys.version_info.major < 3:
if isinstance(self.resource, basestring):
return self.resource
else:
# Python 3
if isinstance(self.resource, str):
return self.resource

if self.resource._uri:
return self.resource._uri
return self.resource._resource_name
Expand Down
4 changes: 3 additions & 1 deletion gapipy/resources/base.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Python 2 and 3
from __future__ import unicode_literals

import json
Expand Down Expand Up @@ -78,7 +79,8 @@ def _update(self, partial=False):

data = self.to_dict()
if partial:
data = {k: v for k, v in data.iteritems() if self._raw_data.get(k) != v}
# .items isn't effecient in Python 2
data = {k: v for k, v in data.items() if self._raw_data.get(k) != v}

return request.update(self.id, json.dumps(data), partial=partial)

Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/booking/agency.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Python 2 and 3
from __future__ import unicode_literals

from ...models import Address
Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/booking/booking.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Python 2 and 3
from __future__ import unicode_literals

from ..base import Resource
Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/booking/customer.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Python 2 and 3
from __future__ import unicode_literals

from ..base import Resource, BaseModel
Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/booking/document.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Python 2 and 3
from __future__ import unicode_literals

from ..base import Resource
Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/booking/nationality.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Python 2 and 3
from __future__ import unicode_literals

from ..base import Resource
Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/booking/override_reason.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#!/usr/bin/env python
# Python 2 and 3
from __future__ import unicode_literals

from ..base import Resource
Expand Down
8 changes: 5 additions & 3 deletions gapipy/resources/booking/service.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Python 2 and 3
from __future__ import unicode_literals

from future.utils import with_metaclass

from ...utils import get_resource_class_from_resource_name
from ...models import (
ArrivalFlightDetail,
Expand Down Expand Up @@ -41,13 +44,12 @@ def __call__(cls, *args, **kwargs):
return type.__call__(new_class, *args, **kwargs)


class Service(Resource):
# with_metaclass is Python 2 and Python 3 method to allow metaclasses
class Service(with_metaclass(TypeBasedServiceMeta, Resource)):
_resource_name = 'services'
_is_listable = False
_is_parent_resource = True

__metaclass__ = TypeBasedServiceMeta

@property
def _as_is_fields(self):
return [
Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/booking/transaction.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Python 2 and 3
from __future__ import unicode_literals

from ..base import Resource
Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/checkin/checkin.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Python 2 and 3
from __future__ import unicode_literals

from ..base import Resource, BaseModel
Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/dossier/accommodation_dossier.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Python 2 and 3
from __future__ import unicode_literals

from ..base import Resource
Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/dossier/activity_dossier.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Python 2 and 3
from __future__ import unicode_literals

from ...utils import humanize_price, LocationLabelMixin, DurationLabelMixin, enforce_string_type
Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/dossier/country_dossier.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Python 2 and 3
from __future__ import unicode_literals

from ..base import Resource
Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/dossier/details.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Python 2 and 3
from __future__ import unicode_literals

from ...models.base import BaseModel
Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/dossier/dossier_segment.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Python 2 and 3
from __future__ import unicode_literals

from ..base import Resource
Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/dossier/place_dossier.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Python 2 and 3
from __future__ import unicode_literals

from ...models.base import BaseModel
Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/dossier/service_level.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Python 2 and 3
from __future__ import unicode_literals

from ...models.base import BaseModel
Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/dossier/transport_dossier.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Python 2 and 3
from __future__ import unicode_literals

from ..base import Resource
Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/geo/airport.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Python 2 and 3
from __future__ import unicode_literals

from ..base import Resource
Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/geo/continent.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Python 2 and 3
from __future__ import unicode_literals

from ..base import Resource
Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/geo/country.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Python 2 and 3
from __future__ import unicode_literals

from ..base import Resource
Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/geo/feature.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Python 2 and 3
from __future__ import unicode_literals

from ..base import Resource
Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/geo/feature_category.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Python 2 and 3
from __future__ import unicode_literals

from ..base import Resource
Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/geo/place.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Python 2 and 3
from __future__ import unicode_literals

from ..base import Resource
Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/geo/state.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Python 2 and 3
from __future__ import unicode_literals

from ..base import Resource
Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/geo/timezone.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Python 2 and 3
from __future__ import unicode_literals

from ..base import Resource
Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/language.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Python 2 and 3
from __future__ import unicode_literals

from .base import Resource
Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/tour/accommodation.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Python 2 and 3
from __future__ import unicode_literals

from ...models import Address
Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/tour/activity.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Python 2 and 3
from __future__ import unicode_literals


Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/tour/departure.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Python 2 and 3
from __future__ import unicode_literals

from ...models import Address, AddOn, DepartureRoom, PP2aPrice
Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/tour/departure_component.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Python 2 and 3
from __future__ import unicode_literals

from ...models.base import BaseModel
Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/tour/image.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
# Python 2 and 3
from __future__ import unicode_literals

from ..base import Resource
Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/tour/itinerary.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
# Python 2 and 3
from __future__ import unicode_literals

from .image import Image, MAP_TYPE
Expand Down
5 changes: 4 additions & 1 deletion gapipy/resources/tour/promotion.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Python 2 and 3
from __future__ import unicode_literals

from ...utils import get_resource_class_from_resource_name
Expand All @@ -16,7 +17,9 @@ def __init__(self, data, **kwargs):
# Fetch the resource class using the `type`, and then derive field
# attributes from that class.
klass = get_resource_class_from_resource_name(data['type'])
for k, v in klass.__dict__.items():
# Python 2 and 3
# inefficient on Python 2 to list items()
for k, v in list(klass.__dict__.items()):
if 'fields' in k and isinstance(v, list):
setattr(self, k, getattr(klass, k))

Expand Down
1 change: 1 addition & 0 deletions gapipy/resources/tour/single_supplement.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# Python 2 and 3
from __future__ import unicode_literals

from ...models import PriceBand
Expand Down

0 comments on commit 7e1f2fa

Please sign in to comment.