55from collections import defaultdict
66from fnmatch import fnmatch
77from pathlib import Path
8+ from types import ModuleType
89from typing import TYPE_CHECKING
910
1011import pytest
1112from mkdocstrings import Inventory
1213
1314import griffe
15+ import griffecli
1416
1517if TYPE_CHECKING :
1618 from collections .abc import Iterator
1719
1820
19- @pytest .fixture (name = "loader" , scope = "module" )
20- def _fixture_loader () -> griffe .GriffeLoader :
21+ def _load_module (module : ModuleType ) -> griffe .GriffeLoader :
2122 loader = griffe .GriffeLoader (
2223 extensions = griffe .load_extensions (
2324 "griffe_inherited_docstrings" ,
2425 "unpack_typeddict" ,
2526 ),
2627 )
27- loader .load ("griffe" )
28+ loader .load (module . __name__ )
2829 loader .resolve_aliases ()
2930 return loader
3031
3132
32- @pytest .fixture (name = "internal_api" , scope = "module" )
33- def _fixture_internal_api (loader : griffe .GriffeLoader ) -> griffe .Module :
34- return loader .modules_collection ["griffe._internal" ]
33+ def _get_internal_api (module : ModuleType , loader : griffe .GriffeLoader | None = None ) -> griffe .Module :
34+ if loader is None :
35+ loader = _load_module (module )
36+ return loader .modules_collection [module .__name__ + "._internal" ]
3537
3638
37- @pytest .fixture (name = "public_api" , scope = "module" )
38- def _fixture_public_api (loader : griffe .GriffeLoader ) -> griffe .Module :
39- return loader .modules_collection ["griffe" ]
39+ def _get_public_api (module : ModuleType , loader : griffe .GriffeLoader | None = None ) -> griffe .Module :
40+ if loader is None :
41+ loader = _load_module (module )
42+ return loader .modules_collection [module .__name__ ]
4043
4144
4245def _yield_public_objects (
@@ -76,19 +79,12 @@ def _yield_public_objects(
7679 continue
7780
7881
79- @pytest .fixture (name = "modulelevel_internal_objects" , scope = "module" )
80- def _fixture_modulelevel_internal_objects (internal_api : griffe .Module ) -> list [griffe .Object | griffe .Alias ]:
81- return list (_yield_public_objects (internal_api , modulelevel = True ))
82+ def _get_modulelevel_internal_objects (tested_module : ModuleType ) -> list [griffe .Object | griffe .Alias ]:
83+ return list (_yield_public_objects (_get_internal_api (tested_module ), modulelevel = True ))
8284
8385
84- @pytest .fixture (name = "internal_objects" , scope = "module" )
85- def _fixture_internal_objects (internal_api : griffe .Module ) -> list [griffe .Object | griffe .Alias ]:
86- return list (_yield_public_objects (internal_api , modulelevel = False , special = True ))
87-
88-
89- @pytest .fixture (name = "public_objects" , scope = "module" )
90- def _fixture_public_objects (public_api : griffe .Module ) -> list [griffe .Object | griffe .Alias ]:
91- return list (_yield_public_objects (public_api , modulelevel = False , inherited = True , special = True ))
86+ def _get_public_objects (tested_module : ModuleType ) -> list [griffe .Object | griffe .Alias ]:
87+ return list (_yield_public_objects (_get_public_api (tested_module ), modulelevel = False , inherited = True , special = True ))
9288
9389
9490@pytest .fixture (name = "inventory" , scope = "module" )
@@ -100,8 +96,9 @@ def _fixture_inventory() -> Inventory:
10096 return Inventory .parse_sphinx (file )
10197
10298
103- def test_alias_proxies (internal_api : griffe . Module ) -> None :
99+ def test_alias_proxies () -> None :
104100 """The Alias class has all the necessary methods and properties."""
101+ internal_api = _get_internal_api (griffe )
105102 alias_members = set (internal_api ["models.Alias" ].all_members .keys ())
106103 for cls in (
107104 internal_api ["models.Module" ],
@@ -114,33 +111,39 @@ def test_alias_proxies(internal_api: griffe.Module) -> None:
114111 assert name in alias_members
115112
116113
117- def test_exposed_objects (modulelevel_internal_objects : list [griffe .Object | griffe .Alias ]) -> None :
114+ @pytest .mark .parametrize ("tested_module" , [griffe , griffecli ])
115+ def test_exposed_objects (tested_module : ModuleType ) -> None :
118116 """All public objects in the internal API are exposed under `griffe`."""
117+ modulelevel_internal_objects = _get_modulelevel_internal_objects (tested_module )
119118 not_exposed = [
120119 obj .path
121120 for obj in modulelevel_internal_objects
122- if obj .name not in griffe .__all__ or not hasattr (griffe , obj .name )
121+ if obj .name not in tested_module .__all__ or not hasattr (tested_module , obj .name )
123122 ]
124123 assert not not_exposed , "Objects not exposed:\n " + "\n " .join (sorted (not_exposed ))
125124
126125
127- def test_unique_names (modulelevel_internal_objects : list [griffe .Object | griffe .Alias ]) -> None :
126+ @pytest .mark .parametrize ("tested_module" , [griffe , griffecli ])
127+ def test_unique_names (tested_module : ModuleType ) -> None :
128128 """All internal objects have unique names."""
129+ modulelevel_internal_objects = _get_modulelevel_internal_objects (tested_module )
129130 names_to_paths = defaultdict (list )
130131 for obj in modulelevel_internal_objects :
131132 names_to_paths [obj .name ].append (obj .path )
132133 non_unique = [paths for paths in names_to_paths .values () if len (paths ) > 1 ]
133134 assert not non_unique , "Non-unique names:\n " + "\n " .join (str (paths ) for paths in non_unique )
134135
135136
136- def test_single_locations (public_api : griffe .Module ) -> None :
137+ @pytest .mark .parametrize ("tested_module" , [griffe , griffecli ])
138+ def test_single_locations (tested_module : ModuleType ) -> None :
137139 """All objects have a single public location."""
138140
139141 def _public_path (obj : griffe .Object | griffe .Alias ) -> bool :
140142 return obj .is_public and (obj .parent is None or _public_path (obj .parent ))
141143
144+ public_api = _get_public_api (tested_module )
142145 multiple_locations = {}
143- for obj_name in set ( griffe .__all__ ) - griffe . _CLI_MISSING_FEATURES :
146+ for obj_name in tested_module .__all__ :
144147 obj = public_api [obj_name ]
145148 if obj .aliases and (
146149 public_aliases := [path for path , alias in obj .aliases .items () if path != obj .path and _public_path (alias )]
@@ -168,16 +171,19 @@ def test_api_matches_inventory(inventory: Inventory, public_objects: list[griffe
168171 assert not not_in_inventory , msg .format (paths = "\n " .join (sorted (not_in_inventory )))
169172
170173
174+ @pytest .mark .parametrize ("tested_module" , [griffe , griffecli ])
171175def test_inventory_matches_api (
172176 inventory : Inventory ,
173177 public_objects : list [griffe .Object | griffe .Alias ],
174- loader : griffe . GriffeLoader ,
178+ tested_module : ModuleType ,
175179) -> None :
176180 """The inventory doesn't contain any additional Python object."""
181+ loader = _load_module (tested_module )
182+ public_api = _get_public_api (tested_module , loader = loader )
183+ public_objects = _get_public_objects (public_api )
177184 not_in_api = []
178185 public_api_paths = {obj .path for obj in public_objects }
179- public_api_paths .add ("griffe" )
180- public_api_paths .add ("griffecli" )
186+ public_api_paths .add (tested_module .__name__ )
181187 for item in inventory .values ():
182188 if item .domain == "py" and "(" not in item .name :
183189 obj = loader .modules_collection [item .name ]
@@ -187,13 +193,16 @@ def test_inventory_matches_api(
187193 assert not not_in_api , msg .format (paths = "\n " .join (sorted (not_in_api )))
188194
189195
190- def test_no_module_docstrings_in_internal_api (internal_api : griffe .Module ) -> None :
196+ @pytest .mark .parametrize ("tested_module" , [griffe , griffecli ])
197+ def test_no_module_docstrings_in_internal_api (tested_module : ModuleType ) -> None :
191198 """No module docstrings should be written in our internal API.
192199
193200 The reasoning is that docstrings are addressed to users of the public API,
194201 but internal modules are not exposed to users, so they should not have docstrings.
195202 """
196203
204+ internal_api = _get_internal_api (tested_module )
205+
197206 def _modules (obj : griffe .Module ) -> Iterator [griffe .Module ]:
198207 for member in obj .modules .values ():
199208 yield member
0 commit comments