Skip to content

Commit

Permalink
PEP8 pass.
Browse files Browse the repository at this point in the history
  • Loading branch information
gtaylor committed Feb 6, 2015
1 parent c3a9815 commit 5150cfd
Show file tree
Hide file tree
Showing 11 changed files with 196 additions and 136 deletions.
5 changes: 3 additions & 2 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
Change Log
==========

1.0.15
------
1.1.0
-----

* A quick PEP8 pass on most of the codebase. Yucky. (gtaylor)
* Changing recommended install method to use pip + PyPi. (radlws)
* Updated rate_request and freight_rate_request examples for WSDL v16
compatibility. (foxxyz)
Expand Down
30 changes: 9 additions & 21 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,26 @@ Python FedEx SOAP API Module

:Author: Greg Taylor
:License: BSD
:Status: Stable

What is it?
-----------

A light wrapper around FedEx's Webservice Soap API.

Requirements
------------

The only dependency is the suds SOAP module, which is available at::
https://fedorahosted.org/suds/
You may also use easy_install or pip to install from PyPi::

pip install suds
A light wrapper around FedEx's Webservice Soap API. We don't do much of any
validation, but we'll help you sort through the pile of SOAP objects FedEx
uses.

Installation
------------

As root/admin on your machine::

python setup.py install
Pip install, bringing in all dependencies::
The easiest way is via pip or easy_install::

pip install fedex

Documentation
-------------

For documentation, see the project webpage at::

http://code.google.com/p/python-fedex/
Refer to the documentation_ for more details on the project.

There are also a lot of useful examples under the examples directory within
this directory.
Expand All @@ -56,3 +42,5 @@ This software is licensed under the BSD License.

python-fedex is not authored by, endorsed by, or in any way affiliated with
FedEx.

.. _documentation: https://pythonhosted.org/fedex/
2 changes: 1 addition & 1 deletion fedex/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,4 @@
our U{Google Code project<http://code.google.com/p/python-fedex/>} and enter
an issue in the U{Issue Tracker<http://code.google.com/p/python-fedex/issues/list>}.
"""
VERSION = '1.0.15'
VERSION = '1.1.0'
28 changes: 25 additions & 3 deletions fedex/base_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,55 @@
common may be found here.
In particular, the L{FedexBaseService} class handles most of the basic,
repetetive setup work that most requests do.
repetitive setup work that most requests do.
"""

import os
import logging

import suds
from suds.client import Client


class FedexBaseServiceException(Exception):
"""
Exception: Serves as the base exception that other service-related
exception objects are sub-classed from.
"""

def __init__(self, error_code, value):
self.error_code = error_code
self.value = value

def __unicode__(self):
return "%s (Error code: %s)" % (repr(self.value), self.error_code)

def __str__(self):
return self.__unicode__()


class FedexFailure(FedexBaseServiceException):
"""
Exception: The request could not be handled at this time. This is generally
a server problem.
"""

pass


class FedexError(FedexBaseServiceException):
"""
Exception: These are generally problems with the client-provided data.
"""

pass


class SchemaValidationError(FedexBaseServiceException):
"""
Exception: There is probably a problem in the data you provided.
"""

def __init__(self, fault):
self.error_code = -1
self.value = "suds encountered an error validating your data against this service's WSDL schema. Please double-check for missing or invalid values, filling all required fields."
Expand All @@ -49,6 +61,7 @@ def __init__(self, fault):
except AttributeError:
pass


class FedexBaseService(object):
"""
This class is the master class for all Fedex request objects. It gets all
Expand All @@ -59,6 +72,7 @@ class FedexBaseService(object):
@note: This object should never be used directly, use one of the included
sub-classes.
"""

def __init__(self, config_obj, wsdl_name, *args, **kwargs):
"""
This constructor should only be called by children of the class. As is
Expand All @@ -70,6 +84,7 @@ def __init__(self, config_obj, wsdl_name, *args, **kwargs):
differentiate this transaction from others. This value will be
returned with the response from Fedex.
"""

self.logger = logging.getLogger('fedex')
"""@ivar: Python logger instance with name 'fedex'."""
self.config_obj = config_obj
Expand All @@ -87,8 +102,6 @@ def __init__(self, config_obj, wsdl_name, *args, **kwargs):

self.client = Client('file:///%s' % self.wsdl_path.lstrip('/'))

#print self.client

self.VersionId = None
"""@ivar: Holds details on the version numbers of the WSDL."""
self.WebAuthenticationDetail = None
Expand All @@ -114,6 +127,7 @@ def __set_web_authentication_detail(self):
Sets up the WebAuthenticationDetail node. This is required for all
requests.
"""

# Start of the authentication stuff.
WebAuthenticationCredential = self.client.factory.create('WebAuthenticationCredential')
WebAuthenticationCredential.Key = self.config_obj.key
Expand All @@ -129,6 +143,7 @@ def __set_client_detail(self):
Sets up the ClientDetail node, which is required for all shipping
related requests.
"""

ClientDetail = self.client.factory.create('ClientDetail')
ClientDetail.AccountNumber = self.config_obj.account_number
ClientDetail.MeterNumber = self.config_obj.meter_number
Expand All @@ -141,6 +156,7 @@ def __set_transaction_detail(self, *args, **kwargs):
"""
Checks kwargs for 'customer_transaction_id' and sets it if present.
"""

customer_transaction_id = kwargs.get('customer_transaction_id', False)
if customer_transaction_id:
TransactionDetail = self.client.factory.create('TransactionDetail')
Expand All @@ -152,6 +168,7 @@ def __set_version_id(self):
"""
Pulles the versioning info for the request from the child request.
"""

VersionId = self.client.factory.create('VersionId')
VersionId.ServiceId = self._version_info['service_id']
VersionId.Major = self._version_info['major']
Expand All @@ -166,13 +183,15 @@ def __prepare_wsdl_objects(self):
any of the required WSDL objects so the user can just print their
__str__() methods and see what they need to fill in.
"""

pass

def __check_response_for_fedex_error(self):
"""
This checks the response for general Fedex errors that aren't related
to any one WSDL.
"""

if self.response.HighestSeverity == "FAILURE":
for notification in self.response.Notifications:
if notification.Severity == "FAILURE":
Expand All @@ -185,6 +204,7 @@ def _check_response_for_request_errors(self):
specific to that module. For example, invalid tracking numbers in
a Tracking request.
"""

if self.response.HighestSeverity == "ERROR":
for notification in self.response.Notifications:
if notification.Severity == "ERROR":
Expand All @@ -195,6 +215,7 @@ def create_wsdl_object_of_type(self, type_name):
"""
Creates and returns a WSDL object of the specified type.
"""

return self.client.factory.create(type_name)

def send_request(self, send_function=None):
Expand All @@ -206,6 +227,7 @@ def send_request(self, send_function=None):
allows for overriding the default function in cases such as
validation requests.
"""

# Send the request and get the response back.
try:
# If the user has overridden the send function, use theirs
Expand Down
12 changes: 10 additions & 2 deletions fedex/printers/unix.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@
installations. By "Unix", we mean Linux, Mac OS, BSD, and various flavors
of Unix.
"""

import binascii


class DirectDevicePrinter(object):
"""
This class pipes the label data directly through a /dev/* entry.
Consequently, this is very Unix/Linux specific. It *MAY* work on Mac too.
"""

def __init__(self, shipment, device="/dev/ttyS0"):
"""
Instantiates from a shipment object. You may optionally specify
Expand All @@ -19,6 +22,7 @@ def __init__(self, shipment, device="/dev/ttyS0"):
@param shipment: A Fedex ProcessShipmentRequest object to pull the
printed label data from.
"""

self.device = device
"""@ivar: A string with the path to the device to print to."""
self.shipment = shipment
Expand All @@ -32,8 +36,11 @@ def print_label(self, package_num=None):
@param package_num: 0-based index of the package to print. This is
only useful for shipments with more than one package.
"""

if package_num:
packages = [self.shipment.response.CompletedShipmentDetail.CompletedPackageDetails[package_num]]
packages = [
self.shipment.response.CompletedShipmentDetail.CompletedPackageDetails[package_num]
]
else:
packages = self.shipment.response.CompletedShipmentDetail.CompletedPackageDetails

Expand All @@ -50,6 +57,7 @@ def _print_base64(self, base64_data):
@type base64_data: L{str}
@param base64_data: The base64 encoded string for the label to print.
"""

label_file = open(self.device, "w")
label_file.write(base64_data)
label_file.close()
label_file.close()
39 changes: 24 additions & 15 deletions fedex/services/address_validation_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,46 @@
easy access. For more details on each, refer to the respective class's
documentation.
"""

from datetime import datetime
from .. base_service import FedexBaseService


class FedexAddressValidationRequest(FedexBaseService):
"""
This class allows you validate anywhere from one to a hundred addresses
in one go. Create AddressToValidate WSDL objects and add them to each
instance of this request using add_address().
"""

def __init__(self, config_obj, *args, **kwargs):
"""
@type config_obj: L{FedexConfig}
@param config_obj: A valid FedexConfig object.
"""

self._config_obj = config_obj

# Holds version info for the VersionId SOAP object.
self._version_info = {'service_id': 'aval', 'major': '2',
'intermediate': '0', 'minor': '0'}
self._version_info = {
'service_id': 'aval',
'major': '2',
'intermediate': '0',
'minor': '0'
}

self.AddressValidationOptions = None
"""@ivar: Holds the AddressValidationOptions WSDL object."""
self.addresses_to_validate = []
"""@ivar: Holds the AddressToValidate WSDL object."""
# Call the parent FedexBaseService class for basic setup work.
super(FedexAddressValidationRequest, self).__init__(self._config_obj,
'AddressValidationService_v2.wsdl',
*args, **kwargs)
super(FedexAddressValidationRequest, self).__init__(
self._config_obj, 'AddressValidationService_v2.wsdl', *args, **kwargs)

def _prepare_wsdl_objects(self):
"""
Create the data structure and get it ready for the WSDL request.
"""

# This holds some optional options for the request..
self.AddressValidationOptions = self.client.factory.create('AddressValidationOptions')

Expand All @@ -53,6 +60,7 @@ def _assemble_and_send_request(self):
@warning: NEVER CALL THIS METHOD DIRECTLY. CALL send_request(),
WHICH RESIDES ON FedexBaseService AND IS INHERITED.
"""

# We get an exception like this when specifying an IntegratorId:
# suds.TypeNotFound: Type not found: 'IntegratorId'
# Setting it to None does not seem to appease it.
Expand All @@ -62,14 +70,14 @@ def _assemble_and_send_request(self):
self.logger.debug(self.TransactionDetail)
self.logger.debug(self.VersionId)
# Fire off the query.
response = self.client.service.addressValidation(WebAuthenticationDetail=self.WebAuthenticationDetail,
ClientDetail=self.ClientDetail,
TransactionDetail=self.TransactionDetail,
Version=self.VersionId,
RequestTimestamp=datetime.now(),
Options=self.AddressValidationOptions,
AddressesToValidate=self.addresses_to_validate)
return response
return self.client.service.addressValidation(
WebAuthenticationDetail=self.WebAuthenticationDetail,
ClientDetail=self.ClientDetail,
TransactionDetail=self.TransactionDetail,
Version=self.VersionId,
RequestTimestamp=datetime.now(),
Options=self.AddressValidationOptions,
AddressesToValidate=self.addresses_to_validate)

def add_address(self, address_item):
"""
Expand All @@ -81,4 +89,5 @@ def add_address(self, address_item):
this FedexAddressValidationRequest object.
See examples/create_shipment.py for more details.
"""
self.addresses_to_validate.append(address_item)

self.addresses_to_validate.append(address_item)
Loading

0 comments on commit 5150cfd

Please sign in to comment.