dump-things-pyclient 0.1.0__tar.gz → 0.1.2__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.
Files changed (19) hide show
  1. {dump_things_pyclient-0.1.0 → dump_things_pyclient-0.1.2}/PKG-INFO +3 -1
  2. dump_things_pyclient-0.1.2/dump_things_pyclient/commands/json2ttl.py +64 -0
  3. dump_things_pyclient-0.1.2/dump_things_pyclient/commands/post_records.py +59 -0
  4. {dump_things_pyclient-0.1.0 → dump_things_pyclient-0.1.2}/dump_things_pyclient/communicate.py +38 -7
  5. {dump_things_pyclient-0.1.0 → dump_things_pyclient-0.1.2}/dump_things_pyclient.egg-info/PKG-INFO +3 -1
  6. {dump_things_pyclient-0.1.0 → dump_things_pyclient-0.1.2}/dump_things_pyclient.egg-info/SOURCES.txt +2 -0
  7. {dump_things_pyclient-0.1.0 → dump_things_pyclient-0.1.2}/dump_things_pyclient.egg-info/entry_points.txt +2 -0
  8. dump_things_pyclient-0.1.2/dump_things_pyclient.egg-info/requires.txt +2 -0
  9. {dump_things_pyclient-0.1.0 → dump_things_pyclient-0.1.2}/pyproject.toml +7 -1
  10. dump_things_pyclient-0.1.0/dump_things_pyclient.egg-info/requires.txt +0 -1
  11. {dump_things_pyclient-0.1.0 → dump_things_pyclient-0.1.2}/README.md +0 -0
  12. {dump_things_pyclient-0.1.0 → dump_things_pyclient-0.1.2}/dump_things_pyclient/__init__.py +0 -0
  13. {dump_things_pyclient-0.1.0 → dump_things_pyclient-0.1.2}/dump_things_pyclient/commands/__init__.py +0 -0
  14. {dump_things_pyclient-0.1.0 → dump_things_pyclient-0.1.2}/dump_things_pyclient/commands/auto_curate.py +0 -0
  15. {dump_things_pyclient-0.1.0 → dump_things_pyclient-0.1.2}/dump_things_pyclient/commands/get_records.py +0 -0
  16. {dump_things_pyclient-0.1.0 → dump_things_pyclient-0.1.2}/dump_things_pyclient/commands/read_pages.py +0 -0
  17. {dump_things_pyclient-0.1.0 → dump_things_pyclient-0.1.2}/dump_things_pyclient.egg-info/dependency_links.txt +0 -0
  18. {dump_things_pyclient-0.1.0 → dump_things_pyclient-0.1.2}/dump_things_pyclient.egg-info/top_level.txt +0 -0
  19. {dump_things_pyclient-0.1.0 → dump_things_pyclient-0.1.2}/setup.cfg +0 -0
@@ -1,9 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dump-things-pyclient
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Summary: A client library and some CLI command for dump-things-services
5
+ Author-email: Christian Mönch <christian.moench@web.de>
5
6
  Requires-Python: >=3.11
6
7
  Description-Content-Type: text/markdown
8
+ Requires-Dist: dump-things-service>=5.3.0
7
9
  Requires-Dist: requests>=2.32.5
8
10
 
9
11
  # Dump Things Python Client
