/usr/lib/python3/dist-packages/sassutils/builder.py is in python3-libsass 0.11.0-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 | """:mod:`sassutils.builder` --- Build the whole directory
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
"""
from __future__ import with_statement
import collections
import io
import os
import os.path
import re
from six import string_types
from sass import compile
__all__ = 'SUFFIXES', 'SUFFIX_PATTERN', 'Manifest', 'build_directory'
#: (:class:`collections.Set`) The set of supported filename suffixes.
SUFFIXES = frozenset(['sass', 'scss'])
#: (:class:`re.RegexObject`) The regular expression pattern which matches to
#: filenames of supported :const:`SUFFIXES`.
SUFFIX_PATTERN = re.compile('[.](' + '|'.join(map(re.escape, SUFFIXES)) + ')$')
def build_directory(sass_path, css_path, output_style='nested',
_root_sass=None, _root_css=None):
"""Compiles all SASS/SCSS files in ``path`` to CSS.
:param sass_path: the path of the directory which contains source files
to compile
:type sass_path: :class:`str`, :class:`basestring`
:param css_path: the path of the directory compiled CSS files will go
:type css_path: :class:`str`, :class:`basestring`
:param output_style: an optional coding style of the compiled result.
choose one of: ``'nested'`` (default), ``'expanded'``,
``'compact'``, ``'compressed'``
:type output_style: :class:`str`
:returns: a dictionary of source filenames to compiled CSS filenames
:rtype: :class:`collections.Mapping`
.. versionadded:: 0.6.0
The ``output_style`` parameter.
"""
if _root_sass is None or _root_css is None:
_root_sass = sass_path
_root_css = css_path
result = {}
if not os.path.isdir(css_path):
os.mkdir(css_path)
for name in os.listdir(sass_path):
sass_fullname = os.path.join(sass_path, name)
if SUFFIX_PATTERN.search(name) and os.path.isfile(sass_fullname):
if name[0] == '_':
# Do not compile if it's partial
continue
css_fullname = os.path.join(css_path, name) + '.css'
css = compile(filename=sass_fullname,
output_style=output_style,
include_paths=[_root_sass])
with io.open(css_fullname, 'w', encoding='utf-8') as css_file:
css_file.write(css)
result[os.path.relpath(sass_fullname, _root_sass)] = \
os.path.relpath(css_fullname, _root_css)
elif os.path.isdir(sass_fullname):
css_fullname = os.path.join(css_path, name)
subresult = build_directory(sass_fullname, css_fullname,
output_style=output_style,
_root_sass=_root_sass,
_root_css=_root_css)
result.update(subresult)
return result
class Manifest(object):
"""Building manifest of SASS/SCSS.
:param sass_path: the path of the directory that contains SASS/SCSS
source files
:type sass_path: :class:`str`, :class:`basestring`
:param css_path: the path of the directory to store compiled CSS
files
:type css_path: :class:`str`, :class:`basestring`
"""
@classmethod
def normalize_manifests(cls, manifests):
if manifests is None:
manifests = {}
elif isinstance(manifests, collections.Mapping):
manifests = dict(manifests)
else:
raise TypeError('manifests must be a mapping object, not ' +
repr(manifests))
for package_name, manifest in manifests.items():
if not isinstance(package_name, string_types):
raise TypeError('manifest keys must be a string of package '
'name, not ' + repr(package_name))
if isinstance(manifest, Manifest):
continue
elif isinstance(manifest, tuple):
manifest = Manifest(*manifest)
elif isinstance(manifest, string_types):
manifest = Manifest(manifest)
else:
raise TypeError(
'manifest values must be a sassutils.builder.Manifest, '
'a pair of (sass_path, css_path), or a string of '
'sass_path, not ' + repr(manifest)
)
manifests[package_name] = manifest
return manifests
def __init__(self, sass_path, css_path=None, wsgi_path=None):
if not isinstance(sass_path, string_types):
raise TypeError('sass_path must be a string, not ' +
repr(sass_path))
if css_path is None:
css_path = sass_path
elif not isinstance(css_path, string_types):
raise TypeError('css_path must be a string, not ' +
repr(css_path))
if wsgi_path is None:
wsgi_path = css_path
elif not isinstance(wsgi_path, string_types):
raise TypeError('wsgi_path must be a string, not ' +
repr(wsgi_path))
self.sass_path = sass_path
self.css_path = css_path
self.wsgi_path = wsgi_path
def resolve_filename(self, package_dir, filename):
"""Gets a proper full relative path of SASS source and
CSS source that will be generated, according to ``package_dir``
and ``filename``.
:param package_dir: the path of package directory
:type package_dir: :class:`str`, :class:`basestring`
:param filename: the filename of SASS/SCSS source to compile
:type filename: :class:`str`, :class:`basestring`
:returns: a pair of (sass, css) path
:rtype: :class:`tuple`
"""
sass_path = os.path.join(package_dir, self.sass_path, filename)
css_filename = filename + '.css'
css_path = os.path.join(package_dir, self.css_path, css_filename)
return sass_path, css_path
def build(self, package_dir, output_style='nested'):
"""Builds the SASS/SCSS files in the specified :attr:`sass_path`.
It finds :attr:`sass_path` and locates :attr:`css_path`
as relative to the given ``package_dir``.
:param package_dir: the path of package directory
:type package_dir: :class:`str`, :class:`basestring`
:param output_style: an optional coding style of the compiled result.
choose one of: ``'nested'`` (default),
``'expanded'``, ``'compact'``, ``'compressed'``
:type output_style: :class:`str`
:returns: the set of compiled CSS filenames
:rtype: :class:`collections.Set`
.. versionadded:: 0.6.0
The ``output_style`` parameter.
"""
sass_path = os.path.join(package_dir, self.sass_path)
css_path = os.path.join(package_dir, self.css_path)
css_files = build_directory(
sass_path, css_path,
output_style=output_style
).values()
return frozenset(os.path.join(self.css_path, filename)
for filename in css_files)
def build_one(self, package_dir, filename, source_map=False):
"""Builds one SASS/SCSS file.
:param package_dir: the path of package directory
:type package_dir: :class:`str`, :class:`basestring`
:param filename: the filename of SASS/SCSS source to compile
:type filename: :class:`str`, :class:`basestring`
:param source_map: whether to use source maps. if :const:`True`
it also write a source map to a ``filename``
followed by :file:`.map` suffix.
default is :const:`False`
:type source_map: :class:`bool`
:returns: the filename of compiled CSS
:rtype: :class:`str`, :class:`basestring`
.. versionadded:: 0.4.0
Added optional ``source_map`` parameter.
"""
sass_filename, css_filename = self.resolve_filename(
package_dir, filename)
root_path = os.path.join(package_dir, self.sass_path)
css_path = os.path.join(package_dir, self.css_path, css_filename)
if source_map:
source_map_path = css_filename + '.map'
css, source_map = compile(
filename=sass_filename,
include_paths=[root_path],
source_map_filename=source_map_path # FIXME
)
else:
css = compile(filename=sass_filename, include_paths=[root_path])
source_map_path = None
source_map = None
css_folder = os.path.dirname(css_path)
if not os.path.exists(css_folder):
os.makedirs(css_folder)
with io.open(css_path, 'w', encoding='utf-8') as f:
f.write(css)
if source_map:
# Source maps are JSON, and JSON has to be UTF-8 encoded
with io.open(source_map_path, 'w', encoding='utf-8') as f:
f.write(source_map)
return css_filename
|