|
|
|
#!/usr/bin/env python
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
"""
|
|
|
|
date, week and year properties
|
|
|
|
"""
|
|
|
|
import re
|
|
|
|
|
|
|
|
from rebulk import Rebulk, RemoveMatch, Rule
|
|
|
|
|
|
|
|
from ..common import dash
|
|
|
|
from ..common.date import search_date, valid_year, valid_week
|
|
|
|
from ..common.pattern import is_disabled
|
|
|
|
from ..common.validators import seps_surround
|
|
|
|
from ...reutils import build_or_pattern
|
|
|
|
|
|
|
|
|
|
|
|
def date(config): # pylint:disable=unused-argument
|
|
|
|
"""
|
|
|
|
Builder for rebulk object.
|
|
|
|
|
|
|
|
:param config: rule configuration
|
|
|
|
:type config: dict
|
|
|
|
:return: Created Rebulk object
|
|
|
|
:rtype: Rebulk
|
|
|
|
"""
|
|
|
|
rebulk = Rebulk().defaults(validator=seps_surround)
|
|
|
|
|
|
|
|
rebulk.regex(r"\d{4}", name="year", formatter=int,
|
|
|
|
disabled=lambda context: is_disabled(context, 'year'),
|
|
|
|
conflict_solver=lambda match, other: other
|
|
|
|
if other.name in ('episode', 'season') and len(other.raw) < len(match.raw)
|
|
|
|
else '__default__',
|
|
|
|
validator=lambda match: seps_surround(match) and valid_year(match.value))
|
|
|
|
|
|
|
|
rebulk.regex(build_or_pattern(config.get('week_words')) + r"-?(\d{1,2})",
|
|
|
|
name="week", formatter=int,
|
|
|
|
children=True,
|
|
|
|
flags=re.IGNORECASE, abbreviations=[dash],
|
|
|
|
conflict_solver=lambda match, other: other
|
|
|
|
if other.name in ('episode', 'season') and len(other.raw) < len(match.raw)
|
|
|
|
else '__default__',
|
|
|
|
validator=lambda match: seps_surround(match) and valid_week(match.value))
|
|
|
|
|
|
|
|
def date_functional(string, context): # pylint:disable=inconsistent-return-statements
|
|
|
|
"""
|
|
|
|
Search for date in the string and retrieves match
|
|
|
|
|
|
|
|
:param string:
|
|
|
|
:return:
|
|
|
|
"""
|
|
|
|
|
|
|
|
ret = search_date(string, context.get('date_year_first'), context.get('date_day_first'))
|
|
|
|
if ret:
|
|
|
|
return ret[0], ret[1], {'value': ret[2]}
|
|
|
|
|
|
|
|
rebulk.functional(date_functional, name="date", properties={'date': [None]},
|
|
|
|
disabled=lambda context: is_disabled(context, 'date'),
|
|
|
|
conflict_solver=lambda match, other: other
|
|
|
|
if other.name in ('episode', 'season', 'crc32')
|
|
|
|
else '__default__')
|
|
|
|
|
|
|
|
rebulk.rules(KeepMarkedYearInFilepart)
|
|
|
|
|
|
|
|
return rebulk
|
|
|
|
|
|
|
|
|
|
|
|
class KeepMarkedYearInFilepart(Rule):
|
|
|
|
"""
|
|
|
|
Keep first years marked with [](){} in filepart, or if no year is marked, ensure it won't override titles.
|
|
|
|
"""
|
|
|
|
priority = 64
|
|
|
|
consequence = RemoveMatch
|
|
|
|
|
|
|
|
def enabled(self, context):
|
|
|
|
return not is_disabled(context, 'year')
|
|
|
|
|
|
|
|
def when(self, matches, context):
|
|
|
|
ret = []
|
|
|
|
if len(matches.named('year')) > 1:
|
|
|
|
for filepart in matches.markers.named('path'):
|
|
|
|
years = matches.range(filepart.start, filepart.end, lambda match: match.name == 'year')
|
|
|
|
if len(years) > 1:
|
|
|
|
group_years = []
|
|
|
|
ungroup_years = []
|
|
|
|
for year in years:
|
|
|
|
if matches.markers.at_match(year, lambda marker: marker.name == 'group'):
|
|
|
|
group_years.append(year)
|
|
|
|
else:
|
|
|
|
ungroup_years.append(year)
|
|
|
|
if group_years and ungroup_years:
|
|
|
|
ret.extend(ungroup_years)
|
|
|
|
ret.extend(group_years[1:]) # Keep the first year in marker.
|
|
|
|
elif not group_years:
|
|
|
|
ret.append(ungroup_years[0]) # Keep first year for title.
|
|
|
|
if len(ungroup_years) > 2:
|
|
|
|
ret.extend(ungroup_years[2:])
|
|
|
|
return ret
|