Created
October 19, 2012 00:19
-
-
Save tgecho/3915553 to your computer and use it in GitHub Desktop.
A proof of concept for automatic dependency detection
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import re | |
from os import path, stat | |
from webassets import Bundle | |
from webassets.exceptions import BundleError | |
DEPENDS_REGEXES = map(re.compile, [ | |
# http://stackoverflow.com/questions/4652777/java-regex-to-get-the-urls-from-css | |
# With addon to handle quotes | |
r'url[\s]*\([\s\'\"]*(?P<url>[^\)\'\"]*)[\s\'\"]*\)[\s]*', | |
r'@import[\s]*[\"|\'](?P<url>[^\'\"]*)[\"|\']', | |
]) | |
PARSE_FILETYPES = ('css', 'scss', 'sass') | |
def cache_key(resolved_path): | |
return (resolved_path, str(stat(resolved_path).st_mtime)) | |
def resolve_dependency(item, env): | |
try: | |
result = env.resolver.resolve_source(item) | |
except IOError, e: | |
raise BundleError(e) | |
if not isinstance(result, list): | |
result = [result] | |
return result | |
def get_dependencies(subject_path, env): | |
resolved_sources = resolve_dependency(subject_path, env) | |
subject_dir = path.dirname(subject_path) | |
depends = [] | |
for resolved_path in resolved_sources: | |
cached = env.cache.get(cache_key(resolved_path), python=True) or {} | |
if cached: | |
return cached.keys() | |
with open(resolved_path) as source: | |
source_data = source.read() | |
for regex in DEPENDS_REGEXES: | |
for match in regex.findall(source_data): | |
normalized = path.normpath(path.join(subject_dir, match)) | |
resolved = resolve_dependency(normalized, env) | |
depends.extend(resolved) | |
for dep in resolved: | |
cached[dep] = stat(dep).st_mtime | |
env.cache.set(cache_key(resolved_path), cached) | |
return depends | |
def recurse_dependencies(sources, global_depends, env): | |
for source in sources: | |
if source.rsplit('.', 1)[-1] in PARSE_FILETYPES: | |
depends = [d for d in get_dependencies(source, env=env) if d not in global_depends] | |
if depends: | |
global_depends.extend(depends) | |
recurse_dependencies(depends, global_depends, env=env) | |
class AutoDependsBundle(Bundle): | |
def resolve_depends(self, env): | |
depends = super(AutoDependsBundle, self).resolve_depends(env) | |
recurse_dependencies(list(self.contents) + depends, depends, env=env) | |
return depends |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment