Browse Source

Merge branch 'master' into pestaa/patch-1

main
Lakshmi Vyasarajan 13 years ago
parent
commit
9c45dad4c2
11 changed files with 163 additions and 6 deletions
  1. +24
    -0
      AUTHORS
  2. +9
    -0
      CHANGELOG.rst
  3. +11
    -2
      README.rst
  4. +1
    -1
      dev-req.txt
  5. +1
    -1
      hyde/ext/plugins/less.py
  6. +99
    -0
      hyde/ext/publishers/pyfs.py
  7. +3
    -0
      hyde/ext/templates/jinja.py
  8. +4
    -0
      hyde/model.py
  9. +9
    -0
      hyde/tests/test_jinja2template.py
  10. +1
    -1
      hyde/version.py
  11. +1
    -1
      requirements.txt

+ 24
- 0
AUTHORS View File

@@ -0,0 +1,24 @@
Hyde is primarily developed and maintained by [Lakshmi Vyasarajan][1]. The new
version of Hyde is sponsored by [Flowplayer][2] and [Tero Piirainen][3].

This version would not exist without the contributions for the
[original hyde project][4].

Contributors
=============


- @rfk

* Bug fixes
* Pyfs publisher with mimetype and etags support

- @tinnet

* Bug fixes (Default template, Syntax template tag)


[1]: http://twitter.com/lakshmivyas
[2]: http://flowplayer.org
[3]: http://cloudpanic.com
[4]: http://github.com/lakshmivyas/hyde

+ 9
- 0
CHANGELOG.rst View File

@@ -1,3 +1,12 @@
Version 0.8.1
=============

Thanks to @rfk.

* Updated to use nose 1.0
* Bug fixes to Less CSS
* PyFS publisher with mimetypes and etags support.

Version 0.8 Version 0.8
============== ==============




+ 11
- 2
README.rst View File

@@ -1,4 +1,4 @@
Version 0.8
Version 0.8.1


A brand new **hyde** A brand new **hyde**
==================== ====================
@@ -112,8 +112,17 @@ Next Steps
- Text Compressor (CSS, JS, HTML) ✓ - Text Compressor (CSS, JS, HTML) ✓
- Image optimizer ✓ - Image optimizer ✓


Links
-----

1. `Changelog`_
2. `Authors`_


.. _hyde: https://github.com/lakshmivyas/hyde .. _hyde: https://github.com/lakshmivyas/hyde
.. _here: http://hyde.github.com .. _here: http://hyde.github.com
.. _Hyde Documentation: https://github.com/hyde/docs .. _Hyde Documentation: https://github.com/hyde/docs
.. _Cloudpanic: https://github.com/tipiirai/cloudpanic .. _Cloudpanic: https://github.com/tipiirai/cloudpanic
.. _Ringce: https://github.com/lakshmivyas/ringce/tree/v3.0
.. _Ringce: https://github.com/lakshmivyas/ringce/tree/v3.0
.. _Authors: https://github.com/hyde/hyde/blob/master/AUTHORS
.. _Changelog: https://github.com/hyde/hyde/blob/master/CHANGELOG.rst

+ 1
- 1
dev-req.txt View File

@@ -9,7 +9,7 @@ Jinja2==2.5.5
pyquery==0.6.1 pyquery==0.6.1
unittest2==0.5.1 unittest2==0.5.1
mock==0.7.0b4 mock==0.7.0b4
nose==0.11.4
nose==1.0.0
pep8==0.6.1 pep8==0.6.1
pylint==0.22.0 pylint==0.22.0
pysmell==0.7.3 pysmell==0.7.3

+ 1
- 1
hyde/ext/plugins/less.py View File

@@ -34,7 +34,7 @@ class LessCSSPlugin(CLTransformer):
""" """


if not resource.source_file.kind == 'less': if not resource.source_file.kind == 'less':
return
return text
import_finder = re.compile( import_finder = re.compile(
'^\\s*@import\s+(?:\'|\")([^\'\"]*)(?:\'|\")\s*\;\s*$', '^\\s*@import\s+(?:\'|\")([^\'\"]*)(?:\'|\")\s*\;\s*$',
re.MULTILINE) re.MULTILINE)


+ 99
- 0
hyde/ext/publishers/pyfs.py View File

@@ -0,0 +1,99 @@
"""
Contains classes and utilities that help publishing a hyde website to
a filesystem using PyFilesystem FS objects.

This publisher provides an easy way to publish to FTP, SFTP, WebDAV or other
servers by specifying a PyFS filesystem URL. For example, the following
are valid URLs that can be used with this publisher:

ftp://my.server.com/~username/my_blog/
dav:https://username:password@my.server.com/path/to/my/site

"""

