Codebase list django-sass / d0d50d63-fe17-4963-a8f0-e08ae88103df/upstream/1.1.0
Import upstream version 1.1.0 Debian Janitor 1 year, 4 months ago
33 changed file(s) with 788 addition(s) and 1002 deletion(s). Raw diff Collapse all Expand all
+0
-9
.gitattributes less more
0 # Explicitly declare text files that should always be normalized and converted
1 # to unix line endings, to reduce cross-platform development issues.
2 *.py text eol=lf
3 *.html text eol=lf
4 *.js text eol=lf
5 *.css text eol=lf
6 *.json text eol=lf
7 *.md text eol=lf
8 *.rst text eol=lf
+0
-387
.gitignore less more
0 # Created by https://www.gitignore.io, modified by CodeRed.
1
2 #######################################
3 ### Editors
4 #######################################
5
6
7 ### Emacs ###
8
9 # -*- mode: gitignore; -*-
10 *~
11 \#*\#
12 /.emacs.desktop
13 /.emacs.desktop.lock
14 *.elc
15 auto-save-list
16 tramp
17 .\#*
18
19 # Org-mode
20 .org-id-locations
21 *_archive
22
23 # flymake-mode
24 *_flymake.*
25
26 # eshell files
27 /eshell/history
28 /eshell/lastdir
29
30 # elpa packages
31 /elpa/
32
33 # reftex files
34 *.rel
35
36 # Flycheck
37 flycheck_*.el
38
39 # server auth directory
40 /server/
41
42 # projectiles files
43 .projectile
44
45 # directory configuration
46 .dir-locals.el
47
48 # network security
49 /network-security.data
50
51
52 ### KomodoEdit ###
53
54 *.komodoproject
55 .komodotools
56
57
58 ### PyCharm ###
59
60 # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
61 # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
62
63 # User-specific stuff
64 .idea/**/workspace.xml
65 .idea/**/tasks.xml
66 .idea/**/usage.statistics.xml
67 .idea/**/dictionaries
68 .idea/**/shelf
69
70 # Generated files
71 .idea/**/contentModel.xml
72
73 # Sensitive or high-churn files
74 .idea/**/dataSources/
75 .idea/**/dataSources.ids
76 .idea/**/dataSources.local.xml
77 .idea/**/sqlDataSources.xml
78 .idea/**/dynamic.xml
79 .idea/**/uiDesigner.xml
80 .idea/**/dbnavigator.xml
81
82 # Gradle
83 .idea/**/gradle.xml
84 .idea/**/libraries
85
86 # Mongo Explorer plugin
87 .idea/**/mongoSettings.xml
88
89 # File-based project format
90 *.iws
91
92 # IntelliJ
93 out/
94
95 # mpeltonen/sbt-idea plugin
96 .idea_modules/
97
98 # JIRA plugin
99 atlassian-ide-plugin.xml
100
101 # Cursive Clojure plugin
102 .idea/replstate.xml
103
104 # Crashlytics plugin (for Android Studio and IntelliJ)
105 com_crashlytics_export_strings.xml
106 crashlytics.properties
107 crashlytics-build.properties
108 fabric.properties
109
110 # Editor-based Rest Client
111 .idea/httpRequests
112
113 # Sonarlint plugin
114 .idea/sonarlint
115
116
117 ### SublimeText ###
118
119 # Cache files for Sublime Text
120 *.tmlanguage.cache
121 *.tmPreferences.cache
122 *.stTheme.cache
123
124 # Workspace files are user-specific
125 *.sublime-workspace
126
127 # Project files should be checked into the repository, unless a significant
128 # proportion of contributors will probably not be using Sublime Text
129 # *.sublime-project
130
131 # SFTP configuration file
132 sftp-config.json
133
134 # Package control specific files
135 Package Control.last-run
136 Package Control.ca-list
137 Package Control.ca-bundle
138 Package Control.system-ca-bundle
139 Package Control.cache/
140 Package Control.ca-certs/
141 Package Control.merged-ca-bundle
142 Package Control.user-ca-bundle
143 oscrypto-ca-bundle.crt
144 bh_unicode_properties.cache
145
146 # Sublime-github package stores a github token in this file
147 # https://packagecontrol.io/packages/sublime-github
148 GitHub.sublime-settings
149
150
151 ### TextMate ###
152
153 *.tmproj
154 *.tmproject
155 tmtags
156
157
158 ### Vim ###
159
160 # Swap
161 [._]*.s[a-v][a-z]
162 [._]*.sw[a-p]
163 [._]s[a-rt-v][a-z]
164 [._]ss[a-gi-z]
165 [._]sw[a-p]
166
167 # Session
168 Session.vim
169
170 # Temporary
171 .netrwhist
172 # Auto-generated tag files
173 tags
174 # Persistent undo
175 [._]*.un~
176
177
178 ### VisualStudioCode ###
179 .vscode/
180
181 ### VisualStudioCode Patch ###
182 # Ignore all local history of files
183 .history
184
185
186
187 #######################################
188 ### Django/Python Stack
189 #######################################
190
191
192 ### Django ###
193
194 *.log
195 *.pot
196 *.pyc
197 __pycache__/
198 local_settings.py
199 db.sqlite3
200
201 # If your build process includes running collectstatic, then you probably don't need or want to include staticfiles/
202 # in your Git repository. Update and uncomment the following line accordingly.
203 # <django-project-name>/staticfiles/
204
205
206 ### Django.Python Stack ###
207
208 # Byte-compiled / optimized / DLL files
209 *.py[cod]
210 *$py.class
211
212 # C extensions
213 *.so
214
215 # Distribution / packaging
216 .Python
217 build/
218 develop-eggs/
219 dist/
220 downloads/
221 eggs/
222 .eggs/
223 lib/
224 lib64/
225 parts/
226 sdist/
227 var/
228 wheels/
229 share/python-wheels/
230 *.egg-info/
231 .installed.cfg
232 *.egg
233 MANIFEST
234
235 # PyInstaller
236 # Usually these files are written by a python script from a template
237 # before PyInstaller builds the exe, so as to inject date/other infos into it.
238 *.manifest
239 *.spec
240
241 # Installer logs
242 pip-log.txt
243 pip-delete-this-directory.txt
244
245 # Unit test / coverage reports
246 htmlcov/
247 .tox/
248 .nox/
249 .coverage
250 .coverage.*
251 .cache
252 nosetests.xml
253 coverage.xml
254 *.cover
255 .hypothesis/
256 .pytest_cache/
257 junit/
258
259 # Translations
260 *.mo
261
262 # Flask stuff:
263 instance/
264 .webassets-cache
265
266 # Scrapy stuff:
267 .scrapy
268
269 # Sphinx documentation
270 docs/_build/
271
272 # PyBuilder
273 target/
274
275 # Jupyter Notebook
276 .ipynb_checkpoints
277
278 # IPython
279 profile_default/
280 ipython_config.py
281
282 # pyenv
283 .python-version
284
285 # celery beat schedule file
286 celerybeat-schedule
287
288 # SageMath parsed files
289 *.sage.py
290
291 # Environments
292 .env
293 .venv
294 env/
295 venv/
296 ENV/
297 env.bak/
298 venv.bak/
299
300 # Spyder project settings
301 .spyderproject
302 .spyproject
303
304 # Rope project settings
305 .ropeproject
306
307 # mkdocs documentation
308 /site
309
310 # mypy
311 .mypy_cache/
312 .dmypy.json
313 dmypy.json
314
315 # Pyre type checker
316 .pyre/
317
318
319 ### OSX ###
320
321 # General
322 .DS_Store
323 .AppleDouble
324 .LSOverride
325
326 # Icon must end with two \r
327 Icon
328
329 # Thumbnails
330 ._*
331
332 # Files that might appear in the root of a volume
333 .DocumentRevisions-V100
334 .fseventsd
335 .Spotlight-V100
336 .TemporaryItems
337 .Trashes
338 .VolumeIcon.icns
339 .com.apple.timemachine.donotpresent
340
341 # Directories potentially created on remote AFP share
342 .AppleDB
343 .AppleDesktop
344 Network Trash Folder
345 Temporary Items
346 .apdisk
347
348
349
350 #######################################
351 ### Operating Systems
352 #######################################
353
354
355 ### Windows ###
356
357 # Windows thumbnail cache files
358 Thumbs.db
359 ehthumbs.db
360 ehthumbs_vista.db
361
362 # Dump file
363 *.stackdump
364
365 # Folder config file
366 [Dd]esktop.ini
367
368 # Recycle Bin used on file shares
369 $RECYCLE.BIN/
370
371 # Windows Installer files
372 *.cab
373 *.msi
374 *.msix
375 *.msm
376 *.msp
377
378 # Windows shortcuts
379 *.lnk
380
381
382 #######################################
383 ### Custom
384 #######################################
385
386 testproject/**/*.css
0 Metadata-Version: 2.1
1 Name: django-sass
2 Version: 1.1.0
3 Summary: The absolute simplest way to use Sass with Django. Pure Python, minimal dependencies, and no special configuration required!
4 Home-page: https://github.com/coderedcorp/django-sass
5 Author: CodeRed LLC
6 Author-email: info@coderedcorp.com
7 License: BSD license
8 Classifier: Environment :: Web Environment
9 Classifier: Framework :: Django :: 2.0
10 Classifier: Framework :: Django :: 2.1
11 Classifier: Framework :: Django :: 2.2
12 Classifier: Framework :: Django :: 3.0
13 Classifier: Framework :: Django :: 3.1
14 Classifier: Framework :: Django
15 Classifier: Intended Audience :: Developers
16 Classifier: License :: OSI Approved :: BSD License
17 Classifier: Natural Language :: English
18 Classifier: Programming Language :: Python :: 3 :: Only
19 Classifier: Programming Language :: Python :: 3
20 Classifier: Programming Language :: Python :: 3.6
21 Classifier: Programming Language :: Python :: 3.7
22 Classifier: Programming Language :: Python :: 3.8
23 Classifier: Programming Language :: Python :: 3.9
24 Description-Content-Type: text/markdown
25 License-File: LICENSE
26
27 django-sass
28 ===========
29
30 The absolute simplest way to use [Sass](https://sass-lang.com/) with Django.
31 Pure Python, minimal dependencies, and no special configuration required.
32
33 [Source code on GitHub](https://github.com/coderedcorp/django-sass)
34
35
36 Status
37 ------
38
39 | | |
40 |------------------------|----------------------|
41 | 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/) |
42 | 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) |
43
44
45 Installation
46 ------------
47
48 1. Install from pip.
49
50 ```
51 pip install django-sass
52 ```
53
54 2. Add to your `INSTALLED_APPS` (you only need to do this in a dev environment,
55 you would not want this in your production settings file, although it adds zero
56 overhead):
57
58 ```python
59 INSTALLED_APPS = [
60 ...,
61 'django_sass',
62 ]
63 ```
64
65 3. Congratulations, you're done 😀
66
67
68 Usage
69 -----
70
71 In your app's static files, use Sass as normal. The only difference is that
72 you can **not** traverse upwards using `../` in `@import` statements. For example:
73
74 ```
75 app1/
76 |- static/
77 |- app1/
78 |- scss/
79 |- _colors.scss
80 |- app1.scss
81 app2/
82 |- static/
83 |- app2/
84 |- scss/
85 |- _colors.scss
86 |- app2.scss
87 ```
88
89 In `app2.scss` you could reference app1's and app2's `_colors.scss` import as so:
90
91 ```scss
92 @import 'app1/scss/colors';
93 @import 'app2/scss/colors';
94 // Or since you are in app2, you can reference its colors with a relative path.
95 @import 'colors';
96 ```
97
98 Then to compile `app2.scss` and put it in the `css` directory,
99 run the following management command (the `-g` will build a source map, which
100 is helpful for debugging CSS):
101
102 ```
103 python manage.py sass app2/static/app2/scss/app2.scss app2/static/app2/css/app2.css -g
104 ```
105
106 Or, you can compile the entire `scss` directory into
107 a corresponding `css` directory. This will traverse all subdirectories as well:
108
109 ```
110 python manage.py sass app2/static/app2/scss/ app2/static/app2/css/
111 ```
112
113 In your Django HTML template, reference the CSS file as normal:
114
115 ```html
116 {% load static %}
117 <link href="{% static 'app2/css/app2.css' %}" rel="stylesheet">
118 ```
119
120 ✨✨ **Congratulations, you are now a Django + Sass developer!** ✨✨
121
122 Now you can commit those CSS files to version control, or run `collectstatic`
123 and deploy them as normal.
124
125 For an example project layout, see `testproject/` in this repository.
126
127
128 Watch Mode
129 ----------
130
131 To have `django-sass` watch files and recompile them as they change (useful in
132 development), add the ``--watch`` flag.
133
134 ```
135 python manage.py sass app2/static/app2/scss/ app2/static/app2/css/ --watch
136 ```
137
138
139 Example: deploying compressed CSS to production
140 -----------------------------------------------
141
142 To compile minified CSS, use the `-t` flag to specify compression level (one of:
143 "expanded", "nested", "compact", "compressed"). The default is "expanded" which
144 is human-readable.
145
146 ```
147 python manage.py sass app2/static/app2/scss/ app2/static/app2/css/ -t compressed
148 ```
149
150 You may now optionally commit the CSS files to version control if so desired,
151 or omit them, whatever fits your needs better. Then run `collectsatic` as normal.
152
153 ```
154 python manage.py collectstatic
155 ```
156
157 And now proceed with deploying your files as normal.
158
159
160 Limitations
161 -----------
162
163 * `@import` statements must reference a path relative to a path in
164 `STATICFILES_FINDERS` (which will usually be an app's `static/` directory or
165 some other directory specified in `STATICFILES_DIRS`). Or they can reference a
166 relative path equal to or below the current file. It does not support
167 traversing up the filesystem (i.e. `../`).
168
169 Legal imports:
170 ```scss
171 @import 'file-from-currdir';
172 @import 'subdir/file';
173 @import 'another-app/file';
174 ```
175 Illegal imports:
176 ```scss
177 @import '../file';
178 ```
179
180 * Only supports `-g`, `-p`, and `-t` options similar to `pysassc`. Ideally
181 `django-sass` will be as similar as possible to the `pysassc` command line
182 interface.
183
184 Feel free to file an issue or make a pull request to improve any of these
185 limitations. 🐱‍💻
186
187
188 Why django-sass?
189 ----------------
190
191 Other packages such as
192 [django-libsass](https://github.com/torchbox/django-libsass) and
193 [django-sass-processor](https://github.com/jrief/django-sass-processor), while
194 nice packages, require `django-compressor` which itself depends on several other
195 packages that require compilation to install.
196
197 Installing `django-compressor` in your production web server requires a LOT of
198 extra bloat including a C compiler. It then will compile the Sass on-the-fly
199 while rendering the HTML templates. This is a wasteful use of CPU on your web
200 server.
201
202 Instead, `django-sass` lets you compile the Sass locally on your machine
203 *before* deploying, to reduce dependencies and CPU time on your production web
204 server. This helps keep things fast and simple.
205
206 * If you simply want to use Sass in development without installing a web of
207 unwanted dependencies, then `django-sass` is for you.
208 * If you don't want to deploy any processors or compressors to your production
209 server, then `django-sass` is for you.
210 * If you don't want to change the way you reference and serve static files,
211 then `django-sass` is for you.
212 * And if you want the absolute simplest installation and setup possible for
213 doing Sass, `django-sass` is for you too.
214
215 django-sass only depends on libsass (which provides pre-built wheels for
216 Windows, Mac, and Linux), and of course Django (any version).
217
218
219 Programmatically Compiling Sass
220 -------------------------------
221
222 You can also use `django-sass` in Python to programmatically compile the sass.
223 This is useful for build scripts and static site generators.
224
225 ```python
226 from django_sass import compile_sass
227
228 # Compile scss and write to output file.
229 compile_sass(
230 inpath="/path/to/file.scss",
231 outpath="/path/to/output.css",
232 output_style="compressed",
233 precision=8,
234 source_map=True
235 )
236 ```
237
238 For more advanced usage, you can specify additional sass search paths outside
239 of your Django project by using the `include_paths` argument.
240
241 ```python
242 from django_sass import compile_sass, find_static_paths
243
244 # Get Django's static paths.
245 dirs = find_static_paths()
246
247 # Add external paths.
248 dirs.append("/external/path/")
249
250 # Compile scss and write to output file.
251 compile_sass(
252 inpath="/path/to/file.scss",
253 outpath="/path/to/output.css",
254 output_style="compressed",
255 precision=8,
256 source_map=True,
257 include_paths=dirs,
258 )
259 ```
260
261 Contributing
262 ------------
263
264 To set up a development environment, first check out this repository, create a
265 venv, then:
266
267 ```
268 (myvenv)$ pip install -r requirements-dev.txt
269 ```
270
271 Before committing, run static analysis tools:
272
273 ```
274 (myvenv)$ black .
275 (myvenv)$ flake8
276 (myvenv)$ mypy
277 ```
278
279 Then run the unit tests:
280
281 ```
282 (myvenv)$ pytest
283 ```
284
285
286 Changelog
287 ---------
288
289 #### 1.1.0
290 * New: Now compiles `.sass` files as well as `.scss` files.
291 * Fix bug when input path is a file and output path does not exist.
292
293 #### 1.0.1
294 * Maintanence release, no functional changes.
295 * Add additional type hints within the codebase.
296 * Tested against Django 3.1
297 * Formatted code with `black`.
298
299 #### 1.0.0
300 * New: You can now use `django_sass` APIs directly in Python.
301 * Added unit tests.
302 * Code quality improvements.
303
304 #### 0.2.0
305 * New feature: `-g` option to build a source map (when input is a file, not a
306 directory).
307
308 #### 0.1.2
309 * Fix: Write compiled CSS files as UTF-8.
310 * Change: Default `-p` precision from 5 to 8 for better support building
311 Bootstrap CSS.
312
313 #### 0.1.1
314 * Fix: Create full file path if not exists when specifying a file output.
315
316 #### 0.1.0
317 * Initial release
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.
+0
-112
azure-pipelines.yml less more
0 # Add steps that analyze code, save build artifacts, deploy, and more:
1 # https://docs.microsoft.com/azure/devops/pipelines/languages/python
2 #
3 # NOTES:
4 #
5 # Display name of each step should be prefixed with one of the following:
6 # CR-QC: for quality control measures.
7 # CR-BUILD: for build-related tasks.
8 # CR-DEPLOY: for publication or deployment.
9 # [no prefix]: for unrelated CI setup/tooling.
10 #
11 # Use PowerShell Core for any utility scripts so they are re-usable across
12 # Windows, macOS, and Linux.
13 #
14
15
16 trigger:
17 - master
18
19
20 stages:
21 - stage: Unit_Tests
22 displayName: Unit Tests
23
24 jobs:
25 - job: pytest
26 displayName: pytest
27 pool:
28 vmImage: 'ubuntu-latest'
29 strategy:
30 matrix:
31 py3.5:
32 PYTHON_VERSION: '3.5'
33 py3.6:
34 PYTHON_VERSION: '3.6'
35 py3.7:
36 PYTHON_VERSION: '3.7'
37 py3.8:
38 PYTHON_VERSION: '3.8'
39
40 steps:
41 - task: UsePythonVersion@0
42 displayName: 'Use Python version'
43 inputs:
44 versionSpec: '$(PYTHON_VERSION)'
45 architecture: 'x64'
46
47 - script: python -m pip install -r requirements-dev.txt
48 displayName: 'CR-QC: Install from local repo'
49
50 - script: pytest ./testproject/
51 displayName: 'CR-QC: Run unit tests'
52
53 - task: PublishTestResults@2
54 displayName: 'Publish unit test report'
55 condition: succeededOrFailed()
56 inputs:
57 testResultsFiles: '**/test-*.xml'
58 testRunTitle: 'Publish test results for Python $(python.version)'
59
60 - task: PublishCodeCoverageResults@1
61 displayName: 'Publish code coverage report'
62 condition: succeededOrFailed()
63 inputs:
64 codeCoverageTool: Cobertura
65 summaryFileLocation: '$(System.DefaultWorkingDirectory)/coverage.xml'
66
67
68 - stage: Static_Analysis
69 displayName: Static Analysis
70 dependsOn: Unit_Tests
71 condition: succeeded('Unit_Tests')
72 jobs:
73 - job: lint
74 displayName: Linters
75 pool:
76 vmImage: 'ubuntu-latest'
77
78 steps:
79 - task: UsePythonVersion@0
80 displayName: 'Use Python version'
81 inputs:
82 versionSpec: '3.8'
83 architecture: 'x64'
84
85 - script: python -m pip install -r requirements-dev.txt
86 displayName: 'CR-QC: Install from local repo'
87
88 - script: flake8 .
89 displayName: 'CR-QC: Static analysis (flake8)'
90
91 - script: mypy .
92 displayName: 'CR-QC: Type check (mypy)'
93
94 - job: codecov
95 displayName: Code Coverage
96 pool:
97 vmImage: 'ubuntu-latest'
98
99 steps:
100 - task: DownloadPipelineArtifact@2
101 displayName: 'Download code coverage from current build'
102 inputs:
103 source: 'current'
104 path: '$(Agent.WorkFolder)/current-artifacts'
105 project: '$(System.TeamProjectId)'
106 pipeline: '$(System.DefinitionId)'
107
108 - pwsh: ./ci/compare-codecov.ps1 -wd $Env:WorkDir
109 displayName: 'CR-QC: Compare code coverage'
110 env:
111 WorkDir: $(Agent.WorkFolder)
+0
-108
ci/compare-codecov.ps1 less more
0 #!/usr/bin/env pwsh
1
2 <#
3 .SYNOPSIS
4 Compares code coverage percent of local coverage.xml file to master branch
5 (Azure Pipeline API).
6
7 .PARAMETER wd
8 The working directory in which to search for current coverage.xml.
9
10 .PARAMETER org
11 Name of the Azure DevOps organization where the pipeline is hosted.
12
13 .PARAMETER project
14 Name of the Azure DevOps project to which the pipeline belongs.
15
16 .PARAMETER pipeline_name
17 Name of the desired pipeline within the project. This is to support projects
18 with multiple pipelines.
19 #>
20
21
22 # ---- SETUP -------------------------------------------------------------------
23
24
25 param(
26 [string] $wd = (Get-Item (Split-Path $PSCommandPath -Parent)).Parent,
27 [string] $org = "coderedcorp",
28 [string] $project = "coderedcms",
29 [string] $pipeline_name = "django-sass"
30 )
31
32 # Hide "UI" and progress bars.
33 $ProgressPreference = "SilentlyContinue"
34
35 # API setup.
36 $ApiBase = "https://dev.azure.com/$org/$project"
37
38
39 # ---- GET CODE COVERAGE FROM RECENT BUILD -------------------------------------
40
41
42 # Get list of all recent builds.
43 $masterBuildJson = (
44 Invoke-WebRequest "$ApiBase/_apis/build/builds?branchName=refs/heads/master&api-version=5.1"
45 ).Content | ConvertFrom-Json
46
47 # Get the latest matching build ID from the list of builds.
48 foreach ($build in $masterBuildJson.value) {
49 if ($build.definition.name -eq $pipeline_name) {
50 $masterLatestId = $build.id
51 break
52 }
53 }
54
55 # Retrieve code coverage for this build ID.
56 $masterCoverageJson = (
57 Invoke-WebRequest "$ApiBase/_apis/test/codecoverage?buildId=$masterLatestId&api-version=5.1-preview.1"
58 ).Content | ConvertFrom-Json
59 foreach ($cov in $masterCoverageJson.coverageData.coverageStats) {
60 if ($cov.label -eq "Lines") {
61 $masterlinerate = [math]::Round(($cov.covered / $cov.total) * 100, 2)
62 }
63 }
64
65
66 # ---- GET COVERAGE FROM LOCAL RUN ---------------------------------------------
67
68
69 # Get current code coverage from coverage.xml file.
70 $coveragePath = Get-ChildItem -Recurse -Filter "coverage.xml" $wd
71 if (Test-Path -Path $coveragePath) {
72 [xml]$BranchXML = Get-Content $coveragePath
73 }
74 else {
75 Write-Host -ForegroundColor Red `
76 "No code coverage from this build. Is pytest configured to output code coverage? Exiting."
77 exit 1
78 }
79 $branchlinerate = [math]::Round([decimal]$BranchXML.coverage.'line-rate' * 100, 2)
80
81
82 # ---- PRINT OUTPUT ------------------------------------------------------------
83
84
85 Write-Output ""
86 Write-Output "Master line coverage rate: $masterlinerate%"
87 Write-Output "Branch line coverage rate: $branchlinerate%"
88
89 if ($masterlinerate -eq 0) {
90 $change = "Infinite"
91 }
92 else {
93 $change = [math]::Abs($branchlinerate - $masterlinerate)
94 }
95
96 if ($branchlinerate -gt $masterlinerate) {
97 Write-Host "Coverage increased by $change% 😀" -ForegroundColor Green
98 exit 0
99 }
100 elseif ($branchlinerate -eq $masterlinerate) {
101 Write-Host "Coverage has not changed." -ForegroundColor Green
102 exit 0
103 }
104 else {
105 Write-Host "Coverage decreased by $change% 😭" -ForegroundColor Red
106 exit 4
107 }
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 Metadata-Version: 2.1
1 Name: django-sass
2 Version: 1.1.0
3 Summary: The absolute simplest way to use Sass with Django. Pure Python, minimal dependencies, and no special configuration required!
4 Home-page: https://github.com/coderedcorp/django-sass
5 Author: CodeRed LLC
6 Author-email: info@coderedcorp.com
7 License: BSD license
8 Classifier: Environment :: Web Environment
9 Classifier: Framework :: Django :: 2.0
10 Classifier: Framework :: Django :: 2.1
11 Classifier: Framework :: Django :: 2.2
12 Classifier: Framework :: Django :: 3.0
13 Classifier: Framework :: Django :: 3.1
14 Classifier: Framework :: Django
15 Classifier: Intended Audience :: Developers
16 Classifier: License :: OSI Approved :: BSD License
17 Classifier: Natural Language :: English
18 Classifier: Programming Language :: Python :: 3 :: Only
19 Classifier: Programming Language :: Python :: 3
20 Classifier: Programming Language :: Python :: 3.6
21 Classifier: Programming Language :: Python :: 3.7
22 Classifier: Programming Language :: Python :: 3.8
23 Classifier: Programming Language :: Python :: 3.9
24 Description-Content-Type: text/markdown
25 License-File: LICENSE
26
27 django-sass
28 ===========
29
30 The absolute simplest way to use [Sass](https://sass-lang.com/) with Django.
31 Pure Python, minimal dependencies, and no special configuration required.
32
33 [Source code on GitHub](https://github.com/coderedcorp/django-sass)
34
35
36 Status
37 ------
38
39 | | |
40 |------------------------|----------------------|
41 | 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/) |
42 | 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) |
43
44
45 Installation
46 ------------
47
48 1. Install from pip.
49
50 ```
51 pip install django-sass
52 ```
53
54 2. Add to your `INSTALLED_APPS` (you only need to do this in a dev environment,
55 you would not want this in your production settings file, although it adds zero
56 overhead):
57
58 ```python
59 INSTALLED_APPS = [
60 ...,
61 'django_sass',
62 ]
63 ```
64
65 3. Congratulations, you're done 😀
66
67
68 Usage
69 -----
70
71 In your app's static files, use Sass as normal. The only difference is that
72 you can **not** traverse upwards using `../` in `@import` statements. For example:
73
74 ```
75 app1/
76 |- static/
77 |- app1/
78 |- scss/
79 |- _colors.scss
80 |- app1.scss
81 app2/
82 |- static/
83 |- app2/
84 |- scss/
85 |- _colors.scss
86 |- app2.scss
87 ```
88
89 In `app2.scss` you could reference app1's and app2's `_colors.scss` import as so:
90
91 ```scss
92 @import 'app1/scss/colors';
93 @import 'app2/scss/colors';
94 // Or since you are in app2, you can reference its colors with a relative path.
95 @import 'colors';
96 ```
97
98 Then to compile `app2.scss` and put it in the `css` directory,
99 run the following management command (the `-g` will build a source map, which
100 is helpful for debugging CSS):
101
102 ```
103 python manage.py sass app2/static/app2/scss/app2.scss app2/static/app2/css/app2.css -g
104 ```
105
106 Or, you can compile the entire `scss` directory into
107 a corresponding `css` directory. This will traverse all subdirectories as well:
108
109 ```
110 python manage.py sass app2/static/app2/scss/ app2/static/app2/css/
111 ```
112
113 In your Django HTML template, reference the CSS file as normal:
114
115 ```html
116 {% load static %}
117 <link href="{% static 'app2/css/app2.css' %}" rel="stylesheet">
118 ```
119
120 ✨✨ **Congratulations, you are now a Django + Sass developer!** ✨✨
121
122 Now you can commit those CSS files to version control, or run `collectstatic`
123 and deploy them as normal.
124
125 For an example project layout, see `testproject/` in this repository.
126
127
128 Watch Mode
129 ----------
130
131 To have `django-sass` watch files and recompile them as they change (useful in
132 development), add the ``--watch`` flag.
133
134 ```
135 python manage.py sass app2/static/app2/scss/ app2/static/app2/css/ --watch
136 ```
137
138
139 Example: deploying compressed CSS to production
140 -----------------------------------------------
141
142 To compile minified CSS, use the `-t` flag to specify compression level (one of:
143 "expanded", "nested", "compact", "compressed"). The default is "expanded" which
144 is human-readable.
145
146 ```
147 python manage.py sass app2/static/app2/scss/ app2/static/app2/css/ -t compressed
148 ```
149
150 You may now optionally commit the CSS files to version control if so desired,
151 or omit them, whatever fits your needs better. Then run `collectsatic` as normal.
152
153 ```
154 python manage.py collectstatic
155 ```
156
157 And now proceed with deploying your files as normal.
158
159
160 Limitations
161 -----------
162
163 * `@import` statements must reference a path relative to a path in
164 `STATICFILES_FINDERS` (which will usually be an app's `static/` directory or
165 some other directory specified in `STATICFILES_DIRS`). Or they can reference a
166 relative path equal to or below the current file. It does not support
167 traversing up the filesystem (i.e. `../`).
168
169 Legal imports:
170 ```scss
171 @import 'file-from-currdir';
172 @import 'subdir/file';
173 @import 'another-app/file';
174 ```
175 Illegal imports:
176 ```scss
177 @import '../file';
178 ```
179
180 * Only supports `-g`, `-p`, and `-t` options similar to `pysassc`. Ideally
181 `django-sass` will be as similar as possible to the `pysassc` command line
182 interface.
183
184 Feel free to file an issue or make a pull request to improve any of these
185 limitations. 🐱‍💻
186
187
188 Why django-sass?
189 ----------------
190
191 Other packages such as
192 [django-libsass](https://github.com/torchbox/django-libsass) and
193 [django-sass-processor](https://github.com/jrief/django-sass-processor), while
194 nice packages, require `django-compressor` which itself depends on several other
195 packages that require compilation to install.
196
197 Installing `django-compressor` in your production web server requires a LOT of
198 extra bloat including a C compiler. It then will compile the Sass on-the-fly
199 while rendering the HTML templates. This is a wasteful use of CPU on your web
200 server.
201
202 Instead, `django-sass` lets you compile the Sass locally on your machine
203 *before* deploying, to reduce dependencies and CPU time on your production web
204 server. This helps keep things fast and simple.
205
206 * If you simply want to use Sass in development without installing a web of
207 unwanted dependencies, then `django-sass` is for you.
208 * If you don't want to deploy any processors or compressors to your production
209 server, then `django-sass` is for you.
210 * If you don't want to change the way you reference and serve static files,
211 then `django-sass` is for you.
212 * And if you want the absolute simplest installation and setup possible for
213 doing Sass, `django-sass` is for you too.
214
215 django-sass only depends on libsass (which provides pre-built wheels for
216 Windows, Mac, and Linux), and of course Django (any version).
217
218
219 Programmatically Compiling Sass
220 -------------------------------
221
222 You can also use `django-sass` in Python to programmatically compile the sass.
223 This is useful for build scripts and static site generators.
224
225 ```python
226 from django_sass import compile_sass
227
228 # Compile scss and write to output file.
229 compile_sass(
230 inpath="/path/to/file.scss",
231 outpath="/path/to/output.css",
232 output_style="compressed",
233 precision=8,
234 source_map=True
235 )
236 ```
237
238 For more advanced usage, you can specify additional sass search paths outside
239 of your Django project by using the `include_paths` argument.
240
241 ```python
242 from django_sass import compile_sass, find_static_paths
243
244 # Get Django's static paths.
245 dirs = find_static_paths()
246
247 # Add external paths.
248 dirs.append("/external/path/")
249
250 # Compile scss and write to output file.
251 compile_sass(
252 inpath="/path/to/file.scss",
253 outpath="/path/to/output.css",
254 output_style="compressed",
255 precision=8,
256 source_map=True,
257 include_paths=dirs,
258 )
259 ```
260
261 Contributing
262 ------------
263
264 To set up a development environment, first check out this repository, create a
265 venv, then:
266
267 ```
268 (myvenv)$ pip install -r requirements-dev.txt
269 ```
270
271 Before committing, run static analysis tools:
272
273 ```
274 (myvenv)$ black .
275 (myvenv)$ flake8
276 (myvenv)$ mypy
277 ```
278
279 Then run the unit tests:
280
281 ```
282 (myvenv)$ pytest
283 ```
284
285
286 Changelog
287 ---------
288
289 #### 1.1.0
290 * New: Now compiles `.sass` files as well as `.scss` files.
291 * Fix bug when input path is a file and output path does not exist.
292
293 #### 1.0.1
294 * Maintanence release, no functional changes.
295 * Add additional type hints within the codebase.
296 * Tested against Django 3.1
297 * Formatted code with `black`.
298
299 #### 1.0.0
300 * New: You can now use `django_sass` APIs directly in Python.
301 * Added unit tests.
302 * Code quality improvements.
303
304 #### 0.2.0
305 * New feature: `-g` option to build a source map (when input is a file, not a
306 directory).
307
308 #### 0.1.2
309 * Fix: Write compiled CSS files as UTF-8.
310 * Change: Default `-p` precision from 5 to 8 for better support building
311 Bootstrap CSS.
312
313 #### 0.1.1
314 * Fix: Create full file path if not exists when specifying a file output.
315
316 #### 0.1.0
317 * Initial release
0 LICENSE
1 MANIFEST.in
2 README.md
3 pyproject.toml
4 requirements-dev.txt
5 setup.cfg
6 setup.py
7 django_sass/__init__.py
8 django_sass/apps.py
9 django_sass.egg-info/PKG-INFO
10 django_sass.egg-info/SOURCES.txt
11 django_sass.egg-info/dependency_links.txt
12 django_sass.egg-info/requires.txt
13 django_sass.egg-info/top_level.txt
14 django_sass/management/commands/sass.py
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
910 junit_family = xunit2
1011 addopts = --cov django_sass --cov-report html --cov-report xml --junitxml junit/test-results.xml ./testproject/
1112 python_files = tests.py test_*.py
12 filterwarnings =
13 ignore
14 default:::django_sass.*
13 filterwarnings =
14 ignore
15 default:::django_sass.*
16
17 [egg_info]
18 tag_build =
19 tag_date = 0
20
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 )
+0
-0
testproject/app1/__init__.py less more
(Empty file)
+0
-5
testproject/app1/apps.py less more
0 from django.apps import AppConfig
1
2
3 class App1Config(AppConfig):
4 name = 'app1'
+0
-5
testproject/app1/static/app1/scss/_include.scss less more
0 /* Tests: app1/scss/_include.scss */
1
2 .app1-include {
3 color: red;
4 }
+0
-0
testproject/app2/__init__.py less more
(Empty file)
+0
-5
testproject/app2/apps.py less more
0 from django.apps import AppConfig
1
2
3 class App2Config(AppConfig):
4 name = 'app2'
+0
-5
testproject/app2/static/app2/scss/_samedir.scss less more
0 /* Tests: app2/scss/_samedir.scss */
1
2 .app2-samedir {
3 color: red;
4 }
+0
-5
testproject/app2/static/app2/scss/subdir/_subdir.scss less more
0 /* Tests: app2/scss/subdir/_subdir.scss */
1
2 .app2-subdir {
3 color: red;
4 }
+0
-20
testproject/app2/static/app2/scss/test.scss less more
0 // app1/scss/_include.scss
1 @import "app1/scss/include";
2
3 // app2/_samedir.scss
4 @import "app2/scss/samedir";
5
6 // app2/subdir/_subdir.scss
7 @import "app2/scss/subdir/subdir";
8
9 // _samedir.scss
10 @import "samedir";
11
12 // subdir/_subdir.scss
13 @import "subdir/subdir";
14
15 // test.scss
16 /* Tests: app2/scss/test.scss */
17 .test {
18 color: red;
19 }
+0
-21
testproject/manage.py less more
0 #!/usr/bin/env python
1 """Django's command-line utility for administrative tasks."""
2 import os
3 import sys
4
5
6 def main():
7 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'testproject.settings')
8 try:
9 from django.core.management import execute_from_command_line
10 except ImportError as exc:
11 raise ImportError(
12 "Couldn't import Django. Are you sure it's installed and "
13 "available on your PYTHONPATH environment variable? Did you "
14 "forget to activate a virtual environment?"
15 ) from exc
16 execute_from_command_line(sys.argv)
17
18
19 if __name__ == '__main__':
20 main()
+0
-2
testproject/requirements.txt less more
0 -e ../ # django-sass locally
1 django
+0
-0
testproject/testproject/__init__.py less more
(Empty file)
+0
-105
testproject/testproject/settings.py less more
0 """
1 Django settings for testproject project.
2
3 Generated by 'django-admin startproject' using Django 2.2.1.
4
5 For more information on this file, see
6 https://docs.djangoproject.com/en/2.2/topics/settings/
7
8 For the full list of settings and their values, see
9 https://docs.djangoproject.com/en/2.2/ref/settings/
10 """
11
12 import os
13
14 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
15 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
16
17
18 # Quick-start development settings - unsuitable for production
19 # See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
20
21 # SECURITY WARNING: keep the secret key used in production secret!
22 SECRET_KEY = '-_wl=tq26(*wyvfza+ncg_436c53pu81d=07j62+vm5y2pc)f^'
23
24 # SECURITY WARNING: don't run with debug turned on in production!
25 DEBUG = True
26
27 ALLOWED_HOSTS = []
28
29
30 # Application definition
31
32 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',
43 ]
44
45 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',
53 ]
54
55 ROOT_URLCONF = 'testproject.urls'
56
57 TEMPLATES = [
58 {
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',
68 ],
69 },
70 },
71 ]
72
73 WSGI_APPLICATION = 'testproject.wsgi.application'
74
75
76 # Database
77 # https://docs.djangoproject.com/en/2.2/ref/settings/#databases
78
79 DATABASES = {
80 'default': {
81 'ENGINE': 'django.db.backends.sqlite3',
82 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
83 }
84 }
85
86
87 # Internationalization
88 # https://docs.djangoproject.com/en/2.2/topics/i18n/
89
90 LANGUAGE_CODE = 'en-us'
91
92 TIME_ZONE = 'UTC'
93
94 USE_I18N = True
95
96 USE_L10N = True
97
98 USE_TZ = True
99
100
101 # Static files (CSS, JavaScript, Images)
102 # https://docs.djangoproject.com/en/2.2/howto/static-files/
103
104 STATIC_URL = '/static/'
+0
-21
testproject/testproject/urls.py less more
0 """testproject URL Configuration
1
2 The `urlpatterns` list routes URLs to views. For more information please see:
3 https://docs.djangoproject.com/en/2.2/topics/http/urls/
4 Examples:
5 Function views
6 1. Add an import: from my_app import views
7 2. Add a URL to urlpatterns: path('', views.home, name='home')
8 Class-based views
9 1. Add an import: from other_app.views import Home
10 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
11 Including another URLconf
12 1. Import the include() function: from django.urls import include, path
13 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
14 """
15 from django.contrib import admin
16 from django.urls import path
17
18 urlpatterns = [
19 path('admin/', admin.site.urls),
20 ]
+0
-16
testproject/testproject/wsgi.py less more
0 """
1 WSGI config for testproject project.
2
3 It exposes the WSGI callable as a module-level variable named ``application``.
4
5 For more information on this file, see
6 https://docs.djangoproject.com/en/2.2/howto/deployment/wsgi/
7 """
8
9 import os
10
11 from django.core.wsgi import get_wsgi_application
12
13 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'testproject.settings')
14
15 application = get_wsgi_application()
+0
-118
testproject/tests.py less more
0 import os
1 import shutil
2 import subprocess
3 import time
4 import unittest
5
6 from django_sass import find_static_paths, find_static_scss
7
8
9 THIS_DIR = os.path.dirname(os.path.abspath(__file__))
10
11
12 class TestDjangoSass(unittest.TestCase):
13
14 def setUp(self):
15 self.outdir = os.path.join(THIS_DIR, "out")
16
17 def tearDown(self):
18 # Clean up output files
19 shutil.rmtree(self.outdir, ignore_errors=True)
20
21 def assert_output(self, real_outpath: str):
22 # Verify that the output file exists.
23 print(real_outpath)
24 self.assertTrue(os.path.isfile(real_outpath))
25
26 # Verify that the file contains expected output from all sass files.
27 with open(real_outpath, encoding="utf8") as f:
28 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)
33
34 def test_find_static_paths(self):
35 paths = find_static_paths()
36 # Assert that it found both of our apps' static dirs.
37 self.assertTrue(os.path.join(THIS_DIR, "app1", "static") in paths)
38 self.assertTrue(os.path.join(THIS_DIR, "app2", "static") in paths)
39
40 def test_find_static_sass(self):
41 files = find_static_scss()
42 # Assert that it found all of our scss files.
43 self.assertTrue(
44 os.path.join(THIS_DIR, "app1", "static", "app1", "scss", "_include.scss") in files)
45 self.assertTrue(
46 os.path.join(THIS_DIR, "app2", "static", "app2", "scss", "_samedir.scss") in files)
47 self.assertTrue(
48 os.path.join(THIS_DIR, "app2", "static", "app2", "scss", "test.scss") in files)
49 self.assertTrue(
50 os.path.join(THIS_DIR, "app2", "static", "app2", "scss", "subdir", "_subdir.scss")
51 in files)
52
53 def test_cli(self):
54 # Input and output paths relative to django static dirs.
55 inpath = os.path.join("app2", "static", "app2", "scss", "test.scss")
56 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)
65
66 def test_cli_dir(self):
67 # Input and output paths relative to django static dirs.
68 inpath = os.path.join("app2", "static", "app2", "scss")
69 outpath = self.outdir
70 # Expected output path on filesystem.
71 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)
80
81 def test_cli_srcmap(self):
82 # Input and output paths relative to django static dirs.
83 inpath = os.path.join("app2", "static", "app2", "scss", "test.scss")
84 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")))
94
95 @unittest.skip
96 def test_cli_watch(self):
97 # Input and output paths relative to django static dirs.
98 inpath = os.path.join("app2", "static", "app2", "scss", "test.scss")
99 outpath = os.path.join(self.outdir, "test.css")
100 # Command to run
101 cmd = ["python", "manage.py", "sass", "--watch", inpath, outpath]
102 # Run the management command on testproject.
103 proc = subprocess.Popen(cmd, cwd=THIS_DIR)
104 time.sleep(0.5)
105 # TODO: This test is not working. Do not know how to intentionally send
106 # a KeyboardInterrupt to the subprocess without having unittest/pytest
107 # immediately die when it sees the interrupt.
108 try:
109 proc.send_signal(subprocess.signal.CTRL_C_EVENT)
110 except KeyboardInterrupt:
111 # We actually want the keyboard interrupt.
112 pass
113 returncode = proc.wait()
114 # Verify the process exited cleanly.
115 self.assertEqual(returncode, 0)
116 # Assert output is correct.
117 self.assert_output(outpath)