@@ -0,0 +1,64 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import json
5
+ import re
6
+ import sys
7
+
8
+ from dump_things_service.converter import (
9
+ Format,
10
+ FormatConverter,
11
+ )
12
+
13
+
14
+ description = f"""Read JSON records from stdin and convert them to TTL
15
+
16
+ This command reads one record per line, either JSON format or a JSON-string
17
+ with a TTL-document from stdin, converts them to TTL or JSON and prints them
18
+ to stdout.
19
+
20
+ """
21
+
22
+
23
+ def main():
24
+ argument_parser = argparse.ArgumentParser(
25
+ description=description,
26
+ formatter_class=argparse.RawDescriptionHelpFormatter,
27
+ )
28
+ argument_parser.add_argument('schema', help='URL of the schema that should be used')
29
+
30
+ arguments = argument_parser.parse_args()
31
+
32
+ print(f'Creating converter for schema {arguments.schema} ...', file=sys.stderr, end='', flush=True)
33
+ converter = FormatConverter(
34
+ arguments.schema,
35
+ input_format=Format.json,
36
+ output_format=Format.ttl,
37
+ )
38
+ print(' done', file=sys.stderr, flush=True)
39
+
40
+ error = False
41
+ for line in sys.stdin:
42
+ json_object = json.loads(line)
43
+
44
+ object_class = json_object.get('schema_type')
45
+ if object_class is None:
46
+ error = True
47
+ print(f'ERROR: No schema_type in {json_object}', file=sys.stderr, flush=True)
48
+ continue
49
+
50
+ class_name = re.search('([_A-Za-z0-9]*$)', object_class).group(0)
51
+
52
+ try:
53
+ ttl = converter.convert(json_object, class_name)
54
+ except ValueError as ve:
55
+ print(f'ERROR: conversion failed for {json_object}: {ve}', file=sys.stderr, flush=True)
56
+ continue
57
+
58
+ print(json.dumps(ttl))
59
+
60
+ return 1 if error else 0
61
+
62
+
63
+ if __name__ == '__main__':
64
+ sys.exit(main())
@@ -0,0 +1,59 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import json
5
+ import os
6
+ import sys
7
+
8
+ from ..communicate import (
9
+ collection_write_record,
10
+ curated_write_record,
11
+ )
12
+
13
+
14
+ def main():
15
+ argument_parser = argparse.ArgumentParser()
16
+ argument_parser.add_argument('base_url')
17
+ argument_parser.add_argument('collection')
18
+ argument_parser.add_argument('cls', metavar='class')
19
+ argument_parser.add_argument('--curated', action='store_true', help='bypass inbox, requires curator token')
20
+
21
+ arguments = argument_parser.parse_args()
22
+
23
+ token = os.environ.get('DUMPTHINGS_TOKEN')
24
+ if token is None:
25
+ print(
26
+ 'WARNING: environment variable DUMPTHINGS_TOKEN not set',
27
+ file=sys.stderr,
28
+ flush=True,
29
+ )
30
+
31
+ if arguments.curated:
32
+ write_record = curated_write_record
33
+ else:
34
+ write_record = collection_write_record
35
+
36
+ posted = False
37
+ for line in sys.stdin:
38
+ record = json.loads(line)
39
+ try:
40
+ write_record(
41
+ service_url=arguments.base_url,
42
+ collection=arguments.collection,
43
+ class_name=arguments.cls,
44
+ record=record,
45
+ token=token,
46
+ )
47
+ except Exception as e:
48
+ print(f'Error: {e}', file=sys.stderr, flush=True)
49
+ else:
50
+ posted = True
51
+ print('.', end='', flush=True)
52
+
53
+ if posted:
54
+ # final newline
55
+ print('')
56
+
57
+
58
+ if __name__ == '__main__':
59
+ sys.exit(main())
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import logging
4
+ import re
4
5
  from itertools import count
