Browse Source

Hyde now has a auto regenerating, barebones http server

main
Lakshmi Vyasarajan 14 years ago
parent
commit
63ef5efa0b
9 changed files with 191 additions and 12 deletions
  1. +34
    -7
      hyde/engine.py
  2. +18
    -1
      hyde/fs.py
  3. +2
    -1
      hyde/generator.py
  4. +4
    -2
      hyde/layouts/test/site.yaml
  5. +1
    -0
      hyde/model.py
  6. +123
    -0
      hyde/server.py
  7. +1
    -1
      hyde/site.py
  8. +7
    -0
      hyde/tests/test_fs.py
  9. +1
    -0
      hyde/tests/test_model.py

+ 34
- 7
hyde/engine.py View File

@@ -49,7 +49,7 @@ class Engine(Application):
The create command. Creates a new site from the template at the given
sitepath.
"""
sitepath = Folder(args.sitepath)
sitepath = Folder(Folder(args.sitepath).fully_expanded_path)
if sitepath.exists and not args.overwrite:
raise HydeException(
"The given site path[%s] is not empty" % sitepath)
@@ -75,14 +75,41 @@ class Engine(Application):
The generate command. Generates the site at the given
deployment directory.
"""
sitepath = Folder(args.sitepath)
site = self.make_site(args.sitepath, args.config)
from hyde.generator import Generator
gen = Generator(site)
gen.generate_all()

@subcommand('serve', help='Serve the website')
@store('-a', '--address', default='localhost', dest='address',
help='The address where the website must be served from.')
@store('-p', '--port', type=int, default=8080, dest='port',
help='The port where the website must be served from.')
@store('-c', '--config-path', default='site.yaml', dest='config',
help='The configuration used to generate the site')
@store('-d', '--deploy-path', default='deploy',
help='Where should the site be generated?')
def serve(self, args):
"""
The serve command. Serves the site at the given
deployment directory, address and port. Regenerates
the entire site or specific files based on ths request.
"""
sitepath = Folder(Folder(args.sitepath).fully_expanded_path)
config_file = sitepath.child(args.config)
site = self.make_site(args.sitepath, args.config)
from hyde.server import HydeWebServer
server = HydeWebServer(site, args.address, args.port)
server.serve_forever()

def make_site(self, sitepath, config):
"""
Creates a site object from the given sitepath and the config file.
"""
sitepath = Folder(Folder(sitepath).fully_expanded_path)
config_file = sitepath.child(config)
logger.info("Reading site configuration from [%s]", config_file)
conf = {}
with open(config_file) as stream:
conf = yaml.load(stream)
site = Site(sitepath, Config(sitepath, conf))

from hyde.generator import Generator
gen = Generator(site)
gen.generate_all()
return Site(sitepath, Config(sitepath, conf))

+ 18
- 1
hyde/fs.py View File

@@ -27,9 +27,11 @@ class FS(object):
"""
The base file system object
"""

def __init__(self, path):
super(FS, self).__init__()
self.path = os.path.expanduser(str(path).strip().rstrip(os.sep))
self.path = os.path.expandvars(os.path.expanduser(
str(path).strip().rstrip(os.sep)))

def __str__(self):
return self.path
@@ -43,6 +45,18 @@ class FS(object):
def __ne__(self, other):
return str(self) != str(other)

@property
def fully_expanded_path(self):
"""
Returns the absolutely absolute path. Calls os.(
normpath, normcase, expandvars and expanduser).
"""
return os.path.abspath(
os.path.normpath(
os.path.normcase(
os.path.expandvars(
os.path.expanduser(self.path)))))

@property
def exists(self):
"""
@@ -142,6 +156,7 @@ class File(FS):
"""
The File object.
"""

def __init__(self, path):
super(File, self).__init__(path)

@@ -436,6 +451,7 @@ class Folder(FS):
"""
Represents a directory.
"""

def __init__(self, path):
super(Folder, self).__init__(path)

@@ -510,6 +526,7 @@ class Folder(FS):
"""
source = self
with source.walker as walker:

@walker.folder_visitor
def visit_folder(folder):
"""


+ 2
- 1
hyde/generator.py View File

@@ -81,7 +81,8 @@ class Generator(object):
if not self.template:
logger.info("Generating site at [%s]" % self.site.sitepath)
self.template = Template.find_template(self.site)
logger.info("Using [%s] as the template", self.template)
logger.info("Using [%s] as the template",
self.template.__class__.__name__)

logger.info("Configuring the template environment")
self.template.configure(self.site.config)


+ 4
- 2
hyde/layouts/test/site.yaml View File

@@ -2,6 +2,8 @@ mode: development
media_root:: media # Relative path from site root (the directory where this file exists)
media_url: /media
template: hyde.ext.jinja2
widgets:
plugins:
aggregators:
- hyde.ext.plugins.meta.MetaPlugin
- hyde.ext.plugins.auto_extend.AutoExtendPlugin
- hyde.ext.plugins.less.LessCSSPlugin
- hyde.ext.plugins.blockdown.BlockdownPlugin

+ 1
- 0
hyde/model.py View File

@@ -51,6 +51,7 @@ class Config(Expando):
layout_root='layout',
media_url='/media',
site_url='/',
not_found='404.html',
plugins = []
)
conf = dict(**default_config)


+ 123
- 0
hyde/server.py View File

@@ -0,0 +1,123 @@
"""
Contains classes and utilities for serving a site
generated from hyde.
"""
import os
import urlparse
import urllib
from SimpleHTTPServer import SimpleHTTPRequestHandler
from BaseHTTPServer import HTTPServer
from hyde.fs import File, Folder
from hyde.site import Site
from hyde.generator import Generator

import logging

logger = logging.getLogger('hyde.server')

import sys
logger.addHandler(logging.StreamHandler(sys.stdout))

class HydeRequestHandler(SimpleHTTPRequestHandler):
"""
Serves files by regenerating the resource (or)
everything when a request is issued.
"""

def do_GET(self):
"""
Idenitfy the requested path. If the query string
contains `refresh`, regenerat the entire site.
Otherwise, regenerate only the requested resource
and serve.
"""
logger.info("Processing request:[%s]" % self.path)
result = urlparse.urlparse(self.path)
query = urlparse.parse_qs(result.query)
if 'refresh' in query:
self.server.regenerate()
del query['refresh']
parts = tuple(result)
parts[4] = urllib.urlencode(query)
new_url = urlparse.urlunparse(parts)
logger.info('Redirecting...[%s]' % new_url)
self.redirect(new_url)
else:
try:
SimpleHTTPRequestHandler.do_GET(self)
except Exception, exception:
logger.error(exception.message)
site = self.server.site
res = site.content.resource_from_relative_path(
site.config.not_found)
self.redirect("/" + res.relative_deploy_path)

def translate_path(self, path):
"""
Finds the absolute path of the requested file by
referring to the `site` variable in the server.
"""
site = self.server.site
result = urlparse.urlparse(self.path)
logger.info("Trying to load file based on request:[%s]" % result.path)
path = result.path.lstrip('/')
res = site.content.resource_from_relative_path(path)
if not res:
logger.info("Cannot load file:[%s]" % path)
raise Exception("Cannot load file: [%s]" % path)
else:
self.server.generate_resource(res)
new_path = site.config.deploy_root_path.child(
res.relative_deploy_path)
return new_path

def redirect(self, path, temporary=True):
"""
Sends a redirect header with the new location.
"""
self.send_response(302 if temporary else 301)
self.send_header('Location', path)
self.end_headers()


class HydeWebServer(HTTPServer):
"""
The hyde web server that regenerates the resource, node or site when
a request is issued.
"""

def __init__(self, site, address, port):
self.site = site
self.site.load()
self.generator = Generator(self.site)

HTTPServer.__init__(self, (address, port),
HydeRequestHandler)

def __reinit__(self):
self.generator = Generator(self.site)
self.regenerate()

def regenerate(self):
"""
Regenerates the entire site.
"""
try:
logger.info('Regenerating the entire site')
self.generator.generate_all()
except Exception, exception:
logger.error('Error occured when regenerating the site [%s]'
% exception.message)
self.__reinit__()

def generate_resource(self, resource):
"""
Regenerates the entire site.
"""
try:
logger.info('Generating resource [%]' % resource)
self.generator.generate_resource(resource)
except Exception, exception:
logger.error('Error [%s] occured when generating the resource [%s]'
% (resource, repr(exception)))
self.__reinit__()

+ 1
- 1
hyde/site.py View File

@@ -311,7 +311,7 @@ class Site(object):

def __init__(self, sitepath=None, config=None):
super(Site, self).__init__()
self.sitepath = Folder(str(sitepath))
self.sitepath = Folder(Folder(sitepath).fully_expanded_path)
self.config = config if config else Config(self.sitepath)
self.content = RootNode(self.config.content_root_path, self)
self.plugins = []


+ 7
- 0
hyde/tests/test_fs.py View File

@@ -60,6 +60,13 @@ def test_path_expands_user():
f = File("~/abc/def")
assert f.path == os.path.expanduser("~/abc/def")

def test_fully_expanded_path():
f = File(__file__).parent
n = f.child_folder('../' + f.name)
e = Folder(n.fully_expanded_path)
assert n != e
assert f == e

def test_parent():
f = File(__file__)
p = f.parent


+ 1
- 0
hyde/tests/test_model.py View File

@@ -77,6 +77,7 @@ class TestConfig(object):
assert hasattr(c, 'plugins')
assert len(c.plugins) == 0
assert c.deploy_root_path == TEST_SITE_ROOT.child_folder('deploy')
assert c.not_found == '404.html'

def test_conf1(self):
c = Config(sitepath=TEST_SITE_ROOT, config_dict=yaml.load(self.conf1))


Loading…
Cancel
Save