Skip to content

Commit 6340119

Browse files
authored
Merge pull request #265 from asottile/fix_collections_abc_warnings
Import abc classes from collections.abc in PY3+
2 parents fd6ed94 + 2e11265 commit 6340119

File tree

7 files changed

+36
-15
lines changed

7 files changed

+36
-15
lines changed

pysass.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44
#if PY_MAJOR_VERSION >= 3
55
#define PySass_IF_PY3(three, two) (three)
66
#define PySass_Object_Bytes(o) PyUnicode_AsUTF8String(PyObject_Str(o))
7+
#define COLLECTIONS_ABC_MOD "collections.abc"
78
#else
89
#define PySass_IF_PY3(three, two) (two)
910
#define PySass_Object_Bytes(o) PyObject_Str(o)
11+
#define COLLECTIONS_ABC_MOD "collections"
1012
#endif
1113

1214
#ifdef __cplusplus
@@ -322,7 +324,7 @@ static union Sass_Value* _to_sass_value(PyObject* value) {
322324
PyObject* sass_list_t = PyObject_GetAttrString(types_mod, "SassList");
323325
PyObject* sass_warning_t = PyObject_GetAttrString(types_mod, "SassWarning");
324326
PyObject* sass_error_t = PyObject_GetAttrString(types_mod, "SassError");
325-
PyObject* collections_mod = PyImport_ImportModule("collections");
327+
PyObject* collections_mod = PyImport_ImportModule(COLLECTIONS_ABC_MOD);
326328
PyObject* mapping_t = PyObject_GetAttrString(collections_mod, "Mapping");
327329

328330
if (value == Py_None) {

sass.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from six import string_types, text_type, PY2, PY3
2626

2727
import _sass
28+
from sassutils._compat import collections_abc
2829

2930
__all__ = (
3031
'MODES', 'OUTPUT_STYLES', 'SOURCE_COMMENTS', 'CompileError', 'SassColor',
@@ -144,7 +145,7 @@ def from_named_function(cls, function):
144145
def __init__(self, name, arguments, callable_):
145146
if not isinstance(name, string_types):
146147
raise TypeError('name must be a string, not ' + repr(name))
147-
elif not isinstance(arguments, collections.Sequence):
148+
elif not isinstance(arguments, collections_abc.Sequence):
148149
raise TypeError('arguments must be a sequence, not ' +
149150
repr(arguments))
150151
elif not callable(callable_):
@@ -582,12 +583,15 @@ def _get_file_arg(key):
582583
include_paths = include_paths.encode(fs_encoding)
583584

584585
custom_functions = kwargs.pop('custom_functions', ())
585-
if isinstance(custom_functions, collections.Mapping):
586+
if isinstance(custom_functions, collections_abc.Mapping):
586587
custom_functions = [
587588
SassFunction.from_lambda(name, lambda_)
588589
for name, lambda_ in custom_functions.items()
589590
]
590-
elif isinstance(custom_functions, (collections.Set, collections.Sequence)):
591+
elif isinstance(
592+
custom_functions,
593+
(collections_abc.Set, collections_abc.Sequence),
594+
):
591595
custom_functions = [
592596
func if isinstance(func, SassFunction)
593597
else SassFunction.from_named_function(func)
@@ -758,7 +762,7 @@ def __new__(cls, msg):
758762
return super(SassWarning, cls).__new__(cls, msg)
759763

760764

761-
class SassMap(collections.Mapping):
765+
class SassMap(collections_abc.Mapping):
762766
"""Because sass maps can have mapping types as keys, we need an immutable
763767
hashable mapping type.
764768

sasstests.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# -*- coding: utf-8 -*-
22
from __future__ import with_statement
33

4-
import collections
54
import contextlib
65
import glob
76
import json
@@ -25,6 +24,7 @@
2524
import pysassc
2625
import sass
2726
import sassc
27+
from sassutils._compat import collections_abc
2828
from sassutils.builder import Manifest, build_directory
2929
from sassutils.wsgi import SassMiddleware
3030

@@ -127,6 +127,12 @@ def normalize_path(path):
127127
'''
128128

129129

130+
@pytest.fixture(autouse=True)
131+
def no_warnings(recwarn):
132+
yield
133+
assert len(recwarn) == 0
134+
135+
130136
class BaseTestCase(unittest.TestCase):
131137

132138
def assert_source_map_equal(self, expected, actual):
@@ -153,7 +159,7 @@ def test_version(self):
153159
assert re.match(r'^\d+\.\d+\.\d+$', sass.__version__)
154160

155161
def test_output_styles(self):
156-
assert isinstance(sass.OUTPUT_STYLES, collections.Mapping)
162+
assert isinstance(sass.OUTPUT_STYLES, collections_abc.Mapping)
157163
assert 'nested' in sass.OUTPUT_STYLES
158164

159165
def test_and_join(self):
@@ -926,8 +932,10 @@ def test_successful(self):
926932
assert os.path.exists(os.path.join(output_dir, 'foo/f2.css'))
927933
assert not os.path.exists(os.path.join(output_dir, 'baz.txt'))
928934

929-
contentsf1 = open(os.path.join(output_dir, 'f1.css')).read()
930-
contentsf2 = open(os.path.join(output_dir, 'foo/f2.css')).read()
935+
with open(os.path.join(output_dir, 'f1.css')) as f:
936+
contentsf1 = f.read()
937+
with open(os.path.join(output_dir, 'foo/f2.css')) as f:
938+
contentsf2 = f.read()
931939
assert contentsf1 == 'a b {\n width: 100%; }\n'
932940
assert contentsf2 == 'foo {\n width: 100%; }\n'
933941

sassutils/_compat.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from six import PY2
2+
3+
4+
if PY2: # pragma: no cover (PY2)
5+
import collections as collections_abc # noqa: F401
6+
else: # pragma: no cover (PY3)
7+
import collections.abc as collections_abc # noqa: F401

sassutils/builder.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
"""
55
from __future__ import with_statement
66

7-
import collections
87
import io
98
import os
109
import os.path
@@ -14,6 +13,7 @@
1413
from six import string_types
1514

1615
from sass import compile
16+
from sassutils._compat import collections_abc
1717

1818
__all__ = 'SUFFIXES', 'SUFFIX_PATTERN', 'Manifest', 'build_directory'
1919

@@ -104,7 +104,7 @@ class Manifest(object):
104104
def normalize_manifests(cls, manifests):
105105
if manifests is None:
106106
manifests = {}
107-
elif isinstance(manifests, collections.Mapping):
107+
elif isinstance(manifests, collections_abc.Mapping):
108108
manifests = dict(manifests)
109109
else:
110110
raise TypeError('manifests must be a mapping object, not ' +
@@ -117,7 +117,7 @@ def normalize_manifests(cls, manifests):
117117
continue
118118
elif isinstance(manifest, tuple):
119119
manifest = Manifest(*manifest)
120-
elif isinstance(manifest, collections.Mapping):
120+
elif isinstance(manifest, collections_abc.Mapping):
121121
manifest = Manifest(**manifest)
122122
elif isinstance(manifest, string_types):
123123
manifest = Manifest(manifest)

sassutils/wsgi.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@
44
"""
55
from __future__ import absolute_import, with_statement
66

7-
import collections
87
import logging
98
import os
109
import os.path
1110

1211
from pkg_resources import resource_filename
1312

1413
from sass import CompileError
14+
from sassutils._compat import collections_abc
1515
from .builder import Manifest
1616

1717
__all__ = 'SassMiddleware',
@@ -98,7 +98,7 @@ def __init__(
9898
'not ' + repr(app))
9999
self.app = app
100100
self.manifests = Manifest.normalize_manifests(manifests)
101-
if not isinstance(package_dir, collections.Mapping):
101+
if not isinstance(package_dir, collections_abc.Mapping):
102102
raise TypeError('package_dir must be a mapping object, not ' +
103103
repr(package_dir))
104104
self.error_status = error_status

tox.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ envlist = pypy, pypy3, py27, py35, py36, py37
55
deps = -rrequirements-dev.txt
66
commands =
77
pytest sasstests.py
8-
flake8 .
8+
pre-commit run --all-files

0 commit comments

Comments
 (0)