from lxml import etree, objectify
from lxml.objectify import Element as Element
from lxml.objectify import SubElement as SubElement
from lxml.objectify import StringElement as StringElement
from lxml.objectify import ObjectifiedElement as ObjectifiedElement
from lxml.etree import ElementBase as ElementBase
import inspect
from types import MethodType
from datetime import date
from datetime import time
iff=lambda a,b,c: b if a else c
NSMAP = {
"rdf" : "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
"rdfs" : "http://www.w3.org/2000/01/rdf-schema#",
"dcterms" : "http://purl.org/dc/elements/1.1/",
"foaf" : "http://xmlns.com/foaf/0.1/",
"owl" : "http://www.w3.org/2002/07/owl#",
"sioc" : "http://rdfs.org/sioc/ns#",
"pt" : "http://www.pearltrees.com/rdf/0.1/#"
}
#
#
#
# tree_id
# tree_id
# 2012-05-23T20:00:32
# 0
#
PREFIXES_FM_PROP={
'title' : 'dcterms',
'creator' : 'creator',
'treeID' : 'pt',
'assoId' : 'pt',
'lastupdate' : 'pt',
'privacy' : 'pt'}
DEFAULTS = {
'privacy': (lambda x : 1),
'lastUpdate' : lambda : "" + date.today() + "T" + time.now()
}
iff=lambda a,b,c: b if a else c
# See: Custom Claass Lookup
# https://lxml.de/element_classes.html
class MyLookup(etree.CustomElementClassLookup):
def lookup(self, node_type, document, namespace, name):
print("namespace="+str(namespace))
if namespace == 'http://www.pearltrees.com/rdf/0.1/#':
if name == "Tree":
return PT_TreeLXML
else:
return None # pass on to (default) fallback
def strip_ns(name):
if name[0]=='{':
return name.tag.split('}')[1]
else:
return name
def get_verb(name):
for i in range(0,len(name)-1):
if name[i]!="_":
three_chars=name[i,i+3]
if three_chars in ('get','has','set','add'):
return three_chars
else:
return None
return None
parser = etree.XMLParser()
parser.set_element_class_lookup(MyLookup())
root_str=''''''
root=etree.fromstring(root_str, parser)
def asgn(name,val,default=None,defaults=None):
if default is None:
if defaults is None:
defaults=DEFAULTS
default=defaults[name]
try:
iff(name in val,val[name],default)
except:
if val is None:
val=default
return val
def add_boilerplate_meth(cls,verb,pred):
print("cls="+str(cls))
print("verb="+str(verb))
print("pred="+str(pred))
def new_meth(self,*prop,**kw):
return __getattr__(self,"_"+verb+"_"+"pred",*prop,*kw)
if str(verb) in ('set','get','add','has'):
setattr(cls,"_"+verb+"_"+pred,MethodType(new_meth, cls))
else:
raise Exception("unkonwn verb in add_boilerplate")
def add_boilerplate_methods(cls,predicates,verbs=('set','get','add','has')):
for verb in verbs:
for pred in predicates:
add_boilerplate_meth(cls,verb,pred)
class PT_Obj(object):
def __add_item_helper__(tag,prefix=None,nsmap=NSMAP,ns=None):
if ns is None and prefix is None:
if tag in PREFIXES_FM_PROP:
prefix=PREFIXES_FM_PROP[tag]
if ns is None and prefix is not None:
ns=nsmap[prefix]
if ns is not None:
tag="{" + ns + "}" + tag
#value=asgn(tag,value)
return tag
#This is a replacement for the python new clas
# See: https://www.geeksforgeeks.org/__new__-in-python/
def _new2(cls, *args,**kw):
self.__init2__
return self
#This is a replacement for the python new clas
# See: https://www.geeksforgeeks.org/__new__-in-python/
def __init2__(self, *args,**kw):
pass
def __getattr__(self, full_name):
verb,name=get_verb(full_name)
if verb=='get':
return lambda : self._get_item(name)
elif verb=='set':
return lambda value : self._set_item(name,value)
elif verb=='has':
return lambda : self._has_item(name)
elif verb=='add':
def adder_method():
iff(len(p)>0,self._add_prop(name*p,**kw),
self._add_item(name*p,**kw))
return adder_method
# Need to code some functional programming piping to do this.
#Add if missing then set item
# elif verb=='aSet'
# if Not self._has_item(name):
# item=self._add_item(name)
# return item._setText(value)
# return self._set_item(value)
#inspect.getmembers(self, predicate=inspect.ismethod)
else:
# https://docs.python.org/3/library/inspect.html#inspect.getmembers
# https://stackoverflow.com/questions/34439/finding-what-methods-a-python-object-has#comment115434232_28220562
for n,v in inspect.getmembers(self):
if n==full_name:
return v
def _add_item(self,tag,nsmap=NSMAP,prefix=None):
pass
def _remove_item(self,about,text=None):
pass
def _add_prop(self,prop,value=None,prefix=None,nsmap=NSMAP,ns=None):
self.setItem(
self._add_item(prop,value,nsmap))
def _setItem(self,item,value):
pass
def _remove_prop():
pass
# - In the orginal pearltrees a tree once was analoges to a mind map for a given
# topic. (e.g. ...)
# - In PT2.0 and on the mindmap concept was replaced by a grid like strucures
# and each node of the tree was replaced by a buch of cards.
# - In either case the tree is the principle web page for each topic containing a number
# of sub items. One major difference is that later version of pearltree lose much of the
# tree struture def __init__(self,**kw):
#
#
#
# tree_id
# tree_id
# 2012-05-23T20:00:32
# 0
#
class PT_Tree(PT_Obj):
def __init__(self,**kw):
self.__init2__
def _new2(cls,*args, **kw):
self.__init2__(*args,**kw)
return self
#This is a replacement for the python new clas
# See: https://www.geeksforgeeks.org/__new__-in-python/
def __init2__(self,attrib=None, parent=None, nsmap=NSMAP, props=None, childern=None):
pass
def _remove_pearl(about):
pass
add_boilerplate_methods(
PT_Tree,(
'title',
'creator',
'treeId',
'assoId',
'lastUpdate',
'privacy'))
class PT_Objectify(ObjectifiedElement,PT_Obj):
#__init__(attrib=None, nsmap=None, *children, **_extra)
#x.__init__(...) initializes x; see help(type(x)) for signature
#def __init2__(self,attrib, nsmap=NSMAP, *children, **_extra):
#
#
# print("attrib=" + str(attrib))
# print("nsmap=" + str(nsmap))
# print("childern=" + str(children))
# print("_extra=" + str(_extra))
# StringElement.__init__(self,attrib,nsmap,*children,**_extra)
# print("Parent Intailized")
def __new__(cls,attr, parent=None, nsmap=NSMAP, *args,**kw):
PT_Objectify.__new2__(cls,attr, parent, *args,**kw)
def __new2__(cls,attr, parent=None, nsmap=NSMAP, *args,**kw):
# https://lxml.de/2.1/namespace_extensions.html
#etree.setDefaultElementClass(cls)
print("attrib=" + str(attr))
print("parent=" + str(parent))
attr2=PT_Obj.__add_item_helper__(attr,prefix=None,nsmap=NSMAP,ns=None)
if parent is None:
el=objectify.Element(attr2)
else:
el=objectify.SubElement(parent,attr2)
PT_Obj.__init2__(el,parent,attr,*args,**kw)
return el #PT_Tree.__new__(el,*args,**kw)
def __init__(self,attrib, parent=None, nsmap=NSMAP, *children, **properties):
self.__init2__(self,attrib, parent=None, nsmap=NSMAP, *children, **properties)
def __init2__(self,attrib=None, parent=None, nsmap=NSMAP, props=None, childern=None):
#for child in childern:
# objectify.SubElement(self,child)
for prop,val in props.items():
PROP=getattr(objectify.E,prop)
objectify.SubElement(self,PROP(val))
def _get_item(name):
name2=strip_ns(name) #TODO: Verify if this is necessary
find = objectify.ObjectPath("."+name2)
try:
return find(self)
except:
return None
def _add_item(self,tag,nsmap=NSMAP,prefix=None):
tag2=__add_item_helper__(self,tag,prefix=None,nsmap=NSMAP,ns=None)
item=objectify.SubElement(self,tag2)
return child_ell
def _has_item(name):
return self._get_item(name) is none
#Propbably redundent:
#def _add_prop(self,prop,value=None,prefix=None,nsmap=NSMAP,ns=None):
# self.setItem(
# self._add_item(prop,value,nsmap))
def _set_item(self,item_name,value):
item=self._get_item(item_name)
#TODO: Maybe throw warning if item text is already set
item._setText(value)
def __str(self):
return etree.tostring(self, pretty_print=True, xml_declaration=True,encoding='UTF8').decode("unicode_escape")
class PT_TreeLXML(PT_Objectify,PT_Tree):
#def __init__(self,attrib, nsmap=NSMAP, *children, **_extra):
# PT_Objectify.__init__(self,attrib, nsmap, *children, **_extra)
#self.__init__=
def __new__(*args,**kw):
return ObjectifiedElement.__new__(*args,**kw)
def __new2__(attr="Tree",parent=root,nsmap=NSMAP,props=None,prefix="pt",ns=None):
# https://lxml.de/2.1/namespace_extensions.html
#etree.setDefaultElementClass(cls)
if attr is None:
return ElementBase.__new__(PT_TreeLXML)
else:
attr2=PT_Obj.__add_item_helper__(attr,prefix=prefix,nsmap=nsmap,ns=None)
el=objectify.SubElement(parent,attr2,nsmap=nsmap)
print(etree.tostring(el, pretty_print=True, xml_declaration=True,encoding='UTF8').decode("unicode_escape"))
PT_Obj.__init2__(el,attr2,parent,nsmap,props)
return el #PT_Tree.__new__(el,*args,**kw)
def __init2__(self,attr=None,parent=None, nsmap=NSMAP, props=None, childern=None):
#for child in childern:
# se=objectify.SubElement(self,child,nsmap=NSMAP)
# print(etree.tostring(se, pretty_print=True, xml_declaration=True,encoding='UTF8').decode("unicode_escape"))
for prop,val in props.items():
#PROP=getattr(objectify.E,prop)
#se=objectify.SubElement(self,child,PROP(val),nsmap=NSMAP)
self._add_prop(prop,value=val,prefix=None,nsmap=NSMAP,ns=None)
#print(etree.tostring(se, pretty_print=True, xml_declaration=True,encoding='UTF8').decode("unicode_escape"))
def __str__(self):
return PT_Objectify.__str__(self)
#def _init(self):
# PT_Objectify._init()
#PT_Objectify.__init__(self,attrib, nsmap, *children, **_extra)
#
#
#
# tree_id
# tree_id
# 2012-05-23T20:00:32
# 0
#
def treeTest(**kw):
tree=PT_TreeLXML.__new2__(
props={
'title' : 'my tree',
'creator' : 'bob',
'tree_id' : '1234',
'assoID' : '23',
'lastUpdate' :'yesterday',
'privacy' : '1'})
print(str(tree))
#def main():
treeTest()
print(etree.tostring(root, pretty_print=True, xml_declaration=True,encoding='UTF8').decode("unicode_escape"))
#if __name__ == "__main__" or 1 == 1: #For testing we will always run main.
# main()