Package workspace ::
Package python-fedex ::
Package fedex ::
Module base_service
|
|
1 """
2 The L{base_service} module contains classes that form the low level foundations
3 of the Web Service API. Things that many different kinds of requests have in
4 common may be found here.
5
6 In particular, the L{FedexBaseService} class handles most of the basic,
7 repetetive setup work that most requests do.
8 """
9 import os
10 import logging
11 import suds
12 from suds.client import Client
13
15 """
16 Serves as the base exception that other service-related exception objects
17 are sub-classed from.
18 """
20 self.error_code = error_code
21 self.value = value
23 return "%s (Error code: %s)" % (repr(self.value), self.error_code)
24
26 """
27 The request could not be handled at this time. This is generally a server
28 problem.
29 """
30 pass
31
33 """
34 These are generally problems with the client-provided data.
35 """
36 pass
37
39 """
40 There is probably a problem in the data you provided.
41 """
43 self.error_code = -1
44 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."
45
47 """
48 This class is the master class for all Fedex request objects. It gets all
49 of the common SOAP objects created via suds and populates them with
50 values from a L{FedexConfig} object, along with keyword arguments
51 via L{__init__}.
52
53 @note: This object should never be used directly, use one of the included
54 sub-classes.
55 """
56 - def __init__(self, config_obj, wsdl_name, *args, **kwargs):
57 """
58 This constructor should only be called by children of the class. As is
59 such, only the optional keyword arguments caught by C{**kwargs} will
60 be documented.
61
62 @type customer_transaction_id: L{str}
63 @keyword customer_transaction_id: A user-specified identifier to
64 differentiate this transaction from others. This value will be
65 returned with the response from Fedex.
66 """
67 self.logger = logging.getLogger('fedex')
68 """@ivar: Python logger instance with name 'fedex'."""
69 self.config_obj = config_obj
70 """@ivar: The FedexConfig object to pull auth info from."""
71
72
73
74 if config_obj.use_test_server:
75 self.logger.info("Using test server.")
76 self.wsdl_path = os.path.join(config_obj.wsdl_path,
77 'test_server_wsdl', wsdl_name)
78 else:
79 self.logger.info("Using production server.")
80 self.wsdl_path = os.path.join(config_obj.wsdl_path, wsdl_name)
81
82 self.client = Client('file://%s' % self.wsdl_path)
83
84 self.VersionId = None
85 """@ivar: Holds details on the version numbers of the WSDL."""
86 self.WebAuthenticationDetail = None
87 """@ivar: WSDL object that holds authentication info."""
88 self.ClientDetail = None
89 """@ivar: WSDL object that holds client account details."""
90 self.response = None
91 """@ivar: The response from Fedex. You will want to pick what you
92 want out here here. This object does have a __str__() method,
93 you'll want to print or log it to see what possible values
94 you can pull."""
95 self.TransactionDetail = None
96 """@ivar: Holds customer-specified transaction IDs."""
97
98 self.__set_web_authentication_detail()
99 self.__set_client_detail()
100 self.__set_version_id()
101 self.__set_transaction_detail(*args, **kwargs)
102 self._prepare_wsdl_objects()
103
105 """
106 Sets up the WebAuthenticationDetail node. This is required for all
107 requests.
108 """
109
110 WebAuthenticationCredential = self.client.factory.create('WebAuthenticationCredential')
111 WebAuthenticationCredential.Key = self.config_obj.key
112 WebAuthenticationCredential.Password = self.config_obj.password
113
114
115 WebAuthenticationDetail = self.client.factory.create('WebAuthenticationDetail')
116 WebAuthenticationDetail.UserCredential = WebAuthenticationCredential
117 self.WebAuthenticationDetail = WebAuthenticationDetail
118
120 """
121 Sets up the ClientDetail node, which is required for all shipping
122 related requests.
123 """
124 ClientDetail = self.client.factory.create('ClientDetail')
125 ClientDetail.AccountNumber = self.config_obj.account_number
126 ClientDetail.MeterNumber = self.config_obj.meter_number
127 ClientDetail.IntegratorId = self.config_obj.integrator_id
128 self.ClientDetail = ClientDetail
129
131 """
132 Checks kwargs for 'customer_transaction_id' and sets it if present.
133 """
134 customer_transaction_id = kwargs.get('customer_transaction_id', False)
135 if customer_transaction_id:
136 TransactionDetail = self.client.factory.create('TransactionDetail')
137 TransactionDetail.CustomerTransactionId = customer_transaction_id
138 self.logger.debug(TransactionDetail)
139 self.TransactionDetail = TransactionDetail
140
142 """
143 Pulles the versioning info for the request from the child request.
144 """
145 VersionId = self.client.factory.create('VersionId')
146 VersionId.ServiceId = self._version_info['service_id']
147 VersionId.Major = self._version_info['major']
148 VersionId.Intermediate = self._version_info['intermediate']
149 VersionId.Minor = self._version_info['minor']
150 self.logger.debug(VersionId)
151 self.VersionId = VersionId
152
154 """
155 This method should be over-ridden on each sub-class. It instantiates
156 any of the required WSDL objects so the user can just print their
157 __str__() methods and see what they need to fill in.
158 """
159 pass
160
162 """
163 This checks the response for general Fedex errors that aren't related
164 to any one WSDL.
165 """
166 if self.response.HighestSeverity == "FAILURE":
167 for notification in self.response.Notifications:
168 if notification.Severity == "FAILURE":
169 raise FedexFailure(notification.Code,
170 notification.Message)
171
173 """
174 Override this in each service module to check for errors that are
175 specific to that module. For example, invalid tracking numbers in
176 a Tracking request.
177 """
178 if self.response.HighestSeverity == "ERROR":
179 for notification in self.response.Notifications:
180 if notification.Severity == "ERROR":
181 raise FedexError(notification.Code,
182 notification.Message)
183
185 """
186 Creates and returns a WSDL object of the specified type.
187 """
188 return self.client.factory.create(type_name)
189
191 """
192 Sends the assembled request on the child object.
193 @type send_function: function reference
194 @keyword send_function: A function reference (passed without the
195 parenthesis) to a function that will send the request. This
196 allows for overriding the default function in cases such as
197 validation requests.
198 """
199
200 try:
201
202
203 if send_function:
204
205 self.response = send_function()
206 else:
207
208 self.response = self._assemble_and_send_request()
209 except suds.WebFault:
210
211
212
213 raise SchemaValidationError()
214
215
216
217 self.__check_response_for_fedex_error()
218
219
220 self._check_response_for_request_errors()
221
222
223 self.logger.debug("== FEDEX QUERY RESULT ==")
224 self.logger.debug(self.response)
225