147 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			147 lines
		
	
	
		
			3.5 KiB
		
	
	
	
		
			Python
		
	
	
	
| from requests.exceptions import ConnectionError, RequestException
 | |
| 
 | |
| 
 | |
| class Attrs:
 | |
| 
 | |
|     @classmethod
 | |
|     def call(cls, f, **kwargs):
 | |
|         return f(cls(**kwargs))
 | |
| 
 | |
|     def __init__(self, **kwargs):
 | |
|         self.attrs = kwargs
 | |
| 
 | |
|     def __getattr__(self, attr):
 | |
|         return self.attrs.get(attr)
 | |
| 
 | |
| 
 | |
| def get_short_error_message(e: Exception):
 | |
|     '''Generate a reasonable short message why the HTTP request failed'''
 | |
| 
 | |
|     if isinstance(e, RequestException) and e.response is not None:
 | |
|         # e.g. "401 Unauthorized"
 | |
|         return '{} {}'.format(e.response.status_code, e.response.reason)
 | |
|     elif isinstance(e, ConnectionError):
 | |
|         # e.g. "ConnectionError" or "ConnectTimeout"
 | |
|         return e.__class__.__name__
 | |
|     else:
 | |
|         return str(e)
 | |
| 
 | |
| 
 | |
| def identity(value, *_, **__):
 | |
|     """
 | |
|     Trivial identity function: return the value passed in its first argument.
 | |
| 
 | |
|     Examples:
 | |
| 
 | |
|     >>> identity(42)
 | |
|     42
 | |
| 
 | |
|     >>> list(
 | |
|     ...     filter(
 | |
|     ...         identity,
 | |
|     ...         [None, False, True, 0, 1, list(), set(), dict()],
 | |
|     ...     ),
 | |
|     ... )
 | |
|     [True, 1]
 | |
|     """
 | |
| 
 | |
|     return value
 | |
| 
 | |
| 
 | |
| def const(value, *_, **__):
 | |
|     """
 | |
|     Given a value, returns a function that simply returns that value.
 | |
| 
 | |
|     Example:
 | |
|     >>> f = const(42)
 | |
|     >>> f()
 | |
|     42
 | |
|     >>> f()
 | |
|     42
 | |
|     """
 | |
| 
 | |
|     return lambda *_, **__: value
 | |
| 
 | |
| 
 | |
| def catching(computation, catcher=identity, exception=Exception):
 | |
|     """
 | |
|     Catch exceptions.
 | |
| 
 | |
|     Call the provided computation with no arguments.  If it throws an exception
 | |
|     of the provided exception class (or any exception, if no class is provided),
 | |
|     return the result of calling the catcher function with the exception as the
 | |
|     sole argument.  If no catcher function is specified, return the exception.
 | |
| 
 | |
|     Examples:
 | |
| 
 | |
|     Catch a KeyError and return the exception itself:
 | |
|     >>> catching(lambda: {'foo': 'bar'}['meh'])
 | |
|     KeyError('meh',)
 | |
| 
 | |
|     Catch a KeyError and return a default value:
 | |
|     >>> catching(
 | |
|     ...     computation=lambda: {'foo': 'bar'}['meh'],
 | |
|     ...     catcher=const('nope'),
 | |
|     ... )
 | |
|     'nope'
 | |
|     """
 | |
| 
 | |
|     try:
 | |
|         return computation()
 | |
|     except exception as e:
 | |
|         return catcher(e)
 | |
| 
 | |
| 
 | |
| def defaulting(computation, default=None, exception=Exception):
 | |
|     """
 | |
|     Like `catching`, but just return a default value if an exception is caught.
 | |
| 
 | |
|     If no default value is supplied, default to None.
 | |
| 
 | |
|     Examples:
 | |
| 
 | |
|     Catch a KeyError and return a default value, like the `get` method:
 | |
|     >>> defaulting(lambda: {'foo': 'bar'}['meh'], 'nope')
 | |
|     'nope'
 | |
| 
 | |
|     Turn a ZeroDivisionError into None:
 | |
|     >>> defaulting(lambda: 1/0) == None
 | |
|     True
 | |
|     """
 | |
| 
 | |
|     return catching(
 | |
|         computation=computation,
 | |
|         catcher=const(default),
 | |
|         exception=exception,
 | |
|     )
 | |
| 
 | |
| 
 | |
| def these(what, where=None):
 | |
|     """
 | |
|     Combinator for yielding multiple values with property access.
 | |
| 
 | |
|     Yields from the values generated by an attribute of the given object, or
 | |
|     the values generated by the given object itself if no attribute key is
 | |
|     specified.
 | |
| 
 | |
|     Examples:
 | |
| 
 | |
|     No attribute key specified; yields from the given object:
 | |
|     >>> these(['foo', 'bar'])
 | |
|     ['foo', 'bar']
 | |
| 
 | |
|     An attribute key is specified; yields from the values generated by the
 | |
|     specified attribute's value:
 | |
|     object:
 | |
|     >>> these({'foo': ['bar', 'baz']}, 'foo')
 | |
|     ['bar', 'baz']
 | |
| 
 | |
|     An invalid attribute key is specified; yields nothing:
 | |
|     >>> these({'foo': ['bar', 'baz']}, 'meh')
 | |
|     []
 | |
|     """
 | |
| 
 | |
|     if not where:
 | |
|         return what
 | |
|     return what[where] if where in what else []
 |