mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	initial import of the packaging package in the standard library
This commit is contained in:
		
							parent
							
								
									566f8a646e
								
							
						
					
					
						commit
						1231a4e097
					
				
					 193 changed files with 30376 additions and 149 deletions
				
			
		
							
								
								
									
										99
									
								
								Lib/packaging/pypi/wrapper.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								Lib/packaging/pypi/wrapper.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,99 @@ | |||
| """Convenient client for all PyPI APIs. | ||||
| 
 | ||||
| This module provides a ClientWrapper class which will use the "simple" | ||||
| or XML-RPC API to request information or files from an index. | ||||
| """ | ||||
| 
 | ||||
| from packaging.pypi import simple, xmlrpc | ||||
| 
 | ||||
| _WRAPPER_MAPPINGS = {'get_release': 'simple', | ||||
|                      'get_releases': 'simple', | ||||
|                      'search_projects': 'simple', | ||||
|                      'get_metadata': 'xmlrpc', | ||||
|                      'get_distributions': 'simple'} | ||||
| 
 | ||||
| _WRAPPER_INDEXES = {'xmlrpc': xmlrpc.Client, | ||||
|                     'simple': simple.Crawler} | ||||
| 
 | ||||
| 
 | ||||
| def switch_index_if_fails(func, wrapper): | ||||
|     """Decorator that switch of index (for instance from xmlrpc to simple) | ||||
|     if the first mirror return an empty list or raises an exception. | ||||
|     """ | ||||
|     def decorator(*args, **kwargs): | ||||
|         retry = True | ||||
|         exception = None | ||||
|         methods = [func] | ||||
|         for f in wrapper._indexes.values(): | ||||
|             if f != func.__self__ and hasattr(f, func.__name__): | ||||
|                 methods.append(getattr(f, func.__name__)) | ||||
|         for method in methods: | ||||
|             try: | ||||
|                 response = method(*args, **kwargs) | ||||
|                 retry = False | ||||
|             except Exception as e: | ||||
|                 exception = e | ||||
|             if not retry: | ||||
|                 break | ||||
|         if retry and exception: | ||||
|             raise exception | ||||
|         else: | ||||
|             return response | ||||
|     return decorator | ||||
| 
 | ||||
| 
 | ||||
| class ClientWrapper: | ||||
|     """Wrapper around simple and xmlrpc clients, | ||||
| 
 | ||||
|     Choose the best implementation to use depending the needs, using the given | ||||
|     mappings. | ||||
|     If one of the indexes returns an error, tries to use others indexes. | ||||
| 
 | ||||
|     :param index: tell which index to rely on by default. | ||||
|     :param index_classes: a dict of name:class to use as indexes. | ||||
|     :param indexes: a dict of name:index already instantiated | ||||
|     :param mappings: the mappings to use for this wrapper | ||||
|     """ | ||||
| 
 | ||||
|     def __init__(self, default_index='simple', index_classes=_WRAPPER_INDEXES, | ||||
|                  indexes={}, mappings=_WRAPPER_MAPPINGS): | ||||
|         self._projects = {} | ||||
|         self._mappings = mappings | ||||
|         self._indexes = indexes | ||||
|         self._default_index = default_index | ||||
| 
 | ||||
|         # instantiate the classes and set their _project attribute to the one | ||||
|         # of the wrapper. | ||||
|         for name, cls in index_classes.items(): | ||||
|             obj = self._indexes.setdefault(name, cls()) | ||||
|             obj._projects = self._projects | ||||
|             obj._index = self | ||||
| 
 | ||||
|     def __getattr__(self, method_name): | ||||
|         """When asking for methods of the wrapper, return the implementation of | ||||
|         the wrapped classes, depending the mapping. | ||||
| 
 | ||||
|         Decorate the methods to switch of implementation if an error occurs | ||||
|         """ | ||||
|         real_method = None | ||||
|         if method_name in _WRAPPER_MAPPINGS: | ||||
|             obj = self._indexes[_WRAPPER_MAPPINGS[method_name]] | ||||
|             real_method = getattr(obj, method_name) | ||||
|         else: | ||||
|             # the method is not defined in the mappings, so we try first to get | ||||
|             # it via the default index, and rely on others if needed. | ||||
|             try: | ||||
|                 real_method = getattr(self._indexes[self._default_index], | ||||
|                                       method_name) | ||||
|             except AttributeError: | ||||
|                 other_indexes = [i for i in self._indexes | ||||
|                                  if i != self._default_index] | ||||
|                 for index in other_indexes: | ||||
|                     real_method = getattr(self._indexes[index], method_name, | ||||
|                                           None) | ||||
|                     if real_method: | ||||
|                         break | ||||
|         if real_method: | ||||
|             return switch_index_if_fails(real_method, self) | ||||
|         else: | ||||
|             raise AttributeError("No index have attribute '%s'" % method_name) | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Tarek Ziade
						Tarek Ziade