File: pattern.py

package info (click to toggle)
osdlyrics 0.5.15%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 2,616 kB
  • sloc: ansic: 19,458; python: 4,867; sh: 572; makefile: 366; sed: 16
file content (170 lines) | stat: -rw-r--r-- 6,170 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# -*- coding: utf-8 -*-
#
# Copyright (C) 2011  Tiger Soldier
#
# This file is part of OSD Lyrics.
#
# OSD Lyrics is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# OSD Lyrics is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with OSD Lyrics.  If not, see <https://www.gnu.org/licenses/>.
#
import os.path
import urllib.parse
import urllib.request

from .errors import PatternException


def expand_file(pattern, metadata):
    """
    Expands the pattern to a file name according to the infomation of a music

    The following are supported place holder in the pattern:
    - %t: Title of the track. 'title' in metadata
    - %p: Performer (artist) of the music. 'artist' in metadata
    - %a: Album of the music. 'album' in metadata
    - %n: Track number of the music. 'tracknumber' in metadata
    - %f: Filename without extension of the music. 'location' in metadata.
    - %%: The `%' punctuation

    Arguments:
    - `pattern`: The pattern to expand.
    - `metadata`: A dict representing metadata. Useful keys are listed above.

    If the pattern cannot be expand, raise an PatternException. Otherwise
    return the expended pattern.

    >>> from osdlyrics.metadata import Metadata
    >>> from_dict = Metadata.from_dict
    >>> metadata = from_dict({'artist': 'Foo',
    ... 'title': 'Bar',
    ... 'tracknumber': '1',
    ... 'album': 'Album',
    ... 'location': 'file:///%E6%AD%8C%E6%9B%B2/%E7%9A%84/%E5%9C%B0%E5%9D%80.mp3'})
    >>> expand_file('%p - %t', metadata)
    'Foo - Bar'
    >>> expand_file('foobar', metadata)
    'foobar'
    >>> print(expand_file('name is %f :)', metadata))
    name is 地址 :)
    >>> expand_file('%something else', metadata)
    '%something else'
    >>> expand_file('%%a - %%t', metadata)
    '%a - %t'
    >>> expand_file('%%%', metadata)
    '%%'
    >>> expand_file('%n - %a:%p,%t', metadata)
    '1 - Album:Foo,Bar'
    >>> expand_file('%t', from_dict({}))
    Traceback (most recent call last):
        ...
    osdlyrics.errors.PatternException: title not in metadata
    """
    keys = {'t': 'title',
            'p': 'artist',
            'a': 'album',
            'n': 'tracknum',
            }
    start = 0
    parts = []
    while start < len(pattern):
        end = pattern.find('%', start)
        if end > -1:
            parts.append(pattern[start:end])
            has_tag = False
            if end + 1 < len(pattern):
                tag = pattern[end + 1]
                if tag == '%':
                    has_tag = True
                    parts.append('%')
                elif tag == 'f':
                    location = metadata.location
                    if not location:
                        raise PatternException('Location not found in metadata')
                    uri = urllib.parse.urlparse(location)
                    if uri.scheme == '':
                        path = uri.path
                    elif uri.scheme == 'file':
                        path = urllib.request.url2pathname(uri.path)
                    else:
                        raise PatternException('Unsupported file scheme %s' % uri.scheme)
                    basename = os.path.basename(path)
                    root, ext = os.path.splitext(basename)
                    has_tag = True
                    parts.append(root)
                elif tag in keys:
                    value = getattr(metadata, keys[tag])
                    if not value:
                        raise PatternException('%s not in metadata' % keys[tag])
                    if not isinstance(value, str):
                        value = str(value)
                    has_tag = True
                    parts.append(value.replace('/', '_'))
            if has_tag:
                start = end + 2
            else:
                start = end + 1
                parts.append('%')
        else:
            parts.append(pattern[start:])
            break
    return ''.join(parts)


def expand_path(pattern, metadata):
    """
    Expands the pattern to a directory path according to the infomation of a music

    The pattern can be one of the three forms:
    - begin with `/': the path is an absolute path and will not be expanded
    - begin with `~/': the path is an relative path and the `~' wiil be expanded to
      the absolute path of the user's home directory
    - `%': the path will be expanded to the directory of the music file according to
      its URI. ``location`` attribute is used in metadata

    Arguments:
    - `pattern`: The pattern to expand.
    - `metadata`: A dict representing metadata. Useful keys are listed above.

    If the pattern cannot be expand, raise an PatternException. Otherwise
    return the expended pattern.


    >>> from osdlyrics.metadata import Metadata
    >>> from_dict = Metadata.from_dict
    >>> expand_path('%', from_dict({'location': 'file:///tmp/a.lrc'}))
    '/tmp'
    >>> expand_path('/bar', from_dict({}))
    '/bar'
    >>> expand_path('%', from_dict({'Title': 'hello'}))
    Traceback (most recent call last):
        ...
    osdlyrics.errors.PatternException: Location not found in metadata
    """
    if pattern == '%':
        location = metadata.location
        if not location:
            raise PatternException('Location not found in metadata')
        uri = urllib.parse.urlparse(location)
        if uri.scheme != 'file':
            raise PatternException('Unsupported scheme: %s' % uri.scheme)
        path = urllib.request.url2pathname(uri.path)
        return os.path.dirname(path)
    path = os.path.expanduser(pattern)
    if not os.path.isabs(path):
        raise PatternException('Path is not absolute: %s' % path)
    return path


if __name__ == '__main__':
    import doctest
    doctest.testmod()