@@ -1,6 +1,7 @@ | |||||
*~ | *~ | ||||
*.pyc | *.pyc | ||||
.DS_Store | .DS_Store | ||||
deploy | |||||
deploy/* | deploy/* | ||||
*.cprof | *.cprof | ||||
*.profile | *.profile | ||||
@@ -78,7 +78,7 @@ class MetaPlugin(Plugin): | |||||
""" | """ | ||||
self.logger.info("Trying to load metadata from resource [%s]" % resource) | self.logger.info("Trying to load metadata from resource [%s]" % resource) | ||||
yaml_finder = re.compile( | yaml_finder = re.compile( | ||||
r"^\s*(?:---|===)\s*\n((?:.|\n)+?)\n\s*(?:---|===)\s*\n", | |||||
r"^\s*(?:---|===)\s*\n((?:.|\n)+?)\n\s*(?:---|===)\s*\n?", | |||||
re.MULTILINE) | re.MULTILINE) | ||||
match = re.match(yaml_finder, text) | match = re.match(yaml_finder, text) | ||||
if not match: | if not match: | ||||
@@ -8,8 +8,7 @@ import re | |||||
from hyde.fs import File, Folder | from hyde.fs import File, Folder | ||||
from hyde.model import Expando | from hyde.model import Expando | ||||
from hyde.template import HtmlWrap, Template | from hyde.template import HtmlWrap, Template | ||||
from hyde.site import Resource | |||||
from hyde.util import getLoggerWithNullHandler, getLoggerWithConsoleHandler | |||||
from hyde.util import getLoggerWithNullHandler | |||||
from jinja2 import contextfunction, Environment | from jinja2 import contextfunction, Environment | ||||
from jinja2 import FileSystemLoader, FileSystemBytecodeCache | from jinja2 import FileSystemLoader, FileSystemBytecodeCache | ||||
@@ -17,7 +16,7 @@ from jinja2 import environmentfilter, Markup, Undefined, nodes | |||||
from jinja2.ext import Extension | from jinja2.ext import Extension | ||||
from jinja2.exceptions import TemplateError | from jinja2.exceptions import TemplateError | ||||
logger = getLoggerWithNullHandler('Jinja2') | |||||
logger = getLoggerWithNullHandler('hyde.engine.Jinja2') | |||||
class SilentUndefined(Undefined): | class SilentUndefined(Undefined): | ||||
""" | """ | ||||
@@ -54,7 +53,7 @@ def markdown(env, value): | |||||
Markdown filter with support for extensions. | Markdown filter with support for extensions. | ||||
""" | """ | ||||
try: | try: | ||||
import markdown | |||||
import markdown as md | |||||
except ImportError: | except ImportError: | ||||
logger.error(u"Cannot load the markdown library.") | logger.error(u"Cannot load the markdown library.") | ||||
raise TemplateError("Cannot load the markdown library") | raise TemplateError("Cannot load the markdown library") | ||||
@@ -65,8 +64,8 @@ def markdown(env, value): | |||||
d['extension_configs'] = getattr(env.config.markdown, | d['extension_configs'] = getattr(env.config.markdown, | ||||
'extension_configs', | 'extension_configs', | ||||
Expando({})).to_dict() | Expando({})).to_dict() | ||||
md = markdown.Markdown(**d) | |||||
return md.convert(output) | |||||
marked = md.Markdown(**d) | |||||
return marked.convert(output) | |||||
@environmentfilter | @environmentfilter | ||||
def syntax(env, value, lexer=None, filename=None): | def syntax(env, value, lexer=None, filename=None): | ||||
@@ -78,7 +77,8 @@ def syntax(env, value, lexer=None, filename=None): | |||||
from pygments import lexers | from pygments import lexers | ||||
from pygments import formatters | from pygments import formatters | ||||
except ImportError: | except ImportError: | ||||
logger.error(u"pygments library is required to use syntax highlighting tags.") | |||||
logger.error(u"pygments library is required to" | |||||
" use syntax highlighting tags.") | |||||
raise TemplateError("Cannot load pygments") | raise TemplateError("Cannot load pygments") | ||||
pyg = (lexers.get_lexer_by_name(lexer) | pyg = (lexers.get_lexer_by_name(lexer) | ||||
@@ -176,8 +176,9 @@ class YamlVar(Extension): | |||||
nodes.Const({}) | nodes.Const({}) | ||||
).set_lineno(lineno), | ).set_lineno(lineno), | ||||
nodes.CallBlock( | nodes.CallBlock( | ||||
self.call_method('_set_yaml', args=[nodes.Name(var, 'load')]), | |||||
[], [], body).set_lineno(lineno) | |||||
self.call_method('_set_yaml', | |||||
args=[nodes.Name(var, 'load')]), | |||||
[], [], body).set_lineno(lineno) | |||||
] | ] | ||||
@@ -197,6 +198,9 @@ class YamlVar(Extension): | |||||
return '' | return '' | ||||
def parse_kwargs(parser): | def parse_kwargs(parser): | ||||
""" | |||||
Parses keyword arguments in tags. | |||||
""" | |||||
name = parser.stream.expect('name').value | name = parser.stream.expect('name').value | ||||
parser.stream.expect('assign') | parser.stream.expect('assign') | ||||
if parser.stream.current.test('string'): | if parser.stream.current.test('string'): | ||||
@@ -220,18 +224,12 @@ class Syntax(Extension): | |||||
lex = nodes.Const(None) | lex = nodes.Const(None) | ||||
filename = nodes.Const(None) | filename = nodes.Const(None) | ||||
def fail_syntax(): | |||||
parser.fail( | |||||
'Invalid syntax tag. Expected:' | |||||
'{% syntax lex=yaml, filename=abc.yaml %} or' | |||||
'{% syntax yaml, \'abc.yaml\' %}') | |||||
if not parser.stream.current.test('block_end'): | if not parser.stream.current.test('block_end'): | ||||
if parser.stream.look().test('assign'): | if parser.stream.look().test('assign'): | ||||
name = value = name1 = value1 = None | |||||
name = value = value1 = None | |||||
(name, value) = parse_kwargs(parser) | (name, value) = parse_kwargs(parser) | ||||
if parser.stream.skip_if('comma'): | if parser.stream.skip_if('comma'): | ||||
(name1, value1) = parse_kwargs(parser) | |||||
(_, value1) = parse_kwargs(parser) | |||||
(lex, filename) = (value, value1) \ | (lex, filename) = (value, value1) \ | ||||
if name == 'lex' \ | if name == 'lex' \ | ||||
@@ -314,6 +312,9 @@ class Reference(Extension): | |||||
def _render_output(self, markings, name, caller=None): | def _render_output(self, markings, name, caller=None): | ||||
""" | |||||
Assigns the result of the contents to the markings variable. | |||||
""" | |||||
if not caller: | if not caller: | ||||
return '' | return '' | ||||
out = caller() | out = caller() | ||||
@@ -334,7 +335,6 @@ class Refer(Extension): | |||||
""" | """ | ||||
token = parser.stream.next() | token = parser.stream.next() | ||||
lineno = token.lineno | lineno = token.lineno | ||||
tag = token.value | |||||
parser.stream.expect('name:to') | parser.stream.expect('name:to') | ||||
template = parser.parse_expression() | template = parser.parse_expression() | ||||
parser.stream.expect('name:as') | parser.stream.expect('name:as') | ||||
@@ -387,12 +387,16 @@ class Refer(Extension): | |||||
] | ] | ||||
def _push_resource(self, namespace, site, resource, template, caller): | def _push_resource(self, namespace, site, resource, template, caller): | ||||
""" | |||||
Saves the current references in a stack. | |||||
""" | |||||
namespace['parent_resource'] = resource | namespace['parent_resource'] = resource | ||||
if not hasattr(resource, 'depends'): | if not hasattr(resource, 'depends'): | ||||
resource.depends = [] | resource.depends = [] | ||||
if not template in resource.depends: | if not template in resource.depends: | ||||
resource.depends.append(template) | resource.depends.append(template) | ||||
namespace['resource'] = site.content.resource_from_relative_path(template) | |||||
namespace['resource'] = site.content.resource_from_relative_path( | |||||
template) | |||||
return '' | return '' | ||||
def _assign_reference(self, markings, namespace, caller): | def _assign_reference(self, markings, namespace, caller): | ||||
@@ -415,17 +419,17 @@ class HydeLoader(FileSystemLoader): | |||||
""" | """ | ||||
def __init__(self, sitepath, site, preprocessor=None): | def __init__(self, sitepath, site, preprocessor=None): | ||||
config = site.config if hasattr(site, 'config') else None | |||||
if config: | |||||
super(HydeLoader, self).__init__([ | |||||
str(config.content_root_path), | |||||
str(config.layout_root_path), | |||||
]) | |||||
else: | |||||
super(HydeLoader, self).__init__(str(sitepath)) | |||||
config = site.config if hasattr(site, 'config') else None | |||||
if config: | |||||
super(HydeLoader, self).__init__([ | |||||
str(config.content_root_path), | |||||
str(config.layout_root_path), | |||||
]) | |||||
else: | |||||
super(HydeLoader, self).__init__(str(sitepath)) | |||||
self.site = site | |||||
self.preprocessor = preprocessor | |||||
self.site = site | |||||
self.preprocessor = preprocessor | |||||
def get_source(self, environment, template): | def get_source(self, environment, template): | ||||
""" | """ | ||||
@@ -573,9 +577,16 @@ class Jinja2Template(Template): | |||||
""" | """ | ||||
return '{{ media_url(\'%s\') }}' % url | return '{{ media_url(\'%s\') }}' % url | ||||
def render(self, text, context): | |||||
def render_resource(self, resource, context): | |||||
""" | """ | ||||
Renders the given resource using the context | Renders the given resource using the context | ||||
""" | """ | ||||
template = self.env.get_template(resource.relative_path) | |||||
return template.render(context) | |||||
def render(self, text, context): | |||||
""" | |||||
Renders the given text using the context | |||||
""" | |||||
template = self.env.from_string(text) | template = self.env.from_string(text) | ||||
return template.render(context) | return template.render(context) |
@@ -283,16 +283,18 @@ class Generator(object): | |||||
logger.debug("Processing [%s]", resource) | logger.debug("Processing [%s]", resource) | ||||
with self.context_for_resource(resource) as context: | with self.context_for_resource(resource) as context: | ||||
if resource.source_file.is_text: | if resource.source_file.is_text: | ||||
text = resource.source_file.read_all() | |||||
text = self.events.begin_text_resource(resource, text) or text | |||||
if resource.uses_template: | if resource.uses_template: | ||||
logger.debug("Rendering [%s]", resource) | logger.debug("Rendering [%s]", resource) | ||||
try: | try: | ||||
text = self.template.render(text, context) | |||||
text = self.template.render_resource(resource, | |||||
context) | |||||
except Exception: | except Exception: | ||||
logger.error("Error occurred when" | logger.error("Error occurred when" | ||||
" processing template:[%s]" % resource) | " processing template:[%s]" % resource) | ||||
raise | raise | ||||
else: | |||||
text = resource.source_file.read_all() | |||||
text = self.events.begin_text_resource(resource, text) or text | |||||
text = self.events.text_resource_complete( | text = self.events.text_resource_complete( | ||||
resource, text) or text | resource, text) or text | ||||
@@ -4,4 +4,3 @@ extends: listing.j2 | |||||
default_block: test | default_block: test | ||||
listable: false | listable: false | ||||
--- | --- | ||||
A |
@@ -66,7 +66,8 @@ | |||||
</section> | </section> | ||||
</div> | </div> | ||||
<footer> | <footer> | ||||
</footer> | |||||
Powered by <a href="http://ringce.com/hyde">hyde</a>. | |||||
</footer> | |||||
{% endblock container %} | {% endblock container %} | ||||
</div> <!--! end of #container --> | </div> <!--! end of #container --> | ||||
{% endblock content%} | {% endblock content%} | ||||
@@ -63,7 +63,8 @@ class Plugin(object): | |||||
def __init__(self, site): | def __init__(self, site): | ||||
super(Plugin, self).__init__() | super(Plugin, self).__init__() | ||||
self.site = site | self.site = site | ||||
self.logger = getLoggerWithNullHandler(self.__class__.__name__) | |||||
self.logger = getLoggerWithNullHandler( | |||||
'hyde.engine.%s' % self.__class__.__name__) | |||||
self.template = None | self.template = None | ||||
@@ -57,6 +57,7 @@ class HydeRequestHandler(SimpleHTTPRequestHandler): | |||||
result = urlparse.urlparse(self.path) | result = urlparse.urlparse(self.path) | ||||
logger.debug("Trying to load file based on request:[%s]" % result.path) | logger.debug("Trying to load file based on request:[%s]" % result.path) | ||||
path = result.path.lstrip('/') | path = result.path.lstrip('/') | ||||
res = None | |||||
if path.strip() == "" or File(path).kind.strip() == "": | if path.strip() == "" or File(path).kind.strip() == "": | ||||
deployed = site.config.deploy_root_path.child(path) | deployed = site.config.deploy_root_path.child(path) | ||||
deployed = Folder.file_or_folder(deployed) | deployed = Folder.file_or_folder(deployed) | ||||
@@ -67,7 +68,6 @@ class HydeRequestHandler(SimpleHTTPRequestHandler): | |||||
res = site.content.resource_from_relative_deploy_path(path) | res = site.content.resource_from_relative_deploy_path(path) | ||||
if not res: | if not res: | ||||
# Check if its a new request | # Check if its a new request | ||||
if self.server.request_time > self.server.regeneration_time: | if self.server.request_time > self.server.regeneration_time: | ||||
# Cannot find the source file using the given path. | # Cannot find the source file using the given path. | ||||
@@ -148,11 +148,33 @@ class HydeWebServer(HTTPServer): | |||||
logger.error('Error occured when regenerating the site [%s]' | logger.error('Error occured when regenerating the site [%s]' | ||||
% exception.message) | % exception.message) | ||||
def generate_node(self, node): | |||||
""" | |||||
Generates the given node. | |||||
""" | |||||
deploy = self.site.config.deploy_root_path | |||||
if not deploy.exists: | |||||
return self.regenerate() | |||||
try: | |||||
logger.info('Generating node [%s]' % node) | |||||
self.generator.generate_node(node, incremental=True) | |||||
except Exception, exception: | |||||
logger.error( | |||||
'Error [%s] occured when generating the node [%s]' | |||||
% (repr(exception), node)) | |||||
def generate_resource(self, resource): | def generate_resource(self, resource): | ||||
""" | """ | ||||
Regenerates the given resource. | Regenerates the given resource. | ||||
""" | """ | ||||
deploy = self.site.config.deploy_root_path | |||||
if not deploy.exists: | |||||
return self.regenerate() | |||||
dest = deploy.child_folder(resource.node.relative_path) | |||||
if not dest.exists: | |||||
return self.generate_node(resource.node) | |||||
try: | try: | ||||
logger.info('Generating resource [%s]' % resource) | logger.info('Generating resource [%s]' % resource) | ||||
self.generator.generate_resource(resource, incremental=True) | self.generator.generate_resource(resource, incremental=True) | ||||
@@ -276,7 +276,8 @@ class TestPlugins(object): | |||||
gen.generate_all() | gen.generate_all() | ||||
begin_text_resource_stub.reset_mock() | begin_text_resource_stub.reset_mock() | ||||
path = self.site.content.source_folder.child('about.html') | path = self.site.content.source_folder.child('about.html') | ||||
gen.generate_resource_at_path(path) | |||||
gen = Generator(self.site) | |||||
gen.generate_resource_at_path(path, incremental=True) | |||||
called_with_resources = sorted([arg[0][0].path for arg in begin_text_resource_stub.call_args_list]) | called_with_resources = sorted([arg[0][0].path for arg in begin_text_resource_stub.call_args_list]) | ||||
assert begin_text_resource_stub.call_count == 1 | assert begin_text_resource_stub.call_count == 1 | ||||
@@ -21,12 +21,18 @@ except: | |||||
def getLoggerWithConsoleHandler(logger_name): | def getLoggerWithConsoleHandler(logger_name): | ||||
logger = logging.getLogger(logger_name) | logger = logging.getLogger(logger_name) | ||||
logger.setLevel(logging.INFO) | logger.setLevel(logging.INFO) | ||||
handler = logging.StreamHandler(sys.stdout) | |||||
formatter = ColorFormatter(fmt="$RESET %(asctime)s " | |||||
if not logger.handlers: | |||||
handler = logging.StreamHandler(sys.stdout) | |||||
if sys.platform == 'win32': | |||||
formatter = logging.Formatter( | |||||
fmt="%(asctime)s %(name)s %(message)s", | |||||
datefmt='%H:%M:%S') | |||||
else: | |||||
formatter = ColorFormatter(fmt="$RESET %(asctime)s " | |||||
"$BOLD$COLOR%(name)s$RESET " | "$BOLD$COLOR%(name)s$RESET " | ||||
"%(message)s", datefmt='%H:%M:%S') | "%(message)s", datefmt='%H:%M:%S') | ||||
handler.setFormatter(formatter) | |||||
logger.addHandler(handler) | |||||
handler.setFormatter(formatter) | |||||
logger.addHandler(handler) | |||||
return logger | return logger | ||||
@@ -36,7 +42,8 @@ def getLoggerWithNullHandler(logger_name): | |||||
and a NullHandler. | and a NullHandler. | ||||
""" | """ | ||||
logger = logging.getLogger(logger_name) | logger = logging.getLogger(logger_name) | ||||
logger.addHandler(NullHandler()) | |||||
if not logger.handlers: | |||||
logger.addHandler(NullHandler()) | |||||
return logger | return logger | ||||