Skip to content

Commit

Permalink
Simplify by combining the glob and regex finder interfaces
Browse files Browse the repository at this point in the history
  • Loading branch information
mjumbewu committed Aug 17, 2012
1 parent bd499d1 commit 68bc9d4
Show file tree
Hide file tree
Showing 9 changed files with 44 additions and 100 deletions.
6 changes: 2 additions & 4 deletions mustachejs/conf.py
Expand Up @@ -21,14 +21,12 @@ def __getattr__(self, k):
MUSTACHEJS_FINDERS=[
"mustachejs.finders.FilesystemFinder",
"mustachejs.finders.AppFinder",
"mustachejs.finders.FilesystemRegexFinder",
"mustachejs.finders.AppRegexFinder",
],
MUSTACHEJS_DIRS=[],
MUSTACHEJS_EXTS=["mustache", "html"],
MUSTACHEJS_APP_DIRNAMES=["jstemplates"],
MUSTACHEJS_I18N_TAGS=["_", "i18n"],
MUSTACHEJS_PREPROCESSORS=['mustachejs.preprocessors.I18nPreprocessor'],
MUSTACHEJS_REGEX_FINDERS=[
"mustachejs.finders.FilesystemRegexFinder",
"mustachejs.finders.AppRegexFinder",
],
)
53 changes: 16 additions & 37 deletions mustachejs/finders.py
Expand Up @@ -12,16 +12,6 @@ def find(self, name):
raise NotImplementedError()



class BaseRegexFinder(object):
# Returns a list of (name, filepath) pairs
# from the given dir matching the given regex
def findAll(self, dir, regex):
raise NotImplementedError()




class FilesystemFinder(BaseFinder):
@property
def directories(self):
Expand Down Expand Up @@ -70,7 +60,7 @@ def _update_matches(self, matches, pathspec, directory, extension):
matches[matchname] = absfilepath


class FilesystemRegexFinder(BaseRegexFinder):
class FilesystemRegexFinder(BaseFinder):
@property
def directories(self):
return conf.MUSTACHEJS_DIRS
Expand All @@ -79,30 +69,26 @@ def directories(self):
def extensions(self):
return conf.MUSTACHEJS_EXTS

def findAll(self, path, regex):
result = []
def find(self, name):
matches = {}

regex = re.compile("(" + regex + ").(?:" + '|'.join(self.extensions) + ")")
for directory in self.directories:
dirpath = os.path.abspath(os.path.join(directory, path))
for file in os.listdir(dirpath):
if not os.path.isdir(file):
match = regex.match(file)
if match is not None:
result += [(match.groups()[0], os.path.join(dirpath, file))]
pattern = re.compile(name + ".(?:" + '|'.join(self.extensions) + ")")

return result
# Bail if there are no capturing groups in the pattern
if pattern.groups == 0:
return []

for directory in self.directories:
self._update_matches(matches, directory, pattern)

return matches.items()

# Convenience subclass to add directory scope to
# the names of the files
class ScopedFilesystemRegexFinder(FilesystemRegexFinder):
def findAll(self, dir, regex):
res = super(ScopedFilesystemRegexFinder, self).findAll(dir, regex)
dir = str(os.path.join(dir))
scope_list = [x for x in dir.split("/") if x is not "." and len(x) > 0]
return [("_".join(scope_list + [name]), dir) for (name, dir) in res]
def _update_matches(self, matches, directory, pattern):
for filename in os.listdir(directory):
if not os.path.isdir(filename):
match = pattern.match(filename)
if match is not None and match.group(1) not in matches:
matches[match.group(1)] = os.path.join(directory, filename)



Expand Down Expand Up @@ -139,10 +125,3 @@ class AppRegexFinder(FilesystemRegexFinder):
@property
def directories(self):
return app_template_dirs



class ScopedAppRegexFinder(ScopedFilesystemRegexFinder):
@property
def directories(self):
return app_template_dirs
14 changes: 0 additions & 14 deletions mustachejs/loading.py
Expand Up @@ -41,15 +41,6 @@ def preprocess(content):
return content


def findAll(dir, regex):
result = []
for finder in regexfinders:
paths = finder.findAll(dir, regex)
if paths is not None:
result += paths
return result


def _get_classes(dotted_paths):
ret = []
for path in dotted_paths:
Expand All @@ -75,17 +66,12 @@ def _get_finders():
return _get_classes(conf.MUSTACHEJS_FINDERS)


def _get_regexfinders():
return _get_classes(conf.MUSTACHEJS_REGEX_FINDERS)


def _get_preprocessors():
return _get_classes(conf.MUSTACHEJS_PREPROCESSORS)


# Instantiate finders
finders = _get_finders()
regexfinders = _get_regexfinders()
preprocessors = _get_preprocessors()


Expand Down
41 changes: 13 additions & 28 deletions mustachejs/templatetags/base.py
@@ -1,7 +1,7 @@
from django import template

