Skip to content

Commit c439a0c

Browse files
committed
Merge branch 'devel'
2 parents a84c94f + 07de63d commit c439a0c

File tree

4 files changed

+54
-9
lines changed

4 files changed

+54
-9
lines changed

CHANGELOG.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,33 @@
44

55
NOTE: potentially breaking changes are flagged with a 🧨 symbol.
66

7+
## 2.3.0
8+
9+
### Added
10+
11+
- `pyppms.ppms.PpmsConnection()` now takes an optional parameter
12+
`cache_users_only` that will prevent any request but `getuser` from being
13+
stored in the local cache. This is useful in scenarios where frequent requests
14+
to PPMS are being done to fetch booking states and such that would be slowed
15+
down enormously if no user caching was present. Obviously the cached users
16+
need to be refreshed explicitly on a regular basis then. Defaults to `False`
17+
which will result in the same behavior as before.
18+
Please note that several things are implicitly being cached (in memory) during
19+
the lifetime of the `PpmsConnection` object (e.g. the PPMS systems) unless
20+
their corresponding method is being called with `force_refresh=True`.
21+
- `pyppms.ppms.PpmsConnection.update_users()` and
22+
`pyppms.ppms.PpmsConnection.get_users()` now both have an optional parameter
23+
`active_only` (defaulting to `True`) that can be used to also request users
24+
that are marked as *inactive* in PPMS.
25+
26+
### Changed
27+
28+
- `pyppms.ppms.PpmsConnection.get_user()` is only logging a `DEBUG` level
29+
message (before: `ERROR`) in case the requested user can't be found since it
30+
also raises a `KeyError`. This is done to prevent cluttering up the logs of
31+
calling code that might use this method to figure out if an account exists in
32+
PPMS and properly deals with the exception raised.
33+
734
## 2.2.0
835

936
### Added

TODO.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# PyPPMS Development ToDos
22

3+
- explain cache setup for a production scenario (`cache_users_only` and regular
4+
explicit cache refreshes for example)
35
- all methods returning a list of user objects (get_group_users, get_admins, ...) should
46
be refactored to return a dict with those objects instead, having the username
57
('login') as the key.

pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ requires = ["poetry-core>=1.0.0", "poetry-dynamic-versioning"]
3636

3737
[tool.poetry-dynamic-versioning]
3838
enable = true
39-
pattern = "^pyppms-((?P<epoch>\\d+)!)?(?P<base>\\d+(\\.\\d+)*)"
4039

4140
[tool.pytest.ini_options]
4241
addopts = "-rs -vv --cov=pyppms --cov-report html --maxfail=1"

src/pyppms/ppms.py

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class PpmsConnection:
5757
``auth_httpstatus``
5858
"""
5959

60-
def __init__(self, url, api_key, timeout=10, cache=""):
60+
def __init__(self, url, api_key, timeout=10, cache="", cache_users_only=False):
6161
"""Constructor for the PPMS connection object.
6262
6363
Open a connection to the PUMAPI defined in `url` and try to authenticate
@@ -83,6 +83,11 @@ def __init__(self, url, api_key, timeout=10, cache=""):
8383
individual text files. Useful for testing and for speeding up
8484
slow requests like 'getusers'. By default empty, which will result
8585
in no caching being done.
86+
cache_users_only : bool, optional
87+
If set to `True`, only `getuser` requests will be cached on disk.
88+
This can be used in to speed up the slow requests (through the
89+
cache), while everything else will be handled through online
90+
requests. By default `False`.
8691
8792
Raises
8893
------
@@ -101,6 +106,7 @@ def __init__(self, url, api_key, timeout=10, cache=""):
101106
"auth_httpstatus": -1,
102107
}
103108
self.cache_path = cache
109+
self.cache_users_only = cache_users_only
104110

