Initial checkin.

This commit is contained in:
Aldo Cortesi 2012-04-28 12:42:03 +12:00
commit b4105be21e
19 changed files with 5397 additions and 0 deletions

8
.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# Python object files
*.py[cd]
MANIFEST
/build
/dist
# Vim swap files
*.swp
/doc

23
libpathod/__init__.py Normal file
View File

@ -0,0 +1,23 @@
from tornado import web, template
import handlers, utils
class PathodApp(web.Application):
def __init__(self, *args, **kwargs):
self.templates = template.Loader(utils.data.path("templates"))
web.Application.__init__(self, *args, **kwargs)
def application(**settings):
return PathodApp(
[
(r"/", handlers.Index),
(r"/log", handlers.Log),
(r"/help", handlers.Help),
(r"/preview", handlers.Preview),
(r"/p/.*", handlers.Pathod, settings),
],
debug=True,
static_path = utils.data.path("static"),
template_path = utils.data.path("templates"),
)

View File

File diff suppressed because it is too large Load Diff

45
libpathod/handlers.py Normal file
View File

@ -0,0 +1,45 @@
import urllib
import tornado.web
import rparse
class _Page(tornado.web.RequestHandler):
def render(self, name, **kwargs):
b = self.application.templates.load(name).generate(**kwargs)
self.write(b)
class Index(_Page):
def get(self):
self.render("index.html", section="main")
class Preview(_Page):
def get(self):
self.render("index.html", section="main")
class Help(_Page):
def get(self):
self.render("help.html", section="help")
class Log(_Page):
def get(self):
self.render("log.html", section="log")
class Pathod(object):
anchor = "/p/"
def __init__(self, application, request, **settings):
self.application, self.request, self.settings = application, request, settings
spec = urllib.unquote(self.request.uri)[len(self.anchor):]
try:
self.response = rparse.parse(self.settings, spec)
except rparse.ParseException, v:
self.response = rparse.StubResponse(
800,
"Error parsing response spec:" + str(v)
)
def _execute(self, transforms, *args, **kwargs):
self.response.render(self.request)

103
libpathod/http.py Normal file
View File

@ -0,0 +1,103 @@
CONTINUE = 100
SWITCHING = 101
OK = 200
CREATED = 201
ACCEPTED = 202
NON_AUTHORITATIVE_INFORMATION = 203
NO_CONTENT = 204
RESET_CONTENT = 205
PARTIAL_CONTENT = 206
MULTI_STATUS = 207
MULTIPLE_CHOICE = 300
MOVED_PERMANENTLY = 301
FOUND = 302
SEE_OTHER = 303
NOT_MODIFIED = 304
USE_PROXY = 305
TEMPORARY_REDIRECT = 307
BAD_REQUEST = 400
UNAUTHORIZED = 401
PAYMENT_REQUIRED = 402
FORBIDDEN = 403
NOT_FOUND = 404
NOT_ALLOWED = 405
NOT_ACCEPTABLE = 406
PROXY_AUTH_REQUIRED = 407
REQUEST_TIMEOUT = 408
CONFLICT = 409
GONE = 410
LENGTH_REQUIRED = 411
PRECONDITION_FAILED = 412
REQUEST_ENTITY_TOO_LARGE = 413
REQUEST_URI_TOO_LONG = 414
UNSUPPORTED_MEDIA_TYPE = 415
REQUESTED_RANGE_NOT_SATISFIABLE = 416
EXPECTATION_FAILED = 417
INTERNAL_SERVER_ERROR = 500
NOT_IMPLEMENTED = 501
BAD_GATEWAY = 502
SERVICE_UNAVAILABLE = 503
GATEWAY_TIMEOUT = 504
HTTP_VERSION_NOT_SUPPORTED = 505
INSUFFICIENT_STORAGE_SPACE = 507
NOT_EXTENDED = 510
RESPONSES = {
# 100
CONTINUE: "Continue",
SWITCHING: "Switching Protocols",
# 200
OK: "OK",
CREATED: "Created",
ACCEPTED: "Accepted",
NON_AUTHORITATIVE_INFORMATION: "Non-Authoritative Information",
NO_CONTENT: "No Content",
RESET_CONTENT: "Reset Content.",
PARTIAL_CONTENT: "Partial Content",
MULTI_STATUS: "Multi-Status",
# 300
MULTIPLE_CHOICE: "Multiple Choices",
MOVED_PERMANENTLY: "Moved Permanently",
FOUND: "Found",
SEE_OTHER: "See Other",
NOT_MODIFIED: "Not Modified",
USE_PROXY: "Use Proxy",
# 306 not defined??
TEMPORARY_REDIRECT: "Temporary Redirect",
# 400
BAD_REQUEST: "Bad Request",
UNAUTHORIZED: "Unauthorized",
PAYMENT_REQUIRED: "Payment Required",
FORBIDDEN: "Forbidden",
NOT_FOUND: "Not Found",
NOT_ALLOWED: "Method Not Allowed",
NOT_ACCEPTABLE: "Not Acceptable",
PROXY_AUTH_REQUIRED: "Proxy Authentication Required",
REQUEST_TIMEOUT: "Request Time-out",
CONFLICT: "Conflict",
GONE: "Gone",
LENGTH_REQUIRED: "Length Required",
PRECONDITION_FAILED: "Precondition Failed",
REQUEST_ENTITY_TOO_LARGE: "Request Entity Too Large",
REQUEST_URI_TOO_LONG: "Request-URI Too Long",
UNSUPPORTED_MEDIA_TYPE: "Unsupported Media Type",
REQUESTED_RANGE_NOT_SATISFIABLE: "Requested Range not satisfiable",
EXPECTATION_FAILED: "Expectation Failed",
# 500
INTERNAL_SERVER_ERROR: "Internal Server Error",
NOT_IMPLEMENTED: "Not Implemented",
BAD_GATEWAY: "Bad Gateway",
SERVICE_UNAVAILABLE: "Service Unavailable",
GATEWAY_TIMEOUT: "Gateway Time-out",
HTTP_VERSION_NOT_SUPPORTED: "HTTP Version not supported",
INSUFFICIENT_STORAGE_SPACE: "Insufficient Storage Space",
NOT_EXTENDED: "Not Extended"
}

429
libpathod/rparse.py Normal file
View File

