<commit_before>import logging
import os
import re

from . import errors
from .libraries import TheTvDb, TvRage


log = logging.getLogger('Core')


def clean_name(filename, before=':', after=','):
    """
    Cleans the string passed in.

    A wrapper of Python's str.replace() with the idea of making the string
    safe for all file systems, but not using the horrible \ character.
    Also allows the user to specify the new characters to be used.

    """
    return filename.replace(before, after)


class Episode(object):

    def __init__(self, _file, number):
        self._file = _file  # cache reverse reference to parent object
        self.number = number

    def __getattr__(self, name):
        if name == 'episode':
            msg = 'Missing episode: Set it with --episode or use %e in your --regex string'
            raise AttributeError(msg)

        msg = "'{0}' object has no attribute '{1}'".format(self.__class__.__name__, name)
        raise AttributeError(msg)

    def __getattribute__(self, item):
        """
        Allow the retrieval of single digit episode numbers but return
        it with a leading zero.
        """
        if item is 'episode_2':
            return '0{0}'.format(self.number)
        return object.__getattribute__(self, item)

    def __str__(self):
        return '{0} - {1}'.format(self.number, self.title)


class File(object):
    default_format = '%n - %s%e - %t.%x'

    def __init__(self, show_name='', season='', episodes=(), extension=''):
        self.show_name = show_name
        self.season = season
        self.episodes = [Episode(_file=self, number=i) for i in episodes]
        self.extension = extension

    def __str__(self):
        filename = getattr(self, 'output_format', self.default_format)

        filename = filename.replace('%n', self.show_name)
        filename = filename.replace('%t', self.title)
        filename = filename.replace('%x', self.extension)

        filename = self.get_season_output(filename)
        filename = self.get_episode_output(filename)

        return filename

    def get_episode_output(self, filename, marker='%e', fill=2):
        if '%e{' in filename:
            fill = filename.split('%e{')[1][:1]
            marker = '%e{' + fill + '}'
        episode = '-'.join([e.number.zfill(int(fill)) for e in self.episodes])
        return filename.replace(marker, episode)

    def get_season_output(self, filename, marker='%s', fill=1):
        if '%s{' in filename:
            fill = filename.split('%s{')[1][:1]
            marker = '%s{' + fill + '}'
        season = self.season.zfill(int(fill))
        return filename.replace(marker, season)

    @property
    def title(self):
        titles = [e.title for e in self.episodes]

        # Check the titles aren't all the same with different (x) parts
        suffixes = tuple('({0})'.format(i+1) for i in range(len(titles)))
        if any([t.endswith(suffixes) for t in titles]):
            stripped_titles = set([t[:-4] for t in titles])
            if len(stripped_titles) is 1:
                titles = stripped_titles

        return ' & '.join(titles)

    def set_output_format(self, user_format, config):
        if user_format is None:
            self.output_format = config.get(self.show_name, 'format')
        else:
            self.output_format = user_format

    def user_overrides(self, show_name, season, episode):
        if show_name:
            self.show_name = show_name

        for e in self.episodes:
            if season:
                e.season = season
            if episode:
                e.number = episode


