mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	
		
			
	
	
		
			108 lines
		
	
	
	
		
			3.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			108 lines
		
	
	
	
		
			3.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
|   | from ..common.info import UNKNOWN, ID | ||
|  | 
 | ||
|  | from . import declarations | ||
|  | 
 | ||
|  | # XXX need tests: | ||
|  | # * variables | ||
|  | # * variable | ||
|  | # * variable_from_id | ||
|  | 
 | ||
|  | 
 | ||
|  | def _iter_vars(filenames, preprocessed, *, | ||
|  |                handle_id=None, | ||
|  |                _iter_decls=declarations.iter_all, | ||
|  |                ): | ||
|  |     if handle_id is None: | ||
|  |         handle_id = ID | ||
|  | 
 | ||
|  |     for filename in filenames or (): | ||
|  |         for kind, funcname, name, decl in _iter_decls(filename, | ||
|  |                                                       preprocessed=preprocessed, | ||
|  |                                                       ): | ||
|  |             if kind != 'variable': | ||
|  |                 continue | ||
|  |             varid = handle_id(filename, funcname, name) | ||
|  |             yield varid, decl | ||
|  | 
 | ||
|  | 
 | ||
|  | # XXX Add a "handle_var" arg like we did for get_resolver()? | ||
|  | 
 | ||
|  | def variables(*filenames, | ||
|  |               perfilecache=None, | ||
|  |               preprocessed=False, | ||
|  |               known=None,  # for types | ||
|  |               handle_id=None, | ||
|  |               _iter_vars=_iter_vars, | ||
|  |               ): | ||
|  |     """Yield (varid, decl) for each variable found in the given files.
 | ||
|  | 
 | ||
|  |     If "preprocessed" is provided (and not False/None) then it is used | ||
|  |     to decide which tool to use to parse the source code after it runs | ||
|  |     through the C preprocessor.  Otherwise the raw | ||
|  |     """
 | ||
|  |     if len(filenames) == 1 and not (filenames[0], str): | ||
|  |         filenames, = filenames | ||
|  | 
 | ||
|  |     if perfilecache is None: | ||
|  |         yield from _iter_vars(filenames, preprocessed) | ||
|  |     else: | ||
|  |         # XXX Cache per-file variables (e.g. `{filename: [(varid, decl)]}`). | ||
|  |         raise NotImplementedError | ||
|  | 
 | ||
|  | 
 | ||
|  | def variable(name, filenames, *, | ||
|  |              local=False, | ||
|  |              perfilecache=None, | ||
|  |              preprocessed=False, | ||
|  |              handle_id=None, | ||
|  |              _iter_vars=variables, | ||
|  |              ): | ||
|  |     """Return (varid, decl) for the first found variable that matches.
 | ||
|  | 
 | ||
|  |     If "local" is True then the first matching local variable in the | ||
|  |     file will always be returned.  To avoid that, pass perfilecache and | ||
|  |     pop each variable from the cache after using it. | ||
|  |     """
 | ||
|  |     for varid, decl in _iter_vars(filenames, | ||
|  |                                   perfilecache=perfilecache, | ||
|  |                                   preprocessed=preprocessed, | ||
|  |                                   ): | ||
|  |         if varid.name != name: | ||
|  |             continue | ||
|  |         if local: | ||
|  |             if varid.funcname: | ||
|  |                 if varid.funcname == UNKNOWN: | ||
|  |                     raise NotImplementedError | ||
|  |                 return varid, decl | ||
|  |         elif not varid.funcname: | ||
|  |             return varid, decl | ||
|  |     else: | ||
|  |         return None, None  # No matching variable was found. | ||
|  | 
 | ||
|  | 
 | ||
|  | def variable_from_id(id, filenames, *, | ||
|  |                      perfilecache=None, | ||
|  |                      preprocessed=False, | ||
|  |                      handle_id=None, | ||
|  |                      _get_var=variable, | ||
|  |                      ): | ||
|  |     """Return (varid, decl) for the first found variable that matches.""" | ||
|  |     local = False | ||
|  |     if isinstance(id, str): | ||
|  |         name = id | ||
|  |     else: | ||
|  |         if id.funcname == UNKNOWN: | ||
|  |             local = True | ||
|  |         elif id.funcname: | ||
|  |             raise NotImplementedError | ||
|  | 
 | ||
|  |         name = id.name | ||
|  |         if id.filename and id.filename != UNKNOWN: | ||
|  |             filenames = [id.filename] | ||
|  |     return _get_var(name, filenames, | ||
|  |                     local=local, | ||
|  |                     perfilecache=perfilecache, | ||
|  |                     preprocessed=preprocessed, | ||
|  |                     handle_id=handle_id, | ||
|  |                     ) |