Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .hgignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
syntax: glob
*.pyc
*.orig
python_usps.egg-info
8 changes: 4 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

from setuptools import setup, find_packages

VERSION = '0.0.1'
VERSION = '0.0.2'
LONG_DESC = """\
A python wrapper to the USPS api, currently only supports the address information api
A python wrapper to the USPS API
"""

setup(name='python-usps',
version=VERSION,
description="A python wrapper to the USPS api, currently only supports the address information api",
description="A python wrapper to the USPS API",
long_description=LONG_DESC,
classifiers=[
'Programming Language :: Python',
Expand All @@ -26,7 +26,7 @@
maintainer_email = 'zbyte64@gmail.com',
url='http://github.com/cuker/python-usps',
license='New BSD License',
packages=find_packages(exclude=['ez_setup', 'usps', 'tests']),
packages=find_packages(exclude=['ez_setup']),
zip_safe=False,
install_requires=[
],
Expand Down
338 changes: 315 additions & 23 deletions tests/tests.py

Large diffs are not rendered by default.

106 changes: 0 additions & 106 deletions usps/addressinformation/base.py

This file was deleted.

4 changes: 1 addition & 3 deletions usps/addressinformation/__init__.py → usps/api/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from base import AddressValidate, ZipCodeLookup, CityStateLookup, USPSXMLError

USPS_CONNECTION = 'http://production.shippingapis.com/ShippingAPI.dll'
USPS_CONNECTION_TEST_SECURE = 'https://secure.shippingapis.com/ShippingAPITest.dll'
USPS_CONNECTION_TEST = 'http://testing.shippingapis.com/ShippingAPITest.dll'
USPS_CONNECTION_TEST = 'http://testing.shippingapis.com/ShippingAPITest.dll'
32 changes: 32 additions & 0 deletions usps/api/addressinformation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'''
See http://www.usps.com/webtools/htm/Address-Information.htm for complete documentation of the API
'''
from usps.api.base import USPSService

class AddressValidate(USPSService):
SERVICE_NAME = 'AddressValidate'
CHILD_XML_NAME = 'Address'
API = 'Verify'
PARAMETERS = ['FirmName',
'Address1',
'Address2',
'City',
'State',
'Zip5',
'Zip4',]


class ZipCodeLookup(USPSService):
SERVICE_NAME = 'ZipCodeLookup'
CHILD_XML_NAME = 'Address'
PARAMETERS = ['FirmName',
'Address1',
'Address2',
'City',
'State',]

class CityStateLookup(USPSService):
SERVICE_NAME = 'CityStateLookup'
CHILD_XML_NAME = 'ZipCode'
PARAMETERS = ['Zip5',]

89 changes: 89 additions & 0 deletions usps/api/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
"""
Base implementation of USPS service wrapper
"""

import urllib, urllib2
from usps.utils import utf8urlencode, xmltodict, dicttoxml
from usps.errors import USPSXMLError

try:
from xml.etree import ElementTree as ET
except ImportError:
from elementtree import ElementTree as ET

class USPSService(object):
"""
Base USPS Service Wrapper implementation
"""
SERVICE_NAME = ''
CHILD_XML_NAME = ''
PARAMETERS = []

@property
def API(self):
return self.SERVICE_NAME

def __init__(self, url, user_id):
self.url = url
self.user_id = user_id

def submit_xml(self, xml):
"""
submit XML to USPS
@param xml: the xml to submit
@return: the response element from USPS
"""
data = {'XML':ET.tostring(xml),
'API':self.API}
response = urllib2.urlopen(self.url, utf8urlencode(data))
root = ET.parse(response).getroot()
if root.tag == 'Error':
raise USPSXMLError(root)
error = root.find('.//Error')
if error:
raise USPSXMLError(error)
return root

def parse_xml(self, xml):
"""
Parse the response from USPS into a dictionary
@param xml: the xml to parse
@return: a dictionary representing the XML response from USPS
"""
items = list()
for item in xml.getchildren():#xml.findall(self.SERVICE_NAME+'Response'):
items.append(xmltodict(item))
return items

def make_xml(self, data, user_id):
"""
Transform the data provided to an XML fragment
@param userid: the USPS API user id
@param data: the data to serialize and send to USPS
@return: an XML fragment representing data
"""
root = ET.Element(self.SERVICE_NAME+'Request')
root.attrib['USERID'] = user_id
index = 0
for data_dict in data:
data_xml = dicttoxml(data_dict, self.CHILD_XML_NAME, self.PARAMETERS)
data_xml.attrib['ID'] = str(index)

root.append(data_xml)
index += 1
return root

def execute(self,data, user_id=None):
"""
Create XML from data dictionary, submit it to
the USPS API and parse the response

@param user_id: a USPS user id
@param data: the data to serialize and submit
@return: the response from USPS as a dictionary
"""
if user_id is None:
user_id = self.user_id

xml = self.make_xml(data, user_id)
return self.parse_xml(self.submit_xml(xml))
50 changes: 50 additions & 0 deletions usps/api/ratecalculator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""
Rate Calculator classes
"""
from usps.api.base import USPSService

class DomesticRateCalculator(USPSService):
"""
Calculator for domestic shipping rates
"""
SERVICE_NAME = 'RateV3'
CHILD_XML_NAME = 'Package'

PARAMETERS = ['Service',
'FirstClassMailType',
'ZipOrigination',
'ZipDestination',
'Pounds',
'Ounces',
'Container',
'Size',
'Width',
'Length',
'Height',
'Girth',
'Machinable',
'ReturnLocations',
'ShipDate',
]


class InternationalRateCalculator(USPSService):
"""
Calculator for international shipping rates
"""
SERVICE_NAME = 'IntlRate'
CHILD_XML_NAME = 'Package'
PARAMETERS = [
'Pounds',
'Ounces',
'Machinable',
'MailType',
'GXG',
'Length',
'Width',
'Height',
'POBoxFlag',
'GiftFlag',
'ValueOfContents',
'Country',
]
Loading