import getpass
import hashlib

from hyde.fs import File, Folder
from hyde.publisher import Publisher

from hyde.util import getLoggerWithNullHandler
logger = getLoggerWithNullHandler('hyde.ext.publishers.pyfs')


from fs.osfs import OSFS
from fs.path import pathjoin
from fs.opener import fsopendir



class PyFS(Publisher):

def initialize(self, settings):
self.settings = settings
self.url = settings.url
self.check_mtime = getattr(settings,"check_mtime",False)
self.check_etag = getattr(settings,"check_etag",False)
if self.check_etag and not isinstance(self.check_etag,basestring):
raise ValueError("check_etag must name the etag algorithm")
self.prompt_for_credentials()
self.fs = fsopendir(self.url)

def prompt_for_credentials(self):
credentials = {}
if "%(username)s" in self.url:
print "Username: ",
credentials["username"] = raw_input().strip()
if "%(password)s" in self.url:
credentials["password"] = getpass.getpass("Password: ")
if credentials:
self.url = self.url % credentials

def publish(self):
super(PyFS, self).publish()
deploy_fs = OSFS(self.site.config.deploy_root_path.path)
for (dirnm,local_filenms) in deploy_fs.walk():
logger.info("Making directory: %s",dirnm)
self.fs.makedir(dirnm,allow_recreate=True)
remote_fileinfos = self.fs.listdirinfo(dirnm,files_only=True)
# Process each local file, to see if it needs updating.
for filenm in local_filenms:
filepath = pathjoin(dirnm,filenm)
# Try to find an existing remote file, to compare metadata.
for (nm,info) in remote_fileinfos:
if nm == filenm:
break
else:
info = {}
# Skip it if the etags match
if self.check_etag and "etag" in info:
with deploy_fs.open(filepath,"rb") as f:
local_etag = self._calculate_etag(f)
if info["etag"] == local_etag:
logger.info("Skipping file [etag]: %s",filepath)
continue
# Skip it if the mtime is more recent remotely.
if self.check_mtime and "modified_time" in info:
local_mtime = deploy_fs.getinfo(filepath)["modified_time"]
if info["modified_time"] > local_mtime:
logger.info("Skipping file [mtime]: %s",filepath)
continue
# Upload it to the remote filesystem.
logger.info("Uploading file: %s",filepath)
with deploy_fs.open(filepath,"rb") as f:
self.fs.setcontents(filepath,f)
# Process each remote file, to see if it needs deleting.
for (filenm,info) in remote_fileinfos:
filepath = pathjoin(dirnm,filenm)
if filenm not in local_filenms:
logger.info("Removing file: %s",filepath)
self.fs.remove(filepath)

def _calculate_etag(self,f):
hasher = getattr(hashlib,self.check_etag.lower())()
data = f.read(1024*64)
while data:
hasher.update(data)
data = f.read(1024*64)
return hasher.hexdigest()


+ 3
- 0
hyde/ext/templates/jinja.py View File

@@ -131,6 +131,9 @@ def syntax(env, value, lexer=None, filename=None):
code = pygments.highlight(value, pyg, formatter) code = pygments.highlight(value, pyg, formatter)
code = code.replace('\n\n', '\n&nbsp;\n').replace('\n', '<br />') code = code.replace('\n\n', '\n&nbsp;\n').replace('\n', '<br />')
caption = filename if filename else pyg.name caption = filename if filename else pyg.name
if hasattr(env.config, 'syntax'):
if not getattr(env.config.syntax, 'use_figure', True):
return Markup(code)
return Markup( return Markup(
'<figure class="code">%s<figcaption>%s</figcaption></figure>\n\n' '<figure class="code">%s<figcaption>%s</figcaption></figure>\n\n'
% (code, caption)) % (code, caption))


+ 4
- 0
hyde/model.py View File

@@ -67,6 +67,10 @@ class Expando(object):
for k, v in d.iteritems(): for k, v in d.iteritems():
if isinstance(v, Expando): if isinstance(v, Expando):
d[k] = v.to_dict() d[k] = v.to_dict()
elif isinstance(v, (tuple, list, set, frozenset)):
seq = type(v)
d[k] = seq(item.to_dict() if isinstance(item, Expando)
else item for item in v)
return d return d






+ 9
- 0
hyde/tests/test_jinja2template.py View File

@@ -85,6 +85,7 @@ def test_typogrify():
""" """
t = Jinja2Template(JINJA2.path) t = Jinja2Template(JINJA2.path)
t.configure(None) t.configure(None)
t.env.filters['dateformat'] = dateformat
html = t.render(source, {}).strip() html = t.render(source, {}).strip()
assert html == u'One <span class="amp">&amp;</span>&nbsp;two' assert html == u'One <span class="amp">&amp;</span>&nbsp;two'


@@ -110,6 +111,7 @@ def test_spaceless():
""" """
t = Jinja2Template(JINJA2.path) t = Jinja2Template(JINJA2.path)
t.configure(None) t.configure(None)
t.env.filters['dateformat'] = dateformat
html = t.render(source, {}).strip() html = t.render(source, {}).strip()
expected = u""" expected = u"""
<html><body><ul><li> <html><body><ul><li>
@@ -146,6 +148,7 @@ def test_markdown_with_extensions():
c = Config(JINJA2.path, config_dict=dict(markdown=dict(extensions=['headerid']))) c = Config(JINJA2.path, config_dict=dict(markdown=dict(extensions=['headerid'])))
s.config = c s.config = c
t.configure(s) t.configure(s)
t.env.filters['dateformat'] = dateformat
html = t.render(source, {}).strip() html = t.render(source, {}).strip()
assert html == u'<h3 id="heading_3">Heading 3</h3>' assert html == u'<h3 id="heading_3">Heading 3</h3>'


@@ -162,6 +165,7 @@ def test_line_statements():
c = Config(JINJA2.path, config_dict=dict(markdown=dict(extensions=['headerid']))) c = Config(JINJA2.path, config_dict=dict(markdown=dict(extensions=['headerid'])))
s.config = c s.config = c
t.configure(s) t.configure(s)
t.env.filters['dateformat'] = dateformat
html = t.render(source, {}).strip() html = t.render(source, {}).strip()
assert html == u'<h3 id="heading_3">Heading 3</h3>' assert html == u'<h3 id="heading_3">Heading 3</h3>'


@@ -184,6 +188,7 @@ def test_line_statements_with_config():
s = Site(JINJA2.path) s = Site(JINJA2.path)
s.config = Config(JINJA2.path, config_dict=yaml.load(config)) s.config = Config(JINJA2.path, config_dict=yaml.load(config))
t.configure(s) t.configure(s)
t.env.filters['dateformat'] = dateformat
html = t.render(source, {}).strip() html = t.render(source, {}).strip()
assert html == u'<h3 id="heading_3">Heading 3</h3>' assert html == u'<h3 id="heading_3">Heading 3</h3>'


@@ -221,6 +226,7 @@ class TestJinjaTemplate(object):
def test_depends(self): def test_depends(self):
t = Jinja2Template(JINJA2.path) t = Jinja2Template(JINJA2.path)
t.configure(None) t.configure(None)
t.env.filters['dateformat'] = dateformat
deps = list(t.get_dependencies('index.html')) deps = list(t.get_dependencies('index.html'))
assert len(deps) == 2 assert len(deps) == 2


@@ -258,6 +264,7 @@ class TestJinjaTemplate(object):
gen = Generator(site) gen = Generator(site)
gen.load_template_if_needed() gen.load_template_if_needed()
template = gen.template template = gen.template
template.env.filters['dateformat'] = dateformat
html = template.render(text, {}).strip() html = template.render(text, {}).strip()


assert html assert html
@@ -538,6 +545,7 @@ two:
""" """
t = Jinja2Template(JINJA2.path) t = Jinja2Template(JINJA2.path)
t.configure(None) t.configure(None)
t.env.filters['dateformat'] = dateformat
html = t.render(text, {}).strip() html = t.render(text, {}).strip()
actual = PyQuery(html) actual = PyQuery(html)
assert actual("ul").length == 2 assert actual("ul").length == 2
@@ -580,6 +588,7 @@ item_list:
""" """
t = Jinja2Template(JINJA2.path) t = Jinja2Template(JINJA2.path)
t.configure(None) t.configure(None)
t.env.filters['dateformat'] = dateformat
html = t.render(text, {}).strip() html = t.render(text, {}).strip()
print html print html
actual = PyQuery(html) actual = PyQuery(html)


+ 1
- 1
hyde/version.py View File

@@ -3,4 +3,4 @@
Handles hyde version Handles hyde version
TODO: Use fabric like versioning scheme TODO: Use fabric like versioning scheme
""" """
__version__ = '0.8'
__version__ = '0.8.1'

+ 1
- 1
requirements.txt View File

@@ -5,4 +5,4 @@ Markdown
MarkupSafe MarkupSafe
smartypants smartypants
-e git://github.com/hyde/typogrify.git#egg=typogrify -e git://github.com/hyde/typogrify.git#egg=typogrify
Jinja2
Jinja2

Loading…
Cancel
Save