Commit e98b986b authored by Martin Urban's avatar Martin Urban
Browse files

merge window manager

parents 6a10f473 34c7a143
......@@ -22,9 +22,12 @@ MANIFEST
hg-check*
vispa.egg*
*.*~
node_modules
docs/source/js
docs/source/py
*.sublime-workspace
.vagrant
vagrant_ansible_inventory_default
node_modules
\ No newline at end of file
node_modules
.atom-build.json
.gitignore
......@@ -61,6 +61,7 @@
"globals": {
"$": false,
"vispa": false,
"Class": false
"Class": false,
"define": false
}
}
......@@ -78,6 +78,8 @@ class Browser(object):
def parse_commandline():
parser = ArgumentParser()
from vispa import RELEASE_VERSION
config_dir = "~/.vispa-%s/conf" % RELEASE_VERSION
parser.add_argument("--config-dir", "-c", dest="configdir",
default=os.path.expanduser(config_dir),
......
......@@ -40,7 +40,7 @@ text.welcome = Welcome to VISPA!
#text.disclaimer =
# leave the feedback address empty to disable feedback
#feedback.address =
#feedback.address =
feedback.subject = VISPA Feedback
# user registration
......@@ -65,13 +65,13 @@ password_url = http://localhost:4282/vispa/password
workspace_action = openFileBrowser
# cache busting: uuid, mtime:<filename>, string
#cache_bust = uuid
#cache_bust = uuid
# time in seconds after which idle sessions are removed
#session_timeout = 3600
# interval (in seconds) to check for idle sessions
session_interval = 60
[websockets]
enabled = False
......@@ -80,7 +80,7 @@ enabled = False
# pxlrun command options, call of executable will be:
# pre_command_options command post_command_options
command = pxlrun
pre_command_options =
pre_command_options =
#pre_command_options = nice -n 19 ionice -c 3
post_command_options = -p
......@@ -92,7 +92,6 @@ manager = local
[workspace]
add = True
alter = True
# allow the use of local workspaces
#allow_local = True
......@@ -103,7 +102,7 @@ sender_address = vispa@domain.tld
smtp.host = 127.0.0.1
smtp.port = 25
[filesystem]
[filesystem]
max_get_size = 20
[extensions]
......@@ -143,15 +142,6 @@ guest_group = guest
role_1 = Student
role_2 = Tutor
role_3 = Manager
# list of permissions that must exist
permissions = ["project.read_items", "project.create_items", "project.edit_items", "project.delete_items"]
# assignment of permissions to default roles. permissions must exists (use line above)
role_1_permissions = ["project.read_items"]
role_2_permissions = ["project.read_items", "project.create_items"]
role_3_permissions = ["project.read_items", "project.create_items", "project.edit_items", "project.delete_items"]
# assignment of roles to user and guest group
user_group_roles = [1]
guest_group_roles = []
......@@ -159,8 +149,6 @@ guest_group_roles = []
# enable guets logins without providing any information
enable_guest_login = False
[ldap-export]
enable = False
......@@ -181,4 +169,3 @@ private_group = True
# create all missing users on startup
sync_on_startup = False
......@@ -51,11 +51,7 @@ clean:
rm -rf source/js
rm -rf source/py
srcs:
python preprocess -s ../vispa/static/js/ -t source/js
sphinx-apidoc -o source/py ../vispa -s rst ../vispa/workspace_loader.py
html: srcs
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
......
# -*- coding: utf-8 -*-
"""
Custom JavaScript domain that adds features used by the VISPA client.
"""
from sphinx import addnodes
from sphinx.domains import Domain, ObjType
from sphinx.locale import l_, _
from sphinx.directives import ObjectDescription
from sphinx.roles import XRefRole
from sphinx.util.nodes import make_refnode
from sphinx.util.docfields import Field, GroupedField, TypedField
from docutils import nodes
# make this compatible with sphinx pre 1.4.5
# https://github.com/sphinx-doc/sphinx/commit/2c396601bf87d0a035a151a5e8fd25b9f702ebe5
def ref_context(env):
try:
return env.ref_context
except:
return env.temp_data
class NumberedField(TypedField):
list_type = nodes.enumerated_list
class JSObject(ObjectDescription):
display_prefix = None
has_arguments = False
def add_target_and_index(self, name_obj, sig, signode):
objectname = self.options.get("object", ref_context(self.env).get("js:object"))
fullname = name_obj[0]
if fullname not in self.state.document.ids:
signode["names"].append(fullname)
signode["ids"].append(fullname.replace("$", "_S_"))
signode["first"] = not self.names
self.state.document.note_explicit_target(signode)
objects = self.env.domaindata["js"]["objects"]
if fullname in objects:
self.state_machine.reporter.warning(
"duplicate object description of %s, " % fullname + "other instance in " +
self.env.doc2path(objects[fullname][0]), line=self.lineno)
objects[fullname] = self.env.docname, self.objtype
indextext = self.get_index_text(objectname, name_obj)
if indextext:
self.indexnode["entries"].append(("single", indextext, fullname.replace("$", "_S_"), ""))
def handle_signature(self, sig, signode):
sig = sig.strip()
if "(" in sig and sig[-1] == ")":
prefix, arglist = sig.split("(", 1)
prefix = prefix.strip()
arglist = arglist[:-1].strip()
else:
prefix = sig
arglist = None
if "." in prefix:
nameprefix, name = prefix.rsplit(".", 1)
else:
nameprefix = None
name = prefix
objectname = ref_context(self.env).get("js:object")
if nameprefix:
if objectname:
nameprefix = objectname + "." + nameprefix
fullname = nameprefix + "." + name
elif objectname:
fullname = objectname + "." + name
else:
# just a function or constructor
objectname = ""
fullname = name
signode["object"] = objectname
signode["fullname"] = fullname
sigprefix = self.get_signature_prefix()
if sigprefix:
signode += addnodes.desc_annotation(sigprefix, sigprefix)
if self.display_prefix:
signode += addnodes.desc_annotation(self.display_prefix, self.display_prefix)
if nameprefix:
signode += addnodes.desc_addname(nameprefix + ".", nameprefix + ".")
signode += addnodes.desc_name(name, name)
if self.has_arguments:
if not arglist:
signode += addnodes.desc_parameterlist()
else:
self.parse_arglist(signode, arglist)
return fullname, nameprefix
def parse_arglist(self, signode, arglist):
possig, _, optsig = arglist.replace(" ", "").partition("[")
if optsig:
optsig = "[" + optsig.replace(",", "")
# create the params list
paramlist = addnodes.desc_parameterlist()
signode += paramlist
# parse positionals
for pos in possig.split(","):
node = addnodes.desc_parameter(pos, pos)
paramlist += node
# parse optionals
opt = ""
parent = paramlist
def add(opt):
node = addnodes.desc_optional()
node.append(addnodes.desc_parameter(opt, opt))
parent.append(node)
return node
for c in optsig:
if c == "[":
if opt:
parent = add(opt)
opt = ""
elif c == "]":
if opt:
add(opt)
opt = ""
else:
parent = parent.parent
else:
opt += c
def get_signature_prefix(self):
return ""
def get_index_text(self, objectname, name_obj):
return ""
class JSAttribute(JSObject):
doc_field_types = [
Field("type",
label = l_("Type"),
has_arg = False,
names = ("type",)
)
]
def get_signatures(self):
return [self.arguments[0].partition(" ")[0]]
def get_signature_prefix(self):
return self.arguments[0].partition(" ")[2]
class JSCallable(JSObject):
has_arguments = True
doc_field_types = [
TypedField("arguments",
label = l_("Arguments"),
names = ("argument", "arg", "parameter", "param"),
typerolename = "func",
typenames = ("paramtype", "type")
),
GroupedField("errors",
label = l_("Throws"),
names = ("throws",),
rolename = "err",
can_collapse = True
),
NumberedField("callback",
label = l_("Callback args"),
names = ("callback", "cb")
)
]
def get_signatures(self):
return [self.arguments[0].partition(")")[0] + ")"]
def get_signature_prefix(self):
return self.arguments[0].partition(")")[2][1:]
class JSFunction(JSCallable):
doc_field_types = JSCallable.doc_field_types[:] + [
Field("returnvalue",
label = l_("Returns"),
has_arg = False,
names = ("returns", "return")
),
Field("returntype",
label = l_("Return type"),
has_arg = False,
names = ("rtype",)
)
]
def get_index_text(self, objectname, name_obj):
return _("%s()") % name_obj[0]
class JSClassConstructor(JSCallable):
display_prefix = "class "
doc_field_types = JSCallable.doc_field_types[:] + [
GroupedField("extends",
label = l_("Extends"),
names = ("extends", "extend"),
can_collapse = True
),
GroupedField("mixins",
label = l_("Mixins"),
names = ("mixins", "mixin"),
can_collapse = True
)
]
def get_index_text(self, objectname, name_obj):
name, obj = name_obj
return _("%s() (class)") % name
class JSMixinConstructor(JSCallable):
display_prefix = "mixin "
doc_field_types = JSCallable.doc_field_types[:] + [
GroupedField("extends",
label = l_("Extends"),
names = ("extends", "extend"),
can_collapse = True
)
]
def get_index_text(self, objectname, name_obj):
name, obj = name_obj
return _("%s() (mixin)") % name
class JSXRefRole(XRefRole):
def process_link(self, env, refnode, has_explicit_title, title, target):
# basically what sphinx.domains.python.PyXRefRole does
refnode["js:object"] = ref_context(env).get("js:object")
if not has_explicit_title:
title = title.lstrip(".")
target = target.lstrip("~")
if title[0:1] == "~":
title = title[1:]
dot = title.rfind(".")
if dot != -1:
title = title[dot+1:]
if target[0:1] == ".":
target = target[1:]
refnode["refspecific"] = True
return title, target
class JavaScriptDomain(Domain):
name = "js"
label = "JavaScript"
object_types = {
"function" : ObjType(l_("function"), "func"),
"class" : ObjType(l_("class"), "class"),
"mixin" : ObjType(l_("mixin"), "mixin"),
"attribute": ObjType(l_("attribute"), "attr")
}
directives = {
"function" : JSFunction,
"class" : JSClassConstructor,
"mixin" : JSMixinConstructor,
"attribute": JSAttribute
}
roles = {
"func" : JSXRefRole(fix_parens=True),
"class": JSXRefRole(fix_parens=True),
"mixin": JSXRefRole(fix_parens=True),
"attr" : JSXRefRole()
}
initial_data = {
"objects": {} # fullname -> docname, objtype
}
def clear_doc(self, docname):
for fullname, (fn, _l) in list(self.data["objects"].items()):
if fn == docname:
del self.data["objects"][fullname]
def merge_domaindata(self, docnames, otherdata):
for fullname, (fn, objtype) in otherdata["objects"].items():
if fn in docnames:
self.data["objects"][fullname] = (fn, objtype)
def find_obj(self, env, obj, name, typ, searchorder=0):
if name[-2:] == "()":
name = name[:-2]
objects = self.data["objects"]
newname = None
if searchorder == 1:
if obj and obj + "." + name in objects:
newname = obj + "." + name
else:
newname = name
else:
if name in objects:
newname = name
elif obj and obj + "." + name in objects:
newname = obj + "." + name
return newname, objects.get(newname)
def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode):
objectname = node.get("js:object")
searchorder = node.hasattr("refspecific") and 1 or 0
name, obj = self.find_obj(env, objectname, target, typ, searchorder)
if not obj:
return None
return make_refnode(builder, fromdocname, obj[0], name.replace("$", "_S_"), contnode, name)
def resolve_any_xref(self, env, fromdocname, builder, target, node, contnode):
objectname = node.get("js:object")
name, obj = self.find_obj(env, objectname, target, None, 1)
if not obj:
return []
return [(
"js:" + self.role_for_objtype(obj[1]),
make_refnode(builder, fromdocname, obj[0], name.replace("$", "_S_"), contnode, name)
)]
def get_objects(self):
for refname, (docname, type) in list(self.data["objects"].items()):
yield refname, refname, type, docname, \
refname.replace("$", "_S_"), 1
def setup(app):
app.domains["js"] = JavaScriptDomain
app._init_i18n()
app._init_env(freshenv=True)
......@@ -4,8 +4,22 @@ import os
import re
import argparse
RST_INDENT = 3
index_tmpl = """\
{title}
{underline}
.. toctree::
:maxdepth: {depth}
{entries}
"""
def main(args):
if not os.path.isdir(args.source):
raise Exception("source path not found: %s" % args.source)
......@@ -18,43 +32,58 @@ def main(args):
raise Exception("target path exists and is a file: %s" % args.target)
os.makedirs(args.target)
if not args.source_extension.startswith("."):
args.source_extension = "." + args.source_extension
if not args.target_extension.startswith("."):
args.target_extension = "." + args.target_extension
print ("start processing %s\n" % args.source)
print("start processing %s\n" % args.source)
process_folder(args, args.source)
print ("\ndone!")
print("\ndone!")
def create_target_path(args, src):
relpath = os.path.relpath(src, args.source)
if os.path.isfile(src):
relpath = os.path.splitext(relpath)[0] + ".rst"
return os.path.normpath(os.path.join(args.target, relpath))
def process_folder(args, source):
for relpath in os.listdir(source):
abspath = os.path.join(source, relpath)
def process_folder(args, src):
for relpath in os.listdir(src):
abspath = os.path.join(src, relpath)
if os.path.isdir(abspath):
process_folder(args, abspath)
elif relpath.endswith(args.source_extension):
elif relpath.endswith(".js"):
process_file(args, abspath)
# create index file
dstdir = create_target_path(args, src)
dst = os.path.join(dstdir, "index.rst")
if src == args.source:
title = "JavaScript API"
depth = 3
else:
title = os.path.basename(dstdir)
depth = 2
underline = "=" * len(title)
entries = []
for elem in os.listdir(dstdir):
if elem == "index":
continue
if os.path.isdir(os.path.join(dstdir, elem)):
elem = elem + "/index"
else:
elem = os.path.splitext(elem)[0]
entries.append(elem)
entries = "\n ".join(entries)
with open(dst, "w") as f:
f.write(index_tmpl.format(title=title, underline=underline, entries=entries, depth=depth))
def process_file(args, path):
if not path.startswith(args.source):
return
subpath = path[len(args.source):]
if subpath.startswith(os.sep):
subpath = subpath[len(os.sep):]
subdir, name = os.path.split(subpath)
targetpath = os.path.join(args.target, subdir)
if not os.path.isdir(targetpath):
if os.path.exists(targetpath):
raise Exception("target path exists and is a file: %s" % args.target)
os.makedirs(targetpath)
name = ".".join(name.split(".")[:-1]) + args.target_extension
targetfilename = os.path.join(targetpath, name)
sourcefile = open(path, "r")
targetfile = open(targetfilename, "w")
print ("create file: %s" % targetfilename)
def process_file(args, src):
dst = create_target_path(args, src)
dstdir = os.path.dirname(dst)
if not os.path.exists(dstdir):
os.makedirs(dstdir)
srcfile = open(src, "r")
dstfile = open(dst, "w")
re_start = re.compile("^(\s*)\/\*\*(.*)$")
re_middle = re.compile("^\s*\*\s(.*)$")
......@@ -63,7 +92,8 @@ def process_file(args, path):
inside = False
indent = 0
for line in sourcefile:
written = 0
for line in srcfile:
if not inside:
m = re_start.match(line)
if m:
......@@ -71,22 +101,29 @@ def process_file(args, path):
m = re_indent.match(m.group(2))
if m:
indent = 0 if not m.group(1) else int(m.group(1))
dstfile.write("\n")
else:
m = re_end.match(line)
if m: