| @@ -1,7 +1,4 @@ | |||
| Django==1.2.3 | |||
| Genshi==0.6 | |||
| Jinja2==2.5.5 | |||
| Mako==0.3.6 | |||
| Markdown==2.0.3 | |||
| MarkupSafe==0.11 | |||
| PyYAML==3.09 | |||
| @@ -3,15 +3,17 @@ | |||
| The command line interface for hyde. | |||
| """ | |||
| import argparse | |||
| from engine import init, gen, serve | |||
| from version import __version__ | |||
| from engine import init, gen, serve | |||
| def main(): | |||
| """ | |||
| The main function called by hyde executable | |||
| """ | |||
| parser = argparse.ArgumentParser(description='hyde - A Python Static Website Generator', | |||
| import sys | |||
| print sys.argv | |||
| parser = argparse.ArgumentParser(description='hyde - a python static website generator', | |||
| epilog='Use %(prog)s {command} -h to get help on individual commands') | |||
| parser.add_argument('-v', '--version', action='version', version='%(prog)s ' + __version__) | |||
| parser.add_argument('-s', '--sitepath', action='store', default='.', help="Location of the hyde site") | |||
| @@ -24,4 +26,5 @@ def main(): | |||
| init_command.add_argument('-f', '--force', action='store_true', default=False, dest='force', | |||
| help='Overwrite the current site if it exists') | |||
| args = parser.parse_args() | |||
| args.run(args) | |||
| args.run(args) | |||
| @@ -0,0 +1,95 @@ | |||
| # -*- coding: utf-8 -*- | |||
| """ | |||
| A nice declarative interface for Argument parser | |||
| """ | |||
| from argparse import ArgumentParser, Namespace | |||
| from collections import namedtuple | |||
| __all__ = [ | |||
| 'command', | |||
| 'param', | |||
| 'Application' | |||
| ] | |||
| class CommandLine(type): | |||
| """ | |||
| Meta class that enables declarative command definitions | |||
| """ | |||
| def __new__(cls, name, bases, attrs): | |||
| instance = super(CommandLine, cls).__new__(cls, name, bases, attrs) | |||
| subcommands = [] | |||
| main_command = None | |||
| for name, member in attrs.iteritems(): | |||
| if hasattr(member, "command"): | |||
| main_command = member | |||
| # else if member.params: | |||
| # subcommands.append(member) | |||
| parser = None | |||
| if main_command: | |||
| parser = ArgumentParser(*main_command.command.args, **main_command.command.kwargs) | |||
| for param in main_command.params: | |||
| parser.add_argument(*param.args, **param.kwargs) | |||
| # subparsers = None | |||
| # if subcommands.length: | |||
| # subparsers = parser.add_subparsers() | |||
| # | |||
| # for command in subcommands: | |||
| # | |||
| # for param in main_command.params: | |||
| # parser.add_argument(*param.args, **param.kwargs) | |||
| instance.parser = parser | |||
| instance.main = main_command | |||
| return instance | |||
| values = namedtuple('__meta_values', 'args, kwargs') | |||
| class metarator(object): | |||
| """ | |||
| A generic decorator that tags the decorated method with | |||
| the passed in arguments for meta classes to process them. | |||
| """ | |||
| def __init__(self, *args, **kwargs): | |||
| self.values = values._make((args, kwargs)) | |||
| def metarate(self, f, name='values'): | |||
| setattr(f, name, self.values) | |||
| return f | |||
| def __call__(self, f): | |||
| return self.metarate(f) | |||
| class command(metarator): | |||
| """ | |||
| Used to decorate the main entry point | |||
| """ | |||
| def __call__(self, f): | |||
| return self.metarate(f, name='command') | |||
| class param(metarator): | |||
| """ | |||
| Use this decorator instead of `ArgumentParser.add_argument`. | |||
| """ | |||
| def __call__(self, f): | |||
| f.params = f.params if hasattr(f, 'params') else [] | |||
| f.params.append(self.values) | |||
| return f | |||
| class Application(object): | |||
| """ | |||
| Bare bones base class for command line applications. Hides the | |||
| meta programming complexities. | |||
| """ | |||
| __metaclass__ = CommandLine | |||
| def parse(self, argv): | |||
| return self.parser.parse_args(argv) | |||
| def run(self, args): | |||
| if hasattr(args, 'run'): | |||
| args.run(args) | |||
| else: | |||
| self.main(args) | |||
| @@ -3,7 +3,74 @@ def init(args): | |||
| print args.sitepath | |||
| print args.force | |||
| print args.template | |||
| # Ensure sitepath is okay (refer to force parameter) | |||
| # Find template by looking at the paths | |||
| # 1. Environment Variable | |||
| # 2. Hyde Data Directory | |||
| # Throw exception on failure | |||
| # Do not delete the site path, just overwrite existing files | |||
| def gen(args): pass | |||
| def serve(args): pass | |||
| def serve(args): pass | |||
| from version import __version__ | |||
| # """ | |||
| # Implements the hyde entry point commands | |||
| # """ | |||
| # class Command(object): | |||
| # """ | |||
| # Base class for hyde commands | |||
| # """ | |||
| # def __init__(self, **kwargs): | |||
| # super(Command, self).__init__(epilog='Use %(prog)s {command} -h to get help on individual commands', **kwargs) | |||
| # self.subcommands = None | |||
| # | |||
| # def compose(self, commands, **kwargs): | |||
| # self.subcommands = self.add_subparsers(**kwargs) | |||
| # for command in commands: | |||
| # self.subcommands.add_parser(command) | |||
| # | |||
| # def run(self, args=None): | |||
| # """ | |||
| # Executes the command | |||
| # """ | |||
| # options = {} | |||
| # options.update(self.defaults) | |||
| # if args: | |||
| # options.update(args) | |||
| # self.execute(options) | |||
| # | |||
| # def execute(self): | |||
| # """ | |||
| # Abstract method for the derived classes | |||
| # """ | |||
| # abstract | |||
| # | |||
| # class HydeCommand(Command): | |||
| # """ | |||
| # The parent command object. | |||
| # """ | |||
| # def __init__(self, **kwargs): | |||
| # super(HydeCommand, self).__init__(**kwargs) | |||
| # self.add_argument('--version', action='version', version='%(prog)s ' + __version__) | |||
| # self.add_argument('-s', '--sitepath', action='store', default='.', help="Location of the hyde site") | |||
| # | |||
| # | |||
| # class Initializer(Command): | |||
| # """ | |||
| # Represents the `hyde init` command | |||
| # """ | |||
| # def __init__(self, parent, **kwargs): | |||
| # super(Initializer, self).__init__(**kwargs) | |||
| # init_command.add_argument('-t', '--template', action='store', default='basic', dest='template', | |||
| # help='Overwrite the current site if it exists') | |||
| # init_command.add_argument('-f', '--force', action='store_true', default=False, dest='force', | |||
| # help='Overwrite the current site if it exists') | |||
| # | |||
| # def run(self): | |||
| # """ | |||
| # | |||
| # """ | |||
| # pass | |||
| @@ -1,19 +1,28 @@ | |||
| """ | |||
| Hyde Template interface realization for Jinja2 | |||
| Jinja template utilties | |||
| """ | |||
| from hyde.template import Template | |||
| from jinja2 import Environment, FileSystemLoader | |||
| # pylint: disable-msg=W0104,E0602,W0613,R0201 | |||
| class Jinja2Template(Template): | |||
| def configure(self, sitepath, config): | |||
| """ | |||
| The Jinja2 Template implementation | |||
| """ | |||
| def __init__(self, sitepath): | |||
| super(Jinja2Template, self).__init__(sitepath) | |||
| self.env = Environment(loader=FileSystemLoader(sitepath)) | |||
| def configure(self, config): | |||
| """ | |||
| Uses the config object to initialize the jinja environment. | |||
| """ | |||
| self.env = Environment(loader=FileSystemLoader(sitepath)) | |||
| pass | |||
| def render(self, template_name, context): | |||
| """ | |||
| Renders the given template using the context | |||
| """ | |||
| t = self.env.get_template(template_name) | |||
| return t.render(context) | |||
| template = self.env.get_template(template_name) | |||
| return template.render(context) | |||
| @@ -1,9 +1,16 @@ | |||
| # -*- coding: utf-8 -*- | |||
| # pylint: disable-msg=W0104,E0602,W0613,R0201 | |||
| """ | |||
| Interface for hyde template engines. To use a different template engine, | |||
| the following interface must be implemented. | |||
| Abstract classes and utilities for template engines | |||
| """ | |||
| class Template(object): | |||
| """ | |||
| Interface for hyde template engines. To use a different template engine, | |||
| the following interface must be implemented. | |||
| """ | |||
| def __init__(self, sitepath): | |||
| self.sitepath = sitepath | |||
| def configure(self, config): | |||
| """ | |||
| The config object is a simple YAML object with required settings. The template | |||
| @@ -12,7 +19,7 @@ class Template(object): | |||
| """ | |||
| abstract | |||
| def render(template_name, context): | |||
| def render(self, template_name, context): | |||
| """ | |||
| Given the name of a template (partial path usually), and the context, this function | |||
| must return the rendered string. | |||
| @@ -0,0 +1,36 @@ | |||
| # -*- coding: utf-8 -*- | |||
| """ | |||
| Use nose | |||
| `$ pip install nose` | |||
| `$ nosetests` | |||
| """ | |||
| from hyde.command_line import Application, command, param | |||
| from util import trap_exit | |||
| from mock import Mock, patch | |||
| @trap_exit | |||
| def test_command_basic(): | |||
| number_of_calls = 0 | |||
| class TestCommandLine(Application): | |||
| @command(description='test') | |||
| @param('--force', action='store_true', dest='force1') | |||
| @param('--force2', action='store', dest='force2') | |||
| @param('--version', action='version', version='%(prog)s 1.0') | |||
| def main(self, params): | |||
| assert params.force1 == eval(params.force2) | |||
| self._main() | |||
| def _main(): pass | |||
| with patch.object(TestCommandLine, '_main') as _main: | |||
| c = TestCommandLine() | |||
| args = c.parse(['--force', '--force2', 'True']) | |||
| c.run(args) | |||
| args = c.parse(['--force2', 'False']) | |||
| c.run(args) | |||
| assert _main.call_count == 2 | |||
| @@ -7,7 +7,7 @@ Use nose | |||
| Code borrowed from rwbench.py from the jinja2 examples | |||
| """ | |||
| from datetime import datetime | |||
| from hyde.ext.templates.jinja2Template import Jinja2Template | |||
| from hyde.ext.templates.jinja import Jinja2Template | |||
| from hyde.fs import File, Folder | |||
| from jinja2.utils import generate_lorem_ipsum | |||
| from random import choice, randrange | |||
| @@ -6,4 +6,15 @@ def assert_html_equals(expected, actual, sanitize=None): | |||
| if sanitize: | |||
| expected = sanitize(expected) | |||
| actual = sanitize(actual) | |||
| assert expected == actual | |||
| assert expected == actual | |||
| def trap_exit(f): | |||
| def test_wrapper(*args): | |||
| try: | |||
| f(*args) | |||
| except SystemExit, e: | |||
| print "Error running test [%s]" % f.__name__ | |||
| print e.message | |||
| raise e | |||
| return test_wrapper | |||
| @@ -1,267 +0,0 @@ | |||
| [MASTER] | |||
| # Profiled execution. | |||
| profile=no | |||
| # Add <file or directory> to the black list. It should be a base name, not a | |||
| # path. You may set this option multiple times. | |||
| #ignore=.svn | |||
| # Pickle collected data for later comparisons. | |||
| persistent=yes | |||
| # Set the cache size for astng objects. | |||
| cache-size=500 | |||
| # List of plugins (as comma separated values of python modules names) to load, | |||
| # usually to register additional checkers. | |||
| load-plugins= | |||
| [MESSAGES CONTROL] | |||
| # Enable only checker(s) with the given id(s). This option conflicts with the | |||
| # disable-checker option | |||
| #enable-checker= | |||
| # Enable all checker(s) except those with the given id(s). This option | |||
| # conflicts with the enable-checker option | |||
| #disable-checker=design | |||
| # Enable all messages in the listed categories. | |||
| #enable-msg-cat= | |||
| # Disable all messages in the listed categories. | |||
| #disable-msg-cat= | |||
| # Enable the message(s) with the given id(s). | |||
| #enable-msg= | |||
| # Disable the message(s) with the given id(s). | |||
| # List of all available ids: http://www.logilab.org/card/pylintfeatures | |||
| # Disabled messages: | |||
| # I0011: Locally disabling %s Used when an inline option disable a message or a messages category. | |||
| disable-msg=I0011 | |||
| [REPORTS] | |||
| # set the output format. Available formats are text, parseable, colorized, msvs | |||
| # (visual studio) and html | |||
| output-format=text | |||
| # Include message's id in output | |||
| include-ids=yes | |||
| # Put messages in a separate file for each module / package specified on the | |||
| # command line instead of printing them on stdout. Reports (if any) will be | |||
| # written in a file name "pylint_global.[txt|html]". | |||
| files-output=no | |||
| # Tells wether to display a full report or only the messages | |||
| reports=yes | |||
| # Python expression which should return a note less than 10 (10 is the highest | |||
| # note).You have access to the variables errors warning, statement which | |||
| # respectivly contain the number of errors / warnings messages and the total | |||
| # number of statements analyzed. This is used by the global evaluation report | |||
| # (R0004). | |||
| evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) | |||
| # Add a comment according to your evaluation note. This is used by the global | |||
| # evaluation report (R0004). | |||
| comment=no | |||
| # Enable the report(s) with the given id(s). | |||
| #enable-report= | |||
| # Disable the report(s) with the given id(s). | |||
| #disable-report= | |||
| # checks for : | |||
| # * doc strings | |||
| # * modules / classes / functions / methods / arguments / variables name | |||
| # * number of arguments, local variables, branchs, returns and statements in | |||
| # functions, methods | |||
| # * required module attributes | |||
| # * dangerous default values as arguments | |||
| # * redefinition of function / method / class | |||
| # * uses of the global statement | |||
| # | |||
| [BASIC] | |||
| # Required attributes for module, separated by a comma | |||
| required-attributes= | |||
| # Regular expression which should only match functions or classes name which do | |||
| # not require a docstring | |||
| no-docstring-rgx=__.*__ | |||
| # Regular expression which should only match correct module names | |||
| module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$ | |||
| # Regular expression which should only match correct module level names | |||
| const-rgx=(([A-Z_][A-Z1-9_]*)|(__.*__)|([a-z_][a-z0-9_]*))$ | |||
| # Regular expression which should only match correct class names | |||
| class-rgx=[_a-zA-Z0-9]+$ | |||
| # Regular expression which should only match correct function names | |||
| function-rgx=[a-z_][a-zA-Z0-9_]{2,40}$ | |||
| # Regular expression which should only match correct method names | |||
| method-rgx=[a-z_][a-zA-Z0-9_]{2,40}$ | |||
| # Regular expression which should only match correct instance attribute names | |||
| attr-rgx=[a-z_][a-z0-9_]{1,30}$ | |||
| #alternative | |||
| #attr-rgx=([a-z_][a-z0-9_]{2,30}|([a-z_][a-zA-Z0-9]{2,30}))$ | |||
| # Regular expression which should only match correct argument names | |||
| argument-rgx=[a-z_][a-z0-9_]{1,30}$ | |||
| # Regular expression which should only match correct variable names | |||
| variable-rgx=[a-z_][a-zA-Z0-9_]{1,30}$ | |||
| # Regular expression which should only match correct list comprehension / | |||
| # generator expression variable names | |||
| inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$ | |||
| # Good variable names which should always be accepted, separated by a comma | |||
| good-names=i,j,k,ex,Run,_ | |||
| # Bad variable names which should always be refused, separated by a comma | |||
| bad-names=foo,bar,baz,toto,tutu,tata | |||
| # List of builtins function names that should not be used, separated by a comma | |||
| bad-functions= | |||
| # try to find bugs in the code using type inference | |||
| # | |||
| [TYPECHECK] | |||
| # Tells wether missing members accessed in mixin class should be ignored. A | |||
| # mixin class is detected if its name ends with "mixin" (case insensitive). | |||
| ignore-mixin-members=yes | |||
| # List of classes names for which member attributes should not be checked | |||
| # (useful for classes with attributes dynamicaly set). | |||
| ignored-classes=SQLObject | |||
| # When zope mode is activated, consider the acquired-members option to ignore | |||
| # access to some undefined attributes. | |||
| zope=no | |||
| # List of members which are usually get through zope's acquisition mecanism and | |||
| # so shouldn't trigger E0201 when accessed (need zope=yes to be considered). | |||
| acquired-members=REQUEST,acl_users,aq_parent | |||
| # checks for | |||
| # * unused variables / imports | |||
| # * undefined variables | |||
| # * redefinition of variable from builtins or from an outer scope | |||
| # * use of variable before assigment | |||
| # | |||
| [VARIABLES] | |||
| # Tells wether we should check for unused import in __init__ files. | |||
| init-import=no | |||
| # A regular expression matching names used for dummy variables (i.e. not used). | |||
| dummy-variables-rgx=_|dummy | |||
| # List of additional names supposed to be defined in builtins. Remember that | |||
| # you should avoid to define new builtins when possible. | |||
| additional-builtins= | |||
| # checks for : | |||
| # * methods without self as first argument | |||
| # * overridden methods signature | |||
| # * access only to existant members via self | |||
| # * attributes not defined in the __init__ method | |||
| # * supported interfaces implementation | |||
| # * unreachable code | |||
| # | |||
| [CLASSES] | |||
| # List of interface methods to ignore, separated by a comma. This is used for | |||
| # instance to not check methods defines in Zope's Interface base class. | |||
| ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by | |||
| # List of method names used to declare (i.e. assign) instance attributes. | |||
| defining-attr-methods=__init__,__new__,setUp | |||
| # checks for | |||
| # * external modules dependencies | |||
| # * relative / wildcard imports | |||
| # * cyclic imports | |||
| # * uses of deprecated modules | |||
| # | |||
| [IMPORTS] | |||
| # Deprecated modules which should not be used, separated by a comma | |||
| deprecated-modules=regsub,string,TERMIOS,Bastion,rexec | |||
| # Create a graph of every (i.e. internal and external) dependencies in the | |||
| # given file (report R0402 must not be disabled) | |||
| import-graph= | |||
| # Create a graph of external dependencies in the given file (report R0402 must | |||
| # not be disabled) | |||
| ext-import-graph= | |||
| # Create a graph of internal dependencies in the given file (report R0402 must | |||
| # not be disabled) | |||
| int-import-graph= | |||
| # checks for : | |||
| # * unauthorized constructions | |||
| # * strict indentation | |||
| # * line length | |||
| # * use of <> instead of != | |||
| # | |||
| [FORMAT] | |||
| # Maximum number of characters on a single line. | |||
| max-line-length=120 | |||
| # Maximum number of lines in a module | |||
| max-module-lines=1000 | |||
| # String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 | |||
| # tab). | |||
| #indent-string=' ' | |||
| # checks for: | |||
| # * warning notes in the code like TODO | |||
| # * PEP 263: source code with non ascii character but no encoding declaration | |||
| # | |||
| [MISCELLANEOUS] | |||
| # List of note tags to take in consideration, separated by a comma. | |||
| notes=TODO | |||
| # checks for similarities and duplicated code. This computation may be | |||
| # memory / CPU intensive, so you should disable it if you experiments some | |||
| # problems. | |||
| # | |||
| [SIMILARITIES] | |||
| # Minimum lines number of a similarity. | |||
| min-similarity-lines=4 | |||
| # Ignore comments when computing similarities. | |||
| ignore-comments=yes | |||
| # Ignore docstrings when computing similarities. | |||
| ignore-docstrings=yes | |||