1. 05 Nov, 2017 20 commits
  2. 04 Nov, 2017 9 commits
    • Antoine Beaupré's avatar
      fix some feeds descriptions in readme · 796e2026
      Antoine Beaupré authored
    • Antoine Beaupré's avatar
      add transmission plugin · 870641d2
      Antoine Beaupré authored
      this plugin is introduced because the exec plugin cannot safely guess
      a subdirectory to save feed into without resorting to using
      plugins. now the transmission plugin has nicer defaults and properly
      guesses a default path based on the item title, which can be
      appropriately modified by filter plugins as needed.
    • Antoine Beaupré's avatar
      more possible naming conflicts · 5b7da34d
      Antoine Beaupré authored
    • Antoine Beaupré's avatar
      cosmetic: consistent test comparison · 966a20b8
      Antoine Beaupré authored
      We should do "expected == actual" because that is the way the diff is
      ordered on display. That's a rather opiniated way of doing things, but
      at least we should be consistent across the board, which we weren't
    • Antoine Beaupré's avatar
      security: avoid possible config setting override · 2a493004
      Antoine Beaupré authored
      It may be possible for parsed feed data to override configuration that
      is passed to plugins and other components. Normally, feedparser
      doesn't send those settings (e.g. output or args) that could
      potentially lead to remote code execution exploits. But there *is* one
      setting that overlaps right now: "url". It can't do anything now,
      because the URL is set *after* the feed is parsed, so it's harmless.
      But who knows how feedparser may change in the future? As a security
      precaution, we created a list of "locked" items that are important for
      us and keep the feed from overriding that.
    • Antoine Beaupré's avatar
      API refactoring: create a Feed class · 7f01625e
      Antoine Beaupré authored
      A "Feed" is the basic representation of a RSS/Atom feed. It derives
      from the feedparser dict but we use our class to regroup functionality
      that was loose around the module, like normalize() and parse(). It
      makes it easier (and possible!) to pass the feed object to the
      multiprocessing module without casting it to a dict(), which means
      plugins actually get access to the full Feed object.
      This also has the advantage of removing the ambiguity of what a "feed"
      is internally: it is explicitly the merge of the config declared by
      the user and the metadata obtained from the feed.
    • Antoine Beaupré's avatar
      API refactoring: merge classes in a controller · 60bcc588
      Antoine Beaupré authored
      The FeedStorage and FeedFetcher class were fairly similar: they were
      wrappers around the storage subsystem, which is basically a "model",
      so they are a "controller" in the classic sense. So merge them both in
      a single "FeedManager" which is a controller class that manipulates
      the underlying object.
      This is the first step of a larger refactoring: we may want to create
      a Feed class of objects to manipulate feeds directly, for example
      allowing filters to operate on OPML import/exports...
    • Antoine Beaupré's avatar
      properly call FeedFetcher constructor · 8a0319d4
      Antoine Beaupré authored
    • Antoine Beaupré's avatar
      initialize FeedFetcher session singleton properly · 55013043
      Antoine Beaupré authored
      without this, the wayback plugin would fail because it
      FeedFetcher._session is None. doing this in the constructor makes the
      accessor faster as well, as we don't need to do another check.
      this should resolve a bug I found in the last run, which we *can't*
      write unit tests for (because we use betamax in tests, which properly
      set the class-level session):
      plugin generated exception: 'NoneType' object has no attribute 'head', skipping
      Traceback (most recent call last):
        File "/usr/local/lib/python3.5/dist-packages/feed2exec/plugins/__init__.py", line 96, in output
          return plugin.output(*args, feed=feed, item=item, lock=lock)
        File "/usr/local/lib/python3.5/dist-packages/feed2exec/plugins/wayback.py", line 28, in output
          res = session.head('%s/save/%s' % (WAYBACK_URL, item.get('link')))
      AttributeError: 'NoneType' object has no attribute 'head'
  3. 24 Oct, 2017 10 commits
  4. 20 Oct, 2017 1 commit
    • Antoine Beaupré's avatar
      use getter/setters for class session · 73760056
      Antoine Beaupré authored
      this makes the code cleaner and more idiomatic
      this does require plugins to use the private member to access the
      session, especially for the test suite, but there are ways of avoiding
      that for third-party plugins: a module-level can be used and
      configured with the static method, for example.