refscan 0.2.3__tar.gz → 0.2.4__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.
- {refscan-0.2.3 → refscan-0.2.4}/PKG-INFO +1 -1
- {refscan-0.2.3 → refscan-0.2.4}/pyproject.toml +1 -1
- {refscan-0.2.3 → refscan-0.2.4}/refscan/lib/Finder.py +12 -2
- {refscan-0.2.3 → refscan-0.2.4}/refscan/scanner.py +10 -2
- {refscan-0.2.3 → refscan-0.2.4}/LICENSE +0 -0
- {refscan-0.2.3 → refscan-0.2.4}/README.md +0 -0
- {refscan-0.2.3 → refscan-0.2.4}/refscan/__init__.py +0 -0
- {refscan-0.2.3 → refscan-0.2.4}/refscan/cli/cli.py +0 -0
- {refscan-0.2.3 → refscan-0.2.4}/refscan/cli/graph.py +0 -0
- {refscan-0.2.3 → refscan-0.2.4}/refscan/cli/scan.py +0 -0
- {refscan-0.2.3 → refscan-0.2.4}/refscan/cli/version.py +0 -0
- {refscan-0.2.3 → refscan-0.2.4}/refscan/grapher.py +0 -0
- {refscan-0.2.3 → refscan-0.2.4}/refscan/lib/Reference.py +0 -0
- {refscan-0.2.3 → refscan-0.2.4}/refscan/lib/ReferenceList.py +0 -0
- {refscan-0.2.3 → refscan-0.2.4}/refscan/lib/Violation.py +0 -0
- {refscan-0.2.3 → refscan-0.2.4}/refscan/lib/ViolationList.py +0 -0
- {refscan-0.2.3 → refscan-0.2.4}/refscan/lib/constants.py +0 -0
- {refscan-0.2.3 → refscan-0.2.4}/refscan/lib/helpers.py +0 -0
- {refscan-0.2.3 → refscan-0.2.4}/refscan/templates/graph.template.html +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: refscan
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: Command-line program that scans the NMDC MongoDB database for referential integrity violations
|
|
5
5
|
Keywords: mongodb,mongo,relationships,reference,database,data,referential integrity,scan
|
|
6
6
|
Requires-Python: >=3.9,<4.0
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from typing import List, Optional, Dict
|
|
2
2
|
|
|
3
3
|
from pymongo.database import Database
|
|
4
|
+
from pymongo.client_session import ClientSession
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
class Finder:
|
|
@@ -10,6 +11,9 @@ class Finder:
|
|
|
10
11
|
"""
|
|
11
12
|
|
|
12
13
|
def __init__(self, database: Database):
|
|
14
|
+
r"""
|
|
15
|
+
Initializes an instance of the `Finder` class. The instance is bound to the specified MongoDB database.
|
|
16
|
+
"""
|
|
13
17
|
self.db = database
|
|
14
18
|
|
|
15
19
|
# Initialize our cache of names of collections we most recently found referenced document `id`s in.
|
|
@@ -114,15 +118,20 @@ class Finder:
|
|
|
114
118
|
return self.cached_id_presence_by_collection[collection_name][document_id]
|
|
115
119
|
|
|
116
120
|
def check_whether_document_having_id_exists_among_collections(
|
|
117
|
-
self, document_id: str, collection_names: List[str]
|
|
121
|
+
self, document_id: str, collection_names: List[str], client_session: ClientSession = None
|
|
118
122
|
) -> Optional[str]:
|
|
119
123
|
r"""
|
|
120
124
|
Checks whether any document in any of the specified collections has the specified value in its `id` field.
|
|
121
125
|
Returns the name of the first collection, if any, containing such a document. If none of the collections
|
|
122
126
|
contain such a document, the function returns `None`.
|
|
123
127
|
|
|
128
|
+
If a `pymongo.client_session.ClientSession` is specified, this function will access the database within
|
|
129
|
+
the context of that session. If a transaction is pending on that session, this feature can be used
|
|
130
|
+
to check whether the specified document _would_ exist if that transaction were to be committed.
|
|
131
|
+
|
|
124
132
|
References:
|
|
125
133
|
- https://pymongo.readthedocs.io/en/stable/api/pymongo/collection.html#pymongo.collection.Collection.find_one
|
|
134
|
+
- https://pymongo.readthedocs.io/en/stable/api/pymongo/client_session.html#transactions
|
|
126
135
|
"""
|
|
127
136
|
|
|
128
137
|
# Initialize the name of the containing collection to `None`.
|
|
@@ -155,7 +164,8 @@ class Finder:
|
|
|
155
164
|
# If we find it in the collection in the database, record the collection name, update both (a) the cache
|
|
156
165
|
# of which documents we have found in which collections, and (b) the cache of names of collections where
|
|
157
166
|
# a referenced document was recently found, and skip searching additional collections.
|
|
158
|
-
|
|
167
|
+
collection = self.db.get_collection(collection_name)
|
|
168
|
+
if collection.find_one(query_filter, projection=["_id"], session=client_session) is not None:
|
|
159
169
|
name_of_collection_containing_target_document = collection_name
|
|
160
170
|
|
|
161
171
|
# Record that a document having this `id` is _present_ in this collection.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from typing import List, Optional, Dict
|
|
2
2
|
|
|
3
3
|
from pymongo.database import Database
|
|
4
|
+
from pymongo.client_session import ClientSession
|
|
4
5
|
from rich.console import Console
|
|
5
6
|
from linkml_runtime import SchemaView
|
|
6
7
|
|
|
@@ -24,6 +25,7 @@ def scan_outgoing_references(
|
|
|
24
25
|
finder: Finder,
|
|
25
26
|
collection_names: List[str],
|
|
26
27
|
source_collection_name: str,
|
|
28
|
+
client_session: ClientSession = None,
|
|
27
29
|
user_wants_to_locate_misplaced_documents: bool = False,
|
|
28
30
|
) -> ViolationList:
|
|
29
31
|
r"""
|
|
@@ -40,6 +42,10 @@ def scan_outgoing_references(
|
|
|
40
42
|
all the legal collections
|
|
41
43
|
:param source_collection_name: Name of collection in which source document resides (this is included in the
|
|
42
44
|
violation report in an attempt to facilitate investigation of violations)
|
|
45
|
+
:param client_session: A `pymongo.client_session.ClientSession` instance that, if specified, will be used when
|
|
46
|
+
searching for referenced documents. If a transaction happens to be pending on that session,
|
|
47
|
+
the scan will effectively happen on the database as it _would_ exist if that transaction
|
|
48
|
+
were to be committed.
|
|
43
49
|
:param collection_names: List of collection names that are described by the schema
|
|
44
50
|
"""
|
|
45
51
|
|
|
@@ -77,7 +83,7 @@ def scan_outgoing_references(
|
|
|
77
83
|
for target_id in target_ids:
|
|
78
84
|
name_of_collection_containing_target_document = (
|
|
79
85
|
finder.check_whether_document_having_id_exists_among_collections(
|
|
80
|
-
collection_names=target_collection_names, document_id=target_id
|
|
86
|
+
collection_names=target_collection_names, document_id=target_id, client_session=client_session
|
|
81
87
|
)
|
|
82
88
|
)
|
|
83
89
|
if name_of_collection_containing_target_document is None:
|
|
@@ -88,7 +94,9 @@ def scan_outgoing_references(
|
|
|
88
94
|
names_of_ineligible_collections = list(set(collection_names) - set(target_collection_names))
|
|
89
95
|
name_of_collection_containing_target_document = (
|
|
90
96
|
finder.check_whether_document_having_id_exists_among_collections(
|
|
91
|
-
collection_names=names_of_ineligible_collections,
|
|
97
|
+
collection_names=names_of_ineligible_collections,
|
|
98
|
+
document_id=target_id,
|
|
99
|
+
client_session=client_session,
|
|
92
100
|
)
|
|
93
101
|
)
|
|
94
102
|
|
|
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
|