Beispiel #1
0
 def run_gen(self):
     """Generates the static site."""
     if not CONFIG.SITE.ENGINES:
         message = "All engines are inactive -- nothing to generate."
         console(message, is_bright=True, color='red')
     else:
         generator.run()
Beispiel #2
0
    def create_widgets(self, engine=None):
        """Create widgets from engine or site."""
        if engine is not None:
            try:
                widgets = engine.config.WIDGETS
            except AttributeError:
                return
        else:
            widgets = self.config.SITE.WIDGETS

        for widget in widgets:
            if engine is not None:
                message = "Creating engine widget: %s" % widget
            else:
                message = "Creating site widget: %s" % widget
            console(message)
            self.logger.debug(message)

            try:
                widget_func = getattr(self.widgets_mod, widget)
            except AttributeError:
                message = "Widget %s not found." % widget
                self.logger.error(message)
                self.logger.debug(format_exc())
                raise

            if engine is not None:
                # engine widgets work on their engine instances
                self.widgets[widget] = widget_func(engine)
            else:
                # site widgets work on this site instance
                self.widgets[widget] = widget_func(self)
            self.logger.debug("created: %s widget" % widget)
Beispiel #3
0
def main(cli_arglist=None):
    """Main execution routine.

    cli_arglist -- List of arguments passed to the command line.

    """
    session = Runner()
    try:
        cmd = session.build_parsers().parse_args(cli_arglist)

        # only build logger if we're not starting a new project
        # or just checking version
        if cmd.name not in ['demo', 'init', 'version']:
            session.build_logger()
            # attach parsed object to the package-wide config
            setattr(CONFIG, 'CMD', cmd)
            os.chdir(CONFIG.VOLT.ROOT_DIR)

        logger = logging.getLogger('main')
        logger.debug("running: %s" % cmd.name)
        cmd.run()
    except ConfigNotFoundError:
        message = "You can only run 'volt %s' inside a Volt project directory." % \
                cmd.name
        console("Error: %s" % message, color='red', is_bright=True)
        console("Start a Volt project by running 'volt init' inside an empty directory.")

        if os.path.exists('volt.log'):
            os.remove('volt.log')

        sys.exit(1)
Beispiel #4
0
 def run_demo(self):
     """Runs a quick demo of Volt."""
     # copy demo files
     self.run_init(is_demo=True)
     console("\nPreparing your lightning-speed Volt tour...",  is_bright=True)
     # need to pass arglist to serve, so we'll call main
     main(['serve'])
Beispiel #5
0
    def run_init(self, is_demo=False):
        """Starts a new Volt project.

        init -- String, must be 'init' or 'demo', denotes which starting files
                will be copied into the current directory.

        """
        cmd_name = 'init' if not is_demo else 'demo'
        dir_content = os.listdir(os.curdir)
        if dir_content != [] and dir_content != ['volt.log']:
            message = "'volt %s' must be run inside an empty directory." % cmd_name
            console("Error: %s" % message, color='red', is_bright=True)
            sys.exit(1)

        # get volt installation directory and demo dir
        target_path = os.path.join(os.path.dirname(__file__), 'templates', cmd_name)

        # we only need the first layer to do the copying
        parent_dir, child_dirs, top_files = os.walk(target_path).next()

        # copy all files in parent that's not a .pyc file
        for top in [x for x in top_files if not x.endswith('.pyc')]:
            shutil.copy2(os.path.join(parent_dir, top), os.curdir)
        # copy all child directories
        for child in child_dirs:
            shutil.copytree(os.path.join(parent_dir, child), child)

        if not is_demo:
            console("\nVolt project started. Have fun!\n", is_bright=True)
Beispiel #6
0
 def run_serve(self):
     """Generates the static site, and if successful, runs the Volt server."""
     self.run_gen()
     if not os.path.exists(CONFIG.VOLT.SITE_DIR):
         message = "Site directory not found -- nothing to serve."
         console(message, is_bright=True, color='red')
     else:
         server.run()
Beispiel #7
0
 def prepare_output(self):
     """Copies the asset directory contents to site directory."""
     message = "Preparing output directory: %s" % self.config.VOLT.SITE_DIR
     console(message)
     self.logger.debug(message)
     if os.path.exists(self.config.VOLT.SITE_DIR):
         shutil.rmtree(self.config.VOLT.SITE_DIR)
     shutil.copytree(self.config.VOLT.ASSET_DIR, self.config.VOLT.SITE_DIR, \
             ignore=shutil.ignore_patterns(self.config.SITE.IGNORE_PATTERN))
Beispiel #8
0
 def dispatch_engines(self):
     """Runs the engines' dispatch method."""
     for engine in self.engines:
         message = "Dispatching %s engine to URL '%s'" % \
                 (engine.lower(), self.engines[engine].config.URL)
         console(message)
         self.logger.debug(message)
         # attach all widgets to each engine, so they're accessible in templates
         self.engines[engine].widgets = self.widgets
         # dispatch them
         self.engines[engine].dispatch()
