#!/usr/bin/env python # -*- coding: utf-8 -*- """ screen_size property """ from rebulk.remodule import re from rebulk import Rebulk, Rule, RemoveMatch from ..common.validators import seps_surround from ..common import dash, seps def screen_size(): """ Builder for rebulk object. :return: Created Rebulk object :rtype: Rebulk """ def conflict_solver(match, other): """ Conflict solver for most screen_size. """ if other.name == 'screen_size': if 'resolution' in other.tags: # The chtouile to solve conflict in "720 x 432" string matching both 720p pattern int_value = _digits_re.findall(match.raw)[-1] if other.value.startswith(int_value): return match return other return '__default__' rebulk = Rebulk().string_defaults(ignore_case=True).regex_defaults(flags=re.IGNORECASE) rebulk.defaults(name="screen_size", validator=seps_surround, conflict_solver=conflict_solver) rebulk.regex(r"(?:\d{3,}(?:x|\*))?360(?:i|p?x?)", value="360p") rebulk.regex(r"(?:\d{3,}(?:x|\*))?368(?:i|p?x?)", value="368p") rebulk.regex(r"(?:\d{3,}(?:x|\*))?480(?:i|p?x?)", value="480p") rebulk.regex(r"(?:\d{3,}(?:x|\*))?576(?:i|p?x?)", value="576p") rebulk.regex(r"(?:\d{3,}(?:x|\*))?720(?:i|p?(?:50|60)?x?)", value="720p") rebulk.regex(r"(?:\d{3,}(?:x|\*))?720(?:p(?:50|60)?x?)", value="720p") rebulk.regex(r"(?:\d{3,}(?:x|\*))?720p?hd", value="720p") rebulk.regex(r"(?:\d{3,}(?:x|\*))?900(?:i|p?x?)", value="900p") rebulk.regex(r"(?:\d{3,}(?:x|\*))?1080i", value="1080i") rebulk.regex(r"(?:\d{3,}(?:x|\*))?1080p?x?", value="1080p") rebulk.regex(r"(?:\d{3,}(?:x|\*))?1080(?:p(?:50|60)?x?)", value="1080p") rebulk.regex(r"(?:\d{3,}(?:x|\*))?1080p?hd", value="1080p") rebulk.regex(r"(?:\d{3,}(?:x|\*))?2160(?:i|p?x?)", value="4K") rebulk.string('4k', value='4K') _digits_re = re.compile(r'\d+') rebulk.defaults(name="screen_size", validator=seps_surround) rebulk.regex(r'\d{3,}-?(?:x|\*)-?\d{3,}', formatter=lambda value: 'x'.join(_digits_re.findall(value)), abbreviations=[dash], tags=['resolution'], conflict_solver=lambda match, other: '__default__' if other.name == 'screen_size' else other) rebulk.rules(ScreenSizeOnlyOne, RemoveScreenSizeConflicts) return rebulk class ScreenSizeOnlyOne(Rule): """ Keep a single screen_size pet filepath part. """ consequence = RemoveMatch def when(self, matches, context): to_remove = [] for filepart in matches.markers.named('path'): screensize = list(reversed(matches.range(filepart.start, filepart.end, lambda match: match.name == 'screen_size'))) if len(screensize) > 1: to_remove.extend(screensize[1:]) return to_remove class RemoveScreenSizeConflicts(Rule): """ Remove season and episode matches which conflicts with screen_size match. """ consequence = RemoveMatch def when(self, matches, context): to_remove = [] for filepart in matches.markers.named('path'): screensize = matches.range(filepart.start, filepart.end, lambda match: match.name == 'screen_size', 0) if not screensize: continue conflicts = matches.conflicting(screensize, lambda match: match.name in ('season', 'episode')) if not conflicts: continue video_profile = matches.range(screensize.end, filepart.end, lambda match: match.name == 'video_profile', 0) if video_profile and not matches.holes(screensize.end, video_profile.start, predicate=lambda h: h.value and h.value.strip(seps)): to_remove.extend(conflicts) date = matches.previous(screensize, lambda match: match.name == 'date', 0) if date and not matches.holes(date.end, screensize.start, predicate=lambda h: h.value and h.value.strip(seps)): to_remove.extend(conflicts) return to_remove