GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Pull Request — master (#47)
by
unknown
01:09
created

qtsass.api.compile_dirname()   A

Complexity

Conditions 4

Size

Total Lines 32
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 16
dl 0
loc 32
rs 9.6
c 0
b 0
f 0
cc 4
nop 3
1
# -*- coding: utf-8 -*-
2
# -----------------------------------------------------------------------------
3
# Copyright (c) 2015 Yann Lanthony
4
# Copyright (c) 2017-2018 Spyder Project Contributors
5
#
6
# Licensed under the terms of the MIT License
7
# (See LICENSE.txt for details)
8
# -----------------------------------------------------------------------------
9
"""qtsass - Compile SCSS files to valid Qt stylesheets."""
10
11
# yapf: disable
12
13
from __future__ import absolute_import, print_function
14
15
# Standard library imports
16
from collections import Mapping, Sequence
17
import logging
18
import os
19
20
# Third party imports
21
import sass
22
23
# Local imports
24
from qtsass.conformers import qt_conform, scss_conform
25
from qtsass.functions import qlineargradient, rgba
26
from qtsass.importers import qss_importer
27
28
29
# yapf: enable
30
31
# Constants
32
DEFAULT_CUSTOM_FUNCTIONS = {'qlineargradient': qlineargradient, 'rgba': rgba}
33
DEFAULT_SOURCE_COMMENTS = False
34
35
# Logger setup
36
_log = logging.getLogger(__name__)
37
38
39
def compile(string, **kwargs):
40
    """
41
    Conform and Compile QtSASS source code to CSS.
42
43
    This function conforms QtSASS to valid SCSS before passing it to
44
    sass.compile. Any keyword arguments you provide will be combined with
45
    qtsass's default keyword arguments and passed to sass.compile.
46
47
    .. code-block:: python
48
49
        >>> import qtsass
50
        >>> qtsass.compile("QWidget {background: rgb(0, 0, 0);}")
51
        QWidget {background:black;}
52
53
    :param string: QtSASS source code to conform and compile.
54
    :param kwargs: Keyword arguments to pass to sass.compile
55
    :returns: CSS string
56
    """
57
    kwargs.setdefault('source_comments', DEFAULT_SOURCE_COMMENTS)
58
    kwargs.setdefault('custom_functions', [])
59
    kwargs.setdefault('importers', [])
60
    kwargs.setdefault('include_paths', [])
61
62
    # Add QtSass importers
63
    if isinstance(kwargs['importers'], Sequence):
64
        kwargs['importers'] = (list(kwargs['importers']) +
65
                               [(0, qss_importer(*kwargs['include_paths']))])
66
    else:
67
        raise ValueError('Expected Sequence for importers '
68
                         'got {}'.format(type(kwargs['importers'])))
69
70
    # Add QtSass custom_functions
71
    if isinstance(kwargs['custom_functions'], Sequence):
72
        kwargs['custom_functions'] = dict(
73
            DEFAULT_CUSTOM_FUNCTIONS,
74
            **{fn.__name__: fn
75
               for fn in kwargs['custom_functions']})
76
    elif isinstance(kwargs['custom_functions'], Mapping):
77
        kwargs['custom_functions'].update(DEFAULT_CUSTOM_FUNCTIONS)
78
    else:
79
        raise ValueError('Expected Sequence or Mapping for custom_functions '
80
                         'got {}'.format(type(kwargs['custom_functions'])))
81
82
    # Conform QtSass source code
83
    try:
84
        kwargs['string'] = scss_conform(string)
85
    except Exception:
86
        _log.error('Failed to conform source code')
87
        raise
88
89
    if _log.isEnabledFor(logging.DEBUG):
90
        from pprint import pformat
91
        log_kwargs = dict(kwargs)
92
        log_kwargs['string'] = 'Conformed SCSS<...>'
93
        _log.debug('Calling sass.compile with:')
94
        _log.debug(pformat(log_kwargs))
95
        _log.debug('Conformed scss:\n{}'.format(kwargs['string']))
96
97
    # Compile QtSass source code
98
    try:
99
        return qt_conform(sass.compile(**kwargs))
100
    except sass.CompileError:
101
        _log.error('Failed to compile source code')
102
        raise
103
104
105
def compile_filename(input_file, output_file, **kwargs):
106
    """Compile and save QtSASS file as CSS.
107
108
    .. code-block:: python
109
110
        >>> import qtsass
111
        >>> qtsass.compile_filename("dummy.scss", "dummy.css")
112
113
    :param input_file: Path to QtSass file.
114
    :param output_file: Path to write Qt compliant CSS.
115
    :param kwargs: Keyword arguments to pass to sass.compile
116
    :returns: CSS string
117
    """
118
    input_root = os.path.abspath(os.path.dirname(input_file))
119
    kwargs.setdefault('include_paths', [input_root])
120
121
    with open(input_file, 'r') as f:
122
        string = f.read()
123
124
    _log.info('Compiling {}...'.format(os.path.normpath(input_file)))
125
    css = compile(string, **kwargs)
126
127
    output_root = os.path.abspath(os.path.dirname(output_file))
128
    if not os.path.isdir(output_root):
129
        os.makedirs(output_root)
130
131
    with open(output_file, 'w') as css_file:
132
        css_file.write(css)
133
        _log.info('Created CSS file {}'.format(os.path.normpath(output_file)))
134
135
    return css
136
137
138
def compile_dirname(input_dir, output_dir, **kwargs):
139
    """Compiles QtSASS files in a directory including subdirectories.
140
141
    .. code-block:: python
142
143
        >>> import qtsass
144
        >>> qtsass.compile_dirname("./scss", "./css")
145
146
    :param input_dir: Directory containing QtSass files.
147
    :param output_dir: Directory to write compiled Qt compliant CSS files to.
148
    :param kwargs: Keyword arguments to pass to sass.compile
149
    """
150
    kwargs.setdefault('include_paths', [input_dir])
151
152
    def is_valid(file_name):
153
        return not file_name.startswith('_') and file_name.endswith('.scss')
154
155
    for root, _, files in os.walk(input_dir):
156
        relative_root = os.path.relpath(root, input_dir)
157
        output_root = os.path.join(output_dir, relative_root)
158
        fkwargs = dict(kwargs)
159
        fkwargs['include_paths'] = fkwargs['include_paths'] + [root]
160
161
        for file_name in [f for f in files if is_valid(f)]:
162
            scss_path = os.path.join(root, file_name)
163
            css_file = os.path.splitext(file_name)[0] + '.css'
164
            css_path = os.path.join(output_root, css_file)
165
166
            if not os.path.isdir(output_root):
167
                os.makedirs(output_root)
168
169
            compile_filename(scss_path, css_path, **fkwargs)
170
171
172
def enable_logging(level=None, handler=None):
173
    """Enable logging for qtsass.
174
175
    Sets the qtsass logger's level to:
176
        1. the provided logging level
177
        2. logging.DEBUG if the QTSASS_DEBUG envvar is a True value
178
        3. logging.WARNING
179
180
    .. code-block:: python
181
        >>> import logging
182
        >>> import qtsass
183
        >>> handler = logging.StreamHandler()
184
        >>> formatter = logging.Formatter('%(level)-8s: %(name)s> %(message)s')
185
        >>> handler.setFormatter(formatter)
186
        >>> qtsass.enable_logging(level=logging.DEBUG, handler=handler)
187
188
    :param level: Optional logging level
189
    :param handler: Optional handler to add
190
    """
191
    if level is None:
192
        debug = os.environ.get('QTSASS_DEBUG', False)
193
        if debug in ('1', 'true', 'True', 'TRUE', 'on', 'On', 'ON'):
194
            level = logging.DEBUG
195
        else:
196
            level = logging.WARNING
197
198
    logger = logging.getLogger('qtsass')
199
    logger.setLevel(level)
200
    if handler:
201
        logger.addHandler(handler)
202
    _log.debug('logging level set to {}.'.format(level))
203
204
205
def watch(source, destination, compiler=None, Watcher=None):
206
    """
207
    Watches a source file or directory, compiling QtSass files when modified.
208
209
    The compiler function defaults to compile_filename when source is a file
210
    and compile_dirname when source is a directory.
211
212
    :param source: Path to source QtSass file or directory.
213
    :param destination: Path to output css file or directory.
214
    :param compiler: Compile function (optional)
215
    :param Watcher: Defaults to qtsass.watchers.Watcher (optional)
216
    :returns: qtsass.watchers.Watcher instance
217
    """
218
    if os.path.isfile(source):
219
        watch_dir = os.path.dirname(source)
220
        compiler = compiler or compile_filename
221
    elif os.path.isdir(source):
222
        watch_dir = source
223
        compiler = compiler or compile_dirname
224
    else:
225
        raise ValueError('source arg must be a dirname or filename...')
226
227
    if Watcher is None:
228
        from qtsass.watchers import Watcher
229
230
    watcher = Watcher(watch_dir, compiler, (source, destination))
231
    return watcher
232