Skip to content

Commit 4c86b2d

Browse files
authored
Allow optional "/" in Doctype syntax (#50)
Now it's allowed to write instead of "*/*/*" the syntax "/*/*/*" and all variations of it. It's the same, but helps to avoid accidental errors
1 parent 7a74e13 commit 4c86b2d

4 files changed

Lines changed: 46 additions & 25 deletions

File tree

changelog.d/50.feature.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Allow optional slash in Doctype syntax.
2+
Now it's allowed to write instead of ``"*/*/*"`` the syntax ``"/*/*/*"`` and all variations of it. It's the same, but helps to avoid accidental errors.

docs/source/reference/_autoapi/docbuild/models/doctype/Doctype.rst

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,19 @@ docbuild.models.doctype.Doctype
1111

1212
A "doctype" that comprises of a product, docset, lifecycle, and language.
1313

14+
The format has the following syntax:
15+
16+
.. code-block:: text
17+
18+
[/]?[PRODUCT]/[DOCSETS][@LIFECYCLES]/LANGS
19+
20+
The placeholders mean the following:
21+
22+
* ``PRODUCT``: a lowercase acronym of a SUSE product, e.g. ``sles``
23+
* ``DOCSETS``: one or more docsets of the mentioned product, separated by comma
24+
* ``LIFECYCLES``: one or more lifecycles, separated by comma or pipe
25+
* ``LANGS``: one or more languages, separated by comma
26+
1427
>>> doctype = Doctype.from_str("sles/15-SP6@supported/en-us,de-de")
1528
>>> doctype.product
1629
<Product.sles: 'sles'>
@@ -134,17 +147,6 @@ docbuild.models.doctype.Doctype
134147

135148
Parse a string that adheres to the doctype format.
136149

137-
The format has the following syntax::
138-
139-
[PRODUCT]/[DOCSETS][@LIFECYCLES]/LANGS
140-
141-
Plural means you can have one or more items:
142-
143-
* ``PRODUCT``: a lowercase acronym of a SUSE product, e.g. ``sles``
144-
* ``DOCSETS``: separated by comma
145-
* ``LIFECYCLES``: separated by comma or pipe
146-
* ``LANGS``: separated by comma
147-
148150

149151

150152
.. py:method:: xpath() -> str

src/docbuild/models/doctype.py

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,19 @@
1515
class Doctype(BaseModel):
1616
"""A "doctype" that comprises of a product, docset, lifecycle, and language.
1717
18+
The format has the following syntax:
19+
20+
.. code-block:: text
21+
22+
[/]?[PRODUCT]/[DOCSETS][@LIFECYCLES]/LANGS
23+
24+
The placeholders mean the following:
25+
26+
* ``PRODUCT``: a lowercase acronym of a SUSE product, e.g. ``sles``
27+
* ``DOCSETS``: one or more docsets of the mentioned product, separated by comma
28+
* ``LIFECYCLES``: one or more lifecycles, separated by comma or pipe
29+
* ``LANGS``: one or more languages, separated by comma
30+
1831
>>> doctype = Doctype.from_str("sles/15-SP6@supported/en-us,de-de")
1932
>>> doctype.product
2033
<Product.sles: 'sles'>
@@ -80,7 +93,7 @@ class Doctype(BaseModel):
8093
# This leads to None in the result if that group isn't matched
8194
_DOCTYPE_REGEX: ClassVar[Pattern] = re.compile(
8295
r'^' # start
83-
r'(?:([^/@]+|\*))?' # optional product (group 1)
96+
r'(?:/?([^/@]+|\*))?' # optional product (group 1)
8497
r'/(?:([^/@]+|\*))?' # optional docset (group 2)
8598
r'(?:@([a-z]+(?:[,|][a-z]+)*))?' # optional lifecycle (group 3)
8699
r'/(\*|[\w-]+(?:,[\w-]+)*)$', # required langs (group 4)
@@ -198,19 +211,7 @@ def coerce_langs(cls, value: str | list[str | LanguageCode]) -> list[LanguageCod
198211

199212
@classmethod
200213
def from_str(cls, doctype_str: str) -> Self:
201-
"""Parse a string that adheres to the doctype format.
202-
203-
The format has the following syntax::
204-
205-
[PRODUCT]/[DOCSETS][@LIFECYCLES]/LANGS
206-
207-
Plural means you can have one or more items:
208-
209-
* ``PRODUCT``: a lowercase acronym of a SUSE product, e.g. ``sles``
210-
* ``DOCSETS``: separated by comma
211-
* ``LIFECYCLES``: separated by comma or pipe
212-
* ``LANGS``: separated by comma
213-
"""
214+
"""Parse a string that adheres to the doctype format."""
214215
match = cls._DOCTYPE_REGEX.match(doctype_str)
215216

216217
if not match:

tests/models/test_doctype.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ def test_multiplestrings_langs_in_doctype():
8484
'//en-us',
8585
(Product.ALL, ['*'], LifecycleFlag.unknown, [LanguageCode('en-us')]),
8686
),
87+
(
88+
'/*/*/en-us',
89+
(Product.ALL, ['*'], LifecycleFlag.unknown, [LanguageCode('en-us')]),
90+
),
8791
(
8892
'*//en-us',
8993
(Product.ALL, ['*'], LifecycleFlag.unknown, [LanguageCode('en-us')]),
@@ -108,6 +112,18 @@ def test_multiplestrings_langs_in_doctype():
108112
'sles/*@beta/en-us',
109113
(Product.sles, ['*'], LifecycleFlag.beta, [LanguageCode('en-us')]),
110114
),
115+
(
116+
'/sles/*@beta/en-us',
117+
(Product.sles, ['*'], LifecycleFlag.beta, [LanguageCode('en-us')]),
118+
),
119+
(
120+
'/*/*@supported/*',
121+
(Product.ALL, ['*'], LifecycleFlag.supported, [LanguageCode('*')]),
122+
),
123+
(
124+
'/*/*/*',
125+
(Product.ALL, ['*'], LifecycleFlag.unknown, [LanguageCode('*')]),
126+
),
111127
],
112128
)
113129
def test_valid_string_from_string(string, expected):

0 commit comments

Comments
 (0)