@@ -74,54 +74,34 @@ def get(cache_active: Optional[bool] = None,
7474 cache_path : Optional [str ] = None ):
7575 '''Static function that if necessary creates and returns the singleton
7676 ModuleManager instance.
77-
78- :param use_caching: If `True`, a file-based caching of the fparser
79- tree will be used. This can significantly accelerate obtaining
80- a PSyIR from a source file.
81- For parallel builds, parallel race conditions to the cache file
82- can happen, but this shouldn't lead to wrong results. However,
83- that's untested so far.
84-
85- :param cache_path: If set, the cache file will be stored in the given
86- path (directory) using a hashsum of the source code to create
87- a unique cache file name. If `None`, a cache file will be created
88- in the same directory as the source file with a new
89- file ending `.psycache`.
90-
9177 '''
9278 if not ModuleManager ._instance :
93- ModuleManager ._instance = ModuleManager (cache_active , cache_path )
79+ ModuleManager ._instance = ModuleManager ()
9480
9581 return ModuleManager ._instance
9682
9783 # ------------------------------------------------------------------------
98- def __init__ (
99- self ,
100- cache_active : Optional [bool ] = None ,
101- cache_path : Optional [str ] = None
102- ):
84+ def __init__ (self ):
10385 """
10486 Set up the module manager. Module manager is actually a singleton
10587 and should not be created directly. Use `ModuleManager.get()`
10688 instead.
10789
108- :param cache_active: Whether to use (`True`) or
109- disable (`False`) caching
110- :param cache_path: Path to the cache directory. If `None`, the
111- cache file will be created in the same directory as the source
112- file with a new file ending `.psycache`.
11390 """
11491
11592 if ModuleManager ._instance is not None :
11693 raise InternalError ("You need to use 'ModuleManager.get()' "
11794 "to get the singleton instance." )
11895
11996 # Disable caching by default
120- self ._cache_active = (
121- cache_active if cache_active is not None else False )
97+ self ._cache_active = False
12298
12399 # Path to cache
124- self ._cache_path : Optional [str ] = cache_path
100+ self ._cache_path : Optional [str ] = None
101+
102+ # Whether to resolve imports while inspecting another import.
103+ # It can be a list of specific module names for finer control.
104+ self ._resolve_indirect_imports : Union [bool , Iterable [str ]] = False
125105
126106 self ._visited_files : dict [str , FileInfo ] = {}
127107
@@ -159,6 +139,75 @@ def __init__(
159139 self ._module_pattern = re .compile (r"^\s*module\s+([a-z]\S*)\s*$" ,
160140 flags = re .IGNORECASE | re .MULTILINE )
161141
142+ @property
143+ def cache_active (self ) -> bool :
144+ '''
145+ :returns: whether the parsed files will be cached.
146+ '''
147+ return self ._cache_active
148+
149+ @cache_active .setter
150+ def cache_active (self , value : bool ):
151+ '''
152+ :param value: specify whether the parsed files will be cached.
153+
154+ :raises TypeError: if the provided value is not a bool.
155+ '''
156+ if not isinstance (value , bool ):
157+ raise TypeError (
158+ f"'cache_active' must be a bool, but found { type (value )} " )
159+ self ._cache_active = value
160+
161+ @property
162+ def cache_path (self ) -> Optional [str ]:
163+ '''
164+ :returns: the path where the cache file will be stored, if it is None
165+ the file will be created in the same directory as the source file.
166+ '''
167+ return self ._cache_path
168+
169+ @cache_path .setter
170+ def cache_path (self , value : Optional [str ]):
171+ '''
172+ :param value: specify the path where the cache file will be stored, if
173+ None the file will be created in the same directory as the source
174+ file.
175+
176+ :raises TypeError: if the provided value is not a str.
177+ '''
178+ if value is not None and not isinstance (value , str ):
179+ raise TypeError (
180+ f"'cache_path' must be a str, but found { type (value )} " )
181+ self ._cache_path = value
182+
183+ @property
184+ def resolve_indirect_imports (self ) -> Union [bool , Iterable [str ]]:
185+ '''
186+ :returns: whether indirect imports will be imported (if found). This
187+ can be a list of module names to provide finer control.
188+ '''
189+ return self ._resolve_indirect_imports
190+
191+ @resolve_indirect_imports .setter
192+ def resolve_indirect_imports (self , value : Union [bool , Iterable [str ]]):
193+ '''
194+ :param value: specify whether indirect imports will be imported (if
195+ found). This can be a list of module names for finer control.
196+
197+ :raises TypeError: if the provided value is not bool or Iterable[str].
198+ '''
199+ if not isinstance (value , (Iterable , bool )):
200+ raise TypeError (
201+ f"'resolve_indirect_imports' must be a boolean or an Iterable,"
202+ f" but found { type (value )} " )
203+ if isinstance (value , Iterable ):
204+ for x in value :
205+ if not isinstance (x , str ):
206+ raise TypeError (
207+ f"'resolve_indirect_imports' must be an Iterable of "
208+ f"str, but found an item of { type (x )} " )
209+ self ._resolve_indirect_imports = value
210+
162211 # ------------------------------------------------------------------------
163212 def add_search_path (self , directories , recursive = True ):
164213 '''If the directory is not already contained in the search path,
@@ -219,7 +268,8 @@ def _add_all_files_from_dir(self, directory: str) -> list[FileInfo]:
219268 FileInfo (
220269 full_path ,
221270 cache_active = self ._cache_active ,
222- cache_path = self ._cache_path
271+ cache_path = self ._cache_path ,
272+ resolve_imports = self ._resolve_indirect_imports
223273 )
224274 new_files .append (self ._visited_files [full_path ])
225275 return new_files
0 commit comments