Last active
December 11, 2018 07:33
-
-
Save leafsummer/e36634fa503bb778723d1cf21ac25beb to your computer and use it in GitHub Desktop.
[tool function]
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
def first(iterable, default=None, key=None): | |
""" | |
Return first element of `iterable` that evaluates true, else return None | |
(or an optional default value). | |
>>> first([0, False, None, [], (), 42]) | |
42 | |
>>> first([0, False, None, [], ()]) is None | |
True | |
>>> first([0, False, None, [], ()], default='ohai') | |
'ohai' | |
>>> import re | |
>>> m = first(re.match(regex, 'abc') for regex in ['b.*', 'a(.*)']) | |
>>> m.group(1) | |
'bc' | |
The optional `key` argument specifies a one-argument predicate function | |
like that used for `filter()`. The `key` argument, if supplied, must be | |
in keyword form. For example: | |
>>> first([1, 1, 3, 4, 5], key=lambda x: x % 2 == 0) | |
4 | |
""" | |
if key is None: | |
for el in iterable: | |
if el: | |
return el | |
else: | |
for el in iterable: | |
if key(el): | |
return el | |
return default | |
# functools.total_ordering is only available from Python 2.7 and 3.2 | |
if is_python_version((2, 7), (3, 2)): | |
from functools import total_ordering | |
else: | |
def total_ordering(cls): # noqa | |
"""Class decorator that fills in missing ordering methods""" | |
convert = { | |
'__lt__': [('__gt__', lambda self, other: other < self), | |
('__le__', lambda self, other: not other < self), | |
('__ge__', lambda self, other: not self < other)], | |
'__le__': [('__ge__', lambda self, other: other <= self), | |
('__lt__', lambda self, other: not other <= self), | |
('__gt__', lambda self, other: not self <= other)], | |
'__gt__': [('__lt__', lambda self, other: other > self), | |
('__ge__', lambda self, other: not other > self), | |
('__le__', lambda self, other: not self > other)], | |
'__ge__': [('__le__', lambda self, other: other >= self), | |
('__gt__', lambda self, other: not other >= self), | |
('__lt__', lambda self, other: not self >= other)] | |
} | |
roots = set(dir(cls)) & set(convert) | |
if not roots: | |
raise ValueError('must define at least one ordering operation: < > <= >=') # noqa | |
root = max(roots) # prefer __lt__ to __le__ to __gt__ to __ge__ | |
for opname, opfunc in convert[root]: | |
if opname not in roots: | |
opfunc.__name__ = str(opname) | |
opfunc.__doc__ = getattr(int, opname).__doc__ | |
setattr(cls, opname, opfunc) | |
return cls | |
def is_ip(value): | |
"""Determine if the given string is an IP address. | |
Python 2 on Windows doesn't provide ``inet_pton``, so this only | |
checks IPv4 addresses in that environment. | |
:param value: value to check | |
:type value: str | |
:return: True if string is an IP address | |
:rtype: bool | |
""" | |
import socket | |
if PY2 and os.name == 'nt': | |
try: | |
socket.inet_aton(value) | |
return True | |
except socket.error: | |
return False | |
for family in (socket.AF_INET, socket.AF_INET6): | |
try: | |
socket.inet_pton(family, value) | |
except socket.error: | |
pass | |
else: | |
return True | |
return False | |
class locked_cached_property(object): | |
"""A decorator that converts a function into a lazy property. The | |
function wrapped is called the first time to retrieve the result | |
and then that calculated result is used the next time you access | |
the value. Works like the one in Werkzeug but has a lock for | |
thread safety. | |
""" | |
def __init__(self, func, name=None, doc=None): | |
self.__name__ = name or func.__name__ | |
self.__module__ = func.__module__ | |
self.__doc__ = doc or func.__doc__ | |
self.func = func | |
self.lock = RLock() | |
def __get__(self, obj, type=None): | |
if obj is None: | |
return self | |
with self.lock: | |
value = obj.__dict__.get(self.__name__, _missing) | |
if value is _missing: | |
value = self.func(obj) | |
obj.__dict__[self.__name__] = value | |
return value | |
class cached_property(property): | |
"""A decorator that converts a function into a lazy property. The | |
function wrapped is called the first time to retrieve the result | |
and then that calculated result is used the next time you access | |
the value:: | |
class Foo(object): | |
@cached_property | |
def foo(self): | |
# calculate something important here | |
return 42 | |
The class has to have a `__dict__` in order for this property to | |
work. | |
""" | |
# implementation detail: A subclass of python's builtin property | |
# decorator, we override __get__ to check for a cached value. If one | |
# choses to invoke __get__ by hand the property will still work as | |
# expected because the lookup logic is replicated in __get__ for | |
# manual invocation. | |
def __init__(self, func, name=None, doc=None): | |
self.__name__ = name or func.__name__ | |
self.__module__ = func.__module__ | |
self.__doc__ = doc or func.__doc__ | |
self.func = func | |
def __set__(self, obj, value): | |
obj.__dict__[self.__name__] = value | |
def __get__(self, obj, type=None): | |
if obj is None: | |
return self | |
value = obj.__dict__.get(self.__name__, _missing) | |
if value is _missing: | |
value = self.func(obj) | |
obj.__dict__[self.__name__] = value | |
return value |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment