'An iterative matcher tries to match different patterns that appear
in the filename.
The \'filetype\' argument indicates which type of file you want to match.
If it is \'autodetect\', the matcher will try to see whether it can guess
that the file corresponds to an episode, or otherwise will assume it is
a movie.
The recognized \'filetype\' values are:
[ autodetect, subtitle, info, movie, moviesubtitle, movieinfo, episode,
episodesubtitle, episodeinfo ]
The IterativeMatcher works mainly in 2 steps:
First, it splits the filename into a match_tree, which is a tree of groups
which have a semantic meaning, such as episode number, movie title,
etc...
The match_tree created looks like the following:
0000000000000000000000000000000000000000000000000000000000000000000000000000000000 111
0000011111111111112222222222222233333333444444444444444455555555666777777778888888 000
0000000000000000000000000000000001111112011112222333333401123334000011233340000000 000
__________________(The.Prestige).______.[____.HP.______.{__-___}.St{__-___}.Chaps].___
xxxxxttttttttttttt               ffffff  vvvv    xxxxxx  ll lll     xx xxx         ccc
[XCT].Le.Prestige.(The.Prestige).DVDRip.[x264.HP.He-Aac.{Fr-Eng}.St{Fr-Eng}.Chaps].mkv
The first 3 lines indicates the group index in which a char in the
filename is located. So for instance, x264 is the group (0, 4, 1), and
it corresponds to a video codec, denoted by the letter\'v\' in the 4th line.
(for more info, see guess.matchtree.to_string)
Second, it tries to merge all this information into a single object
containing all the found properties, and does some (basic) conflict
resolution when they arise.
When you create the Matcher, you can pass it:
- a list \'opts\' of option names, that act as global flags
- a dict \'transfo_opts\' of { transfo_name: (transfo_args, transfo_kwargs) }
with which to call the transfo.process() function.'

def __init__(self, filename, filetype=u'autodetect', opts=None, transfo_opts=None):

    valid_filetypes = (u'autodetect', u'subtitle', u'info', u'video', u'movie', u'moviesubtitle', u'movieinfo', u'episode', u'episodesubtitle', u'episodeinfo')
    if (filetype not in valid_filetypes):
        raise ValueError((u'filetype    needs    to    be    one    of    %s' % valid_filetypes))
    if ((not PY3) and (not isinstance(filename, unicode))):
        log.warning(u'Given    filename    to    matcher    is    not    unicode...')
        filename = filename.decode(u'utf-8')
    filename = normalize_unicode(filename)
    if (opts is None):
        opts = []
    if (not isinstance(opts, list)):
        raise ValueError(u'opts    must    be    a    list    of    option    names!    Received:    type=%s    val=%s', type(opts), opts)
    if (transfo_opts is None):
        transfo_opts = {}
    if (not isinstance(transfo_opts, dict)):
        raise ValueError((u'transfo_opts    must    be    a    dict    of    {    transfo_name:    (args,    kwargs)    }.    ' + u'Received:    type=%s    val=%s'), type(transfo_opts), transfo_opts)
    self.match_tree = MatchTree(filename)
    if (clean_string(filename) == u''):
        return
    mtree = self.match_tree
    mtree.guess.set(u'type', filetype, confidence=1.0)
    def apply_transfo(transfo_name, *args, **kwargs):
        transfo = __import__((u'guessit.transfo.' + transfo_name), globals=globals(), locals=locals(), fromlist=[u'process'], level=0)
        (default_args, default_kwargs) = transfo_opts.get(transfo_name, ((), {}))
        all_args = (args or default_args)
        all_kwargs = dict(default_kwargs)
        all_kwargs.update(kwargs)
        transfo.process(mtree, *all_args, **all_kwargs)
    apply_transfo(u'split_path_components')
    apply_transfo(u'guess_filetype', filetype)
    if (mtree.guess[u'type'] == u'unknown'):
        return
    apply_transfo(u'split_explicit_groups')
    if (mtree.guess[u'type'] in (u'episode', u'episodesubtitle', u'episodeinfo')):
        strategy = [u'guess_date', u'guess_website', u'guess_release_group', u'guess_properties', u'guess_language', u'guess_video_rexps', u'guess_episodes_rexps', u'guess_weak_episodes_rexps']
    else:
        strategy = [u'guess_date', u'guess_website', u'guess_release_group', u'guess_properties', u'guess_language', u'guess_video_rexps']
    if (u'nolanguage' in opts):
        strategy.remove(u'guess_language')
    for name in strategy:
        apply_transfo(name)
    apply_transfo(u'guess_bonus_features')
    apply_transfo(u'guess_year', skip_first_year=(u'skip_first_year' in opts))
    if (u'nocountry' not in opts):
        apply_transfo(u'guess_country')
    apply_transfo(u'guess_idnumber')
    apply_transfo(u'split_on_dash')
    if (mtree.guess[u'type'] in (u'episode', u'episodesubtitle', u'episodeinfo')):
        apply_transfo(u'guess_episode_info_from_position')
    else:
        apply_transfo(u'guess_movie_title_from_position')
    apply_transfo(u'post_process')
    log.debug((u'Found    match    tree:\n%s' % u(mtree)))
