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 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()}