diff options
| author | Eevee (Alex Munroe) <eevee.git@veekun.com> | 2014-03-29 22:17:20 -0700 |
|---|---|---|
| committer | Eevee (Alex Munroe) <eevee.git@veekun.com> | 2014-03-29 22:17:20 -0700 |
| commit | 4a1b03a499dd07c37628f0bae8e36b9deaf1c7d4 (patch) | |
| tree | ff33111291f67ede32da4ab4ed3b1ff652336a0d | |
| parent | 5ba6063e623c8f6726479682bcdfd3f5923f33ee (diff) | |
| download | pyscss-4a1b03a499dd07c37628f0bae8e36b9deaf1c7d4.tar.gz | |
Write CSS out in the same encoding it claims to be.
| -rw-r--r-- | scss/__init__.py | 16 | ||||
| -rw-r--r-- | scss/cssdefs.py | 12 | ||||
| -rw-r--r-- | scss/tool.py | 27 |
3 files changed, 37 insertions, 18 deletions
diff --git a/scss/__init__.py b/scss/__init__.py index 24ac7d8..865e996 100644 --- a/scss/__init__.py +++ b/scss/__init__.py @@ -48,7 +48,6 @@ __license__ = LICENSE from collections import defaultdict import glob -import io from itertools import product import logging import warnings @@ -160,8 +159,8 @@ class SourceFile(object): @classmethod def from_file(cls, f, filename, **kwargs): - encoding = determine_encoding(f) contents = f.read() + encoding = determine_encoding(contents) if isinstance(contents, six.binary_type): contents = contents.decode(encoding) @@ -172,9 +171,9 @@ class SourceFile(object): if isinstance(string, six.text_type): # Already decoded; we don't know what encoding to use for output, # though, so still check for a @charset. - encoding = determine_encoding(io.StringIO(string)) + encoding = determine_encoding(string) elif isinstance(string, six.binary_type): - encoding = determine_encoding(io.BytesIO(string)) + encoding = determine_encoding(string) string = string.decode(encoding) else: raise TypeError("Expected a string, got {0!r}".format(string)) @@ -393,13 +392,17 @@ class Scss(object): #@profile #@print_timing(2) - def Compilation(self, scss_string=None, scss_file=None, super_selector=None, filename=None, is_sass=None, line_numbers=True): + def Compilation(self, scss_string=None, scss_file=None, source_files=None, super_selector=None, filename=None, is_sass=None, line_numbers=True): + # TODO this signature is totally wacky; it should just take a list of + # source files if super_selector: self.super_selector = super_selector + ' ' self.reset() source_file = None - if scss_string is not None: + if source_files is not None: + self.source_files = source_files + elif scss_string is not None: source_file = SourceFile.from_string(scss_string, filename, is_sass, line_numbers) elif scss_file is not None: source_file = SourceFile.from_filename(scss_file, filename, is_sass, line_numbers) @@ -1264,6 +1267,7 @@ class Scss(object): """ Implements @-blocks """ + # TODO handle @charset, probably? # Interpolate the current block # TODO this seems like it should be done in the block header. and more # generally? diff --git a/scss/cssdefs.py b/scss/cssdefs.py index 398a4cc..e312ca5 100644 --- a/scss/cssdefs.py +++ b/scss/cssdefs.py @@ -347,16 +347,12 @@ def is_builtin_css_function(name): # CSS character set determination # Based upon: http://www.w3.org/TR/CSS2/syndata.html#charset -def determine_encoding(f): - """Return the appropriate encoding for the given file, according to the CSS - charset rules. +def determine_encoding(buf): + """Return the appropriate encoding for the given CSS source, according to + the CSS charset rules. - `f` should be a file-like object with the cursor at the beginning. + `buf` may be either a string or bytes. """ - # 200 bytes should be enough for anyone - buf = f.read(200) - f.seek(0) - # The ultimate default is utf8; bravo, W3C bom_encoding = 'UTF-8' diff --git a/scss/tool.py b/scss/tool.py index d765c8f..6b15a37 100644 --- a/scss/tool.py +++ b/scss/tool.py @@ -163,19 +163,38 @@ def run_tests(): def do_build(options, args): if options.output is not None: - output = open(options.output, 'wt') + out = open(options.output, 'wb') else: - output = sys.stdout + out = sys.stdout + # Get the unencoded stream on Python 3 + out = getattr(out, 'buffer', out) css = Scss(scss_opts={ 'style': options.style, 'debug_info': options.debug_info, }) if args: + source_files = [ + SourceFile.from_filename(path, is_sass=options.is_sass) + for path in args + ] for path in args: - output.write(css.compile(scss_file=path, is_sass=options.is_sass)) + out.write(css.compile(scss_file=path, is_sass=options.is_sass)) else: - output.write(css.compile(sys.stdin.read(), is_sass=options.is_sass)) + source_files = [ + SourceFile.from_file(sys.stdin, "<stdin>", is_sass=options.is_sass)] + + encodings = set(source.encoding for source in source_files) + if len(encodings) > 1: + sys.stderr.write( + "Can't combine these files! " + "They have different encodings: {0}\n" + .format(', '.join(encodings)) + ) + sys.exit(3) + + output = css.compile(source_files=source_files) + out.write(output.encode(source_files[0].encoding)) for f, t in profiling.items(): sys.stderr.write("%s took %03fs" % (f, t)) |
