karrio-hermes 2026.1.1__py3-none-any.whl → 2026.1.4__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,155 @@
1
+ """Karrio Hermes tracking API implementation."""
2
+
3
+ import typing
4
+ import karrio.lib as lib
5
+ import karrio.core.models as models
6
+ import karrio.providers.hermes.error as error
7
+ import karrio.providers.hermes.utils as provider_utils
8
+ import karrio.providers.hermes.units as provider_units
9
+ import karrio.schemas.hermes.tracking_response as hermes_res
10
+
11
+
12
+ def _match_status(code: str) -> typing.Optional[str]:
13
+ """Match Hermes event code against TrackingStatus enum values."""
14
+ if not code:
15
+ return None
16
+ for status in list(provider_units.TrackingStatus):
17
+ if code in status.value:
18
+ return status.name
19
+ return None
20
+
21
+
22
+ def _match_reason(code: str) -> typing.Optional[str]:
23
+ """Match Hermes event code against incident reasons.
24
+
25
+ Hermes uses numeric codes that map to statuses, not specific incident reasons.
26
+ Returns None as Hermes does not provide granular incident reason codes.
27
+ """
28
+ return None
29
+
30
+
31
+ def parse_tracking_response(
32
+ _response: lib.Deserializable[dict],
33
+ settings: provider_utils.Settings,
34
+ ) -> typing.Tuple[typing.List[models.TrackingDetails], typing.List[models.Message]]:
35
+ """Parse tracking response from Hermes Shipment Info API."""
36
+ response = _response.deserialize()
37
+
38
+ # Parse the response using generated schema
39
+ tracking_response = lib.to_object(hermes_res.TrackingResponseType, response)
40
+
41
+ # Collect error messages
42
+ messages: typing.List[models.Message] = []
43
+
44
+ # Extract tracking details for each shipment
45
+ tracking_details: typing.List[models.TrackingDetails] = []
46
+
47
+ for shipment_info in tracking_response.shipmentinfo or []:
48
+ # Check for errors in individual shipment result
49
+ if shipment_info.result and shipment_info.result.code:
50
+ if shipment_info.result.code.startswith("e"):
51
+ messages.append(
52
+ models.Message(
53
+ carrier_id=settings.carrier_id,
54
+ carrier_name=settings.carrier_name,
55
+ code=shipment_info.result.code,
56
+ message=shipment_info.result.message or "",
57
+ details=dict(shipment_id=shipment_info.shipmentID),
58
+ )
59
+ )
60
+ continue
61
+
62
+ # Extract tracking details
63
+ details = _extract_details(shipment_info, settings)
64
+ if details:
65
+ tracking_details.append(details)
66
+
67
+ return tracking_details, messages
68
+
69
+
70
+ def _extract_details(
71
+ shipment_info: hermes_res.ShipmentinfoType,
72
+ settings: provider_utils.Settings,
73
+ ) -> typing.Optional[models.TrackingDetails]:
74
+ """Extract tracking details from Hermes shipment info."""
75
+ if not shipment_info.shipmentID:
76
+ return None
77
+
78
+ # Get status events (already in chronological order, most recent last in API)
79
+ # Reverse to have most recent first for Karrio convention
80
+ status_list = list(reversed(shipment_info.status or []))
81
+
82
+ # Get latest event code for overall status
83
+ latest_code = status_list[0].code if status_list else None
84
+ overall_status = _match_status(latest_code) or provider_units.TrackingStatus.in_transit.name
85
+
86
+ # Build tracking events with all required fields per CARRIER_INTEGRATION_GUIDE.md
87
+ events = [
88
+ models.TrackingEvent(
89
+ date=lib.fdate(event.timestamp, "%Y-%m-%dT%H:%M:%S%z"),
90
+ time=lib.flocaltime(event.timestamp, "%Y-%m-%dT%H:%M:%S%z"),
91
+ description=event.description or "",
92
+ code=event.code,
93
+ location=lib.join(
94
+ event.scanningUnit.city if event.scanningUnit else None,
95
+ event.scanningUnit.countryCode if event.scanningUnit else None,
96
+ join=True,
97
+ separator=", ",
98
+ ),
99
+ # REQUIRED: timestamp in ISO 8601 format (already provided by Hermes)
100
+ timestamp=event.timestamp,
101
+ # REQUIRED: normalized status at event level
102
+ status=_match_status(event.code),
103
+ # Incident reason for exception events
104
+ reason=_match_reason(event.code),
105
+ )
106
+ for event in status_list
107
+ ]
108
+
109
+ # Build delivery forecast info if available
110
+ estimated_delivery = None
111
+ if shipment_info.deliveryForecast and shipment_info.deliveryForecast.date:
112
+ estimated_delivery = shipment_info.deliveryForecast.date
113
+
114
+ return models.TrackingDetails(
115
+ carrier_id=settings.carrier_id,
116
+ carrier_name=settings.carrier_name,
117
+ tracking_number=shipment_info.shipmentID,
118
+ events=events,
119
+ delivered=overall_status == "delivered",
120
+ status=overall_status,
121
+ estimated_delivery=estimated_delivery,
122
+ info=models.TrackingInfo(
123
+ carrier_tracking_link=shipment_info.trackingLink,
124
+ customer_name=None,
125
+ shipment_destination_country=(
126
+ shipment_info.receiverAddress.countryCode
127
+ if shipment_info.receiverAddress
128
+ else None
129
+ ),
130
+ shipment_destination_postal_code=(
131
+ str(shipment_info.receiverAddress.zipCode)
132
+ if shipment_info.receiverAddress and shipment_info.receiverAddress.zipCode
133
+ else None
134
+ ),
135
+ ),
136
+ meta=dict(
137
+ client_id=shipment_info.clientID,
138
+ client_reference=shipment_info.clientReference,
139
+ client_reference2=shipment_info.clientReference2,
140
+ part_number=shipment_info.partNumber,
141
+ international_shipment_id=shipment_info.internationalShipmentID,
142
+ ),
143
+ )
144
+
145
+
146
+ def tracking_request(
147
+ payload: models.TrackingRequest,
148
+ settings: provider_utils.Settings,
149
+ ) -> lib.Serializable:
150
+ """Create tracking request for Hermes Shipment Info API.
151
+
152
+ Hermes uses GET requests with query parameters, so we just return
153
+ the tracking numbers to be used as shipmentID query params.
154
+ """
155
+ return lib.Serializable(payload.tracking_numbers)
@@ -64,48 +64,198 @@ class ShippingService(lib.StrEnum):
64
64
  class ShippingOption(lib.Enum):
