karrio-hay-post 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,4 @@
1
+
2
+ from karrio.mappers.hay_post.mapper import Mapper
3
+ from karrio.mappers.hay_post.proxy import Proxy
4
+ from karrio.mappers.hay_post.settings import Settings
@@ -0,0 +1,40 @@
1
+ """Karrio HayPost 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.hay_post as provider
8
+ import karrio.mappers.hay_post.settings as provider_settings
9
+
10
+
11
+ class Mapper(mapper.Mapper):
12
+ settings: provider_settings.Settings
13
+
14
+ def create_rate_request(self, payload: models.RateRequest) -> lib.Serializable:
15
+ return provider.rate_request(payload, self.settings)
16
+
17
+ def create_tracking_request(
18
+ self, payload: models.TrackingRequest
19
+ ) -> lib.Serializable:
20
+ return provider.tracking_request(payload, self.settings)
21
+
22
+ def create_shipment_request(
23
+ self, payload: models.ShipmentRequest
24
+ ) -> lib.Serializable:
25
+ return provider.shipment_request(payload, self.settings)
26
+
27
+ def parse_rate_response(
28
+ self, response: lib.Deserializable[str]
29
+ ) -> typing.Tuple[typing.List[models.RateDetails], typing.List[models.Message]]:
30
+ return provider.parse_rate_response(response, self.settings)
31
+
32
+ def parse_shipment_response(
33
+ self, response: lib.Deserializable[str]
34
+ ) -> typing.Tuple[models.ShipmentDetails, typing.List[models.Message]]:
35
+ return provider.parse_shipment_response(response, self.settings)
36
+
37
+ def parse_tracking_response(
38
+ self, response: lib.Deserializable[str]
39
+ ) -> typing.Tuple[typing.List[models.TrackingDetails], typing.List[models.Message]]:
40
+ return provider.parse_tracking_response(response, self.settings)
@@ -0,0 +1,61 @@
1
+ """Karrio HayPost client proxy."""
2
+
3
+ import karrio.lib as lib
4
+ import karrio.api.proxy as proxy
5
+ import karrio.mappers.hay_post.settings as provider_settings
6
+
7
+
8
+ class Proxy(proxy.Proxy):
9
+ settings: provider_settings.Settings
10
+
11
+ def get_rates(self, request: lib.Serializable) -> lib.Deserializable[str]:
12
+ response = lib.request(
13
+ url=f"{self.settings.server_url}/Api/Order/CalculateTariff",
14
+ data=lib.to_json(lib.to_list(request.serialize())),
15
+ trace=self.trace_as("json"),
16
+ method="POST",
17
+ headers={
18
+ "Accept": "application/json",
19
+ "Content-Type": "application/json",
20
+ "Authorization": self.settings.authorization,
21
+ },
22
+ proxy=self.settings.proxy,
23
+ )
24
+
25
+ response_dict = {"rates": response, "request": request.value}
26
+
27
+ return lib.Deserializable(response_dict, lib.to_dict)
28
+
29
+ def create_shipment(self, request: lib.Serializable) -> lib.Deserializable[str]:
30
+ response = lib.request(
31
+ url=f"{self.settings.server_url}/Api/Order/CreateOrderByCustomerShort",
32
+ data=lib.to_json(request.serialize()),
33
+ trace=self.trace_as("json"),
34
+ method="POST",
35
+ headers={
36
+ "Accept": "application/json",
37
+ "Content-Type": "application/json",
38
+ "Authorization": self.settings.authorization,
39
+ },
40
+ proxy=self.settings.proxy,
41
+ )
42
+
43
+ return lib.Deserializable(response, lib.to_dict)
44
+
45
+ def get_tracking(self, request: lib.Serializable) -> lib.Deserializable[str]:
46
+ query = request.serialize()
47
+ trackingnumber = query[0]
48
+
49
+ response = lib.request(
50
+ url=f"{self.settings.server_url}/Api/Order/Tracking/{trackingnumber}",
51
+ trace=self.trace_as("json"),
52
+ method="GET",
53
+ proxy=self.settings.proxy,
54
+ headers={
55
+ "Accept": "application/json",
56
+ "Content-Type": "application/json",
57
+ "Authorization": self.settings.authorization,
58
+ },
59
+ )
60
+
61
+ return lib.Deserializable(response, lib.to_dict)
@@ -0,0 +1,23 @@
1
+ """Karrio HayPost client settings."""
2
+
3
+ import attr
4
+ import karrio.providers.hay_post.utils as provider_utils
5
+
6
+
7
+ @attr.s(auto_attribs=True)
8
+ class Settings(provider_utils.Settings):
9
+ """HayPost connection settings."""
10
+
11
+ # required carrier specific properties
12
+ username: str
13
+ password: str
14
+ customer_id: str
15
+ customer_type: str
16
+
17
+ # generic properties
18
+ id: str = None
19
+ test_mode: bool = False
20
+ carrier_id: str = "hay_post"
21
+ account_country_code: str = None
22
+ metadata: dict = {}
23
+ config: dict = {}
@@ -0,0 +1,23 @@
1
+ import karrio.core.metadata as metadata
2
+ import karrio.mappers.hay_post as mappers
3
+ import karrio.providers.hay_post.units as units
4
+
5
+
6
+ METADATA = metadata.PluginMetadata(
7
+ status="beta",
8
+ id="hay_post",
9
+ label="HayPost",
10
+
11
+ # Integrations
12
+ Mapper=mappers.Mapper,
13
+ Proxy=mappers.Proxy,
14
+ Settings=mappers.Settings,
15
+
16
+ # Data Units
17
+ services=units.ShippingService,
18
+ options=units.ShippingOption,
19
+ connection_configs=units.ConnectionConfig,
20
+ # package_presets=units.PackagePresets, # Enum of parcel presets/templates
21
+
22
+ is_hub=False
23
+ )
@@ -0,0 +1,11 @@
1
+
2
+ from karrio.providers.hay_post.utils import Settings
3
+ from karrio.providers.hay_post.rate import parse_rate_response, rate_request
4
+ from karrio.providers.hay_post.shipment import (
5
+ parse_shipment_response,
6
+ shipment_request,
7
+ )
8
+ from karrio.providers.hay_post.tracking import (
9
+ parse_tracking_response,
10
+ tracking_request,
11
+ )
@@ -0,0 +1,30 @@
1
+ import typing
2
+ import karrio.lib as lib
3
+ import karrio.core.models as models
4
+ import karrio.providers.hay_post.utils as provider_utils
5
+
6
+ import karrio.schemas.hay_post.error as hay_post
7
+
8
+
9
+ def parse_error_response(
10
+ response: dict,
11
+ settings: provider_utils.Settings,
12
+ **kwargs,
13
+ ) -> typing.List[models.Message]:
14
+ responses = response if isinstance(response, list) else [response]
15
+
16
+ errors: typing.List[hay_post.ErrorType] = [
17
+ lib.to_object(hay_post.ErrorType, error) for error in responses
18
+ ]
19
+
20
+ return [
21
+ models.Message(
22
+ carrier_id=settings.carrier_id,
23
+ carrier_name=settings.carrier_name,
24
+ code="error",
25
+ message=" ".join(error.key.split("_")).capitalize(),
26
+ details={**kwargs},
27
+ )
28
+ for error in errors
29
+ if error.key is not None
30
+ ]
@@ -0,0 +1,115 @@
1
+ import typing
2
+ import karrio.lib as lib
3
+ import karrio.core.models as models
4
+ import karrio.providers.hay_post.error as error
5
+
6
+ import karrio.providers.hay_post.utils as provider_utils
7
+ import karrio.providers.hay_post.units as provider_units
8
+ import karrio.schemas.hay_post.tariff_request as hay_post
9
+
10
+
11
+ def parse_rate_response(
12
+ _response: lib.Deserializable[dict],
13
+ settings: provider_utils.Settings,
14
+ ) -> typing.Tuple[typing.List[models.RateDetails], typing.List[models.Message]]:
15
+ response = _response.deserialize()
16
+ rate_response = lib.to_dict(response.get("rates"))
17
+
18
+ messages = error.parse_error_response(response, settings)
19
+ rates = [
20
+ (
21
+ _extract_details(response, settings)
22
+ if not isinstance(rate_response, dict)
23
+ else None
24
+ )
25
+ ]
26
+
27
+ return rates, messages
28
+
29
+
30
+ def _extract_details(
31
+ data: dict,
32
+ settings: provider_utils.Settings,
33
+ ) -> models.RateDetails:
34
+ service = provider_units.ShippingService.map(
35
+ str(data.get("request", {}).get("serviceCategoryDirectionId", 0))
36
+ )
37
+ currency = provider_units.ShippingCurrency.map(
38
+ str(data.get("request", {}).get("currencyId", 0))
39
+ ).name
40
+
41
+ return models.RateDetails(
42
+ carrier_id=settings.carrier_id,
43
+ carrier_name=settings.carrier_name,
44
+ service=service.name_or_key,
45
+ total_charge=lib.to_money(data.get("rates", 0)),
46
+ currency=currency,
47
+ )
48
+
49
+
50
+ def rate_request(
51
+ payload: models.RateRequest,
52
+ settings: provider_utils.Settings,
53
+ ) -> lib.Serializable:
54
+ shipper = lib.to_address(payload.shipper)
55
+ recipient = lib.to_address(payload.recipient)
56
+ packages = lib.to_packages(payload.parcels)
57
+
58
+ options = lib.to_shipping_options(
59
+ payload.options,
60
+ package_options=packages.options,
61
+ initializer=provider_units.shipping_options_initializer,
62
+ )
63
+
64
+ service = (
65
+ lib.to_services(payload.services, provider_units.ShippingService).first
66
+ or provider_units.ShippingService.yes_ordered_value
67
+ )
68
+
69
+ currency_id = lib.to_int(
70
+ provider_units.ShippingCurrency.map(options.currency.state).value
71
+ or provider_units.ShippingCurrency.AMD.value
72
+ )
73
+ additional_services = [
74
+ int(service.value.code)
75
+ for service in provider_units.ShippingOption
76
+ if service.name in options
77
+ ]
78
+
79
+ if not additional_services:
80
+ additional_services.append(
81
+ int(provider_units.ShippingOption.notification.value.code)
82
+ )
83
+
84
+ request = hay_post.TariffRequestElementType(
85
+ customerId=int(settings.customer_id),
86
+ serviceCategoryDirectionId=int(service.value),
87
+ weight=packages.weight.value,
88
+ totalPrice=packages.total_value if packages.total_value else 0,
89
+ currencyId=currency_id,
90
+ destinationAddress=hay_post.NAddressType(
91
+ cityVillage=recipient.city,
92
+ address=recipient.address_line1,
93
+ postalCode=recipient.postal_code,
94
+ receiverInfo=hay_post.ReceiverInfoType(
95
+ companyName=recipient.company_name,
96
+ firstName=recipient.person_name,
97
+ phoneNumber=recipient.phone_number,
98
+ email=recipient.email,
99
+ ),
100
+ ),
101
+ returnAddress=hay_post.NAddressType(
102
+ cityVillage=shipper.city,
103
+ address=shipper.address_line1,
104
+ postalCode=shipper.postal_code,
105
+ receiverInfo=hay_post.ReceiverInfoType(
106
+ companyName=shipper.company_name,
107
+ firstName=shipper.person_name,
108
+ phoneNumber=shipper.phone_number,
109
+ email=shipper.email,
110
+ ),
111
+ ),
112
+ additionalServices=additional_services,
113
+ )
114
+
115
+ return lib.Serializable(request, lib.to_dict)
@@ -0,0 +1,5 @@
1
+
2
+ from karrio.providers.hay_post.shipment.create import (
3
+ parse_shipment_response,
4
+ shipment_request,
5
+ )
@@ -0,0 +1,106 @@
1
+ import typing
2
+ import karrio.lib as lib
3
+ import karrio.core.units as units
4
+ import karrio.core.models as models
5
+ import karrio.providers.hay_post.error as error
6
+ import karrio.providers.hay_post.utils as provider_utils
7
+ import karrio.providers.hay_post.units as provider_units
8
+ import karrio.schemas.hay_post.order_create_request as hay_post
9
+ import karrio.schemas.hay_post.order_create_response as hay_post_response
10
+
11
+
12
+ def parse_shipment_response(
13
+ _response: lib.Deserializable[dict],
14
+ settings: provider_utils.Settings,
15
+ ) -> typing.Tuple[models.ShipmentDetails, typing.List[models.Message]]:
16
+ response = _response.deserialize()
17
+
18
+ messages = error.parse_error_response(response, settings)
19
+ shipment = (
20
+ _extract_details(response, settings) if response.get("key") is None else None
21
+ )
22
+
23
+ return shipment, messages
24
+
25
+
26
+ def _extract_details(
27
+ data: dict,
28
+ settings: provider_utils.Settings,
29
+ ) -> models.ShipmentDetails:
30
+ shipment = lib.to_object(hay_post_response.OrderCreateResponseType, data)
31
+ return models.ShipmentDetails(
32
+ carrier_id=settings.carrier_id,
33
+ carrier_name=settings.carrier_name,
34
+ tracking_number=shipment.barcode,
35
+ shipment_identifier=str(shipment.id),
36
+ docs=models.Documents(
37
+ label="No label...",
38
+ ),
39
+ meta=dict(
40
+ revertOrderId=shipment.revertOrderId,
41
+ revertBarcode=shipment.revertBarcode,
42
+ postalcode=shipment.postalcode,
43
+ ),
44
+ )
45
+
46
+
47
+ def shipment_request(
48
+ payload: models.ShipmentRequest,
49
+ settings: provider_utils.Settings,
50
+ ) -> lib.Serializable:
51
+ shipper = lib.to_address(payload.shipper)
52
+ recipient = lib.to_address(payload.recipient)
53
+ packages = lib.to_packages(payload.parcels)
54
+ service = provider_units.ShippingService.map(payload.service)
55
+
56
+ options = lib.to_shipping_options(
57
+ payload.options,
58
+ package_options=packages.options,
59
+ initializer=provider_units.shipping_options_initializer,
60
+ )
61
+
62
+ additional_services = [
63
+ int(service.value.code)
64
+ for service in provider_units.ShippingOption
65
+ if service.name in options
66
+ ]
67
+
68
+ shipper_country_id = lib.to_int(
69
+ provider_units.ShippingCountries.map(shipper.country_code).value
70
+ )
71
+ recipient_country_id = lib.to_int(
72
+ provider_units.ShippingCountries.map(recipient.country_code).value
73
+ )
74
+
75
+ request = hay_post.OrderCreateRequestType(
76
+ customerId=int(settings.customer_id),
77
+ serviceCategoryDirectionId=service.value,
78
+ weight=packages.weight.value,
79
+ destinationAddress=hay_post.NAddressType(
80
+ countryId=recipient_country_id,
81
+ street=recipient.street,
82
+ cityVillage=recipient.city,
83
+ postalCode=recipient.postal_code,
84
+ receiverInfo=hay_post.ReceiverInfoType(
85
+ companyName=recipient.company_name,
86
+ firstName=recipient.person_name,
87
+ phoneNumber=recipient.phone_number,
88
+ email=recipient.email,
89
+ ),
90
+ ),
91
+ returnAddress=hay_post.NAddressType(
92
+ countryId=shipper_country_id,
93
+ street=shipper.street,
94
+ cityVillage=shipper.city,
95
+ postalCode=shipper.postal_code,
96
+ receiverInfo=hay_post.ReceiverInfoType(
97
+ companyName=shipper.company_name,
98
+ firstName=shipper.person_name,
99
+ phoneNumber=shipper.phone_number,
100
+ email=shipper.email,
101
+ ),
102
+ ),
103
+ additionalServices=additional_services,
104
+ )
105
+
106
+ return lib.Serializable(request, lib.to_dict)
@@ -0,0 +1,82 @@
1
+ import typing
2
+ import karrio.lib as lib
3
+ import karrio.core.models as models
4
+ import karrio.providers.hay_post.error as error
5
+ import karrio.providers.hay_post.units as provider_units
6
+ import karrio.providers.hay_post.utils as provider_utils
7
+ import karrio.schemas.hay_post.order_tracking_response as hay_post
8
+
9
+ from datetime import datetime
10
+
11
+
12
+ def parse_tracking_response(
13
+ _response: lib.Deserializable[dict],
14
+ settings: provider_utils.Settings,
15
+ ) -> typing.Tuple[typing.List[models.TrackingDetails], typing.List[models.Message]]:
16
+ response = _response.deserialize()
17
+
18
+ messages = error.parse_error_response(response, settings)
19
+ tracking_details = [
20
+ _extract_details(response, settings) if response.get("key") is None else None
21
+ ]
22
+
23
+ return tracking_details, messages
24
+
25
+
26
+ def _extract_details(
27
+ data: dict,
28
+ settings: provider_utils.Settings,
29
+ ) -> models.TrackingDetails:
30
+ detail = lib.to_object(hay_post.OrderTrackingResponseType, data)
31
+
32
+ status = next(
33
+ (
34
+ status.name
35
+ for status in list(provider_units.TrackingStatus)
36
+ if detail.order.stateId in status.value
37
+ ),
38
+ provider_units.TrackingStatus.delivered.name,
39
+ )
40
+
41
+ return models.TrackingDetails(
42
+ tracking_number=detail.order.trackingId,
43
+ carrier_name=settings.carrier_name,
44
+ carrier_id=settings.carrier_id,
45
+ info=models.TrackingInfo(
46
+ customer_name=f"{detail.customer.firstName} {detail.customer.lastName}",
47
+ note=detail.order.comment,
48
+ order_date=lib.fdate(detail.order.createDate, "%Y-%m-%dT%H:%M:%S"),
49
+ order_id=str(detail.order.id),
50
+ package_weight=str(detail.order.weight),
51
+ shipment_pickup_date=lib.fdate(
52
+ detail.order.createDate, "%Y-%m-%dT%H:%M:%S"
53
+ ),
54
+ shipment_service=detail.order.service.name,
55
+ shipment_origin_country=detail.returnAddress.country.name,
56
+ shipment_origin_postal_code=detail.returnAddress.postalCode,
57
+ shipment_destination_country=detail.orderDestinationAddress.country.name,
58
+ shipment_destination_postal_code=detail.orderDestinationAddress.country.name,
59
+ ),
60
+ events=[
61
+ models.TrackingEvent(
62
+ date=lib.fdate(detail.order.createDate, "%Y-%m-%dT%H:%M:%S"),
63
+ description=(
64
+ detail.order.comment if detail.order.comment else "No description"
65
+ ),
66
+ code=detail.order.transactionId,
67
+ time=lib.fdate(detail.order.createDate, "%Y-%m-%dT%H:%M:%S"),
68
+ location=detail.orderDestinationAddress.address,
69
+ )
70
+ ],
71
+ delivered=status == "delivered",
72
+ status=status,
73
+ )
74
+
75
+
76
+ def tracking_request(
77
+ payload: models.TrackingRequest,
78
+ settings: provider_utils.Settings,
79
+ ) -> lib.Serializable:
80
+ request = payload.tracking_numbers
81
+
82
+ return lib.Serializable(request)
@@ -0,0 +1,303 @@
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 ShippingCurrency(lib.StrEnum):
21
+ RUB = "3"
22
+ USD = "2"
23
+ EUR = "4"
24
+ AMD = "1"
25
+
26
+
27
+ class ShippingService(lib.StrEnum):
28
+ """Carrier specific services"""
29
+
30
+ letter_ordered = "88"
31
+ letter_simple = "79"
32
+ letter_valued = "89"
33
+ package_ordered = "93"
34
+ package_simple = "92"
35
+ package_valued = "100"
36
+ parcel_simple = "94"
37
+ parcel_valued = "95"
38
+ postcard_ordered = "91"
39
+ postcard_simple = "90"
40
+ sekogram_simple = "96"
41
+ sprint_simple = "97"
42
+ yes_ordered_value = "99"
43
+
44
+
45
+ class ShippingOption(lib.Enum):
46
+ """Carrier specific options"""
47
+
48
+ notification = lib.OptionEnum("2", bool)
49
+ ordered_packaging = lib.OptionEnum("3", bool)
50
+ pick_up = lib.OptionEnum("4", bool)
51
+ postmen_delivery_value = lib.OptionEnum("5", bool)
52
+ delivery = lib.OptionEnum("6", bool)
53
+ international_notification = lib.OptionEnum("15", bool)
54
+ domestic_sms = lib.OptionEnum("16", bool)
55
+ international_sms = lib.OptionEnum("17", bool)
56
+
57
+
58
+ def shipping_options_initializer(
59
+ options: dict,
60
+ package_options: units.ShippingOptions = None,
61
+ ) -> units.ShippingOptions:
62
+ """
63
+ Apply default values to the given options.
64
+ """
65
+ _options = options.copy()
66
+
67
+ if package_options is not None:
68
+ _options.update(package_options.content)
69
+
70
+ return units.ShippingOptions(_options, ShippingOption)
71
+
72
+
73
+ class ConnectionConfig(lib.Enum):
74
+ shipping_options = lib.OptionEnum("shipping_options", list)
75
+ shipping_services = lib.OptionEnum("shipping_services", list)
76
+
77
+
78
+ class TrackingStatus(lib.Enum):
79
+ on_hold = [11]
80
+ delivered = [6]
81
+ in_transit = [1, 2, 7, 5]
82
+ delivery_failed = [10, 3, 4]
83
+ delivery_delayed = [8, 9]
84
+
85
+
86
+ class ShippingCountries(lib.Enum):
87
+ """Country codes"""
88
+
89
+ AF = 1
90
+ AL = 2
91
+ DZ = 3
92
+ AS = 4
93
+ AD = 5
94
+ AO = 6
95
+ AG = 9
96
+ AR = 10
97
+ AM = 11
98
+ AW = 12
99
+ AU = 13
100
+ AT = 14
101
+ BS = 16
102
+ BH = 17
103
+ BD = 18
104
+ BB = 19
105
+ BY = 20
106
+ BE = 21
107
+ BZ = 22
108
+ BJ = 23
109
+ BT = 25
110
+ BO = 26
111
+ BA = 28
112
+ BW = 29
113
+ BR = 31
114
+ VG = 33
115
+ BG = 35
116
+ BF = 36
117
+ BI = 37
118
+ CV = 38
119
+ KH = 39
120
+ CM = 40
121
+ CA = 41
122
+ KY = 42
123
+ CF = 43
124
+ TD = 44
125
+ CL = 45
126
+ CN = 46
127
+ HK = 47
128
+ MO = 47
129
+ CO = 51
130
+ KM = 52
131
+ CG = 53
132
+ CK = 54
133
+ CR = 55
134
+ HR = 56
135
+ CU = 57
136
+ CY = 59
137
+ CZ = 60
138
+ CD = 63
139
+ DK = 64
140
+ DJ = 65
141
+ DM = 66
142
+ DO = 67
143
+ EC = 68
144
+ EG = 69
145
+ SV = 70
146
+ GQ = 71
147
+ ER = 72
148
+ EE = 73
149
+ ET = 74
150
+ FJ = 77
151
+ FI = 78
152
+ FR = 79
153
+ GF = 80
154
+ PF = 81
155
+ GA = 83
156
+ GM = 84
157
+ GE = 85
158
+ DE = 86
159
+ GH = 87
160
+ GR = 89
161
+ GD = 91
162
+ GU = 93
163
+ GT = 94
164
+ GN = 96
165
+ GW = 97
166
+ GY = 98
167
+ HT = 99
168
+ HN = 102
169
+ HU = 103
170
+ IS = 104
171
+ IN = 105
172
+ ID = 106
173
+ IQ = 108
174
+ IE = 109
175
+ IL = 111
176
+ IT = 112
177
+ JM = 113
178
+ JP = 114
179
+ JO = 116
180
+ KZ = 117
181
+ KE = 118
182
+ KI = 119
183
+ KW = 120
184
+ KG = 121
185
+ LV = 123
186
+ LB = 124
187
+ LS = 125
188
+ LY = 127
189
+ LI = 128
190
+ LT = 129
191
+ LU = 130
192
+ MG = 131
193
+ MW = 132
194
+ MY = 133
195
+ MV = 134
196
+ ML = 135
197
+ MT = 136
198
+ MH = 137
199
+ MQ = 138
200
+ MR = 139
201
+ MU = 140
202
+ MX = 142
203
+ FM = 143
204
+ MC = 144
205
+ MN = 145
206
+ ME = 146
207
+ MZ = 149
208
+ MM = 150
209
+ NA = 151
210
+ NR = 152
211
+ NP = 153
212
+ NL = 154
213
+ NC = 155
214
+ NZ = 156
215
+ NI = 157
216
+ NE = 158
217
+ NG = 159
218
+ NU = 160
219
+ MP = 162
220
+ NO = 163
221
+ OM = 164
222
+ PK = 165
223
+ PW = 166
224
+ PA = 167
225
+ PG = 168
226
+ PY = 169
227
+ PE = 170
228
+ PH = 171
229
+ PL = 173
230
+ PT = 174
231
+ PR = 175
232
+ QA = 176
233
+ MD = 178
234
+ RO = 179
235
+ RU = 180
236
+ RW = 181
237
+ KN = 185
238
+ VC = 189
239
+ WS = 190
240
+ SM = 191
241
+ ST = 192
242
+ SA = 193
243
+ SN = 194
244
+ RS = 195
245
+ SC = 196
246
+ SL = 197
247
+ SG = 198
248
+ SK = 200
249
+ SI = 201
250
+ SB = 202
251
+ SO = 203
252
+ ZA = 204
253
+ ES = 207
254
+ LK = 208
255
+ PS = 209
256
+ SD = 210
257
+ SR = 211
258
+ SE = 214
259
+ CH = 215
260
+ SY = 216
261
+ TJ = 217
262
+ TH = 218
263
+ TL = 220
264
+ TG = 221
265
+ TO = 223
266
+ TT = 224
267
+ TN = 225
268
+ TM = 227
269
+ TV = 229
270
+ UG = 230
271
+ UA = 231
272
+ AE = 232
273
+ GB = 233
274
+ TZ = 234
275
+ US = 237
276
+ UY = 238
277
+ UZ = 239
278
+ VU = 240
279
+ VE = 241
280
+ VN = 242
281
+ YE = 245
282
+ ZM = 246
283
+ ZW = 247
284
+ BN = 252
285
+ GP = 253
286
+ SZ = 254
287
+ BL = 255
288
+ VA = 256
289
+ KR = 257
290
+ KP = 258
291
+ IR = 454
292
+ TW = 455
293
+ TR = 456
294
+ JE = 458
295
+ MK = 459
296
+ CW = 460
297
+ BM = 464
298
+ LA = 465
299
+ LR = 466
300
+ MA = 467
301
+ LC = 468
302
+ SS = 469
303
+ CI = 470
@@ -0,0 +1,65 @@
1
+ import json
2
+ import karrio.lib as lib
3
+ import karrio.core as core
4
+
5
+
6
+ class Settings(core.Settings):
7
+ """HayPost connection settings."""
8
+
9
+ username: str
10
+ password: str
11
+ customer_id: str
12
+ customer_type: str
13
+
14
+ @property
15
+ def proxy(self):
16
+ # Add proxy for using hay_post API in test mode
17
+ if self.test_mode:
18
+ return "username:passowrd@host:port"
19
+ return None
20
+
21
+ @property
22
+ def carrier_name(self):
23
+ return "hay_post"
24
+
25
+ @property
26
+ def connection_config(self) -> lib.units.Options:
27
+ from karrio.providers.hay_post.units import ConnectionConfig
28
+
29
+ return lib.to_connection_config(
30
+ self.config or {},
31
+ option_type=ConnectionConfig,
32
+ )
33
+
34
+ @property
35
+ def server_url(self):
36
+ if self.test_mode:
37
+ return "https://dev-order.haypost.am"
38
+ return "https://order.haypost.am"
39
+
40
+ @property
41
+ def authorization(self):
42
+ url = "https://identity.haypost.am/api/Connect/Token"
43
+ if self.test_mode:
44
+ url = "https://dev-identity.haypost.am/api/Connect/Token"
45
+
46
+ try:
47
+ response = lib.request(
48
+ url=url,
49
+ method="POST",
50
+ data=json.dumps(
51
+ {
52
+ "username": self.username,
53
+ "password": self.password,
54
+ "customerType": self.customer_type,
55
+ }
56
+ ),
57
+ proxy=self.proxy,
58
+ headers={"Content-Type": "application/json"},
59
+ )
60
+
61
+ return lib.to_dict(response).get("accessToken")
62
+
63
+ except Exception as e:
64
+ print(f"Request failed: {e}")
65
+ return None
File without changes
@@ -0,0 +1,12 @@
1
+ import attr
2
+ import jstruct
3
+ import typing
4
+
5
+
6
+ @attr.s(auto_attribs=True)
7
+ class AuthRequestType:
8
+ username: typing.Optional[str] = None
9
+ password: typing.Optional[str] = None
10
+ customerType: typing.Optional[int] = None
11
+ deviceId: typing.Optional[str] = None
12
+ fcmToken: typing.Optional[str] = None
@@ -0,0 +1,11 @@
1
+ import attr
2
+ import jstruct
3
+ import typing
4
+
5
+
6
+ @attr.s(auto_attribs=True)
7
+ class AuthResponseType:
8
+ accessToken: typing.Optional[str] = None
9
+ expDate: typing.Optional[int] = None
10
+ refreshToken: typing.Optional[str] = None
11
+ navigation: typing.Optional[int] = None
@@ -0,0 +1,9 @@
1
+ import attr
2
+ import jstruct
3
+ import typing
4
+
5
+
6
+ @attr.s(auto_attribs=True)
7
+ class ErrorType:
8
+ key: typing.Optional[str] = None
9
+ name: typing.Optional[str] = None
@@ -0,0 +1,36 @@
1
+ import attr
2
+ import jstruct
3
+ import typing
4
+
5
+
6
+ @attr.s(auto_attribs=True)
7
+ class ReceiverInfoType:
8
+ companyName: typing.Optional[str] = None
9
+ firstName: typing.Optional[str] = None
10
+ lastName: typing.Optional[str] = None
11
+ phoneNumber: typing.Optional[str] = None
12
+ email: typing.Optional[str] = None
13
+
14
+
15
+ @attr.s(auto_attribs=True)
16
+ class NAddressType:
17
+ countryId: typing.Optional[int] = None
18
+ provinceStateId: typing.Optional[int] = None
19
+ cityVillage: typing.Optional[str] = None
20
+ street: typing.Optional[str] = None
21
+ building: typing.Optional[int] = None
22
+ apartment: typing.Optional[int] = None
23
+ postalCode: typing.Optional[str] = None
24
+ receiverInfo: typing.Optional[ReceiverInfoType] = jstruct.JStruct[ReceiverInfoType]
25
+
26
+
27
+ @attr.s(auto_attribs=True)
28
+ class OrderCreateRequestType:
29
+ customerId: typing.Optional[int] = None
30
+ serviceCategoryDirectionId: typing.Optional[int] = None
31
+ weight: typing.Optional[int] = None
32
+ comment: typing.Optional[str] = None
33
+ returnRegisteredAddress: typing.Optional[bool] = None
34
+ destinationAddress: typing.Optional[NAddressType] = jstruct.JStruct[NAddressType]
35
+ returnAddress: typing.Optional[NAddressType] = jstruct.JStruct[NAddressType]
36
+ additionalServices: typing.Optional[typing.List[int]] = None
@@ -0,0 +1,12 @@
1
+ import attr
2
+ import jstruct
3
+ import typing
4
+
5
+
6
+ @attr.s(auto_attribs=True)
7
+ class OrderCreateResponseType:
8
+ id: typing.Optional[int] = None
9
+ barcode: typing.Optional[str] = None
10
+ revertOrderId: typing.Optional[int] = None
11
+ revertBarcode: typing.Optional[str] = None
12
+ postalcode: typing.Any = None
@@ -0,0 +1,8 @@
1
+ import attr
2
+ import jstruct
3
+ import typing
4
+
5
+
6
+ @attr.s(auto_attribs=True)
7
+ class OrderTrackingRequestType:
8
+ trackingnumber: typing.Optional[int] = None
@@ -0,0 +1,103 @@
1
+ import attr
2
+ import jstruct
3
+ import typing
4
+
5
+
6
+ @attr.s(auto_attribs=True)
7
+ class AdditionalServiceType:
8
+ id: typing.Optional[int] = None
9
+ name: typing.Optional[str] = None
10
+ fee: typing.Optional[int] = None
11
+ key: typing.Optional[str] = None
12
+ relationIndexId: typing.Optional[int] = None
13
+ isActive: typing.Optional[bool] = None
14
+
15
+
16
+ @attr.s(auto_attribs=True)
17
+ class LegalTypeObjectType:
18
+ id: typing.Optional[int] = None
19
+ name: typing.Optional[str] = None
20
+
21
+
22
+ @attr.s(auto_attribs=True)
23
+ class CustomerType:
24
+ customerId: typing.Optional[int] = None
25
+ firstName: typing.Optional[str] = None
26
+ lastName: typing.Optional[str] = None
27
+ phone: typing.Any = None
28
+ legalType: typing.Optional[LegalTypeObjectType] = jstruct.JStruct[LegalTypeObjectType]
29
+ documents: typing.Optional[typing.List[typing.Any]] = None
30
+ companyName: typing.Any = None
31
+
32
+
33
+ @attr.s(auto_attribs=True)
34
+ class OrderType:
35
+ id: typing.Optional[int] = None
36
+ customerId: typing.Optional[int] = None
37
+ trackingId: typing.Optional[str] = None
38
+ amount: typing.Optional[int] = None
39
+ weight: typing.Optional[int] = None
40
+ stateId: typing.Optional[int] = None
41
+ comment: typing.Optional[str] = None
42
+ service: typing.Optional[LegalTypeObjectType] = jstruct.JStruct[LegalTypeObjectType]
43
+ category: typing.Optional[LegalTypeObjectType] = jstruct.JStruct[LegalTypeObjectType]
44
+ transactionId: typing.Any = None
45
+ bundle: typing.Any = None
46
+ shipment: typing.Any = None
47
+ createDate: typing.Optional[str] = None
48
+ isVerified: typing.Optional[bool] = None
49
+ recaddress: typing.Any = None
50
+ locationId: typing.Any = None
51
+ codAmount: typing.Any = None
52
+ paymentMethodId: typing.Optional[int] = None
53
+ isInternational: typing.Optional[bool] = None
54
+ partner: typing.Any = None
55
+
56
+
57
+ @attr.s(auto_attribs=True)
58
+ class ReceiverInfoType:
59
+ companyName: typing.Optional[str] = None
60
+ firstName: typing.Optional[str] = None
61
+ lastName: typing.Optional[str] = None
62
+ phoneNumber: typing.Optional[str] = None
63
+ email: typing.Optional[str] = None
64
+ nickname: typing.Any = None
65
+
66
+
67
+ @attr.s(auto_attribs=True)
68
+ class NAddressType:
69
+ country: typing.Optional[LegalTypeObjectType] = jstruct.JStruct[LegalTypeObjectType]
70
+ provinceState: typing.Optional[LegalTypeObjectType] = jstruct.JStruct[LegalTypeObjectType]
71
+ cityVillage: typing.Optional[LegalTypeObjectType] = jstruct.JStruct[LegalTypeObjectType]
72
+ street: typing.Optional[LegalTypeObjectType] = jstruct.JStruct[LegalTypeObjectType]
73
+ building: typing.Optional[LegalTypeObjectType] = jstruct.JStruct[LegalTypeObjectType]
74
+ apartment: typing.Optional[LegalTypeObjectType] = jstruct.JStruct[LegalTypeObjectType]
75
+ postalCode: typing.Optional[str] = None
76
+ address: typing.Any = None
77
+ isHomeDelivery: typing.Optional[bool] = None
78
+ isDeliveryPaid: typing.Optional[bool] = None
79
+ deliveryDate: typing.Optional[str] = None
80
+ receiverInfo: typing.Optional[ReceiverInfoType] = jstruct.JStruct[ReceiverInfoType]
81
+ factreceiverInfo: typing.Any = None
82
+
83
+
84
+ @attr.s(auto_attribs=True)
85
+ class OrderStateHistoryType:
86
+ id: typing.Optional[int] = None
87
+ orderId: typing.Optional[int] = None
88
+ stateId: typing.Optional[int] = None
89
+ createDate: typing.Optional[str] = None
90
+ userId: typing.Optional[int] = None
91
+ isActive: typing.Optional[bool] = None
92
+
93
+
94
+ @attr.s(auto_attribs=True)
95
+ class OrderTrackingResponseType:
96
+ order: typing.Optional[OrderType] = jstruct.JStruct[OrderType]
97
+ info: typing.Any = None
98
+ orderDestinationAddress: typing.Optional[NAddressType] = jstruct.JStruct[NAddressType]
99
+ returnAddress: typing.Optional[NAddressType] = jstruct.JStruct[NAddressType]
100
+ customer: typing.Optional[CustomerType] = jstruct.JStruct[CustomerType]
101
+ orderStateHistories: typing.Optional[typing.List[OrderStateHistoryType]] = jstruct.JList[OrderStateHistoryType]
102
+ additionalServices: typing.Optional[typing.List[AdditionalServiceType]] = jstruct.JList[AdditionalServiceType]
103
+ rejectedOrders: typing.Optional[typing.List[typing.Any]] = None
@@ -0,0 +1,80 @@
1
+ import attr
2
+ import jstruct
3
+ import typing
4
+
5
+
6
+ @attr.s(auto_attribs=True)
7
+ class ReceiverInfoType:
8
+ companyName: typing.Optional[str] = None
9
+ firstName: typing.Optional[str] = None
10
+ lastName: typing.Optional[str] = None
11
+ phoneNumber: typing.Optional[str] = None
12
+ email: typing.Optional[str] = None
13
+ nickname: typing.Optional[str] = None
14
+
15
+
16
+ @attr.s(auto_attribs=True)
17
+ class NAddressType:
18
+ countryId: typing.Optional[int] = None
19
+ provinceStateId: typing.Optional[int] = None
20
+ provinceState: typing.Optional[str] = None
21
+ cityVillageId: typing.Optional[int] = None
22
+ cityVillage: typing.Optional[str] = None
23
+ streetId: typing.Optional[int] = None
24
+ street: typing.Optional[str] = None
25
+ buildingId: typing.Optional[int] = None
26
+ building: typing.Optional[str] = None
27
+ apartment: typing.Optional[str] = None
28
+ apartmentId: typing.Optional[int] = None
29
+ address: typing.Optional[str] = None
30
+ postalCode: typing.Optional[str] = None
31
+ deliveryDate: typing.Optional[str] = None
32
+ receiverInfo: typing.Optional[ReceiverInfoType] = jstruct.JStruct[ReceiverInfoType]
33
+
34
+
35
+ @attr.s(auto_attribs=True)
36
+ class CodType:
37
+ amount: typing.Optional[int] = None
38
+ bank: typing.Optional[str] = None
39
+ accountNumber: typing.Optional[str] = None
40
+
41
+
42
+ @attr.s(auto_attribs=True)
43
+ class EnclosureEnclosureType:
44
+ description: typing.Optional[str] = None
45
+ hsCode: typing.Optional[str] = None
46
+ quantity: typing.Optional[int] = None
47
+ weight: typing.Optional[int] = None
48
+ amount: typing.Optional[int] = None
49
+ countryOfOrigin: typing.Optional[str] = None
50
+
51
+
52
+ @attr.s(auto_attribs=True)
53
+ class OrderInfoEnclosureType:
54
+ enclosures: typing.Optional[typing.List[EnclosureEnclosureType]] = jstruct.JList[EnclosureEnclosureType]
55
+ enclosureTypeId: typing.Optional[int] = None
56
+
57
+
58
+ @attr.s(auto_attribs=True)
59
+ class OrderInfoType:
60
+ valuedAmount: typing.Optional[int] = None
61
+ valuedAmountCurrency: typing.Optional[int] = None
62
+ enclosure: typing.Optional[typing.List[OrderInfoEnclosureType]] = jstruct.JList[OrderInfoEnclosureType]
63
+ cod: typing.Optional[CodType] = jstruct.JStruct[CodType]
64
+
65
+
66
+ @attr.s(auto_attribs=True)
67
+ class TariffRequestElementType:
68
+ customerId: typing.Optional[int] = None
69
+ serviceCategoryDirectionId: typing.Optional[int] = None
70
+ weight: typing.Optional[int] = None
71
+ totalPrice: typing.Optional[int] = None
72
+ currencyId: typing.Optional[int] = None
73
+ comment: typing.Optional[str] = None
74
+ returnRegisteredAddress: typing.Optional[bool] = None
75
+ partner: typing.Optional[int] = None
76
+ externalId: typing.Optional[str] = None
77
+ destinationAddress: typing.Optional[NAddressType] = jstruct.JStruct[NAddressType]
78
+ returnAddress: typing.Optional[NAddressType] = jstruct.JStruct[NAddressType]
79
+ orderInfo: typing.Optional[OrderInfoType] = jstruct.JStruct[OrderInfoType]
80
+ additionalServices: typing.Optional[typing.List[int]] = None
@@ -0,0 +1,86 @@
1
+ Metadata-Version: 2.4
2
+ Name: karrio_hay_post
3
+ Version: 2025.5rc1
4
+ Summary: Karrio - HayPost 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.7
12
+ Description-Content-Type: text/markdown
13
+ Requires-Dist: karrio
14
+
15
+ # karrio.hay_post
16
+
17
+ This package is a HayPost extension of the [karrio](https://pypi.org/project/karrio) multi carrier shipping SDK.
18
+
19
+ ## Requirements
20
+
21
+ `Python 3.7+`
22
+
23
+ ## Installation
24
+
25
+ ```bash
26
+ pip install karrio.hay_post
27
+ ```
28
+
29
+ ## Usage
30
+
31
+ ```python
32
+ import karrio.sdk as karrio
33
+ from karrio.mappers.hay_post.settings import Settings
34
+
35
+ # Initialize a carrier gateway
36
+ hay_post = karrio.gateway["hay_post"].create(
37
+ Settings(
38
+ ...
39
+ )
40
+ )
41
+ ```
42
+
43
+ For test mode, you need to add your proxy or use a static IP address that HayPost has whitelisted.
44
+ Additionally, you need to connect with HayPost managers to obtain test and production
45
+ accounts. [Haypost ContactUs](https://www.haypost.am/en/contact-us)
46
+
47
+ Check the [Karrio Mutli-carrier SDK docs](https://docs.karrio.io) for Shipping API requests
48
+
49
+ ## Additional information
50
+
51
+ ### Services
52
+
53
+ * letter_ordered
54
+ * letter_simple
55
+ * letter_valued
56
+ * package_ordered
57
+ * package_simple
58
+ * package_valued
59
+ * parcel_simple
60
+ * parcel_valued
61
+ * postcard_ordered
62
+ * postcard_simple
63
+ * sekogram_simple
64
+ * sprint_simple
65
+ * yes_ordered_value
66
+
67
+ ### Currencies
68
+
69
+ * RUB
70
+ * USD
71
+ * EUR
72
+ * AMD
73
+
74
+ ### Additional Services as Option
75
+
76
+ * notification
77
+ * ordered_packaging
78
+ * pick_up
79
+ * postmen_delivery_value
80
+ * delivery
81
+ * international_notification
82
+ * domestic_sms
83
+ * international_sms
84
+
85
+ ### Note
86
+ * To obtain rates, you first need to configure them in the Carrier Configurations section (Services and Options).
@@ -0,0 +1,27 @@
1
+ karrio/mappers/hay_post/__init__.py,sha256=1KDqsn4fjq_tSOtOpLMPRCY9ox0PmGKSPaET8HVebPs,153
2
+ karrio/mappers/hay_post/mapper.py,sha256=uj_CU-C4eq_zh17PnjhKeH3W0G5nUJagRovsKjn3sH4,1522
3
+ karrio/mappers/hay_post/proxy.py,sha256=1AT6Dgpz9Yc2Gns0ft4l_tA7z2OE3STLmRAmktDtSYw,2186
4
+ karrio/mappers/hay_post/settings.py,sha256=FOi3lE_7mZMmiid-xxhzM2RbLcQbSslEf8ZgIghoHz4,530
5
+ karrio/plugins/hay_post/__init__.py,sha256=QWyl2q-cdQkKMG-LRIZwvNR-_6hwlr_FH2Ku0nkzzFk,565
6
+ karrio/providers/hay_post/__init__.py,sha256=kgo_OSPJ2IZQ8-gv94VuUzCmOd-lg-2LInid3EaLxEY,335
7
+ karrio/providers/hay_post/error.py,sha256=WYD8M-o7jcsyXfpaNa0xO5k-UY0J8x7V7F_lVf3IeqM,845
8
+ karrio/providers/hay_post/rate.py,sha256=_H_WR2YMCRN9ENpSzxwv8VqYkdMYsD0L_YZ9_qFq8a0,3778
9
+ karrio/providers/hay_post/tracking.py,sha256=EwOTybLxitEfcdFq2Mus_fPMv3PyEQK_tITJNsS2Evs,2967
10
+ karrio/providers/hay_post/units.py,sha256=-EZFSjCQ-VeimynqzwSkc40v-XTbvHLrEIlccw_AY_4,4811
11
+ karrio/providers/hay_post/utils.py,sha256=7aukNJcwzvjx4027p7XMwBTdiGXeZOyuFkGpSqRBGIA,1733
12
+ karrio/providers/hay_post/shipment/__init__.py,sha256=Y7q1mUiD5sRy9tWuXpIGqPcDPMLodmOy4-QJ3xpAJCo,110
13
+ karrio/providers/hay_post/shipment/create.py,sha256=cfgG1t0yV1BH1QJN_xXHqlt5y_6vPgyBWPEjIbfcRTU,3625
14
+ karrio/schemas/hay_post/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
+ karrio/schemas/hay_post/auth_request.py,sha256=_GEoPHr590QEy3o4dOA3EhpRRumSLxuhyQn4WcHU2W8,307
16
+ karrio/schemas/hay_post/auth_response.py,sha256=vTpl-Lv4FGQTmL3e2G9JkoMoiUdmocMoF7H7bFm-9d0,270
17
+ karrio/schemas/hay_post/error.py,sha256=mSwJo38_ehtXr8Er7rGhbCP9k55wbCae4aEv4emApXA,162
18
+ karrio/schemas/hay_post/order_create_request.py,sha256=MfLYbWKxKTHalG5Tl_6jfGKOLRGenBXImuS3EFK6D7U,1285
19
+ karrio/schemas/hay_post/order_create_response.py,sha256=nhpjb5pbP8WBQ3z9w2y7fcfFeLlsC3y9uSLhU8v8KDg,306
20
+ karrio/schemas/hay_post/order_tracking_request.py,sha256=m8RBuPzaA7h7x_GQzFdY6kJOHq4awSXVT2GTyHMpyAA,150
21
+ karrio/schemas/hay_post/order_tracking_response.py,sha256=axk2Tny9yRfrSOF7_5FeuVzgLIDIcH69Fohjvxa8UoM,4043
22
+ karrio/schemas/hay_post/tariff_request.py,sha256=lct5WzV7wnFAcjw9Yuls9WDgvw0LQtJfb5OtjbyVa7g,2913
23
+ karrio_hay_post-2025.5rc1.dist-info/METADATA,sha256=8AsnrCRaOUJPSmAkzbn2F9B0vlcHfvYrChc8Goq06wk,1937
24
+ karrio_hay_post-2025.5rc1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
25
+ karrio_hay_post-2025.5rc1.dist-info/entry_points.txt,sha256=XF98wJWJnsSYHoobsm-_5qos_8oHR38gRV8PHtlXqog,61
26
+ karrio_hay_post-2025.5rc1.dist-info/top_level.txt,sha256=FZCY8Nwft8oEGHdl--xku8P3TrnOxu5dETEU_fWpRSM,20
27
+ karrio_hay_post-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
+ hay_post = karrio.plugins.hay_post:METADATA
@@ -0,0 +1,3 @@
1
+ dist
2
+ karrio
3
+ schemas