@@ -272,42 +272,7 @@ static union Sass_Value* _unknown_type_to_sass_error(PyObject* value) {
272272 return retv;
273273}
274274
275- static union Sass_Value* _exception_to_sass_error () {
276- union Sass_Value* retv = NULL ;
277- PyObject* etype = NULL ;
278- PyObject* evalue = NULL ;
279- PyObject* etb = NULL ;
280- PyErr_Fetch (&etype, &evalue, &etb);
281- PyErr_NormalizeException (&etype, &evalue, &etb);
282- {
283- PyObject* traceback_mod = PyImport_ImportModule (" traceback" );
284- PyObject* traceback_parts = PyObject_CallMethod (
285- traceback_mod, " format_exception" , " OOO" , etype, evalue, etb
286- );
287- PyList_Insert (traceback_parts, 0 , PyUnicode_FromString (" \n " ));
288- PyObject* joinstr = PyUnicode_FromString (" " );
289- PyObject* result = PyUnicode_Join (joinstr, traceback_parts);
290- PyObject* bytes = PyUnicode_AsEncodedString (
291- result, " UTF-8" , " strict"
292- );
293- retv = sass_make_error (PySass_Bytes_AS_STRING (bytes));
294- Py_DECREF (traceback_mod);
295- Py_DECREF (traceback_parts);
296- Py_DECREF (joinstr);
297- Py_DECREF (result);
298- Py_DECREF (bytes);
299- }
300- Py_DECREF (etype);
301- Py_DECREF (evalue);
302- Py_DECREF (etb);
303- return retv;
304- }
305-
306275static PyObject* _exception_to_bytes () {
307- /* Grabs a Bytes instance for you to PySass_Bytes_AS_STRING.
308- Remember to Py_DECREF the object later!
309- TODO: This is a terrible violation of DRY, see above.
310- */
311276 PyObject* retv = NULL ;
312277 PyObject* etype = NULL ;
313278 PyObject* evalue = NULL ;
@@ -334,6 +299,22 @@ static PyObject* _exception_to_bytes() {
334299 return retv;
335300}
336301
302+ static union Sass_Value* _exception_to_sass_error () {
303+ PyObject* bytes = _exception_to_bytes ();
304+ union Sass_Value* retv = sass_make_error (PySass_Bytes_AS_STRING (bytes));
305+ Py_DECREF (bytes);
306+ return retv;
307+ }
308+
309+ static Sass_Import_List _exception_to_sass_import_error (const char * path) {
310+ PyObject* bytes = _exception_to_bytes ();
311+ Sass_Import_List import_list = sass_make_import_list (1 );
312+ import_list[0 ] = sass_make_import_entry (path, 0 , 0 );
313+ sass_import_set_error (import_list[0 ], PySass_Bytes_AS_STRING (bytes), 0 , 0 );
314+ Py_DECREF (bytes);
315+ return import_list;
316+ }
317+
337318static union Sass_Value* _to_sass_value (PyObject* value) {
338319 union Sass_Value* retv = NULL ;
339320 PyObject* types_mod = PyImport_ImportModule (" sass" );
@@ -435,74 +416,64 @@ static void _add_custom_functions(
435416 sass_option_set_c_functions (options, fn_list);
436417}
437418
438- Sass_Import_List _call_py_importer_f (
439- const char * path,
440- Sass_Importer_Entry cb,
441- struct Sass_Compiler * comp
419+ static Sass_Import_List _call_py_importer_f (
420+ const char * path, Sass_Importer_Entry cb, struct Sass_Compiler * comp
442421) {
443422 PyObject* pyfunc = (PyObject*)sass_importer_get_cookie (cb);
444- PyObject* py_path = PyUnicode_FromString (path);
445423 PyObject* py_result = NULL ;
446- PyObject *iterator;
447- PyObject *import_item;
448424 Sass_Import_List sass_imports = NULL ;
449425 Py_ssize_t i;
450426
451- py_result = PyObject_CallObject (pyfunc, PySass_IF_PY3 (" y" , " s" ), py_path);
452-
453- if (!py_result) {
454- sass_imports = sass_make_import_list (1 );
455- sass_imports[0 ] = sass_make_import_entry (path, 0 , 0 );
456-
457- PyObject* exc = _exception_to_bytes ();
458- char * err = PySass_Bytes_AS_STRING (exc);
427+ py_result = PyObject_CallFunction (pyfunc, PySass_IF_PY3 (" y" , " s" ), path);
459428
460- sass_import_set_error (sass_imports[0 ],
461- err,
462- 0 , 0 );
463-
464- Py_XDECREF (exc);
465- Py_XDECREF (py_result);
466- return sass_imports;
467- }
429+ /* Handle importer throwing an exception */
430+ if (!py_result) goto done;
468431
432+ /* Could return None indicating it could not handle the import */
469433 if (py_result == Py_None) {
470434 Py_XDECREF (py_result);
471- return 0 ;
435+ return NULL ;
472436 }
473437
474- sass_imports = sass_make_import_list ( PyList_Size (py_result));
475-
476- iterator = PyObject_GetIter ( py_result);
477- while (import_item = PyIter_Next (iterator) ) {
438+ /* Otherwise, we know our importer is well formed (because we wrap it)
439+ * The return value will be a tuple of 1, 2, or 3 tuples */
440+ sass_imports = sass_make_import_list ( PyTuple_GET_SIZE ( py_result) );
441+ for (i = 0 ; i < PyTuple_GET_SIZE (py_result); i += 1 ) {
478442 char * path_str = NULL ; /* XXX: Memory leak? */
479443 char * source_str = NULL ;
480444 char * sourcemap_str = NULL ;
481-
482- /* TODO: Switch statement and error handling for default case. Better way? */
483- if ( PyTuple_GET_SIZE (import_item) == 1 ) {
484- PyArg_ParseTuple (import_item, " es" ,
485- 0 , &path_str);
486- } else if ( PyTuple_GET_SIZE (import_item) == 2 ) {
487- PyArg_ParseTuple (import_item, " eses" ,
488- 0 , &path_str, 0 , &source_str);
489- } else if ( PyTuple_GET_SIZE (import_item) == 3 ) {
490- PyArg_ParseTuple (import_item, " eseses" ,
491- 0 , &path_str, 0 , &source_str, 0 , &sourcemap_str);
445+ PyObject* tup = PyTuple_GET_ITEM (py_result, i);
446+ Py_ssize_t size = PyTuple_GET_SIZE (tup);
447+
448+ if (size == 1 ) {
449+ PyArg_ParseTuple (tup, PySass_IF_PY3 (" y" , " s" ), &path_str);
450+ } else if (size == 2 ) {
451+ PyArg_ParseTuple (
452+ tup, PySass_IF_PY3 (" yy" , " ss" ), &path_str, &source_str
453+ );
454+ } else if (size == 3 ) {
455+ PyArg_ParseTuple (
456+ tup, PySass_IF_PY3 (" yyy" , " sss" ),
457+ &path_str, &source_str, &sourcemap_str
458+ );
492459 }
493460
494461 /* We need to give copies of these arguments; libsass handles
495- deallocation of them later, whereas path_str is left flapping
496- in the breeze -- it's treated const, so that's okay. */
497- if ( source_str ) source_str = strdup (source_str);
498- if ( sourcemap_str ) sourcemap_str = strdup (sourcemap_str);
462+ * deallocation of them later, whereas path_str is left flapping
463+ * in the breeze -- it's treated const, so that's okay. */
464+ if (source_str) source_str = strdup (source_str);
465+ if (sourcemap_str) sourcemap_str = strdup (sourcemap_str);
499466
500- sass_imports[i] = sass_make_import_entry (path_str, source_str, sourcemap_str);
467+ sass_imports[i] = sass_make_import_entry (
468+ path_str, source_str, sourcemap_str
469+ );
470+ }
501471
502- Py_XDECREF (import_item);
472+ done:
473+ if (sass_imports == NULL ) {
474+ sass_imports = _exception_to_sass_import_error (path);
503475 }
504476
505- Py_XDECREF (iterator);
506477 Py_XDECREF (py_result);
507478
508479 return sass_imports;
@@ -513,26 +484,25 @@ static void _add_custom_importers(
513484) {
514485 Py_ssize_t i;
515486 Sass_Importer_List importer_list;
516-
517- if ( custom_importers == Py_None ) {
487+
488+ if (custom_importers == Py_None) {
518489 return ;
519490 }
520-
521- importer_list = sass_make_importer_list (PyList_Size (custom_importers));
522-
523- for (i = 0 ; i < PyList_GET_SIZE (custom_importers); i += 1 ) {
524- PyObject* item = PyList_GET_ITEM (custom_importers, i);
491+
492+ importer_list = sass_make_importer_list (PyTuple_GET_SIZE (custom_importers));
493+
494+ for (i = 0 ; i < PyTuple_GET_SIZE (custom_importers); i += 1 ) {
495+ PyObject* item = PyTuple_GET_ITEM (custom_importers, i);
525496 int priority = 0 ;
526497 PyObject* import_function = NULL ;
527-
528- PyArg_ParseTuple (item, " iO" ,
529- &priority, &import_function);
530-
531- importer_list[i] = sass_make_importer (_call_py_importer_f,
532- priority,
533- import_function);
498+
499+ PyArg_ParseTuple (item, " iO" , &priority, &import_function);
500+
501+ importer_list[i] = sass_make_importer (
502+ _call_py_importer_f, priority, import_function
503+ );
534504 }
535-
505+
536506 sass_option_set_c_importers (options, importer_list);
537507}
538508
@@ -548,7 +518,7 @@ PySass_compile_string(PyObject *self, PyObject *args) {
548518 PyObject *custom_functions;
549519 PyObject *custom_importers;
550520 PyObject *result;
551-
521+
552522 if (!PyArg_ParseTuple (args,
553523 PySass_IF_PY3 (" yiiyiOiO" , " siisiOiO" ),
554524 &string, &output_style, &source_comments,
@@ -566,7 +536,6 @@ PySass_compile_string(PyObject *self, PyObject *args) {
566536 sass_option_set_is_indented_syntax_src (options, indented);
567537 _add_custom_functions (options, custom_functions);
568538 _add_custom_importers (options, custom_importers);
569-
570539 sass_compile_data_context (context);
571540
572541 ctx = sass_data_context_get_context (context);
@@ -578,7 +547,6 @@ PySass_compile_string(PyObject *self, PyObject *args) {
578547 (short int ) !error_status,
579548 error_status ? error_message : output_string
580549 );
581-
582550 sass_delete_data_context (context);
583551 return result;
584552}
@@ -594,7 +562,7 @@ PySass_compile_filename(PyObject *self, PyObject *args) {
594562 int source_comments, error_status, precision;
595563 PyObject *source_map_filename, *custom_functions, *custom_importers,
596564 *result;
597-
565+
598566 if (!PyArg_ParseTuple (args,
599567 PySass_IF_PY3 (" yiiyiOOO" , " siisiOOO" ),
600568 &filename, &output_style, &source_comments,
@@ -625,7 +593,6 @@ PySass_compile_filename(PyObject *self, PyObject *args) {
625593 sass_option_set_precision (options, precision);
626594 _add_custom_functions (options, custom_functions);
627595 _add_custom_importers (options, custom_importers);
628-
629596 sass_compile_file_context (context);
630597
631598 ctx = sass_file_context_get_context (context);
0 commit comments