Browse Source

Provide more informative exceptions. (Issue #204).

*   Better exception handling. (Issue #204)
    -   Hyde now propagates exceptions
    -   Hyde does not raise exceptions by default. `-x` flag is required
        for raising exceptions on error.
    -   Traceback is available in the `verbose` mode
*   Upgraded to commando 0.3.4
*   Upgraded to Jinja 2.7
main
Lakshmi Vyasarajan 11 years ago
parent
commit
979ad3af8b
14 changed files with 99 additions and 61 deletions
  1. +13
    -1
      CHANGELOG.rst
  2. +1
    -1
      README.rst
  3. +5
    -4
      hyde/engine.py
  4. +7
    -1
      hyde/exceptions.py
  5. +12
    -10
      hyde/ext/plugins/css.py
  6. +5
    -2
      hyde/ext/plugins/js.py
  7. +6
    -4
      hyde/ext/plugins/meta.py
  8. +21
    -10
      hyde/ext/templates/jinja.py
  9. +10
    -7
      hyde/generator.py
  10. +9
    -11
      hyde/plugin.py
  11. +3
    -3
      hyde/server.py
  12. +1
    -1
      hyde/version.py
  13. +3
    -3
      requirements.txt
  14. +3
    -3
      setup.py

+ 13
- 1
CHANGELOG.rst View File

@@ -1,3 +1,15 @@
Version 0.8.7a6
============================================================

* Better exception handling. (Issue #204)
- Hyde now propagates exceptions
- Hyde does not raise exceptions by default. `-x` flag is required
for raising exceptions on error.
- Traceback is available in the `verbose` mode
* Upgraded to commando 0.3.4
* Upgraded to Jinja 2.7


Version 0.8.7a5
============================================================

@@ -7,7 +19,7 @@ Version 0.8.7a4
============================================================

* Include project artifacts in sdist. (Issue #211)
- Add LICENSE, AUTHORS and CHANGELOG to MANIFEST.in
- Add LICENSE, AUTHORS and CHANGELOG to MANIFEST.in
* Add "Hyde contributors to LICENSE copyright"




+ 1
- 1
README.rst View File

@@ -1,4 +1,4 @@
Version 0.8.7a5
Version 0.8.7a6

A brand new **hyde**
====================


+ 5
- 4
hyde/engine.py View File

@@ -24,7 +24,7 @@ HYDE_LAYOUTS = "HYDE_LAYOUTS"

class Engine(Application):

def __init__(self, raise_exceptions=True):
def __init__(self, raise_exceptions=False):
logger = getLoggerWithConsoleHandler('hyde')
super(Engine, self).__init__(
raise_exceptions=raise_exceptions,
@@ -34,6 +34,8 @@ class Engine(Application):
@command(description='hyde - a python static website generator',
epilog='Use %(prog)s {command} -h to get help on individual commands')
@true('-v', '--verbose', help="Show detailed information in console")
@true('-x', '--raise-exceptions', default=False,
help="Don't handle exceptions.")
@version('--version', version='%(prog)s ' + __version__)
@store('-s', '--sitepath', default='.', help="Location of the hyde site")
def main(self, args):
@@ -43,6 +45,7 @@ class Engine(Application):
like version and metadata
"""
sitepath = Folder(args.sitepath).fully_expanded_path
self.raise_exceptions = args.raise_exceptions
return Folder(sitepath)

@subcommand('create', help='Create a new hyde site.')
@@ -94,7 +97,6 @@ class Engine(Application):
if args.regen:
self.logger.info("Regenerating the site...")
incremental = False

gen.generate_all(incremental=incremental)
self.logger.info("Generation complete.")

@@ -147,7 +149,6 @@ class Engine(Application):
publisher.publish()



def make_site(self, sitepath, config, deploy=None):
"""
Creates a site object from the given sitepath and the config file.
@@ -155,4 +156,4 @@ class Engine(Application):
config = Config(sitepath, config_file=config)
if deploy:
config.deploy_root = deploy
return Site(sitepath, config)
return Site(sitepath, config)

+ 7
- 1
hyde/exceptions.py View File

@@ -2,4 +2,10 @@ class HydeException(Exception):
"""
Base class for exceptions from hyde
"""
pass

@staticmethod
def reraise(message, exc_info):
_, _, tb = exc_info
raise HydeException(message), None, tb



+ 12
- 10
hyde/ext/plugins/css.py View File

@@ -10,6 +10,7 @@ from hyde.exceptions import HydeException
import os
import re
import subprocess
import sys

from fswrap import File

@@ -71,8 +72,7 @@ class LessCSSPlugin(CLTransformer):
afile = File(afile.path + '.less')
ref = self.site.content.resource_from_path(afile.path)
if not ref:
raise self.template.exception_class(
"Cannot import from path [%s]" % afile.path)
raise HydeException("Cannot import from path [%s]" % afile.path)
ref.is_processable = False
return self.template.get_include_statement(ref.relative_path)
text = self.import_finder.sub(import_to_include, text)
@@ -114,9 +114,11 @@ class LessCSSPlugin(CLTransformer):
try:
self.call_app(args)
except subprocess.CalledProcessError:
raise self.template.exception_class(
HydeException.reraise(
"Cannot process %s. Error occurred when "
"processing [%s]" % (self.app.name, resource.source_file))
"processing [%s]" % (self.app.name, resource.source_file),
sys.exc_info())

return target.read_all()


@@ -155,7 +157,7 @@ class StylusPlugin(CLTransformer):

def import_to_include(match):
"""
Converts a css import statement to include statemnt.
Converts a css import statement to include statement.
"""
if not match.lastindex:
return ''
@@ -172,7 +174,7 @@ class StylusPlugin(CLTransformer):
except AttributeError:
include = False
if not include:
raise self.template.exception_class(
raise HydeException(
"Cannot import from path [%s]" % afile.path)
else:
ref.is_processable = False
@@ -225,9 +227,10 @@ class StylusPlugin(CLTransformer):
try:
self.call_app(args)
except subprocess.CalledProcessError:
raise self.template.exception_class(
HydeException.reraise(
"Cannot process %s. Error occurred when "
"processing [%s]" % (stylus.name, resource.source_file))
"processing [%s]" % (stylus.name, resource.source_file),
sys.exc_info())
return target.read_all()


@@ -291,8 +294,7 @@ class CleverCSSPlugin(Plugin):
afile = File(afile.path + '.ccss')
ref = self.site.content.resource_from_path(afile.path)
if not ref:
raise self.template.exception_class(
"Cannot import from path [%s]" % afile.path)
raise HydeException("Cannot import from path [%s]" % afile.path)
ref.is_processable = False
return self.template.get_include_statement(ref.relative_path)
text = import_finder.sub(import_to_include, text)


+ 5
- 2
hyde/ext/plugins/js.py View File

@@ -3,7 +3,9 @@
JavaScript plugins
"""
import subprocess
import sys

from hyde.exceptions import HydeException
from hyde.plugin import CLTransformer

from fswrap import File
@@ -127,9 +129,10 @@ class RequireJSPlugin(CLTransformer):
try:
self.call_app(args)
except subprocess.CalledProcessError:
raise self.template.exception_class(
HydeException.reraise(
"Cannot process %s. Error occurred when "
"processing [%s]" % (self.app.name, resource.source_file))
"processing [%s]" % (self.app.name, resource.source_file),
sys.exc_info())

return target.read_all()



+ 6
- 4
hyde/ext/plugins/meta.py View File

@@ -8,7 +8,9 @@ from functools import partial
from itertools import ifilter
from operator import attrgetter
import re
import sys

from hyde.exceptions import HydeException
from hyde.model import Expando
from hyde.plugin import Plugin
from hyde.site import Node, Resource
@@ -248,8 +250,9 @@ def get_tagger_sort_method(site):
try:
walker = getattr(content, walker)
except AttributeError:
raise self.template.exception_class(
"Cannot find the sorter: %s" % sorter)
HydeException.reraise(
"Cannot find the sorter: %s" % sorter,
sys.exc_info())
return walker

def walk_resources_tagged_with(node, tag):
@@ -370,8 +373,7 @@ class TaggerPlugin(Plugin):
Generates archives for each tag based on the given configuration.
"""
if not 'template' in config:
raise self.template.exception_class(
"No Template specified in tagger configuration.")
raise HydeException("No Template specified in tagger configuration.")
content = self.site.content.source_folder
source = Folder(config.get('source', ''))
target = content.child_folder(config.get('target', 'tags'))


+ 21
- 10
hyde/ext/templates/jinja.py View File

@@ -4,11 +4,13 @@ Jinja template utilties
"""

from datetime import datetime, date
import itertools
import os
import re
import itertools
import sys
from urllib import quote, unquote

from hyde.exceptions import HydeException
from hyde.model import Expando
from hyde.template import HtmlWrap, Template
from operator import attrgetter
@@ -599,10 +601,20 @@ class HydeLoader(FileSystemLoader):
#
template = template.replace(os.sep, '/')
logger.debug("Loading template [%s] and preprocessing" % template)
(contents,
filename,
date) = super(HydeLoader, self).get_source(
try:
(contents,
filename,
date) = super(HydeLoader, self).get_source(
environment, template)
except UnicodeDecodeError:
HydeException.reraise(
"Unicode error when processing %s" % template, sys.exc_info())
except TemplateError, exc:
HydeException.reraise('Error when processing %s: %s' % (
template,
unicode(exc)
), sys.exc_info())

if self.preprocessor:
resource = self.site.content.resource_from_relative_path(template)
if resource:
@@ -736,9 +748,11 @@ class Jinja2Template(Template):
from jinja2.meta import find_referenced_templates
try:
ast = self.env.parse(text)
except:
logger.error("Error parsing[%s]" % path)
raise
except Exception, e:
HydeException.reraise(
"Error processing %s: \n%s" % (path, unicode(e)),
sys.exc_info())

tpls = find_referenced_templates(ast)
deps = list(self.env.globals['deps'].get('path', []))
for dep in tpls:
@@ -818,9 +832,6 @@ class Jinja2Template(Template):
template = self.env.get_template(resource.relative_path)
out = template.render(context)
except:
out = ""
logger.debug(self.env.loader.get_source(
self.env, resource.relative_path))
raise
return out



+ 10
- 7
hyde/generator.py View File

@@ -3,8 +3,9 @@
The generator class and related utility functions.
"""

from hyde.exceptions import HydeException
from commando.util import getLoggerWithNullHandler
from fswrap import File, Folder
from hyde.exceptions import HydeException
from hyde.model import Context, Dependents
from hyde.plugin import Plugin
from hyde.template import Template
@@ -12,9 +13,9 @@ from hyde.site import Resource

from contextlib import contextmanager
from datetime import datetime

from shutil import copymode
from commando.util import getLoggerWithNullHandler
import sys

logger = getLoggerWithNullHandler('hyde.engine')


@@ -334,10 +335,12 @@ class Generator(object):
try:
text = self.template.render_resource(resource,
context)
except Exception:
logger.error("Error occurred when"
" processing template: [%s]" % resource)
raise
except Exception, e:
HydeException.reraise("Error occurred when"
" processing template: [%s]: %s" %
(resource, repr(e)),
sys.exc_info()
)
else:
text = resource.source_file.read_all()
text = self.events.begin_text_resource(resource, text) or text


+ 9
- 11
hyde/plugin.py View File

@@ -12,6 +12,7 @@ import fnmatch
import os
import re
import subprocess
import sys
import traceback

from commando.util import getLoggerWithNullHandler, load_python_object
@@ -56,18 +57,19 @@ class PluginProxy(object):
def __getattr__(self, method_name):
if hasattr(Plugin, method_name):
def __call_plugins__(*args):
# logger.debug("Calling plugin method [%s]", method_name)
res = None
if self.site.plugins:
for plugin in self.site.plugins:
if hasattr(plugin, method_name):
# logger.debug(
# "\tCalling plugin [%s]",
# plugin.__class__.__name__)
checker = getattr(plugin, 'should_call__' + method_name)
if checker(*args):
function = getattr(plugin, method_name)
res = function(*args)
try:
res = function(*args)
except:
HydeException.reraise(
'Error occured when calling %s' %
plugin.plugin_name, sys.exc_info())
targs = list(args)
if len(targs):
last = targs.pop()
@@ -356,14 +358,11 @@ class CLTransformer(Plugin):
app_path = discover_executable(app_path, self.site.sitepath)

if app_path is None:
raise self.template.exception_class(
self.executable_not_found_message)

raise HydeException(self.executable_not_found_message)
app = File(app_path)

if not app.exists:
raise self.template.exception_class(
self.executable_not_found_message)
raise HydeException(self.executable_not_found_message)

return app

@@ -418,7 +417,6 @@ class CLTransformer(Plugin):
(args[0], unicode(args[1:])))
return subprocess.check_output(args)
except subprocess.CalledProcessError, error:
self.logger.error(traceback.format_exc())
self.logger.error(error.output)
raise



+ 3
- 3
hyde/server.py View File

@@ -162,7 +162,7 @@ class HydeWebServer(HTTPServer):
except Exception, exception:
logger.error('Error occured when regenerating the site [%s]'
% exception.message)
logger.error(traceback.format_exc())
logger.debug(traceback.format_exc())

def generate_node(self, node):
"""
@@ -180,7 +180,7 @@ class HydeWebServer(HTTPServer):
logger.error(
'Error [%s] occured when generating the node [%s]'
% (repr(exception), node))
logger.error(traceback.format_exc())
logger.debug(traceback.format_exc())

def generate_resource(self, resource):
"""
@@ -199,4 +199,4 @@ class HydeWebServer(HTTPServer):
logger.error(
'Error [%s] occured when serving the resource [%s]'
% (repr(exception), resource))
logger.error(traceback.format_exc())
logger.debug(traceback.format_exc())

+ 1
- 1
hyde/version.py View File

@@ -2,4 +2,4 @@
"""
Handles hyde version.
"""
__version__ = '0.8.7a5'
__version__ = '0.8.7a6'

+ 3
- 3
requirements.txt View File

@@ -1,8 +1,8 @@
fswrap==0.1.1
commando==0.3.2a
commando==0.3.4
PyYAML==3.10
Markdown==2.3.1
MarkupSafe==0.15
MarkupSafe==0.18
Pygments==1.6
typogrify==2.0.0
Jinja2==2.6
Jinja2==2.7

+ 3
- 3
setup.py View File

@@ -117,13 +117,13 @@ setup(name=PROJECT,
requires=['python (>= 2.7)'],
install_requires=(
'fswrap==0.1.1',
'commando==0.3.2a',
'commando==0.3.4',
'PyYAML==3.10',
'Markdown==2.3.1',
'MarkupSafe==0.15',
'MarkupSafe==0.18',
'Pygments==1.6',
'typogrify==2.0.0',
'Jinja2==2.6'
'Jinja2==2.7'
),
tests_require=(
'nose', 'mock'


Loading…
Cancel
Save