async-mega-py 2.2.0__tar.gz → 2.2.1__tar.gz

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.
Files changed (25) hide show
  1. {async_mega_py-2.2.0 → async_mega_py-2.2.1}/PKG-INFO +1 -1
  2. {async_mega_py-2.2.0 → async_mega_py-2.2.1}/pyproject.toml +1 -1
  3. async_mega_py-2.2.1/src/mega/__init__.py +8 -0
  4. {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/__main__.py +1 -2
  5. {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/api.py +30 -44
  6. {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/client.py +6 -3
  7. {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/transfer_it.py +7 -3
  8. {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/utils.py +2 -1
  9. async_mega_py-2.2.0/src/mega/__init__.py +0 -4
  10. {async_mega_py-2.2.0 → async_mega_py-2.2.1}/LICENSE +0 -0
  11. {async_mega_py-2.2.0 → async_mega_py-2.2.1}/README.md +0 -0
  12. {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/auth.py +0 -0
  13. {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/chunker.py +0 -0
  14. {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/core.py +0 -0
  15. {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/crypto.py +0 -0
  16. {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/data_structures.py +0 -0
  17. {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/download.py +0 -0
  18. {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/env.py +0 -0
  19. {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/errors.py +0 -0
  20. {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/filesystem.py +0 -0
  21. {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/progress/__init__.py +0 -0
  22. {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/progress/rich_progress.py +0 -0
  23. {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/py.typed +0 -0
  24. {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/upload.py +0 -0
  25. {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/vault.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: async-mega.py
3
- Version: 2.2.0
3
+ Version: 2.2.1
4
4
  Summary: Python library for the Mega.nz and Transfer.it API
5
5
  Keywords: api,downloader,mega,mega.nz,transfer.it
6
6
  Author: NTFSvolume
@@ -34,7 +34,7 @@ license = "Apache-2.0"
34
34
  license-files = ["LICENSE"]
35
35
  readme = "README.md"
36
36
  requires-python = ">=3.11"
37
- version = "2.2.0"
37
+ version = "2.2.1"
38
38
 
39
39
  [project.optional-dependencies]
40
40
  cli = [
@@ -0,0 +1,8 @@
1
+ import importlib.metadata
2
+ from contextvars import ContextVar
3
+
4
+ _package_name_ = "async-mega-py"
5
+ __version__ = importlib.metadata.version(_package_name_)
6
+
7
+ LOG_FILE_PROGRESS: ContextVar[bool] = ContextVar("LOG_FILE_PROGRESS", default=True)
8
+ LOG_HTTP_TRAFFIC: ContextVar[bool] = ContextVar("LOG_HTTP_TRAFFIC", default=False)
@@ -14,8 +14,7 @@ _ = install_rich_traceback(width=None, max_frames=2)
14
14
  import yarl
15
15
  from cyclopts import App, Parameter
16
16
 
17
- from mega import __version__, env
18
- from mega.api import LOG_HTTP_TRAFFIC
17
+ from mega import LOG_HTTP_TRAFFIC, __version__, env
19
18
  from mega.client import MegaNzClient
20
19
  from mega.transfer_it import TransferItClient
21
20
  from mega.utils import Site, setup_logger
@@ -7,15 +7,14 @@ import json
7
7
  import logging
8
8
  import uuid
9
9
  from collections.abc import Mapping, Sequence
10
- from contextvars import ContextVar
11
10
  from functools import wraps
12
- from typing import TYPE_CHECKING, Any, ClassVar, Literal, ParamSpec, Self, TypeVar
11
+ from typing import TYPE_CHECKING, Any, ClassVar, Generic, Literal, ParamSpec, Self, TypeVar
13
12
 
14
13
  import aiohttp
15
14
  import yarl
16
15
  from aiolimiter import AsyncLimiter
17
16
 
18
- from mega import __version__, _package_name_
17
+ from mega import LOG_HTTP_TRAFFIC, __version__, _package_name_
19
18
  from mega.crypto import generate_hashcash
20
19
  from mega.errors import RequestError, RetryRequestError
21
20
  from mega.utils import random_id, random_u32int
@@ -27,8 +26,6 @@ if TYPE_CHECKING:
27
26
  _R = TypeVar("_R")
28
27
 
29
28
 
30
- LOG_HTTP_TRAFFIC: ContextVar[bool] = ContextVar("LOG_HTTP_TRAFFIC", default=False)
31
-
32
29
  logger = logging.getLogger(__name__)
33
30
 
34
31
 
@@ -66,27 +63,23 @@ def retry(
66
63
  return wrapper
67
64
 
68
65
 
69
- @dataclasses.dataclass(slots=True, weakref_slot=True, init=False)
66
+ @dataclasses.dataclass(slots=True, weakref_slot=True)
70
67
  class MegaAPI:
71
- session_id: str | None
72
- _request_id: int
73
- _client_id: str
74
-
75
- __session: aiohttp.ClientSession | None
76
- _auto_close_session: bool
77
- _rate_limiter: AsyncLimiter
78
-
79
- _entrypoint: ClassVar[yarl.URL] = yarl.URL("https://g.api.mega.co.nz/cs")
80
- user_agent: str
81
-
82
- def __init__(self, session: aiohttp.ClientSession | None = None, user_agent: str | None = None) -> None:
83
- self.session_id = None
84
- self._request_id = random_u32int()
85
- self._client_id = random_id(10)
86
- self.__session = session
87
- self._auto_close_session = session is None
88
- self._rate_limiter = AsyncLimiter(100, 60)
89
- self.user_agent = user_agent or f"{_package_name_}/{__version__}"
68
+ _session: aiohttp.ClientSession | None = None
69
+
70
+ user_agent: str = f"{_package_name_}/{__version__}"
71
+
72
+ session_id: str | None = dataclasses.field(init=False, default=None)
73
+ _request_id: int = dataclasses.field(init=False, default_factory=random_u32int)
74
+ _client_id: str = dataclasses.field(init=False, default_factory=lambda: random_id(10))
75
+
76
+ _auto_close_session: bool = dataclasses.field(init=False)
77
+ _rate_limiter: AsyncLimiter = dataclasses.field(init=False, default_factory=lambda: AsyncLimiter(100, 60))
78
+
79
+ _entrypoint: ClassVar[yarl.URL] = dataclasses.field(init=False, default=yarl.URL("https://g.api.mega.co.nz/cs"))
80
+
81
+ def __post_init__(self) -> None:
82
+ self._auto_close_session = self._session is None
90
83
 
91
84
  @property
92
85
  def entrypoint(self) -> yarl.URL:
@@ -96,22 +89,12 @@ class MegaAPI:
96
89
  def client_id(self) -> str:
97
90
  return self._client_id
98
91
 
99
- @property
100
- def request_id(self) -> int:
101
- return self._request_id
102
-
103
- @property
104
- def _session(self) -> aiohttp.ClientSession:
105
- if self.__session is None:
106
- self.__session = aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(sock_connect=160, sock_read=60))
107
- return self.__session
108
-
109
92
  def __repr__(self) -> str:
110
93
  return f"<{type(self).__name__}>(session_id={self.session_id!r}, client_id={self.client_id!r}, auto_close_session={self._auto_close_session!r})"
111
94
 
112
95
  async def aclose(self) -> None:
113
- if self._auto_close_session and self.__session:
114
- await self.__session.close()
96
+ if self._auto_close_session and self._session:
97
+ await self._session.close()
115
98
 
116
99
  async def __enter__(self) -> Self:
117
100
  return self
@@ -175,7 +158,7 @@ class MegaAPI:
175
158
  headers: Mapping[str, str] | None = None,
176
159
  **kwargs: Any,
177
160
  ) -> AsyncGenerator[aiohttp.ClientResponse]:
178
- kwargs["headers"] = {"User-Agent": self.user_agent} | (headers or {})
161
+ kwargs["headers"] = {"User-Agent": self.user_agent, **(headers or {})}
179
162
  request_id = str(uuid.uuid4())
180
163
  if LOG_HTTP_TRAFFIC.get():
181
164
  logger.debug(
@@ -187,6 +170,9 @@ class MegaAPI:
187
170
  )
188
171
 
189
172
  resp = None
173
+ if self._session is None:
174
+ self._session = aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(sock_connect=160, sock_read=60))
175
+
190
176
  try:
191
177
  async with self._rate_limiter, self._session.request(method, url, **kwargs) as resp:
192
178
  yield resp
@@ -244,19 +230,19 @@ class _LazyResponseLog:
244
230
  return str(self.__json__())
245
231
 
246
232
 
247
- class APIContextManager:
248
- __slots__ = ("_api",)
233
+ _API_T = TypeVar("_API_T", bound=MegaAPI, covariant=True)
249
234
 
250
- def __init__(self, session: aiohttp.ClientSession | None = None, *, user_agent: str | None = None) -> None:
251
- self._api: MegaAPI = MegaAPI(session, user_agent)
235
+
236
+ class APIContextManager(Generic[_API_T]):
237
+ __slots__ = ("_api",)
252
238
 
253
239
  async def __aenter__(self) -> Self:
254
240
  return self
255
241
 
256
242
  async def __aexit__(self, *_) -> None:
257
- await self.close()
243
+ await self.aclose()
258
244
 
259
245
  async def aclose(self) -> None:
260
- await self._api.close()
246
+ await self._api.aclose()
261
247
 
262
248
  close = aclose
@@ -7,7 +7,7 @@ from pathlib import Path, PurePosixPath
7
7
  from typing import TYPE_CHECKING
8
8
 
9
9
  from mega import progress
10
- from mega.api import APIContextManager
10
+ from mega.api import APIContextManager, MegaAPI
11
11
  from mega.core import MegaCore
12
12
  from mega.crypto import a32_to_base64, b64_to_a32, b64_url_encode, encrypt_attr, encrypt_key
13
13
  from mega.data_structures import (
@@ -38,13 +38,16 @@ logger = logging.getLogger(__name__)
38
38
  _DOMAIN = Site.MEGA.value
39
39
 
40
40
 
41
- class MegaNzClient(APIContextManager):
41
+ class MegaNzClient(APIContextManager[MegaAPI]):
42
42
  """Interface with all the public methods of the API"""
43
43
 
44
44
  __slots__ = ("_core",)
45
45
 
46
46
  def __init__(self, session: aiohttp.ClientSession | None = None, *, user_agent: str | None = None) -> None:
47
- super().__init__(session, user_agent=user_agent)
47
+ self._api = MegaAPI(session)
48
+ if user_agent:
49
+ self._api.user_agent = user_agent
50
+
48
51
  self._core: MegaCore = MegaCore(self._api)
49
52
  if hasattr(sys, "ps1"):
50
53
  setup_logger(logging.DEBUG)
@@ -45,9 +45,13 @@ class TransferItAPI(MegaAPI):
45
45
  return await super().post(json, params)
46
46
 
47
47
 
48
- class TransferItClient(APIContextManager):
49
- def __init__(self, session: aiohttp.ClientSession | None = None, *, user_agent: str | None = None) -> None: # pyright: ignore[reportMissingSuperCall]
50
- self._api = TransferItAPI(session, user_agent=user_agent)
48
+ class TransferItClient(APIContextManager[TransferItAPI]):
49
+ __slots__ = ()
50
+
51
+ def __init__(self, session: aiohttp.ClientSession | None = None, *, user_agent: str | None = None) -> None:
52
+ self._api = TransferItAPI(session)
53
+ if user_agent:
54
+ self._api.user_agent = user_agent
51
55
 
52
56
  @property
53
57
  def progress_bar(self) -> _GeneratorContextManager[None, None, None]:
@@ -14,6 +14,7 @@ from typing import TYPE_CHECKING, Literal, TypeVar, overload
14
14
  import aiohttp
15
15
  import yarl
16
16
 
17
+ from mega import LOG_FILE_PROGRESS
17
18
  from mega.errors import ValidationError
18
19
 
19
20
  if TYPE_CHECKING:
@@ -63,7 +64,7 @@ def setup_logger(level: int = logging.INFO) -> None:
63
64
 
64
65
 
65
66
  def progress_logger(output_path: Path, file_size: int, *, download: bool) -> Callable[[float], None]:
66
- if not logger.isEnabledFor(10):
67
+ if not (LOG_FILE_PROGRESS.get() and logger.isEnabledFor(logging.DEBUG)):
67
68
  return lambda _: None
68
69
 
69
70
  from mega.data_structures import ByteSize
@@ -1,4 +0,0 @@
1
- import importlib.metadata
2
-
3
- _package_name_ = "async-mega-py"
4
- __version__ = importlib.metadata.version(_package_name_)
File without changes
File without changes