123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- # -*- coding: utf-8 -*-
- #!/usr/bin/env python
- import threading
- from itertools import chain
- from enum import IntEnum as _IntEnum, Enum
- from typing import List
- def enum(**enums):
- return type('Enum', (), enums)
- class IntEnum(_IntEnum):
- @classmethod
- def choices(cls):
- return [ _.value for _ in cls.__members__.values() ]
- class StrEnum(str, Enum):
- @classmethod
- def choices(cls):
- return [ _.value for _ in cls.__members__.values() ]
- class IterConstant(object):
- """
- 用此类代替枚举的原因在于IDE等工具的可观察性, 一定程度牺牲不可变性
- """
- @classmethod
- def choices(cls):
- # type: ()->List[str]
- return map(lambda _: getattr(cls, _),
- [_ for _ in dir(cls) if not _.startswith('__') and not callable(getattr(cls, _))])
- class Singleton(object):
- objs = {}
- objs_locker = threading.Lock()
- def __new__(cls, *args, **kv):
- if cls in cls.objs:
- return cls.objs[cls]['obj']
- cls.objs_locker.acquire()
- try:
- if cls in cls.objs: ## double check locking
- return cls.objs[cls]['obj']
- obj = object.__new__(cls)
- cls.objs[cls] = {'obj': obj, 'init': False}
- setattr(cls, '__init__', cls.decorate_init(cls.__init__))
- return cls.objs[cls]['obj']
- finally:
- cls.objs_locker.release()
- @classmethod
- def decorate_init(cls, fn):
- def init_wrap(*args):
- if not cls.objs[cls]['init']:
- fn(*args)
- cls.objs[cls]['init'] = True
- return
- return init_wrap
- class NoEmptyValueDict(dict):
- @staticmethod
- def _process_args(mapping = (), **kwargs):
- if hasattr(mapping, 'items'):
- mapping = getattr(mapping, 'items')()
- return ((k, v) for k, v in chain(mapping, getattr(kwargs, 'items')()) if v)
- def __setitem__(self, i, y):
- if y:
- super(NoEmptyValueDict, self).__setitem__(i, y)
- def update(self, E = None, **F):
- super(NoEmptyValueDict, self).update(self._process_args(E, **F))
- def setdefault(self, k, d=None):
- if k in self:
- return super(NoEmptyValueDict, self).setdefault(k, d)
- if not d:
- return None
- else:
- return super(NoEmptyValueDict, self).setdefault(k, d)
- class NoInstantiateMeta(type):
- def __call__(cls, *args, **kwargs):
- raise TypeError("BaseIterConstant class cannot be instantiated.")
- class BaseIterConstant(object):
- """
- 代替IterConstant基类
- """
- __metaclass__ = NoInstantiateMeta
- @classmethod
- def choice(cls, call=None):
- """
- call 表示需要对获取的值执行的方法 比如int、str、float、lambda x: x+1
- """
- if call and callable(call):
- return [call(getattr(cls, attr)) for attr in dir(cls) if not attr.startswith("_") and attr.isupper()]
- else:
- return [getattr(cls, attr) for attr in dir(cls) if not attr.startswith("_") and attr.isupper()]
|