Skip to content

Commit f4c4aef

Browse files
committed
First commit
1 parent 05985f9 commit f4c4aef

File tree

4 files changed

+371
-0
lines changed

4 files changed

+371
-0
lines changed

mercadolibre/__init__.py

Whitespace-only changes.

mercadolibre/client.py

+347
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,347 @@
1+
import requests
2+
import time
3+
from mercadolibre import exceptions
4+
from mercadolibre.decorators import valid_token
5+
from urllib.parse import urlencode
6+
7+
8+
class Client(object):
9+
BASE_URL = 'https://api.mercadolibre.com'
10+
11+
auth_urls = {
12+
'MLA': "https://auth.mercadolibre.com.ar", # Argentina
13+
'MLB': "https://auth.mercadolivre.com.br", # Brasil
14+
'MCO': "https://auth.mercadolibre.com.co", # Colombia
15+
'MCR': "https://auth.mercadolibre.com.cr", # Costa Rica
16+
'MEC': "https://auth.mercadolibre.com.ec", # Ecuador
17+
'MLC': "https://auth.mercadolibre.cl", # Chile
18+
'MLM': "https://auth.mercadolibre.com.mx", # Mexico
19+
'MLU': "https://auth.mercadolibre.com.uy", # Uruguay
20+
'MLV': "https://auth.mercadolibre.com.ve", # Venezuela
21+
'MPA': "https://auth.mercadolibre.com.pa", # Panama
22+
'MPE': "https://auth.mercadolibre.com.pe", # Peru
23+
'MPT': "https://auth.mercadolibre.com.pt", # Prtugal
24+
'MRD': "https://auth.mercadolibre.com.do" # Dominicana
25+
}
26+
27+
def __init__(self, client_id, client_secret, site='MCO'):
28+
self.client_id = client_id
29+
self.client_secret = client_secret
30+
self.access_token = None
31+
self.refresh_token = None
32+
self.user_id = None
33+
self.expires_in = None
34+
self.expires_at = None
35+
try:
36+
self.auth_url = self.auth_urls[site]
37+
except KeyError as e:
38+
raise exceptions.InvalidSite()
39+
40+
def get_authorization_url(self, redirect_uri):
41+
params = {
42+
'client_id': self.client_id,
43+
'response_type': 'code',
44+
'redirect_uri': redirect_uri
45+
}
46+
url = self.auth_url + '/authorization?' + urlencode(params)
47+
return url
48+
49+
def exchange_code(self, redirect_uri, code):
50+
params = {
51+
'client_id': self.client_id,
52+
'client_secret': self.client_secret,
53+
'code': code,
54+
'grant_type': 'authorization_code',
55+
'redirect_uri': redirect_uri
56+
}
57+
return self._token(self._post('/oauth/token', params=params))
58+
59+
def refresh_token(self):
60+
params = {
61+
'client_id': self.client_id,
62+
'client_secret': self.client_secret,
63+
'grant_type': 'refresh_token',
64+
'refresh_token': self.refresh_token,
65+
}
66+
return self._token(self._post('/oauth/token', params=params))
67+
68+
def set_token(self, token):
69+
if isinstance(token, dict):
70+
self.access_token = token['access_token']
71+
self.refresh_token = token['refresh_token']
72+
self.user_id = token['user_id']
73+
self.expires_in = token['expires_in']
74+
if 'expires_at' in token:
75+
self.expires_at = token['expires_at']
76+
else:
77+
self.access_token = token
78+
79+
@property
80+
def is_valid_token(self):
81+
if self.expires_at:
82+
return self.expires_at > time.time()
83+
else:
84+
return None
85+
86+
def _token(self, response):
87+
if 'expires_in' in response:
88+
expires_in = response['expires_in']
89+
expires_at = time.time() + int(expires_in)
90+
response['expires_at'] = expires_at
91+
self.expires_at = expires_at
92+
return response
93+
94+
def _get(self, endpoint, params=None):
95+
return self._request('GET', endpoint, params)
96+
97+
def _post(self, endpoint, params=None, data=None):
98+
return self._request('POST', endpoint, params, data)
99+
100+
def _put(self, endpoint, params=None, data=None):
101+
return self._request('PUT', endpoint, params, data)
102+
103+
@valid_token
104+
def _request(self, method, endpoint, params=None, data=None):
105+
if params:
106+
params['access_token'] = self.access_token
107+
else:
108+
params = {'access_token': self.access_token}
109+
response = requests.request(method, self.BASE_URL + endpoint, params=params, data=data)
110+
return self._parse(response)
111+
112+
def _parse(self, response):
113+
print(response.json())
114+
print(response.status_code)
115+
return response
116+
117+
def me(self):
118+
"""Returns account information about the authenticated user.
119+
120+
Returns:
121+
122+
"""
123+
return self._parse(self._get('/users/me'))
124+
125+
def get_user(self, customer_id):
126+
"""User account information.
127+
128+
Args:
129+
customer_id:
130+
131+
Returns:
132+
133+
"""
134+
return self._parse(self._get('/users/{}'.format(customer_id)))
135+
136+
def update_user(self):
137+
raise NotImplementedError
138+
139+
def get_user_address(self, customer_id):
140+
"""Returns addresses registered by the user.
141+
142+
Args:
143+
customer_id:
144+
145+
Returns:
146+
147+
"""
148+
return self._parse(self._get('/users/{}/addresses'.format(customer_id)))
149+
150+
def get_user_accepted_payment_methods(self, customer_id):
151+
"""Returns payment methods accepted by a seller to collect its operations.
152+
153+
Args:
154+
customer_id:
155+
156+
Returns:
157+
158+
"""
159+
return self._parse(self._get('/users/{}/accepted_payment_methods'.format(customer_id)))
160+
161+
def get_application(self, application_id):
162+
"""Returns information about the application.
163+
164+
Args:
165+
application_id:
166+
167+
Returns:
168+
169+
"""
170+
return self._parse(self._get('/applications/{}'.format(application_id)))
171+
172+
def get_user_brands(self, user_id):
173+
"""This resource retrieves brands associated to an user_id. The official_store_id attribute identifies a store.
174+
175+
Args:
176+
user_id:
177+
178+
Returns:
179+
180+
"""
181+
return self._parse(self._get('/users/{}/brands'.format(user_id)))
182+
183+
def get_user_classifields_promotion_packs(self, user_id):
184+
"""Manage user promotion packs.
185+
186+
Args:
187+
user_id:
188+
189+
Returns:
190+
191+
"""
192+
return self._parse(self._get('/users/{}/classifieds_promotion_packs'.format(user_id)))
193+
194+
def create_user_classifields_promotion_packs(self):
195+
raise NotImplementedError
196+
197+
def get_project(self, project_id):
198+
"""Manage projects.
199+
200+
Returns:
201+
202+
"""
203+
return self._parse(self._get('/projects/{}'.format(project_id)))
204+
205+
def create_project(self):
206+
raise NotImplementedError
207+
208+
def update_project(self):
209+
raise NotImplementedError
210+
211+
def delete_project(self):
212+
raise NotImplementedError
213+
214+
def get_my_feeds(self):
215+
"""Notifications history.
216+
217+
Returns:
218+
219+
"""
220+
params = {
221+
'app_id': self.client_id
222+
}
223+
return self._parse(self._get('/myfeeds', params=params))
224+
225+
def get_sites(self):
226+
"""Retrieves information about the sites where MercadoLibre runs.
227+
228+
Returns:
229+
230+
"""
231+
return self._parse(self._get('/sites'))
232+
233+
def get_listing_types(self, site_id):
234+
"""Returns information about listing types.
235+
236+
Args:
237+
site_id:
238+
239+
Returns:
240+
241+
"""
242+
return self._parse(self._get('/sites/{}/listing_types'.format(site_id)))
243+
244+
def get_listing_exposures(self, site_id):
245+
"""Returns different exposure levels associated with all listing types in MercadoLibre.
246+
247+
Args:
248+
site_id:
249+
250+
Returns:
251+
252+
"""
253+
return self._parse(self._get('/sites/{}/listing_exposures'.format(site_id)))
254+
255+
def get_categories(self, site_id):
256+
""" Returns available categories in the site.
257+
258+
Args:
259+
site_id:
260+
261+
Returns:
262+
263+
"""
264+
return self._parse(self._get('/sites/{}/categories'.format(site_id)))
265+
266+
def get_category(self, category_id):
267+
"""Returns information about a category.
268+
269+
Args:
270+
category_id:
271+
272+
Returns:
273+
274+
"""
275+
return self._parse(self._get('/categories/{}'.format(category_id)))
276+
277+
def get_category_attributes(self, category_id):
278+
"""Displays attributes and rules over them in order to describe the items that are stored in each category.
279+
280+
Args:
281+
category_id:
282+
283+
Returns:
284+
285+
"""
286+
return self._parse(self._get('/categories/{}/attributes'.format(category_id)))
287+
288+
def get_countries(self):
289+
"""Returns countries information.
290+
291+
Returns:
292+
293+
"""
294+
return self._parse(self._get('/countries'))
295+
296+
def get_country(self, country_id):
297+
"""Returns country information by country_id.
298+
299+
Returns:
300+
301+
"""
302+
return self._parse(self._get('/countries/{}'.format(country_id)))
303+
304+
def get_state(self, state_id):
305+
""" Returns state information.
306+
307+
Args:
308+
state_id:
309+
310+
Returns:
311+
312+
"""
313+
return self._parse(self._get('/states/{}'.format(state_id)))
314+
315+
def get_city(self, city_id):
316+
"""Returns city information.
317+
318+
Args:
319+
city_id:
320+
321+
Returns:
322+
323+
"""
324+
return self._parse(self._get('/cities/{}'.format(city_id)))
325+
326+
def get_currencies(self):
327+
""" Returns information about all available currencies in MercadoLibre.
328+
329+
Returns:
330+
331+
"""
332+
return self._parse(self._get('/currencies'))
333+
334+
def get_currency(self, currency_id):
335+
"""Returns information about available currencies in MercadoLibre by currency_id.
336+
337+
Args:
338+
currency_id:
339+
340+
Returns:
341+
342+
"""
343+
return self._parse(self._get('/currencies/{}'.format(currency_id)))
344+
345+
def list_item(self, title, condition, category_id, price, currency_id, available_quantity, buying_mode,
346+
listing_type_id, video_id, warranty, pictures, description=None, **kwargs):
347+
return self._parse(self._post('/items'))

mercadolibre/decorators.py

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import time
2+
from functools import wraps
3+
from mercadolibre.exceptions import TokenExpired
4+
5+
6+
def valid_token(func):
7+
@wraps(func)
8+
def helper(*args, **kwargs):
9+
client = args[0]
10+
if client.expires_at and not client.expires_at > time.time():
11+
raise TokenExpired('You must refresh the token.')
12+
return func(*args, **kwargs)
13+
14+
return helper

mercadolibre/exceptions.py

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
class BaseError(Exception):
2+
pass
3+
4+
5+
class InvalidSite(BaseError):
6+
pass
7+
8+
9+
class TokenExpired(BaseError):
10+
pass

0 commit comments

Comments
 (0)