Codebase list django-sass / 4e21618
Import upstream version 1.1.0 Debian Janitor 2 years ago
21 changed file(s) with 323 addition(s) and 157 deletion(s). Raw diff Collapse all Expand all
0 # EditorConfig is awesome: https://EditorConfig.org
1
2 root = true
3
4 [*]
5 charset = utf-8
6 end_of_line = lf
7 indent_style = space
8 insert_final_newline = true
9 max_line_length = 80
10 trim_trailing_whitespace = true
11
12 [*.{html,css,js,json,xml,yaml,yml}]
13 indent_size = 2
14
15 [*.{md,ps1,sh,py,rst}]
16 indent_size = 4
1111
1212 | | |
1313 |------------------------|----------------------|
14 | Python Package |[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/django-sass)](https://pypi.org/project/django-sass/) [![PyPI - Django Version](https://img.shields.io/pypi/djversions/django-sass)](https://pypi.org/project/django-sass/) [![PyPI - Wheel](https://img.shields.io/pypi/wheel/django-sass)](https://pypi.org/project/django-sass/) [![PyPI - Downloads](https://img.shields.io/pypi/dm/django-sass)](https://pypi.org/project/django-sass/) [![PyPI](https://img.shields.io/pypi/v/django-sass)](https://pypi.org/project/django-sass/) |
15 | Build | [![Build Status](https://dev.azure.com/coderedcorp/coderedcms/_apis/build/status/django-sass?branchName=master)](https://dev.azure.com/coderedcorp/coderedcms/_build/latest?definitionId=10&branchName=master) [![Azure DevOps tests (branch)](https://img.shields.io/azure-devops/tests/coderedcorp/coderedcms/10/master)](https://dev.azure.com/coderedcorp/coderedcms/_build/latest?definitionId=10&branchName=master) [![Azure DevOps coverage (branch)](https://img.shields.io/azure-devops/coverage/coderedcorp/coderedcms/10/master)](https://dev.azure.com/coderedcorp/coderedcms/_build/latest?definitionId=10&branchName=master) |
14 | Python Package | [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/django-sass)](https://pypi.org/project/django-sass/) [![PyPI - Django Version](https://img.shields.io/pypi/djversions/django-sass)](https://pypi.org/project/django-sass/) [![PyPI - Wheel](https://img.shields.io/pypi/wheel/django-sass)](https://pypi.org/project/django-sass/) [![PyPI - Downloads](https://img.shields.io/pypi/dm/django-sass)](https://pypi.org/project/django-sass/) [![PyPI](https://img.shields.io/pypi/v/django-sass)](https://pypi.org/project/django-sass/) |
15 | Build | [![Build Status](https://dev.azure.com/coderedcorp/cr-github/_apis/build/status/django-sass?branchName=main)](https://dev.azure.com/coderedcorp/cr-github/_build/latest?definitionId=10&branchName=main) [![Azure DevOps tests (branch)](https://img.shields.io/azure-devops/tests/coderedcorp/cr-github/10/main)](https://dev.azure.com/coderedcorp/cr-github/_build/latest?definitionId=10&branchName=main) [![Azure DevOps coverage (branch)](https://img.shields.io/azure-devops/coverage/coderedcorp/cr-github/10/main)](https://dev.azure.com/coderedcorp/cr-github/_build/latest?definitionId=10&branchName=main) |
1616
1717
1818 Installation
9292
9393 ✨✨ **Congratulations, you are now a Django + Sass developer!** ✨✨
9494
95 Now you can commit those CSS files to version control, or run `collectstatic` and deploy them as normal.
95 Now you can commit those CSS files to version control, or run `collectstatic`
96 and deploy them as normal.
9697
9798 For an example project layout, see `testproject/` in this repository.
9899
100101 Watch Mode
101102 ----------
102103
103 To have `django-sass` watch files and recompile them as they change (useful in development),
104 add the ``--watch`` flag.
104 To have `django-sass` watch files and recompile them as they change (useful in
105 development), add the ``--watch`` flag.
105106
106107 ```
107108 python manage.py sass app2/static/app2/scss/ app2/static/app2/css/ --watch
132133 Limitations
133134 -----------
134135
135 * `@import` statements must reference a path relative to a path in `STATICFILES_FINDERS`
136 (which will usually be an app's `static/` directory or some other directory specified
137 in `STATICFILES_DIRS`). Or they can reference a relative path equal to or below the
138 current file. It does not support traversing up the filesystem (i.e. `../`).
136 * `@import` statements must reference a path relative to a path in
137 `STATICFILES_FINDERS` (which will usually be an app's `static/` directory or
138 some other directory specified in `STATICFILES_DIRS`). Or they can reference a
139 relative path equal to or below the current file. It does not support
140 traversing up the filesystem (i.e. `../`).
139141
140142 Legal imports:
141143 ```scss
148150 @import '../file';
149151 ```
150152
151 * Only files ending in `.scss` are supported for now.
152
153 * Only supports `-g`, `-p`, and `-t` options similar to `pysassc`. Ideally `django-sass` will
154 be as similar as possible to the `pysassc` command line interface.
155
156 Feel free to file an issue or make a pull request to improve any of these limitations. 🐱‍💻
153 * Only supports `-g`, `-p`, and `-t` options similar to `pysassc`. Ideally
154 `django-sass` will be as similar as possible to the `pysassc` command line
155 interface.
156
157 Feel free to file an issue or make a pull request to improve any of these
158 limitations. 🐱‍💻
157159
158160
159161 Why django-sass?
160162 ----------------
161163
162 Other packages such as [django-libsass](https://github.com/torchbox/django-libsass)
163 and [django-sass-processor](https://github.com/jrief/django-sass-processor),
164 while nice packages, require `django-compressor` which itself depends on several
165 other packages that require compilation to install.
166
167 * If you simply want to use Sass in development without installing a web of unwanted
168 dependencies, then `django-sass` is for you.
169 * If you don't want to deploy any processors or compressors to your production server,
170 then `django-sass` is for you.
164 Other packages such as
165 [django-libsass](https://github.com/torchbox/django-libsass) and
166 [django-sass-processor](https://github.com/jrief/django-sass-processor), while
167 nice packages, require `django-compressor` which itself depends on several other
168 packages that require compilation to install.
169
170 Installing `django-compressor` in your production web server requires a LOT of
171 extra bloat including a C compiler. It then will compile the Sass on-the-fly
172 while rendering the HTML templates. This is a wasteful use of CPU on your web
173 server.
174
175 Instead, `django-sass` lets you compile the Sass locally on your machine
176 *before* deploying, to reduce dependencies and CPU time on your production web
177 server. This helps keep things fast and simple.
178
179 * If you simply want to use Sass in development without installing a web of
180 unwanted dependencies, then `django-sass` is for you.
181 * If you don't want to deploy any processors or compressors to your production
182 server, then `django-sass` is for you.
171183 * If you don't want to change the way you reference and serve static files,
172184 then `django-sass` is for you.
173 * And if you want the absolute simplest installation and setup possible for doing Sass,
174 `django-sass` is for you too.
175
176 django-sass only depends on libsass (which provides pre-built wheels for Windows, Mac,
177 and Linux), and of course Django (any version).
185 * And if you want the absolute simplest installation and setup possible for
186 doing Sass, `django-sass` is for you too.
187
188 django-sass only depends on libsass (which provides pre-built wheels for
189 Windows, Mac, and Linux), and of course Django (any version).
178190
179191
180192 Programmatically Compiling Sass
232244 Before committing, run static analysis tools:
233245
234246 ```
247 (myvenv)$ black .
235248 (myvenv)$ flake8
236249 (myvenv)$ mypy
237250 ```
245258
246259 Changelog
247260 ---------
261
262 #### 1.1.0
263 * New: Now compiles `.sass` files as well as `.scss` files.
264 * Fix bug when input path is a file and output path does not exist.
265
266 #### 1.0.1
267 * Maintanence release, no functional changes.
268 * Add additional type hints within the codebase.
269 * Tested against Django 3.1
270 * Formatted code with `black`.
248271
249272 #### 1.0.0
250273 * New: You can now use `django_sass` APIs directly in Python.
252275 * Code quality improvements.
253276
254277 #### 0.2.0
255 * New feature: `-g` option to build a source map (when input is a file, not a directory).
278 * New feature: `-g` option to build a source map (when input is a file, not a
279 directory).
256280
257281 #### 0.1.2
258282 * Fix: Write compiled CSS files as UTF-8.
259 * Change: Default `-p` precision from 5 to 8 for better support building Bootstrap CSS.
283 * Change: Default `-p` precision from 5 to 8 for better support building
284 Bootstrap CSS.
260285
261286 #### 0.1.1
262287 * Fix: Create full file path if not exists when specifying a file output.
1414
1515
1616 trigger:
17 - master
17 - main
1818
1919
2020 stages:
2828 vmImage: 'ubuntu-latest'
2929 strategy:
3030 matrix:
31 py3.5:
32 PYTHON_VERSION: '3.5'
3331 py3.6:
3432 PYTHON_VERSION: '3.6'
3533 py3.7:
3634 PYTHON_VERSION: '3.7'
3735 py3.8:
3836 PYTHON_VERSION: '3.8'
37 py3.9:
38 PYTHON_VERSION: '3.9'
3939
4040 steps:
4141 - task: UsePythonVersion@0
7979 - task: UsePythonVersion@0
8080 displayName: 'Use Python version'
8181 inputs:
82 versionSpec: '3.8'
82 versionSpec: '3.9'
8383 architecture: 'x64'
8484
8585 - script: python -m pip install -r requirements-dev.txt
8787
8888 - script: flake8 .
8989 displayName: 'CR-QC: Static analysis (flake8)'
90
91 - script: black --check .
92 displayName: 'CR-QC: Format check'
9093
9194 - script: mypy .
9295 displayName: 'CR-QC: Type check (mypy)'
11
22 <#
33 .SYNOPSIS
4 Compares code coverage percent of local coverage.xml file to master branch
4 Compares code coverage percent of local coverage.xml file to main branch
55 (Azure Pipeline API).
66
77 .PARAMETER wd
2525 param(
2626 [string] $wd = (Get-Item (Split-Path $PSCommandPath -Parent)).Parent,
2727 [string] $org = "coderedcorp",
28 [string] $project = "coderedcms",
28 [string] $project = "cr-github",
2929 [string] $pipeline_name = "django-sass"
3030 )
3131
4040
4141
4242 # Get list of all recent builds.
43 $masterBuildJson = (
44 Invoke-WebRequest "$ApiBase/_apis/build/builds?branchName=refs/heads/master&api-version=5.1"
43 $mainBuildJson = (
44 Invoke-WebRequest "$ApiBase/_apis/build/builds?branchName=refs/heads/main&api-version=5.1"
4545 ).Content | ConvertFrom-Json
4646
4747 # Get the latest matching build ID from the list of builds.
48 foreach ($build in $masterBuildJson.value) {
48 foreach ($build in $mainBuildJson.value) {
4949 if ($build.definition.name -eq $pipeline_name) {
50 $masterLatestId = $build.id
50 $mainLatestId = $build.id
5151 break
5252 }
5353 }
5454
5555 # Retrieve code coverage for this build ID.
56 $masterCoverageJson = (
57 Invoke-WebRequest "$ApiBase/_apis/test/codecoverage?buildId=$masterLatestId&api-version=5.1-preview.1"
56 $mainCoverageJson = (
57 Invoke-WebRequest "$ApiBase/_apis/test/codecoverage?buildId=$mainLatestId&api-version=5.1-preview.1"
5858 ).Content | ConvertFrom-Json
59 foreach ($cov in $masterCoverageJson.coverageData.coverageStats) {
59 foreach ($cov in $mainCoverageJson.coverageData.coverageStats) {
6060 if ($cov.label -eq "Lines") {
61 $masterlinerate = [math]::Round(($cov.covered / $cov.total) * 100, 2)
61 $mainlinerate = [math]::Round(($cov.covered / $cov.total) * 100, 2)
6262 }
6363 }
6464
8383
8484
8585 Write-Output ""
86 Write-Output "Master line coverage rate: $masterlinerate%"
87 Write-Output "Branch line coverage rate: $branchlinerate%"
86 Write-Output "Main coverage rate: $mainlinerate%"
87 Write-Output "Branch coverage rate: $branchlinerate%"
8888
89 if ($masterlinerate -eq 0) {
89 if ($mainlinerate -eq 0) {
9090 $change = "Infinite"
9191 }
9292 else {
93 $change = [math]::Abs($branchlinerate - $masterlinerate)
93 $change = [math]::Abs($branchlinerate - $mainlinerate)
9494 }
9595
96 if ($branchlinerate -gt $masterlinerate) {
96 if ($branchlinerate -gt $mainlinerate) {
9797 Write-Host "Coverage increased by $change% 😀" -ForegroundColor Green
9898 exit 0
9999 }
100 elseif ($branchlinerate -eq $masterlinerate) {
100 elseif ($branchlinerate -eq $mainlinerate) {
101101 Write-Host "Coverage has not changed." -ForegroundColor Green
102102 exit 0
103103 }
2323
2424 def find_static_scss() -> List[str]:
2525 """
26 Finds all static scss files available in this Django project.
26 Finds all static scss/sass files available in this Django project.
2727
2828 :returns:
29 List of paths of static scss files.
29 List of paths of static scss/sass files.
3030 """
3131 scss_files = []
3232 for finder in get_finders():
3333 for path, storage in finder.list([]):
34 if path.endswith(".scss"):
34 if path.endswith(".scss") or path.endswith(".sass"):
3535 fullpath = finder.find(path)
3636 scss_files.append(fullpath)
3737 return scss_files
3838
3939
40 def compile_sass(inpath: str, outpath: str, output_style: str = None, precision: int = None,
41 source_map: bool = False, include_paths: List[str] = None) -> None:
40 def compile_sass(
41 inpath: str,
42 outpath: str,
43 output_style: str = None,
44 precision: int = None,
45 source_map: bool = False,
46 include_paths: List[str] = None,
47 ) -> None:
4248 """
4349 Calls sass.compile() within context of Django's known static file paths,
4450 and writes output CSS and/or sourcemaps to file.
4551
4652 :param str inpath:
47 Path to SCSS file or directory of SCSS files.
53 Path to SCSS/Sass file or directory of SCSS/Sass files.
4854 :param str outpath:
4955 Path to a CSS file or directory in which to write output. The path will
5056 be created if it does not exist.
8086 # Handle input files.
8187 outfile = None
8288 if os.path.isfile(inpath):
89
8390 sassargs.update({"filename": inpath})
84 if os.path.isdir(outpath):
91
92 # If outpath does not exist, guess if it should be a dir and create it.
93 if not os.path.exists(outpath):
94 if not outpath.endswith(".css"):
95 os.makedirs(outpath)
96
97 # If outpath is a directory, create a child file.
98 # Otherwise use provided file path.
99 if os.path.exists(outpath) and os.path.isdir(outpath):
85100 outfile = os.path.join(
86 outpath, os.path.basename(inpath.replace(".scss", ".css"))
101 outpath,
102 os.path.basename(
103 inpath.replace(".scss", ".css").replace(".sass", ".css")
104 ),
87105 )
88106 else:
89107 outfile = outpath
108
109 # Create source map if specified.
90110 if source_map:
91111 sassargs.update({"source_map_filename": outfile + ".map"})
92112
11
22
33 class DjangoSassConfig(AppConfig):
4 name = 'django_sass'
4 name = "django_sass"
0 from typing import Dict
01 import os
12 import sys
23 import time
7071 self.stdout.write("Watching...")
7172
7273 # Track list of files to watch and their modified time.
73 watchfiles = {}
74 watchfiles = {} # type: Dict[str, float]
7475 while True:
7576 needs_updated = False
7677
9394 precision=o_precision,
9495 source_map=o_srcmap,
9596 )
96 self.stdout.write("Updated files at %s" % time.time())
97 self.stdout.write(
98 "Updated files at %s" % time.time()
99 )
97100 except sass.CompileError as exc:
98101 self.stdout.write(str(exc))
99102
0 [tool.black]
1 line-length = 80
2 target-version = ['py36', 'py37', 'py38']
3 # Regular expression of files to exclude.
4 exclude = '''
5 /(
6 .venv
7 | venv
8 | migrations
9 )/
10 '''
00 -e ./
1 black
12 flake8
23 mypy
34 pytest
00 [flake8]
11 max-line-length = 100
2 exclude = migrations
2 exclude = .venv,venv,migrations
33
44 [mypy]
55 ignore_missing_imports = True
6 namespace_packages = True
67
78 [tool:pytest]
89 DJANGO_SETTINGS_MODULE = testproject.settings
11 from setuptools import setup, find_packages
22
33
4 with open(os.path.join(os.path.dirname(__file__), "README.md"), encoding="utf8") as readme:
4 with open(
5 os.path.join(os.path.dirname(__file__), "README.md"), encoding="utf8"
6 ) as readme:
57 README = readme.read()
68
79 setup(
810 name="django-sass",
9 version="1.0.0",
11 version="1.1.0",
1012 author="CodeRed LLC",
1113 author_email="info@coderedcorp.com",
1214 url="https://github.com/coderedcorp/django-sass",
13 description=("The absolute simplest way to use Sass with Django. Pure Python, "
14 "minimal dependencies, and no special configuration required!"),
15 description=(
16 "The absolute simplest way to use Sass with Django. Pure Python, "
17 "minimal dependencies, and no special configuration required!"
18 ),
1519 long_description=README,
1620 long_description_content_type="text/markdown",
1721 license="BSD license",
1923 packages=find_packages(),
2024 install_requires=[
2125 "django",
22 "libsass"
26 "libsass",
2327 ],
2428 classifiers=[
25 "Intended Audience :: Developers",
26 "License :: OSI Approved :: BSD License",
27 "Natural Language :: English",
28 "Programming Language :: Python :: 3",
29 "Programming Language :: Python :: 3 :: Only",
30 "Framework :: Django",
29 "Environment :: Web Environment",
3130 "Framework :: Django :: 2.0",
3231 "Framework :: Django :: 2.1",
3332 "Framework :: Django :: 2.2",
3433 "Framework :: Django :: 3.0",
35 "Environment :: Web Environment",
34 "Framework :: Django :: 3.1",
35 "Framework :: Django",
36 "Intended Audience :: Developers",
37 "License :: OSI Approved :: BSD License",
38 "Natural Language :: English",
39 "Programming Language :: Python :: 3 :: Only",
40 "Programming Language :: Python :: 3",
41 "Programming Language :: Python :: 3.6",
42 "Programming Language :: Python :: 3.7",
43 "Programming Language :: Python :: 3.8",
44 "Programming Language :: Python :: 3.9",
3645 ],
3746 )
11
22
33 class App1Config(AppConfig):
4 name = 'app1'
4 name = "app1"
11
22
33 class App2Config(AppConfig):
4 name = 'app2'
4 name = "app2"
0 from django.apps import AppConfig
1
2
3 class App3Config(AppConfig):
4 name = "app3"
0 /* Tests: app3/sass/indent_test.sass */
1
2 .test_item
3 border: 1px solid red
44
55
66 def main():
7 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'testproject.settings')
7 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "testproject.settings")
88 try:
99 from django.core.management import execute_from_command_line
1010 except ImportError as exc:
1616 execute_from_command_line(sys.argv)
1717
1818
19 if __name__ == '__main__':
19 if __name__ == "__main__":
2020 main()
1010 """
1111
1212 import os
13 from typing import List
1314
1415 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
1516 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
1920 # See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
2021
2122 # SECURITY WARNING: keep the secret key used in production secret!
22 SECRET_KEY = '-_wl=tq26(*wyvfza+ncg_436c53pu81d=07j62+vm5y2pc)f^'
23 SECRET_KEY = "-_wl=tq26(*wyvfza+ncg_436c53pu81d=07j62+vm5y2pc)f^"
2324
2425 # SECURITY WARNING: don't run with debug turned on in production!
2526 DEBUG = True
2627
27 ALLOWED_HOSTS = []
28 ALLOWED_HOSTS = [] # type: List[str]
2829
2930
3031 # Application definition
3132
3233 INSTALLED_APPS = [
33 'app1',
34 'app2',
35 'django_sass',
36
37 'django.contrib.admin',
38 'django.contrib.auth',
39 'django.contrib.contenttypes',
40 'django.contrib.sessions',
41 'django.contrib.messages',
42 'django.contrib.staticfiles',
34 "app1",
35 "app2",
36 "app3",
37 "django_sass",
38 "django.contrib.admin",
39 "django.contrib.auth",
40 "django.contrib.contenttypes",
41 "django.contrib.sessions",
42 "django.contrib.messages",
43 "django.contrib.staticfiles",
4344 ]
4445
4546 MIDDLEWARE = [
46 'django.middleware.security.SecurityMiddleware',
47 'django.contrib.sessions.middleware.SessionMiddleware',
48 'django.middleware.common.CommonMiddleware',
49 'django.middleware.csrf.CsrfViewMiddleware',
50 'django.contrib.auth.middleware.AuthenticationMiddleware',
51 'django.contrib.messages.middleware.MessageMiddleware',
52 'django.middleware.clickjacking.XFrameOptionsMiddleware',
47 "django.middleware.security.SecurityMiddleware",
48 "django.contrib.sessions.middleware.SessionMiddleware",
49 "django.middleware.common.CommonMiddleware",
50 "django.middleware.csrf.CsrfViewMiddleware",
51 "django.contrib.auth.middleware.AuthenticationMiddleware",
52 "django.contrib.messages.middleware.MessageMiddleware",
53 "django.middleware.clickjacking.XFrameOptionsMiddleware",
5354 ]
5455
55 ROOT_URLCONF = 'testproject.urls'
56 ROOT_URLCONF = "testproject.urls"
5657
5758 TEMPLATES = [
5859 {
59 'BACKEND': 'django.template.backends.django.DjangoTemplates',
60 'DIRS': [],
61 'APP_DIRS': True,
62 'OPTIONS': {
63 'context_processors': [
64 'django.template.context_processors.debug',
65 'django.template.context_processors.request',
66 'django.contrib.auth.context_processors.auth',
67 'django.contrib.messages.context_processors.messages',
60 "BACKEND": "django.template.backends.django.DjangoTemplates",
61 "DIRS": [],
62 "APP_DIRS": True,
63 "OPTIONS": {
64 "context_processors": [
65 "django.template.context_processors.debug",
66 "django.template.context_processors.request",
67 "django.contrib.auth.context_processors.auth",
68 "django.contrib.messages.context_processors.messages",
6869 ],
6970 },
7071 },
7172 ]
7273
73 WSGI_APPLICATION = 'testproject.wsgi.application'
74 WSGI_APPLICATION = "testproject.wsgi.application"
7475
7576
7677 # Database
7778 # https://docs.djangoproject.com/en/2.2/ref/settings/#databases
7879
7980 DATABASES = {
80 'default': {
81 'ENGINE': 'django.db.backends.sqlite3',
82 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
81 "default": {
82 "ENGINE": "django.db.backends.sqlite3",
83 "NAME": os.path.join(BASE_DIR, "db.sqlite3"),
8384 }
8485 }
8586
8788 # Internationalization
8889 # https://docs.djangoproject.com/en/2.2/topics/i18n/
8990
90 LANGUAGE_CODE = 'en-us'
91 LANGUAGE_CODE = "en-us"
9192
92 TIME_ZONE = 'UTC'
93 TIME_ZONE = "UTC"
9394
9495 USE_I18N = True
9596
101102 # Static files (CSS, JavaScript, Images)
102103 # https://docs.djangoproject.com/en/2.2/howto/static-files/
103104
104 STATIC_URL = '/static/'
105 STATIC_URL = "/static/"
1616 from django.urls import path
1717
1818 urlpatterns = [
19 path('admin/', admin.site.urls),
19 path("admin/", admin.site.urls),
2020 ]
1010
1111 from django.core.wsgi import get_wsgi_application
1212
13 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'testproject.settings')
13 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "testproject.settings")
1414
1515 application = get_wsgi_application()
22 import subprocess
33 import time
44 import unittest
5 from typing import List
56
67 from django_sass import find_static_paths, find_static_scss
78
89
910 THIS_DIR = os.path.dirname(os.path.abspath(__file__))
1011
12 SCSS_CONTAINS = [
13 "/* Tests: app1/scss/_include.scss */",
14 "/* Tests: app2/scss/_samedir.scss */",
15 "/* Tests: app2/scss/subdir/_subdir.scss */",
16 "/* Tests: app2/scss/test.scss */",
17 ]
18
1119
1220 class TestDjangoSass(unittest.TestCase):
13
1421 def setUp(self):
1522 self.outdir = os.path.join(THIS_DIR, "out")
1623
1825 # Clean up output files
1926 shutil.rmtree(self.outdir, ignore_errors=True)
2027
21 def assert_output(self, real_outpath: str):
28 def assert_output(
29 self,
30 inpath: str,
31 outpath: str,
32 real_outpath: str,
33 contains: List[str],
34 args: List[str] = None,
35 ):
36 # Command to run
37 args = args or []
38 cmd = ["python", "manage.py", "sass", *args, inpath, outpath]
39 # Run the management command on testproject.
40 proc = subprocess.run(cmd, cwd=THIS_DIR)
41 # Verify the process exited cleanly.
42 self.assertEqual(proc.returncode, 0)
2243 # Verify that the output file exists.
23 print(real_outpath)
24 self.assertTrue(os.path.isfile(real_outpath))
44 # self.assertTrue(os.path.isfile(real_outpath))
2545
2646 # Verify that the file contains expected output from all sass files.
2747 with open(real_outpath, encoding="utf8") as f:
2848 contents = f.read()
29 self.assertTrue("/* Tests: app1/scss/_include.scss */" in contents)
30 self.assertTrue("/* Tests: app2/scss/_samedir.scss */" in contents)
31 self.assertTrue("/* Tests: app2/scss/subdir/_subdir.scss */" in contents)
32 self.assertTrue("/* Tests: app2/scss/test.scss */" in contents)
49 for compiled_data in contains:
50 self.assertTrue(compiled_data in contents)
3351
3452 def test_find_static_paths(self):
3553 paths = find_static_paths()
4159 files = find_static_scss()
4260 # Assert that it found all of our scss files.
4361 self.assertTrue(
44 os.path.join(THIS_DIR, "app1", "static", "app1", "scss", "_include.scss") in files)
62 os.path.join(
63 THIS_DIR, "app1", "static", "app1", "scss", "_include.scss"
64 )
65 in files
66 )
4567 self.assertTrue(
46 os.path.join(THIS_DIR, "app2", "static", "app2", "scss", "_samedir.scss") in files)
68 os.path.join(
69 THIS_DIR, "app2", "static", "app2", "scss", "_samedir.scss"
70 )
71 in files
72 )
4773 self.assertTrue(
48 os.path.join(THIS_DIR, "app2", "static", "app2", "scss", "test.scss") in files)
74 os.path.join(
75 THIS_DIR, "app2", "static", "app2", "scss", "test.scss"
76 )
77 in files
78 )
4979 self.assertTrue(
50 os.path.join(THIS_DIR, "app2", "static", "app2", "scss", "subdir", "_subdir.scss")
51 in files)
80 os.path.join(
81 THIS_DIR,
82 "app2",
83 "static",
84 "app2",
85 "scss",
86 "subdir",
87 "_subdir.scss",
88 )
89 in files
90 )
91 self.assertTrue(
92 os.path.join(
93 THIS_DIR, "app3", "static", "app3", "sass", "indent_test.sass"
94 )
95 in files
96 )
5297
5398 def test_cli(self):
5499 # Input and output paths relative to django static dirs.
55100 inpath = os.path.join("app2", "static", "app2", "scss", "test.scss")
56101 outpath = os.path.join(self.outdir, "test_file.css")
57 # Command to run
58 cmd = ["python", "manage.py", "sass", inpath, outpath]
59 # Run the management command on testproject.
60 proc = subprocess.run(cmd, cwd=THIS_DIR)
61 # Verify the process exited cleanly.
62 self.assertEqual(proc.returncode, 0)
63 # Assert output is correct.
64 self.assert_output(outpath)
102 self.assert_output(
103 inpath=inpath,
104 outpath=outpath,
105 real_outpath=outpath,
106 contains=SCSS_CONTAINS,
107 )
65108
66109 def test_cli_dir(self):
67110 # Input and output paths relative to django static dirs.
68111 inpath = os.path.join("app2", "static", "app2", "scss")
69 outpath = self.outdir
70112 # Expected output path on filesystem.
71113 real_outpath = os.path.join(self.outdir, "test.css")
72 # Command to run
73 cmd = ["python", "manage.py", "sass", inpath, outpath]
74 # Run the management command on testproject.
75 proc = subprocess.run(cmd, cwd=THIS_DIR)
76 # Verify the process exited cleanly.
77 self.assertEqual(proc.returncode, 0)
78 # Assert output is correct.
79 self.assert_output(real_outpath)
114 self.assert_output(
115 inpath=inpath,
116 outpath=self.outdir,
117 real_outpath=real_outpath,
118 contains=SCSS_CONTAINS,
119 )
120
121 def test_cli_infile_outdir(self):
122 # Input is a file; output is non-existant path (without .css extension).
123 inpath = os.path.join("app2", "static", "app2", "scss", "test.scss")
124 outpath = os.path.join(self.outdir, "does-not-exist")
125 # Expected output path on filesystem.
126 real_outpath = os.path.join(outpath, "test.css")
127 self.assert_output(
128 inpath=inpath,
129 outpath=outpath,
130 real_outpath=real_outpath,
131 contains=SCSS_CONTAINS,
132 )
133
134 def test_sass_compiles(self):
135 # Input and output paths relative to django static dirs.
136 inpath = os.path.join("app3", "static", "app3", "sass")
137 # Expected output path on filesystem.
138 real_outpath = os.path.join(self.outdir, "indent_test.css")
139 self.assert_output(
140 inpath=inpath,
141 outpath=self.outdir,
142 real_outpath=real_outpath,
143 contains=["/* Tests: app3/sass/indent_test.sass */"],
144 )
80145
81146 def test_cli_srcmap(self):
82147 # Input and output paths relative to django static dirs.
83148 inpath = os.path.join("app2", "static", "app2", "scss", "test.scss")
84149 outpath = os.path.join(self.outdir, "test.css")
85 # Command to run
86 cmd = ["python", "manage.py", "sass", "-g", inpath, outpath]
87 # Run the management command on testproject.
88 proc = subprocess.run(cmd, cwd=THIS_DIR)
89 # Verify the process exited cleanly.
90 self.assertEqual(proc.returncode, 0)
91 # Assert output is correct.
92 self.assert_output(outpath)
93 self.assertTrue(os.path.isfile(os.path.join(self.outdir, "test.css.map")))
150 self.assert_output(
151 inpath=inpath,
152 outpath=outpath,
153 real_outpath=outpath,
154 contains=SCSS_CONTAINS,
155 args=["-g"],
156 )
157 self.assertTrue(
158 os.path.isfile(os.path.join(self.outdir, "test.css.map"))
159 )
94160
95 @unittest.skip
161 @unittest.skip("Test needs fixed...")
96162 def test_cli_watch(self):
97163 # Input and output paths relative to django static dirs.
98164 inpath = os.path.join("app2", "static", "app2", "scss", "test.scss")