snap-python 0.1.4__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/snaps.py +138 -3
- snap_python/components/store.py +31 -2
- snap_python/schemas/snaps.py +25 -1
- snap_python/schemas/store/info.py +7 -5
- snap_python/schemas/store/track.py +132 -0
- {snap_python-0.1.4.dist-info → snap_python-0.1.6.dist-info}/METADATA +1 -1
- {snap_python-0.1.4.dist-info → snap_python-0.1.6.dist-info}/RECORD +10 -9
- {snap_python-0.1.4.dist-info → snap_python-0.1.6.dist-info}/WHEEL +1 -1
- {snap_python-0.1.4.dist-info → snap_python-0.1.6.dist-info}/LICENSE +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/snaps.py
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import logging
|
|
3
3
|
from pathlib import Path
|
|
4
|
+
from typing import Any
|
|
4
5
|
|
|
5
6
|
import httpx
|
|
6
7
|
|
|
7
8
|
from snap_python.schemas.changes import ChangesResponse
|
|
8
|
-
from snap_python.schemas.common import AsyncResponse
|
|
9
|
+
from snap_python.schemas.common import AsyncResponse, BaseErrorResult
|
|
9
10
|
from snap_python.schemas.snaps import (
|
|
11
|
+
AppsResponse,
|
|
10
12
|
InstalledSnapListResponse,
|
|
11
13
|
SingleInstalledSnapResponse,
|
|
12
14
|
)
|
|
@@ -34,14 +36,13 @@ class SnapsEndpoints:
|
|
|
34
36
|
"GET", self.common_endpoint
|
|
35
37
|
)
|
|
36
38
|
|
|
37
|
-
response = InstalledSnapListResponse.model_validate_json(response.content)
|
|
38
39
|
if response.status_code > 299:
|
|
39
40
|
raise httpx.HTTPStatusError(
|
|
40
41
|
request=response.request,
|
|
41
42
|
response=response,
|
|
42
43
|
message=f"Invalid status code in response: {response.status_code}",
|
|
43
44
|
)
|
|
44
|
-
return response
|
|
45
|
+
return InstalledSnapListResponse.model_validate_json(response.content)
|
|
45
46
|
|
|
46
47
|
async def get_snap_info(self, snap: str) -> SingleInstalledSnapResponse:
|
|
47
48
|
"""
|
|
@@ -331,3 +332,137 @@ class SnapsEndpoints:
|
|
|
331
332
|
previous_changes = changes
|
|
332
333
|
return changes
|
|
333
334
|
return response
|
|
335
|
+
|
|
336
|
+
async def disable_snap(
|
|
337
|
+
self,
|
|
338
|
+
snap: str,
|
|
339
|
+
wait: bool = False,
|
|
340
|
+
) -> AsyncResponse | ChangesResponse:
|
|
341
|
+
"""
|
|
342
|
+
Disables a snap package.
|
|
343
|
+
|
|
344
|
+
:param snap: The name of the snap package to disable.
|
|
345
|
+
:type snap: str
|
|
346
|
+
:param wait: Whether to wait for the disable operation to complete. Defaults to False.
|
|
347
|
+
:type wait: bool, optional
|
|
348
|
+
|
|
349
|
+
:returns: The response from the disable operation.
|
|
350
|
+
:rtype: AsyncResponse | ChangesResponse
|
|
351
|
+
|
|
352
|
+
:raises SnapdAPIError: If there is an error during the snap disable operation.
|
|
353
|
+
"""
|
|
354
|
+
request_data = {
|
|
355
|
+
"action": "disable",
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
raw_response: httpx.Response = await self._client.request(
|
|
359
|
+
"POST", f"{self.common_endpoint}/{snap}", json=request_data
|
|
360
|
+
)
|
|
361
|
+
response = AsyncResponse.model_validate_json(raw_response.content)
|
|
362
|
+
|
|
363
|
+
if wait:
|
|
364
|
+
changes_id = response.change
|
|
365
|
+
previous_changes = None
|
|
366
|
+
while True:
|
|
367
|
+
try:
|
|
368
|
+
changes = await self._client.get_changes_by_id(changes_id)
|
|
369
|
+
except httpx.HTTPError:
|
|
370
|
+
if going_to_reload_daemon(previous_changes):
|
|
371
|
+
logger.debug("Waiting for daemon to reload")
|
|
372
|
+
await asyncio.sleep(0.1)
|
|
373
|
+
continue
|
|
374
|
+
raise
|
|
375
|
+
if changes.ready:
|
|
376
|
+
break
|
|
377
|
+
if isinstance(changes.result, BaseErrorResult):
|
|
378
|
+
raise SnapdAPIError(
|
|
379
|
+
f"Error in snap disable: {changes.result.message}"
|
|
380
|
+
)
|
|
381
|
+
if changes.result.err:
|
|
382
|
+
raise SnapdAPIError(f"Error in snap disable: {changes.result.err}")
|
|
383
|
+
await asyncio.sleep(0.1)
|
|
384
|
+
previous_changes = changes
|
|
385
|
+
return changes
|
|
386
|
+
|
|
387
|
+
return response
|
|
388
|
+
|
|
389
|
+
async def enable_snap(
|
|
390
|
+
self,
|
|
391
|
+
snap: str,
|
|
392
|
+
wait: bool = False,
|
|
393
|
+
) -> AsyncResponse | ChangesResponse:
|
|
394
|
+
"""
|
|
395
|
+
enables a snap package.
|
|
396
|
+
|
|
397
|
+
:param snap: The name of the snap package to enable.
|
|
398
|
+
:type snap: str
|
|
399
|
+
:param wait: Whether to wait for the enable operation to complete. Defaults to False.
|
|
400
|
+
:type wait: bool, optional
|
|
401
|
+
|
|
402
|
+
:returns: The response from the enable operation.
|
|
403
|
+
:rtype: AsyncResponse | ChangesResponse
|
|
404
|
+
|
|
405
|
+
:raises SnapdAPIError: If there is an error during the snap enable operation.
|
|
406
|
+
"""
|
|
407
|
+
request_data = {
|
|
408
|
+
"action": "enable",
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
raw_response: httpx.Response = await self._client.request(
|
|
412
|
+
"POST", f"{self.common_endpoint}/{snap}", json=request_data
|
|
413
|
+
)
|
|
414
|
+
response = AsyncResponse.model_validate_json(raw_response.content)
|
|
415
|
+
|
|
416
|
+
if wait:
|
|
417
|
+
changes_id = response.change
|
|
418
|
+
previous_changes = None
|
|
419
|
+
while True:
|
|
420
|
+
try:
|
|
421
|
+
changes = await self._client.get_changes_by_id(changes_id)
|
|
422
|
+
except httpx.HTTPError:
|
|
423
|
+
if going_to_reload_daemon(previous_changes):
|
|
424
|
+
logger.debug("Waiting for daemon to reload")
|
|
425
|
+
await asyncio.sleep(0.1)
|
|
426
|
+
continue
|
|
427
|
+
raise
|
|
428
|
+
if changes.ready:
|
|
429
|
+
break
|
|
430
|
+
if isinstance(changes.result, BaseErrorResult):
|
|
431
|
+
raise SnapdAPIError(
|
|
432
|
+
f"Error in snap enable: {changes.result.message}"
|
|
433
|
+
)
|
|
434
|
+
if changes.result.err:
|
|
435
|
+
raise SnapdAPIError(f"Error in snap enable: {changes.result.err}")
|
|
436
|
+
await asyncio.sleep(0.1)
|
|
437
|
+
previous_changes = changes
|
|
438
|
+
return changes
|
|
439
|
+
|
|
440
|
+
return response
|
|
441
|
+
|
|
442
|
+
async def get_snap_apps(
|
|
443
|
+
self,
|
|
444
|
+
snap: str,
|
|
445
|
+
services_only: bool = False,
|
|
446
|
+
) -> AppsResponse:
|
|
447
|
+
"""
|
|
448
|
+
Retrieves the applications associated with a specific snap.
|
|
449
|
+
|
|
450
|
+
:param snap: The name of the snap to retrieve applications for.
|
|
451
|
+
:type snap: str
|
|
452
|
+
:param services_only: Whether to retrieve only service applications.
|
|
453
|
+
:type services_only: bool
|
|
454
|
+
|
|
455
|
+
:returns: The response containing the list of applications for the specified snap.
|
|
456
|
+
:rtype: AppsResponse
|
|
457
|
+
"""
|
|
458
|
+
|
|
459
|
+
payload: dict[str, Any] = {"names": [snap]}
|
|
460
|
+
if services_only:
|
|
461
|
+
payload["select"] = "service"
|
|
462
|
+
|
|
463
|
+
response: httpx.Response = await self._client.request(
|
|
464
|
+
"GET", "apps", params=payload
|
|
465
|
+
)
|
|
466
|
+
if response.status_code != 200:
|
|
467
|
+
raise SnapdAPIError(f"Failed to retrieve apps for snap: {snap}")
|
|
468
|
+
return AppsResponse.model_validate_json(response.content)
|
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)
|
snap_python/schemas/snaps.py
CHANGED
|
@@ -32,7 +32,8 @@ class InstalledSnapFields(Revision):
|
|
|
32
32
|
validation_alias=AliasChoices("ignore-validation", "ignore_validation"),
|
|
33
33
|
serialization_alias="ignore-validation",
|
|
34
34
|
)
|
|
35
|
-
install_date: AwareDatetime = Field(
|
|
35
|
+
install_date: Optional[AwareDatetime] = Field(
|
|
36
|
+
default=None,
|
|
36
37
|
validation_alias=AliasChoices("install-date", "install_date"),
|
|
37
38
|
serialization_alias="install-date",
|
|
38
39
|
)
|
|
@@ -98,3 +99,26 @@ class InstalledSnapListResponse(BaseResponse):
|
|
|
98
99
|
|
|
99
100
|
def __len__(self):
|
|
100
101
|
return len(self.result)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class SnapAppInfo(BaseModel):
|
|
105
|
+
snap: Optional[str] = None
|
|
106
|
+
name: str
|
|
107
|
+
desktop_file: Optional[str] = Field(
|
|
108
|
+
default=None,
|
|
109
|
+
validation_alias=AliasChoices("desktop-file", "desktop_file"),
|
|
110
|
+
serialization_alias="desktop-file",
|
|
111
|
+
)
|
|
112
|
+
daemon: Optional[str] = None
|
|
113
|
+
enabled: Optional[bool] = None
|
|
114
|
+
active: Optional[bool] = None
|
|
115
|
+
common_id: Optional[str] = Field(
|
|
116
|
+
default=None,
|
|
117
|
+
validation_alias=AliasChoices("common-id", "common_id"),
|
|
118
|
+
serialization_alias="common-id",
|
|
119
|
+
)
|
|
120
|
+
activators: Optional[list[dict]] = None
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class AppsResponse(BaseResponse):
|
|
124
|
+
result: list[SnapAppInfo]
|
|
@@ -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
|
-
snap_python/components/snaps.py,sha256=
|
|
6
|
-
snap_python/components/store.py,sha256=
|
|
5
|
+
snap_python/components/snaps.py,sha256=NfZAgoNvsvf-aJa-ZZJoJxS-KrwrG6gBe1ScN2WM5To,18003
|
|
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
|
-
snap_python/schemas/snaps.py,sha256=
|
|
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
|