Browse Source

Updated Caper to v0.2.9

pull/2599/head
Dean Gardiner 12 years ago
parent
commit
93aa5b1920
  1. 40
      libs/caper/__init__.py
  2. 4
      libs/caper/helpers.py
  3. 11
      libs/caper/matcher.py
  4. 10
      libs/caper/objects.py
  5. 5
      libs/caper/parsers/base.py
  6. 44
      libs/caper/parsers/scene.py

40
libs/caper/__init__.py

@ -19,7 +19,7 @@ from caper.parsers.anime import AnimeParser
from caper.parsers.scene import SceneParser from caper.parsers.scene import SceneParser
__version_info__ = ('0', '2', '6') __version_info__ = ('0', '2', '9')
__version_branch__ = 'master' __version_branch__ = 'master'
__version__ = "%s%s" % ( __version__ = "%s%s" % (
@ -44,9 +44,11 @@ CL_END = 1
class Caper(object): class Caper(object):
def __init__(self, debug=False): def __init__(self, debug=False):
self.debug = debug
self.parsers = { self.parsers = {
'scene': SceneParser(debug), 'scene': SceneParser,
'anime': AnimeParser(debug) 'anime': AnimeParser
} }
def _closure_split(self, name): def _closure_split(self, name):
@ -63,7 +65,7 @@ class Caper(object):
if len(buf) < 1: if len(buf) < 1:
return return
cur = CaperClosure(buf) cur = CaperClosure(len(closures), buf)
cur.left = closures[len(closures) - 1] if len(closures) > 0 else None cur.left = closures[len(closures) - 1] if len(closures) > 0 else None
if cur.left: if cur.left:
@ -109,7 +111,7 @@ class Caper(object):
""" """
cur_position = 0 cur_position = 0
cur = CaperFragment() cur = None
def end_fragment(fragments, cur, cur_position): def end_fragment(fragments, cur, cur_position):
cur.position = cur_position cur.position = cur_position
@ -126,23 +128,41 @@ class Caper(object):
for closure in closures: for closure in closures:
closure.fragments = [] closure.fragments = []
separator_buffer = ""
for x, ch in enumerate(self._clean_closure(closure.value)): for x, ch in enumerate(self._clean_closure(closure.value)):
if not cur:
cur = CaperFragment(closure)
if ch in FRAGMENT_SEPARATORS: if ch in FRAGMENT_SEPARATORS:
end_fragment(closure.fragments, cur, cur_position) if cur.value:
separator_buffer = ""
separator_buffer += ch
if cur.value or not closure.fragments:
end_fragment(closure.fragments, cur, cur_position)
elif len(separator_buffer) > 1:
cur.value = separator_buffer.strip()
if cur.value:
end_fragment(closure.fragments, cur, cur_position)
separator_buffer = ""
# Reset # Reset
cur = CaperFragment() cur = None
cur_position += 1 cur_position += 1
else: else:
cur.value += ch cur.value += ch
# Finish parsing the last fragment # Finish parsing the last fragment
if cur.value != "": if cur and cur.value:
end_fragment(closure.fragments, cur, cur_position) end_fragment(closure.fragments, cur, cur_position)
# Reset # Reset
cur_position = 0 cur_position = 0
cur = CaperFragment() cur = None
return closures return closures
@ -158,4 +178,4 @@ class Caper(object):
raise ValueError("Unknown parser") raise ValueError("Unknown parser")
# TODO autodetect the parser type # TODO autodetect the parser type
return self.parsers[parser].run(closures) return self.parsers[parser](self.debug).run(closures)

4
libs/caper/helpers.py

@ -74,3 +74,7 @@ def xrange_six(start, stop=None, step=None):
return range(start) return range(start)
else: else:
return xrange(start) return xrange(start)
def delta_seconds(td):
return (td.microseconds + (td.seconds + td.days * 24 * 3600) * 1e6) / 1e6

11
libs/caper/matcher.py

@ -12,9 +12,10 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import re from caper.helpers import is_list_type, update_dict, delta_seconds
from datetime import datetime
from logr import Logr from logr import Logr
from caper.helpers import is_list_type, update_dict import re
class FragmentMatcher(object): class FragmentMatcher(object):
@ -24,6 +25,9 @@ class FragmentMatcher(object):
self.construct_patterns(pattern_groups) self.construct_patterns(pattern_groups)
def construct_patterns(self, pattern_groups): def construct_patterns(self, pattern_groups):
compile_start = datetime.now()
compile_count = 0
for group_name, patterns in pattern_groups: for group_name, patterns in pattern_groups:
if group_name not in self.regex: if group_name not in self.regex:
self.regex[group_name] = [] self.regex[group_name] = []
@ -54,11 +58,14 @@ class FragmentMatcher(object):
value = value[0] value = value[0]
result.append(re.compile(value, re.IGNORECASE)) result.append(re.compile(value, re.IGNORECASE))
compile_count += 1
weight_patterns.append(tuple(result)) weight_patterns.append(tuple(result))
self.regex[group_name].append((weight, weight_patterns)) self.regex[group_name].append((weight, weight_patterns))
Logr.info("Compiled %s patterns in %ss", compile_count, delta_seconds(datetime.now() - compile_start))
def find_group(self, name): def find_group(self, name):
for group_name, weight_groups in self.regex.items(): for group_name, weight_groups in self.regex.items():
if group_name and group_name == name: if group_name and group_name == name:

10
libs/caper/objects.py

@ -16,7 +16,10 @@ from caper.helpers import xrange_six
class CaperClosure(object): class CaperClosure(object):
def __init__(self, value): def __init__(self, index, value):
#: :type: int
self.index = index
#: :type: str #: :type: str
self.value = value self.value = value
@ -30,7 +33,10 @@ class CaperClosure(object):
class CaperFragment(object): class CaperFragment(object):
def __init__(self): def __init__(self, closure=None):
#: :type: CaperClosure
self.closure = closure
#: :type: str #: :type: str
self.value = "" self.value = ""

5
libs/caper/parsers/base.py

@ -15,13 +15,14 @@
from caper import FragmentMatcher from caper import FragmentMatcher
from caper.group import CaptureGroup from caper.group import CaptureGroup
from caper.result import CaperResult, CaperClosureNode from caper.result import CaperResult, CaperClosureNode
from logr import Logr
class Parser(object): class Parser(object):
def __init__(self, pattern_groups, debug=False): def __init__(self, matcher, debug=False):
self.debug = debug self.debug = debug
self.matcher = FragmentMatcher(pattern_groups) self.matcher = matcher
self.closures = None self.closures = None
#: :type: caper.result.CaperResult #: :type: caper.result.CaperResult

44
libs/caper/parsers/scene.py

@ -13,6 +13,7 @@
# limitations under the License. # limitations under the License.
from logr import Logr from logr import Logr
from caper import FragmentMatcher
from caper.parsers.base import Parser from caper.parsers.base import Parser
from caper.result import CaperFragmentNode from caper.result import CaperFragmentNode
@ -22,8 +23,10 @@ PATTERN_GROUPS = [
(1.0, [ (1.0, [
# S01E01-E02 # S01E01-E02
('^S(?P<season>\d+)E(?P<episode_from>\d+)$', '^E(?P<episode_to>\d+)$'), ('^S(?P<season>\d+)E(?P<episode_from>\d+)$', '^E(?P<episode_to>\d+)$'),
# S03 E01 to E08 # 'S03 E01 to E08' or 'S03 E01 - E09'
('^S(?P<season>\d+)$', '^E(?P<episode_from>\d+)$', '^to$', '^E(?P<episode_to>\d+)$'), ('^S(?P<season>\d+)$', '^E(?P<episode_from>\d+)$', '^(to|-)$', '^E(?P<episode_to>\d+)$'),
# 'E01 to E08' or 'E01 - E09'
('^E(?P<episode_from>\d+)$', '^(to|-)$', '^E(?P<episode_to>\d+)$'),
# S01-S03 # S01-S03
('^S(?P<season_from>\d+)$', '^S(?P<season_to>\d+)$'), ('^S(?P<season_from>\d+)$', '^S(?P<season_to>\d+)$'),
@ -58,6 +61,9 @@ PATTERN_GROUPS = [
# Part.3 # Part.3
# Part.1.and.Part.3 # Part.1.and.Part.3
('^Part$', '(?P<part>\d+)'), ('^Part$', '(?P<part>\d+)'),
r'(?P<extra>Special)',
r'(?P<country>NZ|AU|US|UK)'
]), ]),
(0.8, [ (0.8, [
# 100 - 1899, 2100 - 9999 (skips 1900 to 2099 - so we don't get years my mistake) # 100 - 1899, 2100 - 9999 (skips 1900 to 2099 - so we don't get years my mistake)
@ -69,6 +75,7 @@ PATTERN_GROUPS = [
r'^(?P<season>([1-9])|([1-9][0-9]))(?P<episode>\d{2})$' r'^(?P<season>([1-9])|([1-9][0-9]))(?P<episode>\d{2})$'
]) ])
]), ]),
('video', [ ('video', [
r'(?P<aspect>FS|WS)', r'(?P<aspect>FS|WS)',
@ -152,14 +159,23 @@ PATTERN_GROUPS = [
class SceneParser(Parser): class SceneParser(Parser):
matcher = None
def __init__(self, debug=False): def __init__(self, debug=False):
super(SceneParser, self).__init__(PATTERN_GROUPS, debug) if not SceneParser.matcher:
SceneParser.matcher = FragmentMatcher(PATTERN_GROUPS)
Logr.info("Fragment matcher for %s created", self.__class__.__name__)
super(SceneParser, self).__init__(SceneParser.matcher, debug)
def capture_group(self, fragment): def capture_group(self, fragment):
if fragment.left_sep == '-' and not fragment.right: if fragment.closure.index + 1 != len(self.closures):
return fragment.value return None
if fragment.left_sep != '-' or fragment.right:
return None
return None return fragment.value
def run(self, closures): def run(self, closures):
""" """
@ -170,17 +186,17 @@ class SceneParser(Parser):
self.capture_fragment('show_name', single=False)\ self.capture_fragment('show_name', single=False)\
.until(fragment__re='identifier')\ .until(fragment__re='identifier')\
.until(fragment__re='video') \ .until(fragment__re='video')\
.until(fragment__re='dvd') \ .until(fragment__re='dvd')\
.until(fragment__re='audio') \ .until(fragment__re='audio')\
.until(fragment__re='scene') \ .until(fragment__re='scene')\
.execute() .execute()
self.capture_fragment('identifier', regex='identifier', single=False)\ self.capture_fragment('identifier', regex='identifier', single=False)\
.capture_fragment('video', regex='video', single=False) \ .capture_fragment('video', regex='video', single=False)\
.capture_fragment('dvd', regex='dvd', single=False) \ .capture_fragment('dvd', regex='dvd', single=False)\
.capture_fragment('audio', regex='audio', single=False) \ .capture_fragment('audio', regex='audio', single=False)\
.capture_fragment('scene', regex='scene', single=False) \ .capture_fragment('scene', regex='scene', single=False)\
.until(left_sep__eq='-', right__eq=None)\ .until(left_sep__eq='-', right__eq=None)\
.execute() .execute()

Loading…
Cancel
Save