Skip to content

Commit 0ed22d6

Browse files
committed
Handle errors more gracefully
Problem: Unclear error display when an illegal_url or bearer token is used. Solution: URL with trailing slash will immediately raise an exception. Illegal client_id and secret will generate an auth token that is None and this will raise an exception on first use. Logger handling is now fully documented with examples. Docs generation fixed (spelling plugin was preventing generation of html) Archivist unittests split into smaller files as original exceeded 1000 lines. Signed-off-by: Paul Hewlett <[email protected]>
1 parent 4ce0587 commit 0ed22d6

File tree

15 files changed

+680
-532
lines changed

15 files changed

+680
-532
lines changed

README.rst

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,6 +337,26 @@ A recommended minimum configuration would be:
337337
},
338338
})
339339
340+
For convenience this has been encapsulated in a convenience function :code:`set_logger`
341+
which should be called before anything else:
342+
343+
.. code:: python
344+
345+
from archivist.logger import set_logger
346+
from archivist.archivist import Archivist
347+
348+
set_logger("DEBUG")
349+
client_id = getenv("ARCHIVIST_CLIENT_ID")
350+
client_secret_file = getenv("ARCHIVIST_CLIENT_SECRET_FILENAME")
351+
with open(client_secret_file, mode="r", encoding="utf-8") as tokenfile:
352+
client_secret = tokenfile.read().strip()
353+
354+
arch = Archivist(
355+
"https://app.rkvst.io",
356+
(client_id, client_secret),
357+
max_time=300,
358+
)
359+
340360
Development
341361
===========
342362

archivist/archivist.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
_parse_response,
5353
ArchivistBadFieldError,
5454
ArchivistDuplicateError,
55+
ArchivistError,
5556
ArchivistHeaderError,
5657
ArchivistNotFoundError,
5758
)
@@ -131,6 +132,9 @@ def __init__(
131132
self._client_secret = None
132133

133134
self._expires_at = 0
135+
if url.endswith("/"):
136+
raise ArchivistError(f"URL {url} has trailing /")
137+
134138
self._url = url
135139
self._verify = verify
136140
self._response_ring_buffer = deque(maxlen=self.RING_BUFFER_MAX_LEN)
@@ -187,7 +191,9 @@ def auth(self) -> str:
187191
"""str: authorization token."""
188192
if self._client_id is not None and self._expires_at < time():
189193
apptoken = self.appidp.token(self._client_id, self._client_secret) # type: ignore
190-
self._auth = apptoken["access_token"]
194+
self._auth = apptoken.get("access_token")
195+
if self._auth is None:
196+
raise ArchivistError("Auth token from client id,secret is invalid")
191197
self._expires_at = time() + apptoken["expires_in"] - 10 # fudge factor
192198
LOGGER.info("Refresh token")
193199

archivist/errors.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,8 @@ def __description(response):
115115
return f"{__identity(response)} not found ({status_code})"
116116

117117
text = response.text or ""
118-
return f"{text} ({status_code})"
118+
url = getattr(response, "url", "")
119+
return f"{url}: {text} ({status_code})"
119120

120121

121122
def _parse_response(response):

archivist/logger.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77
urllib3 package.
88
99
URL: https://docs.djangoproject.com/en/3.2/topics/logging/
10-
11-
This code is not used directly by this package... but is used in unittests (if enabled)
1210
"""
1311

1412
# pylint: disable=missing-docstring
@@ -20,6 +18,13 @@
2018

2119

2220
def set_logger(level):
21+
"""
22+
Set logging level
23+
24+
Args:
25+
level (str): Either INFO or DEBUG
26+
27+
"""
2328
config.dictConfig(
2429
{
2530
"version": 1,

docs/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ help:
1818
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
1919
%: Makefile
2020
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
21+
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(O)

docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
timestamp
2828
errors
29+
logger
2930
proof_mechanism
3031

3132
Indices and tables

docs/logger.rst

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
2+
.. _loggerref:
3+
4+
Logger
5+
--------------
6+
7+
The first (optional) call from the archivist package is to set the logger.
8+
9+
.. code:: python
10+
11+
from archivist.logger import set_logger
12+
from archivist.archivist import Archivist
13+
14+
set_logger("DEBUG")
15+
client_id = getenv("ARCHIVIST_CLIENT_ID")
16+
client_secret_file = getenv("ARCHIVIST_CLIENT_SECRET_FILENAME")
17+
with open(client_secret_file, mode="r", encoding="utf-8") as tokenfile:
18+
client_secret = tokenfile.read().strip()
19+
20+
arch = Archivist(
21+
"https://app.rkvst.io",
22+
(client_id, client_secret),
23+
max_time=300,
24+
)
25+
26+
27+
.. automodule:: archivist.logger
28+
:members:
29+

examples/create_asset.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from os import getenv
1010

1111
from archivist.archivist import Archivist
12+
from archivist.logger import set_logger
1213
from archivist.proof_mechanism import ProofMechanism
1314
from archivist.utils import get_auth
1415

@@ -74,6 +75,10 @@ def main():
7475
create an example archivist connection and create an asset.
7576
7677
"""
78+
# optional call to set the logger level for all subsystems. The argumant can
79+
# be either "INFO" or "DEBUG". For more sophisticated logging control see the
80+
# documentation.
81+
set_logger("INFO")
7782

7883
# client id and client secret is obtained from the appidp endpoint - see the
7984
# application registrations example code in examples/applications_registration.py

examples/create_event.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from os import getenv
1212

1313
from archivist.archivist import Archivist
14+
from archivist.logger import set_logger
1415

1516

1617
def create_event(arch, asset):
@@ -108,6 +109,11 @@ def main():
108109
the asset and fetch the event.
109110
110111
"""
112+
# optional call to set the logger level for all subsystems. The argumant can
113+
# be either "INFO" or "DEBUG". For more sophisticated logging control see the
114+
# documentation.
115+
set_logger("DEBUG")
116+
111117
# client id and client secret is obtained from the appidp endpoint - see the
112118
# application registrations example code in examples/applications_registration.py
113119
#

functests/execattachments.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
# pylint: disable=unused-variable
2323

2424

25-
class TestAttachmentstCreate(TestCase):
25+
class TestAttachmentsCreate(TestCase):
2626
"""
2727
Test Archivist Attachment Create method
2828
"""

0 commit comments

Comments
 (0)