diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..9dca441 --- /dev/null +++ b/AUTHORS @@ -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 diff --git a/CHANGELOG.rst b/CHANGELOG.rst index e045f20..a6148c8 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -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 ============== diff --git a/README.rst b/README.rst index e31c48c..3bb8952 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,4 @@ -Version 0.8 +Version 0.8.1 A brand new **hyde** ==================== @@ -112,8 +112,17 @@ Next Steps - Text Compressor (CSS, JS, HTML) ✓ - Image optimizer ✓ +Links +----- + +1. `Changelog`_ +2. `Authors`_ + + .. _hyde: https://github.com/lakshmivyas/hyde .. _here: http://hyde.github.com .. _Hyde Documentation: https://github.com/hyde/docs .. _Cloudpanic: https://github.com/tipiirai/cloudpanic -.. _Ringce: https://github.com/lakshmivyas/ringce/tree/v3.0 \ No newline at end of file +.. _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 diff --git a/dev-req.txt b/dev-req.txt index 210c297..4356410 100644 --- a/dev-req.txt +++ b/dev-req.txt @@ -9,7 +9,7 @@ Jinja2==2.5.5 pyquery==0.6.1 unittest2==0.5.1 mock==0.7.0b4 -nose==0.11.4 +nose==1.0.0 pep8==0.6.1 pylint==0.22.0 pysmell==0.7.3 diff --git a/hyde/ext/plugins/less.py b/hyde/ext/plugins/less.py index 575072a..4acf6bb 100644 --- a/hyde/ext/plugins/less.py +++ b/hyde/ext/plugins/less.py @@ -34,7 +34,7 @@ class LessCSSPlugin(CLTransformer): """ if not resource.source_file.kind == 'less': - return + return text import_finder = re.compile( '^\\s*@import\s+(?:\'|\")([^\'\"]*)(?:\'|\")\s*\;\s*$', re.MULTILINE) diff --git a/hyde/ext/publishers/pyfs.py b/hyde/ext/publishers/pyfs.py new file mode 100644 index 0000000..9431afb --- /dev/null +++ b/hyde/ext/publishers/pyfs.py @@ -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() + diff --git a/hyde/ext/templates/jinja.py b/hyde/ext/templates/jinja.py index 5fa3f51..6e86e1a 100644 --- a/hyde/ext/templates/jinja.py +++ b/hyde/ext/templates/jinja.py @@ -131,6 +131,9 @@ def syntax(env, value, lexer=None, filename=None): code = pygments.highlight(value, pyg, formatter) code = code.replace('\n\n', '\n \n').replace('\n', '
') 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( '
%s
%s
\n\n' % (code, caption)) diff --git a/hyde/model.py b/hyde/model.py index f9e166d..1d52203 100644 --- a/hyde/model.py +++ b/hyde/model.py @@ -67,6 +67,10 @@ class Expando(object): for k, v in d.iteritems(): if isinstance(v, Expando): 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 diff --git a/hyde/tests/test_jinja2template.py b/hyde/tests/test_jinja2template.py index f41ed93..734fd70 100644 --- a/hyde/tests/test_jinja2template.py +++ b/hyde/tests/test_jinja2template.py @@ -85,6 +85,7 @@ def test_typogrify(): """ t = Jinja2Template(JINJA2.path) t.configure(None) + t.env.filters['dateformat'] = dateformat html = t.render(source, {}).strip() assert html == u'One & two' @@ -110,6 +111,7 @@ def test_spaceless(): """ t = Jinja2Template(JINJA2.path) t.configure(None) + t.env.filters['dateformat'] = dateformat html = t.render(source, {}).strip() expected = u"""