Commits

March Liu  committed a21f752

modify session to Session type
add predicate segment parser

  • Participants
  • Parent commits 66dd121

Comments (0)

Files changed (3)

File src/socrates/core.py

 from sqlalchemy.orm import sessionmaker, scoped_session, mapper
 import meta
 from socrates.types import Subject, Segment, Predicate, Type
+from socrates.parser import PreExprParser
 
 class Storage(object):
     """
 
     def newPredicate(self, name, objtype_name):
         """
-        此版本的查询条件并不完备,objType和谓词ID的查询应该通过联接严格约束
 >>> from sqlalchemy import DateTime
 >>> storage = Storage("sqlite://", create=True)
 >>> retype = storage.registeType("datetime", colType=DateTime, create=True)
         subjects = Subject.table
         String = self.registed_type["string"]
         strings = String.table
-        pid = self.Session.query(Subject.subject_id).\
-            filter(Subject.predicate_id==meta.IS).\
-            filter(Subject.obj==meta.PREDICATE).\
-            filter(select([String.obj], and_(String.subject_id==Subject.subject_id,
-                                             String.predicate_id==meta.NAME)).as_scalar()==name).scalar()
+        pid = self.get_preidcate_id_by_name(name)
         if not pid:
             pid = self.sequence()
-        if objtype_name == 'subject':
-            objType = meta.SUBJECT
-        else:
-            objType = self.Session.query(strings.c.subject_id).\
-                filter(strings.c.predicate_id==meta.NAME).\
-                filter(strings.c.obj==objtype_name).\
-                filter(select([subjects.c.obj], 
-                              and_(subjects.c.subject_id==strings.c.subject_id,
-                                   subjects.c.predicate_id==meta.IS,)).as_scalar()==meta.TYPE).scalar()
+        objType = self.get_type_id_by_name(objtype_name)
         storid = self.Session.query(subjects.c.obj).\
             filter(subjects.c.subject_id==objType).\
             filter(subjects.c.predicate_id==meta.STORAGE).scalar()
         self.Session.commit()
         return sid
 
-    def writeSegment(self, subject_id, predicate, obj, autocommit=True):
+    def writeSegment(self, subject_id, predicateExpr, obj, autocommit=True):
         """
-        此版本未解决同名谓词问题。仅适用于单一谓词应用,即每个谓词名仅对应一条谓词定义。
+存在复合类型的谓词时,如果没有有指定宾语类型,应该抛出错误,当前
+只是简单的给出第一个匹配顶,这是一种不严谨的方式,以后会改掉。
 >>> from sqlalchemy import DateTime
 >>> storage = Storage("sqlite://", create=True)
 >>> retype = storage.registeType("datetime", colType=DateTime, create=True)
->>> pid = storage.newPredicate('kssoid', 'string')
+>>> pid = storage.newPredicate('kssoid', 'string'
 >>> segment = storage.writeSegment(500, 'kssoid', 'liuxin2')
 >>> print segment.id
 15
 >>> print segment.subject_id
 12
         """
+        pname, tnames = self.parsePredicateExpression(predicateExpr)
+        if len(tnames)>1:
+            raise 'The expr %s extract object types more than one %s. Where I will write?'%(predicateExpr, tnames)
+
         needclose = True
         subjects = self.registed_storage["subject"]
         strings = self.registed_storage["string"]
         else:
             sid = self.sequence()
         pid = self.get_preidcate_id_by_name(predicate)
-        objType = self.Session.query(subjects.c.obj).\
-            filter(subjects.c.subject_id==pid).\
-            filter(subjects.c.predicate_id==meta.OBJTYPE).scalar() 
-        typename = self.Session.query(strings.c.obj).\
-            filter(strings.c.subject_id==objType).\
-            filter(strings.c.predicate_id==meta.NAME).scalar()
-        SegmentType = self.registed_type[typename]
+        SegmentType = self.registed_type[tnames[0]]
         segment = SegmentType(sid, pid, obj)
         self.Session.add(segment)
         if autocommit:
                 return Type(self, segments)
         return Subject(self, segments)
 
+    def filterSegmentsByPair(self, predicate_segment, obj):
+        """
+>>> storage = Storage("sqlite://", create=True)
+>>> pid = storage.newPredicate('ssoid', 'string')
+>>> ssoid = storage.getSubjectById(pid)
+>>> segment = storage.writeSegment(500, 'ssoid', 'March Liu')
+>>> segments = storage.filterSegmentsByPair('kssoid', 'March Liu')
+>>> print segments[0].subject_id
+500
+>>> print segments[0].predicate.name
+u'ssoid'
+>>> print segments[0].obj
+u'March Liu'
+>>> print len(segments)
+1
+        """
+        for k, v in pairs:
+            pname, tnames = self.parsePredicateExpression(k)
+            pid = self.get_preidcate_id_by_name(pname)
+            for tname in tnames:
+                SegmentType = self.registed_type[tnames[0]]
+                for row in self.Session.Query(SegmentType).filter(SegmentType.predicate_id==pid).filter(SegmentType.obj==v):
+                    yield row
+        self.Session.commit()
+
+    def parsePredicateExpression(self, expr):
+        parser = PreExprParser()
+        pname, tname = parser(expr)
+        if tname:
+            tnames = (tname,)
+        else:
+            objType = self.Session.query(subjects.c.obj).\
+                filter(subjects.c.subject_id==pid).\
+                filter(subjects.c.predicate_id==meta.OBJTYPE).scalar() 
+            tnames = self.Session.query(strings.c.obj).\
+                filter(strings.c.subject_id==objType).\
+                filter(strings.c.predicate_id==meta.NAME).all()
+        return pname, tnames
+
+    def get_type_id_by_name(self, name):
+        """
+>>> storage = Storage("sqlite://", create=True)
+>>> storage.get_preidcate_id_by_name("no true")
+>>> print storage.get_preidcate_id_by_name("string")==meta.STRING
+True
+        """
+        if objtype_name == 'subject':
+            re = meta.SUBJECT
+        else:
+            SegmentString = self.registed_type['string']
+            SegmentSubject = self.registed_type['subject']
+            re = self.Session.query(SegmentSubject.subject_id,).\
+                filter(SegmentSubject.predicate_id==meta.IS).\
+                filter(SegmentSubject.obj==meta.TYPE).\
+                filter(select([SegmentString.obj], 
+                              and_(SegmentString.subject_id==SegmentSubject.subject_id,
+                                   SegmentString.predicate_id==meta.NAME)).as_scalar()==name).scalar()
+        #session.close()
+        return re
+
     def get_preidcate_id_by_name(self, name):
         """
 >>> storage = Storage("sqlite://", create=True)

File src/socrates/parser.py

 import re
 from socrates import meta
 
-class Predicate(object):
+class PreExprParser(object):
     """
-    此版本还不能真正实现智能字典的功能
+Predicate expression parser
+>>> parser = PreExprParser()
+>>> parser('name')
+('name', None)
+>>> parser('name:string')
+('name', 'string')
+>>> parser("visit page")
+('visit page', None)
+>>> parser("visit page:string")
+('visit page', 'string')
+>>> parser('"test":"subject"')
+('test', 'subject')
+>>> parser('"test subject":"subject"')
+('test subject', 'subject')
+>>> parser('"test subject:page":"subject"')
+('test subject:page', 'subject')
+>>> parser('"test subject":"string type"')
+('test subject', 'string type')
+>>> parser('"test subject:page":"subject array"')
+('test subject:page', 'subject array')
+>>> parser('"test subject:page":"subject array:integer"')
+('test subject:page', 'subject array:integer')
     """
-    def __init__(self):
-        self.predicate={}
-
-class Type(object):
-    def __init__(self):
-        self.predicate={}
-
-    def __str__(self):
-        return self.name
-
-class PredicateParser(object):
-    """
->>> from sqlalchemy import create_engine
->>> from socrates import meta
->>> from socrates.core import Storage
->>> parser = PredicateParser(Storage(uri="sqlite://", create=True))
->>> predicate = parser('name')
->>> predicate.id
-7
->>> predicate.name
-'name'
->>> predicate.objType
-u'string'
->>> predicate = parser('objType')
->>> predicate.id
-4
->>> predicate.name
-'objType'
->>> predicate.objType
-u'subject'
->>> predicate = parser('storage:string')
->>> predicate.id
-9
->>> predicate.name
-'storage'
->>> predicate.objType
-u'string'
-    """
-    def __init__(self, storage):
-        self.storage = storage
-
-    syntax=re.compile(r"^([^\:]*)(\:.*)?$")
+    syntax=re.compile(r'^(?:\")?((?<=\")(?:[^\"]|(?<=\\).)*(?=\")|(?:[^\:]*))(?:\")?(?:\:(?:\")?((?<=\")(?:[^\"]|(?<=\\).)*(?=\")|(?:[^\:]*))(?:\")?)?$')
     def __call__(self, prdstr):
-        m = PredicateParser.syntax.match(prdstr)
+        m = PreExprParser.syntax.match(prdstr)
         if m:
-            re = Predicate()
-            session = self.storage.session
-            subjects = self.storage.registed_storage["subject"]
-            strings = self.storage.registed_storage["string"]
             name, objType = m.groups()
             return name, objType
         else:

File src/socrates/types.py

     def write(self, predicate, obj):
         segment = self.__storage.writeSegment(self.subject_id, predicate, obj)
         self.segments.append(segment)
-    def predicate(self, name):
-        pid = self.__storage.get_preidcate_id_by_name(name)
-        re = [segment.object for segment in self.segments if segment.predicate_id==pid]
+    def object(self, pname):
+        re = self.objects(pname)
         if len(re)==0:
             return None
         elif len(re)==1:
             return re[0]
         else:
             return re
-    pnames = property(lambda self:set([segment.predicate.name for segment in self.segments]))
+    def __eq__(self, obj):
+        return self.subject_id==obj.sbuject_id
+    def predicates(self):
+        return tuple(set(segment.preidcate for segment in self.segments))
+    def objects(self, pname):
+        pid = self.__storage.get_preidcate_id_by_name(pname)
+        return [segment.object for segment in self.segments if segment.predicate_id==pid]
+
+    pnames = property(lambda self:set(segment.predicate.name for segment in self.segments))
 
 class Predicate(Subject):
     objType = property(lambda self:self.predicate('objType'))
+    objTypes = property(lambda self:tuple(segment.object 
+                                          for segment in self.segments 
+                                          if semgents.predicate_id==meta.OBJTYPE))
     name = property(lambda self:self.predicate('name'))
 
 class Type(Subject):