from ..conf import conf
from ..loading import find, findAll, preprocess, MustacheJSTemplateNotFound
from ..loading import find, preprocess, MustacheJSTemplateNotFound


register = template.Library()
Expand All @@ -10,41 +10,26 @@
class BaseMustacheNode(template.Node):
preprocessors = conf.MUSTACHEJS_PREPROCESSORS

def __init__(self, name_or_path, pattern=None):
if pattern is None:
self.name = template.Variable(name_or_path)
else:
self.path = template.Variable(name_or_path)
self.pattern = template.Variable(pattern)
def __init__(self, name):
self.name = template.Variable(name)

def find_template_matches(self, path):
return find(path)
def find_template_matches(self, name):
return find(name)

def preprocess(self, content):
return preprocess(content)

def render(self, context):
# If this is a path and a patter, loop through and render all the files
# that match the pattern.
if hasattr(self, 'pattern'):
resolved_path = self.path.resolve(context)
pattern = self.pattern.resolve(context)
pairs = findAll(resolved_path, pattern)
return ''.join([self.render_file(context, name, filepath)
for (name, filepath) in pairs])
name = self.name.resolve(context)

# If this is just a file name, render that file.
try:
matches = self.find_template_matches(name)
except MustacheJSTemplateNotFound:
if conf.DEBUG: raise
else: return ''
else:
name = self.name.resolve(context)

try:
matches = self.find_template_matches(name)
except MustacheJSTemplateNotFound:
if conf.DEBUG: raise
else: return ''
else:
return ''.join([self.render_file(context, matchname, filepath)
for (matchname, filepath) in matches])
return ''.join([self.render_file(context, matchname, filepath)
for (matchname, filepath) in matches])

def render_file(self, context, resolved_name, filepath):
try:
Expand Down
7 changes: 3 additions & 4 deletions mustachejs/templatetags/dustjs.py
Expand Up @@ -33,9 +33,8 @@ def dustjs(parser, token):
"""
bits = token.contents.split()
if len(bits) not in [2, 3]:
if len(bits) != 2:
raise template.TemplateSyntaxError(
"'dustjs' tag takes either (1) one argument: the name/id of "
"the template, or (2) two arguments: the name of a subdirectory "
"to search and a regular expression of files to search for")
"'dustjs' tag takes either one argument: the name/id of "
"the template, or a pattern matching a set of templates.")
return DustJSNode(*bits[1:])
7 changes: 3 additions & 4 deletions mustachejs/templatetags/mustacheich.py
Expand Up @@ -27,9 +27,8 @@ def mustacheich(parser, token):
"""
bits = token.contents.split()
if len(bits) not in [2, 3]:
if len(bits) != 2:
raise template.TemplateSyntaxError(
"'mustacheich' tag takes either (1) one argument: the name/id of "
"the template, or (2) two arguments: the name of a subdirectory "
"to search and a regular expression of files to search for")
"'mustacheich' tag takes either one argument: the name/id of "
"the template, or a pattern matching a set of templates.")
return MustacheICanHazNode(*bits[1:])
7 changes: 3 additions & 4 deletions mustachejs/templatetags/mustachejs.py
Expand Up @@ -40,9 +40,8 @@ def mustachejs(parser, token):
"""
bits = token.contents.split()
if len(bits) not in [2, 3]:
if len(bits) != 2:
raise template.TemplateSyntaxError(
"'mustachejs' tag takes either (1) one argument: the name/id of "
"the template, or (2) two arguments: the name of a subdirectory "
"to search and a regular expression of files to search for")
"'mustachejs' tag takes either one argument: the name/id of "
"the template, or a pattern matching a set of templates.")
return MustacheJSNode(*bits[1:])
7 changes: 3 additions & 4 deletions mustachejs/templatetags/mustacheraw.py
Expand Up @@ -24,9 +24,8 @@ def mustacheraw(parser, token):
"""
bits = token.contents.split()
if len(bits) not in [2, 3]:
if len(bits) != 2:
raise template.TemplateSyntaxError(
"'mustacheraw' tag takes either (1) one argument: the name/id of "
"the template, or (2) two arguments: the name of a subdirectory "
"to search and a regular expression of files to search for")
"'mustacheraw' tag takes either one argument: the name/id of "
"the template, or a pattern matching a set of templates.")
return MustacheRaw(*bits[1:])
2 changes: 1 addition & 1 deletion mustachejs/tests/test_ttag.py
Expand Up @@ -36,7 +36,7 @@ def test_no_template(self):
@override_settings(MUSTACHEJS_DIRS=[DIR], DEBUG=True)
def test_multiple_templates_with_regex(self):
res = Template(
"{{% load mustachejs %}}{{% {0} '' 'many.*' %}}".format(self.tag_string)
"{{% load mustachejs %}}{{% {0} '(many.*)' %}}".format(self.tag_string)
).render(Context())

import re
Expand Down

0 comments on commit 68bc9d4

Please sign in to comment.