Last active
August 29, 2015 14:13
-
-
Save hogjonny/ebc6f233504a978fc9a6 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
#!/usr/bin/env python | |
#coding:utf-8 | |
#-------------------------------------------------------------------------- | |
def synthesize(inst, name, value, readonly=False): | |
''' | |
This is a convenience method for OOP | |
synthesizes the creation of attr with convenience methods: | |
x.attrbute | |
x._attribute # attribute storage | |
x.getAttribute() # retreive attribute | |
x.setAttribute() # set attribute (only created if not 'read only') | |
x.delAttribute() # delete the attribute from object | |
''' | |
cls = type(inst) | |
storageName = '_{0}'.format(name) | |
getterName = 'get{0}{1}'.format(name[0].capitalize(), name[1:]) | |
setterName = 'set{0}{1}'.format(name[0].capitalize(), name[1:]) | |
deleterName = 'del{0}{1}'.format(name[0].capitalize(), name[1:]) | |
setattr(inst, storageName, value) | |
# We always define the getter | |
def customGetter(self): | |
return getattr(self, storageName) | |
# Add the Getter | |
if not hasattr(inst, getterName): | |
setattr(cls, getterName, customGetter) | |
# Handle Read Only | |
if readonly : | |
if not hasattr(inst, name): | |
setattr(cls, name, property(fget=getattr(cls, getterName, None) | |
or customGetter, | |
fdel=getattr(cls, getterName, None))) | |
else: | |
# We only define the setter if we aren't read only | |
def customSetter(self, state): | |
setattr(self, storageName, state) | |
if not hasattr(inst, setterName): | |
setattr(cls, setterName, customSetter) | |
member = None | |
if hasattr(cls, name): | |
# we need to try to update the property fget, fset, | |
# fdel incase the class has defined its own custom functions | |
member = getattr(cls, name) | |
if not isinstance(member, property): | |
raise ValueError('Member "{0}" for class "{1}" exists and is not a property.' | |
''.format(name, cls.__name__)) | |
# Regardless if the class has the property or not we still try to set it with | |
setattr(cls, name, property(fget=getattr(member, 'fget', None) | |
or getattr(cls, getterName, None) | |
or customGetter, | |
fset=getattr(member, 'fset', None) | |
or getattr(cls, setterName, None) | |
or customSetter, | |
fdel=getattr(member, 'fdel', None) | |
or getattr(cls, getterName, None))) | |
#-------------------------------------------------------------------------- | |
# ------------------------------------------------------------------------- | |
def find_arg(argPosIndex=None, argTag=None, removeKwarg=None, | |
inArgs=None, inKwargs=None): | |
""" | |
# finds and returns an arg... | |
# if a positional index is given argPosIndex=0, it checks args first | |
# if a argTag is given, it checks kwargs | |
# If removeKwarg=True, it will remove the found arg from kwargs | |
# * I actually want/need to do this often | |
# | |
# return outArg, args, kwargs <-- get back modified kwargs! | |
# | |
# proper usage: | |
# | |
# foundArg, args, kwargs = find_arg(0, 'name',) | |
""" | |
if argPosIndex != None: | |
if not isinstance(argPosIndex, int): | |
raise TypeError('argPosIndex: accepts a index integer!\r' | |
'got: {0}'.format(argPosIndex)) | |
# positional args ... check the position | |
if len(inArgs) > 0: | |
try: | |
foundArg = inArgs[argPosIndex] | |
except: | |
pass | |
# check kwargs ... | |
try: | |
foundArg | |
except: | |
foundArg = inKwargs.pop(argTag, None) #defaults to None | |
if removeKwarg: | |
if argTag in inKwargs: | |
del inKwargs[argTag] | |
return foundArg, inKwargs | |
# ------------------------------------------------------------------------- | |
# ------------------------------------------------------------------------- | |
def setSynthArgKwarg(inst, argPosIndex, argTag, inArgs, inKwargs, | |
removeKwarg=True, defaultValue=None, setAnyway=True): | |
""" | |
Uses find_arg and sets a property on a object. | |
Special args: | |
setAnyway <-- if the object has the property already, set it | |
""" | |
# find the argument, or set to default value | |
foundArg, inKwargs = find_arg(argPosIndex, argTag, removeKwarg, | |
inArgs, inKwargs, | |
defaultValue) | |
# make sure the object doesn't arealdy have this property | |
try: | |
hasattr(inst, argTag) # <-- check if property exists | |
if setAnyway: | |
try: | |
setattr(inst, argTag, foundArg) # <-- try to set | |
except Exception, e: | |
raise e | |
except: | |
try: | |
foundArg = synthesize(inst, argTag, foundArg) | |
except Exception, e: | |
raise e | |
return foundArg, inKwargs | |
#-------------------------------------------------------------------------- | |
########################################################################### | |
# --call block------------------------------------------------------------- | |
if __name__ == "__main__": | |
print "# ----------------------------------------------------------------------- #\r" | |
print '~ find_arg.py ... Running script as __main__' | |
print "# ----------------------------------------------------------------------- #\r" | |
gDebug = 1 | |
########################################################################### | |
## Node Class | |
# ------------------------------------------------------------------------- | |
class TestNode(object): | |
def __init__(self, *args, **kwargs): | |
self._name, kwargs = find_arg(argPosIndex=0, argTag='name', | |
removeKwarg=True, | |
inArgs=args, inKwargs=kwargs ) # <-- first positional OR kwarg | |
self._parent, kwargs = find_arg(argPosIndex=1, argTag='parent', | |
removeKwarg=True, | |
inArgs=args, inKwargs=kwargs ) # <-- second positional OR kwarg | |
self._kwargsDict = {} | |
# arbitrary argument properties | |
# checking **kwargs, any kwargs left | |
# will be used to synthesize a property | |
for key, value in kwargs.items(): | |
self._kwargsDict[key] = value | |
# synthesize(self, '{0}'.format(key), value) <-- I have a method, | |
# which synthesizes properties... with gettr, settr, etc. | |
if gDebug: | |
print("{0}:{1}".format(key, value)) | |
# representation | |
def __repr__(self): | |
return '{0}({1})\r'.format(self.__class__.__name__, self.__dict__) | |
testNode = TestNode('foo') | |
testNode2 = TestNode(name='fool', parent=testNode) | |
testNode3 = TestNode('fubar', testNode2, goober='dufus') | |
print 'testNode2, name: {0}, parent: {1}'.format(testNode2._name, testNode2._parent) | |
print testNode3 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
A convenience method that makes it easy to support _args, *_kwargs
You can assume/expect a position (args, non-key word), or kwarg
testNode = TestNode('foo') ... is the same as
testNode = TestNode(name='foo')