77from collections .abc import Collection , Mapping , Sequence
88from concurrent .futures import Future
99from pathlib import Path
10- from typing import Any , Literal , Required , TypeAlias , TypedDict
10+ from typing import Any , Literal , Required , TypeAlias , TypedDict , cast
1111
1212import yaml
1313
14- EntrypointType : TypeAlias = Literal ["mkdocs_theme" , "mkdocs_plugin" , "markdown_extension" ]
14+ EntrypointType : TypeAlias = Literal [
15+ "properdocs_theme" , "mkdocs_theme" , "properdocs_plugin" , "mkdocs_plugin" , "markdown_extension"
16+ ]
1517
1618
1719class Project (TypedDict , total = False ):
1820 name : Required [str ]
1921 category : Required [str ]
2022 labels : Collection [str ]
23+ properdocs_theme : str | Collection [str ]
2124 mkdocs_theme : str | Collection [str ]
25+ properdocs_plugin : str | Collection [str ]
2226 mkdocs_plugin : str | Collection [str ]
2327 markdown_extension : str | Collection [str ]
2428 github_id : str
@@ -32,10 +36,10 @@ def _get_as_list(mapping: Project, key: EntrypointType) -> Collection[str]:
3236 return names
3337
3438
35- _kind_to_label : Mapping [EntrypointType , str ] = {
36- "mkdocs_plugin" : "plugin" ,
37- " mkdocs_theme" : "theme" ,
38- "markdown_extension" : "markdown" ,
39+ _kinds_to_label : Mapping [Collection [ EntrypointType ] , str ] = {
40+ ( "mkdocs_plugin" , "properdocs_plugin" ) : "plugin" ,
41+ ( "properdocs_theme" , " mkdocs_theme") : "theme" ,
42+ ( "markdown_extension" ,) : "markdown" ,
3943}
4044
4145config : Mapping [str , Any ] = yaml .safe_load (Path ("projects.yaml" ).read_text (encoding = "utf-8" ))
@@ -101,7 +105,7 @@ def check_install_project(project: Project, install_name: str, errors: list[str]
101105pool = concurrent .futures .ThreadPoolExecutor (4 )
102106
103107# Tracks shadowing: projects earlier in the list take precedence.
104- available : dict [EntrypointType , dict [str , str ]] = {k : {} for k in _kind_to_label }
108+ available : dict [EntrypointType , dict [str , str ]] = {k : {} for keys in _kinds_to_label for k in keys }
105109
106110futures : list [tuple [str , Future [list [str ]]]] = []
107111
@@ -122,30 +126,34 @@ def check_install_project(project: Project, install_name: str, errors: list[str]
122126 if label not in all_labels :
123127 errors .append (f"Unknown label: { label !r} - should be one of: { ', ' .join (all_labels )} " )
124128
125- for kind , label in _kind_to_label .items ():
126- items = _get_as_list (project , kind )
127-
129+ for kinds , label in _kinds_to_label .items ():
128130 if label == "plugin" and "theme" in labels and "plugin" not in labels :
129131 pass
130- elif (label in labels ) != bool (items ):
131- errors .append (f"'{ label } ' label should be present if and only if '{ kind } :' is present" )
132-
133- for item in items :
134- already_available = available [kind ].get (item ) or (
135- kind == "mkdocs_plugin" and available [kind ].get (item .split ("/" )[- 1 ])
136- )
137- if already_available :
138- if kind not in project .get ("shadowed" , ()):
139- errors .append (
140- f"{ kind } '{ item .split ('/' )[- 1 ]} ' is present in both project '{ already_available } ' and '{ name } '.\n "
141- f"If that is expected, the later of the two projects will be ignored, "
142- f"and to indicate this, it should contain 'shadowed: [{ kind } ]'"
143- )
144- else :
145- available [kind ][item ] = name
132+ elif (label in labels ) != any (bool (project .get (kind )) for kind in kinds ):
133+ errors .append (f"'{ label } ' label should be present if and only if '{ kinds } :' is present" )
134+
135+ for kind in kinds :
136+ items = _get_as_list (project , kind )
137+
138+ for item in items :
139+ already_available : str | None = None
140+ for subkind in (kind , cast ("EntrypointType" , kind .replace ("mkdocs" , "properdocs" ))):
141+ if already_available is None :
142+ already_available = available [subkind ].get (item )
143+ if already_available is None and "plugin" in kind :
144+ already_available = available [subkind ].get (item .split ("/" )[- 1 ])
145+
146+ if already_available :
147+ if kind not in project .get ("shadowed" , ()):
148+ errors .append (
149+ f"{ kind } '{ item .split ('/' )[- 1 ]} ' is present in both project '{ already_available } ' and '{ name } '.\n "
150+ f"If that is expected, the later of the two projects will be ignored, "
151+ f"and to indicate this, it should contain 'shadowed: [{ kind } ]'"
152+ )
153+ available [kind ].setdefault (item , name )
146154
147155 install_name : str | None = None
148- if any (key in project for key in _kind_to_label ):
156+ if any (key in project for keys in _kinds_to_label for key in keys ):
149157 if "pypi_id" in project :
150158 install_name = project ["pypi_id" ]
151159 if "_" in install_name :
0 commit comments