Codebase list django-sass / 032ef27b-1415-4d50-b82e-f587cf06656e/upstream/master
Import upstream version 1.1.0 Debian Janitor 2 years ago
33 changed file(s) with 789 addition(s) and 1003 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 Description: django-sass
9 ===========
10
11 The absolute simplest way to use [Sass](https://sass-lang.com/) with Django.
12 Pure Python, minimal dependencies, and no special configuration required.
13
14 [Source code on GitHub](https://github.com/coderedcorp/django-sass)
15
16
17 Status
18 ------
19
20 | | |
21 |------------------------|----------------------|
22 | 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/) |
23 | 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) |
24
25
26 Installation
27 ------------
28
29 1. Install from pip.
30
31 ```
32 pip install django-sass
33 ```
34
35 2. Add to your `INSTALLED_APPS` (you only need to do this in a dev environment,
36 you would not want this in your production settings file, although it adds zero
37 overhead):
38
39 ```python
40 INSTALLED_APPS = [
41 ...,
42 'django_sass',
43 ]
44 ```
45
46 3. Congratulations, you're done 😀
47
48
49 Usage
50 -----
51
52 In your app's static files, use Sass as normal. The only difference is that
53 you can **not** traverse upwards using `../` in `@import` statements. For example:
54
55 ```
56 app1/
57 |- static/
58 |- app1/
59 |- scss/
60 |- _colors.scss
61 |- app1.scss
62 app2/
63 |- static/
64 |- app2/
65 |- scss/
66 |- _colors.scss
67 |- app2.scss
68 ```
69
70 In `app2.scss` you could reference app1's and app2's `_colors.scss` import as so:
71
72 ```scss
73 @import 'app1/scss/colors';
74 @import 'app2/scss/colors';
75 // Or since you are in app2, you can reference its colors with a relative path.
76 @import 'colors';
77 ```
78
79 Then to compile `app2.scss` and put it in the `css` directory,
80 run the following management command (the `-g` will build a source map, which
81 is helpful for debugging CSS):
82
83 ```
84 python manage.py sass app2/static/app2/scss/app2.scss app2/static/app2/css/app2.css -g
85 ```
86
87 Or, you can compile the entire `scss` directory into
88 a corresponding `css` directory. This will traverse all subdirectories as well:
89
90 ```
91 python manage.py sass app2/static/app2/scss/ app2/static/app2/css/
92 ```
93
94 In your Django HTML template, reference the CSS file as normal:
95
96 ```html
97 {% load static %}
98 <link href="{% static 'app2/css/app2.css' %}" rel="stylesheet">
99 ```
100
101 ✨✨ **Congratulations, you are now a Django + Sass developer!** ✨✨
102
103 Now you can commit those CSS files to version control, or run `collectstatic`
104 and deploy them as normal.
105
106 For an example project layout, see `testproject/` in this repository.
107
108
109 Watch Mode
110 ----------
111
112 To have `django-sass` watch files and recompile them as they change (useful in
113 development), add the ``--watch`` flag.
114
115 ```
116 python manage.py sass app2/static/app2/scss/ app2/static/app2/css/ --watch
117 ```
118
119
120 Example: deploying compressed CSS to production
121 -----------------------------------------------
122
123 To compile minified CSS, use the `-t` flag to specify compression level (one of:
124 "expanded", "nested", "compact", "compressed"). The default is "expanded" which
125 is human-readable.
126
127 ```
128 python manage.py sass app2/static/app2/scss/ app2/static/app2/css/ -t compressed
129 ```
130
131 You may now optionally commit the CSS files to version control if so desired,
132 or omit them, whatever fits your needs better. Then run `collectsatic` as normal.
133
134 ```
135 python manage.py collectstatic
136 ```
137
138 And now proceed with deploying your files as normal.
139
140
141 Limitations
142 -----------
143
144 * `@import` statements must reference a path relative to a path in
145 `STATICFILES_FINDERS` (which will usually be an app's `static/` directory or
146 some other directory specified in `STATICFILES_DIRS`). Or they can reference a
147 relative path equal to or below the current file. It does not support
148 traversing up the filesystem (i.e. `../`).
149
150 Legal imports:
151 ```scss
152 @import 'file-from-currdir';
153 @import 'subdir/file';
154 @import 'another-app/file';
155 ```
156 Illegal imports:
157 ```scss
158 @import '../file';
159 ```
160
161 * Only supports `-g`, `-p`, and `-t` options similar to `pysassc`. Ideally
162 `django-sass` will be as similar as possible to the `pysassc` command line
163 interface.
164
165 Feel free to file an issue or make a pull request to improve any of these
166 limitations. 🐱‍💻
167
168
169 Why django-sass?
170 ----------------
171
172 Other packages such as
173 [django-libsass](https://github.com/torchbox/django-libsass) and
174 [django-sass-processor](https://github.com/jrief/django-sass-processor), while
175 nice packages, require `django-compressor` which itself depends on several other
176 packages that require compilation to install.
177
178 Installing `django-compressor` in your production web server requires a LOT of
179 extra bloat including a C compiler. It then will compile the Sass on-the-fly
180 while rendering the HTML templates. This is a wasteful use of CPU on your web
181 server.
182
183 Instead, `django-sass` lets you compile the Sass locally on your machine
184 *before* deploying, to reduce dependencies and CPU time on your production web
185 server. This helps keep things fast and simple.
186
187 * If you simply want to use Sass in development without installing a web of
188 unwanted dependencies, then `django-sass` is for you.
189 * If you don't want to deploy any processors or compressors to your production
190 server, then `django-sass` is for you.
191 * If you don't want to change the way you reference and serve static files,
192 then `django-sass` is for you.
193 * And if you want the absolute simplest installation and setup possible for
194 doing Sass, `django-sass` is for you too.
195
196 django-sass only depends on libsass (which provides pre-built wheels for
197 Windows, Mac, and Linux), and of course Django (any version).
198
199
200 Programmatically Compiling Sass
201 -------------------------------
202
203 You can also use `django-sass` in Python to programmatically compile the sass.
204 This is useful for build scripts and static site generators.
205
206 ```python
207 from django_sass import compile_sass
208
209 # Compile scss and write to output file.
210 compile_sass(
211 inpath="/path/to/file.scss",
212 outpath="/path/to/output.css",
213 output_style="compressed",
214 precision=8,
215 source_map=True
216 )
217 ```
218
219 For more advanced usage, you can specify additional sass search paths outside
220 of your Django project by using the `include_paths` argument.
221
222 ```python
223 from django_sass import compile_sass, find_static_paths
224
225 # Get Django's static paths.
226 dirs = find_static_paths()
227
228 # Add external paths.
229 dirs.append("/external/path/")
230
231 # Compile scss and write to output file.
232 compile_sass(
233 inpath="/path/to/file.scss",
234 outpath="/path/to/output.css",
235 output_style="compressed",
236 precision=8,
237 source_map=True,
238 include_paths=dirs,
239 )
240 ```
241
242 Contributing
243 ------------
244
245 To set up a development environment, first check out this repository, create a
246 venv, then:
247
248 ```
249 (myvenv)$ pip install -r requirements-dev.txt
250 ```
251
252 Before committing, run static analysis tools:
253
254 ```
255 (myvenv)$ black .
256 (myvenv)$ flake8
257 (myvenv)$ mypy
258 ```
259
260 Then run the unit tests:
261
262 ```
263 (myvenv)$ pytest
264 ```
265
266
267 Changelog
268 ---------
269
270 #### 1.1.0
271 * New: Now compiles `.sass` files as well as `.scss` files.
272 * Fix bug when input path is a file and output path does not exist.
273
274 #### 1.0.1
275 * Maintanence release, no functional changes.
276 * Add additional type hints within the codebase.
277 * Tested against Django 3.1
278 * Formatted code with `black`.
279
280 #### 1.0.0
281 * New: You can now use `django_sass` APIs directly in Python.
282 * Added unit tests.
283 * Code quality improvements.
284
285 #### 0.2.0
286 * New feature: `-g` option to build a source map (when input is a file, not a
287 directory).
288
289 #### 0.1.2
290 * Fix: Write compiled CSS files as UTF-8.
291 * Change: Default `-p` precision from 5 to 8 for better support building
292 Bootstrap CSS.
293
294 #### 0.1.1
295 * Fix: Create full file path if not exists when specifying a file output.
296
297 #### 0.1.0
298 * Initial release
299
300 Platform: UNKNOWN
301 Classifier: Environment :: Web Environment
302 Classifier: Framework :: Django :: 2.0
303 Classifier: Framework :: Django :: 2.1
304 Classifier: Framework :: Django :: 2.2
305 Classifier: Framework :: Django :: 3.0
306 Classifier: Framework :: Django :: 3.1
307 Classifier: Framework :: Django
308 Classifier: Intended Audience :: Developers
309 Classifier: License :: OSI Approved :: BSD License
310 Classifier: Natural Language :: English
311 Classifier: Programming Language :: Python :: 3 :: Only
312 Classifier: Programming Language :: Python :: 3
313 Classifier: Programming Language :: Python :: 3.6
314 Classifier: Programming Language :: Python :: 3.7
315 Classifier: Programming Language :: Python :: 3.8
316 Classifier: Programming Language :: Python :: 3.9
317 Description-Content-Type: text/markdown
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 Description: django-sass
9 ===========
10
11 The absolute simplest way to use [Sass](https://sass-lang.com/) with Django.
12 Pure Python, minimal dependencies, and no special configuration required.
13
14 [Source code on GitHub](https://github.com/coderedcorp/django-sass)
15
16
17 Status
18 ------
19
20 | | |
21 |------------------------|----------------------|
22 | 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/) |
23 | 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) |
24
25
26 Installation
27 ------------
28
29 1. Install from pip.
30
31 ```
32 pip install django-sass
33 ```
34
35 2. Add to your `INSTALLED_APPS` (you only need to do this in a dev environment,
36 you would not want this in your production settings file, although it adds zero
37 overhead):
38
39 ```python
40 INSTALLED_APPS = [
41 ...,
42 'django_sass',
43 ]
44 ```
45
46 3. Congratulations, you're done 😀
47
48
49 Usage
50 -----
51
52 In your app's static files, use Sass as normal. The only difference is that
53 you can **not** traverse upwards using `../` in `@import` statements. For example:
54
55 ```
56 app1/
57 |- static/
58 |- app1/
59 |- scss/
60 |- _colors.scss
61 |- app1.scss
62 app2/
63 |- static/
64 |- app2/
65 |- scss/
66 |- _colors.scss
67 |- app2.scss
68 ```
69
70 In `app2.scss` you could reference app1's and app2's `_colors.scss` import as so:
71
72 ```scss
73 @import 'app1/scss/colors';
74 @import 'app2/scss/colors';
75 // Or since you are in app2, you can reference its colors with a relative path.
76 @import 'colors';
77 ```
78
79 Then to compile `app2.scss` and put it in the `css` directory,
80 run the following management command (the `-g` will build a source map, which
81 is helpful for debugging CSS):
82
83 ```
84 python manage.py sass app2/static/app2/scss/app2.scss app2/static/app2/css/app2.css -g
85 ```
86
87 Or, you can compile the entire `scss` directory into
88 a corresponding `css` directory. This will traverse all subdirectories as well:
89
90 ```
91 python manage.py sass app2/static/app2/scss/ app2/static/app2/css/
92 ```
93
94 In your Django HTML template, reference the CSS file as normal:
95
96 ```html
97 {% load static %}
98 <link href="{% static 'app2/css/app2.css' %}" rel="stylesheet">
99 ```
100
101 ✨✨ **Congratulations, you are now a Django + Sass developer!** ✨✨
102
103 Now you can commit those CSS files to version control, or run `collectstatic`
104 and deploy them as normal.
105
106 For an example project layout, see `testproject/` in this repository.
107
108
109 Watch Mode
110 ----------
111
112 To have `django-sass` watch files and recompile them as they change (useful in
113 development), add the ``--watch`` flag.
114
115 ```
116 python manage.py sass app2/static/app2/scss/ app2/static/app2/css/ --watch
117 ```
118
119
120 Example: deploying compressed CSS to production
121 -----------------------------------------------
122
123 To compile minified CSS, use the `-t` flag to specify compression level (one of:
124 "expanded", "nested", "compact", "compressed"). The default is "expanded" which
125 is human-readable.
126
127 ```
128 python manage.py sass app2/static/app2/scss/ app2/static/app2/css/ -t compressed
129 ```
130
131 You may now optionally commit the CSS files to version control if so desired,
132 or omit them, whatever fits your needs better. Then run `collectsatic` as normal.
133
134 ```
135 python manage.py collectstatic
136 ```
137
138 And now proceed with deploying your files as normal.
139
140
141 Limitations
142 -----------
143
144 * `@import` statements must reference a path relative to a path in
145 `STATICFILES_FINDERS` (which will usually be an app's `static/` directory or
146 some other directory specified in `STATICFILES_DIRS`). Or they can reference a
147 relative path equal to or below the current file. It does not support
148 traversing up the filesystem (i.e. `../`).
149
150 Legal imports:
151 ```scss
152 @import 'file-from-currdir';
153 @import 'subdir/file';
154 @import 'another-app/file';
155 ```
156 Illegal imports:
157 ```scss
158 @import '../file';
159 ```
160
161 * Only supports `-g`, `-p`, and `-t` options similar to `pysassc`. Ideally
162 `django-sass` will be as similar as possible to the `pysassc` command line
163 interface.
164
165 Feel free to file an issue or make a pull request to improve any of these
166 limitations. 🐱‍💻
167
168
169 Why django-sass?
170 ----------------
171
172 Other packages such as
173 [django-libsass](https://github.com/torchbox/django-libsass) and
174 [django-sass-processor](https://github.com/jrief/django-sass-processor), while
175 nice packages, require `django-compressor` which itself depends on several other
176 packages that require compilation to install.
177
178 Installing `django-compressor` in your production web server requires a LOT of
179 extra bloat including a C compiler. It then will compile the Sass on-the-fly
180 while rendering the HTML templates. This is a wasteful use of CPU on your web
181 server.
182
183 Instead, `django-sass` lets you compile the Sass locally on your machine
184 *before* deploying, to reduce dependencies and CPU time on your production web
185 server. This helps keep things fast and simple.
186
187 * If you simply want to use Sass in development without installing a web of
188 unwanted dependencies, then `django-sass` is for you.
189 * If you don't want to deploy any processors or compressors to your production
190 server, then `django-sass` is for you.
191 * If you don't want to change the way you reference and serve static files,
192 then `django-sass` is for you.
193 * And if you want the absolute simplest installation and setup possible for
194 doing Sass, `django-sass` is for you too.
195
196 django-sass only depends on libsass (which provides pre-built wheels for
197 Windows, Mac, and Linux), and of course Django (any version).
198
199
200 Programmatically Compiling Sass
201 -------------------------------
202
203 You can also use `django-sass` in Python to programmatically compile the sass.
204 This is useful for build scripts and static site generators.
205
206 ```python
207 from django_sass import compile_sass
208
209 # Compile scss and write to output file.
210 compile_sass(
211 inpath="/path/to/file.scss",
212 outpath="/path/to/output.css",
213 output_style="compressed",
214 precision=8,
215 source_map=True
216 )
217 ```
218
219 For more advanced usage, you can specify additional sass search paths outside
220 of your Django project by using the `include_paths` argument.
221
222 ```python
223 from django_sass import compile_sass, find_static_paths
224
225 # Get Django's static paths.
226 dirs = find_static_paths()
227
228 # Add external paths.
229 dirs.append("/external/path/")
230
231 # Compile scss and write to output file.
232 compile_sass(
233 inpath="/path/to/file.scss",
234 outpath="/path/to/output.css",
235 output_style="compressed",
236 precision=8,
237 source_map=True,
238 include_paths=dirs,
239 )
240 ```
241
242 Contributing
243 ------------
244
245 To set up a development environment, first check out this repository, create a
246 venv, then:
247
248 ```
249 (myvenv)$ pip install -r requirements-dev.txt
250 ```
251
252 Before committing, run static analysis tools:
253
254 ```
255 (myvenv)$ black .
256 (myvenv)$ flake8
257 (myvenv)$ mypy
258 ```
259
260 Then run the unit tests:
261
262 ```
263 (myvenv)$ pytest
264 ```
265
266
267 Changelog
268 ---------
269
270 #### 1.1.0
271 * New: Now compiles `.sass` files as well as `.scss` files.
272 * Fix bug when input path is a file and output path does not exist.
273
274 #### 1.0.1
275 * Maintanence release, no functional changes.
276 * Add additional type hints within the codebase.
277 * Tested against Django 3.1
278 * Formatted code with `black`.
279
280 #### 1.0.0
281 * New: You can now use `django_sass` APIs directly in Python.
282 * Added unit tests.
283 * Code quality improvements.
284
285 #### 0.2.0
286 * New feature: `-g` option to build a source map (when input is a file, not a
287 directory).
288
289 #### 0.1.2
290 * Fix: Write compiled CSS files as UTF-8.
291 * Change: Default `-p` precision from 5 to 8 for better support building
292 Bootstrap CSS.
293
294 #### 0.1.1
295 * Fix: Create full file path if not exists when specifying a file output.
296
297 #### 0.1.0
298 * Initial release
299
300 Platform: UNKNOWN
301 Classifier: Environment :: Web Environment
302 Classifier: Framework :: Django :: 2.0
303 Classifier: Framework :: Django :: 2.1
304 Classifier: Framework :: Django :: 2.2
305 Classifier: Framework :: Django :: 3.0
306 Classifier: Framework :: Django :: 3.1
307 Classifier: Framework :: Django
308 Classifier: Intended Audience :: Developers
309 Classifier: License :: OSI Approved :: BSD License
310 Classifier: Natural Language :: English
311 Classifier: Programming Language :: Python :: 3 :: Only
312 Classifier: Programming Language :: Python :: 3
313 Classifier: Programming Language :: Python :: 3.6
314 Classifier: Programming Language :: Python :: 3.7
315 Classifier: Programming Language :: Python :: 3.8
316 Classifier: Programming Language :: Python :: 3.9
317 Description-Content-Type: text/markdown
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]
8 DJANGO_SETTINGS_MODULE = testproject.settings
9 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)