karrio-laposte 2025.5rc1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3 @@
1
+ from karrio.mappers.laposte.mapper import Mapper
2
+ from karrio.mappers.laposte.proxy import Proxy
3
+ from karrio.mappers.laposte.settings import Settings
@@ -0,0 +1,22 @@
1
+ """Karrio La Poste client mapper."""
2
+
3
+ import typing
4
+ import karrio.lib as lib
5
+ import karrio.api.mapper as mapper
6
+ import karrio.core.models as models
7
+ import karrio.providers.laposte as provider
8
+ import karrio.mappers.laposte.settings as provider_settings
9
+
10
+
11
+ class Mapper(mapper.Mapper):
12
+ settings: provider_settings.Settings
13
+
14
+ def create_tracking_request(
15
+ self, payload: models.TrackingRequest
16
+ ) -> lib.Serializable:
17
+ return provider.tracking_request(payload, self.settings)
18
+
19
+ def parse_tracking_response(
20
+ self, response: lib.Deserializable
21
+ ) -> typing.Tuple[typing.List[models.TrackingDetails], typing.List[models.Message]]:
22
+ return provider.parse_tracking_response(response, self.settings)
@@ -0,0 +1,23 @@
1
+ """Karrio La Poste client proxy."""
2
+
3
+ import karrio.lib as lib
4
+ import karrio.api.proxy as proxy
5
+ import karrio.mappers.laposte.settings as provider_settings
6
+
7
+
8
+ class Proxy(proxy.Proxy):
9
+ settings: provider_settings.Settings
10
+
11
+ def get_tracking(self, request: lib.Serializable) -> lib.Deserializable:
12
+ idships = ",".join(request.serialize())
13
+ response = lib.request(
14
+ url=f"{self.settings.server_url}/idships/{idships}?lang={self.settings.lang}",
15
+ trace=self.trace_as("json"),
16
+ headers={
17
+ "accept": "application/json",
18
+ "X-Okapi-Key": self.settings.api_key,
19
+ },
20
+ method="GET",
21
+ )
22
+
23
+ return lib.Deserializable(response, lib.to_dict)
@@ -0,0 +1,21 @@
1
+ """Karrio La Poste client settings."""
2
+
3
+ import attr
4
+ import karrio.providers.laposte.utils as utils
5
+
6
+
7
+ @attr.s(auto_attribs=True)
8
+ class Settings(utils.Settings):
9
+ """La Poste connection settings."""
10
+
11
+ # required carrier specific properties
12
+ api_key: str
13
+ lang: utils.LangEnum = "fr_FR" # type: ignore
14
+
15
+ # generic properties
16
+ id: str = ""
17
+ test_mode: bool = False
18
+ carrier_id: str = "laposte"
19
+ account_country_code: str = "FR"
20
+ metadata: dict = {}
21
+ config: dict = {}
@@ -0,0 +1,20 @@
1
+ import karrio.core.metadata as metadata
2
+ import karrio.mappers.laposte as mappers
3
+ import karrio.providers.laposte.units as units
4
+
5
+
6
+ METADATA = metadata.PluginMetadata(
7
+ status="production-ready",
8
+ id="laposte",
9
+ label="La Poste",
10
+ # Integrations
11
+ Mapper=mappers.Mapper,
12
+ Proxy=mappers.Proxy,
13
+ Settings=mappers.Settings,
14
+ # Data Units
15
+ is_hub=False,
16
+ # New fields
17
+ website="https://www.laposte.fr/",
18
+ documentation="https://www.lapostegroupe.com/en/services-mail-parcels-business-unit",
19
+ description="La Poste is a postal service company in France, operating in Metropolitan France and French overseas territories. The company provides mail delivery, parcel shipping, banking services, and digital solutions.",
20
+ )
@@ -0,0 +1,6 @@
1
+
2
+ from karrio.providers.laposte.utils import Settings
3
+ from karrio.providers.laposte.tracking import (
4
+ parse_tracking_response,
5
+ tracking_request,
6
+ )
@@ -0,0 +1,32 @@
1
+ import karrio.schemas.laposte.error as laposte
2
+ import typing
3
+ import karrio.lib as lib
4
+ import karrio.core.models as models
5
+ import karrio.providers.laposte.utils as provider_utils
6
+
7
+
8
+ def parse_error_response(
9
+ response: typing.Union[dict, typing.List[dict]],
10
+ settings: provider_utils.Settings,
11
+ **kwargs,
12
+ ) -> typing.List[models.Message]:
13
+ responses = response if isinstance(response, list) else [response]
14
+ errors = [
15
+ lib.to_object(laposte.Error, res)
16
+ for res in responses
17
+ if (
18
+ not str(res.get("returnCode")).startswith("20")
19
+ or res.get("code") is not None
20
+ )
21
+ ]
22
+
23
+ return [
24
+ models.Message(
25
+ carrier_id=settings.carrier_id,
26
+ carrier_name=settings.carrier_name,
27
+ code=error.returnCode or error.code,
28
+ message=error.returnMessage or error.message,
29
+ details={**kwargs},
30
+ )
31
+ for error in errors
32
+ ]
@@ -0,0 +1,79 @@
1
+ import karrio.schemas.laposte.tracking_response as laposte
2
+ import typing
3
+ import karrio.lib as lib
4
+ import karrio.core.units as units
5
+ import karrio.core.models as models
6
+ import karrio.providers.laposte.error as error
7
+ import karrio.providers.laposte.utils as provider_utils
8
+ import karrio.providers.laposte.units as provider_units
9
+
10
+
11
+ def parse_tracking_response(
12
+ _response: lib.Deserializable[typing.Union[dict, typing.List[dict]]],
13
+ settings: provider_utils.Settings,
14
+ ) -> typing.Tuple[typing.List[models.TrackingDetails], typing.List[models.Message]]:
15
+ response = _response.deserialize()
16
+ responses = response if isinstance(response, list) else [response]
17
+ messages = error.parse_error_response(responses, settings)
18
+ tracking_details = [
19
+ _extract_details(res["shipment"], settings)
20
+ for res in responses
21
+ if str(res.get("returnCode")).startswith("20")
22
+ ]
23
+
24
+ return tracking_details, messages
25
+
26
+
27
+ def _extract_details(
28
+ data: dict,
29
+ settings: provider_utils.Settings,
30
+ ) -> models.TrackingDetails:
31
+ shipment = lib.to_object(laposte.Shipment, data)
32
+ status = next(
33
+ (
34
+ status.name
35
+ for status in list(provider_units.TrackingStatus)
36
+ if shipment.event[0].code in status.value
37
+ ),
38
+ provider_units.TrackingStatus.in_transit.name,
39
+ )
40
+
41
+ return models.TrackingDetails(
42
+ carrier_id=settings.carrier_id,
43
+ carrier_name=settings.carrier_name,
44
+ tracking_number=shipment.idShip,
45
+ status=status,
46
+ events=[
47
+ models.TrackingEvent(
48
+ date=lib.fdate(event.date, "%Y-%m-%dT%H:%M:%S%z"),
49
+ description=event.label,
50
+ code=event.code,
51
+ time=lib.flocaltime(event.date, "%Y-%m-%dT%H:%M:%S%z"),
52
+ location=None,
53
+ )
54
+ for event in shipment.event
55
+ ],
56
+ estimated_delivery=lib.fdate(shipment.deliveryDate, "%Y-%m-%dT%H:%M:%S%z"),
57
+ delivered=shipment.isFinal,
58
+ info=models.TrackingInfo(
59
+ carrier_tracking_link=shipment.url,
60
+ expected_delivery=lib.fdate(shipment.estimDate, "%Y-%m-%dT%H:%M:%S%z"),
61
+ shipment_service=shipment.product,
62
+ shipping_date=lib.fdate(shipment.entryDate, "%Y-%m-%dT%H:%M:%S%z"),
63
+ shipment_origin_country=getattr(
64
+ shipment.contextData, "originCountry", None
65
+ ),
66
+ shipment_destination_country=getattr(
67
+ shipment.contextData, "arrivalCountry", None
68
+ ),
69
+ ),
70
+ )
71
+
72
+
73
+ def tracking_request(
74
+ payload: models.TrackingRequest,
75
+ settings: provider_utils.Settings,
76
+ ) -> lib.Serializable:
77
+ request = payload.tracking_numbers
78
+
79
+ return lib.Serializable(request)
@@ -0,0 +1,57 @@
1
+ import karrio.lib as lib
2
+ import karrio.core.units as units
3
+
4
+
5
+ class PackagingType(lib.StrEnum):
6
+ """Carrier specific packaging type"""
7
+
8
+ PACKAGE = "PACKAGE"
9
+
10
+ """ Unified Packaging type mapping """
11
+ envelope = PACKAGE
12
+ pak = PACKAGE
13
+ tube = PACKAGE
14
+ pallet = PACKAGE
15
+ small_box = PACKAGE
16
+ medium_box = PACKAGE
17
+ your_packaging = PACKAGE
18
+
19
+
20
+ class ShippingService(lib.StrEnum):
21
+ """Carrier specific services"""
22
+
23
+ laposte_standard_service = "La Poste Standard Service"
24
+
25
+
26
+ class ShippingOption(lib.Enum):
27
+ """Carrier specific options"""
28
+
29
+ # laposte_option = lib.OptionEnum("code")
30
+
31
+ """ Unified Option type mapping """
32
+ # insurance = laposte_coverage # maps unified karrio option to carrier specific
33
+
34
+ pass
35
+
36
+
37
+ def shipping_options_initializer(
38
+ options: dict,
39
+ package_options: units.ShippingOptions = None,
40
+ ) -> units.ShippingOptions:
41
+ """
42
+ Apply default values to the given options.
43
+ """
44
+
45
+ if package_options is not None:
46
+ options.update(package_options.content)
47
+
48
+ def items_filter(key: str) -> bool:
49
+ return key in ShippingOption # type: ignore
50
+
51
+ return units.ShippingOptions(options, ShippingOption, items_filter=items_filter)
52
+
53
+
54
+ class TrackingStatus(lib.Enum):
55
+ delivered = ["DI1"]
56
+ in_transit = [""]
57
+ out_for_delivery = ["MD2", "ET1"]
@@ -0,0 +1,24 @@
1
+ import karrio.lib as lib
2
+ import karrio.core as core
3
+
4
+
5
+ LangEnum = lib.units.create_enum("LangEnum", ["fr_FR", "en_US"])
6
+
7
+
8
+ class Settings(core.Settings):
9
+ """La Poste connection settings."""
10
+
11
+ api_key: str
12
+ lang: LangEnum = "fr_FR" # type: ignore
13
+
14
+ @property
15
+ def carrier_name(self):
16
+ return "laposte"
17
+
18
+ @property
19
+ def server_url(self):
20
+ return "https://api.laposte.fr/suivi/v2"
21
+
22
+ @property
23
+ def tracking_url(self):
24
+ return "https://www.laposte.fr/outils/suivre-vos-envois?code={}"
File without changes
@@ -0,0 +1,14 @@
1
+ import attr
2
+ import jstruct
3
+ import typing
4
+
5
+
6
+ @attr.s(auto_attribs=True)
7
+ class Error:
8
+ returnCode: typing.Optional[int] = None
9
+ returnMessage: typing.Optional[str] = None
10
+ lang: typing.Optional[str] = None
11
+ scope: typing.Optional[str] = None
12
+ idShip: typing.Optional[str] = None
13
+ code: typing.Optional[str] = None
14
+ message: typing.Optional[str] = None
@@ -0,0 +1,61 @@
1
+ import attr
2
+ import jstruct
3
+ import typing
4
+
5
+
6
+ @attr.s(auto_attribs=True)
7
+ class DeliveryChoice:
8
+ deliveryChoice: typing.Optional[int] = None
9
+
10
+
11
+ @attr.s(auto_attribs=True)
12
+ class ContextData:
13
+ deliveryChoice: typing.Optional[DeliveryChoice] = jstruct.JStruct[DeliveryChoice]
14
+ originCountry: typing.Optional[str] = None
15
+ arrivalCountry: typing.Optional[str] = None
16
+
17
+
18
+ @attr.s(auto_attribs=True)
19
+ class Event:
20
+ code: typing.Optional[str] = None
21
+ label: typing.Optional[str] = None
22
+ date: typing.Optional[str] = None
23
+
24
+
25
+ @attr.s(auto_attribs=True)
26
+ class Timeline:
27
+ shortLabel: typing.Optional[str] = None
28
+ longLabel: typing.Optional[str] = None
29
+ id: typing.Optional[int] = None
30
+ country: typing.Optional[str] = None
31
+ status: typing.Optional[bool] = None
32
+ type: typing.Optional[int] = None
33
+ date: typing.Optional[str] = None
34
+
35
+
36
+ @attr.s(auto_attribs=True)
37
+ class Shipment:
38
+ idShip: typing.Optional[str] = None
39
+ holder: typing.Optional[int] = None
40
+ product: typing.Optional[str] = None
41
+ isFinal: typing.Optional[bool] = None
42
+ deliveryDate: typing.Optional[str] = None
43
+ entryDate: typing.Optional[str] = None
44
+ timeline: typing.Optional[typing.List[Timeline]] = jstruct.JList[Timeline]
45
+ event: typing.Optional[typing.List[Event]] = jstruct.JList[Event]
46
+ contextData: typing.Optional[ContextData] = jstruct.JStruct[ContextData]
47
+ estimDate: typing.Optional[str] = None
48
+ url: typing.Optional[str] = None
49
+
50
+
51
+ @attr.s(auto_attribs=True)
52
+ class Response:
53
+ lang: typing.Optional[str] = None
54
+ scope: typing.Optional[str] = None
55
+ returnCode: typing.Optional[int] = None
56
+ shipment: typing.Optional[Shipment] = jstruct.JStruct[Shipment]
57
+
58
+
59
+ @attr.s(auto_attribs=True)
60
+ class TrackingResponse:
61
+ responses: typing.Optional[typing.List[Response]] = jstruct.JList[Response]
@@ -0,0 +1,45 @@
1
+ Metadata-Version: 2.4
2
+ Name: karrio_laposte
3
+ Version: 2025.5rc1
4
+ Summary: Karrio - La Poste Shipping Extension
5
+ Author-email: karrio <hello@karrio.io>
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/karrioapi/karrio
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Programming Language :: Python :: 3
11
+ Requires-Python: >=3.11
12
+ Description-Content-Type: text/markdown
13
+ Requires-Dist: karrio
14
+
15
+
16
+ # karrio.laposte
17
+
18
+ This package is a La Poste extension of the [karrio](https://pypi.org/project/karrio) multi carrier shipping SDK.
19
+
20
+ ## Requirements
21
+
22
+ `Python 3.11+`
23
+
24
+ ## Installation
25
+
26
+ ```bash
27
+ pip install karrio.laposte
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ ```python
33
+ import karrio.sdk as karrio
34
+ from karrio.mappers.laposte.settings import Settings
35
+
36
+
37
+ # Initialize a carrier gateway
38
+ laposte = karrio.gateway["laposte"].create(
39
+ Settings(
40
+ ...
41
+ )
42
+ )
43
+ ```
44
+
45
+ Check the [Karrio Mutli-carrier SDK docs](https://docs.karrio.io) for Shipping API requests
@@ -0,0 +1,18 @@
1
+ karrio/mappers/laposte/__init__.py,sha256=Vc5jW0ohCxnxsv_msdf4ftlVcg5tF9_ETsne2u-UxYk,148
2
+ karrio/mappers/laposte/mapper.py,sha256=TFfFyez_qeX94yxlFMydzNp2B7NvynTHY_8o0irGiMk,735
3
+ karrio/mappers/laposte/proxy.py,sha256=NQyWL0rc-ky80o1NF2eNOpLTq9q6k6RQHosSjDrwgsQ,745
4
+ karrio/mappers/laposte/settings.py,sha256=k7J2BUyX4U8g2T3xFTrNbwvSq0TkSjdBwl3BzPgv98w,498
5
+ karrio/plugins/laposte/__init__.py,sha256=s5MbbVNYqW4OLp_lHKlAR8q-Ws0pLv9JPFa1Kp2fdc0,749
6
+ karrio/providers/laposte/__init__.py,sha256=UmsiUvmZL8zOhAcoZMippZ6okpCPa8BcnWCfNEkSYWw,154
7
+ karrio/providers/laposte/error.py,sha256=oohq1_PrH_AwIbMzDHAwN9Q6pSCdifUw8z6Dz-bt6VA,948
8
+ karrio/providers/laposte/tracking.py,sha256=LgrZYJl8TF7XM6UQ3ZKh0d9cr14Z8ZG1iPYqHAeHdo0,2757
9
+ karrio/providers/laposte/units.py,sha256=dOC62QEibI0bmI4Ukobvj81cH1udqnzHTbIGNBAsQEk,1332
10
+ karrio/providers/laposte/utils.py,sha256=BYbMIdsf-vIQltFPMTy53JlyTF6g9Wva1shPmheIczI,529
11
+ karrio/schemas/laposte/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
+ karrio/schemas/laposte/error.py,sha256=JUKNxIEHhNVZ6aTGyA9QeF6WJRcnv4z_T-lEe4DPNHk,370
13
+ karrio/schemas/laposte/tracking_response.py,sha256=x_VPNtzg4LSrNKPFffzZ0H-tzZNrkLcnQIVXsKJRo7A,1822
14
+ karrio_laposte-2025.5rc1.dist-info/METADATA,sha256=ME6McQbh1vvJHh9T17Dr085pefSCn6aAUy_TOr2sTqs,996
15
+ karrio_laposte-2025.5rc1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
16
+ karrio_laposte-2025.5rc1.dist-info/entry_points.txt,sha256=jFXL-V5ZRLAXwmk3DrdkzFpby2AHihbknUW_61y9Ft8,59
17
+ karrio_laposte-2025.5rc1.dist-info/top_level.txt,sha256=FZCY8Nwft8oEGHdl--xku8P3TrnOxu5dETEU_fWpRSM,20
18
+ karrio_laposte-2025.5rc1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [karrio.plugins]
2
+ laposte = karrio.plugins.laposte:METADATA
@@ -0,0 +1,3 @@
1
+ dist
2
+ karrio
3
+ schemas