refscan 0.4.3__tar.gz → 0.5.0__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.
@@ -1,3 +1,18 @@
1
+ Metadata-Version: 2.3
2
+ Name: refscan
3
+ Version: 0.5.0
4
+ Summary: Command-line program that scans the NMDC MongoDB database for referential integrity violations
5
+ Keywords: mongodb,mongo,relationships,reference,database,data,referential integrity,scan
6
+ Requires-Dist: linkml-runtime>=1.12.1,<2
7
+ Requires-Dist: pymongo>=4.18.3,<5
8
+ Requires-Dist: rich>=13.7.1,<14
9
+ Requires-Dist: typer>=0.29.1,<0.30
10
+ Requires-Python: >=3.10, <4.0
11
+ Project-URL: Documentation, https://github.com/microbiomedata/refscan
12
+ Project-URL: Homepage, https://github.com/microbiomedata/refscan
13
+ Project-URL: Repository, https://github.com/microbiomedata/refscan
14
+ Description-Content-Type: text/markdown
15
+
1
16
  # refscan
2
17
 
3
18
  `refscan` is a command-line tool people can use to **scan** the [NMDC](https://microbiomedata.org/) MongoDB database
@@ -59,7 +74,9 @@ whose definition `refscan` then uses to determine _which fields_ of that documen
59
74
 
60
75
  ## Usage
61
76
 
62
- ### Install
77
+ ### Command-line application
78
+
79
+ #### Install
63
80
 
64
81
  Assuming you have `pipx` installed, you can install the tool by running the following command:
65
82
 
@@ -72,7 +89,7 @@ pipx install refscan
72
89
  > Python scripts that are hosted on PyPI.
73
90
  > You can [install `pipx`](https://pipx.pypa.io/stable/installation/) by running `$ python -m pip install pipx`.
74
91
 
75
- ### Run
92
+ #### Run
76
93
 
77
94
  Once installed, you can display the tool's `--help` snippet by running:
78
95
 
@@ -99,7 +116,7 @@ At the time of this writing, the tool's `--help` snippet is:
99
116
 
100
117
  Each command has its own `--help` snippet.
101
118
 
102
- #### The `scan` command
119
+ ##### The `scan` command
103
120
 
104
121
  At the time of this writing, the `--help` snippet for the `scan` command is:
105
122
 
@@ -148,7 +165,7 @@ At the time of this writing, the `--help` snippet for the `scan` command is:
148
165
 
149
166
  <!-- Note: The above snippet was captured from a terminal window whose width was 90 characters. -->
150
167
 
151
- ##### The MongoDB connection string (`--mongo-uri`)
168
+ ###### The MongoDB connection string (`--mongo-uri`)
152
169
 
153
170
  As documented in the `--help` snippet above, you can provide the MongoDB connection string to the tool via either
154
171
  (a) the `--mongo-uri` option; or (b) an environment variable named `MONGO_URI`. The latter can come in handy
@@ -161,7 +178,7 @@ Here's how you could create that environment variable:
161
178
  export MONGO_URI='mongodb://username:password@localhost:27017'
162
179
  ```
163
180
 
164
- ##### The schema (`--schema`)
181
+ ###### The schema (`--schema`)
165
182
 
166
183
  As documented in the `--help` snippet above, you can provide the path to a YAML-formatted LinkML schema file to the tool
167
184
  via the `--schema` option.
@@ -195,7 +212,7 @@ curl -o schema.yaml https://raw.githubusercontent.com/microbiomedata/nmdc-schema
195
212
  ---
196
213
  </details>
197
214
 
198
- ##### Output
215
+ ###### Output
199
216
 
200
217
  While `refscan` is running, it will display console output indicating what it's currently doing.
201
218
 
@@ -204,7 +221,7 @@ While `refscan` is running, it will display console output indicating what it's
204
221
  Once the scan is complete, the reference report (TSV file) and violation report (TSV file) will be available
205
222
  in the current directory (or in custom directories, if any were specified via CLI options).
206
223
 
207
- #### The `graph` command
224
+ ##### The `graph` command
208
225
 
209
226
  At the time of this writing, the `--help` snippet for the `graph` command is:
210
227
 
@@ -231,7 +248,7 @@ At the time of this writing, the `--help` snippet for the `graph` command is:
231
248
 
232
249
  <!-- Note: The above snippet was captured from a terminal window whose width was 90 characters. -->
233
250
 
234
- ### Update
251
+ #### Update
235
252
 
236
253
  You can update the tool to [the latest version available on PyPI](https://pypi.org/project/refscan/) by running:
237
254
 
@@ -239,7 +256,7 @@ You can update the tool to [the latest version available on PyPI](https://pypi.o
239
256
  pipx upgrade refscan
240
257
  ```
241
258
 
242
- ### Uninstall
259
+ #### Uninstall
243
260
 
244
261
  You can uninstall the tool from your computer by running:
245
262
 
@@ -249,15 +266,65 @@ pipx uninstall refscan
249
266
 
250
267
  ### Container-based usage
251
268
 
252
- You can also run `refscan` via a container image hosted by the [GitHub Container Registry](https://github.com/microbiomedata/refscan/pkgs/container/refscan).
269
+ You can also run `refscan` via a container image hosted by the [GitHub Container Registry](https://github.com/microbiomedata/refscan/pkgs/container/refscan); for example:
253
270
 
254
271
  ```shell
255
- docker run --rm -it refscan --help
272
+ docker run --rm -it ghcr.io/microbiomedata/refscan:sha-51b1bb9 --help
256
273
  ```
257
274
 
258
275
  > Note: When running `refscan` via a container image, you can reference your host machine via the [special hostname](https://docs.docker.com/desktop/troubleshoot-and-support/faqs/general/#how-do-i-connect-from-a-container-to-a-service-on-the-host), "`host.docker.internal`".
259
276
  >
260
- > In other words, `$ docker run refscan --mongo-uri mongodb://host.docker.internal:27017` does the same thing as `$ refscan --mongo-uri mongodb://localhost:27017`, except the first command runs `refscan` within a container while the second one runs it directly on your hose machine.
277
+ > In other words, `$ docker run refscan --mongo-uri mongodb://host.docker.internal:27017` does the same thing as `$ refscan --mongo-uri mongodb://localhost:27017`, except the first command runs `refscan` within a container while the second one runs it directly on your host machine.
278
+
279
+ ### Library usage
280
+
281
+ `refscan` can also be used as a library. This allows application developers to use the various
282
+ functions implemented within `refscan` without having to re-implement them.
283
+
284
+ #### Installation
285
+
286
+ ```sh
287
+ pip install refscan
288
+ ```
289
+
290
+ #### Example usage
291
+
292
+ ```py
293
+ from linkml_runtime import SchemaView
294
+ from refscan.lib.helpers import (
295
+ get_collection_name_to_class_names_map,
296
+ get_collection_names_from_schema,
297
+ get_names_of_classes_eligible_for_collection,
298
+ )
299
+
300
+
301
+ # Instantiate a `SchemaView` bound to the schema.
302
+ schema_view = SchemaView("path/to/schema.yaml")
303
+
304
+ # Get the names of all collections the schema says can exist in the NMDC database.
305
+ # i.e., "What collections can exist?"
306
+ collection_names = get_collection_names_from_schema(schema_view=schema_view)
307
+
308
+ # Get the names of the classes whose instances the schema says can be stored in each collection.
309
+ # i.e., "What can exist in each collection?"
310
+ collection_name_to_class_names_map = get_collection_name_to_class_names_map(
311
+ schema_view=schema_view
312
+ )
313
+
314
+ # Get the names of the classes whose instances the schema says can be stored in the "study_set" collection.
315
+ # i.e., "What can exist in the 'study_set' collection?"
316
+ class_names = get_names_of_classes_eligible_for_collection(
317
+ schema_view=schema_view,
318
+ collection_name="study_set",
319
+ )
320
+ ```
321
+
322
+ #### Note to NMDC developers
323
+
324
+ If you think a given function currently implemented within the `refscan` repository would "fit better"
325
+ in another NMDC repository, please create an issue or otherwise bring it to the attention of a
326
+ `refscan` maintainer. For example, functions that depend upon only a `SchemaView` instance
327
+ (and not upon a MongoDB connection) may "fit better" in the `nmdc-schema` repository.
261
328
 
262
329
  ## Development
263
330
 
@@ -1,18 +1,3 @@
1
- Metadata-Version: 2.3
2
- Name: refscan
3
- Version: 0.4.3
4
- Summary: Command-line program that scans the NMDC MongoDB database for referential integrity violations
5
- Keywords: mongodb,mongo,relationships,reference,database,data,referential integrity,scan
6
- Requires-Dist: linkml-runtime>=1.7.5,<2
7
- Requires-Dist: pymongo>=4.7.1,<5
8
- Requires-Dist: rich>=13.7.1,<14
9
- Requires-Dist: typer>=0.15.1,<0.16
10
- Requires-Python: >=3.9, <4.0
11
- Project-URL: Documentation, https://github.com/microbiomedata/refscan
12
- Project-URL: Homepage, https://github.com/microbiomedata/refscan
13
- Project-URL: Repository, https://github.com/microbiomedata/refscan
14
- Description-Content-Type: text/markdown
15
-
16
1
  # refscan
17
2
 
18
3
  `refscan` is a command-line tool people can use to **scan** the [NMDC](https://microbiomedata.org/) MongoDB database
@@ -74,7 +59,9 @@ whose definition `refscan` then uses to determine _which fields_ of that documen
74
59
 
75
60
  ## Usage
76
61
 
77
- ### Install
62
+ ### Command-line application
63
+
64
+ #### Install
78
65
 
79
66
  Assuming you have `pipx` installed, you can install the tool by running the following command:
80
67
 
@@ -87,7 +74,7 @@ pipx install refscan
87
74
  > Python scripts that are hosted on PyPI.
88
75
  > You can [install `pipx`](https://pipx.pypa.io/stable/installation/) by running `$ python -m pip install pipx`.
89
76
 
90
- ### Run
77
+ #### Run
91
78
 
92
79
  Once installed, you can display the tool's `--help` snippet by running:
93
80
 
@@ -114,7 +101,7 @@ At the time of this writing, the tool's `--help` snippet is:
114
101
 
115
102
  Each command has its own `--help` snippet.
116
103
 
117
- #### The `scan` command
104
+ ##### The `scan` command
118
105
 
119
106
  At the time of this writing, the `--help` snippet for the `scan` command is:
120
107
 
@@ -163,7 +150,7 @@ At the time of this writing, the `--help` snippet for the `scan` command is:
163
150
 
164
151
  <!-- Note: The above snippet was captured from a terminal window whose width was 90 characters. -->
165
152
 
166
- ##### The MongoDB connection string (`--mongo-uri`)
153
+ ###### The MongoDB connection string (`--mongo-uri`)
167
154
 
168
155
  As documented in the `--help` snippet above, you can provide the MongoDB connection string to the tool via either
169
156
  (a) the `--mongo-uri` option; or (b) an environment variable named `MONGO_URI`. The latter can come in handy
@@ -176,7 +163,7 @@ Here's how you could create that environment variable:
176
163
  export MONGO_URI='mongodb://username:password@localhost:27017'
177
164
  ```
178
165
 
179
- ##### The schema (`--schema`)
166
+ ###### The schema (`--schema`)
180
167
 
181
168
  As documented in the `--help` snippet above, you can provide the path to a YAML-formatted LinkML schema file to the tool
182
169
  via the `--schema` option.
@@ -210,7 +197,7 @@ curl -o schema.yaml https://raw.githubusercontent.com/microbiomedata/nmdc-schema
210
197
  ---
211
198
  </details>
212
199
 
213
- ##### Output
200
+ ###### Output
214
201
 
215
202
  While `refscan` is running, it will display console output indicating what it's currently doing.
216
203
 
@@ -219,7 +206,7 @@ While `refscan` is running, it will display console output indicating what it's
219
206
  Once the scan is complete, the reference report (TSV file) and violation report (TSV file) will be available
220
207
  in the current directory (or in custom directories, if any were specified via CLI options).
221
208
 
222
- #### The `graph` command
209
+ ##### The `graph` command
223
210
 
224
211
  At the time of this writing, the `--help` snippet for the `graph` command is:
225
212
 
@@ -246,7 +233,7 @@ At the time of this writing, the `--help` snippet for the `graph` command is:
246
233
 
247
234
  <!-- Note: The above snippet was captured from a terminal window whose width was 90 characters. -->
248
235
 
249
- ### Update
236
+ #### Update
250
237
 
251
238
  You can update the tool to [the latest version available on PyPI](https://pypi.org/project/refscan/) by running:
252
239
 
@@ -254,7 +241,7 @@ You can update the tool to [the latest version available on PyPI](https://pypi.o
254
241
  pipx upgrade refscan
255
242
  ```
256
243
 
257
- ### Uninstall
244
+ #### Uninstall
258
245
 
259
246
  You can uninstall the tool from your computer by running:
260
247
 
@@ -264,15 +251,65 @@ pipx uninstall refscan
264
251
 
265
252
  ### Container-based usage
266
253
 
267
- You can also run `refscan` via a container image hosted by the [GitHub Container Registry](https://github.com/microbiomedata/refscan/pkgs/container/refscan).
254
+ You can also run `refscan` via a container image hosted by the [GitHub Container Registry](https://github.com/microbiomedata/refscan/pkgs/container/refscan); for example:
268
255
 
269
256
  ```shell
270
- docker run --rm -it refscan --help
257
+ docker run --rm -it ghcr.io/microbiomedata/refscan:sha-51b1bb9 --help
271
258
  ```
272
259
 
273
260
  > Note: When running `refscan` via a container image, you can reference your host machine via the [special hostname](https://docs.docker.com/desktop/troubleshoot-and-support/faqs/general/#how-do-i-connect-from-a-container-to-a-service-on-the-host), "`host.docker.internal`".
274
261
  >
275
- > In other words, `$ docker run refscan --mongo-uri mongodb://host.docker.internal:27017` does the same thing as `$ refscan --mongo-uri mongodb://localhost:27017`, except the first command runs `refscan` within a container while the second one runs it directly on your hose machine.
262
+ > In other words, `$ docker run refscan --mongo-uri mongodb://host.docker.internal:27017` does the same thing as `$ refscan --mongo-uri mongodb://localhost:27017`, except the first command runs `refscan` within a container while the second one runs it directly on your host machine.
263
+
264
+ ### Library usage
265
+
266
+ `refscan` can also be used as a library. This allows application developers to use the various
267
+ functions implemented within `refscan` without having to re-implement them.
268
+
269
+ #### Installation
270
+
271
+ ```sh
272
+ pip install refscan
273
+ ```
274
+
275
+ #### Example usage
276
+
277
+ ```py
278
+ from linkml_runtime import SchemaView
279
+ from refscan.lib.helpers import (
280
+ get_collection_name_to_class_names_map,
281
+ get_collection_names_from_schema,
282
+ get_names_of_classes_eligible_for_collection,
283
+ )
284
+
285
+
286
+ # Instantiate a `SchemaView` bound to the schema.
287
+ schema_view = SchemaView("path/to/schema.yaml")
288
+
289
+ # Get the names of all collections the schema says can exist in the NMDC database.
290
+ # i.e., "What collections can exist?"
291
+ collection_names = get_collection_names_from_schema(schema_view=schema_view)
292
+
293
+ # Get the names of the classes whose instances the schema says can be stored in each collection.
294
+ # i.e., "What can exist in each collection?"
295
+ collection_name_to_class_names_map = get_collection_name_to_class_names_map(
296
+ schema_view=schema_view
297
+ )
298
+
299
+ # Get the names of the classes whose instances the schema says can be stored in the "study_set" collection.
300
+ # i.e., "What can exist in the 'study_set' collection?"
301
+ class_names = get_names_of_classes_eligible_for_collection(
302
+ schema_view=schema_view,
303
+ collection_name="study_set",
304
+ )
305
+ ```
306
+
307
+ #### Note to NMDC developers
308
+
309
+ If you think a given function currently implemented within the `refscan` repository would "fit better"
310
+ in another NMDC repository, please create an issue or otherwise bring it to the attention of a
311
+ `refscan` maintainer. For example, functions that depend upon only a `SchemaView` instance
312
+ (and not upon a MongoDB connection) may "fit better" in the `nmdc-schema` repository.
276
313
 
277
314
  ## Development
278
315
 
@@ -1,9 +1,9 @@
1
1
  [project]
2
2
  name = "refscan"
3
- version = "0.4.3"
3
+ version = "0.5.0"
4
4
  description = "Command-line program that scans the NMDC MongoDB database for referential integrity violations"
5
5
  authors = []
6
- requires-python = ">= 3.9, < 4.0"
6
+ requires-python = ">= 3.10, < 4.0"
7
7
  readme = "README.md"
8
8
  keywords = [
9
9
  "mongodb",
@@ -18,16 +18,16 @@ keywords = [
18
18
  dependencies = [
19
19
  # We use `linkml-runtime` to facilitate using `nmdc-schema`.
20
20
  # Docs: https://linkml.io/linkml/developers/schemaview.html#linkml_runtime.utils.schemaview.SchemaView
21
- "linkml-runtime >= 1.7.5, < 2",
21
+ "linkml-runtime >= 1.12.1, < 2",
22
22
  # We use `pymongo` to communicate with MongoDB servers.
23
23
  # Docs: (https://pymongo.readthedocs.io/en/stable/
24
- "pymongo >= 4.7.1, < 5",
24
+ "pymongo >= 4.18.3, < 5",
25
25
  # We use `rich` to format console output.
26
26
  # Docs: https://rich.readthedocs.io/en/stable/index.html
27
27
  "rich >= 13.7.1, < 14",
28
28
  # We use `typer` as a CLI framework.
29
29
  # Docs: https://typer.tiangolo.com/
30
- "typer >= 0.15.1, < 0.16",
30
+ "typer >= 0.29.1, < 0.30",
31
31
  ]
32
32
 
33
33
  [project.urls]
@@ -47,7 +47,7 @@ dev = [
47
47
  # We use `pytest` to run tests.
48
48
  # Usage: $ uv run pytest
49
49
  # Docs: https://docs.pytest.org/en/stable/contents.html
50
- "pytest >= 8.2.2, < 9",
50
+ "pytest>=8.2.2,<10",
51
51
  "pytest-cov >= 5.0.0, < 6",
52
52
  # We use `mongomock` to test MongoDB interaction without involving a real MongoDB instance.
53
53
  # Docs: https://github.com/mongomock/mongomock
@@ -0,0 +1,24 @@
1
+ from typing import TypedDict
2
+
3
+ from bson import ObjectId
4
+
5
+
6
+ class ReferringDocumentDescriptor(TypedDict):
7
+ """
8
+ A custom type that describes the items of the list returned by the function,
9
+ `refscan.scanner.identify_referring_documents`.
10
+
11
+ Docs: https://typing.python.org/en/latest/spec/typeddict.html
12
+ """
13
+
14
+ source_collection_name: str
15
+ """The name of the collection in which the referring document resides."""
16
+
17
+ source_class_name: str
18
+ """The name of the class of which the referring document represent an instance."""
19
+
20
+ source_document_object_id: ObjectId
21
+ """The value in the referring document's `_id` field."""
22
+
23
+ source_document_id: str
24
+ """The value in the referring document's `id` field."""
@@ -14,6 +14,7 @@ from refscan.lib.helpers import (
14
14
  init_progress_bar,
15
15
  )
16
16
  from refscan.lib.ReferenceList import ReferenceList
17
+ from refscan.lib.ReferringDocumentDescriptor import ReferringDocumentDescriptor
17
18
  from refscan.lib.Violation import Violation
18
19
  from refscan.lib.ViolationList import ViolationList
19
20
  from refscan.lib.constants import console as default_console
@@ -25,7 +26,7 @@ def identify_referring_documents(
25
26
  references: ReferenceList,
26
27
  finder: Finder,
27
28
  client_session: Optional[ClientSession] = None,
28
- ) -> List[dict]:
29
+ ) -> List[ReferringDocumentDescriptor]:
29
30
  r"""
30
31
  Identifies documents that reference the specified one.
31
32
 
@@ -50,7 +51,7 @@ def identify_referring_documents(
50
51
  """
51
52
 
52
53
  # Initialize a list of descriptors of documents that reference the specified document.
53
- referring_document_descriptors: List[Dict] = []
54
+ referring_document_descriptors: List[ReferringDocumentDescriptor] = []
54
55
 
55
56
  # If the specified document does not have an `id` field, we know it cannot be referenced.
56
57
  if "id" not in document:
@@ -111,7 +112,11 @@ def identify_referring_documents(
111
112
  schema_view=schema_view,
112
113
  class_uri=referring_document["type"],
113
114
  )
114
- document_descriptor = dict(
115
+ if source_class_name is None:
116
+ raise ValueError(
117
+ f"Failed to translate class_uri '{referring_document['type']}' into schema class name."
118
+ )
119
+ document_descriptor = ReferringDocumentDescriptor(
115
120
  source_collection_name=collection_name,
116
121
  source_class_name=source_class_name,
117
122
  source_document_object_id=referring_document["_id"],
@@ -332,7 +337,9 @@ def scan(
332
337
  # Reference: https://rich.readthedocs.io/en/stable/reference/console.html#rich.console.Console.is_terminal
333
338
  #
334
339
  if not console.is_terminal:
335
- console.print(f"Scanning collection '{source_collection_name}' ({num_relevant_documents} documents).")
340
+ console.print(
341
+ f"Scanning collection '{source_collection_name}' ({num_relevant_documents} relevant documents)."
342
+ )
336
343
 
337
344
  # Advance the progress bar by 0 (this makes it so that, even if there are 0 relevant documents, the progress
338
345
  # bar does not continue incrementing its "elapsed time" even after a subsequent task has begun).
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes