Skip to content

Commit

Permalink
Merge pull request #1 from bimusiek/clickcollect
Browse files Browse the repository at this point in the history
Clickcollect
  • Loading branch information
bimusiek committed Apr 29, 2015
2 parents 79f00db + 37f5ed0 commit 00a753d
Show file tree
Hide file tree
Showing 5 changed files with 272 additions and 6 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ ebaysdk.egg-info/
*.swp
*.pyc
.svn
.idea
2 changes: 1 addition & 1 deletion ebaysdk/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import platform
import logging

__version__ = '2.1.1-dev2'
__version__ = '2.1.1-dev3'
Version = __version__ # for backware compatibility

try:
Expand Down
14 changes: 9 additions & 5 deletions ebaysdk/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,11 +132,7 @@ def build_request(self, verb, data, verb_attrs):
self._request_dict = data
self._request_id = uuid.uuid4()

url = "%s://%s%s" % (
HTTP_SSL[self.config.get('https', False)],
self.config.get('domain'),
self.config.get('uri')
)
url = self.build_request_url(verb)

headers = self.build_request_headers(verb)
headers.update({'User-Agent': UserAgent,
Expand All @@ -150,6 +146,14 @@ def build_request(self, verb, data, verb_attrs):

self.request = request.prepare()

def build_request_url(self, verb):
url = "%s://%s%s" % (
HTTP_SSL[self.config.get('https', False)],
self.config.get('domain'),
self.config.get('uri')
)
return url

def execute_request(self):

log.debug("REQUEST (%s): %s %s" \
Expand Down
259 changes: 259 additions & 0 deletions ebaysdk/inventorymanagement/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
# -*- coding: utf-8 -*-

'''
Authored by: Michal Hernas
Licensed under CDDL 1.0
'''

import os

from ebaysdk import log
from ebaysdk.connection import BaseConnection
from ebaysdk.exception import RequestPaginationError, PaginationLimit
from ebaysdk.config import Config
from ebaysdk.utils import dict2xml

class Connection(BaseConnection):
"""Connection class for the Inventory Management service
API documentation:
http://developer.ebay.com/Devzone/store-pickup/InventoryManagement/index.html
Supported calls:
AddInventory
AddInventoryLocation
DeleteInventory
DeleteInventoryLocation
(all others, see API docs)
Doctests:
Create location first
>>> f = Connection(config_file=os.environ.get('EBAY_YAML'), debug=False)
>>> retval = f.execute('AddInventoryLocation', {
... 'Address1': u'Alexanderplatz 12',
... 'Address2': u'Gebaude 6',
... 'City': u'Berlin',
... 'Country': u'DE',
... 'PostalCode': u'13355',
... 'Latitude': u'37.374488',
... 'Longitude': u'-122.032876',
... 'LocationID': u'ebaysdk_test',
... 'LocationType': u'STORE',
... 'Phone': u'(408)408-4080',
... 'URL': u'http://store.com',
... 'UTCOffset': u'+02:00',
... 'Name': 'Test',
... 'Region': 'Berlin',
... 'PickupInstructions': 'Pick it up soon',
... 'Hours': [{'Day': {'DayOfWeek': 1, 'Interval': {'Open': '08:00:00', 'Close': '10:00:00'}}}]
... })
>>> error = f.error()
>>> if not f.error():
... print(f.response.reply.LocationID.lower())
ebaysdk_test
And now add item it it
>>> f = Connection(config_file=os.environ.get('EBAY_YAML'), debug=False)
>>> retval = f.execute('AddInventory', {"SKU": "SKU_TEST", "Locations": {"Location": [
... {"Availability": "IN_STOCK", "LocationID": "ebaysdk_test", "Quantity": 10}
... ]}})
>>> error = f.error()
>>> if not f.error():
... print(f.response.reply.SKU.lower())
sku_test
Delete item from all locations
>>> f = Connection(config_file=os.environ.get('EBAY_YAML'), debug=False)
>>> retval = f.execute('DeleteInventory', {"SKU": "SKU_TEST", "Confirm": 'true'})
>>> error = f.error()
>>> if not f.error():
... print(f.response.reply.SKU.lower())
sku_test
Delete location
>>> f = Connection(config_file=os.environ.get('EBAY_YAML'), debug=False)
>>> retval = f.execute('DeleteInventoryLocation', {"LocationID": "ebaysdk_test"})
>>> error = f.error()
>>> if not f.error():
... print(f.response.reply.LocationID.lower())
ebaysdk_test
"""

def __init__(self, **kwargs):
"""Finding class constructor.
Keyword arguments:
domain -- API endpoint (default: svcs.ebay.com)
config_file -- YAML defaults (default: ebay.yaml)
debug -- debugging enabled (default: False)
warnings -- warnings enabled (default: False)
uri -- API endpoint uri (default: /services/search/FindingService/v1)
token -- eBay application/user token
version -- version number (default: 1.0.0)
https -- execute of https (default: False)
proxy_host -- proxy hostname
proxy_port -- proxy port number
timeout -- HTTP request timeout (default: 20)
parallel -- ebaysdk parallel object
response_encoding -- API encoding (default: XML)
request_encoding -- API encoding (default: XML)
"""

super(Connection, self).__init__(method='POST', **kwargs)

self.config=Config(domain=kwargs.get('domain', 'api.ebay.com'),
connection_kwargs=kwargs,
config_file=kwargs.get('config_file', 'ebay.yaml'))

# override yaml defaults with args sent to the constructor
self.config.set('domain', kwargs.get('domain', 'api.ebay.com'))
self.config.set('uri', '/selling/inventory/v1')
self.config.set('https', True)
self.config.set('warnings', True)
self.config.set('errors', True)
self.config.set('siteid', None)
self.config.set('response_encoding', 'XML')
self.config.set('request_encoding', 'XML')
self.config.set('proxy_host', None)
self.config.set('proxy_port', None)
self.config.set('token', None)
self.config.set('iaf_token', None)
self.config.set('appid', None)
self.config.set('version', '1.0.0')
self.config.set('service', 'InventoryManagement')
self.config.set('doc_url', 'http://developer.ebay.com/Devzone/store-pickup/InventoryManagement/index.html')

self.datetime_nodes = ['starttimefrom', 'timestamp', 'starttime',
'endtime']
self.base_list_nodes = [
]

endpoints = {
'addinventorylocation': 'locations/delta/add',
'addinventory': 'inventory/delta/add',
'deleteinventory': 'inventory/delta/delete',
'deleteinventorylocation': 'locations/delta/delete',
}

def build_request_url(self, verb):
url = super(Connection, self).build_request_url(verb)
endpoint = self.endpoints[verb.lower()]
return "{0}/{1}".format(url, endpoint)

def build_request_headers(self, verb):
return {
"Authorization": "TOKEN {0}".format(self.config.get('token')),
"Content-Type": "application/xml"
}

def build_request_data(self, verb, data, verb_attrs):
xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
xml += "<" + verb + "Request>"
xml += dict2xml(data)
xml += "</" + verb + "Request>"

return xml

def warnings(self):
warning_string = ""

if len(self._resp_body_warnings) > 0:
warning_string = "%s: %s" \
% (self.verb, ", ".join(self._resp_body_warnings))

return warning_string


def _get_resp_body_errors(self):
"""Parses the response content to pull errors.
Child classes should override this method based on what the errors in the
XML response body look like. They can choose to look at the 'ack',
'Errors', 'errorMessage' or whatever other fields the service returns.
the implementation below is the original code that was part of error()
"""

if self._resp_body_errors and len(self._resp_body_errors) > 0:
return self._resp_body_errors

errors = []
warnings = []
resp_codes = []

if self.verb is None:
return errors

dom = self.response.dom()
if dom is None:
return errors

for e in dom.findall('Errors'):
eSeverity = None
eClass = None
eShortMsg = None
eLongMsg = None
eCode = None

try:
eSeverity = e.findall('SeverityCode')[0].text
except IndexError:
pass

try:
eClass = e.findall('ErrorClassification')[0].text
except IndexError:
pass

try:
eCode = e.findall('ErrorCode')[0].text
except IndexError:
pass

try:
eShortMsg = e.findall('ShortMessage')[0].text
except IndexError:
pass

try:
eLongMsg = e.findall('LongMessage')[0].text
except IndexError:
pass

try:
eCode = e.findall('ErrorCode')[0].text
try:
int_code = int(eCode)
except ValueError:
int_code = None

if int_code and int_code not in resp_codes:
resp_codes.append(int_code)

except IndexError:
pass

msg = "Class: %s, Severity: %s, Code: %s, %s%s" \
% (eClass, eSeverity, eCode, eShortMsg, eLongMsg)

if eSeverity == 'Warning':
warnings.append(msg)
else:
errors.append(msg)

self._resp_body_warnings = warnings
self._resp_body_errors = errors
self._resp_codes = resp_codes

if self.config.get('warnings') and len(warnings) > 0:
log.warn("%s: %s\n\n" % (self.verb, "\n".join(warnings)))

if self.response.reply.Ack == 'Failure':
if self.config.get('errors'):
log.error("%s: %s\n\n" % (self.verb, "\n".join(errors)))

return errors

return []
2 changes: 2 additions & 0 deletions tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import ebaysdk.soa.finditem
import ebaysdk.finding
import ebaysdk.poller.orders
import ebaysdk.inventorymanagement

# does not pass with python3.3
try:
Expand All @@ -41,6 +42,7 @@ def getTestSuite():
suite.addTest(doctest.DocTestSuite(ebaysdk.trading))
suite.addTest(doctest.DocTestSuite(ebaysdk.merchandising))
suite.addTest(doctest.DocTestSuite(ebaysdk.finding))
suite.addTest(doctest.DocTestSuite(ebaysdk.inventorymanagement))

if not sys.version_info[0] >= 3 \
and sys.modules.has_key('grequests') is True:
Expand Down

0 comments on commit 00a753d

Please sign in to comment.