arkindex-client 1.1.1__py3-none-any.whl → 1.1.3__py3-none-any.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.
@@ -1,54 +1,22 @@
1
1
  # -*- coding: utf-8 -*-
2
- import re
3
2
  import typing
4
3
 
5
4
  import typesystem
6
5
 
7
6
  from arkindex.schema.openapi import OPEN_API, OpenAPI
8
7
 
9
- ENCODING_CHOICES = ["json", "yaml", None]
10
8
 
11
- # The regexs give us a best-guess for the encoding if none is specified.
12
- # They check to see if the document looks like it is probably a YAML object or
13
- # probably a JSON object. It'll typically be best to specify the encoding
14
- # explicitly, but this should do for convenience.
15
- INFER_YAML = re.compile(r"^([ \t]*#.*\n|---[ \t]*\n)*\s*[A-Za-z0-9_-]+[ \t]*:")
16
- INFER_JSON = re.compile(r'^\s*{\s*"[A-Za-z0-9_-]+"\s*:')
17
-
18
-
19
- def validate(schema: typing.Union[dict, str, bytes], encoding: str = None):
9
+ def validate(schema: typing.Union[dict, str, bytes]):
20
10
  if not isinstance(schema, (dict, str, bytes)):
21
11
  raise ValueError("schema must be either str, bytes, or dict.")
22
- if encoding not in ENCODING_CHOICES:
23
- raise ValueError(f"encoding must be one of {ENCODING_CHOICES!r}")
24
12
 
25
13
  if isinstance(schema, bytes):
26
14
  schema = schema.decode("utf8", "ignore")
27
15
 
28
16
  if isinstance(schema, str):
29
- if encoding is None:
30
- if INFER_YAML.match(schema):
31
- encoding = "yaml"
32
- elif INFER_JSON.match(schema):
33
- encoding = "json"
34
- else:
35
- text = "Could not determine if content is JSON or YAML."
36
- code = "unknown_encoding"
37
- position = typesystem.Position(line_no=1, column_no=1, char_index=0)
38
- raise typesystem.ParseError(text=text, code=code, position=position)
39
-
40
- tokenize = {"yaml": typesystem.tokenize_yaml, "json": typesystem.tokenize_json}[
41
- encoding
42
- ]
43
- token = tokenize(schema)
44
- value = token.value
45
- else:
46
- token = None
47
- value = schema
48
-
49
- if token is not None:
17
+ token = typesystem.tokenize_json(schema)
50
18
  value = typesystem.validate_with_positions(token=token, validator=OpenAPI)
51
19
  else:
52
- value = OPEN_API.validate(value)
20
+ value = OPEN_API.validate(schema)
53
21
 
54
22
  return OpenAPI().load(value)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: arkindex-client
3
- Version: 1.1.1
3
+ Version: 1.1.3
4
4
  Summary: API client for the Arkindex project
5
5
  Home-page: https://gitlab.teklia.com/arkindex/api-client
6
6
  Author: Teklia <contact@teklia.com>
@@ -20,9 +20,8 @@ Classifier: Topic :: Text Processing :: Indexing
20
20
  Classifier: Topic :: Text Processing :: Linguistic
21
21
  Requires-Python: >=3.8
22
22
  License-File: LICENSE
23
- Requires-Dist: PyYAML==6.0.2
24
23
  Requires-Dist: requests~=2.28
25
24
  Requires-Dist: tenacity==8.2.3
26
- Requires-Dist: typesystem==0.2.5
25
+ Requires-Dist: typesystem==0.4.1
27
26
 
28
27
  Documentation is available at https://api.arkindex.org
@@ -0,0 +1,20 @@
1
+ apistar/__init__.py,sha256=mX65SD-MGA1ZynGKkqh7zEONxAIMsPktTaAXeh69Kwc,231
2
+ apistar/exceptions.py,sha256=yzjDlUB5o0xaORBabqTXmf4ckYjNHz1ceV8ECg3jDek,328
3
+ arkindex/__init__.py,sha256=OBw25Nwe6r1AN3a36-8lnUcDy3nkDIiebBgYNK2Zo9o,99
4
+ arkindex/auth.py,sha256=OeuzFeCQ8FAt0kqPECjsEz-Ki9__-y69z5sAuyTZ28c,1550
5
+ arkindex/compat.py,sha256=Kjxu--QoF8sBxKOvXMtNcDQ0XK7MLc_2C8Q2knll4Lk,805
6
+ arkindex/document.py,sha256=YyqSm3Kc35j3iWuJujyfrLfMy-gNydBtmcR45pUtfC4,3732
7
+ arkindex/exceptions.py,sha256=hDxbgC7uAD8wbTQS1DaEJZ25Nun41Io8Y0BiwrZ1ZSM,2016
8
+ arkindex/mock.py,sha256=olYBFCkLQuuf9gGu7wlmZiLFMQknGGi8evS531RjjUE,2755
9
+ arkindex/pagination.py,sha256=kzOyl2oMqGyyVy7LG7eKK9wAI6YdVzEeOuBEbkdw5Zo,11002
10
+ arkindex/client/__init__.py,sha256=g_G_bSfMbduYzpi9iURTn0cYLV4nMulDR8rD7x-DLyc,142
11
+ arkindex/client/client.py,sha256=ZOcMY5IjOUxADkCsCdpgylJM-oJVY_XObRVH4p4onVI,15428
12
+ arkindex/client/decoders.py,sha256=WmRdqNAFv884XIfHXTkQoohJMapeTq8AqQzsW26K-t4,7952
13
+ arkindex/schema/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ arkindex/schema/openapi.py,sha256=HHAHyUxqa6sK1l8aEy7SHx-9w20Pbov54AB4rHPjguk,9183
15
+ arkindex/schema/validator.py,sha256=Baq2TtqMWZVRU_SYF7aUJ0Y80t-CIboCtK_GV8TPNKE,625
16
+ arkindex_client-1.1.3.dist-info/LICENSE,sha256=s7yDHdG8liSj2PiaVwRi9G5wR1qDXSPmhPJPgWbrkWU,34504
17
+ arkindex_client-1.1.3.dist-info/METADATA,sha256=rOgOnPbp4NP2WnhQMNwx61OIcVQX2nfz-6XrFeO_nQ8,1051
18
+ arkindex_client-1.1.3.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
19
+ arkindex_client-1.1.3.dist-info/top_level.txt,sha256=ALyF0lTPpxOheUGmSVwEhgI6eMYwm_9Eu37G-RwGBRM,17
20
+ arkindex_client-1.1.3.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.44.0)
2
+ Generator: bdist_wheel (0.45.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
arkindex/client/base.py DELETED
@@ -1,98 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- from urllib.parse import quote, urljoin, urlparse
3
-
4
- import typesystem
5
-
6
- from arkindex import exceptions
7
- from arkindex.client.transports import HTTPTransport
8
- from arkindex.schema.validator import validate
9
-
10
-
11
- class BaseClient:
12
- def __init__(
13
- self,
14
- schema,
15
- encoding=None,
16
- auth=None,
17
- decoders=None,
18
- headers=None,
19
- session=None,
20
- allow_cookies=True,
21
- verify=True,
22
- ):
23
- self.document = validate(schema, encoding=encoding)
24
- self.transport = HTTPTransport(
25
- auth=auth,
26
- decoders=decoders,
27
- headers=headers,
28
- session=session,
29
- allow_cookies=allow_cookies,
30
- verify=verify,
31
- )
32
-
33
- def lookup_operation(self, operation_id: str):
34
- for item in self.document.walk_links():
35
- if item.link.name == operation_id:
36
- return item.link
37
- text = 'Operation ID "%s" not found in schema.' % operation_id
38
- message = exceptions.ErrorMessage(text=text, code="invalid-operation")
39
- raise exceptions.ClientError(messages=[message])
40
-
41
- def get_url(self, link, params):
42
- url = urljoin(self.document.url, link.url)
43
-
44
- scheme = urlparse(url).scheme.lower()
45
-
46
- if not scheme:
47
- text = "URL missing scheme '%s'." % url
48
- message = exceptions.ErrorMessage(text=text, code="invalid-url")
49
- raise exceptions.ClientError(messages=[message])
50
-
51
- if scheme not in self.transport.schemes:
52
- text = "Unsupported URL scheme '%s'." % scheme
53
- message = exceptions.ErrorMessage(text=text, code="invalid-url")
54
- raise exceptions.ClientError(messages=[message])
55
-
56
- for field in link.get_path_fields():
57
- value = str(params[field.name])
58
- if "{%s}" % field.name in url:
59
- url = url.replace("{%s}" % field.name, quote(value, safe=""))
60
- elif "{+%s}" % field.name in url:
61
- url = url.replace("{+%s}" % field.name, quote(value, safe="/"))
62
-
63
- return url
64
-
65
- def get_query_params(self, link, params):
66
- return {
67
- field.name: params[field.name]
68
- for field in link.get_query_fields()
69
- if field.name in params
70
- }
71
-
72
- def get_content_and_encoding(self, link, params):
73
- body_field = link.get_body_field()
74
- if body_field and body_field.name in params:
75
- return (params[body_field.name], link.encoding)
76
- return (None, None)
77
-
78
- def request(self, operation_id: str, **params):
79
- link = self.lookup_operation(operation_id)
80
-
81
- validator = typesystem.Object(
82
- properties={field.name: typesystem.Any() for field in link.fields},
83
- required=[field.name for field in link.fields if field.required],
84
- additional_properties=False,
85
- )
86
- try:
87
- validator.validate(params)
88
- except typesystem.ValidationError as exc:
89
- raise exceptions.ClientError(messages=exc.messages()) from None
90
-
91
- method = link.method
92
- url = self.get_url(link, params)
93
- query_params = self.get_query_params(link, params)
94
- (content, encoding) = self.get_content_and_encoding(link, params)
95
-
96
- return self.transport.send(
97
- method, url, query_params=query_params, content=content, encoding=encoding
98
- )
@@ -1,132 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- import http
3
- from importlib.metadata import version
4
-
5
- import requests
6
-
7
- from arkindex import exceptions
8
- from arkindex.client import decoders
9
-
10
- REQUEST_TIMEOUT = (30, 60)
11
-
12
-
13
- class BlockAllCookies(http.cookiejar.CookiePolicy):
14
- """
15
- A cookie policy that rejects all cookies.
16
- Used to override the default `requests` behavior.
17
- """
18
-
19
- return_ok = set_ok = domain_return_ok = path_return_ok = (
20
- lambda self, *args, **kwargs: False
21
- )
22
- netscape = True
23
- rfc2965 = hide_cookie2 = False
24
-
25
-
26
- class BaseTransport:
27
- schemes = None
28
-
29
- def send(self, method, url, query_params=None, content=None, encoding=None):
30
- raise NotImplementedError()
31
-
32
-
33
- class HTTPTransport(BaseTransport):
34
- schemes = ["http", "https"]
35
- default_decoders = [
36
- decoders.JSONDecoder(),
37
- decoders.TextDecoder(),
38
- decoders.DownloadDecoder(),
39
- ]
40
-
41
- def __init__(
42
- self,
43
- auth=None,
44
- decoders=None,
45
- headers=None,
46
- session=None,
47
- allow_cookies=True,
48
- verify=True,
49
- ):
50
- if session is None:
51
- session = requests.Session()
52
- if auth is not None:
53
- session.auth = auth
54
- if not allow_cookies:
55
- session.cookies.set_policy(BlockAllCookies())
56
-
57
- self.session = session
58
- self.verify = verify
59
- self.decoders = list(decoders) if decoders else list(self.default_decoders)
60
-
61
- client_version = version("arkindex-client")
62
- self.headers = {
63
- "accept": ", ".join([decoder.media_type for decoder in self.decoders]),
64
- "user-agent": f"arkindex-client/{client_version}",
65
- }
66
- if headers:
67
- self.headers.update({key.lower(): value for key, value in headers.items()})
68
-
69
- def send(self, method, url, query_params=None, content=None, encoding=None):
70
- options = self.get_request_options(query_params, content, encoding)
71
- response = self.session.request(method, url, **options)
72
- result = self.decode_response_content(response)
73
-
74
- if 400 <= response.status_code <= 599:
75
- title = "%d %s" % (response.status_code, response.reason)
76
- raise exceptions.ErrorResponse(
77
- title=title, status_code=response.status_code, content=result
78
- )
79
-
80
- return result
81
-
82
- def get_decoder(self, content_type=None):
83
- """
84
- Given the value of a 'Content-Type' header, return the appropriate
85
- decoder for handling the response content.
86
- """
87
- if content_type is None:
88
- return self.decoders[0]
89
-
90
- content_type = content_type.split(";")[0].strip().lower()
91
- main_type = content_type.split("/")[0] + "/*"
92
- wildcard_type = "*/*"
93
-
94
- for codec in self.decoders:
95
- if codec.media_type in (content_type, main_type, wildcard_type):
96
- return codec
97
-
98
- text = (
99
- "Unsupported encoding '%s' in response Content-Type header." % content_type
100
- )
101
- message = exceptions.ErrorMessage(text=text, code="cannot-decode-response")
102
- raise exceptions.ClientError(messages=[message])
103
-
104
- def get_request_options(self, query_params=None, content=None, encoding=None):
105
- """
106
- Return the 'options' for sending the outgoing request.
107
- """
108
- options = {
109
- "headers": dict(self.headers),
110
- "params": query_params,
111
- "timeout": REQUEST_TIMEOUT,
112
- "verify": self.verify,
113
- }
114
-
115
- if content is not None:
116
- assert (
117
- encoding == "application/json"
118
- ), "Only JSON request bodies are supported"
119
- options["json"] = content
120
-
121
- return options
122
-
123
- def decode_response_content(self, response):
124
- """
125
- Given an HTTP response, return the decoded data.
126
- """
127
- if not response.content:
128
- return None
129
-
130
- content_type = response.headers.get("content-type")
131
- decoder = self.get_decoder(content_type)
132
- return decoder.decode(response)
@@ -1,66 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- import typesystem
3
-
4
- definitions = typesystem.SchemaDefinitions()
5
-
6
- JSON_SCHEMA = (
7
- typesystem.Object(
8
- properties={
9
- "$ref": typesystem.String(),
10
- "type": typesystem.String() | typesystem.Array(items=typesystem.String()),
11
- "enum": typesystem.Array(unique_items=True, min_items=1),
12
- "definitions": typesystem.Object(
13
- additional_properties=typesystem.Reference(
14
- "JSONSchema", definitions=definitions
15
- )
16
- ),
17
- # String
18
- "minLength": typesystem.Integer(minimum=0),
19
- "maxLength": typesystem.Integer(minimum=0),
20
- "pattern": typesystem.String(format="regex"),
21
- "format": typesystem.String(),
22
- # Numeric
23
- "minimum": typesystem.Number(),
24
- "maximum": typesystem.Number(),
25
- "exclusiveMinimum": typesystem.Number(),
26
- "exclusiveMaximum": typesystem.Number(),
27
- "multipleOf": typesystem.Number(exclusive_minimum=0),
28
- # Object
29
- "properties": typesystem.Object(
30
- additional_properties=typesystem.Reference(
31
- "JSONSchema", definitions=definitions
32
- )
33
- ),
34
- "minProperties": typesystem.Integer(minimum=0),
35
- "maxProperties": typesystem.Integer(minimum=0),
36
- "patternProperties": typesystem.Object(
37
- additional_properties=typesystem.Reference(
38
- "JSONSchema", definitions=definitions
39
- )
40
- ),
41
- "additionalProperties": (
42
- typesystem.Reference("JSONSchema", definitions=definitions)
43
- | typesystem.Boolean()
44
- ),
45
- "required": typesystem.Array(items=typesystem.String(), unique_items=True),
46
- # Array
47
- "items": (
48
- typesystem.Reference("JSONSchema", definitions=definitions)
49
- | typesystem.Array(
50
- items=typesystem.Reference("JSONSchema", definitions=definitions),
51
- min_items=1,
52
- )
53
- ),
54
- "additionalItems": (
55
- typesystem.Reference("JSONSchema", definitions=definitions)
56
- | typesystem.Boolean()
57
- ),
58
- "minItems": typesystem.Integer(minimum=0),
59
- "maxItems": typesystem.Integer(minimum=0),
60
- "uniqueItems": typesystem.Boolean(),
61
- }
62
- )
63
- | typesystem.Boolean()
64
- )
65
-
66
- definitions["JSONSchema"] = JSON_SCHEMA
@@ -1,23 +0,0 @@
1
- apistar/__init__.py,sha256=mX65SD-MGA1ZynGKkqh7zEONxAIMsPktTaAXeh69Kwc,231
2
- apistar/exceptions.py,sha256=yzjDlUB5o0xaORBabqTXmf4ckYjNHz1ceV8ECg3jDek,328
3
- arkindex/__init__.py,sha256=OBw25Nwe6r1AN3a36-8lnUcDy3nkDIiebBgYNK2Zo9o,99
4
- arkindex/auth.py,sha256=OeuzFeCQ8FAt0kqPECjsEz-Ki9__-y69z5sAuyTZ28c,1550
5
- arkindex/compat.py,sha256=Kjxu--QoF8sBxKOvXMtNcDQ0XK7MLc_2C8Q2knll4Lk,805
6
- arkindex/document.py,sha256=SUmzvuJpeHlRC4ozqnqsPFpzZ9_Yb9p6vxIZpMjMCSA,6783
7
- arkindex/exceptions.py,sha256=hDxbgC7uAD8wbTQS1DaEJZ25Nun41Io8Y0BiwrZ1ZSM,2016
8
- arkindex/mock.py,sha256=olYBFCkLQuuf9gGu7wlmZiLFMQknGGi8evS531RjjUE,2755
9
- arkindex/pagination.py,sha256=c6dG_OkQDG00ZfGUbHuZxu-UvOpmYf7dJP1ZaUaha1Y,9008
10
- arkindex/client/__init__.py,sha256=g_G_bSfMbduYzpi9iURTn0cYLV4nMulDR8rD7x-DLyc,142
11
- arkindex/client/base.py,sha256=vlR5HjaNQ_LzIP_FAzaZbhJSh7VzD9mXc0T8C5FB8EU,3400
12
- arkindex/client/client.py,sha256=lfHyicizHDxdymPA1hl0kJj7vdrudVvbE2Ei3qtZqQM,12019
13
- arkindex/client/decoders.py,sha256=F_uBGOrh1BFnZzuW0MTjwm8wAArbybPsrIVol_2vYN0,7886
14
- arkindex/client/transports.py,sha256=482CHa-8S5p190Z4cX6TiCWgz99enfloT7FCNuS02yY,4055
15
- arkindex/schema/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
- arkindex/schema/jsonschema.py,sha256=sJ0OlkowXoE4FnA3r9_QdOmLlDP46K7YPPQm58NkfMo,2572
17
- arkindex/schema/openapi.py,sha256=bwVAEjdHNUf9iRPVdbQwruivs4GAwbe0db1KkLNKa80,17603
18
- arkindex/schema/validator.py,sha256=N2sda7vxfivw68VuyX-MfmUlrXjf_LEHNg6OCKc1mjQ,1926
19
- arkindex_client-1.1.1.dist-info/LICENSE,sha256=s7yDHdG8liSj2PiaVwRi9G5wR1qDXSPmhPJPgWbrkWU,34504
20
- arkindex_client-1.1.1.dist-info/METADATA,sha256=IzsAvC5p34ps77eNhP8x9s-GSN-_qIp1eSlXemcQJLA,1080
21
- arkindex_client-1.1.1.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
22
- arkindex_client-1.1.1.dist-info/top_level.txt,sha256=ALyF0lTPpxOheUGmSVwEhgI6eMYwm_9Eu37G-RwGBRM,17
23
- arkindex_client-1.1.1.dist-info/RECORD,,