Skip to content

Commit 2b3361d

Browse files
authored
Merge pull request #246 from samuelcolvin/custom_import_extensions
support custom import extension
2 parents b0a6e51 + a1f146b commit 2b3361d

File tree

4 files changed

+108
-11
lines changed

4 files changed

+108
-11
lines changed

pysass.cpp

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,17 @@ static void _add_custom_importers(
505505
sass_option_set_c_importers(options, importer_list);
506506
}
507507

508+
static void _add_custom_import_extensions(
509+
struct Sass_Options* options, PyObject* custom_import_extensions
510+
) {
511+
Py_ssize_t i;
512+
513+
for (i = 0; i < PyList_GET_SIZE(custom_import_extensions); i += 1) {
514+
PyObject* ext = PyList_GET_ITEM(custom_import_extensions, i);
515+
sass_option_push_import_extension(options, PyBytes_AS_STRING(ext));
516+
}
517+
}
518+
508519
static PyObject *
509520
PySass_compile_string(PyObject *self, PyObject *args) {
510521
struct Sass_Context *ctx;
@@ -516,13 +527,15 @@ PySass_compile_string(PyObject *self, PyObject *args) {
516527
int source_comments, error_status, precision, indented;
517528
PyObject *custom_functions;
518529
PyObject *custom_importers;
530+
PyObject *custom_import_extensions;
519531
PyObject *result;
520532

521533
if (!PyArg_ParseTuple(args,
522-
PySass_IF_PY3("yiiyiOiO", "siisiOiO"),
534+
PySass_IF_PY3("yiiyiOiOO", "siisiOiOO"),
523535
&string, &output_style, &source_comments,
524536
&include_paths, &precision,
525-
&custom_functions, &indented, &custom_importers)) {
537+
&custom_functions, &indented, &custom_importers,
538+
&custom_import_extensions)) {
526539
return NULL;
527540
}
528541

@@ -535,6 +548,7 @@ PySass_compile_string(PyObject *self, PyObject *args) {
535548
sass_option_set_is_indented_syntax_src(options, indented);
536549
_add_custom_functions(options, custom_functions);
537550
_add_custom_importers(options, custom_importers);
551+
_add_custom_import_extensions(options, custom_import_extensions);
538552
sass_compile_data_context(context);
539553

540554
ctx = sass_data_context_get_context(context);
@@ -560,14 +574,15 @@ PySass_compile_filename(PyObject *self, PyObject *args) {
560574
Sass_Output_Style output_style;
561575
int source_comments, error_status, precision;
562576
PyObject *source_map_filename, *custom_functions, *custom_importers,
563-
*result, *output_filename_hint;
577+
*result, *output_filename_hint, *custom_import_extensions;
564578

565579
if (!PyArg_ParseTuple(args,
566-
PySass_IF_PY3("yiiyiOOOO", "siisiOOOO"),
580+
PySass_IF_PY3("yiiyiOOOOO", "siisiOOOOO"),
567581
&filename, &output_style, &source_comments,
568582
&include_paths, &precision,
569583
&source_map_filename, &custom_functions,
570-
&custom_importers, &output_filename_hint)) {
584+
&custom_importers, &output_filename_hint,
585+
&custom_import_extensions)) {
571586
return NULL;
572587
}
573588

@@ -594,6 +609,7 @@ PySass_compile_filename(PyObject *self, PyObject *args) {
594609
sass_option_set_precision(options, precision);
595610
_add_custom_functions(options, custom_functions);
596611
_add_custom_importers(options, custom_importers);
612+
_add_custom_import_extensions(options, custom_import_extensions);
597613
sass_compile_file_context(context);
598614

599615
ctx = sass_file_context_get_context(context);

sass.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ def _raise(e):
222222

223223
def compile_dirname(
224224
search_path, output_path, output_style, source_comments, include_paths,
225-
precision, custom_functions, importers
225+
precision, custom_functions, importers, custom_import_extensions
226226
):
227227
fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
228228
for dirpath, _, filenames in os.walk(search_path, onerror=_raise):
@@ -240,6 +240,7 @@ def compile_dirname(
240240
s, v, _ = _sass.compile_filename(
241241
input_filename, output_style, source_comments, include_paths,
242242
precision, None, custom_functions, importers, None,
243+
custom_import_extensions,
243244
)
244245
if s:
245246
v = v.decode('UTF-8')
@@ -292,6 +293,9 @@ def compile(**kwargs):
292293
:type custom_functions: :class:`set`,
293294
:class:`collections.abc.Sequence`,
294295
:class:`collections.abc.Mapping`
296+
:param custom_import_extensions: optional extra file extensions which
297+
allow can be imported, eg. ``['.css']``
298+
:type custom_import_extensions: :class:`list`, :class:`tuple`
295299
:param indented: optional declaration that the string is Sass, not SCSS
296300
formatted. :const:`False` by default
297301
:type indented: :class:`bool`
@@ -332,6 +336,9 @@ def compile(**kwargs):
332336
:type custom_functions: :class:`set`,
333337
:class:`collections.abc.Sequence`,
334338
:class:`collections.abc.Mapping`
339+
:param custom_import_extensions: optional extra file extensions which
340+
allow can be imported, eg. ``['.css']``
341+
:type custom_import_extensions: :class:`list`, :class:`tuple`
335342
:param importers: optional callback functions.
336343
see also below `importer callbacks
337344
<importer-callbacks_>`_ description
@@ -374,6 +381,9 @@ def compile(**kwargs):
374381
:type custom_functions: :class:`set`,
375382
:class:`collections.abc.Sequence`,
376383
:class:`collections.abc.Mapping`
384+
:param custom_import_extensions: optional extra file extensions which
385+
allow can be imported, eg. ``['.css']``
386+
:type custom_import_extensions: :class:`list`, :class:`tuple`
377387
:raises sass.CompileError: when it fails for any reason
378388
(for example the given Sass has broken syntax)
379389
@@ -584,6 +594,14 @@ def _get_file_arg(key):
584594
'not {1!r}'.format(SassFunction, custom_functions)
585595
)
586596

597+
_custom_exts = kwargs.pop('custom_import_extensions', []) or []
598+
if not isinstance(_custom_exts, (list, tuple)):
599+
raise TypeError(
600+
'custom_import_extensions must be a list of strings '
601+
'not {}'.format(type(_custom_exts))
602+
)
603+
custom_import_extensions = [ext.encode('utf-8') for ext in _custom_exts]
604+
587605
importers = _validate_importers(kwargs.pop('importers', None))
588606

589607
if 'string' in modes:
@@ -597,7 +615,7 @@ def _get_file_arg(key):
597615
_check_no_remaining_kwargs(compile, kwargs)
598616
s, v = _sass.compile_string(
599617
string, output_style, source_comments, include_paths, precision,
600-
custom_functions, indented, importers,
618+
custom_functions, indented, importers, custom_import_extensions,
601619
)
602620
if s:
603621
return v.decode('utf-8')
@@ -613,7 +631,7 @@ def _get_file_arg(key):
613631
s, v, source_map = _sass.compile_filename(
614632
filename, output_style, source_comments, include_paths, precision,
615633
source_map_filename, custom_functions, importers,
616-
output_filename_hint,
634+
output_filename_hint, custom_import_extensions,
617635
)
618636
if s:
619637
v = v.decode('utf-8')
@@ -631,6 +649,7 @@ def _get_file_arg(key):
631649
s, v = compile_dirname(
632650
search_path, output_path, output_style, source_comments,
633651
include_paths, precision, custom_functions, importers,
652+
custom_import_extensions
634653
)
635654
if s:
636655
return

sassc.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ def main(argv=sys.argv, stdout=sys.stdout, stderr=sys.stderr):
9191
'(output css filename).')
9292
parser.add_option('-I', '--include-path', metavar='DIR',
9393
dest='include_paths', action='append',
94-
help='Path to find "@import"ed (S)CSS source files. '
94+
help='Path to find "@import"ed (S)CSS source files. '
9595
'Can be multiply used.')
9696
parser.add_option(
9797
'-p', '--precision', action='store', type='int', default=5,
@@ -101,6 +101,10 @@ def main(argv=sys.argv, stdout=sys.stdout, stderr=sys.stderr):
101101
'--source-comments', action='store_true', default=False,
102102
help='Include debug info in output',
103103
)
104+
parser.add_option('--import-extensions',
105+
dest='custom_import_extensions', action='append',
106+
help='Extra extensions allowed for sass imports. '
107+
'Can be multiply used.')
104108
options, args = parser.parse_args(argv[1:])
105109
error = functools.partial(print,
106110
parser.get_prog_name() + ': error:',
@@ -130,7 +134,8 @@ def main(argv=sys.argv, stdout=sys.stdout, stderr=sys.stderr):
130134
source_map_filename=source_map_filename,
131135
output_filename_hint=args[1],
132136
include_paths=options.include_paths,
133-
precision=options.precision
137+
precision=options.precision,
138+
custom_import_extensions=options.custom_import_extensions,
134139
)
135140
else:
136141
source_map_filename = None
@@ -140,7 +145,8 @@ def main(argv=sys.argv, stdout=sys.stdout, stderr=sys.stderr):
140145
output_style=options.style,
141146
source_comments=options.source_comments,
142147
include_paths=options.include_paths,
143-
precision=options.precision
148+
precision=options.precision,
149+
custom_import_extensions=options.custom_import_extensions,
144150
)
145151
except (IOError, OSError) as e:
146152
error(e)

sasstests.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1409,3 +1409,59 @@ def test_imports_from_cwd(tmpdir):
14091409
with tmpdir.as_cwd():
14101410
out = sass.compile(filename=main_scss.strpath)
14111411
assert out == ''
1412+
1413+
1414+
def test_import_no_css(tmpdir):
1415+
tmpdir.join('other.css').write('body {color: green}')
1416+
main_scss = tmpdir.join('main.scss')
1417+
main_scss.write("@import 'other';")
1418+
with pytest.raises(sass.CompileError):
1419+
sass.compile(filename=main_scss.strpath)
1420+
1421+
1422+
@pytest.mark.parametrize('exts', [
1423+
('.css',),
1424+
['.css'],
1425+
['.foobar', '.css'],
1426+
])
1427+
def test_import_css(exts, tmpdir):
1428+
tmpdir.join('other.css').write('body {color: green}')
1429+
main_scss = tmpdir.join('main.scss')
1430+
main_scss.write("@import 'other';")
1431+
out = sass.compile(
1432+
filename=main_scss.strpath,
1433+
custom_import_extensions=exts,
1434+
)
1435+
assert out == 'body {\n color: green; }\n'
1436+
1437+
1438+
def test_import_css_error(tmpdir):
1439+
tmpdir.join('other.css').write('body {color: green}')
1440+
main_scss = tmpdir.join('main.scss')
1441+
main_scss.write("@import 'other';")
1442+
with pytest.raises(TypeError):
1443+
sass.compile(
1444+
filename=main_scss.strpath,
1445+
custom_import_extensions='.css',
1446+
)
1447+
1448+
1449+
def test_import_css_string(tmpdir):
1450+
tmpdir.join('other.css').write('body {color: green}')
1451+
with tmpdir.as_cwd():
1452+
out = sass.compile(
1453+
string="@import 'other';",
1454+
custom_import_extensions=['.css'],
1455+
)
1456+
assert out == 'body {\n color: green; }\n'
1457+
1458+
1459+
def test_import_ext_other(tmpdir):
1460+
tmpdir.join('other.foobar').write('body {color: green}')
1461+
main_scss = tmpdir.join('main.scss')
1462+
main_scss.write("@import 'other';")
1463+
out = sass.compile(
1464+
filename=main_scss.strpath,
1465+
custom_import_extensions=['.foobar'],
1466+
)
1467+
assert out == 'body {\n color: green; }\n'

0 commit comments

Comments
 (0)