5
6
  from typing import (
6
7
  Callable,
@@ -18,6 +19,7 @@ __all__ = [
18
19
  'JSON',
19
20
  'get_paginated',
20
21
  'get',
22
+ 'collection_get_classes',
21
23
  'collection_delete_record',
22
24
  'collection_read_records',
23
25
  'collection_read_records_of_class',
@@ -99,6 +101,29 @@ def get(url: str,
99
101
  return _get_from_url(url, token, parameters)
100
102
 
101
103
 
104
+ def collection_get_classes(service_url: str,
105
+ collection: str,
106
+ ) -> Generator[str, None, None]:
107
+ """Read classes that are supported by the collection
108
+
109
+ Get the name of the classes that are known in the collection. If the
110
+ collection does not exist on the server, no class names are returned.
111
+
112
+ :param service_url: the base URL of the service, i.e., the URL up to
113
+ `/<collection>/...` or `/server`
114
+ :param collection: the name of the collection
115
+
116
+ :return: a generator yielding names of the supported classes
117
+ """
118
+ service_url = f'{service_url[:-1]}' if service_url.endswith('/') else service_url
119
+ matcher = re.compile(f'/{collection}/record/([A-Z][_a-zA-Z0-9]*)$')
120
+ open_api_spec = _get_from_url(service_url + '/openapi.json', None)
121
+ for path in open_api_spec['paths']:
122
+ match = matcher.match(path)
123
+ if match:
124
+ yield match.group(1)
125
+
126
+
102
127
  def collection_read_record_with_pid(service_url: str,
103
128
  collection: str,
104
129
  pid: str,
@@ -236,11 +261,12 @@ def collection_write_record(
236
261
  than one record due to inlined-relations extraction. The individual
237
262
  records might have annotations added
238
263
  """
264
+ _check_format_value(format)
239
265
  return _post_to_url(
240
266
  url=_build_url(service_url, collection, f'record/{class_name}'),
241
267
  token=token,
242
- json=record,
243
- params={'format': format})
268
+ params={'format': format},
269
+ **(dict(json=record) if format == 'json' else dict(data=record)))
244
270
 
245
271
 
246
272
  def collection_validate_record(
@@ -269,12 +295,12 @@ def collection_validate_record(
269
295
 
270
296
  :return: True
271
297
  """
272
- service_url = f'{service_url[:-1]}' if service_url.endswith('/') else service_url
298
+ _check_format_value(format)
273
299
  return _post_to_url(
274
300
  url=_build_url(service_url, collection, f'validate/{class_name}'),
275
301
  token=token,
276
- json=record,
277
- params={'format': format})
302
+ params={'format': format},
303
+ **(dict(json=record) if format == 'json' else dict(data=record)))
278
304
 
279
305
 
280
306
  def collection_delete_record(
@@ -660,10 +686,10 @@ def _get_from_url(url: str,
660
686
 
661
687
  def _post_to_url(url: str,
662
688
  token: str | None,
663
- json: JSON,
664
689
  params: dict[str, str] | None = None,
690
+ **kwargs,
665
691
  ) -> JSON:
666
- return _do_request(requests.post, url, token, params, json=json)
692
+ return _do_request(requests.post, url, token, params, **kwargs)
667
693
 
668
694
 
669
695
  def _delete_url(url: str,
@@ -717,3 +743,8 @@ def _get_page(url_base: str,
717
743
  parameters['page'] = first_page
718
744
  parameters['size'] = page_size
719
745
  return _get_from_url(url_base, token, parameters)
746
+
747
+
748
+ def _check_format_value(format: str) -> None:
749
+ if format not in ('json', 'ttl'):
750
+ raise ValueError('Format must be either "json" or "ttl"')
@@ -1,9 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dump-things-pyclient
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Summary: A client library and some CLI command for dump-things-services
5
+ Author-email: Christian Mönch <christian.moench@web.de>
5
6
  Requires-Python: >=3.11
6
7
  Description-Content-Type: text/markdown
8
+ Requires-Dist: dump-things-service>=5.3.0
7
9
  Requires-Dist: requests>=2.32.5
8
10
 
9
11
  # Dump Things Python Client
@@ -11,4 +11,6 @@ dump_things_pyclient.egg-info/top_level.txt
11
11
  dump_things_pyclient/commands/__init__.py
12
12
  dump_things_pyclient/commands/auto_curate.py
13
13
  dump_things_pyclient/commands/get_records.py
14
+ dump_things_pyclient/commands/json2ttl.py
15
+ dump_things_pyclient/commands/post_records.py
14
16
  dump_things_pyclient/commands/read_pages.py
@@ -1,4 +1,6 @@
1
1
  [console_scripts]
2
2
  auto-curate = dump_things_pyclient.commands.auto_curate:main
3
3
  get-records = dump_things_pyclient.commands.get_records:main
4
+ json2ttl = dump_things_pyclient.commands.json2ttl:main
5
+ post-records = dump_things_pyclient.commands.post_records:main
4
6
  read-pages = dump_things_pyclient.commands.read_pages:main
@@ -0,0 +1,2 @@
1
+ dump-things-service>=5.3.0
2
+ requests>=2.32.5
@@ -1,10 +1,14 @@
1
1
  [project]
2
2
  name = "dump-things-pyclient"
3
- version = "0.1.0"
3
+ version = "0.1.2"
4
4
  description = "A client library and some CLI command for dump-things-services"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
7
+ authors = [
8
+ {name="Christian Mönch", email="christian.moench@web.de"},
9
+ ]
7
10
  dependencies = [
11
+ "dump-things-service>=5.3.0",
8
12
  "requests>=2.32.5",
9
13
  ]
10
14
 
@@ -17,3 +21,5 @@ tests = [
17
21
  auto-curate = "dump_things_pyclient.commands.auto_curate:main"
18
22
  read-pages = "dump_things_pyclient.commands.read_pages:main"
19
23
  get-records = "dump_things_pyclient.commands.get_records:main"
24
+ json2ttl = "dump_things_pyclient.commands.json2ttl:main"
25
+ post-records = "dump_things_pyclient.commands.post_records:main"
@@ -1 +0,0 @@
1
- requests>=2.32.5