class TvRenamr(object):
    def __init__(self, working_dir, config, debug=False, dry=False, cache=True):
        self.cache = cache
        self.working_dir = working_dir
        self.dry = dry
        self.debug = debug
        self.config = config

    def remove_part_from_multiple_episodes(self, show_name):
        """Remove the string "Part " from a filename.

        In episode titles of multi-part episodes that use the format
        (Part n) remove the 'Part ' section so the format is (n).

        """
        log.debug('Removing Part from episode name')
        return show_name.replace('(Part ', '(')

    def extract_details_from_file(self, fn, user_regex=None):
        """Using a regular expression extract information from the filename passed in.

        Looks at the file given and extracts from it the show title, it's
        season number and episode number using regular expression magic.
        The default formats accepted are: series.0x00.xxx or series.s0e00.xxx<commit_msg>Set season on File instead of Episode<commit_after>import logging
import os
import re

from . import errors
from .libraries import TheTvDb, TvRage


log = logging.getLogger('Core')


def clean_name(filename, before=':', after=','):
    """
    Cleans the string passed in.

    A wrapper of Python's str.replace() with the idea of making the string
    safe for all file systems, but not using the horrible \ character.
    Also allows the user to specify the new characters to be used.

    """
    return filename.replace(before, after)


class Episode(object):

    def __init__(self, _file, number):
        self._file = _file  # cache reverse reference to parent object
        self.number = number

    def __getattr__(self, name):
        if name == 'episode':
            msg = 'Missing episode: Set it with --episode or use %e in your --regex string'
            raise AttributeError(msg)

        msg = "'{0}' object has no attribute '{1}'".format(self.__class__.__name__, name)
        raise AttributeError(msg)

    def __getattribute__(self, item):
        """
        Allow the retrieval of single digit episode numbers but return
        it with a leading zero.
        """
        if item is 'episode_2':
            return '0{0}'.format(self.number)
        return object.__getattribute__(self, item)

    def __str__(self):
        return '{0} - {1}'.format(self.number, self.title)


class File(object):
    default_format = '%n - %s%e - %t.%x'

    def __init__(self, show_name='', season='', episodes=(), extension=''):
        self.show_name = show_name
        self.season = season
        self.episodes = [Episode(_file=self, number=i) for i in episodes]
        self.extension = extension

    def __str__(self):
        filename = getattr(self, 'output_format', self.default_format)

        filename = filename.replace('%n', self.show_name)
        filename = filename.replace('%t', self.title)
        filename = filename.replace('%x', self.extension)

        filename = self.get_season_output(filename)
        filename = self.get_episode_output(filename)

        return filename

    def get_episode_output(self, filename, marker='%e', fill=2):
        if '%e{' in filename:
            fill = filename.split('%e{')[1][:1]
            marker = '%e{' + fill + '}'
        episode = '-'.join([e.number.zfill(int(fill)) for e in self.episodes])
        return filename.replace(marker, episode)

    def get_season_output(self, filename, marker='%s', fill=1):
        if '%s{' in filename:
            fill = filename.split('%s{')[1][:1]
            marker = '%s{' + fill + '}'
        season = self.season.zfill(int(fill))
        return filename.replace(marker, season)

    @property
    def title(self):
        titles = [e.title for e in self.episodes]

        # Check the titles aren't all the same with different (x) parts
        suffixes = tuple('({0})'.format(i+1) for i in range(len(titles)))
        if any([t.endswith(suffixes) for t in titles]):
            stripped_titles = set([t[:-4] for t in titles])
            if len(stripped_titles) is 1:
                titles = stripped_titles

        return ' & '.join(titles)

    def set_output_format(self, user_format, config):
        if user_format is None:
            self.output_format = config.get(self.show_name, 'format')
        else:
            self.output_format = user_format

    def user_overrides(self, show_name, season, episode):
        if show_name:
            self.show_name = show_name

        if season:
            self.season = int(season)
        for e in self.episodes:
            if episode:
                e.number = episode


class TvRenamr(object):
    def __init__(self, working_dir, config, debug=False, dry=False, cache=True):
        self.cache = cache
        self.working_dir = working_dir
        self.dry = dry
        self.debug = debug
        self.config = config

    def remove_part_from_multiple_episodes(self, show_name):
        """Remove the string "Part " from a filename.

        In episode titles of multi-part episodes that use the format
        (Part n) remove the 'Part ' section so the format is (n).

        """
        log.debug('Removing Part from episode name')
        return show_name.replace('(Part ', '(')

    def extract_details_from_file(self, fn, user_regex=None):
        """Using a regular expression extract information from the filename passed in.

        Looks at the file given and extracts from it the show title, it's
        season number and episode number using regular expression magic.
        The default formats accepted are: series.0x00.xxx or series.s0e00.xxx
{'fraction_non_alphanumeric': 0.11051154759335204, 'fraction_numerical': 0.004964385927045111, 'mean_word_length': 2.49302676215605, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 5, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1306925', 'n_tokens_mistral': 2725, 'n_tokens_neox': 2631, 'n_words': 835}