Repository: Flexget/Flexget

Issue:
base64 issues with python 3.9
I just updated my install of python and something seams to have changed with base64
```
python -V
Python 3.9.0
```

Logs :
```
$ flexget
2020-10-18 13:00:03 CRITICAL plugin                        Exception while loading plugin flexget.plugins.input.apple_trailers
Traceback (most recent call last):
  File "/home/striker/.local/bin/flexget", line 8, in <module>
    sys.exit(main())
    |   |    -> <function main at 0x7f2b3ee7d160>
    |   -> <built-in function exit>
    -> <module 'sys' (built-in)>
  File "/home/striker/.local/lib/python3.9/site-packages/flexget/__init__.py", line 43, in main
    manager.start()
    |       -> <function Manager.start at 0x7f2b3d118280>
    -> <flexget.manager.Manager object at 0x7f2b3d0fdc10>
  File "/home/striker/.local/lib/python3.9/site-packages/flexget/manager.py", line 371, in start
    self.initialize()
    |    -> <function Manager.initialize at 0x7f2b3d118040>
    -> <flexget.manager.Manager object at 0x7f2b3d0fdc10>
  File "/home/striker/.local/lib/python3.9/site-packages/flexget/manager.py", line 211, in initialize
    plugin.load_plugins(
    |      -> <function load_plugins at 0x7f2b3d428c10>
    -> <module 'flexget.plugin' from '/home/striker/.local/lib/python3.9/site-packages/flexget/plugin.py'>
  File "/home/striker/.local/lib/python3.9/site-packages/flexget/plugin.py", line 555, in load_plugins
    _load_plugins_from_dirs(extra_plugins)
    |                       -> ['/home/striker/.config/flexget/plugins', '/home/striker/.local/lib/python3.9/site-packages/flexget/plugins']
    -> <function _load_plugins_from_dirs at 0x7f2b3d428a60>
  File "/home/striker/.local/lib/python3.9/site-packages/flexget/plugin.py", line 473, in _load_plugins_from_dirs
    _import_plugin(module_name, plugin_path)
    |              |            -> PosixPath('/home/striker/.local/lib/python3.9/site-packages/flexget/plugins/input/apple_trailers.py')
    |              -> 'flexget.plugins.input.apple_trailers'
    -> <function _import_plugin at 0x7f2b3d4289d0>
> File "/home/striker/.local/lib/python3.9/site-packages/flexget/plugin.py", line 424, in _import_plugin
    import_module(module_name)
    |             -> 'flexget.plugins.input.apple_trailers'
    -> <function import_module at 0x7f2b3ef898b0>
  File "/usr/lib/python3.9/importlib/__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           |          |           |    |        |        -> 0
           |          |           |    |        -> None
           |          |           |    -> 0
           |          |           -> 'flexget.plugins.input.apple_trailers'
           |          -> <function _gcd_import at 0x7f2b3f0c1310>
           -> <module 'importlib._bootstrap' (frozen)>
  File "<frozen importlib._bootstrap>", line 1030, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
  File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 790, in exec_module
  File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
  File "/home/striker/.local/lib/python3.9/site-packages/flexget/plugins/input/apple_trailers.py", line 3, in <module>
    import feedparser
  File "/home/striker/.local/lib/python3.9/site-packages/feedparser.py", line 93, in <module>
    _base64decode = getattr(base64, 'decodebytes', base64.decodestring)
                            |                      -> <module 'base64' from '/usr/lib/python3.9/base64.py'>
                            -> <module 'base64' from '/usr/lib/python3.9/base64.py'>

AttributeError: module 'base64' has no attribute 'decodestring'
```


Discussion:
The issue is related to feedparser and has been fixed in https://github.com/kurtmckee/feedparser/pull/206

Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -60,6 +60,7 @@ def load_requirements(filename: str) -> List[str]:
         "Programming Language :: Python :: 3.6",
         "Programming Language :: Python :: 3.7",
         "Programming Language :: Python :: 3.8",
+        "Programming Language :: Python :: 3.9",
         "Programming Language :: Python :: Implementation :: CPython",
         "Programming Language :: Python :: Implementation :: PyPy",
     ],


Test patch:
diff --git a/flexget/tests/test_rtorrent.py b/flexget/tests/test_rtorrent.py
--- a/flexget/tests/test_rtorrent.py
+++ b/flexget/tests/test_rtorrent.py
@@ -13,24 +13,6 @@
     torrent_raw = tor_file.read()
 
 
-def compare_binary(obj1, obj2):
-    # Used to compare xmlrpclib.binary objects within a mocked call
-    if not isinstance(obj1, type(obj2)):
-        return False
-    if obj1.data != obj2.data:
-        return False
-    return True
-
-
-class Matcher:
-    def __init__(self, compare, some_obj):
-        self.compare = compare
-        self.some_obj = some_obj
-
-    def __eq__(self, other):
-        return self.compare(self.some_obj, other)
-
-
 @mock.patch('flexget.plugins.clients.rtorrent.xmlrpc_client.ServerProxy')
 class TestRTorrentClient:
     def test_load(self, mocked_proxy):
@@ -55,12 +37,10 @@ def test_load(self, mocked_proxy):
         # Ensure load was called
         assert mocked_proxy.load.raw_start.called
 
-        match_binary = Matcher(compare_binary, xmlrpc_client.Binary(torrent_raw))
-
         called_args = mocked_proxy.load.raw_start.call_args_list[0][0]
         assert len(called_args) == 5
         assert '' == called_args[0]
-        assert match_binary in called_args
+        assert xmlrpc_client.Binary(torrent_raw) in called_args
 
         fields = [p for p in called_args[2:]]
         assert len(fields) == 3