We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
t411 : BUG: Unhandled error in plugin discover: maximum recursion depth exceeded while getting the str of an object
I've got an error when executing my flexget script

flexget execute --task tv-t411 --discover-now

This is the config file
http://pastie.org/10809799

And this is the crash log

[crash_report.2016.04.23.150112065543.zip](https://github.com/Flexget/Flexget/files/233121/crash_report.2016.04.23.150112065543.zip)


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `flexget/plugins/plugin_torrent411.py`
Content:
```
1 from __future__ import unicode_literals, division, absolute_import
2 from builtins import *  # pylint: disable=unused-import, redefined-builtin
3 
4 import logging
5 import re
6 
7 from flexget.config_schema import one_or_more
8 from flexget.manager import Session
9 from flexget.plugins.api_t411 import T411Proxy, FriendlySearchQuery, ApiError
10 from flexget import plugin
11 from flexget.event import event
12 
13 log = logging.getLogger('t411_plugin')
14 
15 
16 def escape_query(search_strings):
17     """
18     Escaping some expression Grey's -> Grey's + Greys + Grey, Marvel's ->Marvel's + Marvels + Marvel etc
19     :param query str[]:
20     :return:
21     """
22     result = []
23     for search_string in search_strings:
24         result.append(search_string)
25         short_query = re.sub("'", "", search_string)
26         if search_string != short_query:
27             result.append(short_query)
28             very_short_query = re.sub("'[a-z]", "", search_string)
29             if short_query != very_short_query:
30                 result.append(very_short_query)
31     return result
32 
33 
34 class T411InputPlugin(object):
35     """T411 search/Input plugin.
36     Before any usage, please add your credential with
37     "flexget t411 add-auth <username> <password>"
38 
39     t411:
40       category: <see available categories on "flexget t411 list-cats">
41       terms: <see available terms on "flexget t411 list-terms --category <category name>"
42       max_resutls: XXX
43     """
44 
45     def __init__(self):
46         self.schema = {
47             'type': 'object',
48             'properties': {
49                 'category': {'type': 'string'},
50                 'terms': one_or_more({'type': 'string'}),
51                 'max_results': {'type': 'number', 'default': 100}
52             },
53             'additionalProperties': False
54         }
55 
56     @staticmethod
57     def build_request_from(config):
58         """
59         Build a query from plugin config dict
60         :param config: dict
61         :return:
62         """
63         query = FriendlySearchQuery()
64         query.category_name = config.get('category')
65         query.term_names = config.get('terms', [])
66         query.max_results = config.get('max_results')
67         return query
68 
69     @plugin.internet(log)
70     def on_task_input(self, task, config):
71         proxy = T411Proxy()
72         proxy.set_credential()
73         query = T411InputPlugin.build_request_from(config)
74         try:
75             return proxy.search(query)
76         except ApiError as e:
77             log.warning("Server send an error message : %d - %s", e.code, e.message)
78             return []
79 
80     @classmethod
81     @plugin.internet(log)
82     def search(cls, entry=None, config=None, task=None):
83         proxy = T411Proxy()
84         proxy.set_credential()
85 
86         query = T411InputPlugin.build_request_from(config)
87         if entry.get('series_season'):
88             query.add_season_term(entry['series_season'])
89             query.add_episode_term(entry['series_episode'])
90             search_strings = escape_query([entry['series_name']])
91         else:
92             search_strings = entry.get('search_strings', [entry['title']])
93             search_strings = escape_query(search_strings)
94 
95         produced_entries = set()
96         for search_string in search_strings:
97             query.expression = search_string
98             try:
99                 search_result = proxy.search(query)
100                 produced_entries.update(search_result)
101             except ApiError as e:
102                 log.warning("Server send an error message : %d - %s", e.code, e.message)
103 
104         return produced_entries
105 
106 
107 class T411LookupPlugin(object):
108     schema = {'type': 'string', 'enum': ['fill', 'override']}
109 
110     @staticmethod
111     def lazy_lookup(entry):
112         string_torrent_id = entry.get('t411_torrent_id')
113         if string_torrent_id is None:
114             log.warning('Looking up T411 for entry pass, no t411_torrent_id found.')
115             pass
116 
117         torrent_id = int(string_torrent_id)
118         proxy = T411Proxy()
119         proxy.set_credential()
120         with Session() as session:
121             try:
122                 log.info("Lookup torrent details for %d", torrent_id)
123                 bind_details = proxy.details(torrent_id, session=session)
124                 unbind_details = [dict([
125                     ('term_type_name', term.type.name),
126                     ('term_type_id', term.type.id),
127                     ('term_id', term.id),
128                     ('term_name', term.name)]) for term in bind_details.terms]
129                 entry['t411_terms'] = unbind_details
130             except ApiError as e:
131                 log.warning("Server send an error message : %d - %s", e.code, e.message)
132 
133     # Run after series and metainfo series
134     @plugin.priority(110)
135     def on_task_metainfo(self, task, config):
136         proxy = T411Proxy()
137         proxy.set_credential()
138         for entry in task.entries:
139             if entry.get('t411_torrent_id') is None:
140                 continue
141 
142             # entry.register_lazy_func(T411LookupPlugin.lazy_lookup, T411LookupPlugin.torrent_details_map)
143             T411LookupPlugin.lazy_lookup(entry)
144             if entry.get('t411_terms', eval_lazy=True) is not None:
145                 video_quality = proxy.parse_terms_to_quality(entry.get('t411_terms'))
146                 entry_quality = entry.get('quality')
147                 if video_quality is None:
148                     log.info('Torrent %i hasn\'t video quality description, pass.', entry.get('t411_torrent_id'))
149                     continue
150                 if entry_quality.source.name == 'unknown' or config == 'override':
151                     entry_quality.source = video_quality.source
152                 if entry_quality.resolution.name == 'unknown' or config == 'override':
153                     entry_quality.resolution = video_quality.resolution
154 
155 
156 @event('plugin.register')
157 def register_plugin():
158     plugin.register(T411InputPlugin, 't411', groups=['search', 'input'], api_ver=2)
159     plugin.register(T411LookupPlugin, 't411_lookup', api_ver=2)
160
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/flexget/plugins/plugin_torrent411.py b/flexget/plugins/plugin_torrent411.py
old mode 100644
new mode 100755
--- a/flexget/plugins/plugin_torrent411.py
+++ b/flexget/plugins/plugin_torrent411.py
@@ -61,7 +61,7 @@
         """
         query = FriendlySearchQuery()
         query.category_name = config.get('category')
-        query.term_names = config.get('terms', [])
+        query.term_names = list(config.get('terms', []))
         query.max_results = config.get('max_results')
         return query

{"golden_diff": "diff --git a/flexget/plugins/plugin_torrent411.py b/flexget/plugins/plugin_torrent411.py\nold mode 100644\nnew mode 100755\n--- a/flexget/plugins/plugin_torrent411.py\n+++ b/flexget/plugins/plugin_torrent411.py\n@@ -61,7 +61,7 @@\n         \"\"\"\n         query = FriendlySearchQuery()\n         query.category_name = config.get('category')\n-        query.term_names = config.get('terms', [])\n+        query.term_names = list(config.get('terms', []))\n         query.max_results = config.get('max_results')\n         return query\n", "issue": "t411 : BUG: Unhandled error in plugin discover: maximum recursion depth exceeded while getting the str of an object\nI've got an error when executing my flexget script\n\nflexget execute --task tv-t411 --discover-now\n\nThis is the config file\nhttp://pastie.org/10809799\n\nAnd this is the crash log\n\n[crash_report.2016.04.23.150112065543.zip](https://github.com/Flexget/Flexget/files/233121/crash_report.2016.04.23.150112065543.zip)\n\n", "before_files": [{"content": "from __future__ import unicode_literals, division, absolute_import\nfrom builtins import *  # pylint: disable=unused-import, redefined-builtin\n\nimport logging\nimport re\n\nfrom flexget.config_schema import one_or_more\nfrom flexget.manager import Session\nfrom flexget.plugins.api_t411 import T411Proxy, FriendlySearchQuery, ApiError\nfrom flexget import plugin\nfrom flexget.event import event\n\nlog = logging.getLogger('t411_plugin')\n\n\ndef escape_query(search_strings):\n    \"\"\"\n    Escaping some expression Grey's -> Grey's + Greys + Grey, Marvel's ->Marvel's + Marvels + Marvel etc\n    :param query str[]:\n    :return:\n    \"\"\"\n    result = []\n    for search_string in search_strings:\n        result.append(search_string)\n        short_query = re.sub(\"'\", \"\", search_string)\n        if search_string != short_query:\n            result.append(short_query)\n            very_short_query = re.sub(\"'[a-z]\", \"\", search_string)\n            if short_query != very_short_query:\n                result.append(very_short_query)\n    return result\n\n\nclass T411InputPlugin(object):\n    \"\"\"T411 search/Input plugin.\n    Before any usage, please add your credential with\n    \"flexget t411 add-auth <username> <password>\"\n\n    t411:\n      category: <see available categories on \"flexget t411 list-cats\">\n      terms: <see available terms on \"flexget t411 list-terms --category <category name>\"\n      max_resutls: XXX\n    \"\"\"\n\n    def __init__(self):\n        self.schema = {\n            'type': 'object',\n            'properties': {\n                'category': {'type': 'string'},\n                'terms': one_or_more({'type': 'string'}),\n                'max_results': {'type': 'number', 'default': 100}\n            },\n            'additionalProperties': False\n        }\n\n    @staticmethod\n    def build_request_from(config):\n        \"\"\"\n        Build a query from plugin config dict\n        :param config: dict\n        :return:\n        \"\"\"\n        query = FriendlySearchQuery()\n        query.category_name = config.get('category')\n        query.term_names = config.get('terms', [])\n        query.max_results = config.get('max_results')\n        return query\n\n    @plugin.internet(log)\n    def on_task_input(self, task, config):\n        proxy = T411Proxy()\n        proxy.set_credential()\n        query = T411InputPlugin.build_request_from(config)\n        try:\n            return proxy.search(query)\n        except ApiError as e:\n            log.warning(\"Server send an error message : %d - %s\", e.code, e.message)\n            return []\n\n    @classmethod\n    @plugin.internet(log)\n    def search(cls, entry=None, config=None, task=None):\n        proxy = T411Proxy()\n        proxy.set_credential()\n\n        query = T411InputPlugin.build_request_from(config)\n        if entry.get('series_season'):\n            query.add_season_term(entry['series_season'])\n            query.add_episode_term(entry['series_episode'])\n            search_strings = escape_query([entry['series_name']])\n        else:\n            search_strings = entry.get('search_strings', [entry['title']])\n            search_strings = escape_query(search_strings)\n\n        produced_entries = set()\n        for search_string in search_strings:\n            query.expression = search_string\n            try:\n                search_result = proxy.search(query)\n                produced_entries.update(search_result)\n            except ApiError as e:\n                log.warning(\"Server send an error message : %d - %s\", e.code, e.message)\n\n        return produced_entries\n\n\nclass T411LookupPlugin(object):\n    schema = {'type': 'string', 'enum': ['fill', 'override']}\n\n    @staticmethod\n    def lazy_lookup(entry):\n        string_torrent_id = entry.get('t411_torrent_id')\n        if string_torrent_id is None:\n            log.warning('Looking up T411 for entry pass, no t411_torrent_id found.')\n            pass\n\n        torrent_id = int(string_torrent_id)\n        proxy = T411Proxy()\n        proxy.set_credential()\n        with Session() as session:\n            try:\n                log.info(\"Lookup torrent details for %d\", torrent_id)\n                bind_details = proxy.details(torrent_id, session=session)\n                unbind_details = [dict([\n                    ('term_type_name', term.type.name),\n                    ('term_type_id', term.type.id),\n                    ('term_id', term.id),\n                    ('term_name', term.name)]) for term in bind_details.terms]\n                entry['t411_terms'] = unbind_details\n            except ApiError as e:\n                log.warning(\"Server send an error message : %d - %s\", e.code, e.message)\n\n    # Run after series and metainfo series\n    @plugin.priority(110)\n    def on_task_metainfo(self, task, config):\n        proxy = T411Proxy()\n        proxy.set_credential()\n        for entry in task.entries:\n            if entry.get('t411_torrent_id') is None:\n                continue\n\n            # entry.register_lazy_func(T411LookupPlugin.lazy_lookup, T411LookupPlugin.torrent_details_map)\n            T411LookupPlugin.lazy_lookup(entry)\n            if entry.get('t411_terms', eval_lazy=True) is not None:\n                video_quality = proxy.parse_terms_to_quality(entry.get('t411_terms'))\n                entry_quality = entry.get('quality')\n                if video_quality is None:\n                    log.info('Torrent %i hasn\\'t video quality description, pass.', entry.get('t411_torrent_id'))\n                    continue\n                if entry_quality.source.name == 'unknown' or config == 'override':\n                    entry_quality.source = video_quality.source\n                if entry_quality.resolution.name == 'unknown' or config == 'override':\n                    entry_quality.resolution = video_quality.resolution\n\n\n@event('plugin.register')\ndef register_plugin():\n    plugin.register(T411InputPlugin, 't411', groups=['search', 'input'], api_ver=2)\n    plugin.register(T411LookupPlugin, 't411_lookup', api_ver=2)\n", "path": "flexget/plugins/plugin_torrent411.py"}], "after_files": [{"content": "# coding=utf-8\nfrom __future__ import unicode_literals, division, absolute_import\nimport logging\nimport re\nfrom flexget.config_schema import one_or_more\nfrom flexget.manager import Session\nfrom flexget.plugins.api_t411 import T411Proxy, FriendlySearchQuery, ApiError\n\nfrom flexget import plugin\nfrom flexget.event import event\n\nlog = logging.getLogger('t411_plugin')\n\n\ndef escape_query(search_strings):\n    \"\"\"\n    Escaping some expression Grey's -> Grey's + Greys + Grey, Marvel's ->Marvel's + Marvels + Marvel etc\n    :param query str[]:\n    :return:\n    \"\"\"\n    result = []\n    for search_string in search_strings:\n        result.append(search_string)\n        short_query = re.sub(\"'\", \"\", search_string)\n        if search_string != short_query:\n            result.append(short_query)\n            very_short_query = re.sub(\"'[a-z]\", \"\", search_string)\n            if short_query != very_short_query:\n                result.append(very_short_query)\n    return result\n\n\nclass T411InputPlugin(object):\n    \"\"\"T411 search/Input plugin.\n    Before any usage, please add your credential with\n    \"flexget t411 add-auth <username> <password>\"\n\n    t411:\n      category: <see available categories on \"flexget t411 list-cats\">\n      terms: <see available terms on \"flexget t411 list-terms --category <category name>\"\n      max_resutls: XXX\n    \"\"\"\n\n    def __init__(self):\n        self.schema = {\n            'type': 'object',\n            'properties': {\n                'category': {'type': 'string'},\n                'terms': one_or_more({'type': 'string'}),\n                'max_results': {'type': 'number', 'default': 100}\n            },\n            'additionalProperties': False\n        }\n\n    @staticmethod\n    def build_request_from(config):\n        \"\"\"\n        Build a query from plugin config dict\n        :param config: dict\n        :return:\n        \"\"\"\n        query = FriendlySearchQuery()\n        query.category_name = config.get('category')\n        query.term_names = list(config.get('terms', []))\n        query.max_results = config.get('max_results')\n        return query\n\n    @plugin.internet(log)\n    def on_task_input(self, task, config):\n        proxy = T411Proxy()\n        proxy.set_credential()\n        query = T411InputPlugin.build_request_from(config)\n        try:\n            return proxy.search(query)\n        except ApiError as e:\n            log.warning(\"Server send an error message : %d - %s\", e.code, e.message)\n            return []\n\n    @classmethod\n    @plugin.internet(log)\n    def search(cls, entry=None, config=None, task=None):\n        proxy = T411Proxy()\n        proxy.set_credential()\n\n        query = T411InputPlugin.build_request_from(config)\n        if entry.get('series_season'):\n            query.add_season_term(entry['series_season'])\n            query.add_episode_term(entry['series_episode'])\n            search_strings = escape_query([entry['series_name']])\n        else:\n            search_strings = entry.get('search_strings', [entry['title']])\n            search_strings = escape_query(search_strings)\n\n        produced_entries = set()\n        for search_string in search_strings:\n            query.expression = search_string\n            try:\n                search_result = proxy.search(query)\n                produced_entries.update(search_result)\n            except ApiError as e:\n                log.warning(\"Server send an error message : %d - %s\", e.code, e.message)\n\n        return produced_entries\n\n\nclass T411LookupPlugin(object):\n    schema = {'type': 'string', 'enum': ['fill', 'override']}\n\n    @staticmethod\n    def lazy_lookup(entry):\n        string_torrent_id = entry.get('t411_torrent_id')\n        if string_torrent_id is None:\n            log.warning('Looking up T411 for entry pass, no t411_torrent_id found.')\n            pass\n\n        torrent_id = int(string_torrent_id)\n        proxy = T411Proxy()\n        proxy.set_credential()\n        with Session() as session:\n            try:\n                log.info(\"Lookup torrent details for %d\", torrent_id)\n                bind_details = proxy.details(torrent_id, session=session)\n                unbind_details = [dict([\n                    ('term_type_name', term.type.name),\n                    ('term_type_id', term.type.id),\n                    ('term_id', term.id),\n                    ('term_name', term.name)]) for term in bind_details.terms]\n                entry['t411_terms'] = unbind_details\n            except ApiError as e:\n                log.warning(\"Server send an error message : %d - %s\", e.code, e.message)\n\n    # Run after series and metainfo series\n    @plugin.priority(110)\n    def on_task_metainfo(self, task, config):\n        proxy = T411Proxy()\n        proxy.set_credential()\n        for entry in task.entries:\n            if entry.get('t411_torrent_id') is None:\n                continue\n\n            # entry.register_lazy_func(T411LookupPlugin.lazy_lookup, T411LookupPlugin.torrent_details_map)\n            T411LookupPlugin.lazy_lookup(entry)\n            if entry.get('t411_terms', eval_lazy=True) is not None:\n                video_quality = proxy.parse_terms_to_quality(entry.get('t411_terms'))\n                entry_quality = entry.get('quality')\n                if video_quality is None:\n                    log.info('Torrent %i hasn\\'t video quality description, pass.', entry.get('t411_torrent_id'))\n                    continue\n                if entry_quality.source.name == 'unknown' or config == 'override':\n                    entry_quality.source = video_quality.source\n                if entry_quality.resolution.name == 'unknown' or config == 'override':\n                    entry_quality.resolution = video_quality.resolution\n\n\n@event('plugin.register')\ndef register_plugin():\n    plugin.register(T411InputPlugin, 't411', groups=['search', 'input'], api_ver=2)\n    plugin.register(T411LookupPlugin, 't411_lookup', api_ver=2)\n", "path": "flexget/plugins/plugin_torrent411.py"}]}