Skip to content

Commit 133040a

Browse files
authored
Merge pull request #56 from PurplShip/document-release-2020.4
Document release 2020.4
2 parents b8040a5 + 52bc987 commit 133040a

File tree

43 files changed

+704
-234
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+704
-234
lines changed

LICENSE

Lines changed: 170 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,174 @@
11
Copyright (c) Contributed Systems LLC
22

3-
PurplShip is an Open Source project licensed under the terms of the LGPLv3 license.
4-
Please see <http://www.gnu.org/licenses/lgpl-3.0.html> for license text.
3+
PurplShip is an Open Source project licensed under the terms of the LGPLv3 license as included below.
54

6-
PurplShip Pro has a commercial-friendly license allowing private forks
7-
and modifications of PurplShip.
5+
PurplShip Pro has a commercial-friendly license allowing private forks and modifications of PurplShip.
86
Please talk to us at https://purplship.com for more details.
7+
8+
_____________________________________________________________________________
9+
10+
GNU LESSER GENERAL PUBLIC LICENSE
11+
Version 3, 29 June 2007
12+
13+
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
14+
Everyone is permitted to copy and distribute verbatim copies
15+
of this license document, but changing it is not allowed.
16+
17+
18+
This version of the GNU Lesser General Public License incorporates
19+
the terms and conditions of version 3 of the GNU General Public
20+
License, supplemented by the additional permissions listed below.
21+
22+
0. Additional Definitions.
23+
24+
As used herein, "this License" refers to version 3 of the GNU Lesser
25+
General Public License, and the "GNU GPL" refers to version 3 of the GNU
26+
General Public License.
27+
28+
"The Library" refers to a covered work governed by this License,
29+
other than an Application or a Combined Work as defined below.
30+
31+
An "Application" is any work that makes use of an interface provided
32+
by the Library, but which is not otherwise based on the Library.
33+
Defining a subclass of a class defined by the Library is deemed a mode
34+
of using an interface provided by the Library.
35+
36+
A "Combined Work" is a work produced by combining or linking an
37+
Application with the Library. The particular version of the Library
38+
with which the Combined Work was made is also called the "Linked
39+
Version".
40+
41+
The "Minimal Corresponding Source" for a Combined Work means the
42+
Corresponding Source for the Combined Work, excluding any source code
43+
for portions of the Combined Work that, considered in isolation, are
44+
based on the Application, and not on the Linked Version.
45+
46+
The "Corresponding Application Code" for a Combined Work means the
47+
object code and/or source code for the Application, including any data
48+
and utility programs needed for reproducing the Combined Work from the
49+
Application, but excluding the System Libraries of the Combined Work.
50+
51+
1. Exception to Section 3 of the GNU GPL.
52+
53+
You may convey a covered work under sections 3 and 4 of this License
54+
without being bound by section 3 of the GNU GPL.
55+
56+
2. Conveying Modified Versions.
57+
58+
If you modify a copy of the Library, and, in your modifications, a
59+
facility refers to a function or data to be supplied by an Application
60+
that uses the facility (other than as an argument passed when the
61+
facility is invoked), then you may convey a copy of the modified
62+
version:
63+
64+
a) under this License, provided that you make a good faith effort to
65+
ensure that, in the event an Application does not supply the
66+
function or data, the facility still operates, and performs
67+
whatever part of its purpose remains meaningful, or
68+
69+
b) under the GNU GPL, with none of the additional permissions of
70+
this License applicable to that copy.
71+
72+
3. Object Code Incorporating Material from Library Header Files.
73+
74+
The object code form of an Application may incorporate material from
75+
a header file that is part of the Library. You may convey such object
76+
code under terms of your choice, provided that, if the incorporated
77+
material is not limited to numerical parameters, data structure
78+
layouts and accessors, or small macros, inline functions and templates
79+
(ten or fewer lines in length), you do both of the following:
80+
81+
a) Give prominent notice with each copy of the object code that the
82+
Library is used in it and that the Library and its use are
83+
covered by this License.
84+
85+
b) Accompany the object code with a copy of the GNU GPL and this license
86+
document.
87+
88+
4. Combined Works.
89+
90+
You may convey a Combined Work under terms of your choice that,
91+
taken together, effectively do not restrict modification of the
92+
portions of the Library contained in the Combined Work and reverse
93+
engineering for debugging such modifications, if you also do each of
94+
the following:
95+
96+
a) Give prominent notice with each copy of the Combined Work that
97+
the Library is used in it and that the Library and its use are
98+
covered by this License.
99+
100+
b) Accompany the Combined Work with a copy of the GNU GPL and this license
101+
document.
102+
103+
c) For a Combined Work that displays copyright notices during
104+
execution, include the copyright notice for the Library among
105+
these notices, as well as a reference directing the user to the
106+
copies of the GNU GPL and this license document.
107+
108+
d) Do one of the following:
109+
110+
0) Convey the Minimal Corresponding Source under the terms of this
111+
License, and the Corresponding Application Code in a form
112+
suitable for, and under terms that permit, the user to
113+
recombine or relink the Application with a modified version of
114+
the Linked Version to produce a modified Combined Work, in the
115+
manner specified by section 6 of the GNU GPL for conveying
116+
Corresponding Source.
117+
118+
1) Use a suitable shared library mechanism for linking with the
119+
Library. A suitable mechanism is one that (a) uses at run time
120+
a copy of the Library already present on the user's computer
121+
system, and (b) will operate properly with a modified version
122+
of the Library that is interface-compatible with the Linked
123+
Version.
124+
125+
e) Provide Installation Information, but only if you would otherwise
126+
be required to provide such information under section 6 of the
127+
GNU GPL, and only to the extent that such information is
128+
necessary to install and execute a modified version of the
129+
Combined Work produced by recombining or relinking the
130+
Application with a modified version of the Linked Version. (If
131+
you use option 4d0, the Installation Information must accompany
132+
the Minimal Corresponding Source and Corresponding Application
133+
Code. If you use option 4d1, you must provide the Installation
134+
Information in the manner specified by section 6 of the GNU GPL
135+
for conveying Corresponding Source.)
136+
137+
5. Combined Libraries.
138+
139+
You may place library facilities that are a work based on the
140+
Library side by side in a single library together with other library
141+
facilities that are not Applications and are not covered by this
142+
License, and convey such a combined library under terms of your
143+
choice, if you do both of the following:
144+
145+
a) Accompany the combined library with a copy of the same work based
146+
on the Library, uncombined with any other library facilities,
147+
conveyed under the terms of this License.
148+
149+
b) Give prominent notice with the combined library that part of it
150+
is a work based on the Library, and explaining where to find the
151+
accompanying uncombined form of the same work.
152+
153+
6. Revised Versions of the GNU Lesser General Public License.
154+
155+
The Free Software Foundation may publish revised and/or new versions
156+
of the GNU Lesser General Public License from time to time. Such new
157+
versions will be similar in spirit to the present version, but may
158+
differ in detail to address new problems or concerns.
159+
160+
Each version is given a distinguishing version number. If the
161+
Library as you received it specifies that a certain numbered version
162+
of the GNU Lesser General Public License "or any later version"
163+
applies to it, you have the option of following the terms and
164+
conditions either of that published version or of any later version
165+
published by the Free Software Foundation. If the Library as you
166+
received it does not specify a version number of the GNU Lesser
167+
General Public License, you may choose any version of the GNU Lesser
168+
General Public License ever published by the Free Software Foundation.
169+
170+
If the Library as you received it specifies that a proxy can decide
171+
whether future versions of the GNU Lesser General Public License shall
172+
apply, that proxy's public statement of acceptance of any version is
173+
permanent authorization for you to choose that version for the
174+
Library.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# PurplShip (Multi-carrier API SDK)
1+
# PurplShip (Multi-carrier API Library)
22

