Skip to content

Instantly share code, notes, and snippets.

@hogjonny
Last active August 29, 2015 14:13
Show Gist options
  • Save hogjonny/ebc6f233504a978fc9a6 to your computer and use it in GitHub Desktop.
Save hogjonny/ebc6f233504a978fc9a6 to your computer and use it in GitHub Desktop.
#!/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
@hogjonny
Copy link
Author

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')

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment