We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Some words confuse movie name parsing.
Entry title is "dan in real life 2007", parser stops at "real"

```
2016-05-01 09:32 DEBUG    imdb_lookup   library_movies_cleanup_test lookup for d
an in real life 2007
2016-05-01 09:32 VERBOSE  imdb_lookup   library_movies_cleanup_test Searching fr
om imdb `dan in real life 2007`
2016-05-01 09:32 DEBUG    parser_internal library_movies_cleanup_test Parsing mo
vie: `dan in real life 2007` kwargs: {}
2016-05-01 09:32 DEBUG    movieparser   library_movies_cleanup_test parts: [u'da
n', u'in', u'real', u'life', u'2007'], cut is: real
2016-05-01 09:32 DEBUG    movieparser   library_movies_cleanup_test after parts 
check, cut data would be: `dan in` abs_cut: 6
2016-05-01 09:32 DEBUG    movieparser   library_movies_cleanup_test data cut to 
`dan in` - this will be the name
2016-05-01 09:32 DEBUG    parser_internal library_movies_cleanup_test Parsing re
sult: <MovieParser(name=dan in,year=2007,quality=unknown)> (in 0.92 ms)
2016-05-01 09:32 DEBUG    utils.imdb    library_movies_cleanup_test smart_match 
name=dan in year=2007
2016-05-01 09:32 DEBUG    utils.imdb    library_movies_cleanup_test Searching: d
an in
```