65
65
  """Carrier specific options."""
66
66
 
67
- # Hermes services as options
68
- hermes_tan_service = lib.OptionEnum("tanService", bool)
69
- hermes_limited_quantities = lib.OptionEnum("limitedQuantitiesService", bool)
70
- hermes_bulk_goods = lib.OptionEnum("bulkGoodService", bool)
71
- hermes_household_signature = lib.OptionEnum("householdSignatureService", bool)
72
- hermes_compact_parcel = lib.OptionEnum("compactParcelService", bool)
73
- hermes_next_day = lib.OptionEnum("nextDayService", bool)
74
- hermes_signature = lib.OptionEnum("signatureService", bool)
75
- hermes_redirection_prohibited = lib.OptionEnum("redirectionProhibitedService", bool)
76
- hermes_exclude_parcel_shop_auth = lib.OptionEnum("excludeParcelShopAuthorization", bool)
77
- hermes_late_injection = lib.OptionEnum("lateInjectionService", bool)
78
-
79
- # Cash on delivery
80
- hermes_cod_amount = lib.OptionEnum("codAmount", float)
81
- hermes_cod_currency = lib.OptionEnum("codCurrency", str)
82
-
83
- # Customer alert service
84
- hermes_notification_email = lib.OptionEnum("notificationEmail", str)
85
- hermes_notification_type = lib.OptionEnum("notificationType", str) # EMAIL, SMS, EMAIL_SMS
86
-
87
- # Stated day service
88
- hermes_stated_day = lib.OptionEnum("statedDay", str) # YYYY-MM-DD format
89
-
90
- # Stated time service
91
- hermes_time_slot = lib.OptionEnum("timeSlot", str) # FORENOON, NOON, AFTERNOON, EVENING
92
-
93
- # Ident service
94
- hermes_ident_id = lib.OptionEnum("identID", str)
95
- hermes_ident_type = lib.OptionEnum("identType", str) # GERMAN_IDENTITY_CARD, etc.
96
- hermes_ident_fsk = lib.OptionEnum("identVerifyFsk", str) # 18
97
- hermes_ident_birthday = lib.OptionEnum("identVerifyBirthday", str) # YYYY-MM-DD
98
-
99
- # Parcel shop delivery
100
- hermes_parcel_shop_id = lib.OptionEnum("psID", str)
101
- hermes_parcel_shop_selection_rule = lib.OptionEnum("psSelectionRule", str) # SELECT_BY_ID, SELECT_BY_RECEIVER_ADDRESS
102
- hermes_parcel_shop_customer_firstname = lib.OptionEnum("psCustomerFirstName", str)
103
- hermes_parcel_shop_customer_lastname = lib.OptionEnum("psCustomerLastName", str)
104
-
105
- # Multipart service
106
- hermes_part_number = lib.OptionEnum("partNumber", int)
107
- hermes_number_of_parts = lib.OptionEnum("numberOfParts", int)
108
- hermes_parent_shipment_order_id = lib.OptionEnum("parentShipmentOrderID", str)
67
+ # Delivery Options (Zustelloptionen tab)
68
+ hermes_next_day = lib.OptionEnum(
69
+ "nextDayService", bool,
70
+ help="Enable next-day delivery service",
71
+ meta=dict(category="DELIVERY_OPTIONS", configurable=True)
72
+ )
73
+ hermes_bulk_goods = lib.OptionEnum(
74
+ "bulkGoodService", bool,
75
+ help="Mark shipment as bulky goods (Sperrgut)",
76
+ meta=dict(category="DELIVERY_OPTIONS", configurable=True)
77
+ )
78
+ hermes_compact_parcel = lib.OptionEnum(
79
+ "compactParcelService", bool,
80
+ help="Enable compact parcel service",
81
+ meta=dict(category="DELIVERY_OPTIONS", configurable=True)
82
+ )
83
+ hermes_redirection_prohibited = lib.OptionEnum(
84
+ "redirectionProhibitedService", bool,
85
+ help="Do not allow redirection to neighbor",
86
+ meta=dict(category="DELIVERY_OPTIONS", configurable=True)
87
+ )
88
+ hermes_stated_day = lib.OptionEnum(
89
+ "statedDay", str,
90
+ help="Specific delivery date (YYYY-MM-DD format)",
91
+ meta=dict(category="DELIVERY_OPTIONS", configurable=True)
92
+ )
93
+ hermes_time_slot = lib.OptionEnum(
94
+ "timeSlot", str,
95
+ help="Delivery time slot (FORENOON, NOON, AFTERNOON, EVENING)",
96
+ meta=dict(category="DELIVERY_OPTIONS", configurable=True)
97
+ )
98
+ hermes_express = lib.OptionEnum(
99
+ "expressService", bool,
100
+ help="Enable express delivery service",
101
+ meta=dict(category="DELIVERY_OPTIONS", configurable=True)
102
+ )
103
+ hermes_after_hours_delivery = lib.OptionEnum(
104
+ "afterHoursDeliveryService", bool,
105
+ help="Enable after-hours delivery (Feierabendservice)",
106
+ meta=dict(category="DELIVERY_OPTIONS", configurable=True)
107
+ )
108
+ hermes_parcel_class = lib.OptionEnum(
109
+ "parcelClass", str,
110
+ help="Parcel size class (XS, S, M, L, XL)",
111
+ meta=dict(category="DELIVERY_OPTIONS", configurable=True)
112
+ )
113
+
114
+ # Signature Options
115
+ hermes_signature = lib.OptionEnum(
116
+ "signatureService", bool,
117
+ help="Require signature upon delivery",
118
+ meta=dict(category="SIGNATURE", configurable=True)
119
+ )
120
+ hermes_household_signature = lib.OptionEnum(
121
+ "householdSignatureService", bool,
122
+ help="Require household member signature",
123
+ meta=dict(category="SIGNATURE", configurable=True)
124
+ )
125
+ hermes_ident_id = lib.OptionEnum(
126
+ "identID", str,
127
+ help="ID number for identity verification",
128
+ meta=dict(category="SIGNATURE", configurable=True)
129
+ )
130
+ hermes_ident_type = lib.OptionEnum(
131
+ "identType", str,
132
+ help="Type of ID for verification (e.g., GERMAN_IDENTITY_CARD)",
133
+ meta=dict(category="SIGNATURE", configurable=True)
134
+ )
135
+ hermes_ident_fsk = lib.OptionEnum(
136
+ "identVerifyFsk", str,
137
+ help="Minimum age verification (e.g., 18)",
138
+ meta=dict(category="SIGNATURE", configurable=True)
139
+ )
140
+ hermes_ident_birthday = lib.OptionEnum(
141
+ "identVerifyBirthday", str,
142
+ help="Verify recipient birthday (YYYY-MM-DD)",
143
+ meta=dict(category="SIGNATURE", configurable=True)
144
+ )
145
+
146
+ # PUDO Options (Parcel Shop)
147
+ hermes_parcel_shop_id = lib.OptionEnum(
148
+ "psID", str,
149
+ help="Hermes ParcelShop ID for delivery",
150
+ meta=dict(category="PUDO", configurable=True)
151
+ )
152
+ hermes_parcel_shop_selection_rule = lib.OptionEnum(
153
+ "psSelectionRule", str,
154
+ help="ParcelShop selection rule (SELECT_BY_ID, SELECT_BY_RECEIVER_ADDRESS)",
155
+ meta=dict(category="PUDO", configurable=True)
156
+ )
157
+ hermes_parcel_shop_customer_firstname = lib.OptionEnum(
158
+ "psCustomerFirstName", str,
159
+ help="Customer first name for ParcelShop pickup",
160
+ meta=dict(category="PUDO", configurable=True)
161
+ )
162
+ hermes_parcel_shop_customer_lastname = lib.OptionEnum(
163
+ "psCustomerLastName", str,
164
+ help="Customer last name for ParcelShop pickup",
165
+ meta=dict(category="PUDO", configurable=True)
166
+ )
167
+ hermes_exclude_parcel_shop_auth = lib.OptionEnum(
168
+ "excludeParcelShopAuthorization", bool,
169
+ help="Exclude ParcelShop delivery authorization",
170
+ meta=dict(category="PUDO", configurable=True)
171
+ )
172
+
173
+ # Notification Options
174
+ hermes_notification_email = lib.OptionEnum(
175
+ "notificationEmail", str,
176
+ help="Email for delivery notifications",
177
+ meta=dict(category="NOTIFICATION", configurable=True)
178
+ )
179
+ hermes_notification_type = lib.OptionEnum(
180
+ "notificationType", str,
181
+ help="Notification type (EMAIL, SMS, EMAIL_SMS)",
182
+ meta=dict(category="NOTIFICATION", configurable=True)
183
+ )
184
+
185
+ # COD Options (Cash on Delivery)
186
+ hermes_cod_amount = lib.OptionEnum(
187
+ "codAmount", float,
188
+ help="Cash on delivery amount",
189
+ meta=dict(category="COD", configurable=True)
190
+ )
191
+ hermes_cod_currency = lib.OptionEnum(
192
+ "codCurrency", str,
193
+ help="Currency for COD amount",
194
+ meta=dict(category="COD", configurable=True)
195
+ )
196
+ hermes_cod_distribution = lib.OptionEnum(
197
+ "codDistribution", str,
198
+ help="COD distribution method (e.g., transfer, check)",
199
+ meta=dict(category="COD", configurable=True)
200
+ )
201
+
202
+ # Dangerous Goods
203
+ hermes_limited_quantities = lib.OptionEnum(
204
+ "limitedQuantitiesService", bool,
205
+ help="Mark shipment as containing limited quantity hazardous materials",
206
+ meta=dict(category="DANGEROUS_GOOD", configurable=True)
207
+ )
208
+
209
+ # Return Options
210
+ hermes_return_enabled = lib.OptionEnum(
211
+ "returnService", bool,
212
+ help="Enable return label for this shipment",
213
+ meta=dict(category="RETURN", configurable=True)
214
+ )
215
+ hermes_include_return_label = lib.OptionEnum(
216
+ "includeReturnLabel", bool,
217
+ help="Include a pre-printed return label inside the package",
218
+ meta=dict(category="RETURN", configurable=True)
219
+ )
220
+ hermes_digital_sales_return = lib.OptionEnum(
221
+ "digitalSalesReturn", bool,
222
+ help="Enable digital sales return (digitale Verkaufsretoure)",
223
+ meta=dict(category="RETURN", configurable=True)
224
+ )
225
+
226
+ # Reference/Instructions Options
227
+ hermes_customer_reference_1 = lib.OptionEnum(
228
+ "customerReference1", str,
229
+ help="Customer reference field 1 (Kundenreferenz 1)",
230
+ meta=dict(category="INSTRUCTIONS", configurable=True)
231
+ )
232
+ hermes_customer_reference_2 = lib.OptionEnum(
233
+ "customerReference2", str,
234
+ help="Customer reference field 2 (Kundenreferenz 2)",
235
+ meta=dict(category="INSTRUCTIONS", configurable=True)
236
+ )
237
+
238
+ # Internal/Multipart Options (not configurable in shipping method editor)
239
+ hermes_tan_service = lib.OptionEnum(
240
+ "tanService", bool,
241
+ meta=dict(configurable=False)
242
+ )
243
+ hermes_late_injection = lib.OptionEnum(
244
+ "lateInjectionService", bool,
245
+ meta=dict(configurable=False)
246
+ )
247
+ hermes_part_number = lib.OptionEnum(
248
+ "partNumber", int,
249
+ meta=dict(configurable=False)
250
+ )
251
+ hermes_number_of_parts = lib.OptionEnum(
252
+ "numberOfParts", int,
253
+ meta=dict(configurable=False)
254
+ )
255
+ hermes_parent_shipment_order_id = lib.OptionEnum(
256
+ "parentShipmentOrderID", str,
257
+ meta=dict(configurable=False)
258
+ )
109
259
 