33
![PuprlShip Core Package](https://github.com/PurplShip/purplship/workflows/PuprlShip%20Core%20Package/badge.svg)
44
[![codecov](https://codecov.io/gh/PurplShip/purplship/branch/master/graph/badge.svg)](https://codecov.io/gh/PurplShip/purplship)

purplship/carriers/australiapost/shipping/shipping_price.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ def shipping_price_request(payload: RateRequest) -> Serializable[ShippingPriceRe
7777
request = ShippingPriceRequest(
7878
shipments=[
7979
Shipment(
80-
shipment_reference=payload.parcel.reference,
80+
shipment_reference=payload.reference,
8181
sender_references=None,
8282
goods_descriptions=None,
8383
despatch_date=None,
@@ -119,7 +119,7 @@ def shipping_price_request(payload: RateRequest) -> Serializable[ShippingPriceRe
119119
authorisation_number=None,
120120
items=[
121121
Item(
122-
item_reference=payload.parcel.reference,
122+
item_reference=payload.reference,
123123
product_id=payload.parcel.id,
124124
item_description=payload.parcel.description,
125125
length=payload.parcel.length,

purplship/carriers/canadapost/shipment/__init__.py

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
from functools import partial
12
from typing import Tuple, List
2-
from purplship.core.utils.xml import Element
3-
from purplship.core.utils.serializable import Serializable
3+
from purplship.core.utils import Element, to_xml, Serializable
4+
from purplship.core.utils.pipeline import Pipeline, Job
45
from purplship.core.models import ShipmentRequest, ShipmentDetails, Message
56
from purplship.carriers.canadapost.utils import Settings
67
from purplship.carriers.canadapost.shipment.contract_shipment import (
@@ -21,9 +22,27 @@ def parse_shipment_response(
2122
return parse_contract_shipment_response(response, settings)
2223

2324

24-
def shipment_request(
25-
payload: ShipmentRequest, settings: Settings
26-
) -> Serializable[Element]:
27-
if settings.contract_id is None or settings.contract_id == "":
28-
return non_contract_shipment_request(payload, settings)
29-
return contract_shipment_request(payload, settings)
25+
def shipment_request(payload: ShipmentRequest, settings: Settings) -> Serializable[Pipeline]:
26+
requests: Pipeline = Pipeline(
27+
create_shipment=lambda *_: partial(_create_shipment, payload=payload, settings=settings)(),
28+
retrieve_label=partial(_get_shipment_label),
29+
)
30+
return Serializable(requests)
31+
32+
33+
def _create_shipment(payload: ShipmentRequest, settings: Settings) -> Job:
34+
no_contract = settings.contract_id is None or settings.contract_id == ""
35+
create_shipment = (non_contract_shipment_request if no_contract else contract_shipment_request)
36+
return Job(
37+
id="non_contract_shipment" if no_contract else "contract_shipment",
38+
data=create_shipment(payload, settings)
39+
)
40+
41+
42+
def _get_shipment_label(shipement_response: str) -> Job:
43+
links = to_xml(shipement_response).xpath(".//*[local-name() = $name]", name="link")
44+
label_url = next(
45+
(link.get("href") for link in links if link.get("rel") == "label"),
46+
None,
47+
)
48+
return Job(id="shipment_label", data=label_url, fallback="")

purplship/carriers/canadapost/shipment/contract_shipment.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ def compute_amount(code: str, _: Any):
216216
else None,
217217
references=ReferencesType(
218218
cost_centre=None,
219-
customer_ref_1=payload.parcel.reference,
219+
customer_ref_1=payload.reference,
220220
customer_ref_2=None,
221221
),
222222
settlement_info=SettlementInfoType(

purplship/carriers/canadapost/shipment/non_contract_shipment.py

Lines changed: 8 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
OptionCode,
55
ServiceType,
66
PackagePresets,
7-
PaymentType,
87
)
98
from purplship.carriers.canadapost.utils import Settings
109
from purplship.core.models import (
@@ -20,7 +19,7 @@
2019
NonContractShipmentInfoType,
2120
DeliverySpecType,
2221
SenderType,
23-
AddressDetailsType,
22+
DomesticAddressDetailsType,
2423
DestinationType,
2524
DestinationAddressDetailsType,
2625
ParcelCharacteristicsType,
@@ -33,7 +32,6 @@
3332
OptionType,
3433
CustomsType,
3534
PreferencesType,
36-
SettlementInfoType,
3735
)
3836

3937

@@ -65,9 +63,7 @@ def _extract_shipment(response: Element, settings: Settings) -> ShipmentDetails:
6563
)
6664

6765

68-
def non_contract_shipment_request(
69-
payload: ShipmentRequest, settings: Settings
70-
) -> Serializable[NonContractShipmentType]:
66+
def non_contract_shipment_request(payload: ShipmentRequest, settings: Settings) -> Serializable[NonContractShipmentType]:
7167
parcel_preset = (
7268
PackagePresets[payload.parcel.package_preset].value
7369
if payload.parcel.package_preset
@@ -93,11 +89,6 @@ def compute_amount(code: str, _: Any):
9389
for name, value in payload.options.items()
9490
if name in OptionCode.__members__
9591
}
96-
payment_type = (
97-
PaymentType[payload.payment.paid_by].value
98-
if payload.payment is not None
99-
else None
100-
)
10192

10293
request = NonContractShipmentType(
10394
requested_shipping_point=None,
@@ -107,12 +98,11 @@ def compute_amount(code: str, _: Any):
10798
name=payload.shipper.person_name,
10899
company=payload.shipper.company_name,
109100
contact_phone=payload.shipper.phone_number,
110-
address_details=AddressDetailsType(
101+
address_details=DomesticAddressDetailsType(
111102
address_line_1=concat_str(payload.shipper.address_line1, join=True),
112103
address_line_2=concat_str(payload.shipper.address_line2, join=True),
113104
city=payload.shipper.city,
114105
prov_state=payload.shipper.state_code,
115-
country_code=payload.shipper.country_code,
116106
postal_zip_code=payload.shipper.postal_code,
117107
),
118108
),
@@ -166,14 +156,13 @@ def compute_amount(code: str, _: Any):
166156
if options.notification
167157
else None,
168158
preferences=PreferencesType(
169-
service_code=None,
170159
show_packing_instructions=True,
171160
show_postage_rate=True,
172-
show_insured_value=True,
161+
show_insured_value=("insurance" in payload.options)
173162
),
174163
references=ReferencesType(
175164
cost_centre=None,
176-
customer_ref_1=payload.parcel.reference,
165+
customer_ref_1=payload.reference,
177166
customer_ref_2=None,
178167
),
179168
customs=CustomsType(
@@ -204,17 +193,7 @@ def compute_amount(code: str, _: Any):
204193
)
205194
if payload.customs is not None
206195
else None,
207-
settlement_info=SettlementInfoType(
208-
paid_by_customer=(
209-
payload.payment.account_number
210-
if payload.payment is not None
211-
else settings.customer_number
212-
),
213-
contract_id=settings.contract_id,
214-
cif_shipment=None,
215-
intended_method_of_payment=payment_type,
216-
promo_code=None,
217-
),
196+
settlement_info=None,
218197
),
219198
)
220199
return Serializable(request, _request_serializer)
@@ -223,6 +202,6 @@ def compute_amount(code: str, _: Any):
223202
def _request_serializer(request: NonContractShipmentType) -> str:
224203
return export(
225204
request,
226-
name_="shipment",
227-
namespacedef_="xmlns=http://www.canadapost.ca/ws/shipment-v8”",
205+
name_="non-contract-shipment",
206+
namespacedef_='xmlns="http://www.canadapost.ca/ws/ncshipment-v4"',
228207
)

purplship/carriers/canadapost/units.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,16 @@ class PackagePresets(Flag):
3030
width=46.0, height=46.0, length=40.6
3131
)
3232
canadapost_xexpresspost_certified_envelope = PackagePreset(
33-
width=26.0, height=15.9, weight=0.5, thickness=1.5
33+
width=26.0, height=15.9, weight=0.5, length=1.5
3434
)
3535
canadapost_xexpresspost_national_large_envelope = PackagePreset(
36-
width=40.0, height=29.2, weight=1.36, thickness=1.5
36+
width=40.0, height=29.2, weight=1.36, length=1.5
3737
)
3838
canadapost_xexpresspost_regional_small_envelope = PackagePreset(
39-
width=26.0, height=15.9, weight=0.5, thickness=1.5
39+
width=26.0, height=15.9, weight=0.5, length=1.5
4040
)
4141
canadapost_xexpresspost_regional_large_envelope = PackagePreset(
42-
width=40.0, height=29.2, weight=1.36, thickness=1.5
42+
width=40.0, height=29.2, weight=1.36, length=1.5
4343
)
4444

4545

0 commit comments

Comments
 (0)