@@ -40,57 +40,70 @@ python -m pytest
4040
4141## Package Layout
4242
43- - ` glpi_python_client.__init__ ` exposes the public import surface.
44- - ` glpi_python_client.clients.api_v2_client.GlpiClient ` owns synchronous API
45- configuration, authentication, context-manager cleanup, and the small
46- user/location/document provisioning surface.
47- - ` glpi_python_client.clients.async_api_v2_client.AsyncGlpiClient ` owns the
48- matching awaitable client surface and keeps blocking requests behind
49- ` asyncio.to_thread() ` boundaries.
50- - ` glpi_python_client.clients.v2 ` contains the internal v2 implementation
51- packages.
52- - ` glpi_python_client.clients.v2.common ` holds reusable setup, endpoint,
53- request, pagination, payload, filter, and error helpers shared by both
54- execution models.
55- - ` glpi_python_client.clients.v2.sync ` contains the synchronous endpoint mixins:
56- ` transport ` , ` tickets ` , ` timeline ` , ` documents ` , ` team ` , and ` directory ` .
57- ` sync.api ` assembles those mixins.
58- - ` glpi_python_client.clients.v2.async_ ` contains the matching asynchronous
59- endpoint mixins and keeps ` asyncio.to_thread() ` at the blocking request and
60- v1-session boundaries. ` async_.api ` assembles those mixins.
61- - ` glpi_python_client.clients._shared ` is a compatibility module that re-exports
62- the scoped v2 helper modules for older internal imports.
63- - ` glpi_python_client.clients.api_v1_session ` contains the legacy v1 session
64- used for document operations.
65- - ` glpi_python_client.models ` contains typed request and response models.
66- - ` glpi_python_client.content.records ` is a compatibility package for raw GLPI
67- payload conversion.
68- - ` glpi_python_client.content.records.core ` contains shared normalization,
69- scalar coercion, nested-reference parsing, and timeline document-link
70- helpers.
71- - ` glpi_python_client.content.records.parsers ` contains model-specific parsers
72- for tickets, timeline items, documents, team members, users, and locations.
43+ - ` glpi_python_client.__init__ ` exposes the public import surface,
44+ including both client classes and the Pydantic models.
45+ - ` glpi_python_client.clients.sync_client.GlpiClient ` is the
46+ synchronous, blocking client. It is the single source of truth for
47+ endpoint behaviour: each public method lives on one of the sync
48+ endpoint mixins under ` glpi_python_client.clients.api.* ` and
49+ ` glpi_python_client.clients.custom.* ` .
50+ - ` glpi_python_client.clients.async_client.AsyncGlpiClient ` is the
51+ asynchronous facade. It inherits the same endpoint mixins and uses
52+ ` glpi_python_client.clients.commons._async_bridge.AsyncBridge ` to wrap
53+ every inherited public sync method into a coroutine dispatched on a
54+ worker thread (` asyncio.to_thread ` by default, or a caller-supplied
55+ ` concurrent.futures.Executor ` ).
56+ - ` glpi_python_client.clients.commons ` holds the reusable building
57+ blocks shared by every endpoint mixin: configuration helpers
58+ (` _config ` ), constants (` _constants ` ), errors (` _errors ` ), filters
59+ (` _filters ` ), HTTP helpers (` _http ` ), payload builders (` _payloads ` ),
60+ the synchronous ` TransportMixin ` (` _transport ` ), and the
61+ ` AsyncBridge ` (` _async_bridge ` ). A shared ` threading.Lock ` in the
62+ transport serialises OAuth token acquisition so concurrent
63+ ` asyncio.gather ` fan-outs on the async client cannot race.
64+ - ` glpi_python_client.clients.api.* ` contains the contract-aligned
65+ synchronous endpoint mixins, grouped by GLPI subtree (administration,
66+ assistance, assistance/timeline, dropdowns, management).
67+ - ` glpi_python_client.clients.custom ` contains custom helpers built on
68+ top of the API mixins. Each helper has a synchronous implementation
69+ (` _ticket_context.py ` , ` _statistics.py ` ) plus an optional async
70+ override (` _ticket_context_async.py ` , ` _statistics_async.py ` ) that
71+ fans the underlying calls out concurrently with ` asyncio.gather ` .
72+ - ` glpi_python_client.auth._v1_session ` contains the legacy v1
73+ session used for binary document uploads.
74+ - ` glpi_python_client.models ` contains typed request and response
75+ models.
76+ - ` glpi_python_client.content ` handles HTML/Markdown conversion for
77+ ticket descriptions, followups, tasks, and solutions.
78+ - ` glpi_python_client.testing ` exposes ` make_client ` and
79+ ` make_async_client ` factories that produce in-memory clients with no
80+ real HTTP plumbing for downstream test suites.
7381- ` docs ` contains the Read the Docs/Sphinx documentation source.
74- - ` skills ` contains contributor-facing Agent Skills for repository workflows.
75- The source distribution includes them for source consumers and contributors,
76- but the wheel still installs only the ` glpi_python_client ` runtime package.
82+ - ` skills ` contains contributor-facing Agent Skills for repository
83+ workflows. The source distribution includes them for source consumers
84+ and contributors, but the wheel still installs only the
85+ ` glpi_python_client ` runtime package.
7786
7887## Adding Endpoints
7988
80891 . Add or extend a model in ` glpi_python_client.models ` .
81- 2 . Add response parsing in the matching
82- ` glpi_python_client.content.records.parsers ` module when the endpoint returns
83- structured data, and put shared parsing helpers in
84- ` glpi_python_client.content.records.core ` only when multiple parsers need
85- them.
86- 3 . Add the client method in the matching
87- ` glpi_python_client.clients.v2.sync ` module and the matching
88- ` glpi_python_client.clients.v2.async_ ` module when applicable.
89- 4 . Put reusable endpoint names, payload builders, response handling, or
90- pagination logic in the focused ` glpi_python_client.clients.v2.common `
91- helper module named for that responsibility.
92- 5 . Add tests for payload serialization, response parsing, and client behavior.
93- 6 . Document the new workflow in ` docs/usage.md ` or the README.
90+ 2 . Add the client method on the matching ** synchronous** endpoint mixin
91+ under ` glpi_python_client.clients.api.* ` (or
92+ ` glpi_python_client.clients.custom.* ` for derived helpers). The
93+ async client picks the new method up automatically through the
94+ ` AsyncBridge ` — do not duplicate the method on a parallel async
95+ mixin unless you genuinely need concurrent fan-out (` asyncio.gather ` )
96+ inside the method body.
97+ 3 . Put reusable endpoint names, payload builders, response handling, or
98+ pagination logic in the focused
99+ ` glpi_python_client.clients.commons ` helper module named for that
100+ responsibility.
101+ 4 . Add unit tests for payload serialization, response parsing, and
102+ client behavior. The parity test in
103+ ` glpi_python_client/clients/tests/test_parity.py ` will fail if the
104+ sync and async surfaces diverge.
105+ 5 . Document the new workflow in ` docs/user_guide.rst ` or the README.
94106
95- Keep organization-specific defaults outside the package core. Applications can
96- map their own entities, profiles, and categories before calling the client.
107+ Keep organization-specific defaults outside the package core.
108+ Applications can map their own entities, profiles, and categories
109+ before calling the client.
0 commit comments