110
260
  """Unified Option type mapping."""
111
261
  signature_required = hermes_signature
@@ -128,15 +278,16 @@ def shipping_options_initializer(
128
278
 
129
279
 
130
280
  class TrackingStatus(lib.Enum):
131
- """Hermes tracking status mapping."""
132
-
133
- on_hold = ["on_hold"]
134
- delivered = ["delivered"]
135
- in_transit = ["in_transit"]
136
- delivery_failed = ["delivery_failed"]
137
- delivery_delayed = ["delivery_delayed"]
138
- out_for_delivery = ["out_for_delivery"]
139
- ready_for_pickup = ["ready_for_pickup"]
281
+ """Hermes tracking status mapping based on Hermes event codes."""
282
+
283
+ pending = ["0000"]
284
+ in_transit = ["1000", "2000"]
285
+ out_for_delivery = ["3000"]
286
+ delivered = ["3500"]
287
+ delivery_failed = ["4000", "4500"]
288
+ ready_for_pickup = ["5000"]
289
+ on_hold = ["6000"]
290
+ delivery_delayed = ["7000"]
140
291
 
141
292
 
142
293
  class LabelType(lib.StrEnum):
@@ -100,3 +100,29 @@ def login(settings: Settings):
100
100
  seconds=float(response.get("expires_in", 3600))
101
101
  )
