Skip to content

Commit

Permalink
Merge bd389ca into affbf63
Browse files Browse the repository at this point in the history
  • Loading branch information
pierreben committed Oct 2, 2018
2 parents affbf63 + bd389ca commit e33ae4a
Show file tree
Hide file tree
Showing 14 changed files with 234 additions and 34 deletions.
48 changes: 48 additions & 0 deletions README.rst
Expand Up @@ -72,3 +72,51 @@ The `Suivi Api <https://developer.laposte.fr/products/suivi/latest>`_
suivi = api.suivi.get('1111111111111')
print suivi.status
Tarif envoi
~~~~~~~~~~~~~

The `Tarif envoi <https://developer.laposte.fr/products/tarifenvoi/latest>`_

Simple call
^^^^^^^^^^^^^^^

.. code-block:: python
rates = api.tarifenvoi.get('lettre', 10)
>>> [{'channel': u'bureau',
'currency': u'\u20ac',
'price': 0.8,
'product': u'Lettre verte'},
{'channel': u'en ligne',
'currency': u'\u20ac',
'price': 0.77,
'product': u'Lettre verte'},
{'channel': u'bureau',
'currency': u'\u20ac',
'price': 0.95,
'product': u'Lettre prioritaire'},
{'channel': u'en ligne',
'currency': u'\u20ac',
'price': 0.92,
'product': u'Lettre prioritaire'},
{'channel': u'bureau',
'currency': u'\u20ac',
'price': 0.78,
'product': u'Ecopli'}]
Filtered call
^^^^^^^^^^^^^^^

.. code-block:: python
from lapostesdk.constants.tarifenvoi import TarifEnvoiChannels
from lapostesdk.constants.tarifenvoi import TarifEnvoiProducts
rates = api.tarifenvoi.get('lettre', 10, channels=[TarifEnvoiChannels.online], products=[TarifEnvoiProducts.first_class_mail])
>>> [{'channel': u'en ligne',
'currency': u'\u20ac',
'price': 0.92,
'product': u'Lettre prioritaire'}]
22 changes: 17 additions & 5 deletions lapostesdk/apis/apibase.py
@@ -1,15 +1,21 @@
# -*- coding:utf-8 -*-

# Standard library imports
from __future__ import unicode_literals

import requests
from importlib import import_module


class ApiBase(object):
def __init__(self, api_key, product, version='v1', entity=None):
self.product = product
self.version = version
self.entity = entity

self.api_url = 'https://api.laposte.fr/%(product)s/%(version)s/' % {
'product': self.product,
'version': self.version}
'product': self.product,
'version': self.version}

self.headers = {'X-Okapi-Key': api_key}

Expand All @@ -21,13 +27,19 @@ def get(self, resource, params={}):
return self.create_object(response, self.entity)

def _get(self, resource, params={}):
r = requests.get(self.api_url + resource, params=params, headers=self.headers)
return r.json()
response = requests.get(self.api_url + resource, params=params, headers=self.headers)

status_code = response.status_code
content = response.json()

if status_code != 200:
raise Exception(content['message'])

return content

def create_object(self, response, entity):
module = import_module('lapostesdk.entities')
obj = getattr(module, self.entity)
instance = obj()
instance.hydrate(response)
return instance

13 changes: 10 additions & 3 deletions lapostesdk/apis/apicontroladresse.py
@@ -1,11 +1,18 @@
# -*- coding:utf-8 -*-

# Standard library imports
from __future__ import unicode_literals

from lapostesdk.apis.apibase import ApiBase


class ApiControlAdresse(ApiBase):
def __init__(self, api_key):
super(ApiControlAdresse, self).__init__(api_key,
product='controladresse', entity='Adresse')
super(ApiControlAdresse, self).__init__(
api_key,
product='controladresse',
entity='Adresse')

def search(self, address):
payload = {'q': address}
return self._get('adresses', params=payload)

20 changes: 6 additions & 14 deletions lapostesdk/apis/apisuivi.py
@@ -1,19 +1,11 @@
# -*- coding:utf-8 -*-

# Standard library imports
from __future__ import unicode_literals

from lapostesdk.apis.apibase import ApiBase


class ApiSuivi(ApiBase):
def __init__(self, api_key):
super(ApiSuivi, self).__init__(api_key, product='suivi', entity='Suivi')

def get(self, resource, params={}):
response = self._get(resource, params)

if response['code'] == 'BAD_REQUEST':
raise Exception(response['message'])

if response['code'] == 'RESOURCE_NOT_FOUND':
raise Exception(response['message'])

if self.entity is None:
return response

return self.create_object(response, self.entity)
26 changes: 26 additions & 0 deletions lapostesdk/apis/apitarifenvoi.py
@@ -0,0 +1,26 @@
# -*- coding:utf-8 -*-

# Standard library imports
from __future__ import unicode_literals

from lapostesdk.apis.apibase import ApiBase


class ApiTarifEnvoi(ApiBase):
def __init__(self, api_key):
super(ApiTarifEnvoi, self).__init__(api_key, product='tarifenvoi', entity='TarifEnvoi')

