Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
68 changed files
with
554 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,3 +2,4 @@ include README.rst | |
include requirements.txt | ||
include LICENSE | ||
include Changelog | ||
recursive-include pyserve/static * |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
" Define web application. " | ||
|
||
import bottle | ||
|
||
|
||
APP = bottle.Bottle() | ||
|
||
|
||
@APP.route('/__serve_static__/<path:re:.*>') | ||
def static(path): | ||
return bottle.static_file(path, APP.config.static) | ||
|
||
|
||
@APP.route('/') | ||
@APP.route('/<path:re:.*>') | ||
def index(path=''): | ||
try: | ||
entry = APP.config.root.parse(path) | ||
|
||
if entry.is_file(): | ||
return bottle.static_file(path, APP.config.root.abspath) | ||
|
||
if APP.config.autoindex: | ||
index = [e for e in entry.entries if e.name in ['index.html', 'index.htm']] | ||
if index: | ||
return bottle.static_file(index[0].path, APP.config.root.abspath) | ||
|
||
return bottle.template('_pyserve_.html', | ||
template_lookup=[APP.config.static], | ||
dir=entry, | ||
app=APP) | ||
|
||
except IOError, e: | ||
return e | ||
bottle.redirect('/') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
from datetime import datetime | ||
from os import path as op, listdir | ||
|
||
from icons import ICONS_BY_EXT, ICONS_BY_NAME | ||
|
||
|
||
def compare(e1, e2): | ||
if type(e1) is not type(e2): | ||
return 1 if type(e1) is File else -1 | ||
return cmp(e1.name, e2.name) | ||
|
||
|
||
class Entry(object): | ||
|
||
default_icon = 'cross.png' | ||
|
||
def __init__(self, path, root=None): | ||
self.root = root | ||
self.path = path | ||
self.abspath = root.join(path) | ||
self.name = op.basename(self.abspath) | ||
self.hidden = self.name.startswith('.') | ||
|
||
def __new__(self, path, root=None): | ||
if not root or not path or path == '/': | ||
return RootDirectory.__new__(RootDirectory, path) | ||
|
||
else: | ||
|
||
abspath = root.join(path) | ||
if op.isdir(abspath): | ||
return Directory.__new__(Directory, path, root) | ||
|
||
elif op.isfile(abspath): | ||
return File.__new__(File, path, root) | ||
|
||
else: | ||
raise IOError('{0} does not exists.'.format(abspath)) | ||
|
||
def join(self, path): | ||
path = path.strip('/') | ||
return op.join(self.abspath, path) if path else self.abspath | ||
|
||
def parse(self, path): | ||
abspath = op.abspath(self.join(path)) | ||
if self.abspath == abspath: | ||
return self | ||
return Entry(path, root=self) | ||
|
||
@staticmethod | ||
def is_file(): | ||
return False | ||
|
||
@property | ||
def link(self): | ||
if not self.path.startswith('/'): | ||
return "/" + self.path | ||
return self.path | ||
|
||
@property | ||
def icon(self): | ||
return self.default_icon | ||
|
||
@property | ||
def modified(self): | ||
return datetime.fromtimestamp(op.getmtime(self.abspath)) | ||
|
||
@property | ||
def size(self): | ||
return op.getsize(self.abspath) | ||
|
||
def __str__(self): | ||
return "<%s [%s]>" % (self.__class__.__name__, self.abspath) | ||
|
||
__repr__ = __str__ | ||
|
||
|
||
class Directory(Entry): | ||
default_icon = 'folder.png' | ||
|
||
def __new__(self, *args, **kwargs): | ||
return object.__new__(Directory, *args, **kwargs) | ||
|
||
@property | ||
def breadcrumb(self): | ||
paths = [''] + self.abspath[len(self.root.abspath):].split('/') | ||
paths.pop() | ||
breadcrumb = [] | ||
while paths: | ||
path = op.join(*paths) | ||
paths.pop() | ||
breadcrumb.append(Entry(path, root=self.root)) | ||
return reversed(list(enumerate(breadcrumb))) | ||
|
||
def is_root(self): | ||
return self == self.root | ||
|
||
@property | ||
def entries(self): | ||
entries = [] | ||
|
||
for path in listdir(self.abspath): | ||
entries.append(Entry(op.join(self.path, path), self.root)) | ||
entries = sorted(entries, cmp=compare) | ||
|
||
if not self.is_root(): | ||
entries.insert(0, ParentDirectory(self.path, self.root)) | ||
|
||
return entries | ||
|
||
|
||
class File(Entry): | ||
default_icon = 'file.png' | ||
|
||
def __new__(self, *args, **kwargs): | ||
return object.__new__(File, *args, **kwargs) | ||
|
||
def __init__(self, *args, **kwargs): | ||
super(File, self).__init__(*args, **kwargs) | ||
self.ext = op.splitext(self.name)[1].strip('.') | ||
|
||
@staticmethod | ||
def is_file(): | ||
return True | ||
|
||
@property | ||
def icon(self): | ||
return ICONS_BY_NAME.get( | ||
self.name, | ||
ICONS_BY_EXT.get( | ||
self.ext, | ||
self.default_icon | ||
)) | ||
|
||
|
||
class RootDirectory(Directory): | ||
default_icon = 'root.png' | ||
|
||
def __init__(self, path, root=None): | ||
self.abspath = op.abspath(path) | ||
super(RootDirectory, self).__init__('/', self) | ||
self.name = 'root' | ||
|
||
def __new__(self, *args, **kwargs): | ||
return object.__new__(RootDirectory, *args, **kwargs) | ||
|
||
@property | ||
def breadcrumb(self): | ||
return [] | ||
|
||
@property | ||
def link(self): | ||
return self.path | ||
|
||
|
||
class ParentDirectory(Directory): | ||
default_icon = 'parent.png' | ||
|
||
def __init__(self, path, root=None): | ||
path = op.dirname(path) | ||
super(ParentDirectory, self).__init__(path, root=root) | ||
self.name = '..' | ||
|
||
def __new__(self, *args, **kwargs): | ||
return object.__new__(ParentDirectory, *args, **kwargs) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
by_ext = [ | ||
('py.png', 'py'), | ||
('python.png', 'pyc'), | ||
('page_white_text_width.png', ['md', 'markdown', 'rst', 'rtf']), | ||
('page_white_text.png', 'txt'), | ||
('page_white_code.png', ['html', 'htm', 'cgi']), | ||
('page_white_visualstudio.png', ['asp', 'vb']), | ||
('page_white_ruby.png', 'rb'), | ||
('page_code.png', 'xhtml'), | ||
('page_white_code_red.png', ['xml', 'xsl', 'xslt', 'yml']), | ||
('script.png', ['js', 'json', 'applescript', 'htc']), | ||
('layout.png', ['css', 'less']), | ||
('page_white_php.png', 'php'), | ||
('page_white_c.png', 'c'), | ||
('page_white_cplusplus.png', 'cpp'), | ||
('page_white_h.png', 'h'), | ||
('database.png', ['db', 'sqlite', 'sqlite3']), | ||
('page_white_database.png', 'sql'), | ||
('page_white_gear.png', ['conf', 'cfg', 'ini', 'reg', 'sys']), | ||
('page_white_zip.png', ['zip', 'tar', 'gz', 'tgz', '7z', 'alz', 'rar', \ | ||
'bin', 'cab']), | ||
('cup.png', 'jar'), | ||
('page_white_cup.png', ['java', 'jsp']), | ||
('application_osx_terminal.png', 'sh'), | ||
('page_white_acrobat.png', 'pdf'), | ||
('package.png', ['pkg', 'dmg']), | ||
('shape_group.png', ['ai', 'svg', 'eps']), | ||
('application_osx.png', 'app'), | ||
('cursor.png', 'cur'), | ||
('feed.png', 'rss'), | ||
('cd.png', ['iso', 'vcd', 'toast']), | ||
('page_white_powerpoint.png', ['ppt', 'pptx']), | ||
('page_white_excel.png', ['xls', 'xlsx', 'csv']), | ||
('page_white_word.png', ['doc', 'docx']), | ||
('page_white_flash.png', 'swf'), | ||
('page_white_actionscript.png', ['fla', 'as']), | ||
('comment.png', 'smi'), | ||
('disk.png', ['bak', 'bup']), | ||
('application_xp_terminal.png', ['bat', 'com']), | ||
('application.png', 'exe'), | ||
('key.png', 'cer'), | ||
('cog.png', ['dll', 'so']), | ||
('pictures.png', 'ics'), | ||
('picture.png', ['gif', 'png', 'jpg', 'jpeg', 'bmp', 'ico']), | ||
('film.png', ['avi', 'mkv']), | ||
('error.png', 'log'), | ||
('music.png', ['mpa', 'mp3', 'off', 'wav']), | ||
('font.png', ['ttf', 'eot']), | ||
('vcard.png', 'vcf') | ||
] | ||
|
||
ICONS_BY_NAME = dict( | ||
Makefile='page_white_gear.png', | ||
Rakefile='page_white_gear.png', | ||
README='page_white_text_width.png', | ||
LICENSE='shield.png', | ||
|
||
) | ||
|
||
ICONS_BY_EXT = dict() | ||
for icon, exts in by_ext: | ||
if not isinstance(exts, list): | ||
exts = [exts] | ||
for e in exts: | ||
ICONS_BY_EXT[e] = icon |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.