Python API

Legacy API

Warning

This API is still supported while the new API below is worked out, but it’s slated for deprecation and eventual removal. If you don’t need any of the features not yet available with the new API, consider porting as soon as possible.

Compiling files

Very basic usage is simple enough:

from scss import Scss
css = Scss()
css.compile("a { color: red + green; }")

Configuration

There are several configuration variables in the scss.config module that you may wish to change.

PROJECT_ROOT: Root of your entire project. Used only to construct defaults for other variables. Defaults to the root of the pyScss installation, which is probably not what you want.

LOAD_PATHS: An iterable of paths to search when using``@import``.

STATIC_ROOT: Used for finding sprite files. Defaults to $PROJECT_ROOT/static.

ASSETS_ROOT: Generated sprites are saved here. Defaults to $STATIC_ROOT/assets.

CACHE_ROOT: Used for storing cached sprite information. Defaults to ASSETS_ROOT.

STATIC_URL: URL equivalent to STATIC_ROOT. Defaults to static/.

ASSETS_URL: URL equivalent to ASSETS_ROOT. Defaults to static/assets/.

SPRTE_MAP_DIRECTION: Direction in which to arrange sprites in a spritesheet. Defaults to vertical; may be changed to horizontal, diagonal, or smart.

VERBOSITY: Increase spew from the compiler. Defaults to 1.

DEBUG: Set to true to make parse errors fatal. Defaults to false.

Django example

A rough example of using pyScss with Django:

import os
import fnmatch

import scss

from django.conf import settings
from django.utils.datastructures import SortedDict
from django.contrib.staticfiles import finders


def finder(glob):
    """
    Finds all files in the django finders for a given glob,
    returns the file path, if available, and the django storage object.
    storage objects must implement the File storage API:
    https://docs.djangoproject.com/en/dev/ref/files/storage/
    """
    for finder in finders.get_finders():
        for path, storage in finder.list([]):
            if fnmatch.fnmatchcase(path, glob):
                yield path, storage


# STATIC_ROOT is where pyScss looks for images and static data.
# STATIC_ROOT can be either a fully qualified path name or a "finder"
# iterable function that receives a filename or glob and returns a tuple
# of the file found and its file storage object for each matching file.
# (https://docs.djangoproject.com/en/dev/ref/files/storage/)
scss.config.STATIC_ROOT = finder
scss.config.STATIC_URL = settings.STATIC_URL

# ASSETS_ROOT is where the pyScss outputs the generated files such as spritemaps
# and compile cache:
scss.config.ASSETS_ROOT = os.path.join(settings.MEDIA_ROOT, 'assets/')
scss.config.ASSETS_URL = settings.MEDIA_URL + 'assets/'

# These are the paths pyScss will look ".scss" files on. This can be the path to
# the compass framework or blueprint or compass-recepies, etc.
scss.config.LOAD_PATHS = [
    '/usr/local/www/sass/frameworks/',
    '/Library/Ruby/Gems/1.8/gems/compass-0.11.5/frameworks/compass/stylesheets/',
    '/Library/Ruby/Gems/1.8/gems/compass-0.11.5/frameworks/blueprint/stylesheets/',
]

# This creates the Scss object used to compile SCSS code. In this example,
# _scss_vars will hold the context variables:
_scss_vars = {}
_scss = scss.Scss(
    scss_vars=_scss_vars,
    scss_opts={
        'compress': True,
        'debug_info': True,
    }
)

# 1. Compile from a string:
compiled_css_from_string = _scss.compile('@import "file2"; a {color: red + green; }')

# 2. Compile from a file:
compiled_css_from_file = _scss.compile(scss_file='file1.scss')

# 3. Compile from a set of files (use SortedDict or collections.OrderedDict to
# maintain the compile order):
_scss._scss_files = SortedDict((
    ('file2.scss', open('file2.scss').read()),
    ('file3.scss', open('file3.scss').read()),
    ('file4.scss', open('file4.scss').read()),
))
compiled_css_from_files = _scss.compile()

Note

The API here is likely to be improved in 1.3, to avoid the need for calling underscored functions.

New API

The simplest example:

from scss.compiler import compile_string

print(compile_string("a { color: red + green; }"))

scss.compiler.compile_string() is just a simple wrapper around the scss.compiler.Compiler class:

from scss.compiler import Compiler

compiler = Compiler()
print(compiler.compile_string("a { color: red + green; }"))

The most common arguments passed to Compiler are:

search_path
A list of paths to search for @imports. May be either strings or pathlib.Path objects.

Extending pyScss

A significant advantage to using pyScss is that you can inject Python values and code into the Sass compilation process.

Injecting values

You can define Sass values by creating and populating a scss.namespace.Namespace:

from scss.namespace import Namespace
from scss.types import String

namespace = Namespace()
namespace.set_variable('$base-url', String('http://localhost/'))
compiler = Compiler(namespace=namespace)
compiler.compile_string('div { background: url($base-url); }')

