Skip to content

Commit b17985a

Browse files
author
Francesco Faraone
committed
Work in progress
1 parent 2be99fd commit b17985a

File tree

6 files changed

+132
-205
lines changed

6 files changed

+132
-205
lines changed

cnct/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# This file is part of the Ingram Micro Cloud Blue Connect connect-fluent-client.
44
# Copyright (c) 2019-2020 Ingram Micro. All Rights Reserved.
55

6-
from cnct.client.exceptions import ClientError, NotFoundError # noqa
6+
from cnct.client.exceptions import ClientError # noqa
77
from cnct.client.fluent import ConnectClient # noqa
88
from cnct.client.version import get_version # noqa
99
from cnct.rql import R # noqa

cnct/client/exceptions.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
from http import HTTPStatus
22

33

4-
class NotFoundError(AttributeError):
5-
pass
6-
7-
84
class ClientError(Exception):
95
def __init__(self, message=None, status_code=None, error_code=None, errors=None):
106
self.message = message

cnct/client/fluent.py

Lines changed: 41 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
from json.decoder import JSONDecodeError
2-
from keyword import iskeyword
32

43
import requests
54
from requests.exceptions import RequestException
65

76
from cnct.client.constants import CONNECT_ENDPOINT_URL, CONNECT_SPECS_URL
8-
from cnct.client.exceptions import ClientError, NotFoundError
7+
from cnct.client.exceptions import ClientError
98
from cnct.client.models import Collection, NS
109
from cnct.client.utils import get_headers
11-
from cnct.help import DefaultFormatter
12-
from cnct.specs.parser import parse
10+
# from cnct.help import DefaultFormatter
11+
from cnct.openapi import OpenAPISpecs
12+
# from cnct.specs.parser import parse
1313

1414

1515
class ConnectClient:
@@ -19,11 +19,12 @@ class ConnectClient:
1919
def __init__(
2020
self,
2121
api_key,
22-
endpoint=CONNECT_ENDPOINT_URL,
23-
specs_location=CONNECT_SPECS_URL,
24-
default_headers={},
22+
endpoint=None,
23+
use_specs=True,
24+
specs_location=None,
25+
validate_calls=True,
26+
default_headers=None,
2527
default_limit=100,
26-
help_formatter=DefaultFormatter(),
2728
):
2829
"""
2930
Create a new instance of the ConnectClient.
@@ -40,65 +41,40 @@ def __init__(
4041
if default_headers and 'Authorization' in default_headers:
4142
raise ValueError('`default_headers` cannot contains `Authorization`')
4243

43-
self.endpoint = endpoint
44+
self.endpoint = endpoint or CONNECT_ENDPOINT_URL
4445
self.api_key = api_key
45-
self.default_headers = default_headers
46-
self.specs_location = specs_location
47-
self.specs = parse(self.specs_location) if self.specs_location else None
46+
self.default_headers = default_headers or {}
47+
self._use_specs = use_specs
48+
self._validate_calls = validate_calls
49+
self.specs_location = specs_location or CONNECT_SPECS_URL
50+
self.specs = None
51+
if self._use_specs:
52+
self.specs = OpenAPISpecs(self.specs_location)
4853
self.response = None
49-
self._help_formatter = help_formatter
54+
# self._help_formatter = help_formatter
5055

5156
def __getattr__(self, name):
5257
"""
53-
Returns a NS or a Collection object called ``name``.
58+
Returns a collection object called ``name``.
5459
55-
:param name: The name of the NS or Collection to retrieve.
60+
:param name: The name of the collection to retrieve.
5661
:type name: str
57-
:raises AttributeError: If OpenAPI specs are not avaliable.
58-
:raises AttributeError: If the name does not exist.
59-
:return: a Collection or a NS called ``name``.
60-
:rtype: Collection, NS
62+
:return: a collection called ``name``.
63+
:rtype: Collection
6164
"""
62-
if not self.specs:
63-
raise AttributeError(
64-
'No specs available. Use `ns` '
65-
'or `collection` methods instead.'
66-
)
6765
if '_' in name:
6866
name = name.replace('_', '-')
69-
if name in self.specs.namespaces:
70-
return self.ns(name)
71-
if name in self.specs.collections:
72-
return self.collection(name)
73-
raise AttributeError('Unable to resolve {}.'.format(name))
74-
75-
def __dir__(self):
76-
"""
77-
Return a list of attributes defined for this ConnectClient instance.
78-
The returned list includes the names of the root namespaces and collections.
67+
return self.collection(name)
7968

80-
:return: List of attributes.
81-
:rtype: list
82-
"""
83-
if not self.specs:
84-
return super().__dir__()
85-
ns = list(self.specs.namespaces.keys())
86-
cl = list(self.specs.collections.keys())
87-
additional_names = []
88-
for name in cl + ns:
89-
if '-' in name:
90-
name = name.replace('-', '_')
91-
if name.isidentifier() and not iskeyword(name):
92-
additional_names.append(name)
93-
return sorted(super().__dir__() + additional_names)
69+
def __call__(self, name):
70+
return self.ns(name)
9471

9572
def ns(self, name):
9673
"""
9774
Returns the namespace called ``name``.
9875
9976
:param name: The name of the namespace to access.
10077
:type name: str
101-
:raises NotFoundError: If a namespace with name ``name`` does not exist.
10278
:return: The namespace called ``name``.
10379
:rtype: NS
10480
"""
@@ -108,19 +84,14 @@ def ns(self, name):
10884
if not name:
10985
raise ValueError('`name` must not be blank.')
11086

111-
if not self.specs:
112-
return NS(self, f'{self.endpoint}/{name}',)
113-
if name in self.specs.namespaces:
114-
return NS(self, f'{self.endpoint}/{name}', self.specs.namespaces[name])
115-
raise NotFoundError(f'The namespace {name} does not exist.')
87+
return NS(self, name)
11688

11789
def collection(self, name):
11890
"""
11991
Returns the collection called ``name``.
12092
12193
:param name: The name of the collection to access.
12294
:type name: str
123-
:raises NotFoundError: If a collection with name ``name`` does not exist.
12495
:return: The collection called ``name``.
12596
:rtype: Collection
12697
"""
@@ -130,18 +101,10 @@ def collection(self, name):
130101
if not name:
131102
raise ValueError('`name` must not be blank.')
132103

133-
if not self.specs:
134-
return Collection(
135-
self,
136-
f'{self.endpoint}/{name}',
137-
)
138-
if name in self.specs.collections:
139-
return Collection(
140-
self,
141-
f'{self.endpoint}/{name}',
142-
self.specs.collections[name],
143-
)
144-
raise NotFoundError(f'The collection {name} does not exist.')
104+
return Collection(
105+
self,
106+
name,
107+
)
145108

146109
def get(self, url, **kwargs):
147110
return self.execute('get', url, **kwargs)
@@ -165,7 +128,17 @@ def update(self, url, payload=None, **kwargs):
165128
def delete(self, url, **kwargs):
166129
return self.execute('delete', url, **kwargs)
167130

168-
def execute(self, method, url, **kwargs):
131+
def execute(self, method, path, **kwargs):
132+
if (
133+
self._use_specs
134+
and self._validate_calls
135+
and not self.specs.exists(method, path)
136+
):
137+
# TODO more info, specs version, method etc
138+
raise ClientError(f'The path `{path}` does not exist.')
139+
140+
url = f'{self.endpoint}/{path}'
141+
169142
kwargs = kwargs or {}
170143
if 'headers' in kwargs:
171144
kwargs['headers'].update(get_headers(self.api_key))

0 commit comments

Comments
 (0)