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.
- {async_mega_py-2.2.0 → async_mega_py-2.2.1}/PKG-INFO +1 -1
- {async_mega_py-2.2.0 → async_mega_py-2.2.1}/pyproject.toml +1 -1
- async_mega_py-2.2.1/src/mega/__init__.py +8 -0
- {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/__main__.py +1 -2
- {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/api.py +30 -44
- {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/client.py +6 -3
- {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/transfer_it.py +7 -3
- {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/utils.py +2 -1
- async_mega_py-2.2.0/src/mega/__init__.py +0 -4
- {async_mega_py-2.2.0 → async_mega_py-2.2.1}/LICENSE +0 -0
- {async_mega_py-2.2.0 → async_mega_py-2.2.1}/README.md +0 -0
- {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/auth.py +0 -0
- {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/chunker.py +0 -0
- {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/core.py +0 -0
- {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/crypto.py +0 -0
- {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/data_structures.py +0 -0
- {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/download.py +0 -0
- {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/env.py +0 -0
- {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/errors.py +0 -0
- {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/filesystem.py +0 -0
- {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/progress/__init__.py +0 -0
- {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/progress/rich_progress.py +0 -0
- {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/py.typed +0 -0
- {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/upload.py +0 -0
- {async_mega_py-2.2.0 → async_mega_py-2.2.1}/src/mega/vault.py +0 -0
|
@@ -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
|
|
66
|
+
@dataclasses.dataclass(slots=True, weakref_slot=True)
|
|
70
67
|
class MegaAPI:
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
self.
|
|
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.
|
|
114
|
-
await self.
|
|
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
|
|
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
|
-
|
|
248
|
-
__slots__ = ("_api",)
|
|
233
|
+
_API_T = TypeVar("_API_T", bound=MegaAPI, covariant=True)
|
|
249
234
|
|
|
250
|
-
|
|
251
|
-
|
|
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.
|
|
243
|
+
await self.aclose()
|
|
258
244
|
|
|
259
245
|
async def aclose(self) -> None:
|
|
260
|
-
await self._api.
|
|
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
|
-
|
|
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
|
-
|
|
50
|
-
|
|
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(
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|