snap-python 0.1.4__py3-none-any.whl → 0.1.5__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.
@@ -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)
@@ -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,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: snap-python
3
- Version: 0.1.4
3
+ Version: 0.1.5
4
4
  Summary: Interact with snapd and snapstore(s) from Python
5
5
  License: MIT
6
6
  Author: Alexander Lukens
@@ -2,12 +2,12 @@ snap_python/__init__.py,sha256=gV43Nempk7HFKD1UCvxUhmP9x6dBmPjotcITREr81Vg,222
2
2
  snap_python/client.py,sha256=rZAfzcQNhdtTyjQml1N-9-nAianFyEwOaI4H_0FMaFE,6612
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=FQ362L83jmhu3MLKszOU1w5jGP8l5-WNBlUTLnR6IW8,13176
5
+ snap_python/components/snaps.py,sha256=NfZAgoNvsvf-aJa-ZZJoJxS-KrwrG6gBe1ScN2WM5To,18003
6
6
  snap_python/components/store.py,sha256=lxN-6cVslAeen-yfZqMPQ2iNvDUNBCClWIvLn5PZi2Q,16971
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=cO0UwghFZwfIlJtAjYDdNgfLKwU7953B9bgolpXcUL0,2980
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
13
  snap_python/schemas/store/info.py,sha256=K2y1NOrSLZEszGJur5L0W_1ap4P038cK4ThSjLcyQLA,4407
@@ -19,7 +19,7 @@ snap_python/schemas/store/refresh.py,sha256=HAlt-rKfy7vmZSCujMXtW9HHXlVYbHGFwy_B
19
19
  snap_python/schemas/store/search.py,sha256=4ghZb8xY6IESxZuAvzSjM9RaEwZAH3zjiC06zLc0zvU,4561
20
20
  snap_python/scrape.py,sha256=ZDJAROp8jwossaAA78gBFTKQzrfnO11RgyyOZqevNd0,4576
21
21
  snap_python/utils.py,sha256=cmUooPg5DzNL197Xxvu7LGD4Gwk3xxsT68wbVytRtV0,1240
22
- snap_python-0.1.4.dist-info/LICENSE,sha256=lYXNZszxC_l2rlBvrHYs-esDegxWh8MKtjrdxA24uOk,1072
23
- snap_python-0.1.4.dist-info/METADATA,sha256=jT6zFn5qHbXNkM8oS4fZQbdGqgFytApIIL85IydP_6M,1883
24
- snap_python-0.1.4.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
25
- snap_python-0.1.4.dist-info/RECORD,,
22
+ snap_python-0.1.5.dist-info/LICENSE,sha256=lYXNZszxC_l2rlBvrHYs-esDegxWh8MKtjrdxA24uOk,1072
23
+ snap_python-0.1.5.dist-info/METADATA,sha256=0JlTOj5NPMtPMKnOmNriwFlE-p99r39erih9VLo4eQw,1883
24
+ snap_python-0.1.5.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
25
+ snap_python-0.1.5.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.1.2
2
+ Generator: poetry-core 2.1.3
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any