--- 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/utils/titles/movie.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.utils.titles.parser import TitleParser
8 from flexget.utils import qualities
9 from flexget.utils.tools import str_to_int
10 
11 log = logging.getLogger('movieparser')
12 
13 
14 def diff_pos(string1, string2):
15     """Returns first position where string1 and string2 differ."""
16     for (count, c) in enumerate(string1):
17         if len(string2) <= count:
18             return count
19         if string2[count] != c:
20             return count
21 
22 
23 class MovieParser(TitleParser):
24 
25     def __init__(self):
26         self.data = None
27         self.reset()
28         TitleParser.__init__(self)
29 
30     @property
31     def fields(self):
32         """
33         Return a dict of all parser fields
34         """
35         return {
36             'movie_parser': self,
37             'movie_name': self.name,
38             'movie_year': self.year,
39             'proper': self.proper,
40             'proper_count': self.proper_count
41         }
42 
43     @property
44     def valid(self):
45         return True
46 
47     @property
48     def proper(self):
49         return self.proper_count > 0
50 
51     @property
52     def is_series(self):
53         return False
54 
55     @property
56     def is_movie(self):
57         return True
58 
59     def reset(self):
60         # parsing results
61         self.name = None
62         self.year = None
63         self.quality = qualities.Quality()
64         self.proper_count = 0
65 
66     def __str__(self):
67         return "<MovieParser(name=%s,year=%s,quality=%s)>" % (self.name, self.year, self.quality)
68 
69     def parse(self, data=None):
70         """Parse movie name. Populates name, year, quality and proper_count attributes"""
71 
72         # Reset before parsing, so the parser can be reused.
73         self.reset()
74 
75         if data is None:
76             data = self.data
77 
78         # Move anything in leading brackets to the end
79         data = re.sub(r'^\[(.*?)\](.*)', r'\2 \1', data)
80 
81         for char in '[]()_,.':
82             data = data.replace(char, ' ')
83 
84         # if there are no spaces
85         if data.find(' ') == -1:
86             data = data.replace('-', ' ')
87 
88         # remove unwanted words (imax, ..)
89         self.remove_words(data, self.remove)
90 
91         data = self.strip_spaces(data)
92 
93         # split to parts
94         parts = data.split(' ')
95         cut_part = 256
96         all_caps = True
97         for part_pos, part in enumerate(parts):
98             cut = False
99             # Don't let the first word be cutoff word
100             if part_pos < 1:
101                 continue
102             # check for year
103             num = str_to_int(part)
104             if num is not None:
105                 if 1930 < num < 2050:
106                     self.year = num
107                     cut = True
108             # Don't consider all caps words cut words if the whole title has been all caps
109             if not part.isupper():
110                 all_caps = False
111             # if length > 3 and whole word in uppers, consider as cut word (most likely a group name)
112             if len(part) > 3 and part.isupper() and part.isalpha() and not all_caps:
113                 cut = True
114             # check for cutoff words
115             if part.lower() in self.cutoffs:
116                 cut = True
117             # check for propers
118             if part.lower() in self.propers:
119                 self.proper_count += 1
120                 cut = True
121             # update cut position
122             if cut and parts.index(part) < cut_part:
123                 cut_part = part_pos
124 
125         if cut_part != 256:
126             log.debug('parts: %s, cut is: %s', parts, parts[cut_part])
127 
128         # calculate cut positon from cut_part
129         abs_cut = len(' '.join(parts[:cut_part]))
130 
131         log.debug('after parts check, cut data would be: `%s` abs_cut: %i', data[:abs_cut], abs_cut)
132 
133         # parse quality
134         quality = qualities.Quality(data)
135         if quality:
136             self.quality = quality
137             # remaining string is same as data but quality information removed
138             # find out position where there is first difference, this is earliest
139             # quality bit, anything after that has no relevance to the movie name
140             dp = diff_pos(data, quality.clean_text)
141             if dp is not None:
142                 log.debug('quality start: %s', dp)
143                 if dp < abs_cut:
144                     log.debug('quality cut is even shorter')
145                     abs_cut = dp
146 
147         # make cut
148         data = data[:abs_cut].strip()
149         log.debug('data cut to `%s` - this will be the name', data)
150 
151         # save results
152         self.name = data
153
```

Path: `flexget/utils/titles/parser.py`
Content:
```
1 from __future__ import unicode_literals, division, absolute_import
2 from builtins import *  # pylint: disable=unused-import, redefined-builtin
3 
4 import re
5 
6 
7 class TitleParser(object):
8     propers = ['proper', 'repack', 'rerip', 'real', 'final']
9 
10     specials = ['special', 'bonus', 'extra', 'omake', 'ova']
11 
12     editions = ['dc', 'extended', 'uncut', 'remastered', 'unrated', 'theatrical', 'chrono', 'se']
13 
14     # TODO: All of the quality related keywords can probably be removed from here, as the quality module handles them
15     codecs = ['x264', 'x.264', 'h264', 'h.264', 'XViD']
16 
17     # lowercase required
18     cutoffs = ['limited', 'xvid', 'h264', 'x264', 'h.264', 'x.264', 'screener', 'unrated', '3d', 'extended',
19                'directors', 'director\'s', 'multisubs', 'dubbed', 'subbed', 'multi'] + propers + specials + editions
20 
21     remove = ['imax']
22 
23     sounds = ['AC3', 'DD5.1', 'DTS']
24 
25     @staticmethod
26     def re_not_in_word(regexp):
27         return r'(?<![^\W_])' + regexp + r'(?![^\W_])'
28 
29     @staticmethod
30     def strip_spaces(text):
31         """Removes all unnecessary duplicate spaces from a text"""
32         return ' '.join(text.split())
33 
34     @staticmethod
35     def remove_words(text, words, not_in_word=False):
36         """Clean all given :words: from :text: case insensitively"""
37         for word in words:
38             text = TitleParser.ireplace(text, word, '', not_in_word=not_in_word)
39         # remove duplicate spaces
40         text = ' '.join(text.split())
41         return text
42 
43     @staticmethod
44     def ireplace(data, old, new, count=0, not_in_word=False):
45         """Case insensitive string replace"""
46         old = re.escape(old)
47         if not_in_word:
48             old = TitleParser.re_not_in_word(old)
49         pattern = re.compile(old, re.I)
50         return re.sub(pattern, new, data, count)
51
```
--- 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/utils/titles/movie.py b/flexget/utils/titles/movie.py
--- a/flexget/utils/titles/movie.py
+++ b/flexget/utils/titles/movie.py
@@ -7,6 +7,7 @@
 from flexget.utils.titles.parser import TitleParser
 from flexget.utils import qualities
 from flexget.utils.tools import str_to_int
+from datetime import datetime
 
 log = logging.getLogger('movieparser')
 
@@ -60,6 +61,7 @@
         # parsing results
         self.name = None
         self.year = None
+        self.year_pos = None
         self.quality = qualities.Quality()
         self.proper_count = 0
 
@@ -102,8 +104,13 @@
             # check for year
             num = str_to_int(part)
             if num is not None:
-                if 1930 < num < 2050:
+                if 1930 < num <= datetime.now().year:
+                    if self.year_pos == cut_part:
+                        # Looks like a year, but we already set the cutpoint to a year, let's move it forward
+                        cut_part = part_pos
+                        
                     self.year = num
+                    self.year_pos = part_pos
                     cut = True
             # Don't consider all caps words cut words if the whole title has been all caps
             if not part.isupper():
@@ -116,8 +123,10 @@
                 cut = True
             # check for propers
             if part.lower() in self.propers:
-                self.proper_count += 1
-                cut = True
+                # 'real' and 'final' are too common in movie titles, only cut if it comes after year
+                if part.lower() not in ['real', 'final'] or self.year:
+                    self.proper_count += 1
+                    cut = True
             # update cut position
             if cut and parts.index(part) < cut_part:
                 cut_part = part_pos
diff --git a/flexget/utils/titles/parser.py b/flexget/utils/titles/parser.py
--- a/flexget/utils/titles/parser.py
+++ b/flexget/utils/titles/parser.py
@@ -16,7 +16,7 @@
 
     # lowercase required
     cutoffs = ['limited', 'xvid', 'h264', 'x264', 'h.264', 'x.264', 'screener', 'unrated', '3d', 'extended',
-               'directors', 'director\'s', 'multisubs', 'dubbed', 'subbed', 'multi'] + propers + specials + editions
+               'directors', 'director\'s', 'multisubs', 'dubbed', 'subbed', 'multi'] + specials + editions
 
     remove = ['imax']

{"golden_diff": "diff --git a/flexget/utils/titles/movie.py b/flexget/utils/titles/movie.py\n--- a/flexget/utils/titles/movie.py\n+++ b/flexget/utils/titles/movie.py\n@@ -7,6 +7,7 @@\n from flexget.utils.titles.parser import TitleParser\n from flexget.utils import qualities\n from flexget.utils.tools import str_to_int\n+from datetime import datetime\n \n log = logging.getLogger('movieparser')\n \n@@ -60,6 +61,7 @@\n         # parsing results\n         self.name = None\n         self.year = None\n+        self.year_pos = None\n         self.quality = qualities.Quality()\n         self.proper_count = 0\n \n@@ -102,8 +104,13 @@\n             # check for year\n             num = str_to_int(part)\n             if num is not None:\n-                if 1930 < num < 2050:\n+                if 1930 < num <= datetime.now().year:\n+                    if self.year_pos == cut_part:\n+                        # Looks like a year, but we already set the cutpoint to a year, let's move it forward\n+                        cut_part = part_pos\n+                        \n                     self.year = num\n+                    self.year_pos = part_pos\n                     cut = True\n             # Don't consider all caps words cut words if the whole title has been all caps\n             if not part.isupper():\n@@ -116,8 +123,10 @@\n                 cut = True\n             # check for propers\n             if part.lower() in self.propers:\n-                self.proper_count += 1\n-                cut = True\n+                # 'real' and 'final' are too common in movie titles, only cut if it comes after year\n+                if part.lower() not in ['real', 'final'] or self.year:\n+                    self.proper_count += 1\n+                    cut = True\n             # update cut position\n             if cut and parts.index(part) < cut_part:\n                 cut_part = part_pos\ndiff --git a/flexget/utils/titles/parser.py b/flexget/utils/titles/parser.py\n--- a/flexget/utils/titles/parser.py\n+++ b/flexget/utils/titles/parser.py\n@@ -16,7 +16,7 @@\n \n     # lowercase required\n     cutoffs = ['limited', 'xvid', 'h264', 'x264', 'h.264', 'x.264', 'screener', 'unrated', '3d', 'extended',\n-               'directors', 'director\\'s', 'multisubs', 'dubbed', 'subbed', 'multi'] + propers + specials + editions\n+               'directors', 'director\\'s', 'multisubs', 'dubbed', 'subbed', 'multi'] + specials + editions\n \n     remove = ['imax']\n", "issue": "Some words confuse movie name parsing.\nEntry title is \"dan in real life 2007\", parser stops at \"real\"\n\n```\n2016-05-01 09:32 DEBUG    imdb_lookup   library_movies_cleanup_test lookup for d\nan in real life 2007\n2016-05-01 09:32 VERBOSE  imdb_lookup   library_movies_cleanup_test Searching fr\nom imdb `dan in real life 2007`\n2016-05-01 09:32 DEBUG    parser_internal library_movies_cleanup_test Parsing mo\nvie: `dan in real life 2007` kwargs: {}\n2016-05-01 09:32 DEBUG    movieparser   library_movies_cleanup_test parts: [u'da\nn', u'in', u'real', u'life', u'2007'], cut is: real\n2016-05-01 09:32 DEBUG    movieparser   library_movies_cleanup_test after parts \ncheck, cut data would be: `dan in` abs_cut: 6\n2016-05-01 09:32 DEBUG    movieparser   library_movies_cleanup_test data cut to \n`dan in` - this will be the name\n2016-05-01 09:32 DEBUG    parser_internal library_movies_cleanup_test Parsing re\nsult: <MovieParser(name=dan in,year=2007,quality=unknown)> (in 0.92 ms)\n2016-05-01 09:32 DEBUG    utils.imdb    library_movies_cleanup_test smart_match \nname=dan in year=2007\n2016-05-01 09:32 DEBUG    utils.imdb    library_movies_cleanup_test Searching: d\nan in\n```\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.utils.titles.parser import TitleParser\nfrom flexget.utils import qualities\nfrom flexget.utils.tools import str_to_int\n\nlog = logging.getLogger('movieparser')\n\n\ndef diff_pos(string1, string2):\n    \"\"\"Returns first position where string1 and string2 differ.\"\"\"\n    for (count, c) in enumerate(string1):\n        if len(string2) <= count:\n            return count\n        if string2[count] != c:\n            return count\n\n\nclass MovieParser(TitleParser):\n\n    def __init__(self):\n        self.data = None\n        self.reset()\n        TitleParser.__init__(self)\n\n    @property\n    def fields(self):\n        \"\"\"\n        Return a dict of all parser fields\n        \"\"\"\n        return {\n            'movie_parser': self,\n            'movie_name': self.name,\n            'movie_year': self.year,\n            'proper': self.proper,\n            'proper_count': self.proper_count\n        }\n\n    @property\n    def valid(self):\n        return True\n\n    @property\n    def proper(self):\n        return self.proper_count > 0\n\n    @property\n    def is_series(self):\n        return False\n\n    @property\n    def is_movie(self):\n        return True\n\n    def reset(self):\n        # parsing results\n        self.name = None\n        self.year = None\n        self.quality = qualities.Quality()\n        self.proper_count = 0\n\n    def __str__(self):\n        return \"<MovieParser(name=%s,year=%s,quality=%s)>\" % (self.name, self.year, self.quality)\n\n    def parse(self, data=None):\n        \"\"\"Parse movie name. Populates name, year, quality and proper_count attributes\"\"\"\n\n        # Reset before parsing, so the parser can be reused.\n        self.reset()\n\n        if data is None:\n            data = self.data\n\n        # Move anything in leading brackets to the end\n        data = re.sub(r'^\\[(.*?)\\](.*)', r'\\2 \\1', data)\n\n        for char in '[]()_,.':\n            data = data.replace(char, ' ')\n\n        # if there are no spaces\n        if data.find(' ') == -1:\n            data = data.replace('-', ' ')\n\n        # remove unwanted words (imax, ..)\n        self.remove_words(data, self.remove)\n\n        data = self.strip_spaces(data)\n\n        # split to parts\n        parts = data.split(' ')\n        cut_part = 256\n        all_caps = True\n        for part_pos, part in enumerate(parts):\n            cut = False\n            # Don't let the first word be cutoff word\n            if part_pos < 1:\n                continue\n            # check for year\n            num = str_to_int(part)\n            if num is not None:\n                if 1930 < num < 2050:\n                    self.year = num\n                    cut = True\n            # Don't consider all caps words cut words if the whole title has been all caps\n            if not part.isupper():\n                all_caps = False\n            # if length > 3 and whole word in uppers, consider as cut word (most likely a group name)\n            if len(part) > 3 and part.isupper() and part.isalpha() and not all_caps:\n                cut = True\n            # check for cutoff words\n            if part.lower() in self.cutoffs:\n                cut = True\n            # check for propers\n            if part.lower() in self.propers:\n                self.proper_count += 1\n                cut = True\n            # update cut position\n            if cut and parts.index(part) < cut_part:\n                cut_part = part_pos\n\n        if cut_part != 256:\n            log.debug('parts: %s, cut is: %s', parts, parts[cut_part])\n\n        # calculate cut positon from cut_part\n        abs_cut = len(' '.join(parts[:cut_part]))\n\n        log.debug('after parts check, cut data would be: `%s` abs_cut: %i', data[:abs_cut], abs_cut)\n\n        # parse quality\n        quality = qualities.Quality(data)\n        if quality:\n            self.quality = quality\n            # remaining string is same as data but quality information removed\n            # find out position where there is first difference, this is earliest\n            # quality bit, anything after that has no relevance to the movie name\n            dp = diff_pos(data, quality.clean_text)\n            if dp is not None:\n                log.debug('quality start: %s', dp)\n                if dp < abs_cut:\n                    log.debug('quality cut is even shorter')\n                    abs_cut = dp\n\n        # make cut\n        data = data[:abs_cut].strip()\n        log.debug('data cut to `%s` - this will be the name', data)\n\n        # save results\n        self.name = data\n", "path": "flexget/utils/titles/movie.py"}, {"content": "from __future__ import unicode_literals, division, absolute_import\nfrom builtins import *  # pylint: disable=unused-import, redefined-builtin\n\nimport re\n\n\nclass TitleParser(object):\n    propers = ['proper', 'repack', 'rerip', 'real', 'final']\n\n    specials = ['special', 'bonus', 'extra', 'omake', 'ova']\n\n    editions = ['dc', 'extended', 'uncut', 'remastered', 'unrated', 'theatrical', 'chrono', 'se']\n\n    # TODO: All of the quality related keywords can probably be removed from here, as the quality module handles them\n    codecs = ['x264', 'x.264', 'h264', 'h.264', 'XViD']\n\n    # lowercase required\n    cutoffs = ['limited', 'xvid', 'h264', 'x264', 'h.264', 'x.264', 'screener', 'unrated', '3d', 'extended',\n               'directors', 'director\\'s', 'multisubs', 'dubbed', 'subbed', 'multi'] + propers + specials + editions\n\n    remove = ['imax']\n\n    sounds = ['AC3', 'DD5.1', 'DTS']\n\n    @staticmethod\n    def re_not_in_word(regexp):\n        return r'(?<![^\\W_])' + regexp + r'(?![^\\W_])'\n\n    @staticmethod\n    def strip_spaces(text):\n        \"\"\"Removes all unnecessary duplicate spaces from a text\"\"\"\n        return ' '.join(text.split())\n\n    @staticmethod\n    def remove_words(text, words, not_in_word=False):\n        \"\"\"Clean all given :words: from :text: case insensitively\"\"\"\n        for word in words:\n            text = TitleParser.ireplace(text, word, '', not_in_word=not_in_word)\n        # remove duplicate spaces\n        text = ' '.join(text.split())\n        return text\n\n    @staticmethod\n    def ireplace(data, old, new, count=0, not_in_word=False):\n        \"\"\"Case insensitive string replace\"\"\"\n        old = re.escape(old)\n        if not_in_word:\n            old = TitleParser.re_not_in_word(old)\n        pattern = re.compile(old, re.I)\n        return re.sub(pattern, new, data, count)\n", "path": "flexget/utils/titles/parser.py"}], "after_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.utils.titles.parser import TitleParser\nfrom flexget.utils import qualities\nfrom flexget.utils.tools import str_to_int\nfrom datetime import datetime\n\nlog = logging.getLogger('movieparser')\n\n\ndef diff_pos(string1, string2):\n    \"\"\"Returns first position where string1 and string2 differ.\"\"\"\n    for (count, c) in enumerate(string1):\n        if len(string2) <= count:\n            return count\n        if string2[count] != c:\n            return count\n\n\nclass MovieParser(TitleParser):\n\n    def __init__(self):\n        self.data = None\n        self.reset()\n        TitleParser.__init__(self)\n\n    @property\n    def fields(self):\n        \"\"\"\n        Return a dict of all parser fields\n        \"\"\"\n        return {\n            'movie_parser': self,\n            'movie_name': self.name,\n            'movie_year': self.year,\n            'proper': self.proper,\n            'proper_count': self.proper_count\n        }\n\n    @property\n    def valid(self):\n        return True\n\n    @property\n    def proper(self):\n        return self.proper_count > 0\n\n    @property\n    def is_series(self):\n        return False\n\n    @property\n    def is_movie(self):\n        return True\n\n    def reset(self):\n        # parsing results\n        self.name = None\n        self.year = None\n        self.year_pos = None\n        self.quality = qualities.Quality()\n        self.proper_count = 0\n\n    def __str__(self):\n        return \"<MovieParser(name=%s,year=%s,quality=%s)>\" % (self.name, self.year, self.quality)\n\n    def parse(self, data=None):\n        \"\"\"Parse movie name. Populates name, year, quality and proper_count attributes\"\"\"\n\n        # Reset before parsing, so the parser can be reused.\n        self.reset()\n\n        if data is None:\n            data = self.data\n\n        # Move anything in leading brackets to the end\n        data = re.sub(r'^\\[(.*?)\\](.*)', r'\\2 \\1', data)\n\n        for char in '[]()_,.':\n            data = data.replace(char, ' ')\n\n        # if there are no spaces\n        if data.find(' ') == -1:\n            data = data.replace('-', ' ')\n\n        # remove unwanted words (imax, ..)\n        self.remove_words(data, self.remove)\n\n        data = self.strip_spaces(data)\n\n        # split to parts\n        parts = data.split(' ')\n        cut_part = 256\n        all_caps = True\n        for part_pos, part in enumerate(parts):\n            cut = False\n            # Don't let the first word be cutoff word\n            if part_pos < 1:\n                continue\n            # check for year\n            num = str_to_int(part)\n            if num is not None:\n                if 1930 < num <= datetime.now().year:\n                    if self.year_pos == cut_part:\n                        # Looks like a year, but we already set the cutpoint to a year, let's move it forward\n                        cut_part = part_pos\n                        \n                    self.year = num\n                    self.year_pos = part_pos\n                    cut = True\n            # Don't consider all caps words cut words if the whole title has been all caps\n            if not part.isupper():\n                all_caps = False\n            # if length > 3 and whole word in uppers, consider as cut word (most likely a group name)\n            if len(part) > 3 and part.isupper() and part.isalpha() and not all_caps:\n                cut = True\n            # check for cutoff words\n            if part.lower() in self.cutoffs:\n                cut = True\n            # check for propers\n            if part.lower() in self.propers:\n                # 'real' and 'final' are too common in movie titles, only cut if it comes after year\n                if part.lower() not in ['real', 'final'] or self.year:\n                    self.proper_count += 1\n                    cut = True\n            # update cut position\n            if cut and parts.index(part) < cut_part:\n                cut_part = part_pos\n\n        if cut_part != 256:\n            log.debug('parts: %s, cut is: %s', parts, parts[cut_part])\n\n        # calculate cut positon from cut_part\n        abs_cut = len(' '.join(parts[:cut_part]))\n\n        log.debug('after parts check, cut data would be: `%s` abs_cut: %i', data[:abs_cut], abs_cut)\n\n        # parse quality\n        quality = qualities.Quality(data)\n        if quality:\n            self.quality = quality\n            # remaining string is same as data but quality information removed\n            # find out position where there is first difference, this is earliest\n            # quality bit, anything after that has no relevance to the movie name\n            dp = diff_pos(data, quality.clean_text)\n            if dp is not None:\n                log.debug('quality start: %s', dp)\n                if dp < abs_cut:\n                    log.debug('quality cut is even shorter')\n                    abs_cut = dp\n\n        # make cut\n        data = data[:abs_cut].strip()\n        log.debug('data cut to `%s` - this will be the name', data)\n\n        # save results\n        self.name = data\n", "path": "flexget/utils/titles/movie.py"}, {"content": "from __future__ import unicode_literals, division, absolute_import\nfrom builtins import *  # pylint: disable=unused-import, redefined-builtin\n\nimport re\n\n\nclass TitleParser(object):\n    propers = ['proper', 'repack', 'rerip', 'real', 'final']\n\n    specials = ['special', 'bonus', 'extra', 'omake', 'ova']\n\n    editions = ['dc', 'extended', 'uncut', 'remastered', 'unrated', 'theatrical', 'chrono', 'se']\n\n    # TODO: All of the quality related keywords can probably be removed from here, as the quality module handles them\n    codecs = ['x264', 'x.264', 'h264', 'h.264', 'XViD']\n\n    # lowercase required\n    cutoffs = ['limited', 'xvid', 'h264', 'x264', 'h.264', 'x.264', 'screener', 'unrated', '3d', 'extended',\n               'directors', 'director\\'s', 'multisubs', 'dubbed', 'subbed', 'multi'] + specials + editions\n\n    remove = ['imax']\n\n    sounds = ['AC3', 'DD5.1', 'DTS']\n\n    @staticmethod\n    def re_not_in_word(regexp):\n        return r'(?<![^\\W_])' + regexp + r'(?![^\\W_])'\n\n    @staticmethod\n    def strip_spaces(text):\n        \"\"\"Removes all unnecessary duplicate spaces from a text\"\"\"\n        return ' '.join(text.split())\n\n    @staticmethod\n    def remove_words(text, words, not_in_word=False):\n        \"\"\"Clean all given :words: from :text: case insensitively\"\"\"\n        for word in words:\n            text = TitleParser.ireplace(text, word, '', not_in_word=not_in_word)\n        # remove duplicate spaces\n        text = ' '.join(text.split())\n        return text\n\n    @staticmethod\n    def ireplace(data, old, new, count=0, not_in_word=False):\n        \"\"\"Case insensitive string replace\"\"\"\n        old = re.escape(old)\n        if not_in_word:\n            old = TitleParser.re_not_in_word(old)\n        pattern = re.compile(old, re.I)\n        return re.sub(pattern, new, data, count)\n", "path": "flexget/utils/titles/parser.py"}]}