@@ -93,6 +93,8 @@ def setupTracker(dirname, backend="anydbm", optimize=False):
9393def setupSchema (db , create , module ):
9494 mls = module .Class (db , "mls" , name = String ())
9595 mls .setkey ("name" )
96+ keyword = module .Class (db , "keyword" , name = String ())
97+ keyword .setkey ("name" )
9698 status = module .Class (db , "status" , name = String (), mls = Multilink ("mls" ))
9799 status .setkey ("name" )
98100 priority = module .Class (db , "priority" , name = String (), order = String ())
@@ -115,7 +117,8 @@ def setupSchema(db, create, module):
115117 foo = Interval (quiet = True , default_value = date .Interval ('-1w' )),
116118 files = Multilink ("file" ), assignedto = Link ('user' , quiet = True ,
117119 rev_multilink = 'issues' ), priority = Link ('priority' ),
118- spam = Multilink ('msg' ), feedback = Link ('msg' ))
120+ spam = Multilink ('msg' ), feedback = Link ('msg' ),
121+ keywords = Multilink ('keyword' ))
119122 stuff = module .Class (db , "stuff" , stuff = String ())
120123 session = module .Class (db , 'session' , title = String ())
121124 msg = module .FileClass (db , "msg" , date = Date (),
@@ -1539,8 +1542,8 @@ def testIndexingPropertiesOnImport(self):
15391542 # import an issue
15401543 title = 'Bzzt'
15411544 nodeid = self .db .issue .import_list (['title' , 'messages' , 'files' ,
1542- 'spam' , 'nosy' , 'superseder' ], [repr (title ), '[]' , '[]' ,
1543- '[]' , '[]' , '[]' ])
1545+ 'spam' , 'nosy' , 'superseder' , 'keywords' ], [repr (title ), '[]' ,
1546+ '[]' , '[]' , '[]' , '[]' , '[]' ])
15441547 self .db .commit ()
15451548
15461549 # Content of title attribute is indexed
@@ -1926,6 +1929,64 @@ def testFilteringMultilink(self):
19261929 ae (filt (None , {'nosy' : ['1' ,'2' ]}, ('+' , 'status' ),
19271930 ('-' , 'deadline' )), ['4' , '3' ])
19281931
1932+ # Currently fails on the very first test for mysql
1933+ @pytest .mark .xfail
1934+ def testFilteringMultilinkExpression (self ):
1935+ ae , iiter = self .filteringSetup ()
1936+ kw1 = self .db .keyword .create (name = 'Key1' )
1937+ kw2 = self .db .keyword .create (name = 'Key2' )
1938+ kw3 = self .db .keyword .create (name = 'Key3' )
1939+ kw4 = self .db .keyword .create (name = 'Key4' )
1940+ self .db .issue .set ('1' , keywords = [kw1 , kw2 ])
1941+ self .db .issue .set ('2' , keywords = [kw1 , kw3 ])
1942+ self .db .issue .set ('3' , keywords = [kw2 , kw3 , kw4 ])
1943+ self .db .issue .set ('4' , keywords = [kw1 , kw2 , kw4 ])
1944+ self .db .commit ()
1945+ kw = 'keywords'
1946+ for filt in iiter ():
1947+ # '1' and '2'
1948+ ae (filt (None , {kw : ['1' , '2' , '-3' ]}),
1949+ ['1' , '4' ])
1950+ # ('2' and '4') and '1'
1951+ ae (filt (None , {kw : ['1' , '2' , '4' , '-3' , '-3' ]}),
1952+ ['4' ])
1953+ # not '4' and '3'
1954+ ae (filt (None , {kw : ['3' , '4' , '-2' , '-3' ]}),
1955+ ['2' ])
1956+ # (not '4' and '3') and '2'
1957+ ae (filt (None , {kw : ['2' , '3' , '4' , '-2' , '-3' , '-3' ]}),
1958+ [])
1959+ # '1' or '2' without explicit 'or'
1960+ ae (filt (None , {kw : ['1' , '2' ]}),
1961+ ['1' , '2' , '3' , '4' ])
1962+ # '1' or '2' with explicit 'or'
1963+ ae (filt (None , {kw : ['1' , '2' , '-4' ]}),
1964+ ['1' , '2' , '3' , '4' ])
1965+ # '3' or '4' without explicit 'or'
1966+ ae (filt (None , {kw : ['3' , '4' ]}),
1967+ ['2' , '3' , '4' ])
1968+ # '3' or '4' with explicit 'or'
1969+ ae (filt (None , {kw : ['3' , '4' , '-4' ]}),
1970+ ['2' , '3' , '4' ])
1971+ # ('3' and '4') or ('1' and '2')
1972+ ae (filt (None , {kw : ['3' , '4' , '-3' , '1' , '2' , '-3' , '-4' ]}),
1973+ ['1' , '3' , '4' ])
1974+ # '2' and empty
1975+ ae (filt (None , {kw : ['2' , '-1' , '-3' ]}),
1976+ [])
1977+ self .db .issue .set ('1' , keywords = [])
1978+ self .db .commit ()
1979+ for filt in iiter ():
1980+ ae (filt (None , {kw : ['-1' ]}),
1981+ ['1' ])
1982+ # These do not work with any of the backends currently
1983+ # '3' or empty (with explicit 'or')
1984+ #ae(filt(None, {kw: ['3', '-1', '-4']}),
1985+ # ['1', '2', '3'])
1986+ # '3' or empty (without explicit 'or')
1987+ #ae(filt(None, {kw: ['3', '-1']}),
1988+ # ['1', '2', '3'])
1989+
19291990 def testFilteringRevMultilink (self ):
19301991 ae , iiter = self .filteringSetupTransitiveSearch ('user' )
19311992 ni = 'nosy_issues'
@@ -2683,18 +2744,19 @@ def stdoutwrite(s):
26832744
26842745 issue_class_spec = tool .do_specification (["issue" ])
26852746 self .assertEqual (sorted (soutput ),
2686- ['assignedto: <roundup.hyperdb.Link to "user">\n ' ,
2687- 'deadline: <roundup.hyperdb.Date>\n ' ,
2688- 'feedback: <roundup.hyperdb.Link to "msg">\n ' ,
2689- 'files: <roundup.hyperdb.Multilink to "file">\n ' ,
2690- 'foo: <roundup.hyperdb.Interval>\n ' ,
2691- 'messages: <roundup.hyperdb.Multilink to "msg">\n ' ,
2692- 'nosy: <roundup.hyperdb.Multilink to "user">\n ' ,
2693- 'priority: <roundup.hyperdb.Link to "priority">\n ' ,
2694- 'spam: <roundup.hyperdb.Multilink to "msg">\n ' ,
2695- 'status: <roundup.hyperdb.Link to "status">\n ' ,
2696- 'superseder: <roundup.hyperdb.Multilink to "issue">\n ' ,
2697- 'title: <roundup.hyperdb.String>\n ' ])
2747+ ['assignedto: <roundup.hyperdb.Link to "user">\n ' ,
2748+ 'deadline: <roundup.hyperdb.Date>\n ' ,
2749+ 'feedback: <roundup.hyperdb.Link to "msg">\n ' ,
2750+ 'files: <roundup.hyperdb.Multilink to "file">\n ' ,
2751+ 'foo: <roundup.hyperdb.Interval>\n ' ,
2752+ 'keywords: <roundup.hyperdb.Multilink to "keyword">\n ' ,
2753+ 'messages: <roundup.hyperdb.Multilink to "msg">\n ' ,
2754+ 'nosy: <roundup.hyperdb.Multilink to "user">\n ' ,
2755+ 'priority: <roundup.hyperdb.Link to "priority">\n ' ,
2756+ 'spam: <roundup.hyperdb.Multilink to "msg">\n ' ,
2757+ 'status: <roundup.hyperdb.Link to "status">\n ' ,
2758+ 'superseder: <roundup.hyperdb.Multilink to "issue">\n ' ,
2759+ 'title: <roundup.hyperdb.String>\n ' ])
26982760
26992761 #userclassprop=tool.do_list(["mls"])
27002762 #tool.print_designator = False
@@ -2793,8 +2855,9 @@ def testAddProperty(self):
27932855 props = self .db .issue .getprops ()
27942856 keys = sorted (props .keys ())
27952857 self .assertEqual (keys , ['activity' , 'actor' , 'assignedto' , 'creation' ,
2796- 'creator' , 'deadline' , 'feedback' , 'files' , 'fixer' , 'foo' , 'id' , 'messages' ,
2797- 'nosy' , 'priority' , 'spam' , 'status' , 'superseder' , 'title' ])
2858+ 'creator' , 'deadline' , 'feedback' , 'files' , 'fixer' , 'foo' ,
2859+ 'id' , 'keywords' , 'messages' , 'nosy' , 'priority' , 'spam' ,
2860+ 'status' , 'superseder' , 'title' ])
27982861 self .assertEqual (self .db .issue .get ('1' , "fixer" ), None )
27992862
28002863 def testRemoveProperty (self ):
@@ -2806,8 +2869,9 @@ def testRemoveProperty(self):
28062869 props = self .db .issue .getprops ()
28072870 keys = sorted (props .keys ())
28082871 self .assertEqual (keys , ['activity' , 'actor' , 'assignedto' , 'creation' ,
2809- 'creator' , 'deadline' , 'feedback' , 'files' , 'foo' , 'id' , 'messages' ,
2810- 'nosy' , 'priority' , 'spam' , 'status' , 'superseder' ])
2872+ 'creator' , 'deadline' , 'feedback' , 'files' , 'foo' , 'id' ,
2873+ 'keywords' , 'messages' , 'nosy' , 'priority' , 'spam' , 'status' ,
2874+ 'superseder' ])
28112875 self .assertEqual (self .db .issue .list (), ['1' ])
28122876
28132877 def testAddRemoveProperty (self ):
@@ -2821,7 +2885,8 @@ def testAddRemoveProperty(self):
28212885 keys = sorted (props .keys ())
28222886 self .assertEqual (keys , ['activity' , 'actor' , 'assignedto' , 'creation' ,
28232887 'creator' , 'deadline' , 'feedback' , 'files' , 'fixer' , 'foo' , 'id' ,
2824- 'messages' , 'nosy' , 'priority' , 'spam' , 'status' , 'superseder' ])
2888+ 'keywords' , 'messages' , 'nosy' , 'priority' , 'spam' , 'status' ,
2889+ 'superseder' ])
28252890 self .assertEqual (self .db .issue .list (), ['1' ])
28262891
28272892 def testNosyMail (self ) :
0 commit comments