Skip to content

Instantly share code, notes, and snippets.

@SmileyChris
Last active November 10, 2015 17:54
Show Gist options
  • Save SmileyChris/78d1922789b316ac1c84 to your computer and use it in GitHub Desktop.
Save SmileyChris/78d1922789b316ac1c84 to your computer and use it in GitHub Desktop.
Smarter django-pipeline finders
"""
Smarter django-pipeline finders.
In your settings file, you'll want something like this:
# Exclude pipelined sources from being found as static files.
STATICFILES_FINDERS = (
'pipeline_finders.PipelineFileSystemFinder',
'pipeline_finders.PipelineAppDirectoriesFinder',
'pipeline_finders.PipelineFinder',
# If using CachedStorage, use this too:
'pipeline.finders.CachedFileFinder',
)
"""
from itertools import chain
from django.contrib.staticfiles import finders, utils
from django.core.files.storage import FileSystemStorage
from django.utils.functional import cached_property
from pipeline.conf import settings
# Mixins
# ------
class PipelineMixin(object):
@cached_property
def pipeline_output_files(self):
files = []
for elem in chain(
settings.PIPELINE_CSS.values(), settings.PIPELINE_JS.values()):
files.append(elem['output_filename'])
return files
@cached_property
def pipeline_source_files(self):
files = set()
for elem in chain(
settings.PIPELINE_CSS.values(), settings.PIPELINE_JS.values()):
files.update(elem['source_filenames'])
return list(files)
def get_ignored_patterns(self, extra_patterns=None):
"""
Allows this mixin to be used before PatternFilterMixin to exclude
source files if pipeline is enabled.
"""
extra_patterns = extra_patterns or []
if settings.PIPELINE_ENABLED:
extra_patterns.extend(self.pipeline_source_files)
return super(PipelineMixin, self).get_ignored_patterns(extra_patterns)
class PatternFilterMixin(object):
ignore_patterns = []
ignore_in_find = True
def get_ignored_patterns(self, extra_patterns=None):
"""
Compile the complete list of patterns to ignore.
"""
patterns = set(self.ignore_patterns)
if extra_patterns:
patterns.update(extra_patterns)
return list(patterns)
def find(self, path, all=False):
"""
If :attr:`ignore_in_find` is ``True``, skip any path that matches the
ignore patterns.
"""
if self.ignore_in_find:
ignore_patterns = self.get_ignored_patterns(self.ignore_patterns)
if utils.matches_patterns(path, self.ignore_patterns):
return []
return super(PatternFilterMixin, self).find(path=path, all=all)
def list(self, ignore_patterns):
"""
Don't include paths that match the ignore patterns.
"""
ignore_patterns = self.get_ignored_patterns(ignore_patterns)
return super(PatternFilterMixin, self).list(ignore_patterns)
# New finders with smarter functionality
# --------------------------------------
class PipelineAppDirectoriesFinder(
PipelineMixin, PatternFilterMixin, finders.AppDirectoriesFinder):
"""
Like AppDirectoriesFinder, but ignores pipeline source files if pipeline is
enabled.
"""
ignore_in_find = False
class PipelineFileSystemFinder(
PipelineMixin, PatternFilterMixin, finders.FileSystemFinder):
"""
Like FileSystemFinder, but ignores pipeline source files if pipeline is
enabled.
"""
ignore_in_find = False
# Replacements for built-in Pipeline finders
# ------------------------------------------
class PipelineFinder(PipelineMixin, finders.BaseFinder):
"""
Looks for files in PIPELINE_CSS and PIPELINE_JS.
Uses a more Djangoistic way of getting the files than pipeline's built-in
one.
"""
storage = FileSystemStorage(settings.PIPELINE_ROOT)
def find(self, path, all=False):
"""
Looks for pipeline output files.
"""
if path in self.pipeline_output_files:
match = self.storage.path(path)
if all:
return [match]
return match
return []
def list(self, *args):
return []
class AppDirectoriesFinder(PatternFilterMixin, finders.AppDirectoriesFinder):
"""
Like AppDirectoriesFinder, but doesn't return any additional ignored
patterns.
This allows us to concentrate/compress our components without dragging
the raw versions in via collectstatic.
Kept for backwards compatibility purposes only. Try
PipelineAppDirectoriesFinder instead.
"""
ignore_patterns = [
'*.js',
'*.css',
'*.less',
'*.scss',
]
class FileSystemFinder(PatternFilterMixin, finders.FileSystemFinder):
"""
Like FileSystemFinder, but doesn't return any additional ignored patterns
This allows us to concentrate/compress our components without dragging
the raw versions in too.
Kept for backwards compatibility purposes only. Try
PipelineFileSystemFinder instead.
"""
ignore_patterns = [
'*.js',
'*.less',
'*.scss',
'*.sh',
'*.html',
'*.md',
'*.markdown',
'*.php',
'*.txt',
'README*',
'LICENSE*',
'*examples*',
'*test*',
'*bin*',
'*samples*',
'*docs*',
'*build*',
'*demo*',
'Makefile*',
'Gemfile*',
]
@eluttner
Copy link

I used this code, and it is still copying the source files to static folder.

I added a file pipeline_finders to myapp directory (same as settings.py)

I included this to settings.py:

STATICFILES_FINDERS = (
    'myapp.pipeline_finders.PipelineFileSystemFinder',
    'myapp.pipeline_finders.PipelineAppDirectoriesFinder',
    'myapp.pipeline_finders.PipelineFinder',
)

And it still copies the source files to static, any tips?

myapp/static/css/css1.css
myapp/static/css/css2.css

PIPELINE_CSS = {
    'css': {
        'source_filenames': (
          'css/*.css',
        ),
        'output_filename': 'css/css.css',
        'extra_context': {
            'media': 'screen,projection',
        },
    }, 
}

thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment