python-alfresco-api 1.2.0__py3-none-any.whl → 1.2.1__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.
@@ -36,7 +36,12 @@ from .clients.conversion_utils import (
36
36
  # Import raw_clients to ensure they get packaged
37
37
  from . import raw_clients
38
38
 
39
- __version__ = "1.2.0"
39
+ # Tolerate Alfresco responses that omit the (spec-required) UserInfo.displayName for JIT /
40
+ # OAuth2 service-account users (defaults displayName -> id). See _compat.py.
41
+ from ._compat import install_shims as _install_shims
42
+ _install_shims()
43
+
44
+ __version__ = "1.2.1"
40
45
  __all__ = [
41
46
  # Factory & utilities
42
47
  "ClientFactory",
@@ -0,0 +1,55 @@
1
+ """Runtime compatibility shims for Alfresco responses that deviate from the OpenAPI spec.
2
+
3
+ Alfresco marks ``UserInfo.displayName`` as *required*, but omits it for JIT / OAuth2 service-account
4
+ users (e.g. ``service-account-*`` produced by the client-credentials grant). That makes the generated
5
+ ``UserInfo.from_dict`` raise ``KeyError('displayName')`` while parsing ``createdByUser`` /
6
+ ``modifiedByUser`` / ``owner`` on node responses.
7
+
8
+ This shim defaults ``displayName`` to ``id`` when it is absent, so parsing never crashes. It lives
9
+ outside ``raw_clients/`` so it survives client re-generation.
10
+
11
+ Scope (verified across all 7 generated raw clients): the ``UserInfo`` model — which is what
12
+ createdBy/modifiedBy/owner deserialize to — exists **only** in the core and search clients; the other
13
+ five (auth, discovery, model, search_sql, workflow) have no required-``displayName`` models. Core's
14
+ group models (``Group`` / ``GroupMember`` / ``GroupBodyCreate`` / ``GroupBodyUpdate``) also mark
15
+ ``displayName`` required, but groups always carry a display name and those models have *other* required
16
+ fields (e.g. ``Group.isRoot``), so they are not the JIT/service-account case and are left alone.
17
+ """
18
+
19
+ from importlib import import_module
20
+
21
+ # UserInfo covers every user reference (createdByUser / modifiedByUser / owner), in the two clients
22
+ # that define it.
23
+ _MODELS = (
24
+ ("python_alfresco_api.raw_clients.alfresco_core_client.core_client.models.user_info", "UserInfo"),
25
+ ("python_alfresco_api.raw_clients.alfresco_search_client.search_client.models.user_info", "UserInfo"),
26
+ )
27
+
28
+
29
+ def _patch_from_dict(cls) -> None:
30
+ if getattr(cls, "_display_name_shim_installed", False):
31
+ return
32
+ _orig_from_dict = cls.from_dict # bound classmethod
33
+
34
+ def _from_dict(src_dict, _orig=_orig_from_dict):
35
+ d = dict(src_dict)
36
+ if "displayName" not in d and "id" in d:
37
+ # Alfresco omitted the (spec-required) display name; fall back to the id.
38
+ d["displayName"] = d["id"]
39
+ return _orig(d)
40
+
41
+ cls.from_dict = staticmethod(_from_dict)
42
+ cls._display_name_shim_installed = True
43
+
44
+
45
+ def install_shims() -> None:
46
+ """Patch ``UserInfo.from_dict`` in the raw clients to tolerate a missing ``displayName``.
47
+
48
+ Idempotent — safe to call more than once.
49
+ """
50
+ for mod_path, cls_name in _MODELS:
51
+ try:
52
+ _patch_from_dict(getattr(import_module(mod_path), cls_name))
53
+ except Exception:
54
+ # Model not present in this build/layout — skip quietly.
55
+ continue
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-alfresco-api
3
- Version: 1.2.0
3
+ Version: 1.2.1
4
4
  Summary: Python Client for all Alfresco Content Services REST APIs, with Pydantic v2 Models, and Event Support
5
5
  Project-URL: Homepage, https://github.com/stevereiner/python-alfresco-api
6
6
  Project-URL: Repository, https://github.com/stevereiner/python-alfresco-api
@@ -325,6 +325,8 @@ master_client = factory.create_master_client()
325
325
 
326
326
  A provided access token that has already expired is detected from its JWT `exp` claim and auto-refreshed when a `refresh_token` + `token_endpoint` are supplied. `ALFRESCO_OAUTH2_*` environment variables are also read when `load_env=True`.
327
327
 
328
+ > **Service account vs. user token.** `client_credentials` authenticates as the client's *service account* (e.g. `service-account-<client-id>`) — a just-in-time Alfresco user with **no display name** and only **default permissions** (not an admin, and not the same as Alfresco's `guest`). For content operations prefer a **user token** (obtain one via a password grant, then pass `access_token`/`refresh_token`) so operations run as a real user with a display name and that user's ACLs. As of **1.2.1** the client also tolerates a missing `displayName` (defaults it to the user id), so the service-account path no longer raises `KeyError`.
329
+
328
330
  ### Sync and Async Usage
329
331
 
330
332
  ```python
@@ -1,4 +1,5 @@
1
- python_alfresco_api/__init__.py,sha256=HWTClg2gAvbZWWaYeJI6uX40QNG7a0ZgSzYsQ9VLVrA,1757
1
+ python_alfresco_api/__init__.py,sha256=PGcKjRKCcSuamQ20gx5AkghQIzda1YzchOBgPB-lahQ,2001
2
+ python_alfresco_api/_compat.py,sha256=liuk6giBNWxS6Qnk4rvzCi-skJohJM9BcfEwLcYFv9w,2541
2
3
  python_alfresco_api/auth_util.py,sha256=pp9Ig_YGIjfS7SwSrjnJGQ0AmhWNx5AHM4B5hZ6_uyY,35333
3
4
  python_alfresco_api/client_factory.py,sha256=-fTIUdT_aPCCH_d9A2RJU7554_yNaUo-ZsZMkxR5588,11458
4
5
  python_alfresco_api/clients/__init__.py,sha256=3_SHjsn1iCht_kEmXDFzPNOZlp-EvH3BajmuzTmUdkI,1877
@@ -768,7 +769,7 @@ python_alfresco_api/utils/node_utils_highlevel.py,sha256=Xfebn8rv958SkMcaaSRS-oa
768
769
  python_alfresco_api/utils/search_utils.py,sha256=0TJGTWtVWb6I-0QNCYyrNfd714CwKl9dZcw6R7L-aR8,15634
769
770
  python_alfresco_api/utils/version_utils.py,sha256=3NIhLyM3rkaH-fm4c-PH8MTIMJmwGKg9KiSBEc8FBJc,11462
770
771
  python_alfresco_api/utils/version_utils_highlevel.py,sha256=xa2O6xZfNN9Lx6iHKGnvHGW7watnu8rPTPlcsZUpdis,19079
771
- python_alfresco_api-1.2.0.dist-info/METADATA,sha256=htoyR5ylbqELYheJwIZAm3TnpLhmici1LJ-8V3ir5as,28860
772
- python_alfresco_api-1.2.0.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
773
- python_alfresco_api-1.2.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
774
- python_alfresco_api-1.2.0.dist-info/RECORD,,
772
+ python_alfresco_api-1.2.1.dist-info/METADATA,sha256=45VOzf7hjpjF2ReK5CDaC9oAdP82bVaewhGXDxzGFc4,29505
773
+ python_alfresco_api-1.2.1.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
774
+ python_alfresco_api-1.2.1.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
775
+ python_alfresco_api-1.2.1.dist-info/RECORD,,