105111
# run in cache-only mode (e.g. for testing or off-line usage) if no API
106112
# key has been specified, skip authentication then:
@@ -241,6 +247,11 @@ def __interception_path(self, req_data, create_dir=False):
241247
request (except credentials like 'apikey').
242248
"""
243249
action = req_data["action"]
250+
251+
if self.cache_users_only and action != "getuser":
252+
LOG.debug(f"NOT caching '{action}' (cache_users_only is set)")
253+
return None
254+
244255
intercept_dir = os.path.join(self.cache_path, action)
245256
if create_dir and not os.path.exists(intercept_dir): # pragma: no cover
246257
try:
@@ -300,7 +311,7 @@ def __init__(self, text, status_code):
300311
raise LookupError("No cache path configured")
301312

302313
intercept_file = self.__interception_path(req_data, create_dir=False)
303-
if not os.path.exists(intercept_file): # pragma: no cover
314+
if not intercept_file or not os.path.exists(intercept_file): # pragma: no cover
304315
raise LookupError(f"No cache hit for [{intercept_file}]")
305316

306317
with open(intercept_file, "r", encoding="utf-8") as infile:
@@ -563,7 +574,7 @@ def get_running_sheet(self, core_facility_ref, date, ignore_uncached_users=False
563574
similar. Note that only the date part is relevant, time will be ignored.
564575
ignore_uncached_users : bool, optional
565576
If set to `True` any booking for a user that is not present in the instance
566-
attribuge `fullname_mapping` will be ignored in the resulting list.
577+
attribute `fullname_mapping` will be ignored in the resulting list.
567578
568579
Returns
569580
-------
@@ -743,7 +754,7 @@ def get_user(self, login_name, skip_cache=False):
743754

744755
if not response.text:
745756
msg = f"User [{login_name}] is unknown to PPMS"
746-
LOG.error(msg)
757+
LOG.debug(msg)
747758
raise KeyError(msg)
748759

749760
user = PpmsUser(response.text)
@@ -871,14 +882,17 @@ def get_user_ids(self, active=False):
871882
LOG.debug(", ".join(users))
872883
return users
873884

874-
def get_users(self, force_refresh=False):
885+
def get_users(self, force_refresh=False, active_only=True):
875886
"""Get user objects for all (or cached) PPMS users.
876887
877888
Parameters
878889
----------
879890
force_refresh : bool, optional
880891
Re-request information from PPMS even if user details have been
881892
cached locally before, by default False.
893+
active_only : bool, optional
894+
If set to `False` also "inactive" users will be fetched from PPMS,
895+
by default `True`.
882896
883897
Returns
884898
-------
@@ -888,7 +902,7 @@ def get_users(self, force_refresh=False):
888902
if self.users and not force_refresh:
889903
LOG.debug("Using cached details for %s users", len(self.users))
890904
else:
891-
self.update_users()
905+
self.update_users(active_only=active_only)
892906

893907
return self.users
894908

@@ -1185,7 +1199,7 @@ def update_systems(self):
11851199

11861200
self.systems = systems
11871201

1188-
def update_users(self, user_ids=[]):
1202+
def update_users(self, user_ids=[], active_only=True):
11891203
"""Update cached details for a list of users from PPMS.
11901204
11911205
Get the user details on a list of users (or all active ones) from PPMS and store
@@ -1199,9 +1213,12 @@ def update_users(self, user_ids=[]):
11991213
user_ids : list(str), optional
12001214
A list of user IDs (login names) to request the cache for, by
12011215
default [] which will result in all *active* users to be requested.
1216+
active_only : bool, optional
1217+
If set to `False` also "inactive" users will be fetched from PPMS,
1218+
by default `True`.
12021219
"""
12031220
if not user_ids:
1204-
user_ids = self.get_user_ids(active=True)
1221+
user_ids = self.get_user_ids(active=active_only)
12051222

12061223
LOG.debug("Updating details on %s users", len(user_ids))
12071224
for user_id in user_ids:

0 commit comments

Comments
 (0)