glpi-python-client 0.6.4__py3-none-any.whl → 0.6.5__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.
- glpi_python_client/__init__.py +1 -1
- glpi_python_client/content/conversion.py +59 -0
- glpi_python_client/models/api_schema/management/_document.py +14 -0
- {glpi_python_client-0.6.4.dist-info → glpi_python_client-0.6.5.dist-info}/METADATA +1 -1
- {glpi_python_client-0.6.4.dist-info → glpi_python_client-0.6.5.dist-info}/RECORD +7 -7
- {glpi_python_client-0.6.4.dist-info → glpi_python_client-0.6.5.dist-info}/WHEEL +0 -0
- {glpi_python_client-0.6.4.dist-info → glpi_python_client-0.6.5.dist-info}/licenses/LICENSE +0 -0
glpi_python_client/__init__.py
CHANGED
|
@@ -179,6 +179,30 @@ def _plain_text_html(text: str) -> str:
|
|
|
179
179
|
return "<p>" + "<br>".join(lines) + "</p>"
|
|
180
180
|
|
|
181
181
|
|
|
182
|
+
#: What a browser strips from the front of a URL, and drops from inside one.
|
|
183
|
+
_URL_LEADING = "".join(chr(c) for c in range(0x21))
|
|
184
|
+
_URL_INNER = str.maketrans("", "", "\t\r\n")
|
|
185
|
+
|
|
186
|
+
#: The elements inside which the reader writes no image, so offers none.
|
|
187
|
+
_UNFORMATTED = ("pre", "code", "kbd", "samp")
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def _is_data_uri(src: str) -> bool:
|
|
191
|
+
"""Whether a browser reads ``src`` as a ``data:`` URI.
|
|
192
|
+
|
|
193
|
+
The scheme is case-insensitive, leading C0 controls and spaces are
|
|
194
|
+
stripped, and tabs and line breaks are dropped wherever they are.
|
|
195
|
+
"""
|
|
196
|
+
|
|
197
|
+
return src.lstrip(_URL_LEADING).translate(_URL_INNER).casefold().startswith("data:")
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def _image_id(el: Tag) -> str | None:
|
|
201
|
+
"""The trimmed ``id`` of an element, or ``None`` when it has none."""
|
|
202
|
+
|
|
203
|
+
return str(el.get("id") or "").strip() or None
|
|
204
|
+
|
|
205
|
+
|
|
182
206
|
def _soup(html: str) -> BeautifulSoup:
|
|
183
207
|
"""Parse ``html`` and drop what a browser does not display."""
|
|
184
208
|
|
|
@@ -402,6 +426,12 @@ class Link:
|
|
|
402
426
|
enclosing_href : str or None
|
|
403
427
|
For an ``<img>`` inside a link, that link's ``href``; ``None``
|
|
404
428
|
otherwise. The image is read before the link around it.
|
|
429
|
+
image_id : str or None
|
|
430
|
+
For an ``<img>``, the value of its ``id`` attribute, trimmed, or
|
|
431
|
+
``None`` when it has none or the element is a link. GLPI sets it to
|
|
432
|
+
the tag of the Document it created for an image it has not rewritten
|
|
433
|
+
into a document link, and that Document carries the same value as its
|
|
434
|
+
tag, so a caller can find it.
|
|
405
435
|
"""
|
|
406
436
|
|
|
407
437
|
href: str
|
|
@@ -410,6 +440,7 @@ class Link:
|
|
|
410
440
|
image: bool = False
|
|
411
441
|
document_id: int | None = None
|
|
412
442
|
enclosing_href: str | None = None
|
|
443
|
+
image_id: str | None = None
|
|
413
444
|
|
|
414
445
|
|
|
415
446
|
#: A ``rewrite_link`` callback: called with each link and image a read meets,
|
|
@@ -664,6 +695,7 @@ class _Converter(MarkdownConverter):
|
|
|
664
695
|
enclosing_href=(
|
|
665
696
|
None if around is None else str(around.get("href") or "")
|
|
666
697
|
),
|
|
698
|
+
image_id=_image_id(el),
|
|
667
699
|
)
|
|
668
700
|
)
|
|
669
701
|
if isinstance(answer, str):
|
|
@@ -1021,6 +1053,33 @@ class GlpiContentConverter:
|
|
|
1021
1053
|
document_id = int(values[0])
|
|
1022
1054
|
return document_id if document_id > 0 else None
|
|
1023
1055
|
|
|
1056
|
+
@staticmethod
|
|
1057
|
+
def data_image_ids(html: str) -> tuple[str, ...]:
|
|
1058
|
+
"""Return the ``id`` of every image a body keeps as a ``data:`` URI.
|
|
1059
|
+
|
|
1060
|
+
Each ``<img>`` whose ``src`` a browser reads as a ``data:`` URI and
|
|
1061
|
+
that has a non-empty ``id`` contributes it, in document order and
|
|
1062
|
+
without repeats. The base64 is not decoded. An image inside ``<pre>``,
|
|
1063
|
+
``<code>``, ``<kbd>`` or ``<samp>`` is left out: the reader shows it
|
|
1064
|
+
as no image, so it never offers it to ``rewrite_link`` either.
|
|
1065
|
+
|
|
1066
|
+
GLPI sets a tag on the Documents it creates from an upload or an
|
|
1067
|
+
editor paste, images or not. For an image it has not rewritten into a
|
|
1068
|
+
document link, that tag is the ``id`` of the ``<img>``
|
|
1069
|
+
(:attr:`Link.image_id`, :attr:`GetDocument.tag`). A caller calls this
|
|
1070
|
+
first, to decide whether it needs to read any Document at all.
|
|
1071
|
+
"""
|
|
1072
|
+
|
|
1073
|
+
if "<" not in html:
|
|
1074
|
+
return ()
|
|
1075
|
+
ids = (
|
|
1076
|
+
_image_id(img)
|
|
1077
|
+
for img in _soup(html).find_all("img")
|
|
1078
|
+
if _is_data_uri(str(img.get("src") or ""))
|
|
1079
|
+
and img.find_parent(_UNFORMATTED) is None
|
|
1080
|
+
)
|
|
1081
|
+
return tuple(dict.fromkeys(i for i in ids if i is not None))
|
|
1082
|
+
|
|
1024
1083
|
@staticmethod
|
|
1025
1084
|
def document_image(
|
|
1026
1085
|
document_id: int,
|
|
@@ -61,6 +61,20 @@ class GetDocument(GlpiModel):
|
|
|
61
61
|
mime: str | None = None
|
|
62
62
|
sha1sum: str | None = None
|
|
63
63
|
|
|
64
|
+
@property
|
|
65
|
+
def tag(self) -> str | None:
|
|
66
|
+
"""The tag GLPI gave the Document, or ``None``.
|
|
67
|
+
|
|
68
|
+
GLPI sets a tag on the Documents it creates from an upload or an
|
|
69
|
+
editor paste, images or not. For an image it has not rewritten into
|
|
70
|
+
a document link, it is the ``id`` of the ``<img>`` left in the body
|
|
71
|
+
(see ``GlpiContentConverter.data_image_ids``). Read from
|
|
72
|
+
``extra_payload``; ``None`` when absent, empty or not a string.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
value = self.extra_payload.get("tag")
|
|
76
|
+
return value if isinstance(value, str) and value else None
|
|
77
|
+
|
|
64
78
|
|
|
65
79
|
class PostDocument(GlpiModel):
|
|
66
80
|
"""Request body for ``POST /Management/Document``.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: glpi-python-client
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.5
|
|
4
4
|
Summary: A typed Python client for GLPI ITSM APIs.
|
|
5
5
|
Project-URL: Homepage, https://github.com/baraline/glpi_python_client
|
|
6
6
|
Project-URL: Documentation, https://glpi-python-client.readthedocs.io/en/latest/
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
glpi_python_client/__init__.py,sha256=
|
|
1
|
+
glpi_python_client/__init__.py,sha256=goD0YVtmpFX2_3vXrg-qOCLUgtCYwEj-wFJeP0-UfLk,5630
|
|
2
2
|
glpi_python_client/_errors.py,sha256=Bc9UvlxulbdcGvzZIKXnJCTL78sW78R6EFg50P-1dpY,7151
|
|
3
3
|
glpi_python_client/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
glpi_python_client/rsql.py,sha256=3u3lH3_-F1bvHbVzxALXTDPoHyoMATP1f4QPTar_sEU,8974
|
|
@@ -95,7 +95,7 @@ glpi_python_client/_sync/clients/custom/__init__.py,sha256=sxfGlHVulucP7bacWhUMi
|
|
|
95
95
|
glpi_python_client/_sync/clients/custom/_statistics.py,sha256=xrD5C99ieROJx60iUomBHacQ_49HpgQL4XjnfREUQvs,38616
|
|
96
96
|
glpi_python_client/_sync/clients/custom/_ticket_context.py,sha256=LDUvKNr8VpZonF5bDo8QYYwMEsWmayVU28Ra3GonNmE,3004
|
|
97
97
|
glpi_python_client/content/__init__.py,sha256=TaZPo8WSvVj4U-hSnxhUcqU8JnCKNZYpfQf4pH45aN4,424
|
|
98
|
-
glpi_python_client/content/conversion.py,sha256=
|
|
98
|
+
glpi_python_client/content/conversion.py,sha256=0dxQW0ojSo1KC8zcTFa476KQa1i3sLWzQ8gTEEVslys,45341
|
|
99
99
|
glpi_python_client/models/__init__.py,sha256=CLvk-1A-88114X7HaS9P6KyfovQjCPRX08J56rJaGls,5454
|
|
100
100
|
glpi_python_client/models/_base.py,sha256=pYg69KHuR5TDED5utr4Knr7HncBnLTxXHJZYf6vEUKA,12183
|
|
101
101
|
glpi_python_client/models/api_schema/__init__.py,sha256=yTxUYih1Xy7NUogzD7UKp2b8HyE4wdeC_FCKS6ZRVVM,1176
|
|
@@ -127,7 +127,7 @@ glpi_python_client/models/api_schema/knowledgebase/_revision.py,sha256=KuTb_F85m
|
|
|
127
127
|
glpi_python_client/models/api_schema/management/__init__.py,sha256=z5ntUAXiXXhZCEIsTVaTgJdXbg0ZW24TZctarfAqjr0,987
|
|
128
128
|
glpi_python_client/models/api_schema/management/_contract.py,sha256=m6g__AKWvDQ09xKyUe8RhRS8xE1d1pOBjqOOG-8u6Ck,14045
|
|
129
129
|
glpi_python_client/models/api_schema/management/_contract_cost.py,sha256=Bp2B3bA5u8CE_oBYY70QIUot8jFLCrX_icXZ4kpYqSE,4966
|
|
130
|
-
glpi_python_client/models/api_schema/management/_document.py,sha256=
|
|
130
|
+
glpi_python_client/models/api_schema/management/_document.py,sha256=kiEkTnOydGHjOyAwTbo020Kei4ffkBDj-9m775gLyfw,5200
|
|
131
131
|
glpi_python_client/models/api_schema/management/_document_item.py,sha256=Bu9c9YdhSs5hGZ8dRfRxqS4g7VZ1A3EJtNbDLulKpWA,3113
|
|
132
132
|
glpi_python_client/models/api_schema/plugins/__init__.py,sha256=GA0pr0PeoPOqwjUilrBujh0OqjUfZhzPWgIlgDJcZog,544
|
|
133
133
|
glpi_python_client/models/api_schema/plugins/_fields.py,sha256=Se-12ZDqk_-on_37YF_hRD5S0e0H6zyha3SXI9xb_9Y,6576
|
|
@@ -136,7 +136,7 @@ glpi_python_client/models/custom_schema/_ticket_context.py,sha256=jnlfgho-aDbmA9
|
|
|
136
136
|
glpi_python_client/testing/__init__.py,sha256=iLtUyJjyv3fEhy3PN25NxNTbtqDl3SoHLbNium0Z80U,568
|
|
137
137
|
glpi_python_client/testing/fixtures.py,sha256=HKt6MXHgcmLn4L98pSwp-oGlc9C--_vrABNe5G_iBeg,1286
|
|
138
138
|
glpi_python_client/testing/utils.py,sha256=JyO3w2d-0kYdtC1hEZ2Tu_YjnCz8nUQ_Ck05-1EhsX4,4404
|
|
139
|
-
glpi_python_client-0.6.
|
|
140
|
-
glpi_python_client-0.6.
|
|
141
|
-
glpi_python_client-0.6.
|
|
142
|
-
glpi_python_client-0.6.
|
|
139
|
+
glpi_python_client-0.6.5.dist-info/METADATA,sha256=xKVBulZ8pipAYJLr8FuRcAM1M21XFiM9PGGq3PNMeZE,8234
|
|
140
|
+
glpi_python_client-0.6.5.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
141
|
+
glpi_python_client-0.6.5.dist-info/licenses/LICENSE,sha256=nL8re-TIKkxCoL7OkSBja6EB4NsQR1HoOJgxv_MEhtc,1088
|
|
142
|
+
glpi_python_client-0.6.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|