@ -0,0 +1,429 @@
import operator, string, random, sys, time
import contrib.pyparsing as pp
import http, utils
import tornado.ioloop
TESTING = False
class ParseException(Exception): pass
DATATYPES = dict(
ascii_letters = string.ascii_letters,
ascii_lowercase = string.ascii_lowercase,
ascii_uppercase = string.ascii_uppercase,
digits = string.digits,
hexdigits = string.hexdigits,
letters = string.letters,
lowercase = string.lowercase,
octdigits = string.octdigits,
printable = string.printable,
punctuation = string.punctuation,
uppercase = string.uppercase,
whitespace = string.whitespace,
ascii = string.printable,
bytes = "".join(chr(i) for i in range(256))
)
v_integer = pp.Regex(r"[+-]?\d+")\
.setName("integer")\
.setParseAction(lambda toks: int(toks[0]))
v_string = pp.MatchFirst(
[
pp.QuotedString("\"", escChar="\\", unquoteResults=True),
pp.QuotedString("'", escChar="\\", unquoteResults=True),
]
)
v_literal = pp.MatchFirst(
[
v_string,
pp.Word("".join(i for i in pp.printables if i not in ",:"))
]
)
class LiteralGenerator:
def __init__(self, s):
self.s = s
def __eq__(self, other):
return self[:] == other
def __len__(self):
return len(self.s)
def __getitem__(self, x):
return self.s.__getitem__(x)
def __getslice__(self, a, b):
return self.s.__getslice__(a, b)
class RandomGenerator:
def __init__(self, chars, length):
self.chars = chars
self.length = length
def __len__(self):
return self.length
def __getitem__(self, x):
return random.choice(self.chars)
def __getslice__(self, a, b):
b = min(b, self.length)
return "".join(random.choice(self.chars) for x in range(a, b))
class FileGenerator:
def __init__(self, path):
self.path = path
class ValueLiteral:
def __init__(self, val):
self.val = val
def get_generator(self, settings):
return LiteralGenerator(self.val)
@classmethod
def expr(klass):
e = v_literal.copy()
return e.setParseAction(lambda x: klass(*x))
def __str__(self):
return self.val
class ValueGenerate:
UNITS = dict(
b = 1024**0,
k = 1024**1,
m = 1024**2,
g = 1024**3,
t = 1024**4,
)
def __init__(self, usize, unit, datatype):
if not unit:
unit = "b"
self.usize, self.unit, self.datatype = usize, unit, datatype
def bytes(self):
return self.usize * self.UNITS[self.unit]
def get_generator(self, settings):
return RandomGenerator(DATATYPES[self.datatype], self.bytes())
@classmethod
def expr(klass):
e = pp.Literal("!").suppress() + v_integer
u = reduce(operator.or_, [pp.Literal(i) for i in klass.UNITS.keys()])
e = e + pp.Optional(u, default=None)
s = pp.Literal(":").suppress()
s += reduce(operator.or_, [pp.Literal(i) for i in DATATYPES.keys()])
e += pp.Optional(s, default="bytes")
return e.setParseAction(lambda x: klass(*x))
def __str__(self):
return "!%s%s:%s"%(self.usize, self.unit, self.datatype)
class ValueFile:
def __init__(self, path):
self.path = path
@classmethod
def expr(klass):
e = pp.Literal("<").suppress()
e = e + v_literal
return e.setParseAction(lambda x: klass(*x))
def get_generator(self, settings):
raise NotImplementedError
def __str__(self):
return "<%s"%(self.path)
Value = pp.MatchFirst(
[
ValueGenerate.expr(),
ValueFile.expr(),
ValueLiteral.expr()
]
)
class Body:
def __init__(self, value):
self.value = value
def mod_response(self, settings, r):
r.body = self.value.get_generator(settings)
@classmethod
def expr(klass):
e = pp.Literal("b:").suppress()
e = e + Value
return e.setParseAction(lambda x: klass(*x))
class _Pause:
def __init__(self, value):
self.value = value
@classmethod
def expr(klass):
e = pp.Literal("p%s:"%klass.sub).suppress()
e = e + pp.MatchFirst(
[
v_integer,
pp.Literal("forever")
]
)
return e.setParseAction(lambda x: klass(*x))
class PauseBefore(_Pause):
sub = "b"
def mod_response(self, settings, r):
r.pauses.append((0, self.value))
class PauseAfter(_Pause):
sub = "a"
def mod_response(self, settings, r):
r.pauses.append((sys.maxint, self.value))
class PauseRandom(_Pause):
sub = "r"
def mod_response(self, settings, r):
r.pauses.append(("random", self.value))
class _Disconnect:
def __init__(self, value):
self.value = value
@classmethod
def expr(klass):
e = pp.Literal("d%s"%klass.sub)
return e.setParseAction(klass)
class DisconnectBefore(_Disconnect):
sub = "b"
def mod_response(self, settings, r):
r.pauses.append((0, self.value))
class DisconnectRandom(_Disconnect):
sub = "r"
def mod_response(self, settings, r):
r.pauses.append(("random", self.value))
class Header:
def __init__(self, key, value):
self.key, self.value = key, value
def mod_response(self, settings, r):
r.headers.append(
(
self.key.get_generator(settings),
self.value.get_generator(settings)
)
)
@classmethod
def expr(klass):
e = pp.Literal("h:").suppress()
e += Value
e += pp.Literal(":").suppress()
e += Value
return e.setParseAction(lambda x: klass(*x))
class Code:
def __init__(self, code, msg=None):
self.code, self.msg = code, msg
if msg is None:
self.msg = ValueLiteral(http.RESPONSES.get(self.code, "Unknown code"))
def mod_response(self, settings, r):
r.code = self.code
r.msg = self.msg.get_generator(settings)
@classmethod
def expr(klass):
e = v_integer
e = e + pp.Optional(
pp.Literal(":").suppress() + Value
)
return e.setParseAction(lambda x: klass(*x))
BLOCKSIZE = 1024
class Response:
comps = [
Body,
Header,
PauseBefore,
PauseAfter,
PauseRandom,
DisconnectBefore,
DisconnectRandom,
]
version = "HTTP/1.1"
code = 200
msg = LiteralGenerator(http.RESPONSES[code])
body = LiteralGenerator("OK")
def __init__(self, settings, tokens):
self.tokens = tokens
self.headers = []
self.pauses = []
for i in tokens:
i.mod_response(settings, self)
if self.body and not self.get_header("Content-Length"):
self.headers.append(
(
LiteralGenerator("Content-Length"),
LiteralGenerator(str(len(self.body))),
)
)
def get_header(self, hdr):
for k, v in self.headers:
if k[:len(hdr)].lower() == hdr:
return v
return None
@classmethod
def expr(klass):
parts = [i.expr() for i in klass.comps]
atom = pp.MatchFirst(parts)
resp = pp.And(
[
Code.expr(),
pp.ZeroOrMore(pp.Literal(",").suppress() + atom)
]
)
return resp
def length(self):
l = len("%s %s "%(self.version, self.code))
l += len(self.msg)
l += 2
for i in self.headers:
l += len(i[0]) + len(i[1])
l += 4
l += 2
l += len(self.body)
return l
def ready_randoms(self, l, lst):
ret = []
for k, v in lst:
if k == "random":
ret.append((random.randrange(l), v))
else:
ret.append((k, v))
ret.sort()
return ret
def add_timeout(self, s, callback):
if TESTING:
callback()
else:
tornado.ioloop.IOLoop.instance().add_timeout(time.time() + s, callback)
def write_values(self, fp, vals, pauses, disconnect, sofar=0, skip=0, blocksize=BLOCKSIZE):
if disconnect == "before":
fp.finish()
return
while vals:
part = vals.pop()
for i in range(skip, len(part), blocksize):
d = part[i:i+blocksize]
if pauses and pauses[-1][0] < (sofar + len(d)):
p = pauses.pop()
offset = p[0]-sofar
vals.append(part)
def pause_callback():
self.write_values(
fp, vals, pauses, disconnect,
sofar=sofar+offset,
skip=i+offset,
blocksize=blocksize
)
def flushed_callback():
# Data has been flushed, set the timeout.
self.add_timeout(p[1], pause_callback)
fp.write(d[:offset], callback=flushed_callback)
return
fp.write(d)
sofar += len(d)
skip = 0
fp.finish()
def render(self, fp):
hdrs = []
for k, v in self.headers:
hdrs.extend([
k,
": ",
v,
"\r\n",
])
vals = [
"%s %s "%(self.version, self.code),
self.msg,
"\r\n",
]
vals.extend(hdrs)
vals.extend([
"\r\n",
self.body
])
vals.reverse()
pauses = self.ready_randoms(self.length(), self.pauses)
pauses.reverse()
return self.write_values(fp, vals, pauses, None)
def __str__(self):
parts = [
"%s %s"%(self.code, self.msg[:])
]
return "\n".join(parts)
class StubResponse:
def __init__(self, code, body):
self.code = code
self.msg = LiteralGenerator(http.RESPONSES.get(code, "Unknown error"))
self.body = LiteralGenerator(body)
self.headers = [
(
LiteralGenerator("Content-Type"),
LiteralGenerator("text/plain")
),
(
LiteralGenerator("Content-Length"),
LiteralGenerator(str(len(self.body)))
)
]
def parse(settings, s):
try:
return Response(settings, Response.expr().parseString(s, parseAll=True))
except pp.ParseException, v:
raise ParseException(v)

543
libpathod/static/bootstrap.min.css vendored Normal file
View File