Beispiel #9
0
    def run_ext(self):
        """Adds template for engine, plugin, or widget."""
        builtin = CONFIG.CMD.builtin
        template = CONFIG.CMD.template
        volt_dir = os.path.dirname(__file__)
        template_source = os.path.join(volt_dir, 'templates')

        if template == 'widget':
            # if template type is widget, only copy / create if it's not
            # present already
            if not os.path.exists(CONFIG.VOLT.USER_WIDGET):

                # if builtin is not an empty string, get the default widgets
                if builtin:
                    builtin_dir = os.path.join(volt_dir, 'config')
                    shutil.copy2(os.path.join(builtin_dir, 'default_widgets.py'),
                        os.path.join(os.curdir, 'widgets.py'))
                # otherwise get the widget template
                else:
                    shutil.copy2(os.path.join(template_source, 'widgets.py'),
                        os.curdir)
        else:
            template_dir = os.path.join(os.getcwd(), template + 's')

            # create plugin / engine dir in the root dir
            # unless it's there already
            if not os.path.exists(template_dir):
                os.mkdir(template_dir)

            # if builtin is specified, try to get the builtin plugin/engine
            if builtin:
                builtin_dir = os.path.join(volt_dir, template, 'builtins')
                try:
                    if builtin == 'atomic':
                        shutil.copytree(os.path.join(builtin_dir, builtin), \
                                os.path.join(template_dir, builtin))
                    else:
                        shutil.copy2(os.path.join(builtin_dir, builtin + '.py'), \
                                template_dir)
                except IOError:
                    message = "Builtin %s '%s' not found." % (template, builtin)
                    console("Error: %s" % message, color='red', is_bright=True)
                    sys.exit(1)

            # otherwise copy the plugin/engine template
            else:
                template_file = template + '.py'
                if not os.path.exists(os.path.join(template_dir, template_file)):
                    shutil.copy2(os.path.join(template_source, template_file), \
                            template_dir)
Beispiel #10
0
def run():
    """Generates the site."""
    logger = logging.getLogger('gen')

    sys.stdout.write("\n")
    message = "Volt %s Static Site Generator" % VERSION
    console(message, is_bright=True)
    logger.debug(message)

    # generate the site!
    start_time = time()
    Site().create()

    message = "Site generated in %.3fs" % (time() - start_time)
    console(message, color='yellow')
    logger.debug(message)
    sys.stdout.write('\n')
Beispiel #11
0
    def run_plugins(self, engine=None):
        """Runs plugins on engine or site."""
        if engine is not None:
            try:
                plugins = engine.config.PLUGINS
            except AttributeError:
                return
        else:
            plugins = self.config.SITE.PLUGINS

        for plugin in plugins:
            if engine is not None:
                message = "Running engine plugin: %s" % (plugin)
            else:
                message = "Running site plugin: %s" % plugin
            console(message)
            self.logger.debug(message)

            if not plugin in self.plugins:
                try:
                    plugin_class = self.get_processor(plugin, 'plugins')
                except ImportError:
                    message = "Plugin %s not found." % plugin
                    self.logger.error(message)
                    self.logger.debug(format_exc())
                    raise

                self.plugins[plugin] = plugin_class()
                self.plugins[plugin].prime()

            if engine is not None:
                # engine plugins work on their engine instances
                self.plugins[plugin].run(engine)
            else:
                # site plugins work on this site instance
                self.plugins[plugin].run(self)

            # attach plugin config values (if defined) for access in templates
            if self.plugins[plugin].USER_CONF_ENTRY is not None:
                setattr(self.config, self.plugins[plugin].USER_CONF_ENTRY, \
                        self.plugins[plugin].config)

            self.logger.debug("ran: %s plugin" % plugin)
Beispiel #12
0
    def activate_engines(self):
        """Activates all engines according to the configurations.

        This method consists of four steps:

            1. Engine priming: all engines listed in CONFIG.SITE.ENGINES are
               loaded. Any engines found in the user directory takes
               precedence over built-in engines. The default settings in each
               engine are then consolidated with the user's setting in
               voltconf.py to yield the final configurations that will be used
               in subsequent engine methods.

            2. Engine preprocessing: all the engines' preprocess() method are
               then run. Any unit processing that happens before the plugins
               are run is done by the preprocess method.

            3. Plugin run: plugins targeting each engine are run to process the
               the target engines' units. Similar to engines, plugins are also
               primed to consolidate the default and user configurations.

            4. Widget creation: widgets for each engine are created and made
               accessible from the any templates.
        """
        for engine_name in self.config.SITE.ENGINES:
            engine_class = self.get_processor(engine_name, 'engines')
            engine = engine_class()
            message = "Engine loaded: %s" % engine_name.capitalize()
            console(message, color='cyan')
            self.logger.debug(message)

            engine.prime()
            self.logger.debug('done: priming %s' % engine_class.__name__)

            engine.preprocess()
            self.logger.debug('done: preprocessing %s' % engine_class.__name__)

            self.run_plugins(engine)
            self.create_widgets(engine)
            self.engines[engine_name] = engine

            # attach engine config values for access in templates
            setattr(self.config, self.engines[engine_name].USER_CONF_ENTRY, \
                    self.engines[engine_name].config)
Beispiel #13
0
def github_search(site):
    """Site widget for returning github repo search, sorted on last push time.
    
    Example usage:
        {% for item in widgets.github_search %}
            <a href="{{ item.url }}">{{ item.name }} ({{ item.watchers }})</a>
        {% endfor %}
    """
    import json
    try: #try python3 first
        from urllib.request import urlopen
        from urllib.parse import urlencode
    except ImportError: # fallback to python2
        from urllib import urlencode, urlopen
    from datetime import datetime
    from volt.utils import console

    # set our search parameters
    query_string = 'static website'
    args = {'language': 'Python'}
    base_url = 'http://github.com/api/v2/json/repos/search/'

    # retrieve search results using urllib and json
    query = '%s%s' % (query_string.replace(' ', '+'), '?' + urlencode(args))
    try:
        response = urlopen(base_url + query).read().decode('utf-8')
    except IOError:
        console("WARNING: github_search can not connect to the internet.\n", \
                color='red', is_bright=True)
        return []
    data = json.loads(response)['repositories']

    # get repos with at least 10 watchers
    results = [repo for repo in data if repo['watchers'] >= 10]

    # finally, we'll sort our selection ~ most recent push time first
    def gettime(datestr, format="%Y/%m/%d %H:%M:%S"):
        return datetime.strptime(datestr[:-6], format)
    results.sort(key=lambda x: gettime(x['pushed_at']), reverse=True)

    return results
Beispiel #14
0
    def write_site_pages(self):
        """Write site pages, such as a separate index.html or 404.html."""
        for filename in self.config.SITE.PAGES:
            message = "Writing site page: '%s'" % filename
            console(message)
            self.logger.debug(message)

            template = self.config.SITE.TEMPLATE_ENV.get_template(filename)
            path = os.path.join(self.config.VOLT.SITE_DIR, filename)
            if os.path.exists(path):
                message = "File %s already exists. Make sure there are no "\
                          "other entries leading to this file path." % path
                console("Error: %s" % message, is_bright=True, color='red')
                self.logger.error(message)
                sys.exit(1)

            rendered = template.render(page={}, CONFIG=self.config, \
                    widgets=self.widgets)
            if sys.version_info[0] < 3:
                rendered = rendered.encode('utf-8')
            write_file(path, rendered)
Beispiel #15
0
    def process_request(self, request, client_address):
        """Finishes one request by instantiating the handler class.

        Prior to handler class initialization, this method checks the latest
        timestamp of all directories inside the Volt project. If the result
        is higher than the prior timestamp (self.last_mtime), then the entire
        site will be regenerated.

        """
        latest_mtime = self.check_dirs_mtime()

        if self.last_mtime < latest_mtime:
            message = "Source file modification detected -- regenerating site"
            console(message, color='yellow')
            self.logger.debug(message)

            self.last_mtime = latest_mtime
            CONFIG.reset()
            generator.run()
            self.logger.debug('done: regenerating site')

        ThreadingTCPServer.process_request(self, request, client_address)
Beispiel #16
0
    def log_message(self, format, *args):
        # overrides parent log_message to provide a more compact output.
        message = format % args

        if int(args[1]) >= 400:
            console(message, color='red')
        elif int(args[1]) >= 300:
            console(message, color='cyan')
        else:
            console(message)
        
        self.logger.debug(message)
Beispiel #17
0
                  13: "You don't have permission to access port %s" % 
                      (CONFIG.CMD.server_port),
                  98: "Port %s already in use" % (CONFIG.CMD.server_port)}
        try:
            message = ERRORS[e.args[0]]
        except (AttributeError, KeyError):
            message = str(e)
        logger.error(message)
        sys.exit(1)

    run_address, run_port = server.socket.getsockname()
    if run_address == '127.0.0.1':
        run_address = 'localhost'

    message = "Volt %s Development Server" % VERSION
    console(message, is_bright=True)
    logger.debug(message)

    message = "Serving %s" % CONFIG.VOLT.SITE_DIR
    console(message)
    logger.debug(message)

    message = "Running at http://%s:%s" % (run_address, run_port)
    console(message)
    logger.debug(message)

    try:
        server.serve_forever()
    except KeyboardInterrupt:
        server.shutdown()
    finally:
Beispiel #18
0
 def error(self, message):
     console("\nError: %s" % message, color='red', is_bright=True)
     self.print_usage()
     sys.stdout.write("\n")
     sys.exit(1)
Beispiel #19
0
 def run_version(self):
     """Shows version number."""
     console("Volt %s" % VERSION)
Beispiel #20
0
 def run_version(self):
     """Shows version number."""
     console("Volt %s" % __version__)