mongojet 0.2.3__cp313-none-win32.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.
- mongojet/__init__.py +58 -0
- mongojet/_client.py +99 -0
- mongojet/_codec.py +104 -0
- mongojet/_collection.py +639 -0
- mongojet/_cursor.py +47 -0
- mongojet/_database.py +205 -0
- mongojet/_gridfs.py +50 -0
- mongojet/_helpers.py +118 -0
- mongojet/_session.py +49 -0
- mongojet/_types.py +473 -0
- mongojet/mongojet.cp313-win32.pyd +0 -0
- mongojet-0.2.3.dist-info/METADATA +202 -0
- mongojet-0.2.3.dist-info/RECORD +15 -0
- mongojet-0.2.3.dist-info/WHEEL +4 -0
- mongojet-0.2.3.dist-info/licenses/LICENSE.txt +201 -0
mongojet/__init__.py
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
from ._client import create_client, Client
|
|
2
|
+
from ._database import Database
|
|
3
|
+
from ._collection import Collection
|
|
4
|
+
from ._gridfs import GridfsBucket
|
|
5
|
+
|
|
6
|
+
from .mongojet import (
|
|
7
|
+
PyMongoError,
|
|
8
|
+
OperationFailure,
|
|
9
|
+
WriteError,
|
|
10
|
+
WriteConcernError,
|
|
11
|
+
DuplicateKeyError,
|
|
12
|
+
BsonSerializationError,
|
|
13
|
+
BsonDeserializationError,
|
|
14
|
+
ConnectionFailure,
|
|
15
|
+
ServerSelectionError,
|
|
16
|
+
ConfigurationError,
|
|
17
|
+
GridFSError,
|
|
18
|
+
NoFile,
|
|
19
|
+
FileExists,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
from ._types import (
|
|
23
|
+
DatabaseOptions,
|
|
24
|
+
CollectionOptions,
|
|
25
|
+
ReadConcern,
|
|
26
|
+
WriteConcern,
|
|
27
|
+
ReadPreference,
|
|
28
|
+
IndexModel,
|
|
29
|
+
IndexModelDef,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
__all__ = (
|
|
33
|
+
'create_client',
|
|
34
|
+
'Client',
|
|
35
|
+
'Database',
|
|
36
|
+
'Collection',
|
|
37
|
+
'PyMongoError',
|
|
38
|
+
'OperationFailure',
|
|
39
|
+
'WriteError',
|
|
40
|
+
'WriteConcernError',
|
|
41
|
+
'DuplicateKeyError',
|
|
42
|
+
'BsonSerializationError',
|
|
43
|
+
'BsonDeserializationError',
|
|
44
|
+
'ConnectionFailure',
|
|
45
|
+
'ServerSelectionError',
|
|
46
|
+
'ConfigurationError',
|
|
47
|
+
'DatabaseOptions',
|
|
48
|
+
'CollectionOptions',
|
|
49
|
+
'ReadConcern',
|
|
50
|
+
'WriteConcern',
|
|
51
|
+
'ReadPreference',
|
|
52
|
+
'IndexModel',
|
|
53
|
+
'IndexModelDef',
|
|
54
|
+
'GridfsBucket',
|
|
55
|
+
'GridFSError',
|
|
56
|
+
'NoFile',
|
|
57
|
+
'FileExists',
|
|
58
|
+
)
|
mongojet/_client.py
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
from bson import CodecOptions
|
|
4
|
+
|
|
5
|
+
from .mongojet import core_create_client # noqa
|
|
6
|
+
|
|
7
|
+
try:
|
|
8
|
+
from typing import Unpack
|
|
9
|
+
except ImportError:
|
|
10
|
+
from typing_extensions import Unpack
|
|
11
|
+
|
|
12
|
+
from ._database import Database
|
|
13
|
+
from ._types import DatabaseOptions, SessionOptions
|
|
14
|
+
from ._codec import Codec
|
|
15
|
+
from ._session import ClientSession
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
async def create_client(url: str, tz_aware: bool = True) -> 'Client':
|
|
19
|
+
core_client = await core_create_client(url=url)
|
|
20
|
+
return Client(core_client, codec_options=CodecOptions(tz_aware=tz_aware))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class Client:
|
|
24
|
+
def __init__(self, core_client, codec_options: CodecOptions) -> None:
|
|
25
|
+
self._codec_options = codec_options
|
|
26
|
+
self._codec = Codec(options=codec_options)
|
|
27
|
+
self._core_client = core_client
|
|
28
|
+
|
|
29
|
+
def get_default_database(
|
|
30
|
+
self,
|
|
31
|
+
codec_options: Optional[CodecOptions] = None,
|
|
32
|
+
**options: Unpack[DatabaseOptions],
|
|
33
|
+
) -> Database:
|
|
34
|
+
default_database = self._core_client.default_database_name
|
|
35
|
+
if default_database is None:
|
|
36
|
+
raise ValueError('No default database name defined or provided.')
|
|
37
|
+
|
|
38
|
+
if options:
|
|
39
|
+
core_database = self._core_client.get_database_with_options(
|
|
40
|
+
default_database,
|
|
41
|
+
self._codec.encode(options),
|
|
42
|
+
)
|
|
43
|
+
else:
|
|
44
|
+
core_database = self._core_client.get_default_database()
|
|
45
|
+
|
|
46
|
+
return Database(
|
|
47
|
+
core_database,
|
|
48
|
+
codec_options=codec_options or self._codec_options,
|
|
49
|
+
client=self,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
def get_database(
|
|
53
|
+
self,
|
|
54
|
+
name: Optional[str] = None,
|
|
55
|
+
codec_options: Optional[CodecOptions] = None,
|
|
56
|
+
**options: Unpack[DatabaseOptions],
|
|
57
|
+
) -> Database:
|
|
58
|
+
if name is None:
|
|
59
|
+
return self.get_default_database(codec_options=codec_options, **options)
|
|
60
|
+
|
|
61
|
+
if options:
|
|
62
|
+
core_database = self._core_client.get_database_with_options(
|
|
63
|
+
name,
|
|
64
|
+
self._codec.encode(options),
|
|
65
|
+
)
|
|
66
|
+
else:
|
|
67
|
+
core_database = self._core_client.get_database(name)
|
|
68
|
+
|
|
69
|
+
return Database(
|
|
70
|
+
core_database,
|
|
71
|
+
codec_options=codec_options or self._codec_options,
|
|
72
|
+
client=self,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
async def start_session(self, **options: Unpack[SessionOptions]) -> ClientSession:
|
|
76
|
+
core_session = await self._core_client.start_session(
|
|
77
|
+
self._codec.encode(options),
|
|
78
|
+
)
|
|
79
|
+
return ClientSession(
|
|
80
|
+
core_session,
|
|
81
|
+
codec_options=self._codec_options,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
async def close(self, immediate=True):
|
|
85
|
+
if immediate:
|
|
86
|
+
await self._core_client.shutdown_immediate()
|
|
87
|
+
else:
|
|
88
|
+
await self._core_client.shutdown()
|
|
89
|
+
|
|
90
|
+
def __getitem__(self, name: str) -> Database:
|
|
91
|
+
return self.get_database(name)
|
|
92
|
+
|
|
93
|
+
def __getattr__(self, name: str) -> Database:
|
|
94
|
+
if name.startswith("_"): # pragma: no cover
|
|
95
|
+
raise AttributeError(
|
|
96
|
+
f"Client has no attribute {name!r}. To access the {name}"
|
|
97
|
+
f" database, use client[{name!r}]."
|
|
98
|
+
)
|
|
99
|
+
return self.__getitem__(name)
|
mongojet/_codec.py
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from typing import Any, Dict, Optional, Mapping
|
|
3
|
+
|
|
4
|
+
import bson
|
|
5
|
+
from bson import CodecOptions
|
|
6
|
+
|
|
7
|
+
DEFAULT_CODEC_OPTIONS = CodecOptions(tz_aware=True)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Codec:
|
|
11
|
+
def __init__(self, options: CodecOptions):
|
|
12
|
+
self._options = options
|
|
13
|
+
|
|
14
|
+
def encode(
|
|
15
|
+
self,
|
|
16
|
+
doc: Optional[Mapping[str, Any]],
|
|
17
|
+
optional=True,
|
|
18
|
+
) -> Optional[bytes]:
|
|
19
|
+
if doc is None:
|
|
20
|
+
return None
|
|
21
|
+
|
|
22
|
+
# if optional and doc=={}
|
|
23
|
+
if optional and not doc:
|
|
24
|
+
return None
|
|
25
|
+
|
|
26
|
+
return bson.BSON.encode(doc, codec_options=self._options)
|
|
27
|
+
|
|
28
|
+
def decode(
|
|
29
|
+
self,
|
|
30
|
+
data: Optional[bytes],
|
|
31
|
+
) -> Optional[Dict[str, Any]]:
|
|
32
|
+
if data is None:
|
|
33
|
+
return None
|
|
34
|
+
|
|
35
|
+
doc = bson.BSON(data).decode(codec_options=self._options)
|
|
36
|
+
|
|
37
|
+
return doc
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def encode(
|
|
41
|
+
doc: Optional[Mapping[str, Any]],
|
|
42
|
+
codec_options=None,
|
|
43
|
+
amend_keys=False,
|
|
44
|
+
optional=True,
|
|
45
|
+
) -> Optional[bytes]:
|
|
46
|
+
"""
|
|
47
|
+
DEPRECATED
|
|
48
|
+
"""
|
|
49
|
+
# ???
|
|
50
|
+
# if not doc:
|
|
51
|
+
# return None
|
|
52
|
+
|
|
53
|
+
if doc is None:
|
|
54
|
+
return None
|
|
55
|
+
|
|
56
|
+
# if optional and doc=={}
|
|
57
|
+
if optional and not doc:
|
|
58
|
+
return None
|
|
59
|
+
|
|
60
|
+
if amend_keys:
|
|
61
|
+
doc = dict_keys_to_camel_case(doc)
|
|
62
|
+
|
|
63
|
+
return bson.BSON.encode(
|
|
64
|
+
doc,
|
|
65
|
+
codec_options=codec_options or DEFAULT_CODEC_OPTIONS,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def decode(
|
|
70
|
+
data: Optional[bytes],
|
|
71
|
+
codec_options=None,
|
|
72
|
+
amend_keys=False,
|
|
73
|
+
) -> Optional[Dict[str, Any]]:
|
|
74
|
+
if data is None:
|
|
75
|
+
return None
|
|
76
|
+
|
|
77
|
+
doc = bson.BSON(data).decode(
|
|
78
|
+
codec_options=codec_options or DEFAULT_CODEC_OPTIONS,
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
if amend_keys:
|
|
82
|
+
doc = dict_keys_to_snake_case(doc)
|
|
83
|
+
|
|
84
|
+
return doc
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def to_camel_case(s: str) -> str:
|
|
88
|
+
s = ''.join(word.capitalize() for word in s.split('_'))
|
|
89
|
+
return s[:1].lower() + s[1:]
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
re_caps = re.compile(r'(?<!^)(?=[A-Z])')
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def to_snake_case(s: str) -> str:
|
|
96
|
+
return re_caps.sub('_', s).lower()
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def dict_keys_to_camel_case(d: Mapping[str, Any]) -> dict:
|
|
100
|
+
return {to_camel_case(k): v for k, v in d.items()}
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def dict_keys_to_snake_case(d: Mapping[str, Any]) -> dict:
|
|
104
|
+
return {to_snake_case(k): v for k, v in d.items()}
|