@ -0,0 +1,543 @@
article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block;}
audio,canvas,video{display:inline-block;*display:inline;*zoom:1;}
audio:not([controls]){display:none;}
html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;}
a:focus{outline:thin dotted;}
a:hover,a:active{outline:0;}
sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline;}
sup{top:-0.5em;}
sub{bottom:-0.25em;}
img{max-width:100%;height:auto;border:0;-ms-interpolation-mode:bicubic;}
button,input,select,textarea{margin:0;font-size:100%;vertical-align:baseline;*vertical-align:middle;}
button,input{*overflow:visible;line-height:normal;}
button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0;}
button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button;}
input[type="search"]{-webkit-appearance:textfield;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;}
input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none;}
textarea{overflow:auto;vertical-align:top;}
body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;line-height:18px;color:#555555;background-color:#ffffff;}
.container{width:940px;margin-left:auto;margin-right:auto;*zoom:1;}.container:before,.container:after{display:table;content:"";}
.container:after{clear:both;}
.fluid-container{position:relative;min-width:940px;padding-left:20px;padding-right:20px;*zoom:1;}.fluid-container:before,.fluid-container:after{display:table;content:"";}
.fluid-container:after{clear:both;}
.fluid-sidebar{width:220px;margin:0 20px 18px;}
.sidebar-left{padding-left:260px;}
.sidebar-right{padding-right:260px;}
.sidebar-left .fluid-sidebar{float:left;margin-left:-240px;}
.sidebar-right .fluid-sidebar{float:right;margin-right:-240px;}
.fluid-content{float:left;width:100%;}
a{color:#0088cc;text-decoration:none;}a:hover{color:#005580;text-decoration:underline;}
.row{margin-left:-20px;*zoom:1;}.row:before,.row:after{display:table;content:"";}
.row:after{clear:both;}
[class*="span"]{float:left;margin-left:20px;}
.span1{width:60px;}
.span2{width:140px;}
.span3{width:220px;}
.span4{width:300px;}
.span5{width:380px;}
.span6{width:460px;}
.span7{width:540px;}
.span8{width:620px;}
.span9{width:700px;}
.span10{width:780px;}
.span11{width:860px;}
.span12{width:940px;}
.offset1{margin-left:100px;}
.offset2{margin-left:180px;}
.offset3{margin-left:260px;}
.offset4{margin-left:340px;}
.offset5{margin-left:420px;}
.offset6{margin-left:500px;}
.offset7{margin-left:580px;}
.offset8{margin-left:660px;}
.offset9{margin-left:740px;}
.offset10{margin-left:820px;}
.offset11{margin-left:900px;}
p{margin:0 0 9px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;line-height:18px;}p small{font-size:11px;color:#999999;}
h1,h2,h3,h4,h5,h6{margin:0;font-weight:bold;color:#333333;text-rendering:optimizelegibility;}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;color:#999999;}
h1{font-size:30px;line-height:36px;}h1 small{font-size:18px;}
h2{font-size:24px;line-height:36px;}h2 small{font-size:18px;}
h3{line-height:27px;font-size:18px;}h3 small{font-size:14px;}
h4,h5,h6{line-height:18px;}
h4{font-size:14px;}h4 small{font-size:12px;}
h5{font-size:12px;}
h6{font-size:11px;color:#999999;text-transform:uppercase;}
ul,ol{padding:0;margin:0 0 9px 25px;}
ul ul,ul ol,ol ol,ol ul{margin-bottom:0;}
ul{list-style:disc;}
ol{list-style:decimal;}
li{line-height:18px;}
ul.unstyled{margin-left:0;list-style:none;}
dl{margin-bottom:18px;}
dt,dd{line-height:18px;}
dt{font-weight:bold;}
dd{margin-left:9px;}
hr{margin:18px 0;border:0;border-top:1px solid #e5e5e5;border-bottom:1px solid #ffffff;}
strong{font-weight:bold;}
em{font-style:italic;}
.muted{color:#999999;}
abbr{font-size:90%;text-transform:uppercase;border-bottom:1px dotted #ddd;cursor:help;}
blockquote{padding:0 0 0 15px;margin:0 0 18px;border-left:5px solid #eeeeee;}blockquote p{margin-bottom:0;font-size:16px;font-weight:300;line-height:22.5px;}
blockquote small{display:block;line-height:18px;color:#999999;}blockquote small:before{content:'\2014 \00A0';}
blockquote.pull-right{float:right;padding-left:0;padding-right:15px;border-left:0;border-right:5px solid #eeeeee;}blockquote.pull-right p,blockquote.pull-right small{text-align:right;}
q:before,q:after,blockquote:before,blockquote:after{content:"";}
address{display:block;margin-bottom:18px;line-height:18px;font-style:normal;}
code,pre{padding:0 3px 2px;font-family:Menlo,Monaco,"Courier New",monospace;font-size:12px;color:#333333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
code{padding:3px 4px;background-color:#fee9cc;color:#d14;background-color:#f7f7f9;border:1px solid #e1e1e8;}
pre{display:block;padding:8.5px;margin:0 0 9px;font-size:12px;line-height:18px;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0, 0, 0, 0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;white-space:pre;white-space:pre-wrap;word-break:break-all;}pre.prettyprint{margin-bottom:18px;}
pre code{padding:0;background-color:transparent;}
small{font-size:100%;}
cite{font-style:normal;}
form{margin:0 0 18px;}
fieldset{padding:0;margin:0;border:0;}
legend{display:block;width:100%;padding:0;margin-bottom:27px;font-size:19.5px;line-height:36px;color:#333333;border:0;border-bottom:1px solid #eee;-webkit-margin-collapse:separate;}
label,input,button,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:18px;}
label{display:block;margin-bottom:5px;color:#333333;}
input,textarea,select,.uneditable-input{display:block;width:210px;height:18px;padding:4px;margin-bottom:9px;font-size:13px;line-height:18px;color:#555555;border:1px solid #ccc;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}
input[type=image],input[type=checkbox],input[type=radio]{width:auto;height:auto;padding:0;margin:3px 0;*margin-top:0;line-height:normal;border:none;cursor:pointer;}
input[type=file]{padding:initial;line-height:initial;border:initial;background-color:#ffffff;background-color:initial;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
input[type=button],input[type=reset],input[type=submit]{width:auto;height:auto;}
select,input[type=file]{height:27px;*margin-top:4px;line-height:27px;}
select{width:220px;vertical-align:middle;background-color:#ffffff;}
select[multiple],select[size]{height:inherit;}
input[type=image]{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
textarea{height:auto;}
.radio,.checkbox{padding-left:18px;}
.radio input[type=radio],.checkbox input[type=checkbox]{float:left;margin-left:-18px;}
.controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:6px;}
.radio.inline,.checkbox.inline{display:inline-block;margin-bottom:0;}
.radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px;}
input,textarea{-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.1);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.1);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.1);-webkit-transition:border linear 0.2s,box-shadow linear 0.2s;-moz-transition:border linear 0.2s,box-shadow linear 0.2s;-ms-transition:border linear 0.2s,box-shadow linear 0.2s;-o-transition:border linear 0.2s,box-shadow linear 0.2s;transition:border linear 0.2s,box-shadow linear 0.2s;}
input:focus,textarea:focus{border-color:rgba(82, 168, 236, 0.8);-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.1),0 0 8px rgba(82, 168, 236, 0.6);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.1),0 0 8px rgba(82, 168, 236, 0.6);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.1),0 0 8px rgba(82, 168, 236, 0.6);outline:0;}
input[type=file]:focus,input[type=checkbox]:focus,select:focus{-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;outline:1px dotted #666;}
.input-mini{width:60px;}
.input-small{width:90px;}
.input-medium{width:150px;}
.input-large{width:210px;}
.input-xlarge{width:270px;}
.input-xxlarge{width:530px;}
input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{float:none;margin-left:0;}
input.span1,textarea.span1,.uneditable-input.span1{width:50px;}
input.span2,textarea.span2,.uneditable-input.span2{width:130px;}
input.span3,textarea.span3,.uneditable-input.span3{width:210px;}
input.span4,textarea.span4,.uneditable-input.span4{width:290px;}
input.span5,textarea.span5,.uneditable-input.span5{width:370px;}
input.span6,textarea.span6,.uneditable-input.span6{width:450px;}
input.span7,textarea.span7,.uneditable-input.span7{width:530px;}
input.span8,textarea.span8,.uneditable-input.span8{width:610px;}
input.span9,textarea.span9,.uneditable-input.span9{width:690px;}
input.span10,textarea.span10,.uneditable-input.span10{width:770px;}
input.span11,textarea.span11,.uneditable-input.span11{width:850px;}
input.span12,textarea.span12,.uneditable-input.span12{width:930px;}
select.span1{width:70px;}
select.span2{width:150px;}
select.span3{width:230px;}
select.span4{width:310px;}
select.span5{width:390px;}
select.span6{width:470px;}
select.span7{width:550px;}
select.span8{width:630px;}
select.span9{width:710px;}
select.span10{width:790px;}
select.span11{width:870px;}
select.span12{width:950px;}
input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{background-color:#f5f5f5;border-color:#ddd;cursor:not-allowed;}
.control-group.error>label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48;}
.control-group.error input,.control-group.error textarea{color:#b94a48;border-color:#ee5f5b;}.control-group.error input:focus,.control-group.error textarea:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7;}
.control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#b94a48;background-color:#fce6e6;border-color:#b94a48;}
.control-group.warning>label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#c09853;}
.control-group.warning input,.control-group.warning textarea{color:#c09853;border-color:#ccae64;}.control-group.warning input:focus,.control-group.warning textarea:focus{border-color:#be9a3f;-webkit-box-shadow:0 0 6px #e5d6b1;-moz-box-shadow:0 0 6px #e5d6b1;box-shadow:0 0 6px #e5d6b1;}
.control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#c09853;background-color:#d2b877;border-color:#c09853;}
.control-group.success>label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847;}
.control-group.success input,.control-group.success textarea{color:#468847;border-color:#57a957;}.control-group.success input:focus,.control-group.success textarea:focus{border-color:#458845;-webkit-box-shadow:0 0 6px #9acc9a;-moz-box-shadow:0 0 6px #9acc9a;box-shadow:0 0 6px #9acc9a;}
.control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#bcddbc;border-color:#468847;}
input:focus:required:invalid,textarea:focus:required:invalid,select:focus:required:invalid{color:#b94a48;border-color:#ee5f5b;}input:focus:required:invalid:focus,textarea:focus:required:invalid:focus,select:focus:required:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7;}
.form-actions{padding:17px 20px 18px;margin-top:18px;margin-bottom:18px;background-color:#f5f5f5;border-top:1px solid #ddd;}
.uneditable-input{display:block;background-color:#ffffff;border-color:#eee;-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.025);cursor:not-allowed;}
:-moz-placeholder{color:#999999;}
::-webkit-input-placeholder{color:#999999;}
.help-block{margin-top:5px;margin-bottom:0;color:#999999;}
.help-inline{*position:relative;*top:-5px;display:inline;padding-left:5px;}
.input-prepend,.input-append{margin-bottom:5px;*zoom:1;}.input-prepend:before,.input-append:before,.input-prepend:after,.input-append:after{display:table;content:"";}
.input-prepend:after,.input-append:after{clear:both;}
.input-prepend input,.input-append input,.input-prepend .uneditable-input,.input-append .uneditable-input{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0;}
.input-prepend .uneditable-input,.input-append .uneditable-input{border-left-color:#ccc;}
.input-prepend .add-on,.input-append .add-on{float:left;display:block;width:auto;min-width:16px;height:18px;margin-right:-1px;padding:4px 4px 4px 5px;font-weight:normal;line-height:18px;color:#999999;text-align:center;text-shadow:0 1px 0 #ffffff;background-color:#f5f5f5;border:1px solid #ccc;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;}
.input-prepend .active,.input-append .active{background-color:#a9dba9;border-color:#46a546;}
.input-prepend .add-on{*margin-top:1px;}
.input-append input,.input-append .uneditable-input{float:left;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;}
.input-append .uneditable-input{border-right-color:#ccc;}
.input-append .add-on{margin-right:0;margin-left:-1px;-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0;}
.search-query{padding-left:14px;padding-right:14px;margin-bottom:0;-webkit-border-radius:14px;-moz-border-radius:14px;border-radius:14px;}
.form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .uneditable-input,.form-inline .uneditable-input,.form-horizontal .uneditable-input{display:inline-block;margin-bottom:0;}
.form-search label,.form-inline label{display:inline-block;}
.control-group{margin-bottom:9px;}
.form-horizontal .control-group{margin-bottom:18px;}
.form-horizontal .control-group>label{float:left;width:140px;padding-top:5px;text-align:right;}
.form-horizontal .controls{margin-left:160px;}
.form-horizontal .form-actions{padding-left:160px;}
table{max-width:100%;border-collapse:collapse;border-spacing:0;}
.table{width:100%;margin-bottom:18px;}.table th,.table td{padding:8px;line-height:18px;text-align:left;border-top:1px solid #ddd;}
.table th{font-weight:bold;vertical-align:bottom;}
.table td{vertical-align:top;}
.table thead:first-child tr th,.table thead:first-child tr td{border-top:0;}
.table tbody+tbody{border-top:2px solid #ddd;}
.table-condensed th,.table-condensed td{padding:4px 5px;}
.table-bordered{border:1px solid #ddd;border-collapse:separate;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}.table-bordered th+th,.table-bordered td+td,.table-bordered th+td,.table-bordered td+th{border-left:1px solid #ddd;}
.table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0;}
.table-bordered thead:first-child tr:first-child th:first-child,.table-bordered tbody:first-child tr:first-child td:first-child{-webkit-border-radius:4px 0 0 0;-moz-border-radius:4px 0 0 0;border-radius:4px 0 0 0;}
.table-bordered thead:first-child tr:first-child th:last-child,.table-bordered tbody:first-child tr:first-child td:last-child{-webkit-border-radius:0 4px 0 0;-moz-border-radius:0 4px 0 0;border-radius:0 4px 0 0;}
.table-bordered thead:last-child tr:last-child th:first-child,.table-bordered tbody:last-child tr:last-child td:first-child{-webkit-border-radius:0 0 0 4px;-moz-border-radius:0 0 0 4px;border-radius:0 0 0 4px;}
.table-bordered thead:last-child tr:last-child th:last-child,.table-bordered tbody:last-child tr:last-child td:last-child{-webkit-border-radius:0 0 4px 0;-moz-border-radius:0 0 4px 0;border-radius:0 0 4px 0;}
.table-striped tbody tr:nth-child(odd) td,.table-striped tbody tr:nth-child(odd) th{background-color:#f9f9f9;}
table .span1{float:none;width:44px;margin-left:0;}
table .span2{float:none;width:124px;margin-left:0;}
table .span3{float:none;width:204px;margin-left:0;}
table .span4{float:none;width:284px;margin-left:0;}
table .span5{float:none;width:364px;margin-left:0;}
table .span6{float:none;width:444px;margin-left:0;}
table .span7{float:none;width:524px;margin-left:0;}
table .span8{float:none;width:604px;margin-left:0;}
table .span9{float:none;width:684px;margin-left:0;}
table .span10{float:none;width:764px;margin-left:0;}
table .span11{float:none;width:844px;margin-left:0;}
table .span12{float:none;width:924px;margin-left:0;}
table .header{cursor:pointer;}table .header:after{content:"";float:right;margin-top:7px;border-width:0 4px 4px;border-style:solid;border-color:#000000 transparent;visibility:hidden;}
table .headerSortUp,table .headerSortDown{background-color:#f7f7f9;text-shadow:0 1px 1px rgba(255, 255, 255, 0.75);}
table .header:hover:after{visibility:visible;}
table .headerSortDown:after,table .headerSortDown:hover:after{visibility:visible;filter:alpha(opacity=60);-moz-opacity:0.6;opacity:0.6;}
table .headerSortUp:after{border-bottom:none;border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid #000000;visibility:visible;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;filter:alpha(opacity=60);-moz-opacity:0.6;opacity:0.6;}
i{background-image:url(docs/assets/img/glyphicons-halflings-sprite.png);background-position:0 0;background-repeat:no-repeat;display:inline-block;vertical-align:text-top;width:14px;height:14px;}
.glass{background-position:0 0;}
.music{background-position:-24px 0;}
.search{background-position:-48px 0;}
.envelope{background-position:-72px 0;}
.heart{background-position:-96px 0;}
.star{background-position:-120px 0;}
.star-empty{background-position:-144px 0;}
.user{background-position:-168px 0;}
.film{background-position:-192px 0;}
.th-large{background-position:-216px 0;}
.th{background-position:-240px 0;}
.th-list{background-position:-264px 0;}
.ok{background-position:-288px 0;}
.remove{background-position:-312px 0;}
.zoom-in{background-position:-336px 0;}
.zoom-out{background-position:-360px 0;}
.off{background-position:-384px 0;}
.signal{background-position:-408px 0;}
.cog{background-position:-432px 0;}
.trash{background-position:-456px 0;}
.home{background-position:0 -24px;}
.file{background-position:-24px -24px;}
.time{background-position:-48px -24px;}
.road{background-position:-72px -24px;}
.download-alt{background-position:-96px -24px;}
.download{background-position:-120px -24px;}
.upload{background-position:-144px -24px;}
.inbox{background-position:-168px -24px;}
.play-circle{background-position:-192px -24px;}
.repeat{background-position:-216px -24px;}
.refresh{background-position:-240px -24px;}
.calendar{background-position:-264px -24px;}
.lock{background-position:-288px -24px;}
.flag{background-position:-312px -24px;}
.headphones{background-position:-336px -24px;}
.volume-off{background-position:-360px -24px;}
.volume-down{background-position:-384px -24px;}
.volume-up{background-position:-408px -24px;}
.qrcode{background-position:-432px -24px;}
.barcode{background-position:-456px -24px;}
.tag{background-position:0 -48px;}
.tags{background-position:-24px -48px;}
.book{background-position:-48px -48px;}
.bookmark{background-position:-72px -48px;}
.print{background-position:-96px -48px;}
.camera{background-position:-120px -48px;}
.font{background-position:-144px -48px;}
.bold{background-position:-168px -48px;}
.italic{background-position:-192px -48px;}
.text-height{background-position:-216px -48px;}
.text-width{background-position:-240px -48px;}
.align-left{background-position:-264px -48px;}
.align-center{background-position:-288px -48px;}
.align-right{background-position:-312px -48px;}
.align-justify{background-position:-336px -48px;}
.list{background-position:-360px -48px;}
.indent-left{background-position:-384px -48px;}
.indent-right{background-position:-408px -48px;}
.facetime-video{background-position:-432px -48px;}
.picture{background-position:-456px -48px;}
.pencil{background-position:0 -72px;}
.map-marker{background-position:-24px -72px;}
.adjust{background-position:-48px -72px;}
.tint{background-position:-72px -72px;}
.edit{background-position:-96px -72px;}
.share{background-position:-120px -72px;}
.check{background-position:-144px -72px;}
.move{background-position:-168px -72px;}
.step-backward{background-position:-192px -72px;}
.fast-backward{background-position:-216px -72px;}
.backward{background-position:-240px -72px;}
.play{background-position:-264px -72px;}
.pause{background-position:-288px -72px;}
.stop{background-position:-312px -72px;}
.forward{background-position:-336px -72px;}
.fast-forward{background-position:-360px -72px;}
.step-forward{background-position:-384px -72px;}
.eject{background-position:-408px -72px;}
.chevron-left{background-position:-432px -72px;}
.chevron-right{background-position:-456px -72px;}
.arrow-left{background-position:-240px -96px;}
.arrow-right{background-position:-264px -96px;}
.arrow-up{background-position:-288px -96px;}
.arrow-down{background-position:-312px -96px;}
.share-alt{background-position:-336px -96px;}
.resize-full{background-position:-360px -96px;}
.resize-small{background-position:-384px -96px;}
.plus{background-position:-408px -96px;}
.minus{background-position:-432px -96px;}
.asterisk{background-position:-456px -96px;}
.dropdown{position:relative;}
.caret{display:inline-block;width:0;height:0;text-indent:-99999px;vertical-align:top;border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid #000000;filter:alpha(opacity=30);-moz-opacity:0.3;opacity:0.3;content:"\2193";}
.dropdown .caret{margin-top:8px;margin-left:2px;*margin-top:7px;}
.dropdown:hover .caret,.open.dropdown .caret{filter:alpha(opacity=100);-moz-opacity:1;opacity:1;}
.dropdown-menu{position:absolute;top:100%;z-index:1000;float:left;display:none;min-width:160px;max-width:220px;_width:160px;padding:4px 0;margin:0;list-style:none;background-color:#ffffff;border-color:#ccc;border-color:rgba(0, 0, 0, 0.2);border-style:solid;border-width:1px;-webkit-border-radius:0 0 5px 5px;-moz-border-radius:0 0 5px 5px;border-radius:0 0 5px 5px;-webkit-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box;zoom:1;*border-right-width:2px;*border-bottom-width:2px;}.dropdown-menu.bottom-up{top:auto;bottom:100%;margin-bottom:2px;}
.dropdown-menu .divider{height:1px;margin:5px 1px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #ffffff;}
.dropdown-menu a{display:block;padding:3px 15px;clear:both;font-weight:normal;line-height:18px;color:#555555;white-space:nowrap;}
.dropdown-menu li>a:hover,.dropdown-menu .active>a,.dropdown-menu .active>a:hover{color:#ffffff;text-decoration:none;background-color:#0088cc;}
.dropdown.open .dropdown-toggle{color:#ffffff;background:#ccc;background:rgba(0, 0, 0, 0.3);}
.dropdown.open .dropdown-menu{display:block;}
.typeahead{margin-top:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #eee;border:1px solid rgba(0, 0, 0, 0.05);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);}.well blockquote{border-color:#ddd;border-color:rgba(0, 0, 0, 0.15);}
.fade{-webkit-transition:opacity 0.15s linear;-moz-transition:opacity 0.15s linear;-ms-transition:opacity 0.15s linear;-o-transition:opacity 0.15s linear;transition:opacity 0.15s linear;opacity:0;}.fade.in{opacity:1;}
.collapse{-webkit-transition:height 0.35s ease;-moz-transition:height 0.35s ease;-ms-transition:height 0.35s ease;-o-transition:height 0.35s ease;transition:height 0.35s ease;position:relative;overflow:hidden;height:0;}.collapse.in{height:auto;}
.close{float:right;font-size:20px;font-weight:bold;line-height:12px;color:#000000;text-shadow:0 1px 0 #ffffff;filter:alpha(opacity=20);-moz-opacity:0.2;opacity:0.2;}.close:hover{color:#000000;text-decoration:none;filter:alpha(opacity=40);-moz-opacity:0.4;opacity:0.4;cursor:pointer;}
.nav{margin-left:0;margin-bottom:18px;list-style:none;}
.nav>li>a{display:block;}
.nav>li>a:hover{text-decoration:none;background-color:#eeeeee;}
.nav.list{padding-left:14px;padding-right:14px;margin-bottom:0;}
.nav.list>li>a,.nav.list .nav-header{display:block;padding:3px 15px;margin-left:-15px;margin-right:-15px;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);}
.nav.list .nav-header{font-size:11px;font-weight:bold;line-height:18px;color:#999999;text-transform:uppercase;}
.nav.list>li+.nav-header{margin-top:9px;}
.nav.list .active>a{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.2);background-color:#0088cc;}
.tabs,.pills{*zoom:1;}.tabs:before,.pills:before,.tabs:after,.pills:after{display:table;content:"";}
.tabs:after,.pills:after{clear:both;}
.tabs>li,.pills>li{float:left;}
.tabs>li>a,.pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px;}
.tabs{border-bottom:1px solid #ddd;}
.tabs>li{margin-bottom:-1px;}
.tabs>li>a{padding-top:9px;padding-bottom:9px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0;}.tabs>li>a:hover{border-color:#eeeeee #eeeeee #dddddd;}
.tabs>.active>a,.tabs>.active>a:hover{color:#555555;background-color:#ffffff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default;}
.pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;}
.pills .active>a,.pills .active>a:hover{color:#ffffff;background-color:#0088cc;}
.nav.stacked>li{float:none;}
.nav.stacked>li>a{margin-right:0;}
.tabs.stacked{border-bottom:0;}
.tabs.stacked>li>a{border:1px solid #ddd;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
.tabs.stacked>li:first-child>a{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0;}
.tabs.stacked>li:last-child>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px;}
.tabs.stacked>li>a:hover{border-color:#ddd;z-index:2;}
.pills.stacked>li>a{margin-bottom:3px;}
.pills.stacked>li:last-child>a{margin-bottom:1px;}
.pills .dropdown-menu,.tabs .dropdown-menu{margin-top:1px;border-width:1px;}
.pills .dropdown-menu{-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
.tabs .dropdown-toggle .caret,.pills .dropdown-toggle .caret{border-top-color:#0088cc;margin-top:6px;}
.tabs .dropdown-toggle:hover .caret,.pills .dropdown-toggle:hover .caret{border-top-color:#005580;}
.tabs .active .dropdown-toggle .caret,.pills .active .dropdown-toggle .caret{border-top-color:#333333;}
.nav>.dropdown.active>a:hover{color:#000000;cursor:pointer;}
.tabs .open .dropdown-toggle,.pills .open .dropdown-toggle,.nav>.open.active>a:hover{color:#ffffff;background-color:#999999;border-color:#999999;}
.nav .open .caret,.nav .open.active .caret,.nav .open a:hover .caret{border-top-color:#ffffff;filter:alpha(opacity=100);-moz-opacity:1;opacity:1;}
.tabs.stacked .open>a:hover{border-color:#999999;}
.tabbable{*zoom:1;}.tabbable:before,.tabbable:after{display:table;content:"";}
.tabbable:after{clear:both;}
.tabs-below .tabs,.tabs-right .tabs,.tabs-left .tabs{border-bottom:0;}
.tab-content>.tab-pane,.pill-content>.pill-pane{display:none;}
.tab-content>.active,.pill-content>.active{display:block;}
.tabs-below .tabs{border-top:1px solid #ddd;}
.tabs-below .tabs>li{margin-top:-1px;margin-bottom:0;}
.tabs-below .tabs>li>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px;}.tabs-below .tabs>li>a:hover{border-bottom-color:transparent;border-top-color:#ddd;}
.tabs-below .tabs .active>a,.tabs-below .tabs .active>a:hover{border-color:transparent #ddd #ddd #ddd;}
.tabs-left .tabs>li,.tabs-right .tabs>li{float:none;}
.tabs-left .tabs>li>a,.tabs-right .tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px;}
.tabs-left .tabs{float:left;margin-right:19px;border-right:1px solid #ddd;}
.tabs-left .tabs>li>a{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px;}
.tabs-left .tabs>li>a:hover{border-color:#eeeeee #dddddd #eeeeee #eeeeee;}
.tabs-left .tabs .active>a,.tabs-left .tabs .active>a:hover{border-color:#ddd transparent #ddd #ddd;}
.tabs-right .tabs{float:right;margin-left:19px;border-left:1px solid #ddd;}
.tabs-right .tabs>li>a{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0;}
.tabs-right .tabs>li>a:hover{border-color:#eeeeee #eeeeee #eeeeee #dddddd;}
.tabs-right .tabs .active>a,.tabs-right .tabs .active>a:hover{border-color:#ddd #ddd #ddd transparent;}
.navbar{overflow:visible;}
.navbar-inner{background-color:#222222;background-color:#222222;background-image:-khtml-gradient(linear, left top, left bottom, from(#333333), to(#222222));background-image:-moz-linear-gradient(top, #333333, #222222);background-image:-ms-linear-gradient(top, #333333, #222222);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #333333), color-stop(100%, #222222));background-image:-webkit-linear-gradient(top, #333333, #222222);background-image:-o-linear-gradient(top, #333333, #222222);background-image:linear-gradient(top, #333333, #222222);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0);-webkit-box-shadow:0 1px 3px rgba(0, 0, 0, 0.25),inset 0 -1px 0 rgba(0, 0, 0, 0.1);-moz-box-shadow:0 1px 3px rgba(0, 0, 0, 0.25),inset 0 -1px 0 rgba(0, 0, 0, 0.1);box-shadow:0 1px 3px rgba(0, 0, 0, 0.25),inset 0 -1px 0 rgba(0, 0, 0, 0.1);}
.navbar .brand:hover{color:#ffffff;text-decoration:none;}
.navbar .brand{float:left;display:block;padding:8px 20px 12px;margin-left:-20px;font-size:20px;font-weight:200;line-height:1;color:#ffffff;}
.navbar p{margin:0;line-height:40px;}.navbar p a:hover{color:#ffffff;background-color:transparent;}
.navbar .btn,.navbar .btn-group{margin-top:5px;}
.navbar .btn-group .btn{margin-top:0;}
.navbar-form{margin-bottom:0;}.navbar-form input,.navbar-form select{display:inline-block;margin-bottom:0;}
.navbar-search{position:relative;float:left;margin-top:6px;margin-bottom:0;}.navbar-search .search-query{padding:4px 9px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:1;color:#ffffff;color:rgba(255, 255, 255, 0.75);background:#444;background:rgba(255, 255, 255, 0.3);border:1px solid #111;-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1),0 1px 0px rgba(255, 255, 255, 0.15);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1),0 1px 0px rgba(255, 255, 255, 0.15);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1),0 1px 0px rgba(255, 255, 255, 0.15);-webkit-transition:none;-moz-transition:none;-ms-transition:none;-o-transition:none;transition:none;}.navbar-search .search-query :-moz-placeholder{color:#eeeeee;}
.navbar-search .search-query ::-webkit-input-placeholder{color:#eeeeee;}
.navbar-search .search-query:hover{color:#ffffff;background-color:#999999;background-color:rgba(255, 255, 255, 0.5);}
.navbar-search .search-query:focus,.navbar-search .search-query.focused{padding:5px 10px;color:#333333;text-shadow:0 1px 0 #ffffff;background-color:#ffffff;border:0;-webkit-box-shadow:0 0 3px rgba(0, 0, 0, 0.15);-moz-box-shadow:0 0 3px rgba(0, 0, 0, 0.15);box-shadow:0 0 3px rgba(0, 0, 0, 0.15);outline:0;}
.navbar-static{margin-bottom:18px;}
.navbar-static .navbar-inner{padding-left:20px;padding-right:20px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
.navbar-fixed{position:fixed;top:0;right:0;left:0;z-index:1030;}
.navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0;}
.navbar .nav.pull-right{float:right;}
.navbar .nav>li{display:block;float:left;}
.navbar .nav>li>a{float:none;padding:10px 10px 11px;line-height:19px;color:#999999;text-decoration:none;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);}
.navbar .nav>li>a:hover{background-color:transparent;color:#ffffff;text-decoration:none;}
.navbar .nav .active>a{color:#ffffff;text-decoration:none;background-color:#222222;background-color:rgba(0, 0, 0, 0.5);}
.navbar .vertical-divider{height:40px;width:1px;margin:0 5px;overflow:hidden;background-color:#222222;border-right:1px solid #444;}
.navbar .nav.pull-right{margin-left:10px;margin-right:0;}
.navbar .dropdown-menu{margin-top:1px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}.navbar .dropdown-menu:before{content:'';display:inline-block;border-left:7px solid transparent;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-bottom-color:rgba(0, 0, 0, 0.2);position:absolute;top:-7px;left:9px;}
.navbar .dropdown-menu:after{content:'';display:inline-block;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #ffffff;position:absolute;top:-6px;left:10px;}
.navbar .nav .dropdown-toggle .caret,.navbar .nav .open.dropdown .caret{border-top-color:#ffffff;}
.navbar .nav .active .caret{filter:alpha(opacity=100);-moz-opacity:1;opacity:1;}
.navbar .nav .open>.dropdown-toggle,.navbar .nav .active>.dropdown-toggle,.navbar .nav .open.active>.dropdown-toggle{background-color:transparent;}
.navbar .nav .active>.dropdown-toggle:hover{color:#ffffff;}
.navbar .nav.pull-right .dropdown-menu{right:0;}.navbar .nav.pull-right .dropdown-menu:before{left:auto;right:12px;}
.navbar .nav.pull-right .dropdown-menu:after{left:auto;right:13px;}
.breadcrumb{padding:7px 14px;margin:0 0 18px;background-color:#f5f5f5;background-image:-khtml-gradient(linear, left top, left bottom, from(#ffffff), to(#f5f5f5));background-image:-moz-linear-gradient(top, #ffffff, #f5f5f5);background-image:-ms-linear-gradient(top, #ffffff, #f5f5f5);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #ffffff), color-stop(100%, #f5f5f5));background-image:-webkit-linear-gradient(top, #ffffff, #f5f5f5);background-image:-o-linear-gradient(top, #ffffff, #f5f5f5);background-image:linear-gradient(top, #ffffff, #f5f5f5);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f5f5f5', GradientType=0);border:1px solid #ddd;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:inset 0 1px 0 #ffffff;-moz-box-shadow:inset 0 1px 0 #ffffff;box-shadow:inset 0 1px 0 #ffffff;}.breadcrumb li{display:inline;text-shadow:0 1px 0 #ffffff;}
.breadcrumb .divider{padding:0 5px;color:#999999;}
.breadcrumb .active a{color:#333333;}
.pagination{height:36px;margin:18px 0;}
.pagination ul{display:inline-block;*display:inline;*zoom:1;margin-left:0;margin-bottom:0;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:0 1px 2px rgba(0, 0, 0, 0.05);}
.pagination li{display:inline;}
.pagination a{float:left;padding:0 14px;line-height:34px;text-decoration:none;border:1px solid #ddd;border-left-width:0;}
.pagination a:hover,.pagination .active a{background-color:#f5f5f5;}
.pagination .active a{color:#999999;}
.pagination .disabled a,.pagination .disabled a:hover{color:#999999;background-color:transparent;cursor:default;}
.pagination li:first-child a{border-left-width:1px;-webkit-border-radius:3px 0 0 3px;-moz-border-radius:3px 0 0 3px;border-radius:3px 0 0 3px;}
.pagination li:last-child a{-webkit-border-radius:0 3px 3px 0;-moz-border-radius:0 3px 3px 0;border-radius:0 3px 3px 0;}
.pagination-centered{text-align:center;}
.pagination-right{text-align:right;}
.pager{margin-left:0;margin-bottom:18px;list-style:none;text-align:center;*zoom:1;}.pager:before,.pager:after{display:table;content:"";}
.pager:after{clear:both;}
.pager li{display:inline;}
.pager a{display:inline-block;padding:6px 15px;background-color:#f5f5f5;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px;}
.pager .next a{float:right;}
.pager .previous a{float:left;}
.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000000;}.modal-backdrop.fade{opacity:0;}
.modal-backdrop,.modal-backdrop.fade.in{filter:alpha(opacity=80);-moz-opacity:0.8;opacity:0.8;}
.modal{position:fixed;top:50%;left:50%;z-index:1050;max-height:500px;overflow:auto;width:560px;margin:-250px 0 0 -280px;background-color:#ffffff;border:1px solid #999;border:1px solid rgba(0, 0, 0, 0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;}.modal.fade{-webkit-transition:opacity .3s linear, top .3s ease-out;-moz-transition:opacity .3s linear, top .3s ease-out;-ms-transition:opacity .3s linear, top .3s ease-out;-o-transition:opacity .3s linear, top .3s ease-out;transition:opacity .3s linear, top .3s ease-out;top:-25%;}
.modal.fade.in{top:50%;}
.modal-header{padding:5px 15px;border-bottom:1px solid #eee;}.modal-header .close{margin-top:7px;}
.modal-body{padding:15px;}
.modal-footer{padding:14px 15px 15px;margin-bottom:0;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;-webkit-box-shadow:inset 0 1px 0 #ffffff;-moz-box-shadow:inset 0 1px 0 #ffffff;box-shadow:inset 0 1px 0 #ffffff;*zoom:1;}.modal-footer:before,.modal-footer:after{display:table;content:"";}
.modal-footer:after{clear:both;}
.modal-footer .btn{float:right;margin-left:5px;}
.tooltip{position:absolute;z-index:1020;display:block;visibility:visible;padding:5px;font-size:11px;filter:alpha(opacity=0);-moz-opacity:0;opacity:0;}.tooltip.in{filter:alpha(opacity=80);-moz-opacity:0.8;opacity:0.8;}
.tooltip.top{margin-top:-2px;}
.tooltip.right{margin-left:2px;}
.tooltip.bottom{margin-top:2px;}
.tooltip.left{margin-left:-2px;}
.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #000000;}
.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000000;}
.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-bottom:5px solid #000000;}
.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-right:5px solid #000000;}
.tooltip-inner{max-width:200px;padding:3px 8px;color:#ffffff;text-align:center;text-decoration:none;background-color:#000000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
.tooltip-arrow{position:absolute;width:0;height:0;}
.popover{position:absolute;top:0;left:0;z-index:1010;display:none;padding:5px;}.popover.top{margin-top:-5px;}
.popover.right{margin-left:5px;}
.popover.bottom{margin-top:5px;}
.popover.left{margin-left:-5px;}
.popover.top .arrow{bottom:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-top:5px solid #000000;}
.popover.right .arrow{top:50%;left:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-right:5px solid #000000;}
.popover.bottom .arrow{top:0;left:50%;margin-left:-5px;border-left:5px solid transparent;border-right:5px solid transparent;border-bottom:5px solid #000000;}
.popover.left .arrow{top:50%;right:0;margin-top:-5px;border-top:5px solid transparent;border-bottom:5px solid transparent;border-left:5px solid #000000;}
.popover .arrow{position:absolute;width:0;height:0;}
.popover .inner{padding:3px;width:280px;overflow:hidden;background:#000000;background:rgba(0, 0, 0, 0.8);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);-moz-box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);box-shadow:0 3px 7px rgba(0, 0, 0, 0.3);}
.popover .title{padding:9px 15px;line-height:1;background-color:#f5f5f5;border-bottom:1px solid #eee;-webkit-border-radius:3px 3px 0 0;-moz-border-radius:3px 3px 0 0;border-radius:3px 3px 0 0;}
.popover .content{padding:14px;background-color:#ffffff;-webkit-border-radius:0 0 3px 3px;-moz-border-radius:0 0 3px 3px;border-radius:0 0 3px 3px;-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;}.popover .content p,.popover .content ul,.popover .content ol{margin-bottom:0;}
.btn.danger,.btn.danger:hover,.btn.success,.btn.success:hover,.btn.info,.btn.info:hover{text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);color:#ffffff;}
.btn.danger{background-color:#c43c35;background-image:-khtml-gradient(linear, left top, left bottom, from(#ee5f5b), to(#c43c35));background-image:-moz-linear-gradient(top, #ee5f5b, #c43c35);background-image:-ms-linear-gradient(top, #ee5f5b, #c43c35);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #ee5f5b), color-stop(100%, #c43c35));background-image:-webkit-linear-gradient(top, #ee5f5b, #c43c35);background-image:-o-linear-gradient(top, #ee5f5b, #c43c35);background-image:linear-gradient(top, #ee5f5b, #c43c35);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0);border-color:#c43c35 #c43c35 #882a25;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);}
.btn.success{background-color:#57a957;background-image:-khtml-gradient(linear, left top, left bottom, from(#62c462), to(#57a957));background-image:-moz-linear-gradient(top, #62c462, #57a957);background-image:-ms-linear-gradient(top, #62c462, #57a957);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #62c462), color-stop(100%, #57a957));background-image:-webkit-linear-gradient(top, #62c462, #57a957);background-image:-o-linear-gradient(top, #62c462, #57a957);background-image:linear-gradient(top, #62c462, #57a957);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0);border-color:#57a957 #57a957 #3d773d;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);}
.btn.info{background-color:#339bb9;background-image:-khtml-gradient(linear, left top, left bottom, from(#5bc0de), to(#339bb9));background-image:-moz-linear-gradient(top, #5bc0de, #339bb9);background-image:-ms-linear-gradient(top, #5bc0de, #339bb9);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #5bc0de), color-stop(100%, #339bb9));background-image:-webkit-linear-gradient(top, #5bc0de, #339bb9);background-image:-o-linear-gradient(top, #5bc0de, #339bb9);background-image:linear-gradient(top, #5bc0de, #339bb9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0);border-color:#339bb9 #339bb9 #22697d;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);}
.btn{display:inline-block;padding:5px 10px 6px;font-size:13px;line-height:normal;color:#333333;text-shadow:0 1px 1px rgba(255, 255, 255, 0.75);background-color:#e6e6e6;background-image:-webkit-gradient(linear, 0 0, 0 100%, from(#ffffff), color-stop(25%, #ffffff), to(#e6e6e6));background-image:-webkit-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);background-image:-moz-linear-gradient(top, #ffffff, #ffffff 25%, #e6e6e6);background-image:-ms-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);background-image:-o-linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);background-image:linear-gradient(#ffffff, #ffffff 25%, #e6e6e6);background-repeat:no-repeat;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#e6e6e6', GradientType=0);border:1px solid #ccc;border-bottom-color:#bbb;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 0 rgba(255, 255, 255, 0.2),0 1px 2px rgba(0, 0, 0, 0.05);cursor:pointer;-webkit-transition:0.1s linear all;-moz-transition:0.1s linear all;-ms-transition:0.1s linear all;-o-transition:0.1s linear all;transition:0.1s linear all;}.btn:hover{color:#333333;text-decoration:none;background-position:0 -15px;}
.btn:focus{outline:1px dotted #666;}
.btn.primary{color:#ffffff;text-shadow:0 -1px 0 rgba(0, 0, 0, 0.25);background-color:#0064cd;background-image:-khtml-gradient(linear, left top, left bottom, from(#049cdb), to(#0064cd));background-image:-moz-linear-gradient(top, #049cdb, #0064cd);background-image:-ms-linear-gradient(top, #049cdb, #0064cd);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #049cdb), color-stop(100%, #0064cd));background-image:-webkit-linear-gradient(top, #049cdb, #0064cd);background-image:-o-linear-gradient(top, #049cdb, #0064cd);background-image:linear-gradient(top, #049cdb, #0064cd);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#049cdb', endColorstr='#0064cd', GradientType=0);border-color:#0064cd #0064cd #003f81;border-color:rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);}
.btn.active,.btn:active{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 2px 4px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);}
.btn.disabled{cursor:default;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=65);-moz-opacity:0.65;opacity:0.65;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
.btn[disabled]{cursor:default;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled = false);filter:alpha(opacity=65);-moz-opacity:0.65;opacity:0.65;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;}
.btn.large{padding:9px 14px 9px;font-size:15px;line-height:normal;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;}
.btn.small{padding:7px 9px 7px;font-size:11px;}
:root .btn{border-radius:0 \0;}
button.btn::-moz-focus-inner,input[type=submit].btn::-moz-focus-inner{padding:0;border:0;}
.btn-group{position:relative;*zoom:1;}.btn-group:before,.btn-group:after{display:table;content:"";}
.btn-group:after{clear:both;}
.btn-group+.btn-group{margin-left:5px;}
.btn-toolbar .btn-group{display:inline-block;}
.btn-group .btn{position:relative;float:left;margin-left:-1px;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;}
.btn-group .btn:first-child{margin-left:0;-webkit-border-top-left-radius:4px;-moz-border-radius-topleft:4px;border-top-left-radius:4px;-webkit-border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px;border-bottom-left-radius:4px;}
.btn-group .btn:last-child,.btn-group .dropdown-toggle{-webkit-border-top-right-radius:4px;-moz-border-radius-topright:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px;border-bottom-right-radius:4px;}
.btn-group .btn.large:first-child{margin-left:0;-webkit-border-top-left-radius:6px;-moz-border-radius-topleft:6px;border-top-left-radius:6px;-webkit-border-bottom-left-radius:6px;-moz-border-radius-bottomleft:6px;border-bottom-left-radius:6px;}
.btn-group .btn.large:last-child,.btn-group .large.dropdown-toggle{-webkit-border-top-right-radius:6px;-moz-border-radius-topright:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;-moz-border-radius-bottomright:6px;border-bottom-right-radius:6px;}
.btn-group .btn:hover,.btn-group .btn:focus,.btn-group .btn:active{z-index:2;}
.btn-group .dropdown-toggle{padding-left:8px;padding-right:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255, 255, 255, 0.125),0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 1px 0 0 rgba(255, 255, 255, 0.125),0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 1px 0 0 rgba(255, 255, 255, 0.125),0 1px 2px rgba(0, 0, 0, 0.05);}
.btn-group.open .dropdown-menu{display:block;margin-top:1px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;}.btn-group.open .dropdown-menu.large{top:40px;}
.btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 1px 6px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);-moz-box-shadow:inset 0 1px 6px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);box-shadow:inset 0 1px 6px rgba(0, 0, 0, 0.15),0 1px 2px rgba(0, 0, 0, 0.05);}
.btn .caret{margin-top:6px;margin-left:0;}
.primary .caret,.danger .caret,.info .caret,.success .caret{border-top-color:#ffffff;filter:alpha(opacity=75);-moz-opacity:0.75;opacity:0.75;}
.alert{padding:8px 35px 8px 14px;margin-bottom:18px;text-shadow:0 1px 0 rgba(255, 255, 255, 0.5);background-color:#fcf8e3;border:1px solid #f3edd2;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
.alert,.alert-heading{color:#c09853;}
.alert .close{*margin-top:3px;position:relative;right:-21px;}
.alert-success{background-color:#dff0d8;border-color:#cfe8c4;}
.alert-success,.alert-success .alert-heading{color:#468847;}
.alert-danger,.alert-error{background-color:#f2dede;border-color:#e9c7c7;}
.alert-danger,.alert-error,.alert-danger .alert-heading,.alert-error .alert-heading{color:#B94A48;}
.alert-info{background-color:#d9edf7;border-color:#bfe1f2;}
.alert-info,.alert-info .alert-heading{color:#3a87ad;}
.alert-block{padding-top:14px;padding-bottom:14px;}
.alert-block>p,.alert-block>ul{margin-bottom:0;}
.alert-block p+p{margin-top:5px;}
.thumbnails{margin-left:-20px;list-style:none;*zoom:1;}.thumbnails:before,.thumbnails:after{display:table;content:"";}
.thumbnails:after{clear:both;}
.thumbnails>li{float:left;margin:0 0 18px 20px;}
.thumbnail{display:block;padding:4px;line-height:1;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0, 0, 0, 0.075);-moz-box-shadow:0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:0 1px 1px rgba(0, 0, 0, 0.075);}
a.thumbnail:hover{border-color:#0088cc;-webkit-box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);-moz-box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);box-shadow:0 1px 4px rgba(0, 105, 214, 0.25);}
.thumbnail>img{display:block;max-width:100%;}
.thumbnail .caption{padding:9px;}
.label{padding:1px 3px 2px;font-size:9.75px;font-weight:bold;color:#ffffff;text-transform:uppercase;background-color:#999999;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;}.label.important{background-color:#c43c35;}
.label.warning{background-color:#f89406;}
.label.success{background-color:#46a546;}
.label.notice{background-color:#62cffc;}
@-webkit-keyframes progress-bar-stripes{from{background-position:0 0;} to{background-position:40px 0;}}@keyframes progress-bar-stripes{from{background-position:0 0;} to{background-position:40px 0;}}.progress,.progress .bar{-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
.progress{height:18px;margin-bottom:18px;background-color:#f9f9f9;background-image:-khtml-gradient(linear, left top, left bottom, from(#f5f5f5), to(#f9f9f9));background-image:-moz-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:-ms-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #f5f5f5), color-stop(100%, #f9f9f9));background-image:-webkit-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:-o-linear-gradient(top, #f5f5f5, #f9f9f9);background-image:linear-gradient(top, #f5f5f5, #f9f9f9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f5f5f5', endColorstr='#f9f9f9', GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);-moz-box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);box-shadow:inset 0 1px 2px rgba(0, 0, 0, 0.1);}
.progress .bar{width:0%;height:18px;background-color:#0480be;background-image:-khtml-gradient(linear, left top, left bottom, from(#149bdf), to(#0480be));background-image:-moz-linear-gradient(top, #149bdf, #0480be);background-image:-ms-linear-gradient(top, #149bdf, #0480be);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #149bdf), color-stop(100%, #0480be));background-image:-webkit-linear-gradient(top, #149bdf, #0480be);background-image:-o-linear-gradient(top, #149bdf, #0480be);background-image:linear-gradient(top, #149bdf, #0480be);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#149bdf', endColorstr='#0480be', GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);box-shadow:inset 0 -1px 0 rgba(0, 0, 0, 0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:width 0.6s ease;-moz-transition:width 0.6s ease;-ms-transition:width 0.6s ease;-o-transition:width 0.6s ease;transition:width 0.6s ease;}
.progress.striped .bar{background-color:#62c462;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);-webkit-background-size:40px 40px;-moz-background-size:40px 40px;-o-background-size:40px 40px;background-size:40px 40px;}
.progress.active .bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite;}
.progress.danger .bar{background-color:#c43c35;background-image:-khtml-gradient(linear, left top, left bottom, from(#ee5f5b), to(#c43c35));background-image:-moz-linear-gradient(top, #ee5f5b, #c43c35);background-image:-ms-linear-gradient(top, #ee5f5b, #c43c35);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #ee5f5b), color-stop(100%, #c43c35));background-image:-webkit-linear-gradient(top, #ee5f5b, #c43c35);background-image:-o-linear-gradient(top, #ee5f5b, #c43c35);background-image:linear-gradient(top, #ee5f5b, #c43c35);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0);}
.progress.danger.striped .bar{background-color:#ee5f5b;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);}
.progress.success .bar{background-color:#57a957;background-image:-khtml-gradient(linear, left top, left bottom, from(#62c462), to(#57a957));background-image:-moz-linear-gradient(top, #62c462, #57a957);background-image:-ms-linear-gradient(top, #62c462, #57a957);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #62c462), color-stop(100%, #57a957));background-image:-webkit-linear-gradient(top, #62c462, #57a957);background-image:-o-linear-gradient(top, #62c462, #57a957);background-image:linear-gradient(top, #62c462, #57a957);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0);}
.progress.success.striped .bar{background-color:#62c462;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);}
.progress.info .bar{background-color:#339bb9;background-image:-khtml-gradient(linear, left top, left bottom, from(#5bc0de), to(#339bb9));background-image:-moz-linear-gradient(top, #5bc0de, #339bb9);background-image:-ms-linear-gradient(top, #5bc0de, #339bb9);background-image:-webkit-gradient(linear, left top, left bottom, color-stop(0%, #5bc0de), color-stop(100%, #339bb9));background-image:-webkit-linear-gradient(top, #5bc0de, #339bb9);background-image:-o-linear-gradient(top, #5bc0de, #339bb9);background-image:linear-gradient(top, #5bc0de, #339bb9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0);}
.progress.info.striped .bar{background-color:#5bc0de;background-image:-webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));background-image:-webkit-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-moz-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-ms-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:-o-linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);background-image:linear-gradient(-45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);}
.accordion{margin-bottom:18px;}
.accordion-group{background-color:#f5f5f5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;}
.accordion-heading{padding:8px 15px;border-bottom:0;}
.accordion-body{margin-bottom:2px;}
.accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5;}
.carousel{position:relative;line-height:1;}
.carousel-inner{overflow:hidden;width:100%;position:relative;}
.carousel .item{display:none;position:relative;-webkit-transition:0.6s ease-in-out left;-moz-transition:0.6s ease-in-out left;-ms-transition:0.6s ease-in-out left;-o-transition:0.6s ease-in-out left;transition:0.6s ease-in-out left;}
.carousel .active,.carousel .next,.carousel .prev{display:block;}
.carousel .active{left:0;}
.carousel .next,.carousel .prev{position:absolute;top:0;width:100%;}
.carousel .next{left:100%;}
.carousel .prev{left:-100%;}
.carousel .next.left,.carousel .prev.right{left:0;}
.carousel .active.left{left:-100%;}
.carousel .active.right{left:100%;}
.carousel-control{position:absolute;top:40%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#ccc;text-align:center;background:#999999;background:rgba(0, 0, 0, 0.5);-webkit-border-radius:20px;-moz-border-radius:20px;border-radius:20px;}.carousel-control.right{left:auto;right:15px;}
.carousel-control:hover{color:#ffffff;text-decoration:none;background:#333333;background:rgba(0, 0, 0, 0.75);}
.carousel-caption{position:absolute;left:0;right:0;bottom:0;padding:10px 15px 5px;background:#333333;background:rgba(0, 0, 0, 0.75);}
.carousel-caption h4,.carousel-caption p{color:#ffffff;}
.pull-right{float:right;}
.pull-left{float:left;}
.hide{display:none;}
.show{display:block;}
.invisible{visibility:hidden;}
.hidden{display:none;visibility:hidden;}
@media (max-width: 480px){.navbar .nav{position:absolute;top:0;left:0;width:180px;padding-top:40px;list-style:none;} .navbar .nav,.navbar .nav>li:last-child a{-webkit-border-radius:0 0 4px 0;-moz-border-radius:0 0 4px 0;border-radius:0 0 4px 0;} .navbar .nav>li{float:none;display:none;} .navbar .nav>li>a{float:none;background-color:#222;} .navbar .nav>.active{display:block;position:absolute;top:0;left:0;} .navbar .nav>.active>a{background-color:transparent;} .navbar .nav>.active>a:hover{background-color:#333;} .navbar .nav>.active>a:after{display:inline-block;width:0;height:0;margin-top:8px;margin-left:6px;text-indent:-99999px;vertical-align:top;border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid #ffffff;filter:alpha(opacity=100);-moz-opacity:1;opacity:1;content:"&darr;";} .navbar .nav:hover>li{display:block;} .navbar .nav:hover>li>a:hover{background-color:#333;} .form-horizontal .control-group>label{float:none;width:auto;padding-top:0;text-align:left;} .form-horizontal .controls{margin-left:0;} .form-horizontal .control-list{padding-top:0;} .form-horizontal .form-actions{padding-left:0;} .modal{position:absolute;top:20px;left:20px;right:20px;width:auto;margin:0;}.modal.fade.in{top:auto;} .modal-header .close{padding:10px;}}@media (max-width: 768px){.navbar-fixed{position:absolute;} .navbar-fixed .nav{float:none;} .container{width:auto;padding:0 20px;} .row{margin-left:0;} .row>[class*="span"]{float:none;display:block;width:auto;margin:0;}}@media (min-width: 768px) and (max-width: 940px){.container{width:748px;} .span1{width:44px;} .span2{width:108px;} .span3{width:172px;} .span4{width:236px;} .span5{width:300px;} .span6{width:364px;} .span7{width:428px;} .span8{width:492px;} .span9{width:556px;} .span10{width:620px;} .span11{width:684px;} .span12{width:748px;} .offset1{margin-left:64px;} .offset2{margin-left:128px;} .offset3{margin-left:192px;} .offset4{margin-left:256px;} .offset5{margin-left:320px;} .offset6{margin-left:384px;} .offset7{margin-left:448px;} .offset8{margin-left:512px;} .offset9{margin-left:576px;} .offset10{margin-left:640px;} .offset11{margin-left:704px;} .offset12{margin-left:768px;}}

View File

@ -0,0 +1,41 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Omnid</title>
<link href="/static/bootstrap.min.css" rel="stylesheet">
<style type="text/css">
body {
padding-top: 60px;
}
</style>
</head>
<body>
<div class="navbar navbar-fixed">
<div class="navbar-inner">
<div class="container">
<a class="brand" href="#">Omnid</a>
<ul class="nav">
<li {% if section== "main" %} class="active" {% end %}><a href="/">Main</a></li>
<li {% if section== "log" %} class="active" {% end %}><a href="/log">Log</a></li>
<li {% if section== "help" %} class="active" {% end %}><a href="/help">Help</a></li>
</ul>
</div>
</div>
</div>
<div class="container">
{% block body %}
{% end %}
<footer>
<p>made by <a href="http://corte.si">Aldo Cortesi</a> </p>
</footer>
</div> <!-- /container -->
</body>
</html>

View File

@ -0,0 +1,4 @@
{% extends frame.html %}
{% block body %}
<h1> Help </h1>
{% end %}

View File

@ -0,0 +1,12 @@
{% extends frame.html %}
{% block body %}
<!-- Main hero unit for a primary marketing message or call to action -->
<div class="hero-unit">
<form>
<input>
<a type="submit" class="btn">explain</a>
</form>
</div>
{% end %}

View File

@ -0,0 +1,5 @@
{% extends frame.html %}
{% block body %}
<h1> Log </h1>
{% end %}

31
libpathod/utils.py Normal file
View File

@ -0,0 +1,31 @@
import copy, os
class Data:
def __init__(self, name):
m = __import__(name)
dirname, _ = os.path.split(m.__file__)
self.dirname = os.path.abspath(dirname)
def path(self, path):
"""
Returns a path to the package data housed at 'path' under this
module.Path can be a path to a file, or to a directory.
This function will raise ValueError if the path does not exist.
"""
fullpath = os.path.join(self.dirname, path)
if not os.path.exists(fullpath):
raise ValueError, "dataPath: %s does not exist."%fullpath
return fullpath
def read(self, path):
"""
Returns a path to the package data housed at 'path' under this
module.Path can be a path to a file, or to a directory.
This function will raise ValueError if the path does not exist.
"""
p = self.path(path)
return open(p).read()
data = Data(__name__)

102
notes Normal file
View File

@ -0,0 +1,102 @@
Value Specifiers:
!500k - 500k of random data
!500k:utf8 - 500k of utf8. Other specifiers: utf8,alphanum,alpha,printable
"foo" - literal
foo - literal
<path - load from path under data directory
<"path literal" - load from path under data directory
Response:
code:[comma-separated features]
Specifying a response:
Code 200:
code:msg
200:VALUE
Headers:
h:VALUE:VALUE
Body:
b:VALUE
Pauses:
pb:5
pb:forever
Pause before sending data:
pb:5
Pause after sending data, before hanging up:
pa:5
Pause after sending a random amoutn of data:
pr:5
Disconnect:
Before sending data:
db
Randomly:
dr
Shortcuts:
Redirects:
code:msg>destination
code>destination
301:VALUE>VALUE
301>http://foo.bar
Content-type:
t:content-type
Examples:
200,b:500k
404,p:5s,b:1k:printable
200,t:text/json,p:5s,b:1k
200,b:1k,xr
Sequences:
200 * 2 | !forever
200 | 404 | 200,b:500g
Anchors:
Passed on command-line?
--anchor /foo/bar 200:!/foo
Built-in help
/help
/explain/expression

21
pathod Executable file
View File

@ -0,0 +1,21 @@
#!/usr/bin/env python
import argparse
import libomnid
import tornado.ioloop
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument("-p", dest='port', default=8888, type=int, help='Port.')
parser.add_argument(
"-s", dest='staticdir', default=None, type=str,
help='Directory for static files.'
)
args = parser.parse_args()
libomnid.application(staticdir=args.staticdir).listen(args.port)
print "omnid listening on port %s"%args.port
try:
tornado.ioloop.IOLoop.instance().start()
except KeyboardInterrupt:
pass

5
test/.pry Normal file
View File

@ -0,0 +1,5 @@
base = ..
coverage = ../libpathod
exclude = .
../libpathod/contrib

262
test/test_rparse.py Normal file
View File

@ -0,0 +1,262 @@
import StringIO, sys
import libpry
from libpathod import rparse
rparse.TESTING = True
class uMisc(libpry.AutoTree):
def test_generators(self):
v = rparse.Value.parseString("val")[0]
g = v.get_generator({})
assert g[:] == "val"
def test_randomgenerator(self):
g = rparse.RandomGenerator("one", 100)
assert len(g[:10]) == 10
assert len(g[1:10]) == 9
assert len(g[:1000]) == 100
assert len(g[1000:1001]) == 0
assert g[0]
def test_literalgenerator(self):
g = rparse.LiteralGenerator("one")
assert g == "one"
assert g[:] == "one"
assert g[1] == "n"
def test_valueliteral(self):
v = rparse.ValueLiteral("foo")
assert v.expr()
assert str(v)
def test_generated_value(self):
v = rparse.Value.parseString("!10b")[0]
assert v.usize == 10
assert v.unit == "b"
assert v.bytes() == 10
v = rparse.Value.parseString("!10")[0]
assert v.unit == "b"
v = rparse.Value.parseString("!10k")[0]
assert v.bytes() == 10240
v = rparse.Value.parseString("!10g")[0]
assert v.bytes() == 1024**3 * 10
v = rparse.Value.parseString("!10g:digits")[0]
assert v.datatype == "digits"
g = v.get_generator({})
assert g[:100]
v = rparse.Value.parseString("!10:digits")[0]
assert v.unit == "b"
assert v.datatype == "digits"
def test_value(self):
assert rparse.Value.parseString("val")[0].val == "val"
assert rparse.Value.parseString("'val'")[0].val == "val"
assert rparse.Value.parseString('"val"')[0].val == "val"
assert rparse.Value.parseString('"\'val\'"')[0].val == "'val'"
v = rparse.Value.parseString("<path")[0]
assert v.path == "path"
v = rparse.Value.parseString("<'one two'")[0]
assert v.path == "one two"
def test_body(self):
e = rparse.Body.expr()
v = e.parseString("b:foo")[0]
assert v.value.val == "foo"
v = e.parseString("b:!100")[0]
assert str(v.value) == "!100b:bytes"
v = e.parseString("b:!100g:digits", parseAll=True)[0]
assert v.value.datatype == "digits"
assert str(v.value) == "!100g:digits"
def test_header(self):
e = rparse.Header.expr()
v = e.parseString("h:foo:bar")[0]
assert v.key.val == "foo"
assert v.value.val == "bar"
def test_code(self):
e = rparse.Code.expr()
v = e.parseString("200")[0]
assert v.code == 200
v = e.parseString("404:msg")[0]
assert v.code == 404
assert v.msg.val == "msg"
r = e.parseString("200:'foo'")[0]
assert r.msg.val == "foo"
r = e.parseString("200:'\"foo\"'")[0]
assert r.msg.val == "\"foo\""
r = e.parseString('200:"foo"')[0]
assert r.msg.val == "foo"
r = e.parseString('404')[0]
assert r.msg.val == "Not Found"
r = e.parseString('10')[0]
assert r.msg.val == "Unknown code"
def test_stub_response(self):
s = rparse.StubResponse(400, "foo")
class uDisconnects(libpry.AutoTree):
def test_before(self):
e = rparse.DisconnectBefore.expr()
v = e.parseString("db")[0]
assert isinstance(v, rparse.DisconnectBefore)
v = e.parseString("db")[0]
assert isinstance(v, rparse.DisconnectBefore)
def test_random(self):
e = rparse.DisconnectRandom.expr()
v = e.parseString("dr")[0]
assert isinstance(v, rparse.DisconnectRandom)
v = e.parseString("dr")[0]
assert isinstance(v, rparse.DisconnectRandom)
class uPauses(libpry.AutoTree):
def test_before(self):
e = rparse.PauseBefore.expr()
v = e.parseString("pb:10")[0]
assert v.value == 10
v = e.parseString("pb:forever")[0]
assert v.value == "forever"
def test_after(self):
e = rparse.PauseAfter.expr()
v = e.parseString("pa:10")[0]
assert v.value == 10
def test_random(self):
e = rparse.PauseRandom.expr()
v = e.parseString("pr:10")[0]
assert v.value == 10
class uparse(libpry.AutoTree):
def test_parse_err(self):
libpry.raises(rparse.ParseException, rparse.parse, {}, "400:msg,b:")
def test_parse_header(self):
r = rparse.parse({}, "400,h:foo:bar")
assert r.get_header("foo") == "bar"
def test_parse_pause_before(self):
r = rparse.parse({}, "400,pb:10")
assert (0, 10) in r.pauses
def test_parse_pause_after(self):
r = rparse.parse({}, "400,pa:10")
assert (sys.maxint, 10) in r.pauses
def test_parse_pause_random(self):
r = rparse.parse({}, "400,pr:10")
assert ("random", 10) in r.pauses
class DummyRequest(StringIO.StringIO):
def write(self, d, callback=None):
StringIO.StringIO.write(self, d)
if callback:
callback()
def finish(self):
return
class uResponse(libpry.AutoTree):
def dummy_response(self):
return rparse.parse({}, "400:msg")
def test_response(self):
r = rparse.parse({}, "400:msg")
assert r.code == 400
assert r.msg == "msg"
r = rparse.parse({}, "400:msg,b:!100b")
assert r.msg == "msg"
assert r.body[:]
assert str(r)
def test_ready_randoms(self):
r = rparse.parse({}, "400:msg")
x = [(0, 5)]
assert r.ready_randoms(100, x) == x
x = [("random", 5)]
ret = r.ready_randoms(100, x)
assert 0 <= ret[0][0] < 100
x = [(1, 5), (0, 5)]
assert r.ready_randoms(100, x) == sorted(x)
def test_write_values_disconnects(self):
r = self.dummy_response()
s = DummyRequest()
tst = "foo"*100
r.write_values(s, [tst], [], "before", blocksize=5)
assert not s.getvalue()
def test_write_values(self):
tst = "foo"*1025
r = rparse.parse({}, "400:msg")
s = DummyRequest()
r.write_values(s, [tst], [], None)
assert s.getvalue() == tst
def test_write_values_pauses(self):
tst = "".join(str(i) for i in range(10))
r = rparse.parse({}, "400:msg")
for i in range(2, 10):
s = DummyRequest()
r.write_values(s, [tst], [(2, 0), (1, 0)], None, blocksize=i)
assert s.getvalue() == tst
for i in range(2, 10):
s = DummyRequest()
r.write_values(s, [tst], [(1, 0)], None, blocksize=i)
assert s.getvalue() == tst
tst = ["".join(str(i) for i in range(10))]*5
for i in range(2, 10):
s = DummyRequest()
r.write_values(s, tst[:], [(1, 0)], None, blocksize=i)
assert s.getvalue() == "".join(tst)
def test_render(self):
s = DummyRequest()
r = rparse.parse({}, "400:msg")
r.render(s)
def test_length(self):
def testlen(x):
s = DummyRequest()
x.render(s)
assert x.length() == len(s.getvalue())
testlen(rparse.parse({}, "400:msg"))
testlen(rparse.parse({}, "400:msg,h:foo:bar"))
testlen(rparse.parse({}, "400:msg,h:foo:bar,b:!100b"))
tests = [
uResponse(),
uPauses(),
uDisconnects(),
uMisc(),
uparse()
]

8
test/test_utils.py Normal file
View File

@ -0,0 +1,8 @@
import libpry
from libpathod import utils
tests = [
]

6
todo Normal file
View File

@ -0,0 +1,6 @@
- Files
- Shortcuts
- HTTPS
- Sequences
- Anchors