@@ -0,0 +1,22 @@ | |||||
The MIT License | |||||
Copyright (c) 2009 - 2010 Lakshmi Vyasarajan, Ringce.com | |||||
Permission is hereby granted, free of charge, to any person obtaining a copy | |||||
of this software and associated documentation files (the "Software"), to deal | |||||
in the Software without restriction, including without limitation the rights | |||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||||
copies of the Software, and to permit persons to whom the Software is | |||||
furnished to do so, subject to the following conditions: | |||||
The above copyright notice and this permission notice shall be included in | |||||
all copies or substantial portions of the Software. | |||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||||
THE SOFTWARE. | |||||
@@ -0,0 +1,107 @@ | |||||
{% extends "root.html" %} | |||||
{% block all %} | |||||
<!doctype html> | |||||
<!-- https://github.com/paulirish/html5-boilerplate/blob/master/index.html --> | |||||
<!-- paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/ --> | |||||
<!--[if lt IE 7 ]> <html lang="en" class="no-js ie6"> <![endif]--> | |||||
<!--[if IE 7 ]> <html lang="en" class="no-js ie7"> <![endif]--> | |||||
<!--[if IE 8 ]> <html lang="en" class="no-js ie8"> <![endif]--> | |||||
<!--[if (gte IE 9)|!(IE)]><!--> <html lang="en" class="no-js"> <!--<![endif]--> | |||||
<head> | |||||
{% block starthead %}{% endblock starthead %} | |||||
<meta charset="{{page.meta.charset|default('utf-8')}}"> | |||||
<!-- Always force latest IE rendering engine (even in intranet) & Chrome Frame | |||||
Remove this if you use the .htaccess --> | |||||
<meta http-equiv="X-UA-Compatible" content="{{page.meta.compatibility|default('IE=edge,chrome=1')"> | |||||
<!-- encoding must be specified within the first 512 bytes www.whatwg.org/specs/web-apps/current-work/multipage/semantics.html#charset --> | |||||
<!-- meta element for compatibility mode needs to be before all elements except title & meta msdn.microsoft.com/en-us/library/cc288325(VS.85).aspx --> | |||||
<!-- Chrome Frame is only invoked if meta element for compatibility mode is within the first 1K bytes code.google.com/p/chromium/issues/detail?id=23003 --> | |||||
<title>{% block title %}{{page.meta.title}}{% endblock %}</title> | |||||
<meta name="description" content="{{page.meta.description}}"> | |||||
<meta name="author" content="{{page.meta.author}}"> | |||||
<!-- Mobile viewport optimized: j.mp/bplateviewport --> | |||||
<meta name="viewport" content="{{page.meta.viewport|default('width=device-width, initial-scale=1.0')"> | |||||
{% block favicons %} | |||||
<!-- Place favicon.ico & apple-touch-icon.png in the root of your domain and delete these references --> | |||||
<link rel="shortcut icon" href="{% media '/favicon.ico' %}"> | |||||
<link rel="apple-touch-icon" href="{% media '/apple-touch-icon.png' %}"> | |||||
{% endblock favicons %} | |||||
{% block css %} | |||||
<!-- CSS : implied media="all" --> | |||||
<link rel="stylesheet" href="{% media 'css/site.css' %}"> | |||||
<!-- Uncomment if you are specifically targeting less enabled mobile browsers | |||||
<link rel="stylesheet" media="handheld" href="css/handheld.css?v=2"> --> | |||||
{% endblock css %} | |||||
{% block headjs %} | |||||
<!-- All JavaScript at the bottom, except for Modernizr which enables HTML5 elements & feature detects --> | |||||
<script src="{% media 'js/libs/modernizr-1.6.min.js' %}"></script> | |||||
{% endblock headjs %} | |||||
{% block endhead %}{% endblock endhead %} | |||||
</head> | |||||
<body id="{{page.id if page.id else page.base_name}}"> | |||||
<div id="container"> | |||||
<header> | |||||
</header> | |||||
<div id="main" role="main"> | |||||
</div> | |||||
<footer> | |||||
</footer> | |||||
</div> <!--! end of #container --> | |||||
<!-- Javascript at the bottom for fast page loading --> | |||||
<!-- Grab Google CDN's jQuery. fall back to local if necessary --> | |||||
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.js"></script> | |||||
<script>!window.jQuery && document.write(unescape('%3Cscript src="js/libs/jquery-1.4.4.js"%3E%3C/script%3E'))</script> | |||||
<!-- scripts concatenated and minified via ant build script--> | |||||
<script src="js/plugins.js"></script> | |||||
<script src="js/script.js"></script> | |||||
<!-- end concatenated and minified scripts--> | |||||
<!--[if lt IE 7 ]> | |||||
<script> | |||||
// More information on tackling transparent PNGs for IE goo.gl/mZiyb | |||||
//fix any <img> or .png_bg background-images | |||||
$.getScript("js/libs/dd_belatedpng.js",function(){ DD_belatedPNG.fix('img, .png_bg'); }); | |||||
</script> | |||||
<![endif]--> | |||||
<!-- yui profiler and profileviewer - remove for production --> | |||||
<script src="js/profiling/yahoo-profiling.min.js"></script> | |||||
<script src="js/profiling/config.js"></script> | |||||
<!-- end profiling code --> | |||||
<!-- asynchronous google analytics: mathiasbynens.be/notes/async-analytics-snippet | |||||
change the UA-XXXXX-X to be your site's ID --> | |||||
<script> | |||||
var _gaq = [['_setAccount', 'UA-XXXXX-X'], ['_trackPageview']]; | |||||
(function(d, t) { | |||||
var g = d.createElement(t), | |||||
s = d.getElementsByTagName(t)[0]; | |||||
g.async = true; | |||||
g.src = ('https:' == location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; | |||||
s.parentNode.insertBefore(g, s); | |||||
})(document, 'script'); | |||||
</script> | |||||
</body> | |||||
</html> | |||||
{% endblock %} |
@@ -0,0 +1 @@ | |||||
{% block all %}{% endblock %} |
@@ -0,0 +1,16 @@ | |||||
{% extends "demo.django" %} | |||||
{%hyde | |||||
title: | |||||
description: | |||||
teaser: | |||||
standalone: generator.htm | |||||
%} | |||||
{% block introduction %} | |||||
{% endblock introduction %} | |||||
{% block documentation %} | |||||
{% endblock documentation %} |
@@ -0,0 +1,678 @@ | |||||
""" | |||||
Unified interface for performing file system tasks. Uses os, os.path. shutil | |||||
and distutil to perform the tasks. The behavior of some functions is slightly | |||||
contaminated with requirements from Hyde: For example, the backup function | |||||
deletes the directory that is being backed up. | |||||
""" | |||||
import os | |||||
import shutil | |||||
import codecs | |||||
import fnmatch | |||||
from datetime import datetime | |||||
# pylint: disable-msg=E0611 | |||||
from distutils import dir_util, file_util | |||||
@staticmethod | |||||
def filter_hidden_inplace(item_list): | |||||
""" | |||||
Given a list of filenames, removes filenames for invisible files (whose | |||||
names begin with dots) or files whose names end in tildes '~'. | |||||
Does not remove files with the filname '.htaccess'. | |||||
The list is modified in-place; this function has no return value. | |||||
""" | |||||
if not item_list: | |||||
return | |||||
wanted = filter( | |||||
lambda item: | |||||
not ((item.startswith('.') and item != ".htaccess") | |||||
or item.endswith('~')), | |||||
item_list) | |||||
count = len(item_list) | |||||
good_item_count = len(wanted) | |||||
if count == good_item_count: | |||||
return | |||||
item_list[:good_item_count] = wanted | |||||
for _ in range(good_item_count, count): | |||||
item_list.pop() | |||||
@staticmethod | |||||
def get_path_fragment(root_dir, a_dir): | |||||
""" | |||||
Gets the path fragment starting at root_dir to a_dir | |||||
""" | |||||
current_dir = a_dir | |||||
current_fragment = '' | |||||
while not current_dir == root_dir: | |||||
(current_dir, current_fragment_part) = os.path.split(current_dir) | |||||
current_fragment = os.path.join( | |||||
current_fragment_part, current_fragment) | |||||
return current_fragment | |||||
@staticmethod | |||||
def get_mirror_dir(directory, source_root, mirror_root, ignore_root = False): | |||||
""" | |||||
Returns the mirror directory from source_root to mirror_root | |||||
""" | |||||
current_fragment = get_path_fragment(source_root, directory) | |||||
if not current_fragment: | |||||
return mirror_root | |||||
mirror_directory = mirror_root | |||||
if not ignore_root: | |||||
mirror_directory = os.path.join( | |||||
mirror_root, | |||||
os.path.basename(source_root)) | |||||
mirror_directory = os.path.join( | |||||
mirror_directory, current_fragment) | |||||
return mirror_directory | |||||
@staticmethod | |||||
def mirror_dir_tree(directory, source_root, mirror_root, ignore_root = False): | |||||
""" | |||||
Create the mirror directory tree | |||||
""" | |||||
mirror_directory = get_mirror_dir( | |||||
directory, source_root, | |||||
mirror_root, ignore_root) | |||||
try: | |||||
os.makedirs(mirror_directory) | |||||
except os.error: | |||||
pass | |||||
return mirror_directory | |||||
class FileSystemEntity(object): | |||||
""" | |||||
Base class for files and folders. | |||||
""" | |||||
def __init__(self, path): | |||||
super(FileSystemEntity, self).__init__() | |||||
if path is FileSystemEntity: | |||||
self.path = path.path | |||||
else: | |||||
self.path = path | |||||
def __str__(self): | |||||
return self.path | |||||
def __repr__(self): | |||||
return self.path | |||||
def allow(self, include=None, exclude=None): | |||||
""" | |||||
Given a set of wilcard patterns in the include and exclude arguments, | |||||
tests if the patterns allow this item for processing. | |||||
The exclude parameter is processed first as a broader filter and then | |||||
include is used as a narrower filter to override the results for more | |||||
specific files. | |||||
Example: | |||||
exclude = (".*", "*~") | |||||
include = (".htaccess") | |||||
""" | |||||
if not include: | |||||
include = () | |||||
if not exclude: | |||||
exclude = () | |||||
if reduce(lambda result, | |||||
pattern: result or | |||||
fnmatch.fnmatch(self.name, pattern), include, False): | |||||
return True | |||||
if reduce(lambda result, pattern: | |||||
result and not fnmatch.fnmatch(self.name, pattern), | |||||
exclude, True): | |||||
return True | |||||
return False | |||||
@property | |||||
def humblepath(self): | |||||
""" | |||||
Expands variables, user, normalizes path and case and coverts | |||||
to absolute. | |||||
""" | |||||
return os.path.abspath( | |||||
os.path.normpath( | |||||
os.path.normcase( | |||||
os.path.expandvars( | |||||
os.path.expanduser(self.path))))) | |||||
def same_as(self, other): | |||||
""" | |||||
Checks if the path of this object is same as `other`. `other` must | |||||
be a FileSystemEntity. | |||||
""" | |||||
return (self.humblepath.rstrip(os.sep) == | |||||
other.humblepath.rstrip(os.sep)) | |||||
@property | |||||
def exists(self): | |||||
""" | |||||
Checks if the entity exists in the file system. | |||||
""" | |||||
return os.path.exists(self.path) | |||||
@property | |||||
def isdir(self): | |||||
""" | |||||
Is this a folder. | |||||
""" | |||||
return os.path.isdir(self.path) | |||||
@property | |||||
def stats(self): | |||||
""" | |||||
Shortcut for os.stat. | |||||
""" | |||||
return os.stat(self.path) | |||||
@property | |||||
def name(self): | |||||
""" | |||||
Name of the entity. Calls os.path.basename. | |||||
""" | |||||
return os.path.basename(self.path) | |||||
@property | |||||
def parent(self): | |||||
""" | |||||
The parent folder. Returns a `Folder` object. | |||||
""" | |||||
return Folder(os.path.dirname(self.path)) | |||||
def __get_destination__(self, destination): | |||||
""" | |||||
Returns a File or Folder object that would represent this entity | |||||
if it were copied or moved to `destination`. `destination` must be | |||||
an instance of File or Folder. | |||||
""" | |||||
if os.path.isdir(str(destination)): | |||||
target = destination.child(self.name) | |||||
if os.path.isdir(self.path): | |||||
return Folder(target) | |||||
else: return File(target) | |||||
else: | |||||
return destination | |||||
# pylint: disable-msg=R0904,W0142 | |||||
class File(FileSystemEntity): | |||||
""" | |||||
Encapsulates commonly used functions related to files. | |||||
""" | |||||
def __init__(self, path): | |||||
super(File, self).__init__(path) | |||||
@property | |||||
def size(self): | |||||
""" | |||||
Gets the file size | |||||
""" | |||||
return os.path.getsize(self.path) | |||||
#return 1 | |||||
def has_extension(self, extension): | |||||
""" | |||||
Checks if this file has the given extension. | |||||
""" | |||||
return self.extension == extension | |||||
def delete(self): | |||||
""" | |||||
Deletes if the file exists. | |||||
""" | |||||
if self.exists: | |||||
os.remove(self.path) | |||||
@property | |||||
def last_modified(self): | |||||
""" | |||||
Returns a datetime object representing the last modified time. | |||||
Calls os.path.getmtime. | |||||
""" | |||||
return datetime.fromtimestamp(os.path.getmtime(self.path)) | |||||
def changed_since(self, basetime): | |||||
""" | |||||
Returns True if the file has been changed since the given time. | |||||
""" | |||||
return self.last_modified > basetime | |||||
def older_than(self, another_file): | |||||
""" | |||||
Checks if this file is older than the given file. Uses last_modified to | |||||
determine age. | |||||
""" | |||||
return another_file.last_modified > self.last_modified | |||||
@property | |||||
def path_without_extension(self): | |||||
""" | |||||
The full path of the file without its extension. | |||||
""" | |||||
return os.path.splitext(self.path)[0] | |||||
@property | |||||
def name_without_extension(self): | |||||
""" | |||||
Name of the file without its extension. | |||||
""" | |||||
return os.path.splitext(self.name)[0] | |||||
@property | |||||
def extension(self): | |||||
""" | |||||
File's extension prefixed with a dot. | |||||
""" | |||||
return os.path.splitext(self.path)[1] | |||||
@property | |||||
def kind(self): | |||||
""" | |||||
File's extension without a dot prefix. | |||||
""" | |||||
return self.extension.lstrip(".") | |||||
def move_to(self, destination): | |||||
""" | |||||
Moves the file to the given destination. Returns a File | |||||
object that represents the target file. `destination` must | |||||
be a File or Folder object. | |||||
""" | |||||
shutil.move(self.path, str(destination)) | |||||
return self.__get_destination__(destination) | |||||
def copy_to(self, destination): | |||||
""" | |||||
Copies the file to the given destination. Returns a File | |||||
object that represents the target file. `destination` must | |||||
be a File or Folder object. | |||||
""" | |||||
shutil.copy(self.path, str(destination)) | |||||
return self.__get_destination__(destination) | |||||
def write(self, text, encoding="utf-8"): | |||||
""" | |||||
Writes the given text to the file using the given encoding. | |||||
""" | |||||
fout = codecs.open(self.path, 'w', encoding) | |||||
fout.write(text) | |||||
fout.close() | |||||
def read_all(self): | |||||
""" | |||||
Reads from the file and returns the content as a string. | |||||
""" | |||||
fin = codecs.open(self.path, 'r') | |||||
read_text = fin.read() | |||||
fin.close() | |||||
return read_text | |||||
# pylint: disable-msg=R0904,W0142 | |||||
class Folder(FileSystemEntity): | |||||
""" | |||||
Encapsulates commonly used directory functions. | |||||
""" | |||||
def __init__(self, path): | |||||
super(Folder, self).__init__(path) | |||||
def __str__(self): | |||||
return self.path | |||||
def __repr__(self): | |||||
return self.path | |||||
def delete(self): | |||||
""" | |||||
Deletes the directory if it exists. | |||||
""" | |||||
if self.exists: | |||||
shutil.rmtree(self.path) | |||||
def depth(self): | |||||
""" | |||||
Returns the number of ancestors of this directory. | |||||
""" | |||||
return len(self.path.split(os.sep)) | |||||
def make(self): | |||||
""" | |||||
Creates this directory and any of the missing directories in the path. | |||||
Any errors that may occur are eaten. | |||||
""" | |||||
try: | |||||
if not self.exists: | |||||
os.makedirs(self.path) | |||||
except os.error: | |||||
pass | |||||
return self | |||||
def is_parent_of(self, other_entity): | |||||
""" | |||||
Returns True if this directory is a direct parent of the the given | |||||
directory. | |||||
""" | |||||
return self.same_as(other_entity.parent) | |||||
def is_ancestor_of(self, other_entity): | |||||
""" | |||||
Returns True if this directory is in the path of the given directory. | |||||
Note that this will return True if the given directory is same as this. | |||||
""" | |||||
folder = other_entity | |||||
while not folder.parent.same_as(folder): | |||||
folder = folder.parent | |||||
if self.same_as(folder): | |||||
return True | |||||
return False | |||||
def child(self, name): | |||||
""" | |||||
Returns a path of a child item represented by `name`. | |||||
""" | |||||
return os.path.join(self.path, name) | |||||
def child_folder(self, *args): | |||||
""" | |||||
Returns a Folder object by joining the path component in args | |||||
to this directory's path. | |||||
""" | |||||
return Folder(os.path.join(self.path, *args)) | |||||
def child_folder_with_fragment(self, fragment): | |||||
""" | |||||
Returns a Folder object by joining the fragment to | |||||
this directory's path. | |||||
""" | |||||
return Folder(os.path.join(self.path, fragment.lstrip(os.sep))) | |||||
def get_fragment(self, root): | |||||
""" | |||||
Returns the path fragment of this directory starting with the given | |||||
directory. | |||||
""" | |||||
return get_path_fragment(str(root), self.path) | |||||
def get_mirror_folder(self, root, mirror_root, ignore_root=False): | |||||
""" | |||||
Returns a Folder object that reperesents if the entire fragment of this | |||||
directory starting with `root` were copied to `mirror_root`. If ignore_root | |||||
is True, the mirror does not include `root` directory itself. | |||||
Example: | |||||
Current Directory: /usr/local/hyde/stuff | |||||
root: /usr/local/hyde | |||||
mirror_root: /usr/tmp | |||||
Result: | |||||
if ignore_root == False: | |||||
Folder(/usr/tmp/hyde/stuff) | |||||
if ignore_root == True: | |||||
Folder(/usr/tmp/stuff) | |||||
""" | |||||
path = get_mirror_dir(self.path, | |||||
str(root), str(mirror_root), ignore_root) | |||||
return Folder(path) | |||||
def create_mirror_folder(self, root, mirror_root, ignore_root=False): | |||||
""" | |||||
Creates the mirror directory returned by `get_mirror_folder` | |||||
""" | |||||
mirror_folder = self.get_mirror_folder( | |||||
root, mirror_root, ignore_root) | |||||
mirror_folder.make() | |||||
return mirror_folder | |||||
def backup(self, destination): | |||||
""" | |||||
Creates a backup of this directory in the given destination. The backup is | |||||
suffixed with a number for uniqueness. Deletes this directory after backup | |||||
is complete. | |||||
""" | |||||
new_name = self.name | |||||
count = 0 | |||||
dest = Folder(destination.child(new_name)) | |||||
while(True): | |||||
dest = Folder(destination.child(new_name)) | |||||
if not dest.exists: | |||||
break | |||||
else: | |||||
count = count + 1 | |||||
new_name = self.name + str(count) | |||||
dest.make() | |||||
dest.move_contents_of(self) | |||||
self.delete() | |||||
return dest | |||||
def move_to(self, destination): | |||||
""" | |||||
Moves this directory to the given destination. Returns a Folder object | |||||
that represents the moved directory. | |||||
""" | |||||
shutil.copytree(self.path, str(destination)) | |||||
shutil.rmtree(self.path) | |||||
return self.__get_destination__(destination) | |||||
def copy_to(self, destination): | |||||
""" | |||||
Copies this directory to the given destination. Returns a Folder object | |||||
that represents the moved directory. | |||||
""" | |||||
shutil.copytree(self.path, str(destination)) | |||||
return self.__get_destination__(destination) | |||||
def move_folder_from(self, source, incremental=False): | |||||
""" | |||||
Moves the given source directory to this directory. If incremental is True | |||||
only newer objects are overwritten. | |||||
""" | |||||
self.copy_folder_from(source, incremental) | |||||
shutil.rmtree(str(source)) | |||||
def copy_folder_from(self, source, incremental=False): | |||||
""" | |||||
Copies the given source directory to this directory. If incremental is True | |||||
only newer objects are overwritten. | |||||
""" | |||||
# There is a bug in dir_util that makes copy_tree crash if a folder in | |||||
# the tree has been deleted before and readded now. To workaround the | |||||
# bug, we first walk the tree and create directories that are needed. | |||||
# | |||||
# pylint: disable-msg=C0111,W0232 | |||||
target_root = self | |||||
# pylint: disable-msg=R0903 | |||||
class _DirCreator: | |||||
@staticmethod | |||||
def visit_folder(folder): | |||||
target = folder.get_mirror_folder( | |||||
source.parent, target_root, ignore_root=True) | |||||
target.make() | |||||
source.walk(_DirCreator) | |||||
dir_util.copy_tree(str(source), | |||||
self.child(source.name), | |||||
update=incremental) | |||||
def move_contents_of(self, source, move_empty_folders=True, | |||||
incremental=False): | |||||
""" | |||||
Moves the contents of the given source directory to this directory. If | |||||
incremental is True only newer objects are overwritten. | |||||
""" | |||||
# pylint: disable-msg=C0111,W0232 | |||||
class _Mover: | |||||
@staticmethod | |||||
def visit_folder(folder): | |||||
self.move_folder_from(folder, incremental) | |||||
@staticmethod | |||||
def visit_file(a_file): | |||||
self.move_file_from(a_file, incremental) | |||||
source.list(_Mover, move_empty_folders) | |||||
def copy_contents_of(self, source, copy_empty_folders=True, | |||||
incremental=False): | |||||
""" | |||||
Copies the contents of the given source directory to this directory. If | |||||
incremental is True only newer objects are overwritten. | |||||
""" | |||||
# pylint: disable-msg=C0111,W0232 | |||||
class _Copier: | |||||
@staticmethod | |||||
def visit_folder(folder): | |||||
self.copy_folder_from(folder, incremental) | |||||
@staticmethod | |||||
def visit_file(a_file): | |||||
self.copy_file_from(a_file, incremental) | |||||
source.list(_Copier, copy_empty_folders) | |||||
def move_file_from(self, source, incremental=False): | |||||
""" | |||||
Moves the given source file to this directory. If incremental is True the | |||||
move is performed only if the source file is newer. | |||||
""" | |||||
self.copy_file_from(source, incremental) | |||||
source.delete() | |||||
def copy_file_from(self, source, incremental=False): | |||||
""" | |||||
Copies the given source file to this directory. If incremental is True the | |||||
move is performed only if the source file is newer. | |||||
""" | |||||
file_util.copy_file(str(source), self.path, update=incremental) | |||||
def list(self, visitor, list_empty_folders=True): | |||||
""" | |||||
Calls the visitor.visit_file or visitor.visit_folder for each file or folder | |||||
in this directory. If list_empty_folders is False folders that are empty are | |||||
skipped. | |||||
""" | |||||
a_files = os.listdir(self.path) | |||||
for a_file in a_files: | |||||
path = os.path.join(self.path, str(a_file)) | |||||
if os.path.isdir(path): | |||||
if not list_empty_folders: | |||||
if Folder(path).empty(): | |||||
continue | |||||
visitor.visit_folder(Folder(path)) | |||||
else: | |||||
visitor.visit_file(File(path)) | |||||
def empty(self): | |||||
""" | |||||
Checks if this directory or any of its subdirectories contain files. | |||||
""" | |||||
paths = os.listdir(self.path) | |||||
for path in paths: | |||||
if os.path.isdir(path): | |||||
if not Folder(path).empty(): | |||||
return False | |||||
else: | |||||
return False | |||||
return True | |||||
def walk(self, visitor = None, pattern = None): | |||||
""" | |||||
Walks the entire hirearchy of this directory starting with itself. | |||||
Calls visitor.visit_folder first and then calls visitor.visit_file for | |||||
any files found. After all files and folders have been exhausted | |||||
visitor.visit_complete is called. | |||||
If a pattern is provided, only the files that match the pattern are | |||||
processed. | |||||
If visitor.visit_folder returns False, the files in the folder are not | |||||
processed. | |||||
""" | |||||
def __visit_folder__(visitor, folder): | |||||
process_folder = True | |||||
if visitor and hasattr(visitor,'visit_folder'): | |||||
process_folder = visitor.visit_folder(folder) | |||||
# If there is no return value assume true | |||||
# | |||||
if process_folder is None: | |||||
process_folder = True | |||||
return process_folder | |||||
def __visit_file__(visitor, a_file): | |||||
if visitor and hasattr(visitor,'visit_file'): | |||||
visitor.visit_file(a_file) | |||||
def __visit_complete__(visitor): | |||||
if visitor and hasattr(visitor,'visit_complete'): | |||||
visitor.visit_complete() | |||||
for root, dirs, a_files in os.walk(self.path): | |||||
folder = Folder(root) | |||||
if not __visit_folder__(visitor, folder): | |||||
dirs[:] = [] | |||||
continue | |||||
for a_file in a_files: | |||||
if not pattern or fnmatch.fnmatch(a_file, pattern): | |||||
__visit_file__(visitor, File(folder.child(a_file))) | |||||
__visit_complete__(visitor) |
@@ -0,0 +1,28 @@ | |||||
""" | |||||
Unified object oriented interface for interacting with file system objects. File system operations in | |||||
python are distributed across modules: os, os.path, fnamtch, shutil and distutils. This module attempts | |||||
to make the right choices for common operations to provide a single interface. | |||||
""" | |||||
import codecs | |||||
import fnmatch | |||||
import os | |||||
import shutil | |||||
from datetime import datetime | |||||
# pylint: disable-msg=E0611 | |||||
from distutils import dir_util, file_util | |||||
class FS(object): | |||||
""" | |||||
The base file system object | |||||
""" | |||||
def __init__(self, path): | |||||
super(FS, self).__init__() | |||||
self.path = str(path) | |||||
def __str__(self): | |||||
return self.path | |||||
def __repr__(self): | |||||
return self.path |
@@ -0,0 +1,16 @@ | |||||
{% extends "demo.django" %} | |||||
{%hyde | |||||
title: | |||||
description: | |||||
teaser: | |||||
standalone: layout.htm | |||||
%} | |||||
{% block introduction %} | |||||
{% endblock introduction %} | |||||
{% block documentation %} | |||||
{% endblock documentation %} |
@@ -0,0 +1,16 @@ | |||||
{% extends "demo.django" %} | |||||
{%hyde | |||||
title: | |||||
description: | |||||
teaser: | |||||
standalone: plugin.htm | |||||
%} | |||||
{% block introduction %} | |||||
{% endblock introduction %} | |||||
{% block documentation %} | |||||
{% endblock documentation %} |
@@ -0,0 +1,14 @@ | |||||
""" | |||||
Use nose | |||||
`$ pip install nose` | |||||
`$ nosetests` | |||||
""" | |||||
from hyde.fs import FS | |||||
def test_representation(): | |||||
f = FS(__file__) | |||||
assert f.path == __file__ | |||||
assert str(f) == __file__ | |||||
assert repr(f) == __file__ | |||||
@@ -0,0 +1,16 @@ | |||||
{% extends "demo.django" %} | |||||
{%hyde | |||||
title: | |||||
description: | |||||
teaser: | |||||
standalone: theme.htm | |||||
%} | |||||
{% block introduction %} | |||||
{% endblock introduction %} | |||||
{% block documentation %} | |||||
{% endblock documentation %} |
@@ -0,0 +1,267 @@ | |||||
[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 |