102
102
  return {**response, "expiry": lib.fdatetime(expiry)}
103
+
104
+
105
+ def get_access_token(settings: Settings) -> str:
106
+ """Get access token from settings."""
107
+ token_data = settings.access_token
108
+ return token_data.get("access_token") if isinstance(token_data, dict) else token_data
109
+
110
+
111
+ def prepare_shipment_data(request: lib.Serializable) -> tuple:
112
+ """Prepare shipment request data and multi-piece flag."""
113
+ requests_data = request.serialize()
114
+ is_multi_piece = request.ctx.get("is_multi_piece", False) if request.ctx else False
115
+ requests_data = requests_data if isinstance(requests_data, list) else [requests_data]
116
+ return requests_data, is_multi_piece
117
+
118
+
119
+ def inject_parent_shipment_id(req_data: dict, parent_id: str) -> dict:
120
+ """Inject parentShipmentOrderID for multi-piece packages 2+."""
121
+ if req_data.get("service", {}).get("multipartService"):
122
+ req_data["service"]["multipartService"]["parentShipmentOrderID"] = parent_id
123
+ return req_data
124
+
125
+
126
+ def extract_shipment_order_id(response: dict) -> str:
127
+ """Extract shipmentOrderID from response for multi-piece linking."""
128
+ return response.get("shipmentOrderID")
@@ -41,3 +41,13 @@ from karrio.schemas.hermes.pickup_create_request import (
41
41
  from karrio.schemas.hermes.pickup_create_response import PickupCreateResponseType
42
42
  from karrio.schemas.hermes.pickup_cancel_request import PickupCancelRequestType
43
43
  from karrio.schemas.hermes.pickup_cancel_response import PickupCancelResponseType
44
+ from karrio.schemas.hermes.tracking_response import (
45
+ TrackingResponseType,
46
+ ShipmentinfoType,
47
+ ResultType,
48
+ StatusType,
49
+ ScanningUnitType,
50
+ ReceiverAddressType as TrackingReceiverAddressType,
51
+ DeliveryForecastType,
52
+ TimeSlotType,
53
+ )
@@ -0,0 +1,63 @@
1
+ import attr
2
+ import jstruct
3
+ import typing
4
+
5
+
6
+ @attr.s(auto_attribs=True)
7
+ class TimeSlotType:
8
+ to: typing.Optional[str] = None
9
+
10
+
11
+ @attr.s(auto_attribs=True)
12
+ class DeliveryForecastType:
13
+ fixed: typing.Optional[bool] = None
14
+ date: typing.Optional[str] = None
15
+ timeSlot: typing.Optional[TimeSlotType] = jstruct.JStruct[TimeSlotType]
16
+
17
+
18
+ @attr.s(auto_attribs=True)
19
+ class ReceiverAddressType:
20
+ city: typing.Optional[str] = None
21
+ zipCode: typing.Optional[int] = None
22
+ countryCode: typing.Optional[str] = None
23
+
24
+
25
+ @attr.s(auto_attribs=True)
26
+ class ResultType:
27
+ code: typing.Optional[str] = None
28
+ message: typing.Optional[str] = None
29
+
30
+
31
+ @attr.s(auto_attribs=True)
32
+ class ScanningUnitType:
33
+ name: typing.Optional[str] = None
34
+ city: typing.Optional[str] = None
35
+ countryCode: typing.Optional[str] = None
36
+
37
+
38
+ @attr.s(auto_attribs=True)
39
+ class StatusType:
40
+ timestamp: typing.Optional[str] = None
41
+ code: typing.Optional[str] = None
42
+ description: typing.Optional[str] = None
43
+ scanningUnit: typing.Optional[ScanningUnitType] = jstruct.JStruct[ScanningUnitType]
44
+
45
+
46
+ @attr.s(auto_attribs=True)
47
+ class ShipmentinfoType:
48
+ shipmentID: typing.Optional[str] = None
49
+ partNumber: typing.Optional[int] = None
50
+ clientID: typing.Optional[int] = None
51
+ clientReference: typing.Optional[str] = None
52
+ clientReference2: typing.Optional[int] = None
53
+ internationalShipmentID: typing.Optional[str] = None
54
+ trackingLink: typing.Optional[str] = None
55
+ result: typing.Optional[ResultType] = jstruct.JStruct[ResultType]
56
+ receiverAddress: typing.Optional[ReceiverAddressType] = jstruct.JStruct[ReceiverAddressType]
57
+ deliveryForecast: typing.Optional[DeliveryForecastType] = jstruct.JStruct[DeliveryForecastType]
58
+ status: typing.Optional[typing.List[StatusType]] = jstruct.JList[StatusType]
59
+
60
+
61
+ @attr.s(auto_attribs=True)
62
+ class TrackingResponseType:
63
+ shipmentinfo: typing.Optional[typing.List[ShipmentinfoType]] = jstruct.JList[ShipmentinfoType]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: karrio_hermes
3
- Version: 2026.1.1
3
+ Version: 2026.1.4
4
4
  Summary: Karrio - Hermes Shipping Extension
5
5
  Author-email: karrio <hello@karrio.io>
6
6
  License-Expression: LGPL-3.0
@@ -1,18 +1,19 @@
1
1
  karrio/mappers/hermes/__init__.py,sha256=3WcvIpOkQAy1p54BhLGfmi1hyY9Dhe0qSG2yZY9mPes,145
2
- karrio/mappers/hermes/mapper.py,sha256=0fZbXPHGg5R4bbhRyJbzfEGNiKXSINW1FJQnhz-4MRM,2258
3
- karrio/mappers/hermes/proxy.py,sha256=FG_OcaMEXiZxZp37m25pgrOtcdCziVk3Kft9HjoEnT8,2858
2
+ karrio/mappers/hermes/mapper.py,sha256=4xOrR9eFX-MKv6LKB32WD8hZuhnscB_OTgeKVVrGo6Q,2700
3
+ karrio/mappers/hermes/proxy.py,sha256=zGbLwJTwunrWp8b1Lg_hs3AwxPSd8Ogy6sydl99YaSs,4492
4
4
  karrio/mappers/hermes/settings.py,sha256=4BTM7ncSQqTBP6J_oJTksBDGhaFHOWoHDnpq0iOWHVo,1151
5
5
  karrio/plugins/hermes/__init__.py,sha256=zUfOhtzuErd1H1ICL4rQt68e6BWRQf_B6_kW5UVzd9M,1020
6
- karrio/providers/hermes/__init__.py,sha256=lwP0P714ipPISsbd_6xXZ4oaCK32yTEHktP8yxmF4NQ,490
6
+ karrio/providers/hermes/__init__.py,sha256=wMiVnPz7EgKdbu1pGBuvalfyuHj5QwSeMijjvEP6q4w,590
7
7
  karrio/providers/hermes/error.py,sha256=YWmYC_l7_nyJCxiqM0Kgf6yV9IpJ04tkdZyyMT7QnkY,2974
8
- karrio/providers/hermes/units.py,sha256=MO1ap8ItQUlwfTTx7_CqxJqx96KY-FyLm4pMSIXRg8g,8665
9
- karrio/providers/hermes/utils.py,sha256=84N70gICmOmP2vjYmnzJbjzLhFaEHvXLKgHALZiE-2k,3077
8
+ karrio/providers/hermes/tracking.py,sha256=olKfHEVYZuwGL9e4348Ui-mAKBGr94FLF6VyxCwtZZg,5941
9
+ karrio/providers/hermes/units.py,sha256=91B_i4BeY1e_XguBOG2MZ126IT3mKdz6-dvn70AJyv8,13633
10
+ karrio/providers/hermes/utils.py,sha256=NOfS_K0Zw7_wxJGBJfkdXwZP6hs0bsaZye5uypztGc4,4163
10
11
  karrio/providers/hermes/pickup/__init__.py,sha256=E59ks-qJAsNmfQgaZ7X0tZuBetITsdRSMJUAZnqxabg,307
11
12
  karrio/providers/hermes/pickup/cancel.py,sha256=JYVGL9decPB0QOHsjrYU5cwT_4vzrpsaEjapC9F3t7A,1587
12
- karrio/providers/hermes/pickup/create.py,sha256=q4AbBqI-_oXglD2DffJpqBp93zZo2hz-gf32DtX5lg8,3556
13
+ karrio/providers/hermes/pickup/create.py,sha256=ICSG7HgF45h8XY0Ypc8voA5TWFSVmysGerh1F-fha24,3993
13
14
  karrio/providers/hermes/shipment/__init__.py,sha256=B_zc5eaS4st1bnIyB_RwYY9XJJ9DyjB1Tb0SaIEJRJ8,209
14
- karrio/providers/hermes/shipment/create.py,sha256=UcKTavylyrdbeFmzXY7pqCUI1lfOxmMO2Cr07xoB1YY,13046
15
- karrio/schemas/hermes/__init__.py,sha256=yw5kUm6WMQ_UJEVW-LQUY-916m7Y-qxp0yLbqIMb2b4,1272
15
+ karrio/providers/hermes/shipment/create.py,sha256=DAkC5O9XHs6QOlLKBTQ8zKQlLNf6h5Ty29_qFhMSBWM,16677
16
+ karrio/schemas/hermes/__init__.py,sha256=zcJLsZ0HvWk9q7J07BAel3ib_eXFoN6_5joxbdzBLV0,1530
16
17
  karrio/schemas/hermes/error_response.py,sha256=BJhI7P8wursdYsYACfDLT8cs-bsnKlJDs0OzurYMPR4,343
17
18
  karrio/schemas/hermes/pickup_cancel_request.py,sha256=rZgm3BpL3iziO_TC_y-cAELMsWjXyvRYWmXYyExhdR0,148
18
19
  karrio/schemas/hermes/pickup_cancel_response.py,sha256=9-STL_Aq0EvXWrNMfvc4DiPK658e1JPp0uhW695XOGI,397
@@ -20,8 +21,9 @@ karrio/schemas/hermes/pickup_create_request.py,sha256=0V14LMl0XVLOZ_zXRzoTLUZ8nB
20
21
  karrio/schemas/hermes/pickup_create_response.py,sha256=sAgq92J0TZOUolhMcvDkp6qSRvxOqWCIZHNQWQN7KeU,397
21
22
  karrio/schemas/hermes/shipment_request.py,sha256=FMqrSlCDG4eGDkuqPDc_DDCbtV_vGRyrRBFCiNTFkmM,7415
22
23
  karrio/schemas/hermes/shipment_response.py,sha256=BI2kUemG-wTzAFpok9KEnlwjm6eK_LemBA_Cyga_e6A,3477
23
- karrio_hermes-2026.1.1.dist-info/METADATA,sha256=_bVkPkY-I95Ys5VB56QlkPmuWyG3xfL0_iWDRqAWyxY,982
24
- karrio_hermes-2026.1.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
25
- karrio_hermes-2026.1.1.dist-info/entry_points.txt,sha256=R8XDrYBqWXTPqaO0iTi4Buz8iQiiBiuHkJVNtZIXTkU,57
26
- karrio_hermes-2026.1.1.dist-info/top_level.txt,sha256=9Nasa6abG7pPPG8MGzlemnqw1ohIqgouzQ7HGBnOFLg,27
27
- karrio_hermes-2026.1.1.dist-info/RECORD,,
24
+ karrio/schemas/hermes/tracking_response.py,sha256=6-bqTSl-N65PHl8cs1puOCFubzIZB55RveLdpNsmTEE,1967
25
+ karrio_hermes-2026.1.4.dist-info/METADATA,sha256=cxB5FLr58U6GhdnY-8PCdSYMGHNPOPNiG46K9X-mirI,982
26
+ karrio_hermes-2026.1.4.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
27
+ karrio_hermes-2026.1.4.dist-info/entry_points.txt,sha256=R8XDrYBqWXTPqaO0iTi4Buz8iQiiBiuHkJVNtZIXTkU,57
28
+ karrio_hermes-2026.1.4.dist-info/top_level.txt,sha256=9Nasa6abG7pPPG8MGzlemnqw1ohIqgouzQ7HGBnOFLg,27
29
+ karrio_hermes-2026.1.4.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5