Skip to content

Commit 738fe84

Browse files
committed
add support for passing previous file to importer callback
1 parent bf336dd commit 738fe84

File tree

3 files changed

+44
-6
lines changed

3 files changed

+44
-6
lines changed

pysass.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -423,9 +423,14 @@ static Sass_Import_List _call_py_importer_f(
423423
PyObject* pyfunc = (PyObject*)sass_importer_get_cookie(cb);
424424
PyObject* py_result = NULL;
425425
Sass_Import_List sass_imports = NULL;
426+
struct Sass_Import* previous;
427+
const char* prev_path;
426428
Py_ssize_t i;
427429

428-
py_result = PyObject_CallFunction(pyfunc, PySass_IF_PY3("y", "s"), path);
430+
previous = sass_compiler_get_last_import(comp);
431+
prev_path = sass_import_get_abs_path(previous);
432+
433+
py_result = PyObject_CallFunction(pyfunc, PySass_IF_PY3("yy", "ss"), path, prev_path);
429434

430435
/* Handle importer throwing an exception */
431436
if (!py_result) goto done;

sass.py

+21-5
Original file line numberDiff line numberDiff line change
@@ -195,9 +195,19 @@ def _to_bytes(obj):
195195

196196

197197
def _importer_callback_wrapper(func):
198+
if PY2:
199+
argspec = inspect.getargspec(func)
200+
else:
201+
argspec = inspect.getfullargspec(func)
202+
203+
num_args = len(argspec.args)
204+
198205
@functools.wraps(func)
199-
def inner(path):
200-
ret = func(path.decode('UTF-8'))
206+
def inner(path, prev):
207+
if num_args == 2:
208+
ret = func(path.decode('UTF-8'), prev.decode('UTF-8'))
209+
else:
210+
ret = func(path.decode('UTF-8'))
201211
return _normalize_importer_return_value(ret)
202212
return inner
203213

@@ -477,8 +487,10 @@ def func_name(a, b):
477487
A priority of zero is acceptable; priority determines the order callbacks
478488
are attempted.
479489
480-
These callbacks must accept a single string argument representing the path
481-
passed to the ``@import`` directive, and either return ``None`` to
490+
These callbacks can accept one or two string arguments. The first argument
491+
is the path that was passed to the ``@import`` directive; the second
492+
(optional) argument is the previous resolved path, where the ``@import``
493+
directive was found. The callbacks must either return ``None`` to
482494
indicate the path wasn't handled by that callback (to continue with others
483495
or fall back on internal ``libsass`` filesystem behaviour) or a list of
484496
one or more tuples, each in one of three forms:
@@ -494,7 +506,7 @@ def func_name(a, b):
494506
495507
.. code-block:: python
496508
497-
def my_importer(path):
509+
def my_importer(path, prev):
498510
return [(path, '#' + path + ' { color: red; }')]
499511
500512
sass.compile(
@@ -530,6 +542,10 @@ def my_importer(path):
530542
Added ``source_map_contents``, ``source_map_embed``,
531543
``omit_source_map_url``, and ``source_map_root`` parameters.
532544
545+
.. versionadded:: 0.18.0
546+
The importer callbacks can now take a second argument, the previously-
547+
resolved path, so that importers can do relative path resolution.
548+
533549
"""
534550
modes = set()
535551
for mode_name in MODES:

sasstests.py

+17
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,23 @@ def importer_returning_one_argument(path):
341341
)
342342
assert ret == 'b i{font-size:20px}.foo-one-arg{color:blue}\n'
343343

344+
def test_importer_prev_path(self):
345+
def importer(path, prev):
346+
assert path in ('a', 'b')
347+
if path == 'a':
348+
assert prev == 'stdin'
349+
return ((path, '@import "b";'),)
350+
elif path == 'b':
351+
assert prev == 'a'
352+
return ((path, 'a { color: red; }'),)
353+
354+
ret = sass.compile(
355+
string='@import "a";',
356+
importers=((0, importer),),
357+
output_style='compressed',
358+
)
359+
assert ret == 'a{color:red}\n'
360+
344361
def test_importer_does_not_handle_returns_None(self):
345362
def importer_one(path):
346363
if path == 'one':

0 commit comments

Comments
 (0)