Created
July 14, 2014 04:46
-
-
Save huyx/543c822c1c64c2280383 to your computer and use it in GitHub Desktop.
支持字典、模块等的合并
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 -*- | |
u'''合并对象,特点: | |
- 字典对象并操作 | |
- 其他对象替换 | |
可以合并的对象包括: | |
- 字典 | |
- 模块 | |
- 其他符合条件的对象 | |
''' | |
import inspect | |
from collections import OrderedDict | |
def isPublic(name): | |
return not name.startswith('_') | |
def isUpper(v): | |
return v.upper() == v | |
def isLower(v): | |
return v.lower() == v | |
def isMerableBaseType(o): | |
'''判断是否可合并 | |
返回: True - 可合并 False - 不可合并 None - 不确定 | |
''' | |
if isinstance(o, (basestring, tuple, list)): | |
return False | |
if isinstance(o, dict): | |
return True | |
if isinstance(o, OrderedDict): | |
return True | |
if inspect.ismodule(o): | |
return True | |
return None | |
def isSource(o): | |
result = isMerableBaseType(o) | |
if result is None: | |
return all(( | |
hasattr(o, 'keys'), | |
hasattr(o, '__getitem__'), | |
)) | |
return result | |
def isTarget(o): | |
result = isMerableBaseType(o) | |
if result is None: | |
return all(( | |
hasattr(o, 'keys'), | |
hasattr(o, '__getitem__'), | |
hasattr(o, '__setitem__'), | |
)) | |
return result | |
def isMergeable(target, source): | |
return isTarget(target) and isSource(source) | |
class Mergeable(object): | |
def __init__(self, o): | |
self.o = o | |
def keys(self): | |
return self.o.keys() | |
def __getitem__(self, key): | |
return self.o.__getitem__(key) | |
class MergeableModule(Mergeable): | |
def keys(self): | |
return [k for k in dir(self.o) if isPublic(k)] | |
def __getitem__(self, key): | |
return getattr(self.o, key) | |
class GeneralSource(Mergeable): | |
pass | |
class ModuleSource(MergeableModule): | |
pass | |
class GeneralTarget(Mergeable): | |
def __setitem__(self, key, value): | |
return self.o.__setitem__(key, value) | |
class ModuleTarget(MergeableModule): | |
def __setitem__(self, key, value): | |
setattr(self.o, key, value) | |
class CaseSensitiveBase(object): | |
'''大小写装饰类 | |
''' | |
def __init__(self, mergeable): | |
self.mergeable = mergeable | |
def _match(self, key): | |
raise NotImplementedError | |
def keys(self): | |
return [k for k in self.mergeable.keys() if self._match(k)] | |
def __getitem__(self, key): | |
return self.mergeable.__getitem__(key) | |
def __setitem__(self, key, value): | |
return self.mergeable.__getitem__(key, value) | |
class UpperCase(CaseSensitiveBase): | |
def match(self, key): | |
return isUpper(key) | |
class LowerCase(CaseSensitiveBase): | |
def match(self, key): | |
return isLower(key) | |
def CaseSensitive(mergeable, case): | |
if isinstance(object, basestring): | |
case = case.lower() | |
if case == 'upper': | |
return UpperCase(mergeable) | |
elif case == 'lower': | |
return LowerCase(mergeable) | |
else: | |
return mergeable | |
def Source(source, case=None): | |
'''工厂函数,返回 Target 对象,所以采用首字母大写 | |
''' | |
if inspect.ismodule(source): | |
return CaseSensitive(ModuleSource(source), case) | |
return CaseSensitive(GeneralSource(source), case) | |
def Target(target, case=None): | |
'''工厂函数,返回 Target 对象,所以采用首字母大写 | |
''' | |
if inspect.ismodule(target): | |
return CaseSensitive(ModuleTarget(target), case) | |
return CaseSensitive(GeneralTarget(target), case) | |
def merge(target, source, case=None): | |
''' | |
>>> from collections import OrderedDict | |
>>> merge(OrderedDict(), OrderedDict([('a', 1)])) | |
OrderedDict([('a', 1)]) | |
>>> merge(OrderedDict([('a', 1)]), OrderedDict([('a', 2)])) | |
OrderedDict([('a', 2)]) | |
>>> merge(OrderedDict([('a', 1)]), OrderedDict([('b', 2)])) | |
OrderedDict([('a', 1), ('b', 2)]) | |
>>> 'ismodule' in merge({}, inspect) | |
True | |
''' | |
target = Target(target) | |
source = Source(source) | |
targetKeys = target.keys() | |
sourceKeys = source.keys() | |
for key in sourceKeys: | |
sourceValue = source[key] | |
if key in targetKeys: | |
targetValue = target[key] | |
if isMergeable(targetValue, sourceValue): | |
merge(targetValue, sourceValue) | |
else: | |
target[key] = sourceValue | |
else: | |
target[key] = sourceValue | |
return target.o | |
if __name__ == '__main__': | |
import doctest | |
doctest.testmod() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment