From 0aa67c67faaaf4c9531b0440706673d0a859f39b Mon Sep 17 00:00:00 2001 From: Anthony Sottile Date: Thu, 10 Dec 2015 11:05:38 -0800 Subject: [PATCH] Disallow arbitrary kwargs in compile() --- sass.py | 15 ++++++++++++++- sasstests.py | 34 +++++++++++++++++++++++++++++----- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/sass.py b/sass.py index bf2498fd..b98a4b34 100644 --- a/sass.py +++ b/sass.py @@ -176,6 +176,16 @@ def compile_dirname( return True, None +def _check_no_remaining_kwargs(func, kwargs): + if kwargs: + raise TypeError( + '{0}() got unexpected keyword argument(s) {1}'.format( + func.__name__, + ', '.join("'{0}'".format(arg) for arg in sorted(kwargs)), + ) + ) + + def compile(**kwargs): """There are three modes of parameters :func:`compile()` can take: ``string``, ``filename``, and ``dirname``. @@ -456,9 +466,10 @@ def func_name(a, b): if not isinstance(indented, bool): raise TypeError('indented must be bool, not ' + repr(source_comments)) + _check_no_remaining_kwargs(compile, kwargs) s, v = compile_string( string, output_style, source_comments, include_paths, precision, - custom_functions, indented + custom_functions, indented, ) if s: return v.decode('utf-8') @@ -470,6 +481,7 @@ def func_name(a, b): raise IOError('{0!r} seems not a file'.format(filename)) elif isinstance(filename, text_type): filename = filename.encode(fs_encoding) + _check_no_remaining_kwargs(compile, kwargs) s, v, source_map = compile_filename( filename, output_style, source_comments, include_paths, precision, source_map_filename, custom_functions, @@ -515,6 +527,7 @@ def func_name(a, b): except ValueError: raise ValueError('dirname must be a pair of (source_dir, ' 'output_dir)') + _check_no_remaining_kwargs(compile, kwargs) s, v = compile_dirname( search_path, output_path, output_style, source_comments, include_paths, precision, custom_functions, diff --git a/sasstests.py b/sasstests.py index 3829e618..c16402e0 100644 --- a/sasstests.py +++ b/sasstests.py @@ -224,6 +224,19 @@ def test_compile_invalid_source_comments(self): string='a { color: blue; }', source_comments='invalid') + def test_compile_disallows_arbitrary_arguments(self): + for args in ( + {'string': 'a{b:c}'}, + {'filename': 'test/a.scss'}, + {'dirname': ('test', '/dev/null')}, + ): + with assert_raises(TypeError) as excinfo: + sass.compile(herp='derp', harp='darp', **args) + msg, = excinfo.value.args + assert msg == ( + "compile() got unexpected keyword argument(s) 'harp', 'herp'" + ) + def test_compile_string(self): actual = sass.compile(string='a { b { color: blue; } }') assert actual == 'a b {\n color: blue; }\n' @@ -1023,13 +1036,24 @@ def compile_with_func(s): @contextlib.contextmanager -def assert_raises_compile_error(expected): +def assert_raises(exctype): + # I want pytest.raises, this'll have to do for now + class C: + pass + try: - yield + yield C assert False, 'Expected to raise!' - except sass.CompileError as e: - msg, = e.args - assert msg.decode('UTF-8') == expected, (msg, expected) + except exctype as e: + C.value = e + + +@contextlib.contextmanager +def assert_raises_compile_error(expected): + with assert_raises(sass.CompileError) as excinfo: + yield + msg, = excinfo.value.args + assert msg.decode('UTF-8') == expected, (msg, expected) class RegexMatcher(object):