snap-python 0.1.5__py3-none-any.whl → 0.1.6__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.
- snap_python/client.py +0 -1
- snap_python/components/store.py +31 -2
- snap_python/schemas/store/info.py +7 -5
- snap_python/schemas/store/track.py +132 -0
- {snap_python-0.1.5.dist-info → snap_python-0.1.6.dist-info}/METADATA +1 -1
- {snap_python-0.1.5.dist-info → snap_python-0.1.6.dist-info}/RECORD +8 -7
- {snap_python-0.1.5.dist-info → snap_python-0.1.6.dist-info}/LICENSE +0 -0
- {snap_python-0.1.5.dist-info → snap_python-0.1.6.dist-info}/WHEEL +0 -0
snap_python/client.py
CHANGED
|
@@ -61,7 +61,6 @@ class SnapClient(AbstractSnapsClient):
|
|
|
61
61
|
headers=self.store_headers,
|
|
62
62
|
)
|
|
63
63
|
self.config = ConfigEndpoints(self)
|
|
64
|
-
self.snapd_client = httpx.AsyncClient(transport=self._transport)
|
|
65
64
|
|
|
66
65
|
@retry(httpx.HTTPError, tries=3, delay=1, backoff=1)
|
|
67
66
|
async def request(self, method: str, endpoint: str, **kwargs) -> httpx.Response:
|
snap_python/components/store.py
CHANGED
|
@@ -23,6 +23,10 @@ from snap_python.schemas.store.search import (
|
|
|
23
23
|
PaginatedSnapSearchResponse,
|
|
24
24
|
SearchResponse,
|
|
25
25
|
)
|
|
26
|
+
from snap_python.schemas.store.track import (
|
|
27
|
+
TrackRiskMap,
|
|
28
|
+
channel_map_to_current_track_map,
|
|
29
|
+
)
|
|
26
30
|
|
|
27
31
|
|
|
28
32
|
class StoreEndpoints:
|
|
@@ -165,7 +169,7 @@ class StoreEndpoints:
|
|
|
165
169
|
async def find(
|
|
166
170
|
self,
|
|
167
171
|
query: str | None = None,
|
|
168
|
-
fields: str | None = None,
|
|
172
|
+
fields: list[str] | None = None,
|
|
169
173
|
name_startswith: str | None = None,
|
|
170
174
|
architecture: str | None = None,
|
|
171
175
|
common_id: str | None = None,
|
|
@@ -183,7 +187,7 @@ class StoreEndpoints:
|
|
|
183
187
|
:param query: The search query.
|
|
184
188
|
:type query: str, optional
|
|
185
189
|
:param fields: The fields to include in the response.
|
|
186
|
-
:type fields: str, optional
|
|
190
|
+
:type fields: list[str], optional
|
|
187
191
|
:param name_startswith: Filter snaps by name prefix.
|
|
188
192
|
:type name_startswith: str, optional
|
|
189
193
|
:param architecture: Filter snaps by architecture.
|
|
@@ -494,3 +498,28 @@ class StoreEndpoints:
|
|
|
494
498
|
response_json["limit"] = limit
|
|
495
499
|
|
|
496
500
|
return PaginatedSnapSearchResponse.model_validate(response_json)
|
|
501
|
+
|
|
502
|
+
async def get_track_risk_map(
|
|
503
|
+
self, snap_name: str
|
|
504
|
+
) -> dict[str, dict[str, TrackRiskMap]]:
|
|
505
|
+
"""Get the track risk map for a snap.
|
|
506
|
+
|
|
507
|
+
:param snap_name: The name of the snap.
|
|
508
|
+
:type snap_name: str
|
|
509
|
+
|
|
510
|
+
:returns: A dictionary mapping tracks to their risk maps.
|
|
511
|
+
:rtype: dict[str, TrackRiskMap]
|
|
512
|
+
"""
|
|
513
|
+
snap_info = await self.get_snap_info(
|
|
514
|
+
snap_name=snap_name,
|
|
515
|
+
fields=[
|
|
516
|
+
"channel-map",
|
|
517
|
+
"architectures",
|
|
518
|
+
"base",
|
|
519
|
+
"revision",
|
|
520
|
+
"confinement",
|
|
521
|
+
"version",
|
|
522
|
+
"created-at",
|
|
523
|
+
],
|
|
524
|
+
)
|
|
525
|
+
return channel_map_to_current_track_map(snap_info.channel_map)
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
# generated by datamodel-codegen:
|
|
2
|
-
# filename: snaps_info_schema.json
|
|
3
|
-
# timestamp: 2024-10-17T01:47:02+00:00
|
|
4
|
-
|
|
5
1
|
from typing import List, Optional
|
|
6
2
|
|
|
7
|
-
from pydantic import
|
|
3
|
+
from pydantic import (
|
|
4
|
+
AliasChoices,
|
|
5
|
+
AwareDatetime,
|
|
6
|
+
BaseModel,
|
|
7
|
+
ConfigDict,
|
|
8
|
+
Field,
|
|
9
|
+
)
|
|
8
10
|
|
|
9
11
|
from snap_python.schemas.snaps import StoreSnap
|
|
10
12
|
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
from pydantic import (
|
|
5
|
+
AwareDatetime,
|
|
6
|
+
BaseModel,
|
|
7
|
+
field_validator,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
from snap_python.schemas.store.info import Channel, ChannelMapItem
|
|
11
|
+
|
|
12
|
+
logger = logging.getLogger("snap_python.schemas.store.track")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class TrackRevisionDetails(BaseModel):
|
|
16
|
+
arch: str
|
|
17
|
+
base: str
|
|
18
|
+
channel: Channel
|
|
19
|
+
confinement: str
|
|
20
|
+
created_at: AwareDatetime
|
|
21
|
+
released_at: AwareDatetime
|
|
22
|
+
revision: int
|
|
23
|
+
risk: str
|
|
24
|
+
track: str
|
|
25
|
+
version: str
|
|
26
|
+
|
|
27
|
+
@field_validator("arch")
|
|
28
|
+
@classmethod
|
|
29
|
+
def validate_arch(cls, value):
|
|
30
|
+
valid_architectures = {
|
|
31
|
+
"amd64",
|
|
32
|
+
"arm64",
|
|
33
|
+
"armhf",
|
|
34
|
+
"i386",
|
|
35
|
+
"ppc64el",
|
|
36
|
+
"s390x",
|
|
37
|
+
"riscv64",
|
|
38
|
+
}
|
|
39
|
+
if value not in valid_architectures:
|
|
40
|
+
raise ValueError(
|
|
41
|
+
f"Invalid architecture: {value}. Must be one of {', '.join(valid_architectures)}."
|
|
42
|
+
)
|
|
43
|
+
return value
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class TrackRiskMap(BaseModel):
|
|
47
|
+
amd64: Optional[TrackRevisionDetails] = None
|
|
48
|
+
arm64: Optional[TrackRevisionDetails] = None
|
|
49
|
+
armhf: Optional[TrackRevisionDetails] = None
|
|
50
|
+
i386: Optional[TrackRevisionDetails] = None
|
|
51
|
+
ppc64el: Optional[TrackRevisionDetails] = None
|
|
52
|
+
s390x: Optional[TrackRevisionDetails] = None
|
|
53
|
+
riscv64: Optional[TrackRevisionDetails] = None
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def architectures(self) -> list[str]:
|
|
57
|
+
"""Return a list of architectures that have revisions."""
|
|
58
|
+
return [
|
|
59
|
+
arch for arch, details in self.model_dump().items() if details is not None
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def channel_map_to_current_track_map(
|
|
64
|
+
channel_map: list[ChannelMapItem],
|
|
65
|
+
) -> dict[str, dict[str, TrackRiskMap]]:
|
|
66
|
+
"""Convert a list of ChannelMapItem to a map of TrackRiskMap.
|
|
67
|
+
|
|
68
|
+
track -> risk -> arch
|
|
69
|
+
"""
|
|
70
|
+
# track -> risk -> arch
|
|
71
|
+
current_track_map: dict[str, dict[str, TrackRiskMap]] = {}
|
|
72
|
+
|
|
73
|
+
all_tracks = set(item.channel.track for item in channel_map)
|
|
74
|
+
logger.debug(f"Found tracks: {', '.join(all_tracks)}")
|
|
75
|
+
|
|
76
|
+
for track in all_tracks:
|
|
77
|
+
current_track_map[track] = {}
|
|
78
|
+
|
|
79
|
+
for item in channel_map:
|
|
80
|
+
track = item.channel.track
|
|
81
|
+
risk = item.channel.risk
|
|
82
|
+
|
|
83
|
+
if not item.architectures:
|
|
84
|
+
logger.error(
|
|
85
|
+
f"Warning: Channel {item} has no architectures defined. Skipping."
|
|
86
|
+
)
|
|
87
|
+
continue
|
|
88
|
+
assert (
|
|
89
|
+
len(item.architectures) == 1
|
|
90
|
+
), "Channel must have exactly one architecture."
|
|
91
|
+
|
|
92
|
+
assert (
|
|
93
|
+
item.revision is not None
|
|
94
|
+
), f"Channel {item} must have a revision defined."
|
|
95
|
+
assert item.channel is not None, f"Channel {item} must have a channel defined."
|
|
96
|
+
assert item.base is not None, f"Channel {item} must have a base defined."
|
|
97
|
+
assert (
|
|
98
|
+
item.confinement is not None
|
|
99
|
+
), f"Channel {item} must have a confinement defined."
|
|
100
|
+
assert item.version is not None, f"Channel {item} must have a version defined."
|
|
101
|
+
assert (
|
|
102
|
+
item.created_at is not None
|
|
103
|
+
), f"Channel {item} must have a created_at defined."
|
|
104
|
+
assert (
|
|
105
|
+
item.channel.released_at is not None
|
|
106
|
+
), f"Channel {item} must have a released_at defined."
|
|
107
|
+
|
|
108
|
+
arch = item.architectures[0]
|
|
109
|
+
|
|
110
|
+
revision_details = TrackRevisionDetails(
|
|
111
|
+
arch=arch,
|
|
112
|
+
base=item.base,
|
|
113
|
+
channel=item.channel,
|
|
114
|
+
confinement=item.confinement,
|
|
115
|
+
created_at=item.created_at,
|
|
116
|
+
released_at=item.channel.released_at,
|
|
117
|
+
revision=item.revision,
|
|
118
|
+
risk=risk,
|
|
119
|
+
track=track,
|
|
120
|
+
version=item.version,
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
if risk not in current_track_map[track]:
|
|
124
|
+
current_track_map[track][risk] = TrackRiskMap()
|
|
125
|
+
setattr(current_track_map[track][risk], arch, revision_details)
|
|
126
|
+
|
|
127
|
+
# re validate the track map to ensure it has all required fields
|
|
128
|
+
for track, risk_map in current_track_map.items():
|
|
129
|
+
for risk in risk_map:
|
|
130
|
+
risk_map[risk] = TrackRiskMap.model_validate(risk_map[risk])
|
|
131
|
+
|
|
132
|
+
return current_track_map
|
|
@@ -1,25 +1,26 @@
|
|
|
1
1
|
snap_python/__init__.py,sha256=gV43Nempk7HFKD1UCvxUhmP9x6dBmPjotcITREr81Vg,222
|
|
2
|
-
snap_python/client.py,sha256=
|
|
2
|
+
snap_python/client.py,sha256=HrgLu0ebhPci8cN3GmfOWc9-ccri80Pk4Oys2RVdoQY,6539
|
|
3
3
|
snap_python/components/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
snap_python/components/config.py,sha256=IO_gCrumphEZioINFmXxb8I5OVsKC9cgSa28sQbZ700,1775
|
|
5
5
|
snap_python/components/snaps.py,sha256=NfZAgoNvsvf-aJa-ZZJoJxS-KrwrG6gBe1ScN2WM5To,18003
|
|
6
|
-
snap_python/components/store.py,sha256=
|
|
6
|
+
snap_python/components/store.py,sha256=gryTStqw4Wu7S7book4arqzfyzFcITRSCbW5BK89ce4,17839
|
|
7
7
|
snap_python/schemas/changes.py,sha256=7SYUFXAQq9arl7hAA3YQ0YubMurPJtknTOVxP8ryqew,1919
|
|
8
8
|
snap_python/schemas/common.py,sha256=GLtC9aBo3O8vLKX9PNvzE-_DKN02OGpwsS7Ik2WK9-8,2608
|
|
9
9
|
snap_python/schemas/config.py,sha256=xXTGhk6TpwI8RlR6_qnfWlBHrBnTwr3hRCO5qCnN-6U,107
|
|
10
10
|
snap_python/schemas/snaps.py,sha256=GTDi6_n5P7o9h7-cDllkkFYn8wS9EQ6VZ32rwYJD07A,3657
|
|
11
11
|
snap_python/schemas/store/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
12
|
snap_python/schemas/store/categories.py,sha256=PewotRqoPs7cMKtlZKsHVNfnJoItmNKMekS1Be-46l0,1082
|
|
13
|
-
snap_python/schemas/store/info.py,sha256=
|
|
13
|
+
snap_python/schemas/store/info.py,sha256=C5T88QMgMJZzG5BwRXGeSDVMlElefjv30i-Gqm8qRyA,4318
|
|
14
14
|
snap_python/schemas/store/json/category_by_name_schema.json,sha256=3-95m6V2WXaPCu_DZw-STa9YHPEbr7CI8fbhjaq881s,1674
|
|
15
15
|
snap_python/schemas/store/json/category_schema.json,sha256=c4h_eyyBbChOiNby3hYfjAh9i_1MDbPJnHHU4rGOGss,1898
|
|
16
16
|
snap_python/schemas/store/json/snaps_find_schema.json,sha256=TfKpnievs5QOc7ah97ATMCQTOEfKspONTZnwSwq_0fI,8866
|
|
17
17
|
snap_python/schemas/store/json/snaps_info_schema.json,sha256=udoOovb6Ea7EnE_R9RuZ1CpY1wOJ3-K8xP4-8zKHgrQ,15888
|
|
18
18
|
snap_python/schemas/store/refresh.py,sha256=HAlt-rKfy7vmZSCujMXtW9HHXlVYbHGFwy_BKfD1uCU,3190
|
|
19
19
|
snap_python/schemas/store/search.py,sha256=4ghZb8xY6IESxZuAvzSjM9RaEwZAH3zjiC06zLc0zvU,4561
|
|
20
|
+
snap_python/schemas/store/track.py,sha256=peOjBVccukjud7_Wn_M2hX6KvoJhyhX74FX5HeeHpm8,4099
|
|
20
21
|
snap_python/scrape.py,sha256=ZDJAROp8jwossaAA78gBFTKQzrfnO11RgyyOZqevNd0,4576
|
|
21
22
|
snap_python/utils.py,sha256=cmUooPg5DzNL197Xxvu7LGD4Gwk3xxsT68wbVytRtV0,1240
|
|
22
|
-
snap_python-0.1.
|
|
23
|
-
snap_python-0.1.
|
|
24
|
-
snap_python-0.1.
|
|
25
|
-
snap_python-0.1.
|
|
23
|
+
snap_python-0.1.6.dist-info/LICENSE,sha256=lYXNZszxC_l2rlBvrHYs-esDegxWh8MKtjrdxA24uOk,1072
|
|
24
|
+
snap_python-0.1.6.dist-info/METADATA,sha256=cfN_x0M8MSEtVq0Du6RlDQTrt6xzbd144tH6jyr_w34,1883
|
|
25
|
+
snap_python-0.1.6.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
26
|
+
snap_python-0.1.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|