def get(self, type, weight, channels=[], products=[]):
params = {'type': type,
'poids': weight}

response = self._get('', params)
response_objects = [self.create_object(r, self.entity) for r in response]

if len(channels) > 0:
response_objects = [response_object for response_object in response_objects if response_object.channel in [channel.value for channel in channels]]

if len(products) > 0:
response_objects = [response_object for response_object in response_objects if response_object.product in [product.value for product in products]]

return response_objects
Empty file.
26 changes: 26 additions & 0 deletions lapostesdk/constants/tarifenvoi.py
@@ -0,0 +1,26 @@
# -*- coding:utf-8 -*-

# Standard library imports
from __future__ import unicode_literals

from enum import Enum


class TarifEnvoiTypes(Enum):
letter = 'lettre'
colissimo = 'colis'
chronopost = 'chronopost'


class TarifEnvoiProducts(Enum):
green_mail = 'Lettre verte'
first_class_mail = 'Lettre prioritaire'
ecopli = 'Ecopli'
colissimo = 'Colissimo France (« avec Signature » en option)'
chronopost_10 = 'Affranchissement Chronopost Chrono 10'
chronopost_13 = 'Affranchissement Chronopost Chrono 13'


class TarifEnvoiChannels(Enum):
post_office = 'bureau'
online = 'en ligne'
7 changes: 6 additions & 1 deletion lapostesdk/entities/__init__.py
@@ -1,4 +1,9 @@
#__all__ = ['adresse', 'suivi']
# -*- coding:utf-8 -*-
# __all__ = ['adresse', 'suivi', 'tarifenvoi']

# Standard library imports
from __future__ import unicode_literals

from lapostesdk.entities.adresse import Adresse
from lapostesdk.entities.suivi import Suivi
from lapostesdk.entities.tarifenvoi import TarifEnvoi
6 changes: 6 additions & 0 deletions lapostesdk/entities/adresse.py
@@ -1,5 +1,11 @@
# -*- coding:utf-8 -*-

# Standard library imports
from __future__ import unicode_literals

from lapostesdk.entities.base import BaseEntity


class Adresse(BaseEntity):
def __init__(self):
self.destinataire = None
Expand Down
6 changes: 6 additions & 0 deletions lapostesdk/entities/base.py
@@ -1,3 +1,9 @@
# -*- coding:utf-8 -*-

# Standard library imports
from __future__ import unicode_literals


class BaseEntity(object):
def hydrate(self, data):
for k in data:
Expand Down
6 changes: 6 additions & 0 deletions lapostesdk/entities/suivi.py
@@ -1,5 +1,11 @@
# -*- coding:utf-8 -*-

# Standard library imports
from __future__ import unicode_literals

from lapostesdk.entities.base import BaseEntity


class Suivi(BaseEntity):
def __init__(self):
self.code = None
Expand Down
14 changes: 14 additions & 0 deletions lapostesdk/entities/tarifenvoi.py
@@ -0,0 +1,14 @@
# -*- coding:utf-8 -*-

# Standard library imports
from __future__ import unicode_literals

from lapostesdk.entities.base import BaseEntity


class TarifEnvoi(BaseEntity):
def __init__(self):
self.channel = None
self.currency = None
self.price = None
self.product = None
9 changes: 8 additions & 1 deletion lapostesdk/laposteapi.py
@@ -1,8 +1,15 @@
from lapostesdk.apis import apisuivi, apicontroladresse
# -*- coding:utf-8 -*-

# Standard library imports
from __future__ import unicode_literals

from lapostesdk.apis import apisuivi, apicontroladresse, apitarifenvoi


class LaPosteApi(object):
def __init__(self, api_key):
self.api_key = api_key

self.suivi = apisuivi.ApiSuivi(self.api_key)
self.controladresse = apicontroladresse.ApiControlAdresse(self.api_key)
self.tarifenvoi = apitarifenvoi.ApiTarifEnvoi(self.api_key)
65 changes: 55 additions & 10 deletions test.py
@@ -1,21 +1,26 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

import unittest
import responses

from lapostesdk.laposteapi import LaPosteApi
from lapostesdk.constants.tarifenvoi import TarifEnvoiChannels
from lapostesdk.constants.tarifenvoi import TarifEnvoiProducts


class TestBase(unittest.TestCase):
def setUp(self):
self.api = LaPosteApi('TheApiKey')


class TestSuiviApi(TestBase):
@responses.activate
def test_get(self):
responses.add(responses.GET,
'https://api.laposte.fr/suivi/v1/1111111111111',
json={'code': '1111111111111'}, status=200)
'https://api.laposte.fr/suivi/v1/1111111111111',
json={'code': '1111111111111'}, status=200)

r = self.api.suivi.get('1111111111111')
self.assertEqual("1111111111111", r.code)
Expand All @@ -27,27 +32,28 @@ def test_get(self):
@responses.activate
def test_bad_request(self):
responses.add(responses.GET,
'https://api.laposte.fr/suivi/v1/123',
json={'code': 'BAD_REQUEST', 'message': 'Mauvais format pour le paramètre code'}, status=200)
'https://api.laposte.fr/suivi/v1/123',
json={'code': 'BAD_REQUEST', 'message': 'Mauvais format pour le paramètre code'}, status=400)

with self.assertRaises(Exception):
self.api.suivi.get('123')

@responses.activate
def test_resource_not_found(self):
responses.add(responses.GET,
'https://api.laposte.fr/suivi/v1/1111111111119',
json={'code': 'RESOURCE_NOT_FOUND', 'message': 'Aucun produit ne correspond à votre recherche'}, status=200)
'https://api.laposte.fr/suivi/v1/1111111111119',
json={'code': 'RESOURCE_NOT_FOUND', 'message': 'Aucun produit ne correspond à votre recherche'}, status=404)

with self.assertRaises(Exception):
self.api.suivi.get('1111111111119')


class TestControlAdresseApi(TestBase):
@responses.activate
def test_search(self):
responses.add(responses.GET,
'https://api.laposte.fr/controladresse/v1/adresses',
json=[{'foo': 'bar'}], status=200)
'https://api.laposte.fr/controladresse/v1/adresses',
json=[{'foo': 'bar'}], status=200)

r = self.api.controladresse.search('116 avenue du Président Kennedy 75220 Paris Cedex 16')
self.assertEqual("bar", r[0]['foo'])
Expand All @@ -60,8 +66,8 @@ def test_search(self):
@responses.activate
def test_get(self):
responses.add(responses.GET,
'https://api.laposte.fr/controladresse/v1/plop',
json={'codePostal': 'bar'}, status=200)
'https://api.laposte.fr/controladresse/v1/plop',
json={'codePostal': 'bar'}, status=200)

r = self.api.controladresse.get('plop')
self.assertEqual("bar", r.codePostal)
Expand All @@ -70,5 +76,44 @@ def test_get(self):
self.assertEquals(responses.calls[0].request.url, 'https://api.laposte.fr/controladresse/v1/plop')
self.assertEquals(responses.calls[0].request.headers['X-Okapi-Key'], 'TheApiKey')


class TestTarifEnvoiApi(TestBase):
@responses.activate
def test_get(self):
responses.add(responses.GET,
'https://api.laposte.fr/tarifenvoi/v1/',
json=[{'currency': '€', 'product': 'Lettre verte', 'price': 0.8, 'channel': 'bureau'}, {'currency': '€', 'product': 'Lettre verte', 'price': 0.77, 'channel': 'en ligne'}, {'currency': '€', 'product': 'Lettre prioritaire', 'price': 0.95, 'channel': 'bureau'}, {'currency': '€', 'product': 'Lettre prioritaire', 'price': 0.92, 'channel': 'en ligne'}, {'currency': '€', 'product': 'Ecopli', 'price': 0.78, 'channel': 'bureau'}], status=200)

r = self.api.tarifenvoi.get('lettre', 10)

self.assertEqual(5, len(r))
self.assertEqual('€', r[0].currency)
self.assertEqual('Lettre verte', r[0].product)
self.assertEqual(0.8, r[0].price)
self.assertEqual('bureau', r[0].channel)

self.assertEquals(len(responses.calls), 1)
self.assertEquals(responses.calls[0].request.url, 'https://api.laposte.fr/tarifenvoi/v1/?type=lettre&poids=10')
self.assertEquals(responses.calls[0].request.headers['X-Okapi-Key'], 'TheApiKey')

@responses.activate
def test_filters(self):
responses.add(responses.GET,
'https://api.laposte.fr/tarifenvoi/v1/',
json=[{'currency': '€', 'product': 'Lettre verte', 'price': 0.8, 'channel': 'bureau'}, {'currency': '€', 'product': 'Lettre verte', 'price': 0.77, 'channel': 'en ligne'}, {'currency': '€', 'product': 'Lettre prioritaire', 'price': 0.95, 'channel': 'bureau'}, {'currency': '€', 'product': 'Lettre prioritaire', 'price': 0.92, 'channel': 'en ligne'}, {'currency': '€', 'product': 'Ecopli', 'price': 0.78, 'channel': 'bureau'}], status=200)

r = self.api.tarifenvoi.get('lettre', 10, channels=[TarifEnvoiChannels.online], products=[TarifEnvoiProducts.first_class_mail])

self.assertEqual(1, len(r))
self.assertEqual('€', r[0].currency)
self.assertEqual('Lettre prioritaire', r[0].product)
self.assertEqual(0.92, r[0].price)
self.assertEqual('en ligne', r[0].channel)

self.assertEquals(len(responses.calls), 1)
self.assertEquals(responses.calls[0].request.url, 'https://api.laposte.fr/tarifenvoi/v1/?type=lettre&poids=10')
self.assertEquals(responses.calls[0].request.headers['X-Okapi-Key'], 'TheApiKey')


if __name__ == '__main__':
unittest.main()

0 comments on commit e33ae4a

Please sign in to comment.