Now, $base-url will be available to the compiled Sass code, just like any other variable. Note that the value given must be one of the Sass types defined in scss.types.

Injecting functions

You can inject functions the same way:

def square(x):
    return x * x

namespace.set_function('square', 1, square)

This creates a function square for use in your Sass source. Optional arguments, keyword arguments, and slurpy arguments are all supported automatically. The arguments are Sass types, and the return value must be one as well.

The second argument is the arity — the number of required arguments, or None if any number of arguments is allowed. Sass functions can be overloaded by arity, so this is required. For functions with optional arguments, adding the same function multiple times can be tedious and error-prone, so the declare decorator is also available:

@namespace.declare
def square(x):
    return x * x

This will inspect the arguments for you and register the function with all arities it accepts. The function name is determined from the Python name: underscores become hyphens, and trailing underscores are removed. If you’d prefer to be more explicit, there’s also a declare_alias:

@namespace.declare_alias('square')
def square(x):
    return x * x

API reference

scss.compiler

class scss.compiler.Compiler(root=PosixPath('.'), search_path=(), namespace=None, extensions=(<class 'scss.extension.core.CoreExtension'>, ), import_static_css=False, output_style=u'nested', generate_source_map=False, live_errors=False, warn_unused_imports=False, ignore_parse_errors=False, loops_have_own_scopes=True, undefined_variables_fatal=True, super_selector=u'')[source]

A Sass compiler. Stores settings and knows how to fire off a compilation. Main entry point into compiling Sass.

call_and_catch_errors(f, *args, **kwargs)[source]

Call the given function with the given arguments. If it succeeds, return its return value. If it raises a scss.errors.SassError and live_errors is turned on, return CSS containing a traceback and error message.

scss.compiler.compile_file(filename, compiler_class=<class 'scss.compiler.Compiler'>, **kwargs)[source]

Compile a single file (provided as a pathlib.Path), and return a string of CSS.

Keyword arguments are passed along to the underlying Compiler.

Note that the search path is set to the file’s containing directory by default, unless you explicitly pass a search_path kwarg.

Parameters:filename (str, bytes, or pathlib.Path) – Path to the file to compile.
scss.compiler.compile_string(string, compiler_class=<class 'scss.compiler.Compiler'>, **kwargs)[source]

Compile a single string, and return a string of CSS.

Keyword arguments are passed along to the underlying Compiler.

class scss.compiler.Compilation(compiler)[source]

A single run of a compiler.

should_scope_loop_in_rule(rule)[source]

Return True iff a looping construct (@each, @for, @while, @if) should get its own scope, as is standard Sass behavior.

parse_selectors(raw_selectors)[source]

Parses out the old xCSS “foo extends bar” syntax.

Returns a 2-tuple: a set of selectors, and a set of extended selectors.

apply_extends(rules)[source]

Run through the given rules and translate all the pending @extends declarations into real selectors on parent rules.

The list is modified in-place and also sorted in dependency order.

create_css(rules)[source]

Generate the final CSS string

exception scss.compiler.SassReturn(retval)[source]

Special control-flow exception used to hop up the stack from a Sass function’s @return.

scss.namespace

Support for Sass’s namespacing rules.

class scss.namespace.Scope(maps=())[source]

Implements Sass variable scoping.

Similar to ChainMap, except that assigning a new value will replace an existing value, not mask it.

class scss.namespace.Namespace(variables=None, functions=None, mixins=None, mutable=True)[source]

...

derive()[source]

Return a new child namespace. All existing variables are still readable and writeable, but any new variables will only exist within a new scope.

declare(function)[source]

Insert a Python function into this Namespace, detecting its name and argument count automatically.

declare_alias(name)[source]

Insert a Python function into this Namespace with an explicitly-given name, but detect its argument count automatically.

scss.extension

Support for compiler extensions, which can affect the compile process and inject their own functions and values.

class scss.extension.Cache(prefix=None)[source]

Serves as a local memory cache storage for extensions usage.

class scss.extension.Extension[source]

An extension to the Sass compile process. Subclass to add your own behavior.

Methods are hooks, called by the compiler at certain points. Each extension is considered in the order it’s provided.

handle_import(name, compilation, rule)[source]

Attempt to resolve an import. Called once for every Sass string listed in an @import statement. Imports that Sass dictates should be converted to plain CSS imports do NOT trigger this hook.

So this:

@import url(foo), "bar", "baz";

would call handle_import twice: once with “bar”, once with “baz”.

Return a scss.source.SourceFile if you want to handle the import, or None if you don’t. (This method returns None by default, so if you don’t care about hooking imports, just don’t implement it.) This method is tried on every registered Extension in order, until one of them returns successfully.

A good example is the core Sass import machinery, which is implemented with this hook; see the source code of the core extension.

class scss.extension.NamespaceAdapterExtension(namespace)[source]

Trivial wrapper that adapts a bare scss.namespace.Namespace into a full extension.