def test_conditions(self): for cond, expected in self.CASES: keep = matching.ConditionParser(lookup, "name").parse(cond) result = set(i.name for i in self.DATA if keep(i)) expected = set(expected.split()) assert result == expected, "Expected %r, but got %r, for '%s' [ %s ]" % ( expected, result, cond, keep)
def test_magic_matching(self): item = Bunch(name="foo", date=time.time() - 86401, one=1, year=2011, size=1024**2) match = lambda c: matching.ConditionParser( lambda _: { "matcher": matching.MagicFilter }, "name").parse(c).match(item) assert match("f??") assert match("name=f*") assert match("date=+1d") assert match("one=y") assert match("one=+0") assert match("year=+2000") assert match("size=1m") assert match("size=1024k") assert not match("a*") assert not match("date=-1d") assert not match("one=false") assert not match("one=+1") assert not match("year=+2525") assert not match("size=-1m")
def on_feed_input(self, feed, _): """ Produce entries from rtorrent items. """ if not self.config["enabled"]: LOG.debugall("plugin disabled") return if self.proxy and self.config["feed_query"]: try: matcher = matching.ConditionParser( engine.FieldDefinition.lookup, "name").parse(self.config["feed_query"]) view = pyrocfg.engine.view(self.config["view"], matcher) for item in view.items(): entry = flexfeed.Entry() entry["title"] = item.name entry["url"] = "file://" + item.metafile entry["uid"] = item.hash entry["location"] = item.metafile yield entry except error.LoggableError, exc: raise plugin.PluginError(exc)
def test_bad_conditions(self): for cond in self.BAD: try: matcher = matching.ConditionParser(lookup).parse(cond) except matching.FilterError, exc: log.debug("BAD: '%s' ==> %s" % (cond, exc)) else: assert False, "[ %s ] '%s' raised no error" % (matcher, cond)
def test_magic_negate(self): matcher = matching.ConditionParser( lambda _: { "matcher": matching.MagicFilter }, "f").parse("!") self.check(matcher[0], matching.NegateFilter, "!") self.check(matcher[0]._inner, matching.MagicFilter, "!") self.check(matcher[0]._inner._inner, matching.PatternFilter, "!")
def test_good_conditions(self): for cond, canonical in self.GOOD: if '%' in canonical: canonical = canonical % cond matcher = matching.ConditionParser(lookup, "name").parse(cond) assert isinstance(matcher, matching.Filter), "Matcher is not a filter" assert str(matcher) == canonical, "'%s' != '%s'" % (matcher, canonical) assert matcher, "Matcher is empty"
def test_magic(self): for cond, expected in self.CASES: matcher = matching.ConditionParser( lambda _: { "matcher": matching.MagicFilter }, "f").parse(cond) log.debug("MAGIC: '%s' ==> %s" % (cond, type(matcher[0]._inner).__name__)) self.check(matcher[0]._inner, expected, cond)
class ConditionPluginBase(plugin.Plugin): """ Base class for condition filter plugins. """ @property def name(self): "Plugin name" return self.plugin_info.name # pylint: disable=E1101 def validator(self): """ Return validator suitable for filter conditions. """ root = validator.factory() root.accept("list").accept("text") # list of conditions ORed together root.accept("text") # a single condition return root def parse(self, config): """ Parse filter condition(s) from config. """ try: from pyrocore.util import matching except ImportError, exc: raise plugin.DependencyError( "You need to (easy_)install 'pyrocore>=0.4' to use the %s plugin (%s)" % (self.name, exc)) if isinstance(config, basestring): config = [config] conditions = [] parser = matching.ConditionParser( matching.ConditionParser.AMENABLE, default_field="title", ident_re=r"(?:\??[_A-Za-z0-9]+\.?)*\??[_A-Za-z0-9]+") for cond in config: try: conditions.append(parser.parse(cond)) except matching.FilterError, exc: raise plugin.PluginError(str(exc))
# print repr(config.engine) # config.engine.open() # print repr(config.engine) # Preparation steps if self.options.fast_query != '=': config.fast_query = int(self.options.fast_query) self.raw_output_format = self.options.output_format default_output_format = "default" if actions: default_output_format = "action_cron" if self.options.cron else "action" self.validate_output_format(default_output_format) sort_key = self.validate_sort_fields() matcher = matching.ConditionParser(engine.FieldDefinition.lookup, "name").parse(self.args) self.LOG.debug("Matcher is: %s" % matcher) # Detach to background? # This MUST happen before the next step, when we connect to the torrent client if self.options.detach: config.engine.load_config() daemon_log = os.path.join(config.config_dir, "log", "rtcontrol.log") osmagic.daemonize(logfile=daemon_log if os.path. exists(os.path.dirname(daemon_log)) else None) time.sleep(.05) # let things settle a little # View handling if self.options.append_view and self.options.alter_view: self.fatal("You cannot combine --append-view with --alter-view")