Advertisement
s243a

pearl.py (2)

Aug 13th, 2022
789
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 11.72 KB | None | 0 0
  1. from lxml import etree, objectify
  2. from lxml.objectify import Element as Element
  3. from lxml.objectify import SubElement as SubElement
  4. from lxml.objectify import StringElement as StringElement
  5. from lxml.objectify import ObjectifiedElement as ObjectifiedElement
  6. from lxml.etree import ElementBase as ElementBase
  7. import inspect
  8. from types import MethodType
  9. from datetime import date
  10. from datetime import time
  11. iff=lambda a,b,c: b if a else c
  12. NSMAP  = {
  13.     "rdf" : "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
  14.     "rdfs" : "http://www.w3.org/2000/01/rdf-schema#",
  15.     "dcterms" : "http://purl.org/dc/elements/1.1/",
  16.     "foaf" : "http://xmlns.com/foaf/0.1/",
  17.     "owl" : "http://www.w3.org/2002/07/owl#",
  18.     "sioc" : "http://rdfs.org/sioc/ns#",
  19.     "pt" : "http://www.pearltrees.com/rdf/0.1/#"
  20.     }
  21.  
  22. #<pt:Tree rdf:about="url_for_some_tree">
  23. #   <dcterms:title><![CDATA[tree_title]]></dcterms:title>
  24. #   <dcterms:creator rdf:resource="https://www.pearltrees.com/somebody#sioc" />
  25. #   <pt:treeId>tree_id</pt:treeId>
  26. #   <pt:assoId>tree_id</pt:assoId>
  27. #   <pt:lastUpdate>2012-05-23T20:00:32</pt:lastUpdate>
  28. #   <pt:privacy>0</pt:privacy>
  29. #</pt:Tree>
  30.  
  31. PREFIXES_FM_PROP={
  32.   'title' : 'dcterms',
  33.   'creator' : 'creator',
  34.   'treeID' : 'pt',
  35.   'assoId' : 'pt',
  36.   'lastupdate' : 'pt',
  37.   'privacy' : 'pt'}
  38.  
  39.  
  40.  
  41. DEFAULTS = {
  42.   'privacy': (lambda x : 1),
  43.   'lastUpdate' : lambda : "" + date.today() + "T" + time.now()
  44. }
  45. iff=lambda a,b,c: b if a else c  
  46.  
  47.  
  48. # See: Custom Claass Lookup
  49. #      https://lxml.de/element_classes.html
  50. class MyLookup(etree.CustomElementClassLookup):
  51.   def lookup(self, node_type, document, namespace, name):
  52.     print("namespace="+str(namespace))
  53.     if namespace == 'http://www.pearltrees.com/rdf/0.1/#':
  54.       if name == "Tree":
  55.         return PT_TreeLXML
  56.     else:
  57.      return None  # pass on to (default) fallback
  58.  
  59. def strip_ns(name):
  60.   if name[0]=='{':
  61.     return name.tag.split('}')[1]
  62.   else:
  63.     return name
  64. def get_verb(name):
  65.   for i in range(0,len(name)-1):
  66.     if name[i]!="_":
  67.       three_chars=name[i,i+3]
  68.       if three_chars in ('get','has','set','add'):
  69.         return three_chars
  70.       else:
  71.         return None
  72.   return None
  73. parser = etree.XMLParser()
  74. parser.set_element_class_lookup(MyLookup())
  75. root_str='''<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  76.         xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
  77.         xmlns:foaf="http://xmlns.com/foaf/0.1/"
  78.         xmlns:dcterms="http://purl.org/dc/elements/1.1/"
  79.         xmlns:pt="http://www.pearltrees.com/rdf/0.1/#"></rdf:RDF>'''
  80. root=etree.fromstring(root_str, parser)
  81. def asgn(name,val,default=None,defaults=None):
  82.   if default is None:
  83.     if defaults is None:
  84.       defaults=DEFAULTS
  85.     default=defaults[name]
  86.   try:
  87.     iff(name in val,val[name],default)
  88.   except:
  89.     if val is None:
  90.       val=default
  91.   return val
  92.  
  93. def add_boilerplate_meth(cls,verb,pred):
  94.   print("cls="+str(cls))
  95.   print("verb="+str(verb))
  96.   print("pred="+str(pred))
  97.   def new_meth(self,*prop,**kw):
  98.     return __getattr__(self,"_"+verb+"_"+"pred",*prop,*kw)
  99.   if str(verb) in ('set','get','add','has'):
  100.     setattr(cls,"_"+verb+"_"+pred,MethodType(new_meth, cls))
  101.   else:
  102.     raise Exception("unkonwn verb in add_boilerplate")
  103. def add_boilerplate_methods(cls,predicates,verbs=('set','get','add','has')):
  104.   for verb in verbs:
  105.     for pred in predicates:
  106.       add_boilerplate_meth(cls,verb,pred)
  107.  
  108. class PT_Obj(object):
  109.   def __add_item_helper__(tag,prefix=None,nsmap=NSMAP,ns=None):
  110.     if ns is None and prefix is None:
  111.       if tag in PREFIXES_FM_PROP:
  112.         prefix=PREFIXES_FM_PROP[tag]
  113.     if ns is None and prefix is not None:
  114.       ns=nsmap[prefix]
  115.     if ns is not None:
  116.       tag="{" + ns + "}" + tag
  117.     #value=asgn(tag,value)
  118.     return tag
  119.   #This is a replacement for the python new clas
  120.   # See: https://www.geeksforgeeks.org/__new__-in-python/  
  121.   def _new2(cls, *args,**kw):
  122.     self.__init2__
  123.     return self
  124.   #This is a replacement for the python new clas
  125.   # See: https://www.geeksforgeeks.org/__new__-in-python/    
  126.   def __init2__(self, *args,**kw):
  127.     pass
  128.   def __getattr__(self, full_name):
  129.     verb,name=get_verb(full_name)  
  130.     if verb=='get':
  131.       return lambda : self._get_item(name)
  132.     elif verb=='set':
  133.       return lambda value : self._set_item(name,value)
  134.     elif verb=='has':
  135.       return lambda : self._has_item(name)
  136.     elif verb=='add':
  137.       def adder_method():
  138.         iff(len(p)>0,self._add_prop(name*p,**kw),
  139.                      self._add_item(name*p,**kw))        
  140.       return adder_method
  141.     # Need to code some functional programming piping to do this.
  142.     #Add if missing then set item
  143.     # elif verb=='aSet'
  144.     #   if Not self._has_item(name):
  145.     #     item=self._add_item(name)
  146.     #     return item._setText(value)
  147.     #   return self._set_item(value)  
  148.     #inspect.getmembers(self, predicate=inspect.ismethod)
  149.     else:
  150.      # https://docs.python.org/3/library/inspect.html#inspect.getmembers
  151.      # https://stackoverflow.com/questions/34439/finding-what-methods-a-python-object-has#comment115434232_28220562
  152.      for n,v in inspect.getmembers(self):
  153.        if n==full_name:
  154.          return v
  155.  
  156.   def _add_item(self,tag,nsmap=NSMAP,prefix=None):
  157.     pass
  158.   def _remove_item(self,about,text=None):
  159.     pass
  160.   def _add_prop(self,prop,value=None,prefix=None,nsmap=NSMAP,ns=None):
  161.     self.setItem(
  162.       self._add_item(prop,value,nsmap))
  163.   def _setItem(self,item,value):
  164.     pass
  165.   def _remove_prop():  
  166.     pass
  167. # - In the orginal pearltrees a tree once was analoges to a mind map for a given
  168. # topic. (e.g. ...)
  169. # - In PT2.0 and on the mindmap concept was replaced by a grid like strucures
  170. # and each node of the tree was replaced by a buch of cards.
  171. # - In either case the tree is the principle web page for each topic containing a number
  172. # of sub items. One major difference is that later version of pearltree lose much of the
  173. # tree struture  def __init__(self,**kw):
  174. #<pt:Tree rdf:about="url_for_some_tree">
  175. #   <dcterms:title><![CDATA[tree_title]]></dcterms:title>
  176. #   <dcterms:creator rdf:resource="https://www.pearltrees.com/somebody#sioc" />
  177. #   <pt:treeId>tree_id</pt:treeId>
  178. #   <pt:assoId>tree_id</pt:assoId>
  179. #   <pt:lastUpdate>2012-05-23T20:00:32</pt:lastUpdate>
  180. #   <pt:privacy>0</pt:privacy>
  181. #</pt:Tree>
  182.  
  183. class PT_Tree(PT_Obj):
  184.   def __init__(self,**kw):
  185.     self.__init2__
  186.   def _new2(cls,*args, **kw):
  187.     self.__init2__(*args,**kw)
  188.     return self
  189.   #This is a replacement for the python new clas
  190.   # See: https://www.geeksforgeeks.org/__new__-in-python/    
  191.   def __init2__(self,attrib=None, parent=None, nsmap=NSMAP, props=None, childern=None):
  192.     pass
  193.   def _remove_pearl(about):
  194.     pass
  195. add_boilerplate_methods(
  196.   PT_Tree,(
  197.     'title',
  198.     'creator',
  199.     'treeId',
  200.     'assoId',
  201.     'lastUpdate',
  202.     'privacy'))
  203.  
  204.  
  205. class PT_Objectify(ObjectifiedElement,PT_Obj):
  206.   #__init__(attrib=None, nsmap=None, *children, **_extra)
  207.   #x.__init__(...) initializes x; see help(type(x)) for signature
  208.   #def __init2__(self,attrib, nsmap=NSMAP, *children, **_extra):
  209.   #
  210.   #
  211.   #  print("attrib=" + str(attrib))
  212.   #  print("nsmap=" + str(nsmap))
  213.   #  print("childern=" + str(children))
  214.   #  print("_extra=" + str(_extra))
  215.   #  StringElement.__init__(self,attrib,nsmap,*children,**_extra)
  216.   #  print("Parent Intailized")
  217.   def __new__(cls,attr, parent=None,  nsmap=NSMAP, *args,**kw):
  218.     PT_Objectify.__new2__(cls,attr, parent, *args,**kw)
  219.   def __new2__(cls,attr, parent=None,  nsmap=NSMAP, *args,**kw):
  220.     # https://lxml.de/2.1/namespace_extensions.html
  221.     #etree.setDefaultElementClass(cls)
  222.     print("attrib=" + str(attr))
  223.     print("parent=" + str(parent))
  224.     attr2=PT_Obj.__add_item_helper__(attr,prefix=None,nsmap=NSMAP,ns=None)
  225.     if parent is None:
  226.       el=objectify.Element(attr2)
  227.     else:
  228.       el=objectify.SubElement(parent,attr2)
  229.     PT_Obj.__init2__(el,parent,attr,*args,**kw)
  230.     return el #PT_Tree.__new__(el,*args,**kw)
  231.   def __init__(self,attrib, parent=None, nsmap=NSMAP, *children, **properties):
  232.     self.__init2__(self,attrib, parent=None, nsmap=NSMAP, *children, **properties)
  233.   def __init2__(self,attrib=None, parent=None, nsmap=NSMAP, props=None, childern=None):
  234.     #for child in childern:
  235.     #  objectify.SubElement(self,child)
  236.     for prop,val in props.items():
  237.       PROP=getattr(objectify.E,prop)
  238.       objectify.SubElement(self,PROP(val))
  239.   def _get_item(name):    
  240.     name2=strip_ns(name) #TODO: Verify if this is necessary
  241.     find = objectify.ObjectPath("."+name2)
  242.     try:
  243.       return find(self)
  244.     except:
  245.       return None    
  246.   def _add_item(self,tag,nsmap=NSMAP,prefix=None):
  247.     tag2=__add_item_helper__(self,tag,prefix=None,nsmap=NSMAP,ns=None)
  248.     item=objectify.SubElement(self,tag2)
  249.     return child_ell
  250.   def _has_item(name):
  251.     return self._get_item(name) is none
  252.   #Propbably redundent:
  253.   #def _add_prop(self,prop,value=None,prefix=None,nsmap=NSMAP,ns=None):
  254.   #  self.setItem(
  255.   #    self._add_item(prop,value,nsmap))
  256.   def _set_item(self,item_name,value):
  257.     item=self._get_item(item_name)
  258.     #TODO: Maybe throw warning if item text is already set
  259.     item._setText(value)
  260.   def __str(self):
  261.     return etree.tostring(self, pretty_print=True, xml_declaration=True,encoding='UTF8').decode("unicode_escape")
  262.  
  263. class PT_TreeLXML(PT_Objectify,PT_Tree):
  264.   #def __init__(self,attrib, nsmap=NSMAP, *children, **_extra):
  265.   #  PT_Objectify.__init__(self,attrib, nsmap, *children, **_extra)
  266.   #self.__init__=
  267.   def __new__(*args,**kw):
  268.     return ObjectifiedElement.__new__(*args,**kw)
  269.   def __new2__(attr="Tree",parent=root,nsmap=NSMAP,props=None,prefix="pt",ns=None):
  270.     # https://lxml.de/2.1/namespace_extensions.html
  271.    
  272.     #etree.setDefaultElementClass(cls)
  273.     if attr is None:
  274.       return ElementBase.__new__(PT_TreeLXML)
  275.     else:
  276.       attr2=PT_Obj.__add_item_helper__(attr,prefix=prefix,nsmap=nsmap,ns=None)    
  277.  
  278.       el=objectify.SubElement(parent,attr2,nsmap=nsmap)
  279.       print(etree.tostring(el, pretty_print=True, xml_declaration=True,encoding='UTF8').decode("unicode_escape"))
  280.       PT_Obj.__init2__(el,attr2,parent,nsmap,props)
  281.       return el #PT_Tree.__new__(el,*args,**kw)
  282.   def __init2__(self,attr=None,parent=None, nsmap=NSMAP, props=None, childern=None):
  283.     #for child in childern:
  284.     #  se=objectify.SubElement(self,child,nsmap=NSMAP)
  285.     #  print(etree.tostring(se, pretty_print=True, xml_declaration=True,encoding='UTF8').decode("unicode_escape"))
  286.     for prop,val in props.items():
  287.       #PROP=getattr(objectify.E,prop)
  288.       #se=objectify.SubElement(self,child,PROP(val),nsmap=NSMAP)
  289.  
  290.  
  291.       self._add_prop(prop,value=val,prefix=None,nsmap=NSMAP,ns=None)
  292.       #print(etree.tostring(se, pretty_print=True, xml_declaration=True,encoding='UTF8').decode("unicode_escape"))
  293.   def __str__(self):
  294.     return PT_Objectify.__str__(self)
  295.   #def _init(self):
  296.   #  PT_Objectify._init()
  297.  
  298.     #PT_Objectify.__init__(self,attrib, nsmap, *children, **_extra)
  299.  
  300. #<pt:Tree rdf:about="url_for_some_tree">
  301. #   <dcterms:title><![CDATA[tree_title]]></dcterms:title>
  302. #   <dcterms:creator rdf:resource="https://www.pearltrees.com/somebody#sioc" />
  303. #   <pt:treeId>tree_id</pt:treeId>
  304. #   <pt:assoId>tree_id</pt:assoId>
  305. #   <pt:lastUpdate>2012-05-23T20:00:32</pt:lastUpdate>
  306. #   <pt:privacy>0</pt:privacy>
  307. #</pt:Tree>
  308. def treeTest(**kw):
  309.   tree=PT_TreeLXML.__new2__(
  310.     props={
  311.       'title' : 'my tree',
  312.       'creator' : 'bob',
  313.       'tree_id' : '1234',
  314.       'assoID' : '23',
  315.       'lastUpdate' :'yesterday',
  316.       'privacy' : '1'})
  317.   print(str(tree))
  318. #def main():
  319. treeTest()
  320. print(etree.tostring(root, pretty_print=True, xml_declaration=True,encoding='UTF8').decode("unicode_escape"))
  321.  
  322. #if __name__ == "__main__" or 1 == 1: #For testing we will always run main.
  323. #    main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement