|
Server : Apache/2.2.22 (Unix) mod_ssl/2.2.22 OpenSSL/1.0.0-fips mod_auth_passthrough/2.1 mod_bwlimited/1.4 System : Linux server.jackjohnson.com 2.6.32-279.5.2.el6.x86_64 #1 SMP Fri Aug 24 01:07:11 UTC 2012 x86_64 User : jackjohn ( 502) PHP Version : 5.3.17 Disable Function : NONE Directory : /usr/share/system-config-network/netconfpkg/ |
Upload File : |
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
"""\
Basic classes with predefined properties
Example usage:
class Article(Gdtstruct):
"A basic Article class"
# fields and types are dynamically set by the initializer
gdtstruct_properties([('title', Gdtstr, "The Title of the Article"),
('page', Gdtlist, "List of pages in the Article")
])
def __init__(self, *args):
super(Article, self).__init__(*args)
self.title = Gdtstr("")
self.page = Gdtlist()
class Page(Gdtstruct):
# fields and types are dynamically set by the initializer
gdtstruct_properties([('text', Gdtstr, "The text of the page"),
])
def __init__(self, *args):
super(Page, self).__init__(*args)
self.text = Gdtstr(args[0] if len(args) else "")
a = Article()
print Article.title.__doc__
print
a.title = "My title"
a.page.append(Page("page 1"))
a.page.append(Page("page 2"))
a.commit()
print a
print
a.title = "My bad title"
a.page[1].text = "bad page 2"
a.page.append(Page("bad page 3"))
print a
print
a.page.rollback()
print a
print
a.rollback()
print a
Output of the example:
The Title of the Article
Article.title=My title
Article.page.1.Page.text=page 1
Article.page.2.Page.text=page 2
Article.title=My bad title
Article.page.1.Page.text=page 1
Article.page.2.Page.text=bad page 2
Article.page.3.Page.text=bad page 3
Article.title=My bad title
Article.page.1.Page.text=page 1
Article.page.2.Page.text=page 2
Article.title=My title
Article.page.1.Page.text=page 1
Article.page.2.Page.text=page 2
"""
import sys
# pylint: disable-msg=W0403
from .transaction import Transaction, Transactionlist
# pylint: disable-msg=W0142, W0212
def _classinitializer(proc):
"basic idea stolen from zope.interface.advice, P.J. Eby"
def _newproc(*args, **kwargs):
frame = sys._getframe(1)
if '__module__' in frame.f_locals and not \
'__module__' in frame.f_code.co_varnames: # we are in a class
if '__metaclass__' in frame.f_locals:
raise SyntaxError("Don't use two class initializers or\n"
"a class initializer together with a "
"__metaclass__ hook")
def _makecls(name, bases, dic):
"create the class"
try:
cls = type(name, bases, dic)
except TypeError, e:
if "can't have only classic bases" in str(e):
cls = type(name, bases + (object,), dic)
else: # other strange errs, e.g. __slots__ conflicts
raise
proc(cls, *args, **kwargs)
return cls
frame.f_locals["__metaclass__"] = _makecls
else:
proc(*args, **kwargs)
# pylint: disable-msg=W0621
_newproc.__name__ = proc.__name__
_newproc.__module__ = proc.__module__
_newproc.__doc__ = proc.__doc__
_newproc.__dict__ = proc.__dict__
return _newproc
@_classinitializer
def gdtstruct_properties(cls, schema):
"""
Add properties to cls, according to the schema, which is a list
of pairs (fieldname, Gdtobject_subclass, docstring).
A Gdtobject_subclass is a callable converting the field value
into the Gdtobject_subclass.
Instances of cls are expected to have private attributes
with names determined by the field names.
"""
# from netconfpkg.gdt import Gdtstruct, Gdtobject
# if not issubclass(cls, Gdtstruct) and (type(cls) != Gdtobject):
# raise AttributeError('Class %s must be subclass of Gdtstruct!'
# % cls.__name__ )
for name, typecast, docstring in schema:
#if not issubclass(typecast, Gdtobject):
# raise AttributeError('Class %s must be subclass of Gdtobject!'
# % typecast.__name__ )
if hasattr(cls, name): # avoid accidental overriding
raise AttributeError('You are overriding %s!' % name)
# def _getter(self, name=name, typecast = typecast):
def _getter(self, name=name):
"get the property 'name'"
if not hasattr(self, '_' + name):
return None
# return typecast()
return getattr(self, '_' + name)
def _setter(self, value, name=name, typecast=typecast):
"set the property 'name'"
if value == None:
setattr(self, '_' + name, None)
else:
if hasattr(typecast, "apply"):
nval = typecast()
#print >> sys.stderr, typecast
nval.apply(value)
else:
nval = typecast(value)
setattr(self, '_' + name, nval)
def _deler(self, name=name):
setattr(self, '_' + name, None)
setattr(cls, name, property(_getter, _setter, _deler, doc=docstring))
cls._fields.add(name)
#cls._fields.sort()
cls._types[name]=typecast
@_classinitializer
def gdtlist_properties(cls, typecast):
"""
Add properties to cls, according to the schema, which is a list
of pairs (fieldname, Gdtobject_subclass, docstring).
A Gdtobject_subclass is a callable converting the field value
into the Gdtobject_subclass.
Instances of cls are expected to have private attributes
with names determined by the field names.
"""
cls._type=typecast
class Gdtobject(Transaction):
"The base of all Gdtobjects"
keyid = None
def tostr(self, prefix_string = None):
"returns a string in gdt representation"
raise NotImplementedError
def __str__(self):
return self.tostr()
def test(self):
"test on integrity, to be implemented by sub-classes"
return True
class Gdtcontainer(Gdtobject):
"A base container class, which contains several Gdtobjects"
def apply(self, other):
"copy from another object"
raise NotImplementedError
class Gdtstruct(Gdtcontainer):
"A base class, which can be used with gdtstruct_properties"
_fields = set()
_types = dict()
def test(self):
all_ok = True
for field in self._fields:
if hasattr(self, "test" + field):
tm = getattr(self, "test" + field)
if type(tm) == type(self.test):
try:
all_ok &= tm()
except NotImplementedError: # pylint: disable-msg=W0704
# ignore not implemented test methods
pass
elif hasattr(self, "_" + field):
val = getattr(self, "_" + field)
if hasattr(val, "test"):
tm = getattr(val, "test")
if type(tm) == type(self.test):
try:
all_ok &= tm()
except NotImplementedError: # pylint: disable-msg=W0704
# ignore not implemented test methods
pass
return all_ok
def tostr(self, prefix_string = None):
"returns a string in gdt representation"
if prefix_string == None:
prefix_string = self.__class__.__name__
mstr = ""
fields = list(self._fields)
fields.sort()
for name in fields:
if hasattr(self, name):
val = getattr(self, name)
if val == None:
continue
if isinstance(val, Gdtcontainer):
mstr += val.tostr("%s.%s" % (prefix_string, name))
else:
mstr += "%s.%s=%s\n" % (prefix_string, name, str(val))
return mstr
def fromstr(self, vals, value):
name=vals[0]
if name in self._fields:
if len(vals) > 1:
o = getattr(self, name)
if o == None:
o = self._types[name]()
o.fromstr(vals[1:], value)
setattr(self, name, o)
else:
if self._types[name] == bool:
setattr(self, name, value == "True" or False)
else:
setattr(self, name, self._types[name](value))
else:
raise KeyError
def apply(self, other):
"copy from another object"
for field in self._fields:
if hasattr(other, field):
setattr(self, field, getattr(other, field))
class Gdtlist(Transactionlist, Gdtcontainer):
"A list base class, which can hold Gdtobjects in a list."
_type=None
def tostr(self, prefix_string = None):
"returns a string in gdt representation"
if prefix_string == None:
prefix_string = self.__class__.__name__
mstr = ""
i = 0
for value in self:
i += 1
if isinstance(value, Gdtobject):
kid = value.keyid
if kid:
kid = getattr(value, kid)
else:
kid = str(i)
# mstr += value.tostr("%s.%s.%s"
# % (prefix_string, kid,
# value.__class__.__name__))
mstr += value.tostr("%s.%s"
% (prefix_string, kid))
else:
mstr += "%s.%d=%s\n" % (prefix_string, i, value)
return mstr
def fromstr(self, vals, value):
if vals[0] == self._type.__name__:
del vals[0]
index = int(vals[0])
if index > len(self):
for i in range(0, index - len(self)):
self.append(self._type())
child = self[index-1]
if isinstance(child, Gdtobject):
child.fromstr(vals[1:], value)
else:
self[index-1] = self._type(value)
def test(self):
all_ok = True
for val in self:
if hasattr(val, "test"):
tm = getattr(val, "test")
if type(tm) == type(self.test):
try:
all_ok &= tm()
except NotImplementedError: # pylint: disable-msg=W0704
# ignore not implemented test methods
pass
return all_ok
def apply(self, value):
del self[:]
self.extend(value)
Gdtstr = str
Gdtbool = bool
Gdtint = int