Removed outdated documentation
@ -1,153 +0,0 @@
|
|||||||
# Makefile for Sphinx documentation
|
|
||||||
#
|
|
||||||
|
|
||||||
# You can set these variables from the command line.
|
|
||||||
SPHINXOPTS =
|
|
||||||
SPHINXBUILD = sphinx-build
|
|
||||||
PAPER = a4
|
|
||||||
BUILDDIR = _build
|
|
||||||
|
|
||||||
# Internal variables.
|
|
||||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
|
||||||
PAPEROPT_letter = -D latex_paper_size=letter
|
|
||||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
|
||||||
# the i18n builder cannot share the environment and doctrees with the others
|
|
||||||
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
|
||||||
|
|
||||||
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
|
|
||||||
|
|
||||||
help:
|
|
||||||
@echo "Please use \`make <target>' where <target> is one of"
|
|
||||||
@echo " html to make standalone HTML files"
|
|
||||||
@echo " dirhtml to make HTML files named index.html in directories"
|
|
||||||
@echo " singlehtml to make a single large HTML file"
|
|
||||||
@echo " pickle to make pickle files"
|
|
||||||
@echo " json to make JSON files"
|
|
||||||
@echo " htmlhelp to make HTML files and a HTML help project"
|
|
||||||
@echo " qthelp to make HTML files and a qthelp project"
|
|
||||||
@echo " devhelp to make HTML files and a Devhelp project"
|
|
||||||
@echo " epub to make an epub"
|
|
||||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
|
||||||
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
|
||||||
@echo " text to make text files"
|
|
||||||
@echo " man to make manual pages"
|
|
||||||
@echo " texinfo to make Texinfo files"
|
|
||||||
@echo " info to make Texinfo files and run them through makeinfo"
|
|
||||||
@echo " gettext to make PO message catalogs"
|
|
||||||
@echo " changes to make an overview of all changed/added/deprecated items"
|
|
||||||
@echo " linkcheck to check all external links for integrity"
|
|
||||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
|
||||||
|
|
||||||
clean:
|
|
||||||
-rm -rf $(BUILDDIR)/*
|
|
||||||
|
|
||||||
html:
|
|
||||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
|
||||||
|
|
||||||
dirhtml:
|
|
||||||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
|
||||||
|
|
||||||
singlehtml:
|
|
||||||
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
|
||||||
|
|
||||||
pickle:
|
|
||||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
|
||||||
@echo
|
|
||||||
@echo "Build finished; now you can process the pickle files."
|
|
||||||
|
|
||||||
json:
|
|
||||||
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
|
||||||
@echo
|
|
||||||
@echo "Build finished; now you can process the JSON files."
|
|
||||||
|
|
||||||
htmlhelp:
|
|
||||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
|
||||||
@echo
|
|
||||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
|
||||||
".hhp project file in $(BUILDDIR)/htmlhelp."
|
|
||||||
|
|
||||||
qthelp:
|
|
||||||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
|
||||||
@echo
|
|
||||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
|
||||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
|
||||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/UDS.qhcp"
|
|
||||||
@echo "To view the help file:"
|
|
||||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/UDS.qhc"
|
|
||||||
|
|
||||||
devhelp:
|
|
||||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
|
||||||
@echo
|
|
||||||
@echo "Build finished."
|
|
||||||
@echo "To view the help file:"
|
|
||||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/UDS"
|
|
||||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/UDS"
|
|
||||||
@echo "# devhelp"
|
|
||||||
|
|
||||||
epub:
|
|
||||||
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
|
||||||
|
|
||||||
latex:
|
|
||||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
|
||||||
@echo
|
|
||||||
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
|
||||||
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
|
||||||
"(use \`make latexpdf' here to do that automatically)."
|
|
||||||
|
|
||||||
latexpdf:
|
|
||||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
|
||||||
@echo "Running LaTeX files through pdflatex..."
|
|
||||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf
|
|
||||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
|
||||||
|
|
||||||
text:
|
|
||||||
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
|
||||||
|
|
||||||
man:
|
|
||||||
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
|
||||||
|
|
||||||
texinfo:
|
|
||||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
|
|
||||||
@echo "Run \`make' in that directory to run these through makeinfo" \
|
|
||||||
"(use \`make info' here to do that automatically)."
|
|
||||||
|
|
||||||
info:
|
|
||||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
|
||||||
@echo "Running Texinfo files through makeinfo..."
|
|
||||||
make -C $(BUILDDIR)/texinfo info
|
|
||||||
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
|
|
||||||
|
|
||||||
gettext:
|
|
||||||
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
|
|
||||||
|
|
||||||
changes:
|
|
||||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
|
||||||
@echo
|
|
||||||
@echo "The overview file is in $(BUILDDIR)/changes."
|
|
||||||
|
|
||||||
linkcheck:
|
|
||||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
|
||||||
@echo
|
|
||||||
@echo "Link check complete; look for any errors in the above output " \
|
|
||||||
"or in $(BUILDDIR)/linkcheck/output.txt."
|
|
||||||
|
|
||||||
doctest:
|
|
||||||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
|
||||||
@echo "Testing of doctests in the sources finished, look at the " \
|
|
||||||
"results in $(BUILDDIR)/doctest/output.txt."
|
|
@ -1,4 +0,0 @@
|
|||||||
# Sphinx build info version 1
|
|
||||||
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
|
|
||||||
config: ecdf0c047589d7bf803c9f99cefd9819
|
|
||||||
tags: 645f666f9bcd5a90fca523b33c5a78b7
|
|
@ -1,307 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
# are permitted provided that the following conditions are met:
|
|
||||||
#
|
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
|
||||||
# this list of conditions and the following disclaimer.
|
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
|
||||||
# and/or other materials provided with the distribution.
|
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
|
||||||
# may be used to endorse or promote products derived from this software
|
|
||||||
# without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
'''
|
|
||||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
|
||||||
'''
|
|
||||||
from django.utils.translation import ugettext_noop as translatable
|
|
||||||
from uds.core.ui.UserInterface import gui
|
|
||||||
from uds.core import auths
|
|
||||||
|
|
||||||
import logging
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
class SampleAuth(auths.Authenticator):
|
|
||||||
'''
|
|
||||||
This class represents a sample authenticator.
|
|
||||||
|
|
||||||
As this, it will provide:
|
|
||||||
* The authenticator functionality
|
|
||||||
* 3 Groups, "Mortals", "Gods" and "Daemons", just random group names selected.. :-),
|
|
||||||
plus groups that we enter at Authenticator form, from admin interface.
|
|
||||||
* Search of groups (inside the 3 groups used in this sample plus entered)
|
|
||||||
* Search for people (will return the search string + 000...999 as usernames)
|
|
||||||
* The Required form description for administration interface, so admins can create
|
|
||||||
new authenticators of this kind.
|
|
||||||
|
|
||||||
In this sample, we will provide a simple standard auth, with owner drawn
|
|
||||||
login form that will simply show users that has been created and allow web user
|
|
||||||
to select one of them.
|
|
||||||
|
|
||||||
For this class to get visible at administration client as a authenticator type,
|
|
||||||
we MUST register it at package __init__
|
|
||||||
|
|
||||||
:note: At class level, the translations must be simply marked as so
|
|
||||||
using ugettext_noop. This is done in this way because we will translate
|
|
||||||
the string when it is sent to the administration client.
|
|
||||||
'''
|
|
||||||
|
|
||||||
#: Name of type, used at administration interface to identify this
|
|
||||||
#: authenticator (i.e. LDAP, SAML, ...)
|
|
||||||
#: This string will be translated when provided to admin interface
|
|
||||||
#: using ugettext, so you can mark it as "translatable" at derived classes (using ugettext_noop)
|
|
||||||
#: if you want so it can be translated.
|
|
||||||
typeName = translatable('Sample Authenticator')
|
|
||||||
|
|
||||||
#: Name of type used by Managers to identify this type of service
|
|
||||||
#: We could have used here the Class name, but we decided that the
|
|
||||||
#: module implementator will be the one that will provide a name that
|
|
||||||
#: will relation the class (type) and that name.
|
|
||||||
typeType = 'SampleAuthenticator'
|
|
||||||
|
|
||||||
#: Description shown at administration level for this authenticator.
|
|
||||||
#: This string will be translated when provided to admin interface
|
|
||||||
#: using ugettext, so you can mark it as "translatable" at derived classes (using ugettext_noop)
|
|
||||||
#: if you want so it can be translated.
|
|
||||||
typeDescription = translatable('Sample dummy authenticator')
|
|
||||||
|
|
||||||
|
|
||||||
#: Icon file, used to represent this authenticator at administration interface
|
|
||||||
#: This file should be at same folder as this class is, except if you provide
|
|
||||||
#: your own :py:meth:uds.core.BaseModule.BaseModule.icon method.
|
|
||||||
iconFile = 'auth.png'
|
|
||||||
|
|
||||||
#: Mark this authenticator as that the users comes from outside the UDS
|
|
||||||
#: database, that are most authenticator (except Internal DB)
|
|
||||||
#: True is the default value, so we do not need it in fact
|
|
||||||
# isExternalSource = True
|
|
||||||
|
|
||||||
#: If we need to enter the password for this user when creating a new
|
|
||||||
#: user at administration interface. Used basically by internal authenticator.
|
|
||||||
#: False is the default value, so this is not needed in fact
|
|
||||||
#: needsPassword = False
|
|
||||||
|
|
||||||
#: Label for username field, shown at administration interface user form.
|
|
||||||
userNameLabel = translatable('Fake User')
|
|
||||||
|
|
||||||
# Label for group field, shown at administration interface user form.
|
|
||||||
groupNameLabel = translatable('Fake Group')
|
|
||||||
|
|
||||||
#: Definition of this type of authenticator form
|
|
||||||
#: We will define a simple form where we will use a simple
|
|
||||||
#: list editor to allow entering a few group names
|
|
||||||
|
|
||||||
groups = gui.EditableList(label=translatable('Groups'), values = ['Gods', 'Daemons', 'Mortals'])
|
|
||||||
|
|
||||||
def initialize(self, values):
|
|
||||||
'''
|
|
||||||
Simply check if we have
|
|
||||||
at least one group in the list
|
|
||||||
'''
|
|
||||||
|
|
||||||
# To avoid problems, we only check data if values are passed
|
|
||||||
# If values are not passed in, form data will only be available after
|
|
||||||
# unserialization, and at this point all will be default values
|
|
||||||
# so self.groups.value will be []
|
|
||||||
if values is not None and len(self.groups.value) < 2:
|
|
||||||
raise auths.Authenticator.ValidationException(translatable('We need more that two items!'))
|
|
||||||
|
|
||||||
def searchUsers(self, pattern):
|
|
||||||
'''
|
|
||||||
Here we will receive a pattern for searching users.
|
|
||||||
|
|
||||||
This method is invoked from interface, so an administrator can search users.
|
|
||||||
|
|
||||||
If we do not provide this method, the authenticator will not provide search
|
|
||||||
facility for users. In our case, we will simply return a list of users
|
|
||||||
(array of dictionaries with ids and names) with the pattern plus 1..10
|
|
||||||
'''
|
|
||||||
return [ { 'id' : '{0}-{1}'.format(pattern, a), 'name' : '{0} number {1}'.format(pattern, a) } for a in range(1, 10)]
|
|
||||||
|
|
||||||
def searchGroups(self, pattern):
|
|
||||||
'''
|
|
||||||
Here we we will receive a patter for searching groups.
|
|
||||||
|
|
||||||
In this sample, we will try to locate elements that where entered at
|
|
||||||
sample authenticator form (when created), and return the ones that
|
|
||||||
contains the pattern indicated.
|
|
||||||
'''
|
|
||||||
pattern = pattern.lower()
|
|
||||||
res = []
|
|
||||||
for g in self.groups.value:
|
|
||||||
if g.lower().find(pattern) != -1:
|
|
||||||
res.append({'id' : g, 'name' : ''})
|
|
||||||
return res
|
|
||||||
|
|
||||||
def authenticate(self, username, credentials, groupsManager):
|
|
||||||
'''
|
|
||||||
This method is invoked by UDS whenever it needs an user to be authenticated.
|
|
||||||
It is used from web interface, but also from administration interface to
|
|
||||||
check credentials and access of user.
|
|
||||||
|
|
||||||
The tricky part of this method is the groupsManager, but it's easy to
|
|
||||||
understand what is used it for.
|
|
||||||
|
|
||||||
Imagine some authenticator, for example, an LDAP. It has its users, it has
|
|
||||||
its groups, and it has it relations (which user belongs to which group).
|
|
||||||
|
|
||||||
Now think about UDS. UDS know nothing about this, it only knows what
|
|
||||||
the administator has entered at admin interface (groups mainly, but he can
|
|
||||||
create users also).
|
|
||||||
|
|
||||||
UDS knows about this groups, but we need to relation those with the ones
|
|
||||||
know by the authenticator.
|
|
||||||
|
|
||||||
To do this, we have created a simple mechanism, where the authenticator
|
|
||||||
receives a groupsManager, that knows all groups known by UDS, and has
|
|
||||||
the method so the authenticator can say, for the username being validated,
|
|
||||||
to which uds groups it belongs to.
|
|
||||||
|
|
||||||
This is done using the :py:meth:uds.core.auths.GroupsManager.GroupsManager.validate
|
|
||||||
method of the provided groups manager.
|
|
||||||
|
|
||||||
At return, UDS will do two things:
|
|
||||||
* If there is no group inside the groupsManager mareked as valid, it will
|
|
||||||
denied access.
|
|
||||||
* If there is some groups marked as valid, it will refresh the known
|
|
||||||
UDS relations (this means that the database will be refresehd so the user
|
|
||||||
has valid groups).
|
|
||||||
|
|
||||||
This also means that the group membership is only checked at user login (well,
|
|
||||||
in fact its also checked when an administrator tries to modify an user)
|
|
||||||
|
|
||||||
So, authenticate must not also validate the user credentials, but also
|
|
||||||
indicate the group membership of this user inside UDS.
|
|
||||||
|
|
||||||
:note: groupsManager is an in/out parameter
|
|
||||||
'''
|
|
||||||
if username != credentials: # All users with same username and password are allowed
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Now the tricky part. We will make this user belong to groups that contains at leat
|
|
||||||
# two letters equals to the groups names known by UDS
|
|
||||||
# For this, we will ask the groups manager for the groups names, and will check that and,
|
|
||||||
# if the user match this criteria, will mark that group as valid
|
|
||||||
for g in groupsManager.getGroupsNames():
|
|
||||||
if len(set(g.lower()).intersection(username.lower())) >= 2:
|
|
||||||
groupsManager.validate(g)
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
def getGroups(self, username, groupsManager):
|
|
||||||
'''
|
|
||||||
As with authenticator part related to groupsManager, this
|
|
||||||
method will fill the groups to which the specified username belongs to.
|
|
||||||
|
|
||||||
We have to fill up groupsManager from two different places, so it's not
|
|
||||||
a bad idea to make a method that get the "real" authenticator groups and
|
|
||||||
them simply call to :py:meth:uds.core.auths.GroupsManager.GroupsManager.validate
|
|
||||||
|
|
||||||
In our case, we simply repeat the process that we also do at authenticate
|
|
||||||
'''
|
|
||||||
for g in groupsManager.getGroupsNames():
|
|
||||||
if len(set(g.lower()).intersection(username.lower())) >= 2:
|
|
||||||
groupsManager.validate(g)
|
|
||||||
|
|
||||||
def getHtml(self, request):
|
|
||||||
'''
|
|
||||||
If we override this method from the base one, we are telling UDS
|
|
||||||
that we want to draw our own authenticator.
|
|
||||||
|
|
||||||
This way, we can do whataver we want here (for example redirect to a site
|
|
||||||
for a single sign on) generation our ouwn html (and javascript ofc).
|
|
||||||
|
|
||||||
'''
|
|
||||||
# Here there is a sample, commented out
|
|
||||||
# In this sample, we will make a list of valid users, and when clicked,
|
|
||||||
# it will fill up original form with username and same password, and submit it.
|
|
||||||
#res = ''
|
|
||||||
#for u in self.dbAuthenticator().users.all():
|
|
||||||
# res += '<a class="myNames" id="{0}" href="">{0}</a><br/>'.format(u.name)
|
|
||||||
#
|
|
||||||
#res += '<script type="text/javascript">$(".myNames").click(function() { '
|
|
||||||
#res += '$("#id_user").val(this.id); $("#id_password").val(this.id); $("#loginform").submit(); return false;});</script>'
|
|
||||||
#return res
|
|
||||||
|
|
||||||
# I know, this is a bit ugly, but this is just a sample :-)
|
|
||||||
|
|
||||||
res = '<p>Login name: <input id="logname" type="text"/></p>'
|
|
||||||
res +='<p><a href="" onclick="window.location.replace(\'' + self.callbackUrl() + '?user='
|
|
||||||
res += '\' + $(\'#logname\').val()); return false;">Login</a></p>'
|
|
||||||
return res
|
|
||||||
|
|
||||||
|
|
||||||
def authCallback(self, parameters):
|
|
||||||
'''
|
|
||||||
We provide this as a sample of callback for an user.
|
|
||||||
We will accept all petitions that has "user" parameter
|
|
||||||
|
|
||||||
This method will get invoked by url redirections, probably by an SSO.
|
|
||||||
|
|
||||||
The idea behind this is that we can provide:
|
|
||||||
* Simple user/password authentications
|
|
||||||
* Own authentications (not UDS, authenticator "owned"), but with no redirections
|
|
||||||
* Own authentications via redirections (as most SSO will do)
|
|
||||||
|
|
||||||
Here, we will receive the parameters for this
|
|
||||||
'''
|
|
||||||
user = parameters.get('user', None)
|
|
||||||
|
|
||||||
return user
|
|
||||||
|
|
||||||
def createUser(self, usrData):
|
|
||||||
'''
|
|
||||||
This method provides a "check oportunity" to authenticators for users created
|
|
||||||
manually at administration interface.
|
|
||||||
|
|
||||||
If we do not provide this method, the administration interface will not allow
|
|
||||||
to create new users "by hand", i mean, the "new" options from menus will dissapear.
|
|
||||||
|
|
||||||
usrData is a dictionary that contains the input parameters from user,
|
|
||||||
with at least name, realName, comments, state & password.
|
|
||||||
|
|
||||||
We can modify this parameters, we can modify ALL, but name is not recommended to
|
|
||||||
modify it unles you know what you are doing.
|
|
||||||
|
|
||||||
Here, we will set the state to "Inactive" and realName to the same as username, but twice :-)
|
|
||||||
'''
|
|
||||||
from uds.core.util.State import State
|
|
||||||
usrData['realName'] = usrData['name'] + ' ' + usrData['name']
|
|
||||||
usrData['state'] = State.INACTIVE
|
|
||||||
|
|
||||||
def modifyUser(self, usrData):
|
|
||||||
'''
|
|
||||||
This method provides a "check opportunity" to authenticator for users modified
|
|
||||||
at administration interface.
|
|
||||||
|
|
||||||
If we do not provide this method, nothing will happen (default one does nothing, but
|
|
||||||
it's valid).
|
|
||||||
|
|
||||||
usrData is a dictionary that contains the input parameters from user,
|
|
||||||
with at least name, realName, comments, state & password.
|
|
||||||
|
|
||||||
We can modify this parameters, we can modify ALL, but name is not recommended to
|
|
||||||
modify it unless you know what you are doing.
|
|
||||||
|
|
||||||
Here, we will simply update the realName of the user, and (we have to take care
|
|
||||||
this this kind of things) modify the userName to a new one, the original plus '-1'
|
|
||||||
'''
|
|
||||||
usrData['realName'] = usrData['name'] + ' ' + usrData['name']
|
|
||||||
usrData['name'] = usrData['name'] + '-1'
|
|
@ -1,196 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
# are permitted provided that the following conditions are met:
|
|
||||||
#
|
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
|
||||||
# this list of conditions and the following disclaimer.
|
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
|
||||||
# and/or other materials provided with the distribution.
|
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
|
||||||
# may be used to endorse or promote products derived from this software
|
|
||||||
# without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
'''
|
|
||||||
Created on Jun 22, 2012
|
|
||||||
|
|
||||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
|
||||||
'''
|
|
||||||
|
|
||||||
from django.utils.translation import ugettext_noop as translatable, ugettext as _
|
|
||||||
from uds.core.services import ServiceProvider
|
|
||||||
from SampleService import ServiceOne, ServiceTwo
|
|
||||||
from uds.core.ui import gui
|
|
||||||
|
|
||||||
import logging
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class Provider(ServiceProvider):
|
|
||||||
'''
|
|
||||||
This class represents the sample services provider
|
|
||||||
|
|
||||||
In this class we provide:
|
|
||||||
* The Provider functionality
|
|
||||||
* The basic configuration parameters for the provider
|
|
||||||
* The form fields needed by administrators to configure this provider
|
|
||||||
|
|
||||||
:note: At class level, the translation must be simply marked as so
|
|
||||||
using ugettext_noop. This is so cause we will translate the string when
|
|
||||||
sent to the administration client.
|
|
||||||
|
|
||||||
For this class to get visible at administration client as a provider type,
|
|
||||||
we MUST register it at package __init__.
|
|
||||||
|
|
||||||
'''
|
|
||||||
#: What kind of services we offer, this are classes inherited from Service
|
|
||||||
offers = [ServiceOne, ServiceTwo]
|
|
||||||
#: Name to show the administrator. This string will be translated BEFORE
|
|
||||||
#: sending it to administration interface, so don't forget to
|
|
||||||
#: mark it as translatable (using ugettext_noop)
|
|
||||||
typeName = translatable('Sample Provider')
|
|
||||||
#: Type used internally to identify this provider
|
|
||||||
typeType = 'SampleProvider'
|
|
||||||
#: Description shown at administration interface for this provider
|
|
||||||
typeDescription = translatable('Sample (and dummy) service provider')
|
|
||||||
#: Icon file used as icon for this provider. This string will be translated
|
|
||||||
#: BEFORE sending it to administration interface, so don't forget to
|
|
||||||
#: mark it as translatable (using ugettext_noop)
|
|
||||||
iconFile = 'provider.png'
|
|
||||||
|
|
||||||
# now comes the form fields
|
|
||||||
# There is always two fields that are requested to the admin, that are:
|
|
||||||
# Service Name, that is a name that the admin uses to name this provider
|
|
||||||
# Description, that is a short description that the admin gives to this provider
|
|
||||||
# Now we are going to add a few fields that we need to use this provider
|
|
||||||
# Remember that these are "dummy" fields, that in fact are not required
|
|
||||||
# but used for sample purposes
|
|
||||||
# If we don't indicate an order, the output order of fields will be
|
|
||||||
# "random"
|
|
||||||
|
|
||||||
#: Remote host. Here core will translate label and tooltip, remember to
|
|
||||||
#: mark them as translatable using ugettext_noop.
|
|
||||||
remoteHost = gui.TextField(oder=1,
|
|
||||||
length = 64,
|
|
||||||
label = translatable('Remote host'),
|
|
||||||
tooltip = translatable('This fields contains a remote host'),
|
|
||||||
required = True,
|
|
||||||
)
|
|
||||||
#: Name of your pet (sample, not really needed :-) )
|
|
||||||
petName = gui.TextField(order=2,
|
|
||||||
length = 32,
|
|
||||||
label = translatable('Your pet\'s name'),
|
|
||||||
tooltip = translatable('If you like, write the name of your pet'),
|
|
||||||
requred = False,
|
|
||||||
defvalue = 'Tux' #: This will not get translated
|
|
||||||
)
|
|
||||||
#: Age of Methuselah (matusalén in spanish)
|
|
||||||
#: in Spain there is a well-known to say that something is very old,
|
|
||||||
#: "Tiene mas años que matusalén"(is older than Methuselah)
|
|
||||||
methAge = gui.NumericField(order = 3,
|
|
||||||
length = 4, # That is, max allowed value is 9999
|
|
||||||
label = translatable('Age of Methuselah'),
|
|
||||||
tooltip = translatable('If you know it, please, tell me!!!'),
|
|
||||||
required = True, #: Numeric fields have always a value, so this not really needed
|
|
||||||
defvalue = '4500'
|
|
||||||
)
|
|
||||||
|
|
||||||
#: Is Methuselah istill alive?
|
|
||||||
methAlive = gui.CheckBoxField(order = 4,
|
|
||||||
label = translatable('Is Methuselah still alive?'),
|
|
||||||
tooltip = translatable('If you fail, this will not get saved :-)'),
|
|
||||||
required = True, #: Also means nothing. Check boxes has always a value
|
|
||||||
defvalue = gui.TRUE #: By default, at new item, check this
|
|
||||||
)
|
|
||||||
|
|
||||||
# There is more fields type, but not here the best place to cover it
|
|
||||||
def initialize(self, values = None):
|
|
||||||
'''
|
|
||||||
We will use the "autosave" feature for form fields, that is more than
|
|
||||||
enought for most providers. (We simply need to store data provided by user
|
|
||||||
and, maybe, initialize some kind of connection with this values).
|
|
||||||
|
|
||||||
Normally provider values are rally used at sevice level, cause we never
|
|
||||||
instantiate nothing except a service from a provider.
|
|
||||||
'''
|
|
||||||
|
|
||||||
# If you say meth is alive, you are wrong!!! (i guess..)
|
|
||||||
# values are only passed from administration client. Internals
|
|
||||||
# instantiations are always empty.
|
|
||||||
if values is not None and self.methAlive.isTrue():
|
|
||||||
raise ServiceProvider.ValidationException(_('Methuselah is not alive!!! :-)'))
|
|
||||||
|
|
||||||
# Marshal and unmarshal are defaults ones, also enought
|
|
||||||
|
|
||||||
# As we use "autosave" fields feature, dictValues is also provided by
|
|
||||||
# base class so we don't have to mess with all those things...
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def test(env, data):
|
|
||||||
'''
|
|
||||||
Create your test method here so the admin can push the "check" button
|
|
||||||
and this gets executed.
|
|
||||||
Args:
|
|
||||||
env: environment passed for testing (temporal environment passed)
|
|
||||||
|
|
||||||
data: data passed for testing (data obtained from the form
|
|
||||||
definition)
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Array of two elements, first is True of False, depending on test
|
|
||||||
(True is all right, false is error),
|
|
||||||
second is an String with error, preferably internacionalizated..
|
|
||||||
|
|
||||||
In this case, wi well do nothing more that use the provider params
|
|
||||||
|
|
||||||
Note also that this is an static method, that will be invoked using
|
|
||||||
the admin user provided data via administration client, and a temporary
|
|
||||||
environment that will be erased after invoking this method
|
|
||||||
'''
|
|
||||||
try:
|
|
||||||
# We instantiate the provider, but this may fail...
|
|
||||||
instance = Provider(env, data)
|
|
||||||
logger.debug('Methuselah has {0} years and is {1} :-)'
|
|
||||||
.format(instance.methAge.value, instance.methAlive.value))
|
|
||||||
except ServiceProvider.ValidationException as e:
|
|
||||||
# If we say that meth is alive, instantiation will
|
|
||||||
return [False, str(e)]
|
|
||||||
except Exception as e:
|
|
||||||
logger.exception("Exception caugth!!!")
|
|
||||||
return [False, str(e)]
|
|
||||||
return [True, _('Nothing tested, but all went fine..')]
|
|
||||||
|
|
||||||
# Congratulations!!!, the needed part of your first simple provider is done!
|
|
||||||
# Now you can go to administration panel, and check it
|
|
||||||
#
|
|
||||||
# From now onwards, we implement our own methods, that will be used by,
|
|
||||||
# for example, services derived from this provider
|
|
||||||
def host(self):
|
|
||||||
'''
|
|
||||||
Sample method, in fact in this we just return
|
|
||||||
the value of host field, that is an string
|
|
||||||
'''
|
|
||||||
return self.remoteHost.value
|
|
||||||
|
|
||||||
|
|
||||||
def methYears(self):
|
|
||||||
'''
|
|
||||||
Another sample return, it will in fact return the Methuselah years
|
|
||||||
'''
|
|
@ -1,272 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
# are permitted provided that the following conditions are met:
|
|
||||||
#
|
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
|
||||||
# this list of conditions and the following disclaimer.
|
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
|
||||||
# and/or other materials provided with the distribution.
|
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
|
||||||
# may be used to endorse or promote products derived from this software
|
|
||||||
# without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
'''
|
|
||||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
|
||||||
'''
|
|
||||||
|
|
||||||
from django.utils.translation import ugettext as _
|
|
||||||
from uds.core.services import Publication
|
|
||||||
from uds.core.util.State import State
|
|
||||||
from datetime import datetime
|
|
||||||
import logging
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
class SamplePublication(Publication):
|
|
||||||
'''
|
|
||||||
This class shows how a publication is developed.
|
|
||||||
|
|
||||||
In order to a publication to work correctly, we must provide at least the
|
|
||||||
following methods:
|
|
||||||
* Of course, the __init__
|
|
||||||
* :py:meth:`.publish`
|
|
||||||
* :py:meth:`.checkState`
|
|
||||||
* :py:meth:`.finish`
|
|
||||||
|
|
||||||
Also, of course, methods from :py:class:`uds.core.Serializable.Serializable`
|
|
||||||
|
|
||||||
|
|
||||||
Publication do not have an configuration interface, all data contained
|
|
||||||
inside an instance of a Publication must be serialized if you want them between
|
|
||||||
method calls.
|
|
||||||
|
|
||||||
It's not waranteed that the class will not be serialized/deserialized
|
|
||||||
between methods calls, so, first of all, implement the marshal and umnarshal
|
|
||||||
mehods needed by all serializable classes.
|
|
||||||
|
|
||||||
Also a thing to note is that operations requested to Publications must be
|
|
||||||
*as fast as posible*. The operations executes in a separated thread,
|
|
||||||
and so it cant take a bit more time to execute, but it's recommended that
|
|
||||||
the operations executes as fast as posible, and, if it will take a long time,
|
|
||||||
split operation so we can keep track of state.
|
|
||||||
|
|
||||||
This means that, if we have "slow" operations, we must
|
|
||||||
|
|
||||||
We first of all declares an estimation of how long a publication will take.
|
|
||||||
This value is instance based, so if we override it in our class, the suggested
|
|
||||||
time could change.
|
|
||||||
|
|
||||||
The class attribute that indicates this suggested time is "suggestedTime", and
|
|
||||||
it's expressed in seconds, (i.e. "suggestedTime = 10")
|
|
||||||
'''
|
|
||||||
|
|
||||||
suggestedTime = 5 #: Suggested recheck time if publication is unfinished in seconds
|
|
||||||
|
|
||||||
def initialize(self):
|
|
||||||
'''
|
|
||||||
This method will be invoked by default __init__ of base class, so it gives
|
|
||||||
us the oportunity to initialize whataver we need here.
|
|
||||||
|
|
||||||
In our case, we setup a few attributes..
|
|
||||||
'''
|
|
||||||
|
|
||||||
# We do not check anything at marshal method, so we ensure that
|
|
||||||
# default values are correctly handled by marshal.
|
|
||||||
self._name = 'test'
|
|
||||||
self._reason = '' # No error, no reason for it
|
|
||||||
self._number = 1
|
|
||||||
|
|
||||||
def marshal(self):
|
|
||||||
'''
|
|
||||||
returns data from an instance of Sample Publication serialized
|
|
||||||
'''
|
|
||||||
return '\t'.join( [self._name, self._reason, str(self._number)] )
|
|
||||||
|
|
||||||
def unmarshal(self, data):
|
|
||||||
'''
|
|
||||||
deserializes the data and loads it inside instance.
|
|
||||||
'''
|
|
||||||
logger.debug('Data: {0}'.format(data))
|
|
||||||
vals = data.split('\t')
|
|
||||||
logger.debug('Values: {0}'.format(vals))
|
|
||||||
self._name = vals[0]
|
|
||||||
self._reason = vals[1]
|
|
||||||
self._number = int(vals[2])
|
|
||||||
|
|
||||||
|
|
||||||
def publish(self):
|
|
||||||
'''
|
|
||||||
This method is invoked whenever the administrator requests a new publication.
|
|
||||||
|
|
||||||
The method is not invoked directly (i mean, that the administration request
|
|
||||||
do no makes a call to this method), but a DelayedTask is saved witch will
|
|
||||||
initiate all publication stuff (and, of course, call this method).
|
|
||||||
|
|
||||||
You MUST implement it, so the publication do really something.
|
|
||||||
All publications can be synchronous or asynchronous.
|
|
||||||
|
|
||||||
The main difference between both is that first do whatever needed, (the
|
|
||||||
action must be fast enough to do not block core), returning State.FINISHED.
|
|
||||||
|
|
||||||
The second (asynchronous) are publications that could block the core, so
|
|
||||||
it have to be done in more than one step.
|
|
||||||
|
|
||||||
An example publication could be a copy of a virtual machine, where:
|
|
||||||
* First we invoke the copy operation to virtualization provider
|
|
||||||
* Second, we kept needed values inside instance so we can serialize
|
|
||||||
them whenever requested
|
|
||||||
* Returns an State.RUNNING, indicating the core that the publication
|
|
||||||
has started but has to finish sometime later. (We do no check
|
|
||||||
again the state and keep waiting here, because we will block the
|
|
||||||
core untill this operation is finished).
|
|
||||||
|
|
||||||
In our example wi will simple assign a name, and set number to 5. We
|
|
||||||
will use this number later, to make a "delay" at check if the publication
|
|
||||||
has finished. (see method checkState)
|
|
||||||
|
|
||||||
We also will make this publication an "stepped one", that is, it will not
|
|
||||||
finish at publish call but a later checkState call
|
|
||||||
|
|
||||||
Take care with instantiating threads from here. Whenever a publish returns
|
|
||||||
"State.RUNNING", the core will recheck it later, but not using this instance
|
|
||||||
and maybe that even do not use this server.
|
|
||||||
|
|
||||||
If you want to use threadings or somethin likt it, use DelayedTasks and
|
|
||||||
do not block it. You also musht provide the mechanism to allow those
|
|
||||||
DelayedTask to communicate with the publication.
|
|
||||||
|
|
||||||
One sample could be, for example, to copy a bunch of files, but we know
|
|
||||||
that this copy can take a long time and don't want it to take make it
|
|
||||||
all here, but in a separate task. Now, do you remember that "environment"
|
|
||||||
that is unique for every instance?, well, we can create a delayed task,
|
|
||||||
and pass that environment (owned by this intance) as a mechanism for
|
|
||||||
informing when the task is finished. (We insert at delayed tasks queue
|
|
||||||
an instance, not a class itself, so we can instantiate a class and
|
|
||||||
store it at delayed task queue.
|
|
||||||
|
|
||||||
Also note that, in that case, this class can also acomplish that by simply
|
|
||||||
using the suggestedTime attribute and the checkState method in most cases.
|
|
||||||
'''
|
|
||||||
self._number = 5
|
|
||||||
self._reason = ''
|
|
||||||
return State.RUNNING
|
|
||||||
|
|
||||||
def checkState(self):
|
|
||||||
'''
|
|
||||||
Our publish method will initiate publication, but will not finish it.
|
|
||||||
So in our sample, wi will only check if _number reaches 0, and if so
|
|
||||||
return that we have finished, else we will return that we are working
|
|
||||||
on it.
|
|
||||||
|
|
||||||
One publish returns State.RUNNING, this task will get called untill
|
|
||||||
checkState returns State.FINISHED.
|
|
||||||
|
|
||||||
Also, wi will make the publication fail one of every 10 calls to this
|
|
||||||
method.
|
|
||||||
|
|
||||||
Note: Destroying an publication also makes use of this method, so you
|
|
||||||
must keep the info of that you are checking (publishing or destroying...)
|
|
||||||
In our case, destroy is 1-step action so this will no get called while
|
|
||||||
destroying...
|
|
||||||
'''
|
|
||||||
import random
|
|
||||||
self._number -= 1
|
|
||||||
# Serialization will take care of storing self._number
|
|
||||||
|
|
||||||
# One of every 10 calls
|
|
||||||
if random.randint(0, 9) == 9:
|
|
||||||
self._reason = _('Random integer was 9!!! :-)')
|
|
||||||
return State.ERROR
|
|
||||||
|
|
||||||
if self._number <= 0:
|
|
||||||
return State.FINISHED
|
|
||||||
else:
|
|
||||||
return State.RUNNING
|
|
||||||
|
|
||||||
|
|
||||||
def finish(self):
|
|
||||||
'''
|
|
||||||
Invoked when Publication manager noticed that the publication has finished.
|
|
||||||
This give us the oportunity of cleaning up things (as stored vars, etc..),
|
|
||||||
or initialize variables that will be needed in a later phase (by deployed
|
|
||||||
services)
|
|
||||||
|
|
||||||
Returned value, if any, is ignored
|
|
||||||
'''
|
|
||||||
import string
|
|
||||||
import random
|
|
||||||
# Make simply a random string
|
|
||||||
self._name = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(10))
|
|
||||||
|
|
||||||
def reasonOfError(self):
|
|
||||||
'''
|
|
||||||
If a publication produces an error, here we must notify the reason why
|
|
||||||
it happened. This will be called just after publish or checkState
|
|
||||||
if they return State.ERROR
|
|
||||||
|
|
||||||
Returns an string, in our case, set at checkState
|
|
||||||
'''
|
|
||||||
return self._reason
|
|
||||||
|
|
||||||
def destroy(self):
|
|
||||||
'''
|
|
||||||
This is called once a publication is no more needed.
|
|
||||||
|
|
||||||
This method do whatever needed to clean up things, such as
|
|
||||||
removing created "external" data (environment gets cleaned by core),
|
|
||||||
etc..
|
|
||||||
|
|
||||||
The retunred value is the same as when publishing, State.RUNNING,
|
|
||||||
State.FINISHED or State.ERROR.
|
|
||||||
'''
|
|
||||||
self._name = ''
|
|
||||||
self._reason = '' # In fact, this is not needed, but cleaning up things... :-)
|
|
||||||
|
|
||||||
# We do not do anything else to destroy this instance of publication
|
|
||||||
return State.FINISHED
|
|
||||||
|
|
||||||
|
|
||||||
def cancel(self):
|
|
||||||
'''
|
|
||||||
Invoked for canceling the current operation.
|
|
||||||
This can be invoked directly by an administration or by the clean up
|
|
||||||
of the deployed service (indirectly).
|
|
||||||
When administrator requests it, the cancel is "delayed" and not
|
|
||||||
invoked directly.
|
|
||||||
|
|
||||||
Also, take into account that cancel is the initiation of, maybe, a
|
|
||||||
multiple-step action, so it returns, as publish and destroy does.
|
|
||||||
|
|
||||||
In our case, cancel simply invokes "destroy", that cleans up
|
|
||||||
things and returns that the action has finished in 1 step.
|
|
||||||
'''
|
|
||||||
return self.destroy()
|
|
||||||
|
|
||||||
# Here ends the publication needed methods.
|
|
||||||
# Methods provided below are specific for this publication
|
|
||||||
# and will be used by user deployments that uses this kind of publication
|
|
||||||
|
|
||||||
def getBaseName(self):
|
|
||||||
'''
|
|
||||||
This sample method (just for this sample publication), provides
|
|
||||||
the name generater for this publication. This is just a sample, and
|
|
||||||
this will do the work
|
|
||||||
'''
|
|
||||||
return self._name
|
|
@ -1,236 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
# are permitted provided that the following conditions are met:
|
|
||||||
#
|
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
|
||||||
# this list of conditions and the following disclaimer.
|
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
|
||||||
# and/or other materials provided with the distribution.
|
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
|
||||||
# may be used to endorse or promote products derived from this software
|
|
||||||
# without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
'''
|
|
||||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
|
||||||
'''
|
|
||||||
|
|
||||||
from django.utils.translation import ugettext_noop as translatable, ugettext as _
|
|
||||||
from uds.core.services import Service
|
|
||||||
from SamplePublication import SamplePublication
|
|
||||||
from SampleUserDeploymentOne import SampleUserDeploymentOne
|
|
||||||
from SampleUserDeploymentTwo import SampleUserDeploymentTwo
|
|
||||||
|
|
||||||
from uds.core.ui import gui
|
|
||||||
|
|
||||||
import logging
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
class ServiceOne(Service):
|
|
||||||
'''
|
|
||||||
Basic service, the first part (variables) include the description of the service.
|
|
||||||
|
|
||||||
Remember to fill all variables needed, but at least you must define:
|
|
||||||
* typeName
|
|
||||||
* typeType
|
|
||||||
* typeDescription
|
|
||||||
* iconFile (defaults to service.png)
|
|
||||||
* publicationType, type of publication in case it needs publication.
|
|
||||||
If this is not provided, core will assume that the service do not
|
|
||||||
needs publishing.
|
|
||||||
* deployedType, type of deployed user service. Do not forget this!!!
|
|
||||||
|
|
||||||
The rest of them can be ommited, but its recommended that you fill all
|
|
||||||
declarations shown in this sample (that in fact, are all)
|
|
||||||
|
|
||||||
This description informs the core what this service really provides,
|
|
||||||
and how this is done. Look at description of class variables for more
|
|
||||||
information.
|
|
||||||
|
|
||||||
'''
|
|
||||||
#: Name to show the administrator. This string will be translated BEFORE
|
|
||||||
#: sending it to administration interface, so don't forget to
|
|
||||||
#: mark it as translatable (using ugettext_noop)
|
|
||||||
typeName = translatable('Sample Service One')
|
|
||||||
#: Type used internally to identify this provider
|
|
||||||
typeType = 'SampleService1'
|
|
||||||
#: Description shown at administration interface for this provider
|
|
||||||
typeDescription = translatable('Sample (and dummy) service ONE')
|
|
||||||
#: Icon file used as icon for this provider. This string will be translated
|
|
||||||
#: BEFORE sending it to administration interface, so don't forget to
|
|
||||||
#: mark it as translatable (using ugettext_noop)
|
|
||||||
iconFile = 'service.png'
|
|
||||||
|
|
||||||
# Functional related data
|
|
||||||
|
|
||||||
#: If the service provides more than 1 "deployed user" (-1 = no limit,
|
|
||||||
#: 0 = ???? (do not use it!!!), N = max number to deploy
|
|
||||||
maxDeployed = -1
|
|
||||||
#: If we need to generate "cache" for this service, so users can access the
|
|
||||||
#: provided services faster. Is usesCache is True, you will need also
|
|
||||||
#: set publicationType, do take care about that!
|
|
||||||
usesCache = False
|
|
||||||
#: Tooltip shown to user when this item is pointed at admin interface, none
|
|
||||||
#: because we don't use it
|
|
||||||
cacheTooltip = translatable('None')
|
|
||||||
#: If we need to generate a "Level 2" cache for this service (i.e., L1
|
|
||||||
#: could be running machines and L2 suspended machines)
|
|
||||||
usesCache_L2 = False
|
|
||||||
#: Tooltip shown to user when this item is pointed at admin interface, None
|
|
||||||
#: also because we don't use it
|
|
||||||
cacheTooltip_L2 = translatable('None')
|
|
||||||
|
|
||||||
#: If the service needs a s.o. manager (managers are related to agents
|
|
||||||
#: provided by services itselfs, i.e. virtual machines with actors)
|
|
||||||
needsManager = False
|
|
||||||
#: If true, the system can't do an automatic assignation of a deployed user
|
|
||||||
#: service from this service
|
|
||||||
mustAssignManually = False
|
|
||||||
|
|
||||||
#: Types of publications (preparated data for deploys)
|
|
||||||
#: In our case, we do no need a publication, so this is None
|
|
||||||
publicationType = None
|
|
||||||
#: Types of deploys (services in cache and/or assigned to users)
|
|
||||||
deployedType = SampleUserDeploymentOne
|
|
||||||
|
|
||||||
# Now the form part, this service will have only two "dummy" fields
|
|
||||||
# If we don't indicate an order, the output order of fields will be
|
|
||||||
# "random"
|
|
||||||
|
|
||||||
colour = gui.ChoiceField(order = 1,
|
|
||||||
label = translatable('Colour'),
|
|
||||||
tooltip = translatable('Colour of the field'),
|
|
||||||
# In this case, the choice can have none value selected by default
|
|
||||||
required = True,
|
|
||||||
values = [ gui.choiceItem('red', 'Red'),
|
|
||||||
gui.choiceItem('green', 'Green'),
|
|
||||||
gui.choiceItem('blue', 'Blue'),
|
|
||||||
gui.choiceItem('nonsense', 'Blagenta')
|
|
||||||
],
|
|
||||||
defvalue = '1' # Default value is the ID of the choicefield
|
|
||||||
)
|
|
||||||
|
|
||||||
passw = gui.PasswordField(order = 2,
|
|
||||||
label = translatable('Password'),
|
|
||||||
tooltip = translatable('Password for testing purposes'),
|
|
||||||
required = True,
|
|
||||||
defvalue = '1234' #: Default password are nonsense?? :-)
|
|
||||||
)
|
|
||||||
|
|
||||||
baseName = gui.TextField(order = 3,
|
|
||||||
label = translatable('Services names'),
|
|
||||||
tooltip = translatable('Base name for this user services'),
|
|
||||||
# In this case, the choice can have none value selected by default
|
|
||||||
required = True,
|
|
||||||
defvalue = '' # Default value is the ID of the choicefield
|
|
||||||
)
|
|
||||||
|
|
||||||
def initialize(self, values):
|
|
||||||
'''
|
|
||||||
We check here form values to see if they are valid.
|
|
||||||
|
|
||||||
Note that we check them throught FROM variables, that already has been
|
|
||||||
initialized by __init__ method of base class, before invoking this.
|
|
||||||
'''
|
|
||||||
|
|
||||||
# We don't need to check anything, bat because this is a sample, we do
|
|
||||||
# As in provider, we receive values only at new Service creation,
|
|
||||||
# so we only need to validate params if values is not None
|
|
||||||
if values is not None:
|
|
||||||
if self.colour.value == 'nonsense':
|
|
||||||
raise Service.ValidationException('The selected colour is invalid!!!')
|
|
||||||
|
|
||||||
|
|
||||||
# Services itself are non testeable right now, so we don't even have
|
|
||||||
# to provide one!!!
|
|
||||||
|
|
||||||
|
|
||||||
# Congratulations!!!, the needed part of your first simple service is done!
|
|
||||||
# Now you can go to administration panel, and check it
|
|
||||||
#
|
|
||||||
# From now onwards, we implement our own methods, that will be used by,
|
|
||||||
# for example, services derived from this provider
|
|
||||||
|
|
||||||
def getColour(self):
|
|
||||||
'''
|
|
||||||
Simply returns colour, for deployed user services.
|
|
||||||
|
|
||||||
Remember that choiceField.value returns the id part of the ChoiceItem
|
|
||||||
'''
|
|
||||||
return self.colour.value
|
|
||||||
|
|
||||||
def getPassw(self):
|
|
||||||
'''
|
|
||||||
Simply returns passwd, for deloyed user services
|
|
||||||
'''
|
|
||||||
return self.passw.value
|
|
||||||
|
|
||||||
def getBaseName(self):
|
|
||||||
'''
|
|
||||||
'''
|
|
||||||
return self.baseName.value
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ServiceTwo(Service):
|
|
||||||
'''
|
|
||||||
Just a second service, no comments here (almost same that ServiceOne
|
|
||||||
'''
|
|
||||||
typeName = translatable('Sample Service Two')
|
|
||||||
typeType = 'SampleService2'
|
|
||||||
typeDescription = translatable('Sample (and dummy) service ONE+ONE')
|
|
||||||
iconFile = 'provider.png' #: We reuse provider icon here :-)
|
|
||||||
|
|
||||||
# Functional related data
|
|
||||||
maxDeployed = 5
|
|
||||||
usesCache = True
|
|
||||||
cacheTooltip = translatable('L1 cache for dummy elements')
|
|
||||||
usesCache_L2 = True
|
|
||||||
cacheTooltip_L2 = translatable('L2 cache for dummy elements')
|
|
||||||
|
|
||||||
needsManager = False
|
|
||||||
mustAssignManually = False
|
|
||||||
|
|
||||||
#: Types of publications. In this case, we will include a publication
|
|
||||||
#: type for this one
|
|
||||||
#: Note that this is a MUST if you indicate that needPublication
|
|
||||||
publicationType = SamplePublication
|
|
||||||
#: Types of deploys (services in cache and/or assigned to users)
|
|
||||||
deployedType = SampleUserDeploymentTwo
|
|
||||||
|
|
||||||
|
|
||||||
# Gui, we will use here the EditableList field
|
|
||||||
names = gui.EditableList(label=translatable('List of names'))
|
|
||||||
|
|
||||||
def __init__(self, environment, parent, values = None):
|
|
||||||
'''
|
|
||||||
We here can get a HUGE list from client.
|
|
||||||
Right now, this is treated same as other fields, in a near
|
|
||||||
future we will se how to handle this better
|
|
||||||
'''
|
|
||||||
super(ServiceTwo, self).__init__(environment, parent, values)
|
|
||||||
|
|
||||||
# No checks here
|
|
||||||
|
|
||||||
def getNames(self):
|
|
||||||
'''
|
|
||||||
For using at deployed services, really nothing
|
|
||||||
'''
|
|
||||||
return self.names.value
|
|
@ -1,373 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
# are permitted provided that the following conditions are met:
|
|
||||||
#
|
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
|
||||||
# this list of conditions and the following disclaimer.
|
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
|
||||||
# and/or other materials provided with the distribution.
|
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
|
||||||
# may be used to endorse or promote products derived from this software
|
|
||||||
# without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
'''
|
|
||||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
|
||||||
'''
|
|
||||||
|
|
||||||
from uds.core.services import UserDeployment
|
|
||||||
from uds.core.util.State import State
|
|
||||||
import logging
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
class SampleUserDeploymentOne(UserDeployment):
|
|
||||||
'''
|
|
||||||
This class generates the user consumable elements of the service tree.
|
|
||||||
|
|
||||||
After creating at administration interface an Deployed Service, UDS will
|
|
||||||
create consumable services for users using UserDeployment class as
|
|
||||||
provider of this elements.
|
|
||||||
|
|
||||||
|
|
||||||
At class instantiation, this will receive an environment with"generator",
|
|
||||||
that are classes that provides a way to generate unique items.
|
|
||||||
|
|
||||||
The generators provided right now are 'mac' and 'name'. To get more info
|
|
||||||
about this, look at py:class:`uds.core.util.UniqueMacGenerator.UniqueNameGenerator`
|
|
||||||
and py:class:`uds.core.util.UniqueNameGenerator.UniqueNameGenerator`
|
|
||||||
|
|
||||||
This first sample do not uses cache. To see one with cache, see
|
|
||||||
SampleUserDeploymentTwo. The main difference are the "...Cache".." methods,
|
|
||||||
that here are not needed.
|
|
||||||
|
|
||||||
As sample also of environment storage usage, wi will use here the provider
|
|
||||||
storage to keep all our needed info, leaving marshal and unmarshal (needed
|
|
||||||
by Serializble classes, like this) empty (that is, returns '' first and does
|
|
||||||
nothing the second one)
|
|
||||||
|
|
||||||
Also Remember, if you don't include this class as the deployedType of the
|
|
||||||
SampleServiceOne, or whenever you trie to access a service of SampleServiceOne,
|
|
||||||
you will get an excetion that says that you havent included the deployedType.
|
|
||||||
'''
|
|
||||||
|
|
||||||
#: Recheck every five seconds by default (for task methods)
|
|
||||||
suggestedTime = 5
|
|
||||||
|
|
||||||
# Serializable needed methods
|
|
||||||
def marshal(self):
|
|
||||||
'''
|
|
||||||
Does nothing right here, we will use envoronment storage in this sample
|
|
||||||
'''
|
|
||||||
return ''
|
|
||||||
|
|
||||||
def unmarshal(self, str_):
|
|
||||||
'''
|
|
||||||
Does nothing here also, all data are keeped at environment storage
|
|
||||||
'''
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def getName(self):
|
|
||||||
'''
|
|
||||||
We override this to return a name to display. Default inplementation
|
|
||||||
(in base class), returns getUniqueIde() value
|
|
||||||
This name will help user to identify elements, and is only used
|
|
||||||
at administration interface.
|
|
||||||
|
|
||||||
We will use here the environment name provided generator to generate
|
|
||||||
a name for this element.
|
|
||||||
|
|
||||||
The namaGenerator need two params, the base name and a length for a
|
|
||||||
numeric incremental part for generating unique names. This are unique for
|
|
||||||
all UDS names generations, that is, UDS will not generate this name again
|
|
||||||
until this name is freed, or object is removed, what makes its environment
|
|
||||||
to also get removed, that makes all uniques ids (names and macs right now)
|
|
||||||
to also get released.
|
|
||||||
|
|
||||||
Every time get method of a generator gets called, the generator creates
|
|
||||||
a new unique name, so we keep the first generated name cached and don't
|
|
||||||
generate more names. (Generator are simple utility classes)
|
|
||||||
'''
|
|
||||||
name = self.storage().readData('name')
|
|
||||||
if name is None:
|
|
||||||
name = self.nameGenerator().get( self.service().getBaseName()
|
|
||||||
+ '-' + self.service().getColour(), 3 )
|
|
||||||
# Store value for persistence
|
|
||||||
self.storage().saveData('name', name)
|
|
||||||
|
|
||||||
return name
|
|
||||||
|
|
||||||
def setIp(self, ip):
|
|
||||||
'''
|
|
||||||
In our case, there is no OS manager associated with this, so this method
|
|
||||||
will never get called, but we put here as sample.
|
|
||||||
|
|
||||||
Whenever an os manager actor notifies the broker the state of the service
|
|
||||||
(mainly machines), the implementation of that os manager can (an probably will)
|
|
||||||
need to notify the IP of the deployed service. Remember that UDS treats with
|
|
||||||
IP services, so will probable needed in every service that you will create.
|
|
||||||
:note: This IP is the IP of the "consumed service", so the transport can
|
|
||||||
access it.
|
|
||||||
'''
|
|
||||||
self.storage().saveData('ip', str(ip))
|
|
||||||
|
|
||||||
def getUniqueId(self):
|
|
||||||
'''
|
|
||||||
Return and unique identifier for this service.
|
|
||||||
In our case, we will generate a mac name, that can be also as sample
|
|
||||||
of 'mac' generator use, and probably will get used something like this
|
|
||||||
at some services.
|
|
||||||
|
|
||||||
The get method of a mac generator takes one param, that is the mac range
|
|
||||||
to use to get an unused mac.
|
|
||||||
'''
|
|
||||||
mac = self.storage().readData('mac')
|
|
||||||
if mac is None:
|
|
||||||
mac = self.macGenerator().get( '00:00:00:00:00:00-00:FF:FF:FF:FF:FF' )
|
|
||||||
self.storage().saveData('mac', mac)
|
|
||||||
return mac
|
|
||||||
|
|
||||||
def getIp(self):
|
|
||||||
'''
|
|
||||||
We need to implement this method, so we can return the IP for transports
|
|
||||||
use. If no IP is known for this service, this must return None
|
|
||||||
|
|
||||||
If our sample do not returns an IP, IP transport will never work with
|
|
||||||
this service. Remember in real cases to return a valid IP address if
|
|
||||||
the service is accesible and you alredy know that (for example, because
|
|
||||||
the IP has been assigend via setIp by an os manager) or because
|
|
||||||
you get it for some other method.
|
|
||||||
|
|
||||||
Storage returns None if key is not stored.
|
|
||||||
|
|
||||||
:note: Keeping the IP address is responsibility of the User Deployment.
|
|
||||||
Every time the core needs to provide the service to the user, or
|
|
||||||
show the IP to the administrator, this method will get called
|
|
||||||
|
|
||||||
'''
|
|
||||||
ip = self.storage().readData('ip')
|
|
||||||
if ip is None:
|
|
||||||
ip = '192.168.0.34' # Sample IP for testing purposses only
|
|
||||||
return ip
|
|
||||||
|
|
||||||
def setReady(self):
|
|
||||||
'''
|
|
||||||
This is a task method. As that, the expected return values are
|
|
||||||
State values RUNNING, FINISHED or ERROR.
|
|
||||||
|
|
||||||
The method is invoked whenever a machine is provided to an user, right
|
|
||||||
before presenting it (via transport rendering) to the user.
|
|
||||||
|
|
||||||
This method exist for this kind of situations (i will explain it with a
|
|
||||||
sample)
|
|
||||||
|
|
||||||
Imagine a Service tree (Provider, Service, ...) for virtual machines.
|
|
||||||
This machines will get created by the UserDeployment implementation, but,
|
|
||||||
at some time, the machine can be put at in an state (suspend, shut down)
|
|
||||||
that will make the transport impossible to connect with it.
|
|
||||||
|
|
||||||
This method, in this case, will check the state of the machine, and if
|
|
||||||
it is "ready", that is, powered on and accesible, it will return
|
|
||||||
"State.FINISHED". If the machine is not accesible (has ben erased, for
|
|
||||||
example), it will return "State.ERROR" and store a reason of error so UDS
|
|
||||||
can ask for it and present this information to the Administrator.
|
|
||||||
|
|
||||||
If the machine powered off, or suspended, or any other state that is not
|
|
||||||
directly usable but can be put in an usable state, it will return
|
|
||||||
"State.RUNNING", and core will use checkState to see when the operation
|
|
||||||
has finished.
|
|
||||||
|
|
||||||
I hope this sample is enough to explain the use of this method..
|
|
||||||
'''
|
|
||||||
|
|
||||||
# In our case, the service is always ready
|
|
||||||
return State.FINISHED
|
|
||||||
|
|
||||||
def deployForUser(self, user):
|
|
||||||
'''
|
|
||||||
Deploys an service instance for an user.
|
|
||||||
|
|
||||||
This is a task method. As that, the excepted return values are
|
|
||||||
State values RUNNING, FINISHED or ERROR.
|
|
||||||
|
|
||||||
The user parameter is not realy neded, but provided. It indicates the
|
|
||||||
Database User Object (see py:mod:`uds.modules`) to which this deployed
|
|
||||||
user service will be assigned to.
|
|
||||||
|
|
||||||
This method will get called whenever a new deployed service for an user
|
|
||||||
is needed. This will give this class the oportunity to create
|
|
||||||
a service that is assigned to an user.
|
|
||||||
|
|
||||||
The way of using this method is as follows:
|
|
||||||
|
|
||||||
If the service gets created in "one step", that is, before the return
|
|
||||||
of this method, the consumable service for the user gets created, it
|
|
||||||
will return "State.FINISH".
|
|
||||||
If the service needs more steps (as in this case), we will return
|
|
||||||
"State.RUNNING", and if it has an error, it wil return "State.ERROR" and
|
|
||||||
store an error string so administration interface can show it.
|
|
||||||
|
|
||||||
We do not use user for anything, as in most cases will be.
|
|
||||||
'''
|
|
||||||
import random
|
|
||||||
|
|
||||||
self.storage().saveData('count', '0')
|
|
||||||
|
|
||||||
# random fail
|
|
||||||
if random.randint(0, 9) == 9:
|
|
||||||
self.storage().saveData('error', 'Random error at deployForUser :-)')
|
|
||||||
return State.ERROR
|
|
||||||
|
|
||||||
return State.RUNNING
|
|
||||||
|
|
||||||
|
|
||||||
def checkState(self):
|
|
||||||
'''
|
|
||||||
Our deployForUser method will initiate the consumable service deployment,
|
|
||||||
but will not finish it.
|
|
||||||
|
|
||||||
So in our sample, we will only check if a number reaches 5, and if so
|
|
||||||
return that we have finished, else we will return that we are working
|
|
||||||
on it.
|
|
||||||
|
|
||||||
One deployForUser returns State.RUNNING, this task will get called until
|
|
||||||
checkState returns State.FINISHED.
|
|
||||||
|
|
||||||
Also, we will make the publication fail one of every 10 calls to this
|
|
||||||
method.
|
|
||||||
|
|
||||||
Note: Destroying, canceling and deploying for cache also makes use of
|
|
||||||
this method, so you must keep the info of that you are checking if you
|
|
||||||
need it.
|
|
||||||
In our case, destroy is 1-step action so this will no get called while
|
|
||||||
destroying, and cancel will simply invoke destroy
|
|
||||||
'''
|
|
||||||
import random
|
|
||||||
|
|
||||||
count = int(self.storage().readData('count')) + 1
|
|
||||||
# Count is always a valid value, because this method will never get
|
|
||||||
# called before deployForUser, deployForCache, destroy or cancel.
|
|
||||||
# In our sample, we only use checkState in case of deployForUser,
|
|
||||||
# so at first call count will be 0.
|
|
||||||
if count >= 5:
|
|
||||||
return State.FINISHED
|
|
||||||
|
|
||||||
# random fail
|
|
||||||
if random.randint(0, 9) == 9:
|
|
||||||
self.storage().saveData('error', 'Random error at checkState :-)')
|
|
||||||
return State.ERROR
|
|
||||||
|
|
||||||
self.storage().saveData('count', str(count))
|
|
||||||
return State.RUNNING
|
|
||||||
|
|
||||||
def finish(self):
|
|
||||||
'''
|
|
||||||
Invoked when the core notices that the deployment of a service has finished.
|
|
||||||
(No matter wether it is for cache or for an user)
|
|
||||||
|
|
||||||
This gives the oportunity to make something at that moment.
|
|
||||||
:note: You can also make these operations at checkState, this is really
|
|
||||||
not needed, but can be provided (default implementation of base class does
|
|
||||||
nothing)
|
|
||||||
'''
|
|
||||||
# Note that this is not really needed, is just a sample of storage use
|
|
||||||
self.storage().remove('count')
|
|
||||||
|
|
||||||
def assignToUser(self, user):
|
|
||||||
'''
|
|
||||||
This method is invoked whenever a cache item gets assigned to an user.
|
|
||||||
This gives the User Deployment an oportunity to do whatever actions
|
|
||||||
are required so the service puts at a correct state for using by a service.
|
|
||||||
|
|
||||||
In our sample, the service is always ready, so this does nothing.
|
|
||||||
|
|
||||||
This is not a task method. All level 1 cache items can be diretly
|
|
||||||
assigned to an user with no more work needed, but, if something is needed,
|
|
||||||
here you can do whatever you need
|
|
||||||
'''
|
|
||||||
pass
|
|
||||||
|
|
||||||
def userLoggedIn(self, user):
|
|
||||||
'''
|
|
||||||
This method must be available so os managers can invoke it whenever
|
|
||||||
an user get logged into a service.
|
|
||||||
|
|
||||||
Default implementation does nothing, so if you are going to do nothing,
|
|
||||||
you don't need to implement it.
|
|
||||||
|
|
||||||
The responability of notifying it is of os manager actor, and it's
|
|
||||||
directly invoked by os managers (right now, linux os manager and windows
|
|
||||||
os manager)
|
|
||||||
|
|
||||||
The user provided is just an string, that is provided by actor.
|
|
||||||
'''
|
|
||||||
# We store the value at storage, but never get used, just an example
|
|
||||||
self.storage().saveData('user', user)
|
|
||||||
|
|
||||||
def userLoggedOut(self, user):
|
|
||||||
'''
|
|
||||||
This method must be available so os managers can invoke it whenever
|
|
||||||
an user get logged out if a service.
|
|
||||||
|
|
||||||
Default implementation does nothing, so if you are going to do nothing,
|
|
||||||
you don't need to implement it.
|
|
||||||
|
|
||||||
The responability of notifying it is of os manager actor, and it's
|
|
||||||
directly invoked by os managers (right now, linux os manager and windows
|
|
||||||
os manager)
|
|
||||||
|
|
||||||
The user provided is just an string, that is provided by actor.
|
|
||||||
'''
|
|
||||||
# We do nothing more that remove the user
|
|
||||||
self.storage().remove('user')
|
|
||||||
|
|
||||||
def reasonOfError(self):
|
|
||||||
'''
|
|
||||||
Returns the reason of the error.
|
|
||||||
|
|
||||||
Remember that the class is responsible of returning this whenever asked
|
|
||||||
for it, and it will be asked everytime it's needed to be shown to the
|
|
||||||
user (when the administation asks for it).
|
|
||||||
'''
|
|
||||||
return self.storage().readData('error') or 'No error'
|
|
||||||
|
|
||||||
def destroy(self):
|
|
||||||
'''
|
|
||||||
This is a task method. As that, the excepted return values are
|
|
||||||
State values RUNNING, FINISHED or ERROR.
|
|
||||||
|
|
||||||
Invoked for destroying a deployed service
|
|
||||||
Do whatever needed here, as deleting associated data if needed (i.e. a copy of the machine, snapshots, etc...)
|
|
||||||
@return: State.FINISHED if no more checks/steps for deployment are needed, State.RUNNING if more steps are needed (steps checked using checkState)
|
|
||||||
'''
|
|
||||||
return State.FINISHED
|
|
||||||
|
|
||||||
def cancel(self):
|
|
||||||
'''
|
|
||||||
This is a task method. As that, the excepted return values are
|
|
||||||
State values RUNNING, FINISHED or ERROR.
|
|
||||||
|
|
||||||
This can be invoked directly by an administration or by the clean up
|
|
||||||
of the deployed service (indirectly).
|
|
||||||
When administrator requests it, the cancel is "delayed" and not
|
|
||||||
invoked directly.
|
|
||||||
'''
|
|
||||||
return State.FINISHED
|
|
||||||
|
|
@ -1,469 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
# are permitted provided that the following conditions are met:
|
|
||||||
#
|
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
|
||||||
# this list of conditions and the following disclaimer.
|
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
|
||||||
# and/or other materials provided with the distribution.
|
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
|
||||||
# may be used to endorse or promote products derived from this software
|
|
||||||
# without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
'''
|
|
||||||
.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com
|
|
||||||
'''
|
|
||||||
|
|
||||||
from uds.core.services import UserDeployment
|
|
||||||
from uds.core.util.State import State
|
|
||||||
import logging
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
class SampleUserDeploymentTwo(UserDeployment):
|
|
||||||
'''
|
|
||||||
This class generates the user consumable elements of the service tree.
|
|
||||||
|
|
||||||
This is almost the same as SampleUserDeploymentOne, but differs that this one
|
|
||||||
uses the publication to get data from it, in a very basic way.
|
|
||||||
|
|
||||||
After creating at administration interface an Deployed Service, UDS will
|
|
||||||
create consumable services for users using UserDeployment class as
|
|
||||||
provider of this elements.
|
|
||||||
|
|
||||||
At class instantiation, this will receive an environment with"generator",
|
|
||||||
that are classes that provides a way to generate unique items.
|
|
||||||
|
|
||||||
The generators provided right now are 'mac' and 'name'. To get more info
|
|
||||||
about this, look at py:class:`uds.core.util.UniqueMacGenerator.UniqueNameGenerator`
|
|
||||||
and py:class:`uds.core.util.UniqueNameGenerator.UniqueNameGenerator`
|
|
||||||
|
|
||||||
As sample also of environment storage usage, wi will use here the provider
|
|
||||||
storage to keep all our needed info, leaving marshal and unmarshal (needed
|
|
||||||
by Serializable classes, like this) empty (that is, returns '' first and does
|
|
||||||
nothing the second one)
|
|
||||||
|
|
||||||
Also Remember, if you don't include this class as the deployedType of the
|
|
||||||
SampleServiceTwo, or whenever you try to access a service of SampleServiceTwo,
|
|
||||||
you will get an exception that says that you haven't included the deployedType.
|
|
||||||
'''
|
|
||||||
|
|
||||||
#: Recheck every five seconds by default (for task methods)
|
|
||||||
suggestedTime = 2
|
|
||||||
|
|
||||||
def initialize(self):
|
|
||||||
'''
|
|
||||||
Initialize default attributes values here. We can do whatever we like,
|
|
||||||
but for this sample this is just right...
|
|
||||||
'''
|
|
||||||
self._name = ''
|
|
||||||
self._ip = ''
|
|
||||||
self._mac = ''
|
|
||||||
self._error = ''
|
|
||||||
self._count = 0
|
|
||||||
|
|
||||||
# Serializable needed methods
|
|
||||||
def marshal(self):
|
|
||||||
'''
|
|
||||||
Marshal own data, in this sample we will marshal internal needed
|
|
||||||
attributes.
|
|
||||||
|
|
||||||
In this case, the data will be store with the database record. To
|
|
||||||
minimize database storage usage, we will "zip" data before returning it.
|
|
||||||
Anyway, we should keep this data as low as possible, we also have an
|
|
||||||
storage for loading larger data.
|
|
||||||
|
|
||||||
:note: It's a good idea when providing marshalers, to store a 'version'
|
|
||||||
beside the values, so we can, at a later stage, treat with old
|
|
||||||
data for current modules.
|
|
||||||
'''
|
|
||||||
data = '\t'.join(['v1', self._name, self._ip, self._mac, self._error,
|
|
||||||
str(self._count)])
|
|
||||||
return data.encode('zip')
|
|
||||||
|
|
||||||
def unmarshal(self, str_):
|
|
||||||
'''
|
|
||||||
We unmarshal the content.
|
|
||||||
'''
|
|
||||||
data = str_.decode('zip').split('\t')
|
|
||||||
# Data Version check
|
|
||||||
# If we include some new data at some point in a future, we can
|
|
||||||
# add "default" values at v1 check, and load new values at 'v2' check.
|
|
||||||
if data[0] == 'v1':
|
|
||||||
self._name, self._ip, self._mac, self._error, count = data[1:]
|
|
||||||
self._count = int(count)
|
|
||||||
|
|
||||||
def getName(self):
|
|
||||||
'''
|
|
||||||
We override this to return a name to display. Default implementation
|
|
||||||
(in base class), returns getUniqueIde() value
|
|
||||||
This name will help user to identify elements, and is only used
|
|
||||||
at administration interface.
|
|
||||||
|
|
||||||
We will use here the environment name provided generator to generate
|
|
||||||
a name for this element.
|
|
||||||
|
|
||||||
The namaGenerator need two params, the base name and a length for a
|
|
||||||
numeric incremental part for generating unique names. This are unique for
|
|
||||||
all UDS names generations, that is, UDS will not generate this name again
|
|
||||||
until this name is freed, or object is removed, what makes its environment
|
|
||||||
to also get removed, that makes all unique ids (names and macs right now)
|
|
||||||
to also get released.
|
|
||||||
|
|
||||||
Every time get method of a generator gets called, the generator creates
|
|
||||||
a new unique name, so we keep the first generated name cached and don't
|
|
||||||
generate more names. (Generator are simple utility classes)
|
|
||||||
'''
|
|
||||||
if self._name == '':
|
|
||||||
self._name = self.nameGenerator().get( self.publication().getBaseName(),
|
|
||||||
3 )
|
|
||||||
# self._name will be stored when object is marshaled
|
|
||||||
return self._name
|
|
||||||
|
|
||||||
def setIp(self, ip):
|
|
||||||
'''
|
|
||||||
In our case, there is no OS manager associated with this, so this method
|
|
||||||
will never get called, but we put here as sample.
|
|
||||||
|
|
||||||
Whenever an os manager actor notifies the broker the state of the service
|
|
||||||
(mainly machines), the implementation of that os manager can (an probably will)
|
|
||||||
need to notify the IP of the deployed service. Remember that UDS treats with
|
|
||||||
IP services, so will probable needed in every service that you will create.
|
|
||||||
:note: This IP is the IP of the "consumed service", so the transport can
|
|
||||||
access it.
|
|
||||||
'''
|
|
||||||
self._ip = ip
|
|
||||||
|
|
||||||
def getUniqueId(self):
|
|
||||||
'''
|
|
||||||
Return and unique identifier for this service.
|
|
||||||
In our case, we will generate a mac name, that can be also as sample
|
|
||||||
of 'mac' generator use, and probably will get used something like this
|
|
||||||
at some services.
|
|
||||||
|
|
||||||
The get method of a mac generator takes one param, that is the mac range
|
|
||||||
to use to get an unused mac.
|
|
||||||
|
|
||||||
The mac generated is not used by anyone, it will not depend on
|
|
||||||
the range, the generator will take care that this mac is unique
|
|
||||||
and in the range provided, or it will return None. The ranges
|
|
||||||
are wide enough to ensure that we always will get a mac address
|
|
||||||
in this case, but if this is not your case, take into account that
|
|
||||||
None is a possible return value, and in that case, you should return an
|
|
||||||
invalid id right now. Every time a task method is invoked, the core
|
|
||||||
will try to update the value of the unique id using this method, so
|
|
||||||
that id can change with time. (In fact, it's not unique at database level,
|
|
||||||
it's unique in the sense that you must return an unique id that can, for
|
|
||||||
example, be used by os managers to identify this element).
|
|
||||||
|
|
||||||
:note: Normally, getting out of macs in the mac pool is a bad thing... :-)
|
|
||||||
'''
|
|
||||||
if self._mac == '':
|
|
||||||
self._mac = self.macGenerator().get( '00:00:00:00:00:00-00:FF:FF:FF:FF:FF' )
|
|
||||||
return self._mac
|
|
||||||
|
|
||||||
def getIp(self):
|
|
||||||
'''
|
|
||||||
We need to implement this method, so we can return the IP for transports
|
|
||||||
use. If no IP is known for this service, this must return None
|
|
||||||
|
|
||||||
If our sample do not returns an IP, IP transport will never work with
|
|
||||||
this service. Remember in real cases to return a valid IP address if
|
|
||||||
the service is accesible and you alredy know that (for example, because
|
|
||||||
the IP has been assigend via setIp by an os manager) or because
|
|
||||||
you get it for some other method.
|
|
||||||
|
|
||||||
Storage returns None if key is not stored.
|
|
||||||
|
|
||||||
:note: Keeping the IP address is responsibility of the User Deployment.
|
|
||||||
Every time the core needs to provide the service to the user, or
|
|
||||||
show the IP to the administrator, this method will get called
|
|
||||||
|
|
||||||
'''
|
|
||||||
if self._ip == '':
|
|
||||||
return '192.168.0.34' # Sample IP for testing purposes only
|
|
||||||
return self._ip
|
|
||||||
|
|
||||||
def setReady(self):
|
|
||||||
'''
|
|
||||||
This is a task method. As that, the excepted return values are
|
|
||||||
State values RUNNING, FINISHED or ERROR.
|
|
||||||
|
|
||||||
The method is invoked whenever a machine is provided to an user, right
|
|
||||||
before presenting it (via transport rendering) to the user.
|
|
||||||
|
|
||||||
This method exist for this kind of situations (i will explain it with a
|
|
||||||
sample)
|
|
||||||
|
|
||||||
Imagine a Service tree (Provider, Service, ...) for virtual machines.
|
|
||||||
This machines will get created by the UserDeployment implementation, but,
|
|
||||||
at some time, the machine can be put at in an state (suspend, shut down)
|
|
||||||
that will make the transport impossible to connect with it.
|
|
||||||
|
|
||||||
This method, in this case, will check the state of the machine, and if
|
|
||||||
it is "ready", that is, powered on and accessible, it will return
|
|
||||||
"State.FINISHED". If the machine is not accessible (has been erased, for
|
|
||||||
example), it will return "State.ERROR" and store a reason of error so UDS
|
|
||||||
can ask for it and present this information to the Administrator.
|
|
||||||
|
|
||||||
If the machine powered off, or suspended, or any other state that is not
|
|
||||||
directly usable but can be put in an usable state, it will return
|
|
||||||
"State.RUNNING", and core will use checkState to see when the operation
|
|
||||||
has finished.
|
|
||||||
|
|
||||||
I hope this sample is enough to explain the use of this method..
|
|
||||||
'''
|
|
||||||
|
|
||||||
# In our case, the service is always ready
|
|
||||||
return State.FINISHED
|
|
||||||
|
|
||||||
def deployForUser(self, user):
|
|
||||||
'''
|
|
||||||
Deploys an service instance for an user.
|
|
||||||
|
|
||||||
This is a task method. As that, the excepted return values are
|
|
||||||
State values RUNNING, FINISHED or ERROR.
|
|
||||||
|
|
||||||
The user parameter is not realy neded, but provided. It indicates the
|
|
||||||
Database User Object (see py:mod:`uds.modules`) to which this deployed
|
|
||||||
user service will be assigned to.
|
|
||||||
|
|
||||||
This method will get called whenever a new deployed service for an user
|
|
||||||
is needed. This will give this class the oportunity to create
|
|
||||||
a service that is assigned to an user.
|
|
||||||
|
|
||||||
The way of using this method is as follows:
|
|
||||||
|
|
||||||
If the service gets created in "one step", that is, before the return
|
|
||||||
of this method, the consumable service for the user gets created, it
|
|
||||||
will return "State.FINISH".
|
|
||||||
If the service needs more steps (as in this case), we will return
|
|
||||||
"State.RUNNING", and if it has an error, it wil return "State.ERROR" and
|
|
||||||
store an error string so administration interface can show it.
|
|
||||||
|
|
||||||
We do not use user for anything, as in most cases will be.
|
|
||||||
'''
|
|
||||||
import random
|
|
||||||
|
|
||||||
self._count = 0
|
|
||||||
|
|
||||||
# random fail
|
|
||||||
if random.randint(0, 9) == 9:
|
|
||||||
# Note that we can mark this string as translatable, and return
|
|
||||||
# it translated at reasonOfError method
|
|
||||||
self._error = 'Random error at deployForUser :-)'
|
|
||||||
return State.ERROR
|
|
||||||
|
|
||||||
return State.RUNNING
|
|
||||||
|
|
||||||
def deployForCache(self, cacheLevel):
|
|
||||||
'''
|
|
||||||
Deploys a user deployment as cache.
|
|
||||||
|
|
||||||
This is a task method. As that, the expected return values are
|
|
||||||
State values RUNNING, FINISHED or ERROR.
|
|
||||||
|
|
||||||
In our sample, this will do exactly the same as deploy for user,
|
|
||||||
except that it will never will give an error.
|
|
||||||
|
|
||||||
See deployForUser for a description of what this method should do.
|
|
||||||
|
|
||||||
:note: deployForCache is invoked whenever a new cache element is needed
|
|
||||||
for an specific user deployment. It will also indicate for what
|
|
||||||
cache level (L1, L2) is the deployment
|
|
||||||
'''
|
|
||||||
self._count = 0
|
|
||||||
return State.RUNNING
|
|
||||||
|
|
||||||
def moveToCache(self, newLevel):
|
|
||||||
'''
|
|
||||||
This method is invoked whenever the core needs to move from the current
|
|
||||||
cache level to a new cache level an user deployment.
|
|
||||||
|
|
||||||
This is a task method. As that, the expected return values are
|
|
||||||
State values RUNNING, FINISHED or ERROR.
|
|
||||||
|
|
||||||
We only provide newLevel, because there is only two cache levels, so if
|
|
||||||
newLevel is L1, the actual is L2, and if it is L2, the actual is L1.
|
|
||||||
|
|
||||||
Actually there is no possibility to move assigned services again back to
|
|
||||||
cache. If some service needs that kind of functionallity, this must be
|
|
||||||
provided at service level (for example, when doing publishing creating
|
|
||||||
a number of services that will be used, released and reused by users).
|
|
||||||
|
|
||||||
Also, user deployments that are at cache level 2 will never get directly
|
|
||||||
assigned to user. First, it will pass to L1 and then it will get assigned.
|
|
||||||
|
|
||||||
A good sample of a real implementation of this is moving a virtual machine
|
|
||||||
from a "suspended" state to "running" state to assign it to an user.
|
|
||||||
|
|
||||||
In this sample, there is L2 cache also, but moving from L1 to L2 and
|
|
||||||
from L2 to L1 is doing really nothing, so this method will do nothing.
|
|
||||||
|
|
||||||
In a real scenario, we will, for example, suspend or resume virtual machine
|
|
||||||
and, return State.RUNNING and at checkState check if this task is completed.
|
|
||||||
'''
|
|
||||||
pass
|
|
||||||
|
|
||||||
def checkState(self):
|
|
||||||
'''
|
|
||||||
Our deployForUser method will initiate the consumable service deployment,
|
|
||||||
but will not finish it.
|
|
||||||
|
|
||||||
So in our sample, we will only check if a number reaches 5, and if so
|
|
||||||
return that we have finished, else we will return that we are working
|
|
||||||
on it.
|
|
||||||
|
|
||||||
One deployForUser returns State.RUNNING, this task will get called until
|
|
||||||
checkState returns State.FINISHED.
|
|
||||||
|
|
||||||
Also, we will make the user deployment fail one of every 10 calls to this
|
|
||||||
method.
|
|
||||||
|
|
||||||
Note: Destroying, canceling and deploying for cache also makes use of
|
|
||||||
this method, so you must keep the info of that you are checking if you
|
|
||||||
need it.
|
|
||||||
|
|
||||||
In our case, destroy is 1-step action so this will no get called while
|
|
||||||
destroying, and cancel will simply invoke destroy. Cache deployment is
|
|
||||||
exactly as user deployment, except that the core will not assign it to
|
|
||||||
anyone, and cache moving operations is
|
|
||||||
'''
|
|
||||||
import random
|
|
||||||
|
|
||||||
self._count += 1
|
|
||||||
# Count is always a valid value, because this method will never get
|
|
||||||
# called before deployForUser, deployForCache, destroy or cancel.
|
|
||||||
# In our sample, we only use checkState in case of deployForUser,
|
|
||||||
# so at first call count will be 0.
|
|
||||||
if self._count >= 5:
|
|
||||||
return State.FINISHED
|
|
||||||
|
|
||||||
# random fail
|
|
||||||
if random.randint(0, 9) == 9:
|
|
||||||
self._error = 'Random error at checkState :-)'
|
|
||||||
return State.ERROR
|
|
||||||
|
|
||||||
return State.RUNNING
|
|
||||||
|
|
||||||
def finish(self):
|
|
||||||
'''
|
|
||||||
Invoked when the core notices that the deployment of a service has finished.
|
|
||||||
(No matter whether it is for cache or for an user)
|
|
||||||
|
|
||||||
This gives the opportunity to make something at that moment.
|
|
||||||
|
|
||||||
:note: You can also make these operations at checkState, this is really
|
|
||||||
not needed, but can be provided (default implementation of base class does
|
|
||||||
nothing)
|
|
||||||
'''
|
|
||||||
# We set count to 0, not needed but for sample purposes
|
|
||||||
self._count = 0
|
|
||||||
|
|
||||||
def assignToUser(self, user):
|
|
||||||
'''
|
|
||||||
This method is invoked whenever a cache item gets assigned to an user.
|
|
||||||
This is not a task method right now, simply a notification. This means
|
|
||||||
that L1 cache items must be directly usable (except for the readyness part)
|
|
||||||
by users in a single step operation.
|
|
||||||
|
|
||||||
Note that there will be an setReady call before letting the user consume
|
|
||||||
this user deployment, so this is more informational (so, if you keep at
|
|
||||||
what cache level is this instance, you can update it) than anything else.
|
|
||||||
|
|
||||||
This is not a task method. All level 1 cache items can be dircetly
|
|
||||||
assigned to an user with no more work needed, but, if something is needed,
|
|
||||||
here you can do whatever you need.
|
|
||||||
|
|
||||||
user is a Database user object.
|
|
||||||
'''
|
|
||||||
logger.debug('Assigned to user {0}'.format(user))
|
|
||||||
|
|
||||||
def userLoggedIn(self, user):
|
|
||||||
'''
|
|
||||||
This method must be available so os managers can invoke it whenever
|
|
||||||
an user get logged into a service.
|
|
||||||
|
|
||||||
Default implementation does nothing, so if you are going to do nothing,
|
|
||||||
you don't need to implement it.
|
|
||||||
|
|
||||||
The responsibility of notifying it is of os manager actor, and it's
|
|
||||||
directly invoked by os managers (right now, linux os manager and windows
|
|
||||||
os manager)
|
|
||||||
|
|
||||||
The user provided is just an string, that is provided by actors.
|
|
||||||
'''
|
|
||||||
# We store the value at storage, but never get used, just an example
|
|
||||||
self.storage().saveData('user', user)
|
|
||||||
|
|
||||||
def userLoggedOut(self, user):
|
|
||||||
'''
|
|
||||||
This method must be available so os managers can invoke it whenever
|
|
||||||
an user get logged out if a service.
|
|
||||||
|
|
||||||
Default implementation does nothing, so if you are going to do nothing,
|
|
||||||
you don't need to implement it.
|
|
||||||
|
|
||||||
The responability of notifying it is of os manager actor, and it's
|
|
||||||
directly invoked by os managers (right now, linux os manager and windows
|
|
||||||
os manager)
|
|
||||||
|
|
||||||
The user provided is just an string, that is provided by actor.
|
|
||||||
'''
|
|
||||||
# We do nothing more that remove the user
|
|
||||||
self.storage().remove('user')
|
|
||||||
|
|
||||||
def reasonOfError(self):
|
|
||||||
'''
|
|
||||||
Returns the reason of the error.
|
|
||||||
|
|
||||||
Remember that the class is responsible of returning this whenever asked
|
|
||||||
for it, and it will be asked everytime it's needed to be shown to the
|
|
||||||
user (when the administation asks for it).
|
|
||||||
|
|
||||||
:note: Remember that you can use ugettext to translate this error to
|
|
||||||
user language whenever it is possible. (This one will get invoked
|
|
||||||
directly from admin interface and, as so, will have translation
|
|
||||||
environment correctly set up.
|
|
||||||
'''
|
|
||||||
return self._error
|
|
||||||
|
|
||||||
def destroy(self):
|
|
||||||
'''
|
|
||||||
This is a task method. As that, the excepted return values are
|
|
||||||
State values RUNNING, FINISHED or ERROR.
|
|
||||||
|
|
||||||
Invoked for destroying a deployed service
|
|
||||||
Do whatever needed here, as deleting associated data if needed (i.e. a copy of the machine, snapshots, etc...)
|
|
||||||
@return: State.FINISHED if no more checks/steps for deployment are needed, State.RUNNING if more steps are needed (steps checked using checkState)
|
|
||||||
'''
|
|
||||||
return State.FINISHED
|
|
||||||
|
|
||||||
def cancel(self):
|
|
||||||
'''
|
|
||||||
This is a task method. As that, the excepted return values are
|
|
||||||
State values RUNNING, FINISHED or ERROR.
|
|
||||||
|
|
||||||
This can be invoked directly by an administration or by the clean up
|
|
||||||
of the deployed service (indirectly).
|
|
||||||
When administrator requests it, the cancel is "delayed" and not
|
|
||||||
invoked directly.
|
|
||||||
'''
|
|
||||||
return State.FINISHED
|
|
@ -1,44 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
#
|
|
||||||
# Copyright (c) 2012 Virtual Cable S.L.
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
# Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
# are permitted provided that the following conditions are met:
|
|
||||||
#
|
|
||||||
# * Redistributions of source code must retain the above copyright notice,
|
|
||||||
# this list of conditions and the following disclaimer.
|
|
||||||
# * Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
# this list of conditions and the following disclaimer in the documentation
|
|
||||||
# and/or other materials provided with the distribution.
|
|
||||||
# * Neither the name of Virtual Cable S.L. nor the names of its contributors
|
|
||||||
# may be used to endorse or promote products derived from this software
|
|
||||||
# without specific prior written permission.
|
|
||||||
#
|
|
||||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
'''
|
|
||||||
Sample Service module.
|
|
||||||
|
|
||||||
This package simply shows how a new service can be implemented.
|
|
||||||
|
|
||||||
|
|
||||||
The first thing to do in every package that is a module is register the
|
|
||||||
class that is responsible of providing the module with the system.
|
|
||||||
|
|
||||||
For this, we must simply import the class at __init__, UDS will take care
|
|
||||||
of the rest
|
|
||||||
'''
|
|
||||||
|
|
||||||
from SampleProvider import Provider
|
|
||||||
|
|
@ -1,96 +0,0 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
|
||||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
||||||
|
|
||||||
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
||||||
|
|
||||||
<title>Overview: module code — UDS 1.0 documentation</title>
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../_static/sphinxdoc.css" type="text/css" />
|
|
||||||
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
var DOCUMENTATION_OPTIONS = {
|
|
||||||
URL_ROOT: '../',
|
|
||||||
VERSION: '1.0',
|
|
||||||
COLLAPSE_INDEX: false,
|
|
||||||
FILE_SUFFIX: '.html',
|
|
||||||
HAS_SOURCE: true
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<script type="text/javascript" src="../_static/jquery.js"></script>
|
|
||||||
<script type="text/javascript" src="../_static/underscore.js"></script>
|
|
||||||
<script type="text/javascript" src="../_static/doctools.js"></script>
|
|
||||||
<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
|
||||||
<link rel="top" title="UDS 1.0 documentation" href="../index.html" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="related">
|
|
||||||
<h3>Navigation</h3>
|
|
||||||
<ul>
|
|
||||||
<li class="right" style="margin-right: 10px">
|
|
||||||
<a href="../genindex.html" title="General Index"
|
|
||||||
accesskey="I">index</a></li>
|
|
||||||
<li class="right" >
|
|
||||||
<a href="../py-modindex.html" title="Python Module Index"
|
|
||||||
>modules</a> |</li>
|
|
||||||
<li><a href="../index.html">UDS 1.0 documentation</a> »</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="sphinxsidebar">
|
|
||||||
<div class="sphinxsidebarwrapper">
|
|
||||||
<div id="searchbox" style="display: none">
|
|
||||||
<h3>Quick search</h3>
|
|
||||||
<form class="search" action="../search.html" method="get">
|
|
||||||
<input type="text" name="q" />
|
|
||||||
<input type="submit" value="Go" />
|
|
||||||
<input type="hidden" name="check_keywords" value="yes" />
|
|
||||||
<input type="hidden" name="area" value="default" />
|
|
||||||
</form>
|
|
||||||
<p class="searchtip" style="font-size: 90%">
|
|
||||||
Enter search terms or a module, class or function name.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="document">
|
|
||||||
<div class="documentwrapper">
|
|
||||||
<div class="bodywrapper">
|
|
||||||
<div class="body">
|
|
||||||
|
|
||||||
<h1>All modules for which code is available</h1>
|
|
||||||
<ul><li><a href="uds/core.html">uds.core</a></li>
|
|
||||||
<ul><li><a href="uds/core/auths.html">uds.core.auths</a></li>
|
|
||||||
<li><a href="uds/core/services.html">uds.core.services</a></li>
|
|
||||||
<ul><li><a href="uds/core/services/Exceptions.html">uds.core.services.Exceptions</a></li>
|
|
||||||
</ul><li><a href="uds/core/ui/UserInterface.html">uds.core.ui.UserInterface</a></li>
|
|
||||||
</ul><li><a href="uds/models.html">uds.models</a></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="clearer"></div>
|
|
||||||
</div>
|
|
||||||
<div class="related">
|
|
||||||
<h3>Navigation</h3>
|
|
||||||
<ul>
|
|
||||||
<li class="right" style="margin-right: 10px">
|
|
||||||
<a href="../genindex.html" title="General Index"
|
|
||||||
>index</a></li>
|
|
||||||
<li class="right" >
|
|
||||||
<a href="../py-modindex.html" title="Python Module Index"
|
|
||||||
>modules</a> |</li>
|
|
||||||
<li><a href="../index.html">UDS 1.0 documentation</a> »</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="footer">
|
|
||||||
© Copyright 2012, Virtual Cable S.L.U..
|
|
||||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.2.2.
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,136 +0,0 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
|
||||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
||||||
|
|
||||||
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
||||||
|
|
||||||
<title>uds.core — UDS 1.0 documentation</title>
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../../_static/sphinxdoc.css" type="text/css" />
|
|
||||||
<link rel="stylesheet" href="../../_static/pygments.css" type="text/css" />
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
var DOCUMENTATION_OPTIONS = {
|
|
||||||
URL_ROOT: '../../',
|
|
||||||
VERSION: '1.0',
|
|
||||||
COLLAPSE_INDEX: false,
|
|
||||||
FILE_SUFFIX: '.html',
|
|
||||||
HAS_SOURCE: true
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<script type="text/javascript" src="../../_static/jquery.js"></script>
|
|
||||||
<script type="text/javascript" src="../../_static/underscore.js"></script>
|
|
||||||
<script type="text/javascript" src="../../_static/doctools.js"></script>
|
|
||||||
<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
|
||||||
<link rel="top" title="UDS 1.0 documentation" href="../../index.html" />
|
|
||||||
<link rel="up" title="Module code" href="../index.html" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="related">
|
|
||||||
<h3>Navigation</h3>
|
|
||||||
<ul>
|
|
||||||
<li class="right" style="margin-right: 10px">
|
|
||||||
<a href="../../genindex.html" title="General Index"
|
|
||||||
accesskey="I">index</a></li>
|
|
||||||
<li class="right" >
|
|
||||||
<a href="../../py-modindex.html" title="Python Module Index"
|
|
||||||
>modules</a> |</li>
|
|
||||||
<li><a href="../../index.html">UDS 1.0 documentation</a> »</li>
|
|
||||||
<li><a href="../index.html" accesskey="U">Module code</a> »</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="sphinxsidebar">
|
|
||||||
<div class="sphinxsidebarwrapper">
|
|
||||||
<div id="searchbox" style="display: none">
|
|
||||||
<h3>Quick search</h3>
|
|
||||||
<form class="search" action="../../search.html" method="get">
|
|
||||||
<input type="text" name="q" />
|
|
||||||
<input type="submit" value="Go" />
|
|
||||||
<input type="hidden" name="check_keywords" value="yes" />
|
|
||||||
<input type="hidden" name="area" value="default" />
|
|
||||||
</form>
|
|
||||||
<p class="searchtip" style="font-size: 90%">
|
|
||||||
Enter search terms or a module, class or function name.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="document">
|
|
||||||
<div class="documentwrapper">
|
|
||||||
<div class="bodywrapper">
|
|
||||||
<div class="body">
|
|
||||||
|
|
||||||
<h1>Source code for uds.core</h1><div class="highlight"><pre>
|
|
||||||
<span class="c"># -*- coding: utf-8 -*-</span>
|
|
||||||
|
|
||||||
<span class="c">#</span>
|
|
||||||
<span class="c"># Copyright (c) 2012 Virtual Cable S.L.</span>
|
|
||||||
<span class="c"># All rights reserved.</span>
|
|
||||||
<span class="c">#</span>
|
|
||||||
<span class="c"># Redistribution and use in source and binary forms, with or without modification,</span>
|
|
||||||
<span class="c"># are permitted provided that the following conditions are met:</span>
|
|
||||||
<span class="c">#</span>
|
|
||||||
<span class="c"># * Redistributions of source code must retain the above copyright notice,</span>
|
|
||||||
<span class="c"># this list of conditions and the following disclaimer.</span>
|
|
||||||
<span class="c"># * Redistributions in binary form must reproduce the above copyright notice,</span>
|
|
||||||
<span class="c"># this list of conditions and the following disclaimer in the documentation</span>
|
|
||||||
<span class="c"># and/or other materials provided with the distribution.</span>
|
|
||||||
<span class="c"># * Neither the name of Virtual Cable S.L. nor the names of its contributors</span>
|
|
||||||
<span class="c"># may be used to endorse or promote products derived from this software</span>
|
|
||||||
<span class="c"># without specific prior written permission.</span>
|
|
||||||
<span class="c">#</span>
|
|
||||||
<span class="c"># THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"</span>
|
|
||||||
<span class="c"># AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE</span>
|
|
||||||
<span class="c"># IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE</span>
|
|
||||||
<span class="c"># DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE</span>
|
|
||||||
<span class="c"># FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL</span>
|
|
||||||
<span class="c"># DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR</span>
|
|
||||||
<span class="c"># SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER</span>
|
|
||||||
<span class="c"># CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,</span>
|
|
||||||
<span class="c"># OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE</span>
|
|
||||||
<span class="c"># OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</span>
|
|
||||||
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd">Core of UDS.</span>
|
|
||||||
<span class="sd">This package contains all core-related code for UDS</span>
|
|
||||||
<span class="sd">@author: Adolfo Gómez, dkmaster at dkmon dot com</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">unicode_literals</span>
|
|
||||||
|
|
||||||
<span class="c"># Core needs tasks manager to register scheduled jobs, so we ensure of that here</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">Environment</span> <span class="kn">import</span> <span class="n">Environmentable</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">Serializable</span> <span class="kn">import</span> <span class="n">Serializable</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">BaseModule</span> <span class="kn">import</span> <span class="n">Module</span>
|
|
||||||
<span class="kn">import</span> <span class="nn">services</span>
|
|
||||||
<span class="kn">import</span> <span class="nn">auths</span>
|
|
||||||
<span class="kn">import</span> <span class="nn">transports</span>
|
|
||||||
</pre></div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="clearer"></div>
|
|
||||||
</div>
|
|
||||||
<div class="related">
|
|
||||||
<h3>Navigation</h3>
|
|
||||||
<ul>
|
|
||||||
<li class="right" style="margin-right: 10px">
|
|
||||||
<a href="../../genindex.html" title="General Index"
|
|
||||||
>index</a></li>
|
|
||||||
<li class="right" >
|
|
||||||
<a href="../../py-modindex.html" title="Python Module Index"
|
|
||||||
>modules</a> |</li>
|
|
||||||
<li><a href="../../index.html">UDS 1.0 documentation</a> »</li>
|
|
||||||
<li><a href="../index.html" >Module code</a> »</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="footer">
|
|
||||||
© Copyright 2012, Virtual Cable S.L.U..
|
|
||||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.2.2.
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,146 +0,0 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
|
||||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
||||||
|
|
||||||
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
||||||
|
|
||||||
<title>uds.core.auths — UDS 1.0 documentation</title>
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../../../_static/sphinxdoc.css" type="text/css" />
|
|
||||||
<link rel="stylesheet" href="../../../_static/pygments.css" type="text/css" />
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
var DOCUMENTATION_OPTIONS = {
|
|
||||||
URL_ROOT: '../../../',
|
|
||||||
VERSION: '1.0',
|
|
||||||
COLLAPSE_INDEX: false,
|
|
||||||
FILE_SUFFIX: '.html',
|
|
||||||
HAS_SOURCE: true
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<script type="text/javascript" src="../../../_static/jquery.js"></script>
|
|
||||||
<script type="text/javascript" src="../../../_static/underscore.js"></script>
|
|
||||||
<script type="text/javascript" src="../../../_static/doctools.js"></script>
|
|
||||||
<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
|
||||||
<link rel="top" title="UDS 1.0 documentation" href="../../../index.html" />
|
|
||||||
<link rel="up" title="uds.core" href="../core.html" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="related">
|
|
||||||
<h3>Navigation</h3>
|
|
||||||
<ul>
|
|
||||||
<li class="right" style="margin-right: 10px">
|
|
||||||
<a href="../../../genindex.html" title="General Index"
|
|
||||||
accesskey="I">index</a></li>
|
|
||||||
<li class="right" >
|
|
||||||
<a href="../../../py-modindex.html" title="Python Module Index"
|
|
||||||
>modules</a> |</li>
|
|
||||||
<li><a href="../../../index.html">UDS 1.0 documentation</a> »</li>
|
|
||||||
<li><a href="../../index.html" >Module code</a> »</li>
|
|
||||||
<li><a href="../core.html" accesskey="U">uds.core</a> »</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="sphinxsidebar">
|
|
||||||
<div class="sphinxsidebarwrapper">
|
|
||||||
<div id="searchbox" style="display: none">
|
|
||||||
<h3>Quick search</h3>
|
|
||||||
<form class="search" action="../../../search.html" method="get">
|
|
||||||
<input type="text" name="q" />
|
|
||||||
<input type="submit" value="Go" />
|
|
||||||
<input type="hidden" name="check_keywords" value="yes" />
|
|
||||||
<input type="hidden" name="area" value="default" />
|
|
||||||
</form>
|
|
||||||
<p class="searchtip" style="font-size: 90%">
|
|
||||||
Enter search terms or a module, class or function name.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="document">
|
|
||||||
<div class="documentwrapper">
|
|
||||||
<div class="bodywrapper">
|
|
||||||
<div class="body">
|
|
||||||
|
|
||||||
<h1>Source code for uds.core.auths</h1><div class="highlight"><pre>
|
|
||||||
<span class="c"># -*- coding: utf-8 -*-</span>
|
|
||||||
|
|
||||||
<span class="c">#</span>
|
|
||||||
<span class="c"># Copyright (c) 2012 Virtual Cable S.L.</span>
|
|
||||||
<span class="c"># All rights reserved.</span>
|
|
||||||
<span class="c">#</span>
|
|
||||||
<span class="c"># Redistribution and use in source and binary forms, with or without modification,</span>
|
|
||||||
<span class="c"># are permitted provided that the following conditions are met:</span>
|
|
||||||
<span class="c">#</span>
|
|
||||||
<span class="c"># * Redistributions of source code must retain the above copyright notice,</span>
|
|
||||||
<span class="c"># this list of conditions and the following disclaimer.</span>
|
|
||||||
<span class="c"># * Redistributions in binary form must reproduce the above copyright notice,</span>
|
|
||||||
<span class="c"># this list of conditions and the following disclaimer in the documentation</span>
|
|
||||||
<span class="c"># and/or other materials provided with the distribution.</span>
|
|
||||||
<span class="c"># * Neither the name of Virtual Cable S.L. nor the names of its contributors</span>
|
|
||||||
<span class="c"># may be used to endorse or promote products derived from this software</span>
|
|
||||||
<span class="c"># without specific prior written permission.</span>
|
|
||||||
<span class="c">#</span>
|
|
||||||
<span class="c"># THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"</span>
|
|
||||||
<span class="c"># AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE</span>
|
|
||||||
<span class="c"># IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE</span>
|
|
||||||
<span class="c"># DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE</span>
|
|
||||||
<span class="c"># FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL</span>
|
|
||||||
<span class="c"># DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR</span>
|
|
||||||
<span class="c"># SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER</span>
|
|
||||||
<span class="c"># CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,</span>
|
|
||||||
<span class="c"># OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE</span>
|
|
||||||
<span class="c"># OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</span>
|
|
||||||
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd">UDS authentication related interfaces and classes</span>
|
|
||||||
|
|
||||||
<span class="sd">.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">unicode_literals</span>
|
|
||||||
|
|
||||||
<span class="kn">from</span> <span class="nn">BaseAuthenticator</span> <span class="kn">import</span> <span class="n">Authenticator</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">User</span> <span class="kn">import</span> <span class="n">User</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">Group</span> <span class="kn">import</span> <span class="n">Group</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">GroupsManager</span> <span class="kn">import</span> <span class="n">GroupsManager</span>
|
|
||||||
<span class="kn">import</span> <span class="nn">Exceptions</span>
|
|
||||||
|
|
||||||
<span class="n">__updated__</span> <span class="o">=</span> <span class="s">'2014-02-19'</span>
|
|
||||||
|
|
||||||
|
|
||||||
<span class="k">def</span> <span class="nf">factory</span><span class="p">():</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> Returns factory for register/access to authenticators</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">AuthsFactory</span> <span class="kn">import</span> <span class="n">AuthsFactory</span>
|
|
||||||
<span class="k">return</span> <span class="n">AuthsFactory</span><span class="o">.</span><span class="n">factory</span><span class="p">()</span>
|
|
||||||
</pre></div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="clearer"></div>
|
|
||||||
</div>
|
|
||||||
<div class="related">
|
|
||||||
<h3>Navigation</h3>
|
|
||||||
<ul>
|
|
||||||
<li class="right" style="margin-right: 10px">
|
|
||||||
<a href="../../../genindex.html" title="General Index"
|
|
||||||
>index</a></li>
|
|
||||||
<li class="right" >
|
|
||||||
<a href="../../../py-modindex.html" title="Python Module Index"
|
|
||||||
>modules</a> |</li>
|
|
||||||
<li><a href="../../../index.html">UDS 1.0 documentation</a> »</li>
|
|
||||||
<li><a href="../../index.html" >Module code</a> »</li>
|
|
||||||
<li><a href="../core.html" >uds.core</a> »</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="footer">
|
|
||||||
© Copyright 2012, Virtual Cable S.L.U..
|
|
||||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.2.2.
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,152 +0,0 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
|
||||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
||||||
|
|
||||||
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
||||||
|
|
||||||
<title>uds.core.services — UDS 1.0 documentation</title>
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../../../_static/sphinxdoc.css" type="text/css" />
|
|
||||||
<link rel="stylesheet" href="../../../_static/pygments.css" type="text/css" />
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
var DOCUMENTATION_OPTIONS = {
|
|
||||||
URL_ROOT: '../../../',
|
|
||||||
VERSION: '1.0',
|
|
||||||
COLLAPSE_INDEX: false,
|
|
||||||
FILE_SUFFIX: '.html',
|
|
||||||
HAS_SOURCE: true
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<script type="text/javascript" src="../../../_static/jquery.js"></script>
|
|
||||||
<script type="text/javascript" src="../../../_static/underscore.js"></script>
|
|
||||||
<script type="text/javascript" src="../../../_static/doctools.js"></script>
|
|
||||||
<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
|
||||||
<link rel="top" title="UDS 1.0 documentation" href="../../../index.html" />
|
|
||||||
<link rel="up" title="uds.core" href="../core.html" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="related">
|
|
||||||
<h3>Navigation</h3>
|
|
||||||
<ul>
|
|
||||||
<li class="right" style="margin-right: 10px">
|
|
||||||
<a href="../../../genindex.html" title="General Index"
|
|
||||||
accesskey="I">index</a></li>
|
|
||||||
<li class="right" >
|
|
||||||
<a href="../../../py-modindex.html" title="Python Module Index"
|
|
||||||
>modules</a> |</li>
|
|
||||||
<li><a href="../../../index.html">UDS 1.0 documentation</a> »</li>
|
|
||||||
<li><a href="../../index.html" >Module code</a> »</li>
|
|
||||||
<li><a href="../core.html" accesskey="U">uds.core</a> »</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="sphinxsidebar">
|
|
||||||
<div class="sphinxsidebarwrapper">
|
|
||||||
<div id="searchbox" style="display: none">
|
|
||||||
<h3>Quick search</h3>
|
|
||||||
<form class="search" action="../../../search.html" method="get">
|
|
||||||
<input type="text" name="q" />
|
|
||||||
<input type="submit" value="Go" />
|
|
||||||
<input type="hidden" name="check_keywords" value="yes" />
|
|
||||||
<input type="hidden" name="area" value="default" />
|
|
||||||
</form>
|
|
||||||
<p class="searchtip" style="font-size: 90%">
|
|
||||||
Enter search terms or a module, class or function name.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="document">
|
|
||||||
<div class="documentwrapper">
|
|
||||||
<div class="bodywrapper">
|
|
||||||
<div class="body">
|
|
||||||
|
|
||||||
<h1>Source code for uds.core.services</h1><div class="highlight"><pre>
|
|
||||||
<span class="c"># -*- coding: utf-8 -*-</span>
|
|
||||||
|
|
||||||
<span class="c">#</span>
|
|
||||||
<span class="c"># Copyright (c) 2012 Virtual Cable S.L.</span>
|
|
||||||
<span class="c"># All rights reserved.</span>
|
|
||||||
<span class="c">#</span>
|
|
||||||
<span class="c"># Redistribution and use in source and binary forms, with or without modification,</span>
|
|
||||||
<span class="c"># are permitted provided that the following conditions are met:</span>
|
|
||||||
<span class="c">#</span>
|
|
||||||
<span class="c"># * Redistributions of source code must retain the above copyright notice,</span>
|
|
||||||
<span class="c"># this list of conditions and the following disclaimer.</span>
|
|
||||||
<span class="c"># * Redistributions in binary form must reproduce the above copyright notice,</span>
|
|
||||||
<span class="c"># this list of conditions and the following disclaimer in the documentation</span>
|
|
||||||
<span class="c"># and/or other materials provided with the distribution.</span>
|
|
||||||
<span class="c"># * Neither the name of Virtual Cable S.L. nor the names of its contributors</span>
|
|
||||||
<span class="c"># may be used to endorse or promote products derived from this software</span>
|
|
||||||
<span class="c"># without specific prior written permission.</span>
|
|
||||||
<span class="c">#</span>
|
|
||||||
<span class="c"># THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"</span>
|
|
||||||
<span class="c"># AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE</span>
|
|
||||||
<span class="c"># IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE</span>
|
|
||||||
<span class="c"># DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE</span>
|
|
||||||
<span class="c"># FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL</span>
|
|
||||||
<span class="c"># DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR</span>
|
|
||||||
<span class="c"># SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER</span>
|
|
||||||
<span class="c"># CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,</span>
|
|
||||||
<span class="c"># OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE</span>
|
|
||||||
<span class="c"># OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</span>
|
|
||||||
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd">UDS Service modules interfaces and classes.</span>
|
|
||||||
|
|
||||||
<span class="sd">.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">unicode_literals</span>
|
|
||||||
|
|
||||||
<span class="kn">from</span> <span class="nn">BaseServiceProvider</span> <span class="kn">import</span> <span class="n">ServiceProvider</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">BaseService</span> <span class="kn">import</span> <span class="n">Service</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">BasePublication</span> <span class="kn">import</span> <span class="n">Publication</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">BaseDeployed</span> <span class="kn">import</span> <span class="n">UserDeployment</span>
|
|
||||||
|
|
||||||
<span class="kn">from</span> <span class="nn">ClusteredServiceProvider</span> <span class="kn">import</span> <span class="n">ClusteredServiceProvider</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">ClusteredService</span> <span class="kn">import</span> <span class="n">ClusteredService</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">ClusteredPublication</span> <span class="kn">import</span> <span class="n">ClusteredPublication</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">ClusteredUserDeployment</span> <span class="kn">import</span> <span class="n">ClusteredUserDeployment</span>
|
|
||||||
|
|
||||||
<span class="kn">import</span> <span class="nn">Exceptions</span>
|
|
||||||
|
|
||||||
<span class="n">__updated__</span> <span class="o">=</span> <span class="s">'2014-03-22'</span>
|
|
||||||
|
|
||||||
|
|
||||||
<span class="k">def</span> <span class="nf">factory</span><span class="p">():</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> Returns factory for register/access to service providers</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">ServiceProviderFactory</span> <span class="kn">import</span> <span class="n">ServiceProviderFactory</span>
|
|
||||||
<span class="k">return</span> <span class="n">ServiceProviderFactory</span><span class="o">.</span><span class="n">factory</span><span class="p">()</span>
|
|
||||||
</pre></div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="clearer"></div>
|
|
||||||
</div>
|
|
||||||
<div class="related">
|
|
||||||
<h3>Navigation</h3>
|
|
||||||
<ul>
|
|
||||||
<li class="right" style="margin-right: 10px">
|
|
||||||
<a href="../../../genindex.html" title="General Index"
|
|
||||||
>index</a></li>
|
|
||||||
<li class="right" >
|
|
||||||
<a href="../../../py-modindex.html" title="Python Module Index"
|
|
||||||
>modules</a> |</li>
|
|
||||||
<li><a href="../../../index.html">UDS 1.0 documentation</a> »</li>
|
|
||||||
<li><a href="../../index.html" >Module code</a> »</li>
|
|
||||||
<li><a href="../core.html" >uds.core</a> »</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="footer">
|
|
||||||
© Copyright 2012, Virtual Cable S.L.U..
|
|
||||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.2.2.
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,181 +0,0 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
|
||||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
||||||
|
|
||||||
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
||||||
|
|
||||||
<title>uds.core.services.Exceptions — UDS 1.0 documentation</title>
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../../../../_static/sphinxdoc.css" type="text/css" />
|
|
||||||
<link rel="stylesheet" href="../../../../_static/pygments.css" type="text/css" />
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
var DOCUMENTATION_OPTIONS = {
|
|
||||||
URL_ROOT: '../../../../',
|
|
||||||
VERSION: '1.0',
|
|
||||||
COLLAPSE_INDEX: false,
|
|
||||||
FILE_SUFFIX: '.html',
|
|
||||||
HAS_SOURCE: true
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<script type="text/javascript" src="../../../../_static/jquery.js"></script>
|
|
||||||
<script type="text/javascript" src="../../../../_static/underscore.js"></script>
|
|
||||||
<script type="text/javascript" src="../../../../_static/doctools.js"></script>
|
|
||||||
<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
|
||||||
<link rel="top" title="UDS 1.0 documentation" href="../../../../index.html" />
|
|
||||||
<link rel="up" title="uds.core.services" href="../services.html" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="related">
|
|
||||||
<h3>Navigation</h3>
|
|
||||||
<ul>
|
|
||||||
<li class="right" style="margin-right: 10px">
|
|
||||||
<a href="../../../../genindex.html" title="General Index"
|
|
||||||
accesskey="I">index</a></li>
|
|
||||||
<li class="right" >
|
|
||||||
<a href="../../../../py-modindex.html" title="Python Module Index"
|
|
||||||
>modules</a> |</li>
|
|
||||||
<li><a href="../../../../index.html">UDS 1.0 documentation</a> »</li>
|
|
||||||
<li><a href="../../../index.html" >Module code</a> »</li>
|
|
||||||
<li><a href="../../core.html" >uds.core</a> »</li>
|
|
||||||
<li><a href="../services.html" accesskey="U">uds.core.services</a> »</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="sphinxsidebar">
|
|
||||||
<div class="sphinxsidebarwrapper">
|
|
||||||
<div id="searchbox" style="display: none">
|
|
||||||
<h3>Quick search</h3>
|
|
||||||
<form class="search" action="../../../../search.html" method="get">
|
|
||||||
<input type="text" name="q" />
|
|
||||||
<input type="submit" value="Go" />
|
|
||||||
<input type="hidden" name="check_keywords" value="yes" />
|
|
||||||
<input type="hidden" name="area" value="default" />
|
|
||||||
</form>
|
|
||||||
<p class="searchtip" style="font-size: 90%">
|
|
||||||
Enter search terms or a module, class or function name.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="document">
|
|
||||||
<div class="documentwrapper">
|
|
||||||
<div class="bodywrapper">
|
|
||||||
<div class="body">
|
|
||||||
|
|
||||||
<h1>Source code for uds.core.services.Exceptions</h1><div class="highlight"><pre>
|
|
||||||
<span class="c"># -*- coding: utf-8 -*-</span>
|
|
||||||
|
|
||||||
<span class="c">#</span>
|
|
||||||
<span class="c"># Copyright (c) 2012 Virtual Cable S.L.</span>
|
|
||||||
<span class="c"># All rights reserved.</span>
|
|
||||||
<span class="c">#</span>
|
|
||||||
<span class="c"># Redistribution and use in source and binary forms, with or without modification,</span>
|
|
||||||
<span class="c"># are permitted provided that the following conditions are met:</span>
|
|
||||||
<span class="c">#</span>
|
|
||||||
<span class="c"># * Redistributions of source code must retain the above copyright notice,</span>
|
|
||||||
<span class="c"># this list of conditions and the following disclaimer.</span>
|
|
||||||
<span class="c"># * Redistributions in binary form must reproduce the above copyright notice,</span>
|
|
||||||
<span class="c"># this list of conditions and the following disclaimer in the documentation</span>
|
|
||||||
<span class="c"># and/or other materials provided with the distribution.</span>
|
|
||||||
<span class="c"># * Neither the name of Virtual Cable S.L. nor the names of its contributors</span>
|
|
||||||
<span class="c"># may be used to endorse or promote products derived from this software</span>
|
|
||||||
<span class="c"># without specific prior written permission.</span>
|
|
||||||
<span class="c">#</span>
|
|
||||||
<span class="c"># THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"</span>
|
|
||||||
<span class="c"># AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE</span>
|
|
||||||
<span class="c"># IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE</span>
|
|
||||||
<span class="c"># DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE</span>
|
|
||||||
<span class="c"># FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL</span>
|
|
||||||
<span class="c"># DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR</span>
|
|
||||||
<span class="c"># SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER</span>
|
|
||||||
<span class="c"># CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,</span>
|
|
||||||
<span class="c"># OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE</span>
|
|
||||||
<span class="c"># OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</span>
|
|
||||||
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd">.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">unicode_literals</span>
|
|
||||||
|
|
||||||
<span class="n">__updated__</span> <span class="o">=</span> <span class="s">'2014-03-22'</span>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="viewcode-block" id="UnsupportedException"><a class="viewcode-back" href="../../../../api/modules/services/Exceptions.html#uds.core.services.Exceptions.UnsupportedException">[docs]</a><span class="k">class</span> <span class="nc">UnsupportedException</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> Reflects that we request an operation that is not supported, i.e. Cancel a publication with snapshots</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="k">pass</span>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="viewcode-block" id="OperationException"><a class="viewcode-back" href="../../../../api/modules/services/Exceptions.html#uds.core.services.Exceptions.OperationException">[docs]</a><span class="k">class</span> <span class="nc">OperationException</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> Reflects that the operation requested can't be acomplished, i.e. remove an snapshot without snapshot reference, cancel non running operation, etc...</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="k">pass</span>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="viewcode-block" id="PublishException"><a class="viewcode-back" href="../../../../api/modules/services/Exceptions.html#uds.core.services.Exceptions.PublishException">[docs]</a><span class="k">class</span> <span class="nc">PublishException</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> Reflects thate the publication can't be done for causes we don't know in advance</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="k">pass</span>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="viewcode-block" id="DeploymentException"><a class="viewcode-back" href="../../../../api/modules/services/Exceptions.html#uds.core.services.Exceptions.DeploymentException">[docs]</a><span class="k">class</span> <span class="nc">DeploymentException</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> Reflects that a deployment of a service (at cache, or assigned to user) can't be done for causes we don't know in advance</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="k">pass</span>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="viewcode-block" id="CancelException"><a class="viewcode-back" href="../../../../api/modules/services/Exceptions.html#uds.core.services.Exceptions.CancelException">[docs]</a><span class="k">class</span> <span class="nc">CancelException</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> Reflects that a "cancel" operation can't be done for some reason</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="viewcode-block" id="InvalidServiceException"><a class="viewcode-back" href="../../../../api/modules/services/Exceptions.html#uds.core.services.Exceptions.InvalidServiceException">[docs]</a><span class="k">class</span> <span class="nc">InvalidServiceException</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> Invalid service specified. The service is not ready</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="k">pass</span>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="viewcode-block" id="MaxServicesReachedException"><a class="viewcode-back" href="../../../../api/modules/services/Exceptions.html#uds.core.services.Exceptions.MaxServicesReachedException">[docs]</a><span class="k">class</span> <span class="nc">MaxServicesReachedException</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> Number of maximum services has been reached, and no more services</span>
|
|
||||||
<span class="sd"> can be created for users.</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="k">pass</span></div>
|
|
||||||
</pre></div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="clearer"></div>
|
|
||||||
</div>
|
|
||||||
<div class="related">
|
|
||||||
<h3>Navigation</h3>
|
|
||||||
<ul>
|
|
||||||
<li class="right" style="margin-right: 10px">
|
|
||||||
<a href="../../../../genindex.html" title="General Index"
|
|
||||||
>index</a></li>
|
|
||||||
<li class="right" >
|
|
||||||
<a href="../../../../py-modindex.html" title="Python Module Index"
|
|
||||||
>modules</a> |</li>
|
|
||||||
<li><a href="../../../../index.html">UDS 1.0 documentation</a> »</li>
|
|
||||||
<li><a href="../../../index.html" >Module code</a> »</li>
|
|
||||||
<li><a href="../../core.html" >uds.core</a> »</li>
|
|
||||||
<li><a href="../services.html" >uds.core.services</a> »</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="footer">
|
|
||||||
© Copyright 2012, Virtual Cable S.L.U..
|
|
||||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.2.2.
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,940 +0,0 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
|
||||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
||||||
|
|
||||||
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
||||||
|
|
||||||
<title>uds.core.ui.UserInterface — UDS 1.0 documentation</title>
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../../../../_static/sphinxdoc.css" type="text/css" />
|
|
||||||
<link rel="stylesheet" href="../../../../_static/pygments.css" type="text/css" />
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
var DOCUMENTATION_OPTIONS = {
|
|
||||||
URL_ROOT: '../../../../',
|
|
||||||
VERSION: '1.0',
|
|
||||||
COLLAPSE_INDEX: false,
|
|
||||||
FILE_SUFFIX: '.html',
|
|
||||||
HAS_SOURCE: true
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<script type="text/javascript" src="../../../../_static/jquery.js"></script>
|
|
||||||
<script type="text/javascript" src="../../../../_static/underscore.js"></script>
|
|
||||||
<script type="text/javascript" src="../../../../_static/doctools.js"></script>
|
|
||||||
<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
|
||||||
<link rel="top" title="UDS 1.0 documentation" href="../../../../index.html" />
|
|
||||||
<link rel="up" title="uds.core" href="../../core.html" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="related">
|
|
||||||
<h3>Navigation</h3>
|
|
||||||
<ul>
|
|
||||||
<li class="right" style="margin-right: 10px">
|
|
||||||
<a href="../../../../genindex.html" title="General Index"
|
|
||||||
accesskey="I">index</a></li>
|
|
||||||
<li class="right" >
|
|
||||||
<a href="../../../../py-modindex.html" title="Python Module Index"
|
|
||||||
>modules</a> |</li>
|
|
||||||
<li><a href="../../../../index.html">UDS 1.0 documentation</a> »</li>
|
|
||||||
<li><a href="../../../index.html" >Module code</a> »</li>
|
|
||||||
<li><a href="../../core.html" accesskey="U">uds.core</a> »</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="sphinxsidebar">
|
|
||||||
<div class="sphinxsidebarwrapper">
|
|
||||||
<div id="searchbox" style="display: none">
|
|
||||||
<h3>Quick search</h3>
|
|
||||||
<form class="search" action="../../../../search.html" method="get">
|
|
||||||
<input type="text" name="q" />
|
|
||||||
<input type="submit" value="Go" />
|
|
||||||
<input type="hidden" name="check_keywords" value="yes" />
|
|
||||||
<input type="hidden" name="area" value="default" />
|
|
||||||
</form>
|
|
||||||
<p class="searchtip" style="font-size: 90%">
|
|
||||||
Enter search terms or a module, class or function name.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="document">
|
|
||||||
<div class="documentwrapper">
|
|
||||||
<div class="bodywrapper">
|
|
||||||
<div class="body">
|
|
||||||
|
|
||||||
<h1>Source code for uds.core.ui.UserInterface</h1><div class="highlight"><pre>
|
|
||||||
<span class="c"># -*- coding: utf-8 -*-</span>
|
|
||||||
|
|
||||||
<span class="c">#</span>
|
|
||||||
<span class="c"># Copyright (c) 2012 Virtual Cable S.L.</span>
|
|
||||||
<span class="c"># All rights reserved.</span>
|
|
||||||
<span class="c">#</span>
|
|
||||||
<span class="c"># Redistribution and use in source and binary forms, with or without modification,</span>
|
|
||||||
<span class="c"># are permitted provided that the following conditions are met:</span>
|
|
||||||
<span class="c">#</span>
|
|
||||||
<span class="c"># * Redistributions of source code must retain the above copyright notice,</span>
|
|
||||||
<span class="c"># this list of conditions and the following disclaimer.</span>
|
|
||||||
<span class="c"># * Redistributions in binary form must reproduce the above copyright notice,</span>
|
|
||||||
<span class="c"># this list of conditions and the following disclaimer in the documentation</span>
|
|
||||||
<span class="c"># and/or other materials provided with the distribution.</span>
|
|
||||||
<span class="c"># * Neither the name of Virtual Cable S.L. nor the names of its contributors</span>
|
|
||||||
<span class="c"># may be used to endorse or promote products derived from this software</span>
|
|
||||||
<span class="c"># without specific prior written permission.</span>
|
|
||||||
<span class="c">#</span>
|
|
||||||
<span class="c"># THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"</span>
|
|
||||||
<span class="c"># AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE</span>
|
|
||||||
<span class="c"># IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE</span>
|
|
||||||
<span class="c"># DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE</span>
|
|
||||||
<span class="c"># FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL</span>
|
|
||||||
<span class="c"># DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR</span>
|
|
||||||
<span class="c"># SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER</span>
|
|
||||||
<span class="c"># CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,</span>
|
|
||||||
<span class="c"># OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE</span>
|
|
||||||
<span class="c"># OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</span>
|
|
||||||
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd">.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">unicode_literals</span>
|
|
||||||
|
|
||||||
<span class="kn">from</span> <span class="nn">django.utils.translation</span> <span class="kn">import</span> <span class="n">get_language</span><span class="p">,</span> <span class="n">ugettext</span> <span class="k">as</span> <span class="n">_</span>
|
|
||||||
<span class="kn">import</span> <span class="nn">cPickle</span>
|
|
||||||
<span class="kn">import</span> <span class="nn">logging</span>
|
|
||||||
|
|
||||||
<span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="n">__name__</span><span class="p">)</span>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="viewcode-block" id="gui"><a class="viewcode-back" href="../../../../api/modules/FormFields.html#uds.core.ui.UserInterface.gui">[docs]</a><span class="k">class</span> <span class="nc">gui</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> This class contains the representations of fields needed by UDS modules and</span>
|
|
||||||
<span class="sd"> administation interface.</span>
|
|
||||||
|
|
||||||
<span class="sd"> This contains fields types, that modules uses to make a form and interact</span>
|
|
||||||
<span class="sd"> with users.</span>
|
|
||||||
|
|
||||||
<span class="sd"> The use of this provided fields are as follows:</span>
|
|
||||||
|
|
||||||
<span class="sd"> The Module is descendant of "BaseModule", which also is inherited from this</span>
|
|
||||||
<span class="sd"> class.</span>
|
|
||||||
|
|
||||||
<span class="sd"> At class level, we declare the fields needed to interact with the user, as</span>
|
|
||||||
<span class="sd"> this example:</span>
|
|
||||||
|
|
||||||
<span class="sd"> .. code-block:: python</span>
|
|
||||||
|
|
||||||
<span class="sd"> class AuthModule(Authenticator):</span>
|
|
||||||
<span class="sd"> # ...</span>
|
|
||||||
<span class="sd"> # Other initializations</span>
|
|
||||||
<span class="sd"> # ...</span>
|
|
||||||
<span class="sd"> users = gui.EditableList(label = 'Users', tooltip = 'Select users',</span>
|
|
||||||
<span class="sd"> order = 1, values = ['user1', 'user2', 'user3', 'user4'])</span>
|
|
||||||
<span class="sd"> passw = gui.Password(label='Pass', length=32, tooltip='Password',</span>
|
|
||||||
<span class="sd"> order = 2, required = True, defValue = '12345')</span>
|
|
||||||
<span class="sd"> # ...</span>
|
|
||||||
<span class="sd"> # more fields</span>
|
|
||||||
<span class="sd"> # ...</span>
|
|
||||||
|
|
||||||
<span class="sd"> At class instantiation, this data is extracted and processed, so the admin</span>
|
|
||||||
<span class="sd"> can access this form to let users</span>
|
|
||||||
<span class="sd"> create new instances of this module.</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
|
|
||||||
<span class="c"># : True string value</span>
|
|
||||||
<span class="n">TRUE</span> <span class="o">=</span> <span class="s">'true'</span>
|
|
||||||
<span class="c"># : False string value</span>
|
|
||||||
<span class="n">FALSE</span> <span class="o">=</span> <span class="s">'false'</span>
|
|
||||||
|
|
||||||
<span class="c"># : Static Callbacks simple registry</span>
|
|
||||||
<span class="n">callbacks</span> <span class="o">=</span> <span class="p">{}</span>
|
|
||||||
|
|
||||||
<span class="c"># Helpers</span>
|
|
||||||
<span class="nd">@staticmethod</span>
|
|
||||||
<span class="k">def</span> <span class="nf">convertToChoices</span><span class="p">(</span><span class="n">vals</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> Helper to convert from array of strings to the same dict used in choice,</span>
|
|
||||||
<span class="sd"> multichoice, ..</span>
|
|
||||||
<span class="sd"> The id is set to values in the array (strings), while text is left empty.</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="n">res</span> <span class="o">=</span> <span class="p">[]</span>
|
|
||||||
<span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">vals</span><span class="p">:</span>
|
|
||||||
<span class="n">res</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s">'id'</span><span class="p">:</span> <span class="n">v</span><span class="p">,</span> <span class="s">'text'</span><span class="p">:</span> <span class="s">''</span><span class="p">})</span>
|
|
||||||
<span class="k">return</span> <span class="n">res</span>
|
|
||||||
|
|
||||||
<span class="nd">@staticmethod</span>
|
|
||||||
<span class="k">def</span> <span class="nf">convertToList</span><span class="p">(</span><span class="n">vals</span><span class="p">):</span>
|
|
||||||
<span class="k">if</span> <span class="n">vals</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
|
|
||||||
<span class="k">return</span> <span class="p">[</span><span class="nb">unicode</span><span class="p">(</span><span class="n">v</span><span class="p">)</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">vals</span><span class="p">]</span>
|
|
||||||
<span class="k">return</span> <span class="p">[]</span>
|
|
||||||
|
|
||||||
<span class="nd">@staticmethod</span>
|
|
||||||
<span class="k">def</span> <span class="nf">choiceItem</span><span class="p">(</span><span class="n">id_</span><span class="p">,</span> <span class="n">text</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> Helper method to create a single choice item.</span>
|
|
||||||
|
|
||||||
<span class="sd"> Args:</span>
|
|
||||||
<span class="sd"> id: Id of the choice to create</span>
|
|
||||||
|
|
||||||
<span class="sd"> text: Text to assign to the choice to create</span>
|
|
||||||
|
|
||||||
<span class="sd"> Returns:</span>
|
|
||||||
<span class="sd"> An dictionary, that is the representation of a single choice item,</span>
|
|
||||||
<span class="sd"> with 2 keys, 'id' and 'text'</span>
|
|
||||||
|
|
||||||
<span class="sd"> :note: Text can be anything, the method converts it first to text before</span>
|
|
||||||
<span class="sd"> assigning to dictionary</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="k">return</span> <span class="p">{</span><span class="s">'id'</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="n">id_</span><span class="p">),</span> <span class="s">'text'</span><span class="p">:</span> <span class="nb">str</span><span class="p">(</span><span class="n">text</span><span class="p">)}</span>
|
|
||||||
|
|
||||||
<span class="nd">@staticmethod</span>
|
|
||||||
<span class="k">def</span> <span class="nf">strToBool</span><span class="p">(</span><span class="n">str_</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> Converts the string "true" (case insensitive) to True (boolean).</span>
|
|
||||||
<span class="sd"> Anything else is converted to false</span>
|
|
||||||
|
|
||||||
<span class="sd"> Args:</span>
|
|
||||||
<span class="sd"> str: Str to convert to boolean</span>
|
|
||||||
|
|
||||||
<span class="sd"> Returns:</span>
|
|
||||||
<span class="sd"> True if the string is "true" (case insensitive), False else.</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">str_</span><span class="p">,</span> <span class="nb">bool</span><span class="p">):</span>
|
|
||||||
<span class="k">return</span> <span class="n">str_</span>
|
|
||||||
<span class="k">if</span> <span class="nb">unicode</span><span class="p">(</span><span class="n">str_</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="o">==</span> <span class="n">gui</span><span class="o">.</span><span class="n">TRUE</span><span class="p">:</span>
|
|
||||||
<span class="k">return</span> <span class="bp">True</span>
|
|
||||||
<span class="k">return</span> <span class="bp">False</span>
|
|
||||||
|
|
||||||
<span class="nd">@staticmethod</span>
|
|
||||||
<span class="k">def</span> <span class="nf">boolToStr</span><span class="p">(</span><span class="n">bol</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> Converts a boolean to the string representation. True is converted to</span>
|
|
||||||
<span class="sd"> "true", False to "false".</span>
|
|
||||||
|
|
||||||
<span class="sd"> Args:</span>
|
|
||||||
<span class="sd"> bol: Boolean value (True or false) to convert</span>
|
|
||||||
|
|
||||||
<span class="sd"> Returns:</span>
|
|
||||||
<span class="sd"> "true" if bol evals to True, "false" if don't.</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="k">if</span> <span class="n">bol</span><span class="p">:</span>
|
|
||||||
<span class="k">return</span> <span class="n">gui</span><span class="o">.</span><span class="n">TRUE</span>
|
|
||||||
<span class="k">return</span> <span class="n">gui</span><span class="o">.</span><span class="n">FALSE</span>
|
|
||||||
|
|
||||||
<span class="c"># Classes</span>
|
|
||||||
|
|
||||||
<div class="viewcode-block" id="gui.InputField"><a class="viewcode-back" href="../../../../api/modules/FormFields.html#uds.core.ui.UserInterface.gui.InputField">[docs]</a> <span class="k">class</span> <span class="nc">InputField</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> Class representing an simple input field.</span>
|
|
||||||
<span class="sd"> This class is not directly usable, must be used by any inherited class</span>
|
|
||||||
<span class="sd"> (fields all of them)</span>
|
|
||||||
<span class="sd"> All fields are inherited from this one</span>
|
|
||||||
|
|
||||||
<span class="sd"> The data managed for an input field, and their default values are:</span>
|
|
||||||
<span class="sd"> * length: Max length of the field. Defaults to DEFAULT_LENGTH</span>
|
|
||||||
<span class="sd"> * required: If this field is a MUST. defaults to false</span>
|
|
||||||
<span class="sd"> * label: Label used with this field. Defaults to ''</span>
|
|
||||||
<span class="sd"> * defvalue: Default value for the field. Defaults to '' (this is</span>
|
|
||||||
<span class="sd"> always an string)</span>
|
|
||||||
<span class="sd"> * rdonly: If the field is read only on modification. On creation,</span>
|
|
||||||
<span class="sd"> all fields are "writable". Defaults to False</span>
|
|
||||||
<span class="sd"> * order: order inside the form, defaults to 0 (if two or more fields</span>
|
|
||||||
<span class="sd"> has same order, the output order may be anything)</span>
|
|
||||||
<span class="sd"> * tooltip: Tooltip used in the form, defaults to ''</span>
|
|
||||||
<span class="sd"> * type: type of the input field, defaults to "text box" (TextField)</span>
|
|
||||||
|
|
||||||
<span class="sd"> In every single field, you must at least indicate:</span>
|
|
||||||
<span class="sd"> * if required or not</span>
|
|
||||||
<span class="sd"> * order</span>
|
|
||||||
<span class="sd"> * label</span>
|
|
||||||
<span class="sd"> * tooltip</span>
|
|
||||||
<span class="sd"> * defvalue</span>
|
|
||||||
<span class="sd"> * rdonly if can't be modified once it's created</span>
|
|
||||||
|
|
||||||
<span class="sd"> Any other paremeter needed is indicated in the corresponding field class.</span>
|
|
||||||
|
|
||||||
<span class="sd"> Also a value field is available, so you can get/set the form field value.</span>
|
|
||||||
<span class="sd"> This property expects always an string, no matter what kind of field it is.</span>
|
|
||||||
|
|
||||||
<span class="sd"> Take into account also that "value" has precedence over "defValue",</span>
|
|
||||||
<span class="sd"> so if you use both, the used one will be "value". This is valid for</span>
|
|
||||||
<span class="sd"> all form fields.</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="n">TEXT_TYPE</span> <span class="o">=</span> <span class="s">'text'</span>
|
|
||||||
<span class="n">TEXTBOX_TYPE</span> <span class="o">=</span> <span class="s">'textbox'</span>
|
|
||||||
<span class="n">NUMERIC_TYPE</span> <span class="o">=</span> <span class="s">'numeric'</span>
|
|
||||||
<span class="n">PASSWORD_TYPE</span> <span class="o">=</span> <span class="s">'password'</span>
|
|
||||||
<span class="n">HIDDEN_TYPE</span> <span class="o">=</span> <span class="s">'hidden'</span>
|
|
||||||
<span class="n">CHOICE_TYPE</span> <span class="o">=</span> <span class="s">'choice'</span>
|
|
||||||
<span class="n">MULTI_CHOICE_TYPE</span> <span class="o">=</span> <span class="s">'multichoice'</span>
|
|
||||||
<span class="n">EDITABLE_LIST</span> <span class="o">=</span> <span class="s">'editlist'</span>
|
|
||||||
<span class="n">CHECKBOX_TYPE</span> <span class="o">=</span> <span class="s">'checkbox'</span>
|
|
||||||
|
|
||||||
<span class="n">DEFAULT_LENTGH</span> <span class="o">=</span> <span class="mi">32</span> <span class="c"># : If length of some fields are not especified, this value is used as default</span>
|
|
||||||
|
|
||||||
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">):</span>
|
|
||||||
<span class="bp">self</span><span class="o">.</span><span class="n">_data</span> <span class="o">=</span> <span class="p">{</span>
|
|
||||||
<span class="s">'length'</span><span class="p">:</span> <span class="n">options</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'length'</span><span class="p">,</span> <span class="n">gui</span><span class="o">.</span><span class="n">InputField</span><span class="o">.</span><span class="n">DEFAULT_LENTGH</span><span class="p">),</span>
|
|
||||||
<span class="s">'required'</span><span class="p">:</span> <span class="n">options</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'required'</span><span class="p">,</span> <span class="bp">False</span><span class="p">),</span>
|
|
||||||
<span class="s">'label'</span><span class="p">:</span> <span class="n">options</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'label'</span><span class="p">,</span> <span class="s">''</span><span class="p">),</span>
|
|
||||||
<span class="s">'defvalue'</span><span class="p">:</span> <span class="nb">unicode</span><span class="p">(</span><span class="n">options</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'defvalue'</span><span class="p">,</span> <span class="s">''</span><span class="p">)),</span>
|
|
||||||
<span class="s">'rdonly'</span><span class="p">:</span> <span class="n">options</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'rdonly'</span><span class="p">,</span> <span class="bp">False</span><span class="p">),</span> <span class="c"># This property only affects in "modify" operations</span>
|
|
||||||
<span class="s">'order'</span><span class="p">:</span> <span class="n">options</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'order'</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span>
|
|
||||||
<span class="s">'tooltip'</span><span class="p">:</span> <span class="n">options</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'tooltip'</span><span class="p">,</span> <span class="s">''</span><span class="p">),</span>
|
|
||||||
<span class="s">'type'</span><span class="p">:</span> <span class="n">gui</span><span class="o">.</span><span class="n">InputField</span><span class="o">.</span><span class="n">TEXT_TYPE</span><span class="p">,</span>
|
|
||||||
<span class="s">'value'</span><span class="p">:</span> <span class="n">options</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'value'</span><span class="p">,</span> <span class="s">''</span><span class="p">),</span>
|
|
||||||
<span class="p">}</span>
|
|
||||||
|
|
||||||
<span class="k">def</span> <span class="nf">_type</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">type_</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> Sets the type of this field.</span>
|
|
||||||
|
|
||||||
<span class="sd"> Args:</span>
|
|
||||||
<span class="sd"> type: Type to set (from constants of this class)</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="bp">self</span><span class="o">.</span><span class="n">_data</span><span class="p">[</span><span class="s">'type'</span><span class="p">]</span> <span class="o">=</span> <span class="n">type_</span>
|
|
||||||
|
|
||||||
<div class="viewcode-block" id="gui.InputField.isType"><a class="viewcode-back" href="../../../../api/modules/FormFields.html#uds.core.ui.UserInterface.gui.InputField.isType">[docs]</a> <span class="k">def</span> <span class="nf">isType</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">type_</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> Returns true if this field is of specified type</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_data</span><span class="p">[</span><span class="s">'type'</span><span class="p">]</span> <span class="o">==</span> <span class="n">type_</span>
|
|
||||||
</div>
|
|
||||||
<span class="nd">@property</span>
|
|
||||||
<span class="k">def</span> <span class="nf">value</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> Obtains the stored value</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_data</span><span class="p">[</span><span class="s">'value'</span><span class="p">]</span>
|
|
||||||
|
|
||||||
<span class="nd">@value.setter</span>
|
|
||||||
<div class="viewcode-block" id="gui.InputField.value"><a class="viewcode-back" href="../../../../api/modules/FormFields.html#uds.core.ui.UserInterface.gui.InputField.value">[docs]</a> <span class="k">def</span> <span class="nf">value</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> Stores new value (not the default one)</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="bp">self</span><span class="o">.</span><span class="n">_setValue</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
|
|
||||||
</div>
|
|
||||||
<span class="k">def</span> <span class="nf">_setValue</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> So we can override value setting at descendants</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="bp">self</span><span class="o">.</span><span class="n">_data</span><span class="p">[</span><span class="s">'value'</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
|
|
||||||
|
|
||||||
<div class="viewcode-block" id="gui.InputField.guiDescription"><a class="viewcode-back" href="../../../../api/modules/FormFields.html#uds.core.ui.UserInterface.gui.InputField.guiDescription">[docs]</a> <span class="k">def</span> <span class="nf">guiDescription</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> Returns the dictionary with the description of this item.</span>
|
|
||||||
<span class="sd"> We copy it, cause we need to translate the label and tooltip fields</span>
|
|
||||||
<span class="sd"> and don't want to</span>
|
|
||||||
<span class="sd"> alter original values.</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="n">data</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_data</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
|
|
||||||
<span class="n">data</span><span class="p">[</span><span class="s">'label'</span><span class="p">]</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="s">'label'</span><span class="p">]</span> <span class="o">!=</span> <span class="s">''</span> <span class="ow">and</span> <span class="n">_</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="s">'label'</span><span class="p">])</span> <span class="ow">or</span> <span class="s">''</span>
|
|
||||||
<span class="n">data</span><span class="p">[</span><span class="s">'tooltip'</span><span class="p">]</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="s">'tooltip'</span><span class="p">]</span> <span class="o">!=</span> <span class="s">''</span> <span class="ow">and</span> <span class="n">_</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="s">'tooltip'</span><span class="p">])</span> <span class="ow">or</span> <span class="s">''</span>
|
|
||||||
<span class="k">return</span> <span class="n">data</span>
|
|
||||||
</div>
|
|
||||||
<span class="nd">@property</span>
|
|
||||||
<span class="k">def</span> <span class="nf">defValue</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> Returns the default value for this field</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_data</span><span class="p">[</span><span class="s">'defvalue'</span><span class="p">]</span>
|
|
||||||
|
|
||||||
<span class="nd">@defValue.setter</span>
|
|
||||||
<div class="viewcode-block" id="gui.InputField.defValue"><a class="viewcode-back" href="../../../../api/modules/FormFields.html#uds.core.ui.UserInterface.gui.InputField.defValue">[docs]</a> <span class="k">def</span> <span class="nf">defValue</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">defValue</span><span class="p">):</span>
|
|
||||||
<span class="bp">self</span><span class="o">.</span><span class="n">setDefValue</span><span class="p">(</span><span class="n">defValue</span><span class="p">)</span>
|
|
||||||
</div>
|
|
||||||
<div class="viewcode-block" id="gui.InputField.setDefValue"><a class="viewcode-back" href="../../../../api/modules/FormFields.html#uds.core.ui.UserInterface.gui.InputField.setDefValue">[docs]</a> <span class="k">def</span> <span class="nf">setDefValue</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">defValue</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> Sets the default value of the field·</span>
|
|
||||||
|
|
||||||
<span class="sd"> Args:</span>
|
|
||||||
<span class="sd"> defValue: Default value (string)</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="bp">self</span><span class="o">.</span><span class="n">_data</span><span class="p">[</span><span class="s">'defvalue'</span><span class="p">]</span> <span class="o">=</span> <span class="n">defValue</span>
|
|
||||||
</div>
|
|
||||||
<span class="nd">@property</span>
|
|
||||||
<span class="k">def</span> <span class="nf">label</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
||||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_data</span><span class="p">[</span><span class="s">'label'</span><span class="p">]</span>
|
|
||||||
</div>
|
|
||||||
<div class="viewcode-block" id="gui.TextField"><a class="viewcode-back" href="../../../../api/modules/FormFields.html#uds.core.ui.UserInterface.gui.TextField">[docs]</a> <span class="k">class</span> <span class="nc">TextField</span><span class="p">(</span><span class="n">InputField</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> This represents a text field.</span>
|
|
||||||
|
|
||||||
<span class="sd"> The values of parameters are inherited from :py:class:`InputField`</span>
|
|
||||||
|
|
||||||
<span class="sd"> Additionally to standard parameters, the length parameter is a</span>
|
|
||||||
<span class="sd"> recommended one for this kind of field.</span>
|
|
||||||
|
|
||||||
<span class="sd"> You can specify that this is a multiline text box with **multiline**</span>
|
|
||||||
<span class="sd"> parameter. If it exists, and is greater than 1, indicates how much</span>
|
|
||||||
<span class="sd"> lines will be used to display field. (Max number is 8)</span>
|
|
||||||
|
|
||||||
<span class="sd"> Example usage:</span>
|
|
||||||
|
|
||||||
<span class="sd"> .. code-block:: python</span>
|
|
||||||
|
|
||||||
<span class="sd"> # Declares an text form field, with label "Host", tooltip</span>
|
|
||||||
<span class="sd"> # "Host name for this module", that is required,</span>
|
|
||||||
<span class="sd"> # with max length of 64 chars and order = 1, and is editable</span>
|
|
||||||
<span class="sd"> # after creation.</span>
|
|
||||||
<span class="sd"> host = gui.TextField(length=64, label = _('Host'), order = 1,</span>
|
|
||||||
<span class="sd"> tooltip = _('Host name for this module'), required = True)</span>
|
|
||||||
|
|
||||||
<span class="sd"> # Declares an text form field, with label "Other",</span>
|
|
||||||
<span class="sd"> # tooltip "Other info", that is not required, that is not</span>
|
|
||||||
<span class="sd"> # required and that is not editable after creation.</span>
|
|
||||||
<span class="sd"> other = gui.TextField(length=64, label = _('Other'), order = 1,</span>
|
|
||||||
<span class="sd"> tooltip = _('Other info'), rdonly = True)</span>
|
|
||||||
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">):</span>
|
|
||||||
<span class="nb">super</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">__class__</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="o">**</span><span class="n">options</span><span class="p">)</span>
|
|
||||||
<span class="bp">self</span><span class="o">.</span><span class="n">_type</span><span class="p">(</span><span class="n">gui</span><span class="o">.</span><span class="n">InputField</span><span class="o">.</span><span class="n">TEXT_TYPE</span><span class="p">)</span>
|
|
||||||
<span class="n">multiline</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">options</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'multiline'</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span>
|
|
||||||
<span class="k">if</span> <span class="n">multiline</span> <span class="o">></span> <span class="mi">8</span><span class="p">:</span>
|
|
||||||
<span class="n">multiline</span> <span class="o">=</span> <span class="mi">8</span>
|
|
||||||
<span class="bp">self</span><span class="o">.</span><span class="n">_data</span><span class="p">[</span><span class="s">'multiline'</span><span class="p">]</span> <span class="o">=</span> <span class="n">multiline</span>
|
|
||||||
</div>
|
|
||||||
<div class="viewcode-block" id="gui.NumericField"><a class="viewcode-back" href="../../../../api/modules/FormFields.html#uds.core.ui.UserInterface.gui.NumericField">[docs]</a> <span class="k">class</span> <span class="nc">NumericField</span><span class="p">(</span><span class="n">InputField</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> This represents a numeric field. It apears with an spin up/down button.</span>
|
|
||||||
|
|
||||||
<span class="sd"> The values of parameres are inherited from :py:class:`InputField`</span>
|
|
||||||
|
|
||||||
<span class="sd"> Additionally to standard parameters, the length parameter indicates the</span>
|
|
||||||
<span class="sd"> max number of digits (0-9 values).</span>
|
|
||||||
|
|
||||||
<span class="sd"> Example usage:</span>
|
|
||||||
|
|
||||||
<span class="sd"> .. code-block:: python</span>
|
|
||||||
|
|
||||||
<span class="sd"> # Declares an numeric form field, with max value of 99999, label</span>
|
|
||||||
<span class="sd"> # "Port", that is required,</span>
|
|
||||||
<span class="sd"> # with tooltip "Port (usually 443)" and order 1</span>
|
|
||||||
<span class="sd"> num = gui.NumericField(length=5, label = _('Port'),</span>
|
|
||||||
<span class="sd"> defvalue = '443', order = 1, tooltip = _('Port (usually 443)'),</span>
|
|
||||||
<span class="sd"> required = True)</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">):</span>
|
|
||||||
<span class="nb">super</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">__class__</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="o">**</span><span class="n">options</span><span class="p">)</span>
|
|
||||||
<span class="bp">self</span><span class="o">.</span><span class="n">_type</span><span class="p">(</span><span class="n">gui</span><span class="o">.</span><span class="n">InputField</span><span class="o">.</span><span class="n">NUMERIC_TYPE</span><span class="p">)</span>
|
|
||||||
|
|
||||||
<div class="viewcode-block" id="gui.NumericField.num"><a class="viewcode-back" href="../../../../api/modules/FormFields.html#uds.core.ui.UserInterface.gui.NumericField.num">[docs]</a> <span class="k">def</span> <span class="nf">num</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> Return value as integer</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">value</span><span class="p">)</span>
|
|
||||||
</div></div>
|
|
||||||
<div class="viewcode-block" id="gui.PasswordField"><a class="viewcode-back" href="../../../../api/modules/FormFields.html#uds.core.ui.UserInterface.gui.PasswordField">[docs]</a> <span class="k">class</span> <span class="nc">PasswordField</span><span class="p">(</span><span class="n">InputField</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> This represents a password field. It appears with "*" at input, so the contents is not displayed</span>
|
|
||||||
|
|
||||||
<span class="sd"> The values of parameres are inherited from :py:class:`InputField`</span>
|
|
||||||
|
|
||||||
<span class="sd"> Additionally to standard parameters, the length parameter is a recommended one for this kind of field.</span>
|
|
||||||
|
|
||||||
<span class="sd"> Example usage:</span>
|
|
||||||
|
|
||||||
<span class="sd"> .. code-block:: python</span>
|
|
||||||
|
|
||||||
<span class="sd"> # Declares an text form field, with label "Password",</span>
|
|
||||||
<span class="sd"> # tooltip "Password of the user", that is required,</span>
|
|
||||||
<span class="sd"> # with max length of 32 chars and order = 2, and is</span>
|
|
||||||
<span class="sd"> # editable after creation.</span>
|
|
||||||
<span class="sd"> passw = gui.PasswordField(lenth=32, label = _('Password'),</span>
|
|
||||||
<span class="sd"> order = 4, tooltip = _('Password of the user'),</span>
|
|
||||||
<span class="sd"> required = True)</span>
|
|
||||||
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">):</span>
|
|
||||||
<span class="nb">super</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">__class__</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="o">**</span><span class="n">options</span><span class="p">)</span>
|
|
||||||
<span class="bp">self</span><span class="o">.</span><span class="n">_type</span><span class="p">(</span><span class="n">gui</span><span class="o">.</span><span class="n">InputField</span><span class="o">.</span><span class="n">PASSWORD_TYPE</span><span class="p">)</span>
|
|
||||||
</div>
|
|
||||||
<div class="viewcode-block" id="gui.HiddenField"><a class="viewcode-back" href="../../../../api/modules/FormFields.html#uds.core.ui.UserInterface.gui.HiddenField">[docs]</a> <span class="k">class</span> <span class="nc">HiddenField</span><span class="p">(</span><span class="n">InputField</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> This represents a hidden field. It is not displayed to the user. It use</span>
|
|
||||||
<span class="sd"> is for keeping info at form needed</span>
|
|
||||||
<span class="sd"> by module, but not editable by user (i.e., one service can keep info</span>
|
|
||||||
<span class="sd"> about the parent provider in hiddens)</span>
|
|
||||||
|
|
||||||
<span class="sd"> The values of parameres are inherited from :py:class:`InputField`</span>
|
|
||||||
|
|
||||||
<span class="sd"> These are almost the same as TextFields, but they do not get displayed</span>
|
|
||||||
<span class="sd"> for user interaction.</span>
|
|
||||||
|
|
||||||
<span class="sd"> Example usage:</span>
|
|
||||||
|
|
||||||
<span class="sd"> .. code-block:: python</span>
|
|
||||||
|
|
||||||
<span class="sd"> # Declares an empty hidden field</span>
|
|
||||||
<span class="sd"> hidden = gui.HiddenField()</span>
|
|
||||||
|
|
||||||
|
|
||||||
<span class="sd"> After that, at initGui method of module, we can store a value inside</span>
|
|
||||||
<span class="sd"> using setDefValue as shown here:</span>
|
|
||||||
|
|
||||||
<span class="sd"> .. code-block:: python</span>
|
|
||||||
|
|
||||||
<span class="sd"> def initGui(self):</span>
|
|
||||||
<span class="sd"> # always set defValue using self, cause we only want to store</span>
|
|
||||||
<span class="sd"> # value for current instance</span>
|
|
||||||
<span class="sd"> self.hidden.setDefValue(self.parent().serialize())</span>
|
|
||||||
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">):</span>
|
|
||||||
<span class="nb">super</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">__class__</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="o">**</span><span class="n">options</span><span class="p">)</span>
|
|
||||||
<span class="bp">self</span><span class="o">.</span><span class="n">_isSerializable</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'serializable'</span><span class="p">,</span> <span class="s">''</span><span class="p">)</span> <span class="o">!=</span> <span class="s">''</span>
|
|
||||||
<span class="bp">self</span><span class="o">.</span><span class="n">_type</span><span class="p">(</span><span class="n">gui</span><span class="o">.</span><span class="n">InputField</span><span class="o">.</span><span class="n">HIDDEN_TYPE</span><span class="p">)</span>
|
|
||||||
|
|
||||||
<span class="k">def</span> <span class="nf">isSerializable</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
||||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_isSerializable</span>
|
|
||||||
</div>
|
|
||||||
<div class="viewcode-block" id="gui.CheckBoxField"><a class="viewcode-back" href="../../../../api/modules/FormFields.html#uds.core.ui.UserInterface.gui.CheckBoxField">[docs]</a> <span class="k">class</span> <span class="nc">CheckBoxField</span><span class="p">(</span><span class="n">InputField</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> This represents a check box field, with values "true" and "false"</span>
|
|
||||||
|
|
||||||
<span class="sd"> The values of parameters are inherited from :py:class:`InputField`</span>
|
|
||||||
|
|
||||||
<span class="sd"> The valid values for this defvalue are: "true" and "false" (as strings)</span>
|
|
||||||
|
|
||||||
<span class="sd"> Example usage:</span>
|
|
||||||
|
|
||||||
<span class="sd"> .. code-block:: python</span>
|
|
||||||
|
|
||||||
<span class="sd"> # Declares an check box field, with label "Use SSL", order 3,</span>
|
|
||||||
<span class="sd"> # tooltip "If checked, will use a ssl connection", default value</span>
|
|
||||||
<span class="sd"> # unchecked (not included, so it's empty, so it's not true :-))</span>
|
|
||||||
<span class="sd"> ssl = gui.CheckBoxField(label = _('Use SSL'), order = 3,</span>
|
|
||||||
<span class="sd"> tooltip = _('If checked, will use a ssl connection'))</span>
|
|
||||||
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">):</span>
|
|
||||||
<span class="nb">super</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">__class__</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="o">**</span><span class="n">options</span><span class="p">)</span>
|
|
||||||
<span class="bp">self</span><span class="o">.</span><span class="n">_type</span><span class="p">(</span><span class="n">gui</span><span class="o">.</span><span class="n">InputField</span><span class="o">.</span><span class="n">CHECKBOX_TYPE</span><span class="p">)</span>
|
|
||||||
|
|
||||||
<div class="viewcode-block" id="gui.CheckBoxField.isTrue"><a class="viewcode-back" href="../../../../api/modules/FormFields.html#uds.core.ui.UserInterface.gui.CheckBoxField.isTrue">[docs]</a> <span class="k">def</span> <span class="nf">isTrue</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> Checks that the value is true</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">value</span> <span class="o">==</span> <span class="s">'true'</span>
|
|
||||||
</div></div>
|
|
||||||
<div class="viewcode-block" id="gui.ChoiceField"><a class="viewcode-back" href="../../../../api/modules/FormFields.html#uds.core.ui.UserInterface.gui.ChoiceField">[docs]</a> <span class="k">class</span> <span class="nc">ChoiceField</span><span class="p">(</span><span class="n">InputField</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> This represents a simple combo box with single selection.</span>
|
|
||||||
|
|
||||||
<span class="sd"> The values of parameters are inherited from :py:class:`InputField`</span>
|
|
||||||
|
|
||||||
<span class="sd"> ChoiceField needs a function to provide values inside it.</span>
|
|
||||||
|
|
||||||
<span class="sd"> * We specify the values via "values" option this way:</span>
|
|
||||||
|
|
||||||
<span class="sd"> Example:</span>
|
|
||||||
|
|
||||||
<span class="sd"> .. code-block:: python</span>
|
|
||||||
|
|
||||||
<span class="sd"> choices = gui.ChoiceField(label="choices", values = [ {'id':'1',</span>
|
|
||||||
<span class="sd"> 'text':'Text 1'}, {'id':'xxx', 'text':'Text 2'}])</span>
|
|
||||||
|
|
||||||
<span class="sd"> You can specify a multi valuated field via id-values, or a</span>
|
|
||||||
<span class="sd"> single-valued field via id-value</span>
|
|
||||||
|
|
||||||
<span class="sd"> * We can override choice values at UserInterface derived class</span>
|
|
||||||
<span class="sd"> constructor or initGui using setValues</span>
|
|
||||||
|
|
||||||
<span class="sd"> There is an extra option available for this kind of field:</span>
|
|
||||||
|
|
||||||
<span class="sd"> fills: This options is a dictionary that contains this fields:</span>
|
|
||||||
<span class="sd"> * 'callbackName' : Callback name for invocation via the specific</span>
|
|
||||||
<span class="sd"> method xml-rpc. This name is a name we assign to this callback,</span>
|
|
||||||
<span class="sd"> and is used to locate the method when callback is invoked from</span>
|
|
||||||
<span class="sd"> admin interface.</span>
|
|
||||||
<span class="sd"> * 'function' : Function to execute.</span>
|
|
||||||
|
|
||||||
<span class="sd"> This funtion receives one parameter, that is a dictionary with</span>
|
|
||||||
<span class="sd"> all parameters (that, in time, are fields names) that we have</span>
|
|
||||||
<span class="sd"> requested.</span>
|
|
||||||
|
|
||||||
<span class="sd"> The expected return value for this callback is an array of</span>
|
|
||||||
<span class="sd"> dictionaries with fields and values to set, as</span>
|
|
||||||
<span class="sd"> example show below shows.</span>
|
|
||||||
<span class="sd"> * 'parameters' : Array of field names to pass back to server so</span>
|
|
||||||
<span class="sd"> it can obtain the results.</span>
|
|
||||||
|
|
||||||
<span class="sd"> Of course, this fields must be part of the module.</span>
|
|
||||||
|
|
||||||
<span class="sd"> Example:</span>
|
|
||||||
|
|
||||||
<span class="sd"> .. code-block:: python</span>
|
|
||||||
|
|
||||||
<span class="sd"> choice1 = gui.ChoiceField(label="Choice 1", values = ....,</span>
|
|
||||||
<span class="sd"> fills = { 'target': 'choice2', 'callback': fncValues,</span>
|
|
||||||
<span class="sd"> 'parameters': ['choice1', 'name']}</span>
|
|
||||||
<span class="sd"> )</span>
|
|
||||||
<span class="sd"> choice2 = ghui.ChoiceField(label="Choice 2")</span>
|
|
||||||
|
|
||||||
<span class="sd"> Here is a more detailed explanation, using the VC service module as</span>
|
|
||||||
<span class="sd"> sample.</span>
|
|
||||||
|
|
||||||
<span class="sd"> .. code-block:: python</span>
|
|
||||||
|
|
||||||
<span class="sd"> class VCHelpers(object):</span>
|
|
||||||
<span class="sd"> # ...</span>
|
|
||||||
<span class="sd"> # other stuff</span>
|
|
||||||
<span class="sd"> # ...</span>
|
|
||||||
<span class="sd"> @staticmethod</span>
|
|
||||||
<span class="sd"> def getMachines(parameters):</span>
|
|
||||||
<span class="sd"> # ...initialization and other stuff...</span>
|
|
||||||
<span class="sd"> if parameters['resourcePool'] != '':</span>
|
|
||||||
<span class="sd"> # ... do stuff ...</span>
|
|
||||||
<span class="sd"> data = [ { 'name' : 'machine', 'values' : 'xxxxxx' } ]</span>
|
|
||||||
<span class="sd"> return data</span>
|
|
||||||
|
|
||||||
<span class="sd"> class ModuleVC(services.Service)</span>
|
|
||||||
<span class="sd"> # ...</span>
|
|
||||||
<span class="sd"> # stuff</span>
|
|
||||||
<span class="sd"> # ...</span>
|
|
||||||
<span class="sd"> resourcePool = gui.ChoiceField(</span>
|
|
||||||
<span class="sd"> label=_("Resource Pool"), rdonly = False, order = 5,</span>
|
|
||||||
<span class="sd"> fills = {</span>
|
|
||||||
<span class="sd"> 'callbackName' : 'vcFillMachinesFromResource',</span>
|
|
||||||
<span class="sd"> 'function' : VCHelpers.getMachines,</span>
|
|
||||||
<span class="sd"> 'parameters' : ['vc', 'ev', 'resourcePool']</span>
|
|
||||||
<span class="sd"> },</span>
|
|
||||||
<span class="sd"> tooltip = _('Resource Pool containing base machine'),</span>
|
|
||||||
<span class="sd"> required = True</span>
|
|
||||||
<span class="sd"> )</span>
|
|
||||||
|
|
||||||
<span class="sd"> machine = gui.ChoiceField(label = _("Base Machine"), order = 6,</span>
|
|
||||||
<span class="sd"> tooltip = _('Base machine for this service'), required = True )</span>
|
|
||||||
|
|
||||||
<span class="sd"> vc = gui.HiddenField()</span>
|
|
||||||
<span class="sd"> ev = gui.HiddenField() # ....</span>
|
|
||||||
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">):</span>
|
|
||||||
<span class="nb">super</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">__class__</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="o">**</span><span class="n">options</span><span class="p">)</span>
|
|
||||||
<span class="bp">self</span><span class="o">.</span><span class="n">_data</span><span class="p">[</span><span class="s">'values'</span><span class="p">]</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'values'</span><span class="p">,</span> <span class="p">[])</span>
|
|
||||||
<span class="k">if</span> <span class="s">'fills'</span> <span class="ow">in</span> <span class="n">options</span><span class="p">:</span>
|
|
||||||
<span class="c"># Save fnc to register as callback</span>
|
|
||||||
<span class="n">fills</span> <span class="o">=</span> <span class="n">options</span><span class="p">[</span><span class="s">'fills'</span><span class="p">]</span>
|
|
||||||
<span class="n">fnc</span> <span class="o">=</span> <span class="n">fills</span><span class="p">[</span><span class="s">'function'</span><span class="p">]</span>
|
|
||||||
<span class="n">fills</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s">'function'</span><span class="p">)</span>
|
|
||||||
<span class="bp">self</span><span class="o">.</span><span class="n">_data</span><span class="p">[</span><span class="s">'fills'</span><span class="p">]</span> <span class="o">=</span> <span class="n">fills</span>
|
|
||||||
<span class="n">gui</span><span class="o">.</span><span class="n">callbacks</span><span class="p">[</span><span class="n">fills</span><span class="p">[</span><span class="s">'callbackName'</span><span class="p">]]</span> <span class="o">=</span> <span class="n">fnc</span>
|
|
||||||
<span class="bp">self</span><span class="o">.</span><span class="n">_type</span><span class="p">(</span><span class="n">gui</span><span class="o">.</span><span class="n">InputField</span><span class="o">.</span><span class="n">CHOICE_TYPE</span><span class="p">)</span>
|
|
||||||
|
|
||||||
<div class="viewcode-block" id="gui.ChoiceField.setValues"><a class="viewcode-back" href="../../../../api/modules/FormFields.html#uds.core.ui.UserInterface.gui.ChoiceField.setValues">[docs]</a> <span class="k">def</span> <span class="nf">setValues</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">values</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> Set the values for this choice field</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="bp">self</span><span class="o">.</span><span class="n">_data</span><span class="p">[</span><span class="s">'values'</span><span class="p">]</span> <span class="o">=</span> <span class="n">values</span>
|
|
||||||
</div></div>
|
|
||||||
<div class="viewcode-block" id="gui.MultiChoiceField"><a class="viewcode-back" href="../../../../api/modules/FormFields.html#uds.core.ui.UserInterface.gui.MultiChoiceField">[docs]</a> <span class="k">class</span> <span class="nc">MultiChoiceField</span><span class="p">(</span><span class="n">InputField</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> Multichoices are list of items that are multi-selectable.</span>
|
|
||||||
|
|
||||||
<span class="sd"> There is a new parameter here, not covered by InputField:</span>
|
|
||||||
<span class="sd"> * 'rows' to tell gui how many rows to display (the length of the</span>
|
|
||||||
<span class="sd"> displayable list)</span>
|
|
||||||
|
|
||||||
<span class="sd"> "defvalue" is expresed as a comma separated list of ids</span>
|
|
||||||
|
|
||||||
<span class="sd"> This class do not have callback support, as ChoiceField does.</span>
|
|
||||||
|
|
||||||
<span class="sd"> The values is an array of dictionaries, in the form [ { 'id' : 'a',</span>
|
|
||||||
<span class="sd"> 'text': b }, ... ]</span>
|
|
||||||
|
|
||||||
<span class="sd"> Example usage:</span>
|
|
||||||
|
|
||||||
<span class="sd"> .. code-block:: python</span>
|
|
||||||
|
|
||||||
<span class="sd"> # Declares a multiple choices field, with label "Datastores", that</span>
|
|
||||||
<span class="sd"> is editable, with 5 rows for displaying</span>
|
|
||||||
<span class="sd"> # data at most in user interface, 8th in order, that is required</span>
|
|
||||||
<span class="sd"> and has tooltip "Datastores where to put incrementals",</span>
|
|
||||||
<span class="sd"> # this field is required and has 2 selectable items: "datastore0"</span>
|
|
||||||
<span class="sd"> with id "0" and "datastore1" with id "1"</span>
|
|
||||||
<span class="sd"> datastores = gui.MultiChoiceField(label = _("Datastores"),</span>
|
|
||||||
<span class="sd"> rdonly = False, rows = 5, order = 8,</span>
|
|
||||||
<span class="sd"> tooltip = _('Datastores where to put incrementals'),</span>
|
|
||||||
<span class="sd"> required = True,</span>
|
|
||||||
<span class="sd"> values = [ {'id': '0', 'text': 'datastore0' },</span>
|
|
||||||
<span class="sd"> {'id': '1', 'text': 'datastore1' } ]</span>
|
|
||||||
<span class="sd"> )</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">):</span>
|
|
||||||
<span class="nb">super</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">__class__</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="o">**</span><span class="n">options</span><span class="p">)</span>
|
|
||||||
<span class="bp">self</span><span class="o">.</span><span class="n">_data</span><span class="p">[</span><span class="s">'values'</span><span class="p">]</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'values'</span><span class="p">,</span> <span class="p">[])</span>
|
|
||||||
<span class="bp">self</span><span class="o">.</span><span class="n">_data</span><span class="p">[</span><span class="s">'rows'</span><span class="p">]</span> <span class="o">=</span> <span class="n">options</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'rows'</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
|
|
||||||
<span class="bp">self</span><span class="o">.</span><span class="n">_type</span><span class="p">(</span><span class="n">gui</span><span class="o">.</span><span class="n">InputField</span><span class="o">.</span><span class="n">MULTI_CHOICE_TYPE</span><span class="p">)</span>
|
|
||||||
|
|
||||||
<div class="viewcode-block" id="gui.MultiChoiceField.setValues"><a class="viewcode-back" href="../../../../api/modules/FormFields.html#uds.core.ui.UserInterface.gui.MultiChoiceField.setValues">[docs]</a> <span class="k">def</span> <span class="nf">setValues</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">values</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> Set the values for this multi choice field</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="bp">self</span><span class="o">.</span><span class="n">_data</span><span class="p">[</span><span class="s">'values'</span><span class="p">]</span> <span class="o">=</span> <span class="n">values</span>
|
|
||||||
</div></div>
|
|
||||||
<div class="viewcode-block" id="gui.EditableList"><a class="viewcode-back" href="../../../../api/modules/FormFields.html#uds.core.ui.UserInterface.gui.EditableList">[docs]</a> <span class="k">class</span> <span class="nc">EditableList</span><span class="p">(</span><span class="n">InputField</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> Editables list are lists of editable elements (i.e., a list of IPs, macs,</span>
|
|
||||||
<span class="sd"> names, etcc) treated as simple strings with no id</span>
|
|
||||||
|
|
||||||
<span class="sd"> The struct used to pass values is an array of strings, i.e. ['1', '2',</span>
|
|
||||||
<span class="sd"> 'test', 'bebito', ...]</span>
|
|
||||||
|
|
||||||
<span class="sd"> This list don't have "selected" items, so its defvalue field is simply</span>
|
|
||||||
<span class="sd"> ignored.</span>
|
|
||||||
|
|
||||||
<span class="sd"> We only nee to pass in "label" and, maybe, "values" to set default</span>
|
|
||||||
<span class="sd"> content for the list.</span>
|
|
||||||
|
|
||||||
<span class="sd"> Keep in mind that this is an user editable list, so the user can insert</span>
|
|
||||||
<span class="sd"> values and/or import values from files, so</span>
|
|
||||||
<span class="sd"> by default it will probably have no content at all.</span>
|
|
||||||
|
|
||||||
<span class="sd"> Example usage:</span>
|
|
||||||
|
|
||||||
<span class="sd"> .. code-block:: python</span>
|
|
||||||
|
|
||||||
<span class="sd"> #</span>
|
|
||||||
<span class="sd"> ipList = gui.EditableList(label=_('List of IPS'))</span>
|
|
||||||
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
|
|
||||||
<span class="c"># : Constant for separating values at "value" method</span>
|
|
||||||
<span class="n">SEPARATOR</span> <span class="o">=</span> <span class="s">'</span><span class="se">\001</span><span class="s">'</span>
|
|
||||||
|
|
||||||
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">options</span><span class="p">):</span>
|
|
||||||
<span class="nb">super</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">__class__</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="o">**</span><span class="n">options</span><span class="p">)</span>
|
|
||||||
<span class="bp">self</span><span class="o">.</span><span class="n">_data</span><span class="p">[</span><span class="s">'values'</span><span class="p">]</span> <span class="o">=</span> <span class="n">gui</span><span class="o">.</span><span class="n">convertToList</span><span class="p">(</span><span class="n">options</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s">'values'</span><span class="p">,</span> <span class="p">[]))</span>
|
|
||||||
<span class="bp">self</span><span class="o">.</span><span class="n">_type</span><span class="p">(</span><span class="n">gui</span><span class="o">.</span><span class="n">InputField</span><span class="o">.</span><span class="n">EDITABLE_LIST</span><span class="p">)</span>
|
|
||||||
|
|
||||||
<span class="k">def</span> <span class="nf">_setValue</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">values</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> So we can override value setting at descendants</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="nb">super</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">__class__</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="n">_setValue</span><span class="p">(</span><span class="n">values</span><span class="p">)</span>
|
|
||||||
<span class="bp">self</span><span class="o">.</span><span class="n">_data</span><span class="p">[</span><span class="s">'values'</span><span class="p">]</span> <span class="o">=</span> <span class="n">gui</span><span class="o">.</span><span class="n">convertToList</span><span class="p">(</span><span class="n">values</span><span class="p">)</span>
|
|
||||||
|
|
||||||
</div></div>
|
|
||||||
<span class="k">class</span> <span class="nc">UserInterfaceType</span><span class="p">(</span><span class="nb">type</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> Metaclass definition for moving the user interface descriptions to a usable</span>
|
|
||||||
<span class="sd"> better place</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="k">def</span> <span class="nf">__new__</span><span class="p">(</span><span class="n">cls</span><span class="p">,</span> <span class="n">classname</span><span class="p">,</span> <span class="n">bases</span><span class="p">,</span> <span class="n">classDict</span><span class="p">):</span>
|
|
||||||
<span class="n">newClassDict</span> <span class="o">=</span> <span class="p">{}</span>
|
|
||||||
<span class="n">_gui</span> <span class="o">=</span> <span class="p">{}</span>
|
|
||||||
<span class="c"># We will keep a reference to gui elements also at _gui so we can access them easily</span>
|
|
||||||
<span class="k">for</span> <span class="n">attrName</span><span class="p">,</span> <span class="n">attr</span> <span class="ow">in</span> <span class="n">classDict</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
|
|
||||||
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">attr</span><span class="p">,</span> <span class="n">gui</span><span class="o">.</span><span class="n">InputField</span><span class="p">):</span>
|
|
||||||
<span class="n">_gui</span><span class="p">[</span><span class="n">attrName</span><span class="p">]</span> <span class="o">=</span> <span class="n">attr</span>
|
|
||||||
<span class="n">newClassDict</span><span class="p">[</span><span class="n">attrName</span><span class="p">]</span> <span class="o">=</span> <span class="n">attr</span>
|
|
||||||
<span class="n">newClassDict</span><span class="p">[</span><span class="s">'_gui'</span><span class="p">]</span> <span class="o">=</span> <span class="n">_gui</span>
|
|
||||||
<span class="k">return</span> <span class="nb">type</span><span class="o">.</span><span class="n">__new__</span><span class="p">(</span><span class="n">cls</span><span class="p">,</span> <span class="n">classname</span><span class="p">,</span> <span class="n">bases</span><span class="p">,</span> <span class="n">newClassDict</span><span class="p">)</span>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="viewcode-block" id="UserInterface"><a class="viewcode-back" href="../../../../api/modules/BaseModule.html#uds.core.ui.UserInterface.UserInterface">[docs]</a><span class="k">class</span> <span class="nc">UserInterface</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> This class provides the management for gui descriptions (user forms)</span>
|
|
||||||
|
|
||||||
<span class="sd"> Once a class is derived from this one, that class can contain Field</span>
|
|
||||||
<span class="sd"> Descriptions,</span>
|
|
||||||
<span class="sd"> that will be managed correctly.</span>
|
|
||||||
|
|
||||||
<span class="sd"> By default, the values passed to this class constructor are used to fill</span>
|
|
||||||
<span class="sd"> the gui form fields values.</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="n">__metaclass__</span> <span class="o">=</span> <span class="n">UserInterfaceType</span>
|
|
||||||
|
|
||||||
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">values</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
|
|
||||||
<span class="kn">import</span> <span class="nn">copy</span>
|
|
||||||
<span class="c"># : If there is an array of elements to initialize, simply try to store values on form fields</span>
|
|
||||||
<span class="c"># Generate a deep copy of inherited Gui, so each User Interface instance has its own "field" set, and do not share the "fielset" with others, what can be really dangerous</span>
|
|
||||||
<span class="c"># Till now, nothing bad happened cause there where being used "serialized", but this do not have to be this way</span>
|
|
||||||
<span class="bp">self</span><span class="o">.</span><span class="n">_gui</span> <span class="o">=</span> <span class="n">copy</span><span class="o">.</span><span class="n">deepcopy</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_gui</span><span class="p">)</span> <span class="c"># Ensure "gui" is our own instance, deep copied from base</span>
|
|
||||||
<span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">val</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_gui</span><span class="o">.</span><span class="n">iteritems</span><span class="p">():</span> <span class="c"># And refresg references to them</span>
|
|
||||||
<span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">val</span><span class="p">)</span>
|
|
||||||
|
|
||||||
<span class="k">if</span> <span class="n">values</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
|
|
||||||
<span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_gui</span><span class="o">.</span><span class="n">iteritems</span><span class="p">():</span>
|
|
||||||
<span class="k">if</span> <span class="n">k</span> <span class="ow">in</span> <span class="n">values</span><span class="p">:</span>
|
|
||||||
<span class="n">v</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="n">values</span><span class="p">[</span><span class="n">k</span><span class="p">]</span>
|
|
||||||
|
|
||||||
<div class="viewcode-block" id="UserInterface.initGui"><a class="viewcode-back" href="../../../../api/modules/BaseModule.html#uds.core.ui.UserInterface.UserInterface.initGui">[docs]</a> <span class="k">def</span> <span class="nf">initGui</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> This method gives the oportunity to initialize gui fields before they</span>
|
|
||||||
<span class="sd"> are send to administartion client.</span>
|
|
||||||
<span class="sd"> We need this because at initialization time we probably don't have the</span>
|
|
||||||
<span class="sd"> data for gui.</span>
|
|
||||||
|
|
||||||
<span class="sd"> :note: This method is used as a "trick" to allow to modify default form</span>
|
|
||||||
<span class="sd"> data for services. Services are child of Service Providers, and</span>
|
|
||||||
<span class="sd"> will probably need data from Provider to fill initial form data.</span>
|
|
||||||
<span class="sd"> The rest of modules will not use this, and this only will be used</span>
|
|
||||||
<span class="sd"> when the user requests a new service or wants to modify existing</span>
|
|
||||||
<span class="sd"> one.</span>
|
|
||||||
<span class="sd"> :note: There is a drawback of this, and it is that there is that this</span>
|
|
||||||
<span class="sd"> method will modify service default data. It will run fast (probably),</span>
|
|
||||||
<span class="sd"> but may happen that two services of same type are requested at same</span>
|
|
||||||
<span class="sd"> time, and returned data will be probable a nonsense. We will take care</span>
|
|
||||||
<span class="sd"> of this posibility in a near version...</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="k">pass</span>
|
|
||||||
</div>
|
|
||||||
<div class="viewcode-block" id="UserInterface.valuesDict"><a class="viewcode-back" href="../../../../api/modules/BaseModule.html#uds.core.ui.UserInterface.UserInterface.valuesDict">[docs]</a> <span class="k">def</span> <span class="nf">valuesDict</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> Returns own data needed for user interaction as a dict of key-names -></span>
|
|
||||||
<span class="sd"> values. The values returned must be strings.</span>
|
|
||||||
|
|
||||||
<span class="sd"> Example:</span>
|
|
||||||
<span class="sd"> we have 2 text field, first named "host" and second named "port",</span>
|
|
||||||
<span class="sd"> we can do something like this:</span>
|
|
||||||
|
|
||||||
<span class="sd"> .. code-block:: python</span>
|
|
||||||
|
|
||||||
<span class="sd"> return { 'host' : self.host, 'port' : self.port }</span>
|
|
||||||
|
|
||||||
<span class="sd"> (Just the reverse of :py:meth:`.__init__`, __init__ receives this</span>
|
|
||||||
<span class="sd"> dict, valuesDict must return the dict)</span>
|
|
||||||
|
|
||||||
<span class="sd"> Names must coincide with fields declared.</span>
|
|
||||||
|
|
||||||
<span class="sd"> Returns:</span>
|
|
||||||
<span class="sd"> Dictionary, associated with declared fields.</span>
|
|
||||||
<span class="sd"> Default implementation returns the values stored at the gui form</span>
|
|
||||||
<span class="sd"> fields declared.</span>
|
|
||||||
|
|
||||||
<span class="sd"> :note: By default, the provided method returns the correct values</span>
|
|
||||||
<span class="sd"> extracted from form fields</span>
|
|
||||||
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="n">dic</span> <span class="o">=</span> <span class="p">{}</span>
|
|
||||||
<span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_gui</span><span class="o">.</span><span class="n">iteritems</span><span class="p">():</span>
|
|
||||||
<span class="k">if</span> <span class="n">v</span><span class="o">.</span><span class="n">isType</span><span class="p">(</span><span class="n">gui</span><span class="o">.</span><span class="n">InputField</span><span class="o">.</span><span class="n">EDITABLE_LIST</span><span class="p">):</span>
|
|
||||||
<span class="n">dic</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">=</span> <span class="n">gui</span><span class="o">.</span><span class="n">convertToList</span><span class="p">(</span><span class="n">v</span><span class="o">.</span><span class="n">value</span><span class="p">)</span>
|
|
||||||
<span class="k">elif</span> <span class="n">v</span><span class="o">.</span><span class="n">isType</span><span class="p">(</span><span class="n">gui</span><span class="o">.</span><span class="n">InputField</span><span class="o">.</span><span class="n">MULTI_CHOICE_TYPE</span><span class="p">):</span>
|
|
||||||
<span class="n">dic</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">=</span> <span class="n">gui</span><span class="o">.</span><span class="n">convertToChoices</span><span class="p">(</span><span class="n">v</span><span class="o">.</span><span class="n">value</span><span class="p">)</span>
|
|
||||||
<span class="k">else</span><span class="p">:</span>
|
|
||||||
<span class="n">dic</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">=</span> <span class="n">v</span><span class="o">.</span><span class="n">value</span>
|
|
||||||
<span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">'Dict: {0}'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">dic</span><span class="p">))</span>
|
|
||||||
<span class="k">return</span> <span class="n">dic</span>
|
|
||||||
</div>
|
|
||||||
<div class="viewcode-block" id="UserInterface.serializeForm"><a class="viewcode-back" href="../../../../api/modules/BaseModule.html#uds.core.ui.UserInterface.UserInterface.serializeForm">[docs]</a> <span class="k">def</span> <span class="nf">serializeForm</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> All values stored at form fields are serialized and returned as a single</span>
|
|
||||||
<span class="sd"> string</span>
|
|
||||||
<span class="sd"> Separating char is</span>
|
|
||||||
|
|
||||||
<span class="sd"> The returned string is zipped and then converted to base 64</span>
|
|
||||||
|
|
||||||
<span class="sd"> Note: Hidens are not serialized, they are ignored</span>
|
|
||||||
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="n">arr</span> <span class="o">=</span> <span class="p">[]</span>
|
|
||||||
<span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_gui</span><span class="o">.</span><span class="n">iteritems</span><span class="p">():</span>
|
|
||||||
<span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">'serializing Key: {0}/{1}'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="o">.</span><span class="n">value</span><span class="p">))</span>
|
|
||||||
<span class="k">if</span> <span class="n">v</span><span class="o">.</span><span class="n">isType</span><span class="p">(</span><span class="n">gui</span><span class="o">.</span><span class="n">InputField</span><span class="o">.</span><span class="n">HIDDEN_TYPE</span><span class="p">)</span> <span class="ow">and</span> <span class="n">v</span><span class="o">.</span><span class="n">isSerializable</span><span class="p">()</span> <span class="ow">is</span> <span class="bp">False</span><span class="p">:</span>
|
|
||||||
<span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">'Field {0} is not serializable'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">k</span><span class="p">))</span>
|
|
||||||
<span class="k">continue</span>
|
|
||||||
<span class="k">if</span> <span class="n">v</span><span class="o">.</span><span class="n">isType</span><span class="p">(</span><span class="n">gui</span><span class="o">.</span><span class="n">InputField</span><span class="o">.</span><span class="n">EDITABLE_LIST</span><span class="p">)</span> <span class="ow">or</span> <span class="n">v</span><span class="o">.</span><span class="n">isType</span><span class="p">(</span><span class="n">gui</span><span class="o">.</span><span class="n">InputField</span><span class="o">.</span><span class="n">MULTI_CHOICE_TYPE</span><span class="p">):</span>
|
|
||||||
<span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">'Serializing value {0}'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">v</span><span class="o">.</span><span class="n">value</span><span class="p">))</span>
|
|
||||||
<span class="n">val</span> <span class="o">=</span> <span class="s">'</span><span class="se">\001</span><span class="s">'</span> <span class="o">+</span> <span class="n">cPickle</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="n">v</span><span class="o">.</span><span class="n">value</span><span class="p">)</span>
|
|
||||||
<span class="k">else</span><span class="p">:</span>
|
|
||||||
<span class="n">val</span> <span class="o">=</span> <span class="n">v</span><span class="o">.</span><span class="n">value</span>
|
|
||||||
<span class="k">if</span> <span class="n">val</span> <span class="ow">is</span> <span class="bp">True</span><span class="p">:</span>
|
|
||||||
<span class="n">val</span> <span class="o">=</span> <span class="n">gui</span><span class="o">.</span><span class="n">TRUE</span>
|
|
||||||
<span class="k">elif</span> <span class="n">val</span> <span class="ow">is</span> <span class="bp">False</span><span class="p">:</span>
|
|
||||||
<span class="n">val</span> <span class="o">=</span> <span class="n">gui</span><span class="o">.</span><span class="n">FALSE</span>
|
|
||||||
<span class="n">arr</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">k</span> <span class="o">+</span> <span class="s">'</span><span class="se">\003</span><span class="s">'</span> <span class="o">+</span> <span class="n">val</span><span class="p">)</span>
|
|
||||||
<span class="k">return</span> <span class="s">'</span><span class="se">\002</span><span class="s">'</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">arr</span><span class="p">)</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s">'zip'</span><span class="p">)</span>
|
|
||||||
</div>
|
|
||||||
<div class="viewcode-block" id="UserInterface.unserializeForm"><a class="viewcode-back" href="../../../../api/modules/BaseModule.html#uds.core.ui.UserInterface.UserInterface.unserializeForm">[docs]</a> <span class="k">def</span> <span class="nf">unserializeForm</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">values</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> This method unserializes the values previously obtained using</span>
|
|
||||||
<span class="sd"> :py:meth:`serializeForm`, and stores</span>
|
|
||||||
<span class="sd"> the valid values form form fileds inside its corresponding field</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="k">if</span> <span class="n">values</span> <span class="o">==</span> <span class="s">''</span><span class="p">:</span> <span class="c"># Has nothing</span>
|
|
||||||
<span class="k">return</span>
|
|
||||||
|
|
||||||
<span class="k">try</span><span class="p">:</span>
|
|
||||||
<span class="c"># Set all values to defaults ones</span>
|
|
||||||
<span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_gui</span><span class="o">.</span><span class="n">iterkeys</span><span class="p">():</span>
|
|
||||||
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_gui</span><span class="p">[</span><span class="n">k</span><span class="p">]</span><span class="o">.</span><span class="n">isType</span><span class="p">(</span><span class="n">gui</span><span class="o">.</span><span class="n">InputField</span><span class="o">.</span><span class="n">HIDDEN_TYPE</span><span class="p">)</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">_gui</span><span class="p">[</span><span class="n">k</span><span class="p">]</span><span class="o">.</span><span class="n">isSerializable</span><span class="p">()</span> <span class="ow">is</span> <span class="bp">False</span><span class="p">:</span>
|
|
||||||
<span class="c"># logger.debug('Field {0} is not unserializable'.format(k))</span>
|
|
||||||
<span class="k">continue</span>
|
|
||||||
<span class="bp">self</span><span class="o">.</span><span class="n">_gui</span><span class="p">[</span><span class="n">k</span><span class="p">]</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_gui</span><span class="p">[</span><span class="n">k</span><span class="p">]</span><span class="o">.</span><span class="n">defValue</span>
|
|
||||||
|
|
||||||
<span class="n">values</span> <span class="o">=</span> <span class="n">values</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s">'zip'</span><span class="p">)</span>
|
|
||||||
<span class="k">if</span> <span class="n">values</span> <span class="o">==</span> <span class="s">''</span><span class="p">:</span> <span class="c"># Has nothing</span>
|
|
||||||
<span class="k">return</span>
|
|
||||||
|
|
||||||
<span class="k">for</span> <span class="n">txt</span> <span class="ow">in</span> <span class="n">values</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">'</span><span class="se">\002</span><span class="s">'</span><span class="p">):</span>
|
|
||||||
<span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="o">=</span> <span class="n">txt</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">'</span><span class="se">\003</span><span class="s">'</span><span class="p">)</span>
|
|
||||||
<span class="k">if</span> <span class="n">k</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_gui</span><span class="p">:</span>
|
|
||||||
<span class="k">try</span><span class="p">:</span>
|
|
||||||
<span class="k">if</span> <span class="n">v</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s">'</span><span class="se">\001</span><span class="s">'</span><span class="p">:</span>
|
|
||||||
<span class="n">val</span> <span class="o">=</span> <span class="n">cPickle</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="n">v</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">))</span>
|
|
||||||
<span class="k">else</span><span class="p">:</span>
|
|
||||||
<span class="n">val</span> <span class="o">=</span> <span class="n">v</span>
|
|
||||||
<span class="k">except</span><span class="p">:</span>
|
|
||||||
<span class="n">val</span> <span class="o">=</span> <span class="s">''</span>
|
|
||||||
<span class="bp">self</span><span class="o">.</span><span class="n">_gui</span><span class="p">[</span><span class="n">k</span><span class="p">]</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="n">val</span>
|
|
||||||
<span class="c"># logger.debug('Value for {0}:{1}'.format(k, val))</span>
|
|
||||||
<span class="k">except</span><span class="p">:</span>
|
|
||||||
<span class="c"># Values can contain invalid characters, so we log every single char</span>
|
|
||||||
<span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s">'Invalid serialization data on {0} {1}'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">values</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s">'hex'</span><span class="p">)))</span>
|
|
||||||
</div>
|
|
||||||
<span class="nd">@classmethod</span>
|
|
||||||
<div class="viewcode-block" id="UserInterface.guiDescription"><a class="viewcode-back" href="../../../../api/modules/BaseModule.html#uds.core.ui.UserInterface.UserInterface.guiDescription">[docs]</a> <span class="k">def</span> <span class="nf">guiDescription</span><span class="p">(</span><span class="n">cls</span><span class="p">,</span> <span class="n">obj</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd"> This simple method generates the gui description needed by the</span>
|
|
||||||
<span class="sd"> administration client, so it can</span>
|
|
||||||
<span class="sd"> represent it at user interface and manage it.</span>
|
|
||||||
|
|
||||||
<span class="sd"> Args:</span>
|
|
||||||
<span class="sd"> object: If not none, object that will get its "initGui" invoked</span>
|
|
||||||
<span class="sd"> This will only happen (not to be None) in Services.</span>
|
|
||||||
<span class="sd"> '''</span>
|
|
||||||
<span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">'Active languaje for gui translation: {0}'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">get_language</span><span class="p">()))</span>
|
|
||||||
<span class="n">gui</span> <span class="o">=</span> <span class="n">cls</span>
|
|
||||||
<span class="k">if</span> <span class="n">obj</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
|
|
||||||
<span class="n">obj</span><span class="o">.</span><span class="n">initGui</span><span class="p">()</span> <span class="c"># We give the "oportunity" to fill necesary gui data before providing it to client</span>
|
|
||||||
<span class="n">gui</span> <span class="o">=</span> <span class="n">obj</span>
|
|
||||||
|
|
||||||
<span class="n">res</span> <span class="o">=</span> <span class="p">[]</span>
|
|
||||||
<span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">val</span> <span class="ow">in</span> <span class="n">gui</span><span class="o">.</span><span class="n">_gui</span><span class="o">.</span><span class="n">iteritems</span><span class="p">():</span>
|
|
||||||
<span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">'{0} ### {1}'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">val</span><span class="p">))</span>
|
|
||||||
<span class="n">res</span><span class="o">.</span><span class="n">append</span><span class="p">({</span><span class="s">'name'</span><span class="p">:</span> <span class="n">key</span><span class="p">,</span> <span class="s">'gui'</span><span class="p">:</span> <span class="n">val</span><span class="o">.</span><span class="n">guiDescription</span><span class="p">(),</span> <span class="s">'value'</span><span class="p">:</span> <span class="s">''</span><span class="p">})</span>
|
|
||||||
|
|
||||||
<span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">'>>>>>>>>>>>> Gui Description: {0} -- {1}'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">res</span><span class="p">))</span>
|
|
||||||
<span class="k">return</span> <span class="n">res</span></div></div>
|
|
||||||
</pre></div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="clearer"></div>
|
|
||||||
</div>
|
|
||||||
<div class="related">
|
|
||||||
<h3>Navigation</h3>
|
|
||||||
<ul>
|
|
||||||
<li class="right" style="margin-right: 10px">
|
|
||||||
<a href="../../../../genindex.html" title="General Index"
|
|
||||||
>index</a></li>
|
|
||||||
<li class="right" >
|
|
||||||
<a href="../../../../py-modindex.html" title="Python Module Index"
|
|
||||||
>modules</a> |</li>
|
|
||||||
<li><a href="../../../../index.html">UDS 1.0 documentation</a> »</li>
|
|
||||||
<li><a href="../../../index.html" >Module code</a> »</li>
|
|
||||||
<li><a href="../../core.html" >uds.core</a> »</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="footer">
|
|
||||||
© Copyright 2012, Virtual Cable S.L.U..
|
|
||||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.2.2.
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,183 +0,0 @@
|
|||||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
|
||||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
||||||
|
|
||||||
|
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
||||||
<head>
|
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
||||||
|
|
||||||
<title>uds.models — UDS 1.0 documentation</title>
|
|
||||||
|
|
||||||
<link rel="stylesheet" href="../../_static/sphinxdoc.css" type="text/css" />
|
|
||||||
<link rel="stylesheet" href="../../_static/pygments.css" type="text/css" />
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
|
||||||
var DOCUMENTATION_OPTIONS = {
|
|
||||||
URL_ROOT: '../../',
|
|
||||||
VERSION: '1.0',
|
|
||||||
COLLAPSE_INDEX: false,
|
|
||||||
FILE_SUFFIX: '.html',
|
|
||||||
HAS_SOURCE: true
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<script type="text/javascript" src="../../_static/jquery.js"></script>
|
|
||||||
<script type="text/javascript" src="../../_static/underscore.js"></script>
|
|
||||||
<script type="text/javascript" src="../../_static/doctools.js"></script>
|
|
||||||
<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
|
|
||||||
<link rel="top" title="UDS 1.0 documentation" href="../../index.html" />
|
|
||||||
<link rel="up" title="Module code" href="../index.html" />
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="related">
|
|
||||||
<h3>Navigation</h3>
|
|
||||||
<ul>
|
|
||||||
<li class="right" style="margin-right: 10px">
|
|
||||||
<a href="../../genindex.html" title="General Index"
|
|
||||||
accesskey="I">index</a></li>
|
|
||||||
<li class="right" >
|
|
||||||
<a href="../../py-modindex.html" title="Python Module Index"
|
|
||||||
>modules</a> |</li>
|
|
||||||
<li><a href="../../index.html">UDS 1.0 documentation</a> »</li>
|
|
||||||
<li><a href="../index.html" accesskey="U">Module code</a> »</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="sphinxsidebar">
|
|
||||||
<div class="sphinxsidebarwrapper">
|
|
||||||
<div id="searchbox" style="display: none">
|
|
||||||
<h3>Quick search</h3>
|
|
||||||
<form class="search" action="../../search.html" method="get">
|
|
||||||
<input type="text" name="q" />
|
|
||||||
<input type="submit" value="Go" />
|
|
||||||
<input type="hidden" name="check_keywords" value="yes" />
|
|
||||||
<input type="hidden" name="area" value="default" />
|
|
||||||
</form>
|
|
||||||
<p class="searchtip" style="font-size: 90%">
|
|
||||||
Enter search terms or a module, class or function name.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="document">
|
|
||||||
<div class="documentwrapper">
|
|
||||||
<div class="bodywrapper">
|
|
||||||
<div class="body">
|
|
||||||
|
|
||||||
<h1>Source code for uds.models</h1><div class="highlight"><pre>
|
|
||||||
<span class="c"># -*- coding: utf-8 -*-</span>
|
|
||||||
|
|
||||||
<span class="c">#</span>
|
|
||||||
<span class="c"># Copyright (c) 2012 Virtual Cable S.L.</span>
|
|
||||||
<span class="c"># All rights reserved.</span>
|
|
||||||
<span class="c">#</span>
|
|
||||||
<span class="c"># Redistribution and use in source and binary forms, with or without modification,</span>
|
|
||||||
<span class="c"># are permitted provided that the following conditions are met:</span>
|
|
||||||
<span class="c">#</span>
|
|
||||||
<span class="c"># * Redistributions of source code must retain the above copyright notice,</span>
|
|
||||||
<span class="c"># this list of conditions and the following disclaimer.</span>
|
|
||||||
<span class="c"># * Redistributions in binary form must reproduce the above copyright notice,</span>
|
|
||||||
<span class="c"># this list of conditions and the following disclaimer in the documentation</span>
|
|
||||||
<span class="c"># and/or other materials provided with the distribution.</span>
|
|
||||||
<span class="c"># * Neither the name of Virtual Cable S.L. nor the names of its contributors</span>
|
|
||||||
<span class="c"># may be used to endorse or promote products derived from this software</span>
|
|
||||||
<span class="c"># without specific prior written permission.</span>
|
|
||||||
<span class="c">#</span>
|
|
||||||
<span class="c"># THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"</span>
|
|
||||||
<span class="c"># AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE</span>
|
|
||||||
<span class="c"># IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE</span>
|
|
||||||
<span class="c"># DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE</span>
|
|
||||||
<span class="c"># FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL</span>
|
|
||||||
<span class="c"># DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR</span>
|
|
||||||
<span class="c"># SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER</span>
|
|
||||||
<span class="c"># CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,</span>
|
|
||||||
<span class="c"># OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE</span>
|
|
||||||
<span class="c"># OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</span>
|
|
||||||
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
<span class="sd">.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com</span>
|
|
||||||
<span class="sd">'''</span>
|
|
||||||
|
|
||||||
<span class="kn">from</span> <span class="nn">__future__</span> <span class="kn">import</span> <span class="n">unicode_literals</span>
|
|
||||||
|
|
||||||
<span class="n">__updated__</span> <span class="o">=</span> <span class="s">'2014-04-24'</span>
|
|
||||||
|
|
||||||
<span class="kn">import</span> <span class="nn">logging</span>
|
|
||||||
|
|
||||||
<span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="n">__name__</span><span class="p">)</span>
|
|
||||||
|
|
||||||
|
|
||||||
<span class="c"># Utility</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">uds.models.Util</span> <span class="kn">import</span> <span class="n">getSqlDatetime</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">uds.models.Util</span> <span class="kn">import</span> <span class="n">optimizeTable</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">uds.models.Util</span> <span class="kn">import</span> <span class="n">NEVER</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">uds.models.Util</span> <span class="kn">import</span> <span class="n">NEVER_UNIX</span>
|
|
||||||
|
|
||||||
<span class="c"># Services</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">uds.models.Provider</span> <span class="kn">import</span> <span class="n">Provider</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">uds.models.Service</span> <span class="kn">import</span> <span class="n">Service</span>
|
|
||||||
|
|
||||||
<span class="c"># Os managers</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">uds.models.OSManager</span> <span class="kn">import</span> <span class="n">OSManager</span>
|
|
||||||
|
|
||||||
<span class="c"># Transports</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">uds.models.Transport</span> <span class="kn">import</span> <span class="n">Transport</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">uds.models.Network</span> <span class="kn">import</span> <span class="n">Network</span>
|
|
||||||
|
|
||||||
|
|
||||||
<span class="c"># Authenticators</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">uds.models.Authenticator</span> <span class="kn">import</span> <span class="n">Authenticator</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">uds.models.User</span> <span class="kn">import</span> <span class="n">User</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">uds.models.UserPreference</span> <span class="kn">import</span> <span class="n">UserPreference</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">uds.models.Group</span> <span class="kn">import</span> <span class="n">Group</span>
|
|
||||||
|
|
||||||
|
|
||||||
<span class="c"># Provisioned services</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">uds.models.ServicesPool</span> <span class="kn">import</span> <span class="n">DeployedService</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">uds.models.ServicesPoolPublication</span> <span class="kn">import</span> <span class="n">DeployedServicePublication</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">uds.models.UserService</span> <span class="kn">import</span> <span class="n">UserService</span>
|
|
||||||
|
|
||||||
<span class="c"># Especific log information for an user service</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">uds.models.Log</span> <span class="kn">import</span> <span class="n">Log</span>
|
|
||||||
|
|
||||||
<span class="c"># Stats</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">uds.models.StatsCounters</span> <span class="kn">import</span> <span class="n">StatsCounters</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">uds.models.StatsEvents</span> <span class="kn">import</span> <span class="n">StatsEvents</span>
|
|
||||||
|
|
||||||
|
|
||||||
<span class="c"># General utility models, such as a database cache (for caching remote content of slow connections to external services providers for example)</span>
|
|
||||||
<span class="c"># We could use django cache (and maybe we do it in a near future), but we need to clean up things when objecs owning them are deleted</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">uds.models.Cache</span> <span class="kn">import</span> <span class="n">Cache</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">uds.models.Config</span> <span class="kn">import</span> <span class="n">Config</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">uds.models.Storage</span> <span class="kn">import</span> <span class="n">Storage</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">uds.models.UniqueId</span> <span class="kn">import</span> <span class="n">UniqueId</span>
|
|
||||||
|
|
||||||
<span class="c"># Workers/Schedulers related</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">uds.models.Scheduler</span> <span class="kn">import</span> <span class="n">Scheduler</span>
|
|
||||||
<span class="kn">from</span> <span class="nn">uds.models.DelayedTask</span> <span class="kn">import</span> <span class="n">DelayedTask</span>
|
|
||||||
</pre></div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="clearer"></div>
|
|
||||||
</div>
|
|
||||||
<div class="related">
|
|
||||||
<h3>Navigation</h3>
|
|
||||||
<ul>
|
|
||||||
<li class="right" style="margin-right: 10px">
|
|
||||||
<a href="../../genindex.html" title="General Index"
|
|
||||||
>index</a></li>
|
|
||||||
<li class="right" >
|
|
||||||
<a href="../../py-modindex.html" title="Python Module Index"
|
|
||||||
>modules</a> |</li>
|
|
||||||
<li><a href="../../index.html">UDS 1.0 documentation</a> »</li>
|
|
||||||
<li><a href="../index.html" >Module code</a> »</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="footer">
|
|
||||||
© Copyright 2012, Virtual Cable S.L.U..
|
|
||||||
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.2.2.
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,9 +0,0 @@
|
|||||||
==============
|
|
||||||
UDS's core API
|
|
||||||
==============
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
|
|
||||||
models
|
|
||||||
modules
|
|
||||||
/development/samples/samples
|
|
@ -1,24 +0,0 @@
|
|||||||
===================
|
|
||||||
UDS Database Models
|
|
||||||
===================
|
|
||||||
|
|
||||||
This section describes de models used in UDS.
|
|
||||||
|
|
||||||
The models described here are implemented using Django models, so you can get more
|
|
||||||
info about Django models functionalty at `Django project website <http://www.djangoproject.com/>`_
|
|
||||||
|
|
||||||
The function of the models inside UDS is to provide the persistence needed by
|
|
||||||
the core and by other utility classes that are provided, such as a Cache, Storage
|
|
||||||
or unique IDs.
|
|
||||||
|
|
||||||
Right now the models are used all over UDS, but with time we will limit the use
|
|
||||||
of this models to be done through managers or utility clases designed for that
|
|
||||||
purpose.
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
|
|
||||||
models/services
|
|
||||||
models/authentication
|
|
||||||
models/transport
|
|
||||||
models/other
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
|||||||
=============================
|
|
||||||
Authentication Related models
|
|
||||||
=============================
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: 2
|
|
||||||
|
|
||||||
.. module:: uds.models
|
|
||||||
|
|
||||||
.. autoclass:: Authenticator
|
|
||||||
:members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
.. autoclass:: User
|
|
||||||
:members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
.. autoclass:: Group
|
|
||||||
:members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
.. autoclass:: UserPreference
|
|
||||||
:members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
|||||||
============
|
|
||||||
Other models
|
|
||||||
============
|
|
||||||
|
|
||||||
Environment related
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
.. module:: uds.models
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: 2
|
|
||||||
|
|
||||||
.. autoclass:: Cache
|
|
||||||
:members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
.. autoclass:: Storage
|
|
||||||
:members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
.. autoclass:: UniqueId
|
|
||||||
:members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
Module related
|
|
||||||
--------------
|
|
||||||
|
|
||||||
.. autoclass:: Config
|
|
||||||
:members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
Scheduling and background workers related
|
|
||||||
-----------------------------------------
|
|
||||||
|
|
||||||
.. autoclass:: Scheduler
|
|
||||||
:members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
.. autoclass:: DelayedTask
|
|
||||||
:members:
|
|
||||||
:show-inheritance:
|
|
@ -1,33 +0,0 @@
|
|||||||
======================
|
|
||||||
Service Related models
|
|
||||||
======================
|
|
||||||
|
|
||||||
This models takes cares of persistence of the Services and its associated elements.
|
|
||||||
|
|
||||||
DESCRIBE HIEARARCHY HERE
|
|
||||||
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: 2
|
|
||||||
|
|
||||||
.. module:: uds.models
|
|
||||||
|
|
||||||
.. autoclass:: Provider
|
|
||||||
:members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
.. autoclass:: Service
|
|
||||||
:members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
.. autoclass:: DeployedService
|
|
||||||
:members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
.. autoclass:: DeployedServicePublication
|
|
||||||
:members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
.. autoclass:: UserService
|
|
||||||
:members:
|
|
||||||
:show-inheritance:
|
|
@ -1,18 +0,0 @@
|
|||||||
========================
|
|
||||||
Transport Related models
|
|
||||||
========================
|
|
||||||
.. toctree::
|
|
||||||
:maxdepth: 2
|
|
||||||
|
|
||||||
.. module:: uds.models
|
|
||||||
|
|
||||||
.. autoclass:: Transport
|
|
||||||
:members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
.. autoclass:: Network
|
|
||||||
:members:
|
|
||||||
:show-inheritance:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
|||||||
===========
|
|
||||||
UDS Modules
|
|
||||||
===========
|
|
||||||
|
|
||||||
|
|
||||||
Modules are the basic component of plugin architecture of UDS.
|
|
||||||
|
|
||||||
As so, they are spreadly covered here, and with
|
|
||||||
:doc:`samples </development/samples/samples>` must give enough information for
|
|
||||||
allowing anyone to develop their own modules.
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
|
|
||||||
modules/BaseModule
|
|
||||||
modules/FormFields
|
|
||||||
modules/ServiceModules
|
|
||||||
modules/AuthenticatorModule
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
|||||||
=====================
|
|
||||||
Authenticator Modules
|
|
||||||
=====================
|
|
||||||
|
|
||||||
Authenticator modules are responsible of providing the user authentication
|
|
||||||
part inside UDS.
|
|
||||||
|
|
||||||
They are composed of a package where it is provided and, at least, the following
|
|
||||||
elements:
|
|
||||||
|
|
||||||
* One icon for administration interface representation. Icon is png file of
|
|
||||||
16x16.
|
|
||||||
* One class, derived from uds.core.auths.Authenticator, providing the needed
|
|
||||||
logic for that authenticator.
|
|
||||||
* Registration of the class inside uds at package's __init__.
|
|
||||||
|
|
||||||
All packages included inside uds.auths will automatically be imported, but
|
|
||||||
the authenticators needs to register as valid authenticators, and the best place
|
|
||||||
to do that is at the authenticator's package __init__.
|
|
||||||
|
|
||||||
The best way to understand what you need to create your own authenticator,
|
|
||||||
is to look at :doc:`modules samples </development/samples/samples>`
|
|
||||||
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
|
|
||||||
auths/Authenticator
|
|
@ -1,53 +0,0 @@
|
|||||||
===========
|
|
||||||
Base Module
|
|
||||||
===========
|
|
||||||
|
|
||||||
The Base module is the base class used for all modules of UDS.
|
|
||||||
|
|
||||||
In order to deveplop an UDS Module, there is a number of basic methods that you must provide.
|
|
||||||
|
|
||||||
There are the clases that are base of BaseModule, that are:
|
|
||||||
* BaseModule_
|
|
||||||
* Environmentable_
|
|
||||||
* Serializable_
|
|
||||||
* UserInterface_
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
|
|
||||||
BaseModule
|
|
||||||
----------
|
|
||||||
|
|
||||||
.. module:: uds.core
|
|
||||||
|
|
||||||
.. autoclass:: Module
|
|
||||||
:members:
|
|
||||||
|
|
||||||
Environmentable
|
|
||||||
---------------
|
|
||||||
|
|
||||||
.. autoclass:: Environmentable
|
|
||||||
:members:
|
|
||||||
|
|
||||||
|
|
||||||
Serializable
|
|
||||||
------------
|
|
||||||
|
|
||||||
.. autoclass:: Serializable
|
|
||||||
:members:
|
|
||||||
|
|
||||||
|
|
||||||
UserInterface
|
|
||||||
-------------
|
|
||||||
|
|
||||||
UserInterface is the class responsible for managing the Field Descriptions of modules.
|
|
||||||
|
|
||||||
This fields descriptions are intended for allowing an easy exposition of configuration form via the
|
|
||||||
administration interface.
|
|
||||||
|
|
||||||
You can obtain more information about user interface fields at :doc:`User interface fields types <FormFields>`.
|
|
||||||
|
|
||||||
.. module:: uds.core.ui.UserInterface
|
|
||||||
|
|
||||||
.. autoclass:: UserInterface
|
|
||||||
:members:
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
|||||||
Form Fields
|
|
||||||
===========
|
|
||||||
|
|
||||||
Form Fields are utility clases provided for allowing easy communication of modules
|
|
||||||
and administration interface.
|
|
||||||
|
|
||||||
It helps to define the administration level forms that will be used to manage
|
|
||||||
different modules (service providers, services, authenticators, transports, ...)
|
|
||||||
|
|
||||||
All modules that needs to be presented to admin users, use UserInterface as one
|
|
||||||
of their base class.
|
|
||||||
|
|
||||||
Think that not all interfaces needed by different modules need a direct representation
|
|
||||||
at administration interface level, (for example, UserDeployment do not need to be
|
|
||||||
managed by administrators, nor publications, both corresponding to service modules).
|
|
||||||
|
|
||||||
.. module:: uds.core.ui.UserInterface
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
|
|
||||||
|
|
||||||
The types of fields provided are:
|
|
||||||
* :py:class:`gui.TextField`
|
|
||||||
* :py:class:`gui.NumericField`
|
|
||||||
* :py:class:`gui.PasswordField`
|
|
||||||
* :py:class:`gui.HiddenField`
|
|
||||||
* :py:class:`gui.CheckBoxField`
|
|
||||||
* :py:class:`gui.ChoiceField`
|
|
||||||
* :py:class:`gui.MultiChoiceField`
|
|
||||||
* :py:class:`gui.EditableList`
|
|
||||||
|
|
||||||
.. autoclass:: gui
|
|
||||||
:members: InputField, TextField, NumericField, PasswordField, HiddenField, CheckBoxField, ChoiceField, MultiChoiceField, EditableList
|
|
@ -1,53 +0,0 @@
|
|||||||
===============
|
|
||||||
Service Modules
|
|
||||||
===============
|
|
||||||
|
|
||||||
Service modules are responsible for giving the user consumable ip services for
|
|
||||||
users.
|
|
||||||
|
|
||||||
They are composed of a package where it is provided, at least, the following
|
|
||||||
elements:
|
|
||||||
|
|
||||||
* One icon for administration interface representation. Icon is png file of
|
|
||||||
16x16.
|
|
||||||
* A Full tree of classes, derived from interfaces (descrived below)
|
|
||||||
* Registration of the class inside UDS at package's __init__.
|
|
||||||
|
|
||||||
All packages included inside uds.services will automatically be imported, but
|
|
||||||
the service providers (root of service trees) needs to register as valid
|
|
||||||
providers, and the best place to do that is at the authenticator's package __init__.
|
|
||||||
|
|
||||||
the Full tree of classes needed by the service modules are:
|
|
||||||
|
|
||||||
* **Provider**: This is the root tree of any service. It represents an agrupation
|
|
||||||
of services under the same root. As sample, a service provider can be an
|
|
||||||
Open nebula server, an VC, or whataver is a common root for a number of services.
|
|
||||||
* **Service**: This is the representation of what a service will give to an user.
|
|
||||||
As such, this is not what the user will consume, but this is more the definition
|
|
||||||
of what the user will consume. Before assigning a service to an user, the admin
|
|
||||||
will need to declare a "Deployed Service", that is a definition, using this service
|
|
||||||
an a number of other modules, of what the user will consume. Inside this service
|
|
||||||
we need to provide the information needed for deploying an user consumable item,
|
|
||||||
such as if it needs to be "prepared", if it supports cache, if it must be assigned
|
|
||||||
to an user "manually", and all the custom data that the user deployments and publications
|
|
||||||
will need.
|
|
||||||
* **Publication**. Some services, before being assigned to users, needs some kind of
|
|
||||||
preparation. This process of preparation is called here "publication". The service
|
|
||||||
itself will declare if it needs a publication and, if needed, who is responsible of
|
|
||||||
that. Services with needed publication will use this kind of class to provide
|
|
||||||
such preparation.
|
|
||||||
* **User Deployment**. This is what will provide the final user consumable service.
|
|
||||||
The user deployment is the last responsible for, using the provided service
|
|
||||||
and provided publication (if needed), to create the elements that the user will
|
|
||||||
consume.
|
|
||||||
|
|
||||||
The best way to understand what you need to create your own services,
|
|
||||||
is to look at :doc:`modules samples </development/samples/samples>`
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
|
|
||||||
services/Provider
|
|
||||||
services/Service
|
|
||||||
services/Publication
|
|
||||||
services/UserDeployment
|
|
||||||
services/Exceptions
|
|
@ -1,15 +0,0 @@
|
|||||||
=======================
|
|
||||||
Authenticator Interface
|
|
||||||
=======================
|
|
||||||
|
|
||||||
The authenticator class is in fact an interface. UDS authenticators must derive
|
|
||||||
from this, and must provide the logic so UDS can manage the users and groups that
|
|
||||||
an authenticator provides.
|
|
||||||
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
|
|
||||||
.. module:: uds.core.auths
|
|
||||||
|
|
||||||
.. autoclass:: Authenticator
|
|
||||||
:members:
|
|
@ -1,9 +0,0 @@
|
|||||||
==================
|
|
||||||
Service Exceptions
|
|
||||||
==================
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
|
|
||||||
.. automodule:: uds.core.services.Exceptions
|
|
||||||
:members:
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
|||||||
==================
|
|
||||||
Provider interface
|
|
||||||
==================
|
|
||||||
|
|
||||||
The provider class is the root class of the module. It keeps the common information
|
|
||||||
needed by all services provided by this "provider".
|
|
||||||
|
|
||||||
Think about a provider as the class that will declare all stuff neded by core and
|
|
||||||
child services to provide and administrator user a way to create services to be
|
|
||||||
consumed by users.
|
|
||||||
|
|
||||||
One good example is a Virtualization server. Here we keep information about that
|
|
||||||
server (ip address, protocol, ....) and services provided by that "provider" will
|
|
||||||
make use of that information to make the administrator not provide it once an again
|
|
||||||
for every service we put on that virtualization server.
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
|
|
||||||
.. module:: uds.core.services
|
|
||||||
|
|
||||||
For a detailed example of a service provider, you can see the provided
|
|
||||||
:doc:`provider sample </development/samples/services/Provider>`
|
|
||||||
|
|
||||||
.. autoclass:: ServiceProvider
|
|
||||||
:members:
|
|
||||||
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
|||||||
=====================
|
|
||||||
Publication interface
|
|
||||||
=====================
|
|
||||||
|
|
||||||
The publication class is in fact an interface. It represents, in those case that
|
|
||||||
a service needs the preparation, the logic for that preparation.
|
|
||||||
|
|
||||||
So the publication class is responsible of doing whatever is needed to get the
|
|
||||||
deployed service (that is the compound of a service, an os manager, transports
|
|
||||||
and authenticators) ready for deploying user consumables.
|
|
||||||
|
|
||||||
Note that not all services needs to implement this class, only in those case
|
|
||||||
where that service declares that a publication is needed.
|
|
||||||
|
|
||||||
|
|
||||||
As functional sample of a publication, imagine that we want to assing KVM COW
|
|
||||||
machines to users. The publication class can make a clone of the base machine
|
|
||||||
(that the service itself has taken note of which one is), and then the COWs will
|
|
||||||
be created from this cloned machine.
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
|
|
||||||
.. module:: uds.core.services
|
|
||||||
|
|
||||||
For a detailed example of a service provider, you can see the provided
|
|
||||||
:doc:`publication sample </development/samples/services/Publication>`
|
|
||||||
|
|
||||||
.. autoclass:: Publication
|
|
||||||
:members:
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
|||||||
=================
|
|
||||||
Service interface
|
|
||||||
=================
|
|
||||||
|
|
||||||
The service class is in fact an interface. It represents the base for all user
|
|
||||||
deployments (that is, consumable user services) that will be provided.
|
|
||||||
|
|
||||||
As such, the service is responsible for keeping the information that, at deployments,
|
|
||||||
will be neded by provided user consumable services.
|
|
||||||
|
|
||||||
A good sample of a service can be a KVM machine that will be copied COW and that COWs
|
|
||||||
will be assigned to users. In that case, we will collect which machine will be copied,
|
|
||||||
where it is to be copied, an a few more params that the user deployments will need.
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
|
|
||||||
.. module:: uds.core.services
|
|
||||||
|
|
||||||
For a detailed example of a service provider, you can see the provided
|
|
||||||
:doc:`service sample </development/samples/services/Service>`
|
|
||||||
|
|
||||||
.. autoclass:: Service
|
|
||||||
:members:
|
|
||||||
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
|||||||
========================
|
|
||||||
UserDeployment interface
|
|
||||||
========================
|
|
||||||
|
|
||||||
The user deployment class is in fact an interface. It represents the final consumable
|
|
||||||
that will be assigned to an user, and, as such, it must provide some mechanisms to
|
|
||||||
allow core to manage those consumables.
|
|
||||||
|
|
||||||
A good sample of an user deployment can be a KVM Virtual Machine, cloned COW from
|
|
||||||
another, and assigned to an user.
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
|
|
||||||
.. module:: uds.core.services
|
|
||||||
|
|
||||||
For detailed examples of a couple of user deployments, you can see the provided
|
|
||||||
:doc:`service sample </development/samples/services/DeployedServiceOne>` and
|
|
||||||
:doc:`service sample </development/samples/services/DeployedServiceTwo>`
|
|
||||||
|
|
||||||
.. autoclass:: UserDeployment
|
|
||||||
:members:
|
|
||||||
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
|||||||
==================
|
|
||||||
UDS's architecture
|
|
||||||
==================
|
|
||||||
|
|
||||||
This section covers the current UDS Arquiceture & diagrams.
|
|
||||||
|
|
||||||
UDS is built on the Django web framework, which itself is
|
|
||||||
built on Python, thus MyTARDIS follows the architectural model
|
|
||||||
of Django.
|
|
||||||
|
|
||||||
Component Architecture
|
|
||||||
----------------------
|
|
||||||
|
|
||||||
This diagram shows the major components of UDS.
|
|
||||||
|
|
||||||
* Core components
|
|
||||||
* `Apache Http <http://projects.apache.org/projects/http_server.html>`_
|
|
||||||
* `WSGI <http://code.google.com/p/modwsgi/>`_
|
|
||||||
* `Django <http://www.djangoproject.com/>`_
|
|
||||||
* `Python <http://docs.python.org/>`_.
|
|
||||||
|
|
||||||
* RDBMS
|
|
||||||
UDS is currently being developed/testing on Mysql 5 Database.
|
|
||||||
May other databases will work also, but no one else has been tested.
|
|
||||||
|
|
||||||
Functional Architecture
|
|
||||||
-----------------------
|
|
||||||
|
|
||||||
UDS is build using Django as base support for Web acess and Database access.
|
|
||||||
|
|
||||||
Over this, UDS uses the following diagram:
|
|
||||||
|
|
||||||
DIAGRAM
|
|
||||||
|
|
||||||
Core
|
|
||||||
Basic core funcionality.
|
|
@ -1,3 +0,0 @@
|
|||||||
===================
|
|
||||||
Contributing to UDS
|
|
||||||
===================
|
|
@ -1,3 +0,0 @@
|
|||||||
==============
|
|
||||||
UDS Repository
|
|
||||||
==============
|
|
@ -1,15 +0,0 @@
|
|||||||
====================
|
|
||||||
Sample Authenticator
|
|
||||||
====================
|
|
||||||
|
|
||||||
The authenticator is the responsible of providing the needed mechanisms to UDS for
|
|
||||||
user authentication.
|
|
||||||
|
|
||||||
As thatm this must provide a number of methods, that will allow UDS to manage
|
|
||||||
things the way it needs to. (Access users, groups, check credentials, etc...)
|
|
||||||
|
|
||||||
Here you can :download:`Download sample </_downloads/samples/auths/SampleAuth.py>`
|
|
||||||
|
|
||||||
|
|
||||||
.. literalinclude:: /_downloads/samples/auths/SampleAuth.py
|
|
||||||
:linenos:
|
|
@ -1,100 +0,0 @@
|
|||||||
===================
|
|
||||||
UDS Modules Samples
|
|
||||||
===================
|
|
||||||
|
|
||||||
In this section we cover basic samples of the different kind of mudules supported
|
|
||||||
by UDS.
|
|
||||||
|
|
||||||
UDS is designed in a modular way, meaning this that it has a core that allows
|
|
||||||
a number of modules to get plugged inside the whole system.
|
|
||||||
|
|
||||||
This modules are:
|
|
||||||
|
|
||||||
* Services, including all stuff around them.
|
|
||||||
* Transports
|
|
||||||
* OS Managers
|
|
||||||
* Authenticators
|
|
||||||
|
|
||||||
This secion will try to give sample of every module, what it must do and how this
|
|
||||||
must be done.
|
|
||||||
|
|
||||||
Service Sample
|
|
||||||
--------------
|
|
||||||
|
|
||||||
A service is composed of several classes. This classes depends on how the service works.
|
|
||||||
|
|
||||||
This are:
|
|
||||||
|
|
||||||
* *Provider*, that is simply the "root" where services
|
|
||||||
descent, so we can configure just one part of the service parameters and rest
|
|
||||||
of them at service level.
|
|
||||||
|
|
||||||
One sample of provider is a virtualization server, such as oVirt, Open Nebula, or
|
|
||||||
others like it. We can keep info about server at provider level, and info about
|
|
||||||
what we need in an specific service at service level.
|
|
||||||
|
|
||||||
* *Service*, that is a service definition, that must be deployed at a later stage
|
|
||||||
to offer something to the users.
|
|
||||||
|
|
||||||
Following our previous sample, if provider was an oVirt server, a service can
|
|
||||||
be a Virtual Machine cloned COW.
|
|
||||||
|
|
||||||
* *Publication*, This class is optional. If service declares that needs a
|
|
||||||
publication for deployment of user instance, this class implements exactly
|
|
||||||
that, the publication for that service. Publications are in fact a way of
|
|
||||||
allowing services to prepare something in a stage prior to creating the
|
|
||||||
user consumable services.
|
|
||||||
|
|
||||||
Following our previous sample, if provider was an oVirt Server and the service
|
|
||||||
was a Virtual Machine cloned for Cow, the poblication can be a full clone of
|
|
||||||
the service machine for making COWS from this one.
|
|
||||||
|
|
||||||
* *DeployedService*, This class is the user consumed service itself. After a
|
|
||||||
service is created, it must be deployed, and deploy will mean that there will
|
|
||||||
be "instances" of that service (User Deployments) that will be consumed by
|
|
||||||
users.
|
|
||||||
|
|
||||||
Following our previous sample, if the publication was a full copy machine,
|
|
||||||
an deployed service can be a machine in COW format using as base that
|
|
||||||
machine.
|
|
||||||
|
|
||||||
|
|
||||||
From theese, the only not really needed is Publication. Publication will only be
|
|
||||||
needed whenever a service needs a "preparation" before creating the user consumable
|
|
||||||
deployed services. For a service to be usable, we will need the full tree, meaning
|
|
||||||
this that we will provide all controllers (Provider, service or services, publication
|
|
||||||
or publications, deployed service or deployed services.).
|
|
||||||
|
|
||||||
All class belonging to a service must be grouped under the same package, and we
|
|
||||||
well need to register this package for the system to recognize it as service.
|
|
||||||
|
|
||||||
For this, we must register the Provider, that has references to rest of items.
|
|
||||||
|
|
||||||
Provider declares which services it provides. Services declares which publication
|
|
||||||
and deployed service it needs. Provider can declare multiples services it offers,
|
|
||||||
but services has at most one publication and exatly one deployed service.
|
|
||||||
|
|
||||||
So, by registering the Provider, we register the whole tree provided by de package.
|
|
||||||
|
|
||||||
Here you can find samples of every class needed for creating a new package of
|
|
||||||
services.
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
|
|
||||||
services/whatisneeded
|
|
||||||
services/Provider
|
|
||||||
services/Service
|
|
||||||
services/Publication
|
|
||||||
services/DeployedServiceOne
|
|
||||||
services/DeployedServiceTwo
|
|
||||||
|
|
||||||
|
|
||||||
Authenticator Sample
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
An authenticator is composed of a single class, derived from :py:class:`uds.core.auths.Authenticator`.
|
|
||||||
|
|
||||||
Here you can find a sample of an authenticator.
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
auths/Authenticator
|
|
@ -1,20 +0,0 @@
|
|||||||
==========================
|
|
||||||
Sample User Deployment One
|
|
||||||
==========================
|
|
||||||
|
|
||||||
User deployments are the class that are responsible for creating the ultimate consumable
|
|
||||||
user service, that is, for managing that whenever the core requests a new service for
|
|
||||||
an user, this classes will take responsibility to provide it.
|
|
||||||
|
|
||||||
Here we cover SampleUserDeploymentOne that is for SampleServiceOne, do not needs to be
|
|
||||||
published and do not uses cache.
|
|
||||||
|
|
||||||
You can easily follow the code to see what it does, and what you have to do if you
|
|
||||||
want to provide a new one.
|
|
||||||
|
|
||||||
:download:`Download sample </_downloads/samples/services/SampleUserDeploymentOne.py>`
|
|
||||||
|
|
||||||
|
|
||||||
.. literalinclude:: /_downloads/samples/services/SampleUserDeploymentOne.py
|
|
||||||
:linenos:
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
|||||||
==========================
|
|
||||||
Sample User Deployment Two
|
|
||||||
==========================
|
|
||||||
|
|
||||||
User deployments are the class that are responsible for creating the ultimate consumable
|
|
||||||
user service, that is, for managing that whenever the core requests a new service for
|
|
||||||
an user, this classes will take responsibility to provide it.
|
|
||||||
|
|
||||||
Here we cover SampleUserDeploymentTwo that is for SampleServiceTwo, needs to be
|
|
||||||
published and has L1 and L2 cache items.
|
|
||||||
|
|
||||||
You can easily follow the code to see what it does, and what you have to do if you
|
|
||||||
want to provide a new one.
|
|
||||||
|
|
||||||
:download:`Download sample </_downloads/samples/services/SampleUserDeploymentTwo.py>`
|
|
||||||
|
|
||||||
|
|
||||||
.. literalinclude:: /_downloads/samples/services/SampleUserDeploymentTwo.py
|
|
||||||
:linenos:
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
|||||||
=======================
|
|
||||||
Sample Service Provider
|
|
||||||
=======================
|
|
||||||
|
|
||||||
The service provider is the top of the tree of services needed clases.
|
|
||||||
It main function is to provide a base for services, where this services contains
|
|
||||||
a common parent that is, for example, a server, a range of IPs, etc...
|
|
||||||
|
|
||||||
This sample covers a simple service provider, explains also a bit about FormFields
|
|
||||||
and shows what tasks must be done by a service provider.
|
|
||||||
|
|
||||||
You can easily follow the code to see what it does, and what you have to do if you
|
|
||||||
want to provide a new one.
|
|
||||||
|
|
||||||
:download:`Download sample </_downloads/samples/services/SampleProvider.py>`
|
|
||||||
|
|
||||||
|
|
||||||
.. literalinclude:: /_downloads/samples/services/SampleProvider.py
|
|
||||||
:linenos:
|
|
@ -1,23 +0,0 @@
|
|||||||
==================
|
|
||||||
Sample publication
|
|
||||||
==================
|
|
||||||
|
|
||||||
A publication is a class responsible for making a service defined available to be
|
|
||||||
consumed by users.
|
|
||||||
|
|
||||||
Not all services needs publications as you have already seen if you are following
|
|
||||||
the samples. Publications are only needed for services that needs some kind of
|
|
||||||
preparation, as, for example, with Virtual Machines, clone the base virtual machine
|
|
||||||
so we can create COW copies from this clone. This kind of behavior needs a preparation
|
|
||||||
step, that is efectively to clone the virtual base, and that will be the task of a
|
|
||||||
publication for that kind of services.
|
|
||||||
|
|
||||||
You can easily follow the code to see what it does, and what you have to do if you
|
|
||||||
want to provide a new one.
|
|
||||||
|
|
||||||
:download:`Download sample </_downloads/samples/services/SamplePublication.py>`
|
|
||||||
|
|
||||||
|
|
||||||
.. literalinclude:: /_downloads/samples/services/SamplePublication.py
|
|
||||||
:linenos:
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
|||||||
==============
|
|
||||||
Sample service
|
|
||||||
==============
|
|
||||||
|
|
||||||
Here we cover two services. ServiceOne, that do not needs publication and
|
|
||||||
ServiceTwo, that needs publication.
|
|
||||||
|
|
||||||
This sample should be enought to guide you through the creation of a new service.
|
|
||||||
|
|
||||||
:download:`Download sample </_downloads/samples/services/SampleService.py>`
|
|
||||||
|
|
||||||
|
|
||||||
.. literalinclude:: /_downloads/samples/services/SampleService.py
|
|
||||||
:linenos:
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
|||||||
Needs for a service package
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
For a new package of services, you will need:
|
|
||||||
|
|
||||||
|
|
||||||
* One package (python package), of course :-).
|
|
||||||
* One icon for the provider, in png format an 16x16 size. Colours is left
|
|
||||||
to your election. This icon will be informed at Provider class.
|
|
||||||
* One icon for every service that the provider will expose. Same as provider
|
|
||||||
icons. These icons will be informed at Service class. Every single class
|
|
||||||
must provide its own icon.
|
|
||||||
* Registering the provider. For the samples show here, this will be at
|
|
||||||
__init__ of the package.
|
|
||||||
|
|
||||||
The contents of the sample package __init__ file is:
|
|
||||||
|
|
||||||
.. literalinclude:: /_downloads/samples/services/__init__.py
|
|
||||||
:linenos:
|
|
||||||
|
|
||||||
:download:`Download sample </_downloads/samples/services/__init__.py>`
|
|
||||||
|
|
||||||
* Put the package under the apropiate uds package. In the case of
|
|
||||||
services, this is under "uds.core".
|
|
||||||
|
|
||||||
Core will look for all packages under "uds.services" and import them at
|
|
||||||
initialization of the server, so every package under this will get their
|
|
||||||
__init__ called, where we register the provider.
|
|
||||||
|
|
||||||
* Follow the samples provided here as base
|
|
||||||
|
|
||||||
|
|
@ -1,71 +0,0 @@
|
|||||||
.. _index:
|
|
||||||
|
|
||||||
===================
|
|
||||||
UDS's documentation
|
|
||||||
===================
|
|
||||||
|
|
||||||
This documentation is provided so we can understand (hopefully) UDS, its internals,
|
|
||||||
and everything about it.
|
|
||||||
|
|
||||||
Right now the documentation is not too ritch, but we are working on it so it will
|
|
||||||
get the needed level for this kind of project.
|
|
||||||
|
|
||||||
|
|
||||||
First Steps
|
|
||||||
===========
|
|
||||||
|
|
||||||
* **From scratch:**
|
|
||||||
:doc:`Overview <intro/overview>` |
|
|
||||||
:doc:`Installation <intro/install>`
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:hidden:
|
|
||||||
|
|
||||||
intro/overview
|
|
||||||
intro/install
|
|
||||||
|
|
||||||
The internals of uds
|
|
||||||
====================
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
|
|
||||||
development/architecture
|
|
||||||
development/development
|
|
||||||
api/index
|
|
||||||
|
|
||||||
UDS Open source project
|
|
||||||
=======================
|
|
||||||
|
|
||||||
* **Community:**
|
|
||||||
:doc:`How to get involved <development/contributing>` |
|
|
||||||
:doc:`The UDS source code repository <development/repository>`
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
:hidden:
|
|
||||||
|
|
||||||
development/contributing
|
|
||||||
development/repository
|
|
||||||
|
|
||||||
|
|
||||||
Acknowledgements
|
|
||||||
================
|
|
||||||
|
|
||||||
We want to thaks all the people that has contributed to de project, an also
|
|
||||||
other Open Source project used to improve this one.
|
|
||||||
|
|
||||||
List of other software used to build UDS:
|
|
||||||
|
|
||||||
* `Django <http://www.djangoproject.com/>`_
|
|
||||||
* `XML-RPC.NET Copyright (c) 2006 Charles Cook <http://www.xml-rpc.net/>`_
|
|
||||||
* `Darkglass reworked graphics <http://kde-look.org/content/show.php/Dark-Glass+reviewed?content=67902>`_
|
|
||||||
* `Crystal project <http://kde-look.org/content/show.php/Crystal+Project?content=60475>`_
|
|
||||||
* `South <http://south.aeracode.org/>`_
|
|
||||||
* `Jsch <http://www.jcraft.com/jsch/>`_
|
|
||||||
* `JQuery <http://jquery.org/>`_
|
|
||||||
* `Plugin detect library <http://www.pinlady.net/PluginDetect/>`_
|
|
||||||
* `JQuery UI <http://jqueryui.com/>`_
|
|
||||||
|
|
||||||
I hope to do nor forget anythinh here, if i do, please, report it so we can credit
|
|
||||||
to every project that UDS makes use of.
|
|
||||||
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
|||||||
==============
|
|
||||||
Installing UDS
|
|
||||||
==============
|
|
||||||
|
|
||||||
In order to run UDS, you will need:
|
|
||||||
|
|
||||||
* Django Server 1.4
|
|
||||||
* South module for Django
|
|
||||||
* Mysql libraries for python
|
|
||||||
* Mysql Database
|
|
||||||
* Ldap Libraries for python
|
|
||||||
* Criptographic package for python
|
|
||||||
|
|
||||||
Default transports are compiled in binary form, and keeped inside UDS repository,
|
|
||||||
so you won't need Java to put UDS to work.
|
|
||||||
|
|
||||||
Once you have all of this, you will have to follow these steps:
|
|
||||||
|
|
||||||
* Obtain UDS from repository, you can see how to do this from
|
|
||||||
:doc:`repository access documentation </development/repository>`
|
|
||||||
* Configure a database for use with UDS. To do this, simple create a database
|
|
||||||
inside your Mysql server, and a user with all permissions in this database.
|
|
||||||
* Configure UDS settings.
|
|
||||||
Inside "server" folder, you will find "settings.py". This file contains the
|
|
||||||
configuration of UDS (if it runs in debug mode, ..). The most important part
|
|
||||||
here is the DATABASES section, where you will set up the database that UDS
|
|
||||||
will use. Simply change "host", "port", "udsername", "password" and "name"
|
|
||||||
to match your database settings.
|
|
||||||
Here, we have to take care that, if we left UDS in debug mode, Django will keep
|
|
||||||
track of all petitions to UDS, so memory will grow constantly. Do not get scared
|
|
||||||
if you see that UDS starts to waste too much memory. Simply restart it or, if it's
|
|
||||||
intended to be running for a while, set DEBUG variable to "False".
|
|
||||||
Important sections are:
|
|
||||||
|
|
||||||
* Create initial database tables.
|
|
||||||
Inside UDS folder, where you downloaded it, you will see a "manage.py".
|
|
||||||
This python application is the responsible for managing UDS, from database creation,
|
|
||||||
migrations, backend start & stop, web server (testing web server btw), ...
|
|
||||||
To create initial databases, we will do:
|
|
||||||
|
|
||||||
python manage.py sync
|
|
||||||
python manage.py migrate
|
|
||||||
|
|
||||||
Now we have all databases and everything that UDS needs for starting up ready... :-)
|
|
||||||
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
|||||||
===============
|
|
||||||
UDS at a glance
|
|
||||||
===============
|
|
||||||
|
|
||||||
UDS has been developed to make a single open source server that allows the access
|
|
||||||
to the growing ip services catalog.
|
|
||||||
|
|
||||||
For this, we have try to make a framework that allows the use of any ip service,
|
|
||||||
focusing initially at VDI because it's the mayor need for the people we have
|
|
||||||
contacted initially .
|
|
||||||
|
|
||||||
Also, first version of UDS has been developed "fast" (very fast indeed), so now
|
|
||||||
we need to make a revision an adapt de code of the framework so it's more
|
|
||||||
'pythonic'. (Think that i start learning python one day like this, and less than
|
|
||||||
a week later i started this proyect). So think that, althouth UDS is fully
|
|
||||||
functional, has been tested and is stable enought for any production environment,
|
|
||||||
there is a lot of work to do.
|
|
||||||
|
|
||||||
As so, UDS not only provides default modules for a lot of things (virtualization
|
|
||||||
provider, authentication providers, protocols, ...), but also provides the core
|
|
||||||
itself to allow anyone who wants or needs something, incorporate it to the
|
|
||||||
catalog of UDS in an easy and fast way.
|
|
||||||
|
|
||||||
* In order to use UDS, you must simply :doc:`Follow the installation guide <install>`.
|
|
||||||
|
|
||||||
* In order to design and implement your own modules, you must:
|
|
||||||
|
|
||||||
* :doc:`Understand the architecture </development/architecture>`
|
|
||||||
* :doc:`See some module samples </development/samples/samples>`
|
|
||||||
|
|
||||||
* In order to contribute, you must install UDS, understand it, an read the
|
|
||||||
:doc:`contributing guide </development/contributing>`
|
|
Before Width: | Height: | Size: 673 B |
@ -1,537 +0,0 @@
|
|||||||
/*
|
|
||||||
* basic.css
|
|
||||||
* ~~~~~~~~~
|
|
||||||
*
|
|
||||||
* Sphinx stylesheet -- basic theme.
|
|
||||||
*
|
|
||||||
* :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
|
|
||||||
* :license: BSD, see LICENSE for details.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* -- main layout ----------------------------------------------------------- */
|
|
||||||
|
|
||||||
div.clearer {
|
|
||||||
clear: both;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- relbar ---------------------------------------------------------------- */
|
|
||||||
|
|
||||||
div.related {
|
|
||||||
width: 100%;
|
|
||||||
font-size: 90%;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.related h3 {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.related ul {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0 0 0 10px;
|
|
||||||
list-style: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.related li {
|
|
||||||
display: inline;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.related li.right {
|
|
||||||
float: right;
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- sidebar --------------------------------------------------------------- */
|
|
||||||
|
|
||||||
div.sphinxsidebarwrapper {
|
|
||||||
padding: 10px 5px 0 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.sphinxsidebar {
|
|
||||||
float: left;
|
|
||||||
width: 230px;
|
|
||||||
margin-left: -100%;
|
|
||||||
font-size: 90%;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.sphinxsidebar ul {
|
|
||||||
list-style: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.sphinxsidebar ul ul,
|
|
||||||
div.sphinxsidebar ul.want-points {
|
|
||||||
margin-left: 20px;
|
|
||||||
list-style: square;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.sphinxsidebar ul ul {
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.sphinxsidebar form {
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.sphinxsidebar input {
|
|
||||||
border: 1px solid #98dbcc;
|
|
||||||
font-family: sans-serif;
|
|
||||||
font-size: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.sphinxsidebar #searchbox input[type="text"] {
|
|
||||||
width: 170px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.sphinxsidebar #searchbox input[type="submit"] {
|
|
||||||
width: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
border: 0;
|
|
||||||
max-width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- search page ----------------------------------------------------------- */
|
|
||||||
|
|
||||||
ul.search {
|
|
||||||
margin: 10px 0 0 20px;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul.search li {
|
|
||||||
padding: 5px 0 5px 20px;
|
|
||||||
background-image: url(file.png);
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: 0 7px;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul.search li a {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul.search li div.context {
|
|
||||||
color: #888;
|
|
||||||
margin: 2px 0 0 30px;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul.keywordmatches li.goodmatch a {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- index page ------------------------------------------------------------ */
|
|
||||||
|
|
||||||
table.contentstable {
|
|
||||||
width: 90%;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.contentstable p.biglink {
|
|
||||||
line-height: 150%;
|
|
||||||
}
|
|
||||||
|
|
||||||
a.biglink {
|
|
||||||
font-size: 1.3em;
|
|
||||||
}
|
|
||||||
|
|
||||||
span.linkdescr {
|
|
||||||
font-style: italic;
|
|
||||||
padding-top: 5px;
|
|
||||||
font-size: 90%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- general index --------------------------------------------------------- */
|
|
||||||
|
|
||||||
table.indextable {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.indextable td {
|
|
||||||
text-align: left;
|
|
||||||
vertical-align: top;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.indextable dl, table.indextable dd {
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.indextable tr.pcap {
|
|
||||||
height: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.indextable tr.cap {
|
|
||||||
margin-top: 10px;
|
|
||||||
background-color: #f2f2f2;
|
|
||||||
}
|
|
||||||
|
|
||||||
img.toggler {
|
|
||||||
margin-right: 3px;
|
|
||||||
margin-top: 3px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.modindex-jumpbox {
|
|
||||||
border-top: 1px solid #ddd;
|
|
||||||
border-bottom: 1px solid #ddd;
|
|
||||||
margin: 1em 0 1em 0;
|
|
||||||
padding: 0.4em;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.genindex-jumpbox {
|
|
||||||
border-top: 1px solid #ddd;
|
|
||||||
border-bottom: 1px solid #ddd;
|
|
||||||
margin: 1em 0 1em 0;
|
|
||||||
padding: 0.4em;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- general body styles --------------------------------------------------- */
|
|
||||||
|
|
||||||
a.headerlink {
|
|
||||||
visibility: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1:hover > a.headerlink,
|
|
||||||
h2:hover > a.headerlink,
|
|
||||||
h3:hover > a.headerlink,
|
|
||||||
h4:hover > a.headerlink,
|
|
||||||
h5:hover > a.headerlink,
|
|
||||||
h6:hover > a.headerlink,
|
|
||||||
dt:hover > a.headerlink {
|
|
||||||
visibility: visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.body p.caption {
|
|
||||||
text-align: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.body td {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.field-list ul {
|
|
||||||
padding-left: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.first {
|
|
||||||
margin-top: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
p.rubric {
|
|
||||||
margin-top: 30px;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
img.align-left, .figure.align-left, object.align-left {
|
|
||||||
clear: left;
|
|
||||||
float: left;
|
|
||||||
margin-right: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
img.align-right, .figure.align-right, object.align-right {
|
|
||||||
clear: right;
|
|
||||||
float: right;
|
|
||||||
margin-left: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
img.align-center, .figure.align-center, object.align-center {
|
|
||||||
display: block;
|
|
||||||
margin-left: auto;
|
|
||||||
margin-right: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.align-left {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.align-center {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.align-right {
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- sidebars -------------------------------------------------------------- */
|
|
||||||
|
|
||||||
div.sidebar {
|
|
||||||
margin: 0 0 0.5em 1em;
|
|
||||||
border: 1px solid #ddb;
|
|
||||||
padding: 7px 7px 0 7px;
|
|
||||||
background-color: #ffe;
|
|
||||||
width: 40%;
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
p.sidebar-title {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- topics ---------------------------------------------------------------- */
|
|
||||||
|
|
||||||
div.topic {
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
padding: 7px 7px 0 7px;
|
|
||||||
margin: 10px 0 10px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
p.topic-title {
|
|
||||||
font-size: 1.1em;
|
|
||||||
font-weight: bold;
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- admonitions ----------------------------------------------------------- */
|
|
||||||
|
|
||||||
div.admonition {
|
|
||||||
margin-top: 10px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
padding: 7px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.admonition dt {
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.admonition dl {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
p.admonition-title {
|
|
||||||
margin: 0px 10px 5px 0px;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.body p.centered {
|
|
||||||
text-align: center;
|
|
||||||
margin-top: 25px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- tables ---------------------------------------------------------------- */
|
|
||||||
|
|
||||||
table.docutils {
|
|
||||||
border: 0;
|
|
||||||
border-collapse: collapse;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.docutils td, table.docutils th {
|
|
||||||
padding: 1px 8px 1px 5px;
|
|
||||||
border-top: 0;
|
|
||||||
border-left: 0;
|
|
||||||
border-right: 0;
|
|
||||||
border-bottom: 1px solid #aaa;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.field-list td, table.field-list th {
|
|
||||||
border: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.footnote td, table.footnote th {
|
|
||||||
border: 0 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
th {
|
|
||||||
text-align: left;
|
|
||||||
padding-right: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.citation {
|
|
||||||
border-left: solid 1px gray;
|
|
||||||
margin-left: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.citation td {
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- other body styles ----------------------------------------------------- */
|
|
||||||
|
|
||||||
ol.arabic {
|
|
||||||
list-style: decimal;
|
|
||||||
}
|
|
||||||
|
|
||||||
ol.loweralpha {
|
|
||||||
list-style: lower-alpha;
|
|
||||||
}
|
|
||||||
|
|
||||||
ol.upperalpha {
|
|
||||||
list-style: upper-alpha;
|
|
||||||
}
|
|
||||||
|
|
||||||
ol.lowerroman {
|
|
||||||
list-style: lower-roman;
|
|
||||||
}
|
|
||||||
|
|
||||||
ol.upperroman {
|
|
||||||
list-style: upper-roman;
|
|
||||||
}
|
|
||||||
|
|
||||||
dl {
|
|
||||||
margin-bottom: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
dd p {
|
|
||||||
margin-top: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
dd ul, dd table {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
dd {
|
|
||||||
margin-top: 3px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
margin-left: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
dt:target, .highlighted {
|
|
||||||
background-color: #fbe54e;
|
|
||||||
}
|
|
||||||
|
|
||||||
dl.glossary dt {
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 1.1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.field-list ul {
|
|
||||||
margin: 0;
|
|
||||||
padding-left: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.field-list p {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.optional {
|
|
||||||
font-size: 1.3em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.versionmodified {
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
.system-message {
|
|
||||||
background-color: #fda;
|
|
||||||
padding: 5px;
|
|
||||||
border: 3px solid red;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footnote:target {
|
|
||||||
background-color: #ffa;
|
|
||||||
}
|
|
||||||
|
|
||||||
.line-block {
|
|
||||||
display: block;
|
|
||||||
margin-top: 1em;
|
|
||||||
margin-bottom: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.line-block .line-block {
|
|
||||||
margin-top: 0;
|
|
||||||
margin-bottom: 0;
|
|
||||||
margin-left: 1.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.guilabel, .menuselection {
|
|
||||||
font-family: sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
.accelerator {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
.classifier {
|
|
||||||
font-style: oblique;
|
|
||||||
}
|
|
||||||
|
|
||||||
abbr, acronym {
|
|
||||||
border-bottom: dotted 1px;
|
|
||||||
cursor: help;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- code displays --------------------------------------------------------- */
|
|
||||||
|
|
||||||
pre {
|
|
||||||
overflow: auto;
|
|
||||||
overflow-y: hidden; /* fixes display issues on Chrome browsers */
|
|
||||||
}
|
|
||||||
|
|
||||||
td.linenos pre {
|
|
||||||
padding: 5px 0px;
|
|
||||||
border: 0;
|
|
||||||
background-color: transparent;
|
|
||||||
color: #aaa;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.highlighttable {
|
|
||||||
margin-left: 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
table.highlighttable td {
|
|
||||||
padding: 0 0.5em 0 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
tt.descname {
|
|
||||||
background-color: transparent;
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 1.2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
tt.descclassname {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
tt.xref, a tt {
|
|
||||||
background-color: transparent;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.viewcode-link {
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
.viewcode-back {
|
|
||||||
float: right;
|
|
||||||
font-family: sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.viewcode-block:target {
|
|
||||||
margin: -1px -10px;
|
|
||||||
padding: 0 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- math display ---------------------------------------------------------- */
|
|
||||||
|
|
||||||
img.math {
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.body div.math p {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
span.eqno {
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- printout stylesheet --------------------------------------------------- */
|
|
||||||
|
|
||||||
@media print {
|
|
||||||
div.document,
|
|
||||||
div.documentwrapper,
|
|
||||||
div.bodywrapper {
|
|
||||||
margin: 0 !important;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.sphinxsidebar,
|
|
||||||
div.related,
|
|
||||||
div.footer,
|
|
||||||
#top-link {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
Before Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 202 B |
@ -1,238 +0,0 @@
|
|||||||
/*
|
|
||||||
* doctools.js
|
|
||||||
* ~~~~~~~~~~~
|
|
||||||
*
|
|
||||||
* Sphinx JavaScript utilities for all documentation.
|
|
||||||
*
|
|
||||||
* :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
|
|
||||||
* :license: BSD, see LICENSE for details.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* select a different prefix for underscore
|
|
||||||
*/
|
|
||||||
$u = _.noConflict();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* make the code below compatible with browsers without
|
|
||||||
* an installed firebug like debugger
|
|
||||||
if (!window.console || !console.firebug) {
|
|
||||||
var names = ["log", "debug", "info", "warn", "error", "assert", "dir",
|
|
||||||
"dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace",
|
|
||||||
"profile", "profileEnd"];
|
|
||||||
window.console = {};
|
|
||||||
for (var i = 0; i < names.length; ++i)
|
|
||||||
window.console[names[i]] = function() {};
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* small helper function to urldecode strings
|
|
||||||
*/
|
|
||||||
jQuery.urldecode = function(x) {
|
|
||||||
return decodeURIComponent(x).replace(/\+/g, ' ');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* small helper function to urlencode strings
|
|
||||||
*/
|
|
||||||
jQuery.urlencode = encodeURIComponent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This function returns the parsed url parameters of the
|
|
||||||
* current request. Multiple values per key are supported,
|
|
||||||
* it will always return arrays of strings for the value parts.
|
|
||||||
*/
|
|
||||||
jQuery.getQueryParameters = function(s) {
|
|
||||||
if (typeof s == 'undefined')
|
|
||||||
s = document.location.search;
|
|
||||||
var parts = s.substr(s.indexOf('?') + 1).split('&');
|
|
||||||
var result = {};
|
|
||||||
for (var i = 0; i < parts.length; i++) {
|
|
||||||
var tmp = parts[i].split('=', 2);
|
|
||||||
var key = jQuery.urldecode(tmp[0]);
|
|
||||||
var value = jQuery.urldecode(tmp[1]);
|
|
||||||
if (key in result)
|
|
||||||
result[key].push(value);
|
|
||||||
else
|
|
||||||
result[key] = [value];
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* highlight a given string on a jquery object by wrapping it in
|
|
||||||
* span elements with the given class name.
|
|
||||||
*/
|
|
||||||
jQuery.fn.highlightText = function(text, className) {
|
|
||||||
function highlight(node) {
|
|
||||||
if (node.nodeType == 3) {
|
|
||||||
var val = node.nodeValue;
|
|
||||||
var pos = val.toLowerCase().indexOf(text);
|
|
||||||
if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) {
|
|
||||||
var span = document.createElement("span");
|
|
||||||
span.className = className;
|
|
||||||
span.appendChild(document.createTextNode(val.substr(pos, text.length)));
|
|
||||||
node.parentNode.insertBefore(span, node.parentNode.insertBefore(
|
|
||||||
document.createTextNode(val.substr(pos + text.length)),
|
|
||||||
node.nextSibling));
|
|
||||||
node.nodeValue = val.substr(0, pos);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!jQuery(node).is("button, select, textarea")) {
|
|
||||||
jQuery.each(node.childNodes, function() {
|
|
||||||
highlight(this);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this.each(function() {
|
|
||||||
highlight(this);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Small JavaScript module for the documentation.
|
|
||||||
*/
|
|
||||||
var Documentation = {
|
|
||||||
|
|
||||||
init : function() {
|
|
||||||
this.fixFirefoxAnchorBug();
|
|
||||||
this.highlightSearchWords();
|
|
||||||
this.initIndexTable();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* i18n support
|
|
||||||
*/
|
|
||||||
TRANSLATIONS : {},
|
|
||||||
PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; },
|
|
||||||
LOCALE : 'unknown',
|
|
||||||
|
|
||||||
// gettext and ngettext don't access this so that the functions
|
|
||||||
// can safely bound to a different name (_ = Documentation.gettext)
|
|
||||||
gettext : function(string) {
|
|
||||||
var translated = Documentation.TRANSLATIONS[string];
|
|
||||||
if (typeof translated == 'undefined')
|
|
||||||
return string;
|
|
||||||
return (typeof translated == 'string') ? translated : translated[0];
|
|
||||||
},
|
|
||||||
|
|
||||||
ngettext : function(singular, plural, n) {
|
|
||||||
var translated = Documentation.TRANSLATIONS[singular];
|
|
||||||
if (typeof translated == 'undefined')
|
|
||||||
return (n == 1) ? singular : plural;
|
|
||||||
return translated[Documentation.PLURALEXPR(n)];
|
|
||||||
},
|
|
||||||
|
|
||||||
addTranslations : function(catalog) {
|
|
||||||
for (var key in catalog.messages)
|
|
||||||
this.TRANSLATIONS[key] = catalog.messages[key];
|
|
||||||
this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')');
|
|
||||||
this.LOCALE = catalog.locale;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* add context elements like header anchor links
|
|
||||||
*/
|
|
||||||
addContextElements : function() {
|
|
||||||
$('div[id] > :header:first').each(function() {
|
|
||||||
$('<a class="headerlink">\u00B6</a>').
|
|
||||||
attr('href', '#' + this.id).
|
|
||||||
attr('title', _('Permalink to this headline')).
|
|
||||||
appendTo(this);
|
|
||||||
});
|
|
||||||
$('dt[id]').each(function() {
|
|
||||||
$('<a class="headerlink">\u00B6</a>').
|
|
||||||
attr('href', '#' + this.id).
|
|
||||||
attr('title', _('Permalink to this definition')).
|
|
||||||
appendTo(this);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* workaround a firefox stupidity
|
|
||||||
*/
|
|
||||||
fixFirefoxAnchorBug : function() {
|
|
||||||
if (document.location.hash && $.browser.mozilla)
|
|
||||||
window.setTimeout(function() {
|
|
||||||
document.location.href += '';
|
|
||||||
}, 10);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* highlight the search words provided in the url in the text
|
|
||||||
*/
|
|
||||||
highlightSearchWords : function() {
|
|
||||||
var params = $.getQueryParameters();
|
|
||||||
var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
|
|
||||||
if (terms.length) {
|
|
||||||
var body = $('div.body');
|
|
||||||
if (!body.length) {
|
|
||||||
body = $('body');
|
|
||||||
}
|
|
||||||
window.setTimeout(function() {
|
|
||||||
$.each(terms, function() {
|
|
||||||
body.highlightText(this.toLowerCase(), 'highlighted');
|
|
||||||
});
|
|
||||||
}, 10);
|
|
||||||
$('<p class="highlight-link"><a href="javascript:Documentation.' +
|
|
||||||
'hideSearchWords()">' + _('Hide Search Matches') + '</a></p>')
|
|
||||||
.appendTo($('#searchbox'));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* init the domain index toggle buttons
|
|
||||||
*/
|
|
||||||
initIndexTable : function() {
|
|
||||||
var togglers = $('img.toggler').click(function() {
|
|
||||||
var src = $(this).attr('src');
|
|
||||||
var idnum = $(this).attr('id').substr(7);
|
|
||||||
$('tr.cg-' + idnum).toggle();
|
|
||||||
if (src.substr(-9) == 'minus.png')
|
|
||||||
$(this).attr('src', src.substr(0, src.length-9) + 'plus.png');
|
|
||||||
else
|
|
||||||
$(this).attr('src', src.substr(0, src.length-8) + 'minus.png');
|
|
||||||
}).css('display', '');
|
|
||||||
if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) {
|
|
||||||
togglers.click();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* helper function to hide the search marks again
|
|
||||||
*/
|
|
||||||
hideSearchWords : function() {
|
|
||||||
$('#searchbox .highlight-link').fadeOut(300);
|
|
||||||
$('span.highlighted').removeClass('highlighted');
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* make the url absolute
|
|
||||||
*/
|
|
||||||
makeURL : function(relativeURL) {
|
|
||||||
return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get the current relative url
|
|
||||||
*/
|
|
||||||
getCurrentURL : function() {
|
|
||||||
var path = document.location.pathname;
|
|
||||||
var parts = path.split(/\//);
|
|
||||||
$.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() {
|
|
||||||
if (this == '..')
|
|
||||||
parts.pop();
|
|
||||||
});
|
|
||||||
var url = parts.join('/');
|
|
||||||
return path.substring(url.lastIndexOf('/') + 1, path.length - 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// quick alias for translations
|
|
||||||
_ = Documentation.gettext;
|
|
||||||
|
|
||||||
$(document).ready(function() {
|
|
||||||
Documentation.init();
|
|
||||||
});
|
|
Before Width: | Height: | Size: 368 B |
Before Width: | Height: | Size: 363 B |
Before Width: | Height: | Size: 392 B |
9404
server/documentation/_build/html/_static/jquery.js
vendored
Before Width: | Height: | Size: 199 B |
Before Width: | Height: | Size: 218 B |
Before Width: | Height: | Size: 199 B |
@ -1,62 +0,0 @@
|
|||||||
.highlight .hll { background-color: #ffffcc }
|
|
||||||
.highlight { background: #eeffcc; }
|
|
||||||
.highlight .c { color: #408090; font-style: italic } /* Comment */
|
|
||||||
.highlight .err { border: 1px solid #FF0000 } /* Error */
|
|
||||||
.highlight .k { color: #007020; font-weight: bold } /* Keyword */
|
|
||||||
.highlight .o { color: #666666 } /* Operator */
|
|
||||||
.highlight .cm { color: #408090; font-style: italic } /* Comment.Multiline */
|
|
||||||
.highlight .cp { color: #007020 } /* Comment.Preproc */
|
|
||||||
.highlight .c1 { color: #408090; font-style: italic } /* Comment.Single */
|
|
||||||
.highlight .cs { color: #408090; background-color: #fff0f0 } /* Comment.Special */
|
|
||||||
.highlight .gd { color: #A00000 } /* Generic.Deleted */
|
|
||||||
.highlight .ge { font-style: italic } /* Generic.Emph */
|
|
||||||
.highlight .gr { color: #FF0000 } /* Generic.Error */
|
|
||||||
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
|
|
||||||
.highlight .gi { color: #00A000 } /* Generic.Inserted */
|
|
||||||
.highlight .go { color: #333333 } /* Generic.Output */
|
|
||||||
.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
|
|
||||||
.highlight .gs { font-weight: bold } /* Generic.Strong */
|
|
||||||
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
|
|
||||||
.highlight .gt { color: #0044DD } /* Generic.Traceback */
|
|
||||||
.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */
|
|
||||||
.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
|
|
||||||
.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
|
|
||||||
.highlight .kp { color: #007020 } /* Keyword.Pseudo */
|
|
||||||
.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
|
|
||||||
.highlight .kt { color: #902000 } /* Keyword.Type */
|
|
||||||
.highlight .m { color: #208050 } /* Literal.Number */
|
|
||||||
.highlight .s { color: #4070a0 } /* Literal.String */
|
|
||||||
.highlight .na { color: #4070a0 } /* Name.Attribute */
|
|
||||||
.highlight .nb { color: #007020 } /* Name.Builtin */
|
|
||||||
.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */
|
|
||||||
.highlight .no { color: #60add5 } /* Name.Constant */
|
|
||||||
.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */
|
|
||||||
.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */
|
|
||||||
.highlight .ne { color: #007020 } /* Name.Exception */
|
|
||||||
.highlight .nf { color: #06287e } /* Name.Function */
|
|
||||||
.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */
|
|
||||||
.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
|
|
||||||
.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */
|
|
||||||
.highlight .nv { color: #bb60d5 } /* Name.Variable */
|
|
||||||
.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */
|
|
||||||
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
|
|
||||||
.highlight .mf { color: #208050 } /* Literal.Number.Float */
|
|
||||||
.highlight .mh { color: #208050 } /* Literal.Number.Hex */
|
|
||||||
.highlight .mi { color: #208050 } /* Literal.Number.Integer */
|
|
||||||
.highlight .mo { color: #208050 } /* Literal.Number.Oct */
|
|
||||||
.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */
|
|
||||||
.highlight .sc { color: #4070a0 } /* Literal.String.Char */
|
|
||||||
.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
|
|
||||||
.highlight .s2 { color: #4070a0 } /* Literal.String.Double */
|
|
||||||
.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
|
|
||||||
.highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */
|
|
||||||
.highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
|
|
||||||
.highlight .sx { color: #c65d09 } /* Literal.String.Other */
|
|
||||||
.highlight .sr { color: #235388 } /* Literal.String.Regex */
|
|
||||||
.highlight .s1 { color: #4070a0 } /* Literal.String.Single */
|
|
||||||
.highlight .ss { color: #517918 } /* Literal.String.Symbol */
|
|
||||||
.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
|
|
||||||
.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */
|
|
||||||
.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */
|
|
||||||
.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */
|
|
||||||
.highlight .il { color: #208050 } /* Literal.Number.Integer.Long */
|
|
@ -1,622 +0,0 @@
|
|||||||
/*
|
|
||||||
* searchtools.js_t
|
|
||||||
* ~~~~~~~~~~~~~~~~
|
|
||||||
*
|
|
||||||
* Sphinx JavaScript utilties for the full-text search.
|
|
||||||
*
|
|
||||||
* :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
|
|
||||||
* :license: BSD, see LICENSE for details.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Porter Stemmer
|
|
||||||
*/
|
|
||||||
var Stemmer = function() {
|
|
||||||
|
|
||||||
var step2list = {
|
|
||||||
ational: 'ate',
|
|
||||||
tional: 'tion',
|
|
||||||
enci: 'ence',
|
|
||||||
anci: 'ance',
|
|
||||||
izer: 'ize',
|
|
||||||
bli: 'ble',
|
|
||||||
alli: 'al',
|
|
||||||
entli: 'ent',
|
|
||||||
eli: 'e',
|
|
||||||
ousli: 'ous',
|
|
||||||
ization: 'ize',
|
|
||||||
ation: 'ate',
|
|
||||||
ator: 'ate',
|
|
||||||
alism: 'al',
|
|
||||||
iveness: 'ive',
|
|
||||||
fulness: 'ful',
|
|
||||||
ousness: 'ous',
|
|
||||||
aliti: 'al',
|
|
||||||
iviti: 'ive',
|
|
||||||
biliti: 'ble',
|
|
||||||
logi: 'log'
|
|
||||||
};
|
|
||||||
|
|
||||||
var step3list = {
|
|
||||||
icate: 'ic',
|
|
||||||
ative: '',
|
|
||||||
alize: 'al',
|
|
||||||
iciti: 'ic',
|
|
||||||
ical: 'ic',
|
|
||||||
ful: '',
|
|
||||||
ness: ''
|
|
||||||
};
|
|
||||||
|
|
||||||
var c = "[^aeiou]"; // consonant
|
|
||||||
var v = "[aeiouy]"; // vowel
|
|
||||||
var C = c + "[^aeiouy]*"; // consonant sequence
|
|
||||||
var V = v + "[aeiou]*"; // vowel sequence
|
|
||||||
|
|
||||||
var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0
|
|
||||||
var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1
|
|
||||||
var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1
|
|
||||||
var s_v = "^(" + C + ")?" + v; // vowel in stem
|
|
||||||
|
|
||||||
this.stemWord = function (w) {
|
|
||||||
var stem;
|
|
||||||
var suffix;
|
|
||||||
var firstch;
|
|
||||||
var origword = w;
|
|
||||||
|
|
||||||
if (w.length < 3)
|
|
||||||
return w;
|
|
||||||
|
|
||||||
var re;
|
|
||||||
var re2;
|
|
||||||
var re3;
|
|
||||||
var re4;
|
|
||||||
|
|
||||||
firstch = w.substr(0,1);
|
|
||||||
if (firstch == "y")
|
|
||||||
w = firstch.toUpperCase() + w.substr(1);
|
|
||||||
|
|
||||||
// Step 1a
|
|
||||||
re = /^(.+?)(ss|i)es$/;
|
|
||||||
re2 = /^(.+?)([^s])s$/;
|
|
||||||
|
|
||||||
if (re.test(w))
|
|
||||||
w = w.replace(re,"$1$2");
|
|
||||||
else if (re2.test(w))
|
|
||||||
w = w.replace(re2,"$1$2");
|
|
||||||
|
|
||||||
// Step 1b
|
|
||||||
re = /^(.+?)eed$/;
|
|
||||||
re2 = /^(.+?)(ed|ing)$/;
|
|
||||||
if (re.test(w)) {
|
|
||||||
var fp = re.exec(w);
|
|
||||||
re = new RegExp(mgr0);
|
|
||||||
if (re.test(fp[1])) {
|
|
||||||
re = /.$/;
|
|
||||||
w = w.replace(re,"");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (re2.test(w)) {
|
|
||||||
var fp = re2.exec(w);
|
|
||||||
stem = fp[1];
|
|
||||||
re2 = new RegExp(s_v);
|
|
||||||
if (re2.test(stem)) {
|
|
||||||
w = stem;
|
|
||||||
re2 = /(at|bl|iz)$/;
|
|
||||||
re3 = new RegExp("([^aeiouylsz])\\1$");
|
|
||||||
re4 = new RegExp("^" + C + v + "[^aeiouwxy]$");
|
|
||||||
if (re2.test(w))
|
|
||||||
w = w + "e";
|
|
||||||
else if (re3.test(w)) {
|
|
||||||
re = /.$/;
|
|
||||||
w = w.replace(re,"");
|
|
||||||
}
|
|
||||||
else if (re4.test(w))
|
|
||||||
w = w + "e";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 1c
|
|
||||||
re = /^(.+?)y$/;
|
|
||||||
if (re.test(w)) {
|
|
||||||
var fp = re.exec(w);
|
|
||||||
stem = fp[1];
|
|
||||||
re = new RegExp(s_v);
|
|
||||||
if (re.test(stem))
|
|
||||||
w = stem + "i";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 2
|
|
||||||
re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
|
|
||||||
if (re.test(w)) {
|
|
||||||
var fp = re.exec(w);
|
|
||||||
stem = fp[1];
|
|
||||||
suffix = fp[2];
|
|
||||||
re = new RegExp(mgr0);
|
|
||||||
if (re.test(stem))
|
|
||||||
w = stem + step2list[suffix];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 3
|
|
||||||
re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
|
|
||||||
if (re.test(w)) {
|
|
||||||
var fp = re.exec(w);
|
|
||||||
stem = fp[1];
|
|
||||||
suffix = fp[2];
|
|
||||||
re = new RegExp(mgr0);
|
|
||||||
if (re.test(stem))
|
|
||||||
w = stem + step3list[suffix];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 4
|
|
||||||
re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;
|
|
||||||
re2 = /^(.+?)(s|t)(ion)$/;
|
|
||||||
if (re.test(w)) {
|
|
||||||
var fp = re.exec(w);
|
|
||||||
stem = fp[1];
|
|
||||||
re = new RegExp(mgr1);
|
|
||||||
if (re.test(stem))
|
|
||||||
w = stem;
|
|
||||||
}
|
|
||||||
else if (re2.test(w)) {
|
|
||||||
var fp = re2.exec(w);
|
|
||||||
stem = fp[1] + fp[2];
|
|
||||||
re2 = new RegExp(mgr1);
|
|
||||||
if (re2.test(stem))
|
|
||||||
w = stem;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 5
|
|
||||||
re = /^(.+?)e$/;
|
|
||||||
if (re.test(w)) {
|
|
||||||
var fp = re.exec(w);
|
|
||||||
stem = fp[1];
|
|
||||||
re = new RegExp(mgr1);
|
|
||||||
re2 = new RegExp(meq1);
|
|
||||||
re3 = new RegExp("^" + C + v + "[^aeiouwxy]$");
|
|
||||||
if (re.test(stem) || (re2.test(stem) && !(re3.test(stem))))
|
|
||||||
w = stem;
|
|
||||||
}
|
|
||||||
re = /ll$/;
|
|
||||||
re2 = new RegExp(mgr1);
|
|
||||||
if (re.test(w) && re2.test(w)) {
|
|
||||||
re = /.$/;
|
|
||||||
w = w.replace(re,"");
|
|
||||||
}
|
|
||||||
|
|
||||||
// and turn initial Y back to y
|
|
||||||
if (firstch == "y")
|
|
||||||
w = firstch.toLowerCase() + w.substr(1);
|
|
||||||
return w;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple result scoring code.
|
|
||||||
*/
|
|
||||||
var Scorer = {
|
|
||||||
// Implement the following function to further tweak the score for each result
|
|
||||||
// The function takes a result array [filename, title, anchor, descr, score]
|
|
||||||
// and returns the new score.
|
|
||||||
/*
|
|
||||||
score: function(result) {
|
|
||||||
return result[4];
|
|
||||||
},
|
|
||||||
*/
|
|
||||||
|
|
||||||
// query matches the full name of an object
|
|
||||||
objNameMatch: 11,
|
|
||||||
// or matches in the last dotted part of the object name
|
|
||||||
objPartialMatch: 6,
|
|
||||||
// Additive scores depending on the priority of the object
|
|
||||||
objPrio: {0: 15, // used to be importantResults
|
|
||||||
1: 5, // used to be objectResults
|
|
||||||
2: -5}, // used to be unimportantResults
|
|
||||||
// Used when the priority is not in the mapping.
|
|
||||||
objPrioDefault: 0,
|
|
||||||
|
|
||||||
// query found in title
|
|
||||||
title: 15,
|
|
||||||
// query found in terms
|
|
||||||
term: 5
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Search Module
|
|
||||||
*/
|
|
||||||
var Search = {
|
|
||||||
|
|
||||||
_index : null,
|
|
||||||
_queued_query : null,
|
|
||||||
_pulse_status : -1,
|
|
||||||
|
|
||||||
init : function() {
|
|
||||||
var params = $.getQueryParameters();
|
|
||||||
if (params.q) {
|
|
||||||
var query = params.q[0];
|
|
||||||
$('input[name="q"]')[0].value = query;
|
|
||||||
this.performSearch(query);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
loadIndex : function(url) {
|
|
||||||
$.ajax({type: "GET", url: url, data: null,
|
|
||||||
dataType: "script", cache: true,
|
|
||||||
complete: function(jqxhr, textstatus) {
|
|
||||||
if (textstatus != "success") {
|
|
||||||
document.getElementById("searchindexloader").src = url;
|
|
||||||
}
|
|
||||||
}});
|
|
||||||
},
|
|
||||||
|
|
||||||
setIndex : function(index) {
|
|
||||||
var q;
|
|
||||||
this._index = index;
|
|
||||||
if ((q = this._queued_query) !== null) {
|
|
||||||
this._queued_query = null;
|
|
||||||
Search.query(q);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
hasIndex : function() {
|
|
||||||
return this._index !== null;
|
|
||||||
},
|
|
||||||
|
|
||||||
deferQuery : function(query) {
|
|
||||||
this._queued_query = query;
|
|
||||||
},
|
|
||||||
|
|
||||||
stopPulse : function() {
|
|
||||||
this._pulse_status = 0;
|
|
||||||
},
|
|
||||||
|
|
||||||
startPulse : function() {
|
|
||||||
if (this._pulse_status >= 0)
|
|
||||||
return;
|
|
||||||
function pulse() {
|
|
||||||
var i;
|
|
||||||
Search._pulse_status = (Search._pulse_status + 1) % 4;
|
|
||||||
var dotString = '';
|
|
||||||
for (i = 0; i < Search._pulse_status; i++)
|
|
||||||
dotString += '.';
|
|
||||||
Search.dots.text(dotString);
|
|
||||||
if (Search._pulse_status > -1)
|
|
||||||
window.setTimeout(pulse, 500);
|
|
||||||
}
|
|
||||||
pulse();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* perform a search for something (or wait until index is loaded)
|
|
||||||
*/
|
|
||||||
performSearch : function(query) {
|
|
||||||
// create the required interface elements
|
|
||||||
this.out = $('#search-results');
|
|
||||||
this.title = $('<h2>' + _('Searching') + '</h2>').appendTo(this.out);
|
|
||||||
this.dots = $('<span></span>').appendTo(this.title);
|
|
||||||
this.status = $('<p style="display: none"></p>').appendTo(this.out);
|
|
||||||
this.output = $('<ul class="search"/>').appendTo(this.out);
|
|
||||||
|
|
||||||
$('#search-progress').text(_('Preparing search...'));
|
|
||||||
this.startPulse();
|
|
||||||
|
|
||||||
// index already loaded, the browser was quick!
|
|
||||||
if (this.hasIndex())
|
|
||||||
this.query(query);
|
|
||||||
else
|
|
||||||
this.deferQuery(query);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* execute search (requires search index to be loaded)
|
|
||||||
*/
|
|
||||||
query : function(query) {
|
|
||||||
var i;
|
|
||||||
var stopwords = ["a","and","are","as","at","be","but","by","for","if","in","into","is","it","near","no","not","of","on","or","such","that","the","their","then","there","these","they","this","to","was","will","with"];
|
|
||||||
|
|
||||||
// stem the searchterms and add them to the correct list
|
|
||||||
var stemmer = new Stemmer();
|
|
||||||
var searchterms = [];
|
|
||||||
var excluded = [];
|
|
||||||
var hlterms = [];
|
|
||||||
var tmp = query.split(/\s+/);
|
|
||||||
var objectterms = [];
|
|
||||||
for (i = 0; i < tmp.length; i++) {
|
|
||||||
if (tmp[i] !== "") {
|
|
||||||
objectterms.push(tmp[i].toLowerCase());
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($u.indexOf(stopwords, tmp[i].toLowerCase()) != -1 || tmp[i].match(/^\d+$/) ||
|
|
||||||
tmp[i] === "") {
|
|
||||||
// skip this "word"
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// stem the word
|
|
||||||
var word = stemmer.stemWord(tmp[i].toLowerCase());
|
|
||||||
var toAppend;
|
|
||||||
// select the correct list
|
|
||||||
if (word[0] == '-') {
|
|
||||||
toAppend = excluded;
|
|
||||||
word = word.substr(1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
toAppend = searchterms;
|
|
||||||
hlterms.push(tmp[i].toLowerCase());
|
|
||||||
}
|
|
||||||
// only add if not already in the list
|
|
||||||
if (!$u.contains(toAppend, word))
|
|
||||||
toAppend.push(word);
|
|
||||||
}
|
|
||||||
var highlightstring = '?highlight=' + $.urlencode(hlterms.join(" "));
|
|
||||||
|
|
||||||
// console.debug('SEARCH: searching for:');
|
|
||||||
// console.info('required: ', searchterms);
|
|
||||||
// console.info('excluded: ', excluded);
|
|
||||||
|
|
||||||
// prepare search
|
|
||||||
var terms = this._index.terms;
|
|
||||||
var titleterms = this._index.titleterms;
|
|
||||||
|
|
||||||
// array of [filename, title, anchor, descr, score]
|
|
||||||
var results = [];
|
|
||||||
$('#search-progress').empty();
|
|
||||||
|
|
||||||
// lookup as object
|
|
||||||
for (i = 0; i < objectterms.length; i++) {
|
|
||||||
var others = [].concat(objectterms.slice(0, i),
|
|
||||||
objectterms.slice(i+1, objectterms.length));
|
|
||||||
results = results.concat(this.performObjectSearch(objectterms[i], others));
|
|
||||||
}
|
|
||||||
|
|
||||||
// lookup as search terms in fulltext
|
|
||||||
results = results.concat(this.performTermsSearch(searchterms, excluded, terms, Scorer.term))
|
|
||||||
.concat(this.performTermsSearch(searchterms, excluded, titleterms, Scorer.title));
|
|
||||||
|
|
||||||
// let the scorer override scores with a custom scoring function
|
|
||||||
if (Scorer.score) {
|
|
||||||
for (i = 0; i < results.length; i++)
|
|
||||||
results[i][4] = Scorer.score(results[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// now sort the results by score (in opposite order of appearance, since the
|
|
||||||
// display function below uses pop() to retrieve items) and then
|
|
||||||
// alphabetically
|
|
||||||
results.sort(function(a, b) {
|
|
||||||
var left = a[4];
|
|
||||||
var right = b[4];
|
|
||||||
if (left > right) {
|
|
||||||
return 1;
|
|
||||||
} else if (left < right) {
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
// same score: sort alphabetically
|
|
||||||
left = a[1].toLowerCase();
|
|
||||||
right = b[1].toLowerCase();
|
|
||||||
return (left > right) ? -1 : ((left < right) ? 1 : 0);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// for debugging
|
|
||||||
//Search.lastresults = results.slice(); // a copy
|
|
||||||
//console.info('search results:', Search.lastresults);
|
|
||||||
|
|
||||||
// print the results
|
|
||||||
var resultCount = results.length;
|
|
||||||
function displayNextItem() {
|
|
||||||
// results left, load the summary and display it
|
|
||||||
if (results.length) {
|
|
||||||
var item = results.pop();
|
|
||||||
var listItem = $('<li style="display:none"></li>');
|
|
||||||
if (DOCUMENTATION_OPTIONS.FILE_SUFFIX === '') {
|
|
||||||
// dirhtml builder
|
|
||||||
var dirname = item[0] + '/';
|
|
||||||
if (dirname.match(/\/index\/$/)) {
|
|
||||||
dirname = dirname.substring(0, dirname.length-6);
|
|
||||||
} else if (dirname == 'index/') {
|
|
||||||
dirname = '';
|
|
||||||
}
|
|
||||||
listItem.append($('<a/>').attr('href',
|
|
||||||
DOCUMENTATION_OPTIONS.URL_ROOT + dirname +
|
|
||||||
highlightstring + item[2]).html(item[1]));
|
|
||||||
} else {
|
|
||||||
// normal html builders
|
|
||||||
listItem.append($('<a/>').attr('href',
|
|
||||||
item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX +
|
|
||||||
highlightstring + item[2]).html(item[1]));
|
|
||||||
}
|
|
||||||
if (item[3]) {
|
|
||||||
listItem.append($('<span> (' + item[3] + ')</span>'));
|
|
||||||
Search.output.append(listItem);
|
|
||||||
listItem.slideDown(5, function() {
|
|
||||||
displayNextItem();
|
|
||||||
});
|
|
||||||
} else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
|
|
||||||
$.ajax({url: DOCUMENTATION_OPTIONS.URL_ROOT + '_sources/' + item[0] + '.txt',
|
|
||||||
dataType: "text",
|
|
||||||
complete: function(jqxhr, textstatus) {
|
|
||||||
var data = jqxhr.responseText;
|
|
||||||
if (data !== '') {
|
|
||||||
listItem.append(Search.makeSearchSummary(data, searchterms, hlterms));
|
|
||||||
}
|
|
||||||
Search.output.append(listItem);
|
|
||||||
listItem.slideDown(5, function() {
|
|
||||||
displayNextItem();
|
|
||||||
});
|
|
||||||
}});
|
|
||||||
} else {
|
|
||||||
// no source available, just display title
|
|
||||||
Search.output.append(listItem);
|
|
||||||
listItem.slideDown(5, function() {
|
|
||||||
displayNextItem();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// search finished, update title and status message
|
|
||||||
else {
|
|
||||||
Search.stopPulse();
|
|
||||||
Search.title.text(_('Search Results'));
|
|
||||||
if (!resultCount)
|
|
||||||
Search.status.text(_('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.'));
|
|
||||||
else
|
|
||||||
Search.status.text(_('Search finished, found %s page(s) matching the search query.').replace('%s', resultCount));
|
|
||||||
Search.status.fadeIn(500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
displayNextItem();
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* search for object names
|
|
||||||
*/
|
|
||||||
performObjectSearch : function(object, otherterms) {
|
|
||||||
var filenames = this._index.filenames;
|
|
||||||
var objects = this._index.objects;
|
|
||||||
var objnames = this._index.objnames;
|
|
||||||
var titles = this._index.titles;
|
|
||||||
|
|
||||||
var i;
|
|
||||||
var results = [];
|
|
||||||
|
|
||||||
for (var prefix in objects) {
|
|
||||||
for (var name in objects[prefix]) {
|
|
||||||
var fullname = (prefix ? prefix + '.' : '') + name;
|
|
||||||
if (fullname.toLowerCase().indexOf(object) > -1) {
|
|
||||||
var score = 0;
|
|
||||||
var parts = fullname.split('.');
|
|
||||||
// check for different match types: exact matches of full name or
|
|
||||||
// "last name" (i.e. last dotted part)
|
|
||||||
if (fullname == object || parts[parts.length - 1] == object) {
|
|
||||||
score += Scorer.objNameMatch;
|
|
||||||
// matches in last name
|
|
||||||
} else if (parts[parts.length - 1].indexOf(object) > -1) {
|
|
||||||
score += Scorer.objPartialMatch;
|
|
||||||
}
|
|
||||||
var match = objects[prefix][name];
|
|
||||||
var objname = objnames[match[1]][2];
|
|
||||||
var title = titles[match[0]];
|
|
||||||
// If more than one term searched for, we require other words to be
|
|
||||||
// found in the name/title/description
|
|
||||||
if (otherterms.length > 0) {
|
|
||||||
var haystack = (prefix + ' ' + name + ' ' +
|
|
||||||
objname + ' ' + title).toLowerCase();
|
|
||||||
var allfound = true;
|
|
||||||
for (i = 0; i < otherterms.length; i++) {
|
|
||||||
if (haystack.indexOf(otherterms[i]) == -1) {
|
|
||||||
allfound = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!allfound) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var descr = objname + _(', in ') + title;
|
|
||||||
|
|
||||||
var anchor = match[3];
|
|
||||||
if (anchor === '')
|
|
||||||
anchor = fullname;
|
|
||||||
else if (anchor == '-')
|
|
||||||
anchor = objnames[match[1]][1] + '-' + fullname;
|
|
||||||
// add custom score for some objects according to scorer
|
|
||||||
if (Scorer.objPrio.hasOwnProperty(match[2])) {
|
|
||||||
score += Scorer.objPrio[match[2]];
|
|
||||||
} else {
|
|
||||||
score += Scorer.objPrioDefault;
|
|
||||||
}
|
|
||||||
results.push([filenames[match[0]], fullname, '#'+anchor, descr, score]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return results;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* search for full-text terms in the index
|
|
||||||
*/
|
|
||||||
performTermsSearch : function(searchterms, excluded, terms, score) {
|
|
||||||
var filenames = this._index.filenames;
|
|
||||||
var titles = this._index.titles;
|
|
||||||
|
|
||||||
var i, j, file, files;
|
|
||||||
var fileMap = {};
|
|
||||||
var results = [];
|
|
||||||
|
|
||||||
// perform the search on the required terms
|
|
||||||
for (i = 0; i < searchterms.length; i++) {
|
|
||||||
var word = searchterms[i];
|
|
||||||
// no match but word was a required one
|
|
||||||
if ((files = terms[word]) === undefined)
|
|
||||||
break;
|
|
||||||
if (files.length === undefined) {
|
|
||||||
files = [files];
|
|
||||||
}
|
|
||||||
// create the mapping
|
|
||||||
for (j = 0; j < files.length; j++) {
|
|
||||||
file = files[j];
|
|
||||||
if (file in fileMap)
|
|
||||||
fileMap[file].push(word);
|
|
||||||
else
|
|
||||||
fileMap[file] = [word];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// now check if the files don't contain excluded terms
|
|
||||||
for (file in fileMap) {
|
|
||||||
var valid = true;
|
|
||||||
|
|
||||||
// check if all requirements are matched
|
|
||||||
if (fileMap[file].length != searchterms.length)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// ensure that none of the excluded terms is in the search result
|
|
||||||
for (i = 0; i < excluded.length; i++) {
|
|
||||||
if (terms[excluded[i]] == file ||
|
|
||||||
$u.contains(terms[excluded[i]] || [], file)) {
|
|
||||||
valid = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we have still a valid result we can add it to the result list
|
|
||||||
if (valid) {
|
|
||||||
results.push([filenames[file], titles[file], '', null, score]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* helper function to return a node containing the
|
|
||||||
* search summary for a given text. keywords is a list
|
|
||||||
* of stemmed words, hlwords is the list of normal, unstemmed
|
|
||||||
* words. the first one is used to find the occurance, the
|
|
||||||
* latter for highlighting it.
|
|
||||||
*/
|
|
||||||
makeSearchSummary : function(text, keywords, hlwords) {
|
|
||||||
var textLower = text.toLowerCase();
|
|
||||||
var start = 0;
|
|
||||||
$.each(keywords, function() {
|
|
||||||
var i = textLower.indexOf(this.toLowerCase());
|
|
||||||
if (i > -1)
|
|
||||||
start = i;
|
|
||||||
});
|
|
||||||
start = Math.max(start - 120, 0);
|
|
||||||
var excerpt = ((start > 0) ? '...' : '') +
|
|
||||||
$.trim(text.substr(start, 240)) +
|
|
||||||
((start + 240 - text.length) ? '...' : '');
|
|
||||||
var rv = $('<div class="context"></div>').text(excerpt);
|
|
||||||
$.each(hlwords, function() {
|
|
||||||
rv = rv.highlightText(this, 'highlighted');
|
|
||||||
});
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$(document).ready(function() {
|
|
||||||
Search.init();
|
|
||||||
});
|
|
@ -1,339 +0,0 @@
|
|||||||
/*
|
|
||||||
* sphinxdoc.css_t
|
|
||||||
* ~~~~~~~~~~~~~~~
|
|
||||||
*
|
|
||||||
* Sphinx stylesheet -- sphinxdoc theme. Originally created by
|
|
||||||
* Armin Ronacher for Werkzeug.
|
|
||||||
*
|
|
||||||
* :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
|
|
||||||
* :license: BSD, see LICENSE for details.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
@import url("basic.css");
|
|
||||||
|
|
||||||
/* -- page layout ----------------------------------------------------------- */
|
|
||||||
|
|
||||||
body {
|
|
||||||
font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
|
|
||||||
'Verdana', sans-serif;
|
|
||||||
font-size: 14px;
|
|
||||||
letter-spacing: -0.01em;
|
|
||||||
line-height: 150%;
|
|
||||||
text-align: center;
|
|
||||||
background-color: #BFD1D4;
|
|
||||||
color: black;
|
|
||||||
padding: 0;
|
|
||||||
border: 1px solid #aaa;
|
|
||||||
|
|
||||||
margin: 0px 80px 0px 80px;
|
|
||||||
min-width: 740px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.document {
|
|
||||||
background-color: white;
|
|
||||||
text-align: left;
|
|
||||||
background-image: url(contents.png);
|
|
||||||
background-repeat: repeat-x;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.bodywrapper {
|
|
||||||
margin: 0 240px 0 0;
|
|
||||||
border-right: 1px solid #ccc;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.body {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0.5em 20px 20px 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.related {
|
|
||||||
font-size: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.related ul {
|
|
||||||
background-image: url(navigation.png);
|
|
||||||
height: 2em;
|
|
||||||
border-top: 1px solid #ddd;
|
|
||||||
border-bottom: 1px solid #ddd;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.related ul li {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
height: 2em;
|
|
||||||
float: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.related ul li.right {
|
|
||||||
float: right;
|
|
||||||
margin-right: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.related ul li a {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0 5px 0 5px;
|
|
||||||
line-height: 1.75em;
|
|
||||||
color: #EE9816;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.related ul li a:hover {
|
|
||||||
color: #3CA8E7;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.sphinxsidebarwrapper {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.sphinxsidebar {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0.5em 15px 15px 0;
|
|
||||||
width: 210px;
|
|
||||||
float: right;
|
|
||||||
font-size: 1em;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.sphinxsidebar h3, div.sphinxsidebar h4 {
|
|
||||||
margin: 1em 0 0.5em 0;
|
|
||||||
font-size: 1em;
|
|
||||||
padding: 0.1em 0 0.1em 0.5em;
|
|
||||||
color: white;
|
|
||||||
border: 1px solid #86989B;
|
|
||||||
background-color: #AFC1C4;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.sphinxsidebar h3 a {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.sphinxsidebar ul {
|
|
||||||
padding-left: 1.5em;
|
|
||||||
margin-top: 7px;
|
|
||||||
padding: 0;
|
|
||||||
line-height: 130%;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.sphinxsidebar ul ul {
|
|
||||||
margin-left: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.footer {
|
|
||||||
background-color: #E3EFF1;
|
|
||||||
color: #86989B;
|
|
||||||
padding: 3px 8px 3px 0;
|
|
||||||
clear: both;
|
|
||||||
font-size: 0.8em;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.footer a {
|
|
||||||
color: #86989B;
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -- body styles ----------------------------------------------------------- */
|
|
||||||
|
|
||||||
p {
|
|
||||||
margin: 0.8em 0 0.5em 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: #CA7900;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:hover {
|
|
||||||
color: #2491CF;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.body a {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0.7em 0 0.3em 0;
|
|
||||||
font-size: 1.5em;
|
|
||||||
color: #11557C;
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
margin: 1.3em 0 0.2em 0;
|
|
||||||
font-size: 1.35em;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
margin: 1em 0 -0.3em 0;
|
|
||||||
font-size: 1.2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.body h1 a, div.body h2 a, div.body h3 a, div.body h4 a, div.body h5 a, div.body h6 a {
|
|
||||||
color: black!important;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 a.anchor, h2 a.anchor, h3 a.anchor, h4 a.anchor, h5 a.anchor, h6 a.anchor {
|
|
||||||
display: none;
|
|
||||||
margin: 0 0 0 0.3em;
|
|
||||||
padding: 0 0.2em 0 0.2em;
|
|
||||||
color: #aaa!important;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor,
|
|
||||||
h5:hover a.anchor, h6:hover a.anchor {
|
|
||||||
display: inline;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 a.anchor:hover, h2 a.anchor:hover, h3 a.anchor:hover, h4 a.anchor:hover,
|
|
||||||
h5 a.anchor:hover, h6 a.anchor:hover {
|
|
||||||
color: #777;
|
|
||||||
background-color: #eee;
|
|
||||||
}
|
|
||||||
|
|
||||||
a.headerlink {
|
|
||||||
color: #c60f0f!important;
|
|
||||||
font-size: 1em;
|
|
||||||
margin-left: 6px;
|
|
||||||
padding: 0 4px 0 4px;
|
|
||||||
text-decoration: none!important;
|
|
||||||
}
|
|
||||||
|
|
||||||
a.headerlink:hover {
|
|
||||||
background-color: #ccc;
|
|
||||||
color: white!important;
|
|
||||||
}
|
|
||||||
|
|
||||||
cite, code, tt {
|
|
||||||
font-family: 'Consolas', 'Deja Vu Sans Mono',
|
|
||||||
'Bitstream Vera Sans Mono', monospace;
|
|
||||||
font-size: 0.95em;
|
|
||||||
letter-spacing: 0.01em;
|
|
||||||
}
|
|
||||||
|
|
||||||
tt {
|
|
||||||
background-color: #f2f2f2;
|
|
||||||
border-bottom: 1px solid #ddd;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
tt.descname, tt.descclassname, tt.xref {
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr {
|
|
||||||
border: 1px solid #abc;
|
|
||||||
margin: 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
a tt {
|
|
||||||
border: 0;
|
|
||||||
color: #CA7900;
|
|
||||||
}
|
|
||||||
|
|
||||||
a tt:hover {
|
|
||||||
color: #2491CF;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre {
|
|
||||||
font-family: 'Consolas', 'Deja Vu Sans Mono',
|
|
||||||
'Bitstream Vera Sans Mono', monospace;
|
|
||||||
font-size: 0.95em;
|
|
||||||
letter-spacing: 0.015em;
|
|
||||||
line-height: 120%;
|
|
||||||
padding: 0.5em;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
background-color: #f8f8f8;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre a {
|
|
||||||
color: inherit;
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
td.linenos pre {
|
|
||||||
padding: 0.5em 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.quotebar {
|
|
||||||
background-color: #f8f8f8;
|
|
||||||
max-width: 250px;
|
|
||||||
float: right;
|
|
||||||
padding: 2px 7px;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.topic {
|
|
||||||
background-color: #f8f8f8;
|
|
||||||
}
|
|
||||||
|
|
||||||
table {
|
|
||||||
border-collapse: collapse;
|
|
||||||
margin: 0 -0.5em 0 -0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
table td, table th {
|
|
||||||
padding: 0.2em 0.5em 0.2em 0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.admonition, div.warning {
|
|
||||||
font-size: 0.9em;
|
|
||||||
margin: 1em 0 1em 0;
|
|
||||||
border: 1px solid #86989B;
|
|
||||||
background-color: #f7f7f7;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.admonition p, div.warning p {
|
|
||||||
margin: 0.5em 1em 0.5em 1em;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.admonition pre, div.warning pre {
|
|
||||||
margin: 0.4em 1em 0.4em 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.admonition p.admonition-title,
|
|
||||||
div.warning p.admonition-title {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0.1em 0 0.1em 0.5em;
|
|
||||||
color: white;
|
|
||||||
border-bottom: 1px solid #86989B;
|
|
||||||
font-weight: bold;
|
|
||||||
background-color: #AFC1C4;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.warning {
|
|
||||||
border: 1px solid #940000;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.warning p.admonition-title {
|
|
||||||
background-color: #CF0000;
|
|
||||||
border-bottom-color: #940000;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.admonition ul, div.admonition ol,
|
|
||||||
div.warning ul, div.warning ol {
|
|
||||||
margin: 0.1em 0.5em 0.5em 3em;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.versioninfo {
|
|
||||||
margin: 1em 0 0 0;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
background-color: #DDEAF0;
|
|
||||||
padding: 8px;
|
|
||||||
line-height: 1.3em;
|
|
||||||
font-size: 0.9em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.viewcode-back {
|
|
||||||
font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
|
|
||||||
'Verdana', sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.viewcode-block:target {
|
|
||||||
background-color: #f4debf;
|
|
||||||
border-top: 1px solid #ac9;
|
|
||||||
border-bottom: 1px solid #ac9;
|
|
||||||
}
|
|
Before Width: | Height: | Size: 372 B |
Before Width: | Height: | Size: 363 B |
@ -1,808 +0,0 @@
|
|||||||
/*
|
|
||||||
* websupport.js
|
|
||||||
* ~~~~~~~~~~~~~
|
|
||||||
*
|
|
||||||
* sphinx.websupport utilties for all documentation.
|
|
||||||
*
|
|
||||||
* :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS.
|
|
||||||
* :license: BSD, see LICENSE for details.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
(function($) {
|
|
||||||
$.fn.autogrow = function() {
|
|
||||||
return this.each(function() {
|
|
||||||
var textarea = this;
|
|
||||||
|
|
||||||
$.fn.autogrow.resize(textarea);
|
|
||||||
|
|
||||||
$(textarea)
|
|
||||||
.focus(function() {
|
|
||||||
textarea.interval = setInterval(function() {
|
|
||||||
$.fn.autogrow.resize(textarea);
|
|
||||||
}, 500);
|
|
||||||
})
|
|
||||||
.blur(function() {
|
|
||||||
clearInterval(textarea.interval);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
$.fn.autogrow.resize = function(textarea) {
|
|
||||||
var lineHeight = parseInt($(textarea).css('line-height'), 10);
|
|
||||||
var lines = textarea.value.split('\n');
|
|
||||||
var columns = textarea.cols;
|
|
||||||
var lineCount = 0;
|
|
||||||
$.each(lines, function() {
|
|
||||||
lineCount += Math.ceil(this.length / columns) || 1;
|
|
||||||
});
|
|
||||||
var height = lineHeight * (lineCount + 1);
|
|
||||||
$(textarea).css('height', height);
|
|
||||||
};
|
|
||||||
})(jQuery);
|
|
||||||
|
|
||||||
(function($) {
|
|
||||||
var comp, by;
|
|
||||||
|
|
||||||
function init() {
|
|
||||||
initEvents();
|
|
||||||
initComparator();
|
|
||||||
}
|
|
||||||
|
|
||||||
function initEvents() {
|
|
||||||
$('a.comment-close').live("click", function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
hide($(this).attr('id').substring(2));
|
|
||||||
});
|
|
||||||
$('a.vote').live("click", function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
handleVote($(this));
|
|
||||||
});
|
|
||||||
$('a.reply').live("click", function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
openReply($(this).attr('id').substring(2));
|
|
||||||
});
|
|
||||||
$('a.close-reply').live("click", function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
closeReply($(this).attr('id').substring(2));
|
|
||||||
});
|
|
||||||
$('a.sort-option').live("click", function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
handleReSort($(this));
|
|
||||||
});
|
|
||||||
$('a.show-proposal').live("click", function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
showProposal($(this).attr('id').substring(2));
|
|
||||||
});
|
|
||||||
$('a.hide-proposal').live("click", function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
hideProposal($(this).attr('id').substring(2));
|
|
||||||
});
|
|
||||||
$('a.show-propose-change').live("click", function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
showProposeChange($(this).attr('id').substring(2));
|
|
||||||
});
|
|
||||||
$('a.hide-propose-change').live("click", function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
hideProposeChange($(this).attr('id').substring(2));
|
|
||||||
});
|
|
||||||
$('a.accept-comment').live("click", function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
acceptComment($(this).attr('id').substring(2));
|
|
||||||
});
|
|
||||||
$('a.delete-comment').live("click", function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
deleteComment($(this).attr('id').substring(2));
|
|
||||||
});
|
|
||||||
$('a.comment-markup').live("click", function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
toggleCommentMarkupBox($(this).attr('id').substring(2));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set comp, which is a comparator function used for sorting and
|
|
||||||
* inserting comments into the list.
|
|
||||||
*/
|
|
||||||
function setComparator() {
|
|
||||||
// If the first three letters are "asc", sort in ascending order
|
|
||||||
// and remove the prefix.
|
|
||||||
if (by.substring(0,3) == 'asc') {
|
|
||||||
var i = by.substring(3);
|
|
||||||
comp = function(a, b) { return a[i] - b[i]; };
|
|
||||||
} else {
|
|
||||||
// Otherwise sort in descending order.
|
|
||||||
comp = function(a, b) { return b[by] - a[by]; };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset link styles and format the selected sort option.
|
|
||||||
$('a.sel').attr('href', '#').removeClass('sel');
|
|
||||||
$('a.by' + by).removeAttr('href').addClass('sel');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a comp function. If the user has preferences stored in
|
|
||||||
* the sortBy cookie, use those, otherwise use the default.
|
|
||||||
*/
|
|
||||||
function initComparator() {
|
|
||||||
by = 'rating'; // Default to sort by rating.
|
|
||||||
// If the sortBy cookie is set, use that instead.
|
|
||||||
if (document.cookie.length > 0) {
|
|
||||||
var start = document.cookie.indexOf('sortBy=');
|
|
||||||
if (start != -1) {
|
|
||||||
start = start + 7;
|
|
||||||
var end = document.cookie.indexOf(";", start);
|
|
||||||
if (end == -1) {
|
|
||||||
end = document.cookie.length;
|
|
||||||
by = unescape(document.cookie.substring(start, end));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setComparator();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show a comment div.
|
|
||||||
*/
|
|
||||||
function show(id) {
|
|
||||||
$('#ao' + id).hide();
|
|
||||||
$('#ah' + id).show();
|
|
||||||
var context = $.extend({id: id}, opts);
|
|
||||||
var popup = $(renderTemplate(popupTemplate, context)).hide();
|
|
||||||
popup.find('textarea[name="proposal"]').hide();
|
|
||||||
popup.find('a.by' + by).addClass('sel');
|
|
||||||
var form = popup.find('#cf' + id);
|
|
||||||
form.submit(function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
addComment(form);
|
|
||||||
});
|
|
||||||
$('#s' + id).after(popup);
|
|
||||||
popup.slideDown('fast', function() {
|
|
||||||
getComments(id);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hide a comment div.
|
|
||||||
*/
|
|
||||||
function hide(id) {
|
|
||||||
$('#ah' + id).hide();
|
|
||||||
$('#ao' + id).show();
|
|
||||||
var div = $('#sc' + id);
|
|
||||||
div.slideUp('fast', function() {
|
|
||||||
div.remove();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Perform an ajax request to get comments for a node
|
|
||||||
* and insert the comments into the comments tree.
|
|
||||||
*/
|
|
||||||
function getComments(id) {
|
|
||||||
$.ajax({
|
|
||||||
type: 'GET',
|
|
||||||
url: opts.getCommentsURL,
|
|
||||||
data: {node: id},
|
|
||||||
success: function(data, textStatus, request) {
|
|
||||||
var ul = $('#cl' + id);
|
|
||||||
var speed = 100;
|
|
||||||
$('#cf' + id)
|
|
||||||
.find('textarea[name="proposal"]')
|
|
||||||
.data('source', data.source);
|
|
||||||
|
|
||||||
if (data.comments.length === 0) {
|
|
||||||
ul.html('<li>No comments yet.</li>');
|
|
||||||
ul.data('empty', true);
|
|
||||||
} else {
|
|
||||||
// If there are comments, sort them and put them in the list.
|
|
||||||
var comments = sortComments(data.comments);
|
|
||||||
speed = data.comments.length * 100;
|
|
||||||
appendComments(comments, ul);
|
|
||||||
ul.data('empty', false);
|
|
||||||
}
|
|
||||||
$('#cn' + id).slideUp(speed + 200);
|
|
||||||
ul.slideDown(speed);
|
|
||||||
},
|
|
||||||
error: function(request, textStatus, error) {
|
|
||||||
showError('Oops, there was a problem retrieving the comments.');
|
|
||||||
},
|
|
||||||
dataType: 'json'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a comment via ajax and insert the comment into the comment tree.
|
|
||||||
*/
|
|
||||||
function addComment(form) {
|
|
||||||
var node_id = form.find('input[name="node"]').val();
|
|
||||||
var parent_id = form.find('input[name="parent"]').val();
|
|
||||||
var text = form.find('textarea[name="comment"]').val();
|
|
||||||
var proposal = form.find('textarea[name="proposal"]').val();
|
|
||||||
|
|
||||||
if (text == '') {
|
|
||||||
showError('Please enter a comment.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable the form that is being submitted.
|
|
||||||
form.find('textarea,input').attr('disabled', 'disabled');
|
|
||||||
|
|
||||||
// Send the comment to the server.
|
|
||||||
$.ajax({
|
|
||||||
type: "POST",
|
|
||||||
url: opts.addCommentURL,
|
|
||||||
dataType: 'json',
|
|
||||||
data: {
|
|
||||||
node: node_id,
|
|
||||||
parent: parent_id,
|
|
||||||
text: text,
|
|
||||||
proposal: proposal
|
|
||||||
},
|
|
||||||
success: function(data, textStatus, error) {
|
|
||||||
// Reset the form.
|
|
||||||
if (node_id) {
|
|
||||||
hideProposeChange(node_id);
|
|
||||||
}
|
|
||||||
form.find('textarea')
|
|
||||||
.val('')
|
|
||||||
.add(form.find('input'))
|
|
||||||
.removeAttr('disabled');
|
|
||||||
var ul = $('#cl' + (node_id || parent_id));
|
|
||||||
if (ul.data('empty')) {
|
|
||||||
$(ul).empty();
|
|
||||||
ul.data('empty', false);
|
|
||||||
}
|
|
||||||
insertComment(data.comment);
|
|
||||||
var ao = $('#ao' + node_id);
|
|
||||||
ao.find('img').attr({'src': opts.commentBrightImage});
|
|
||||||
if (node_id) {
|
|
||||||
// if this was a "root" comment, remove the commenting box
|
|
||||||
// (the user can get it back by reopening the comment popup)
|
|
||||||
$('#ca' + node_id).slideUp();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
error: function(request, textStatus, error) {
|
|
||||||
form.find('textarea,input').removeAttr('disabled');
|
|
||||||
showError('Oops, there was a problem adding the comment.');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recursively append comments to the main comment list and children
|
|
||||||
* lists, creating the comment tree.
|
|
||||||
*/
|
|
||||||
function appendComments(comments, ul) {
|
|
||||||
$.each(comments, function() {
|
|
||||||
var div = createCommentDiv(this);
|
|
||||||
ul.append($(document.createElement('li')).html(div));
|
|
||||||
appendComments(this.children, div.find('ul.comment-children'));
|
|
||||||
// To avoid stagnating data, don't store the comments children in data.
|
|
||||||
this.children = null;
|
|
||||||
div.data('comment', this);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* After adding a new comment, it must be inserted in the correct
|
|
||||||
* location in the comment tree.
|
|
||||||
*/
|
|
||||||
function insertComment(comment) {
|
|
||||||
var div = createCommentDiv(comment);
|
|
||||||
|
|
||||||
// To avoid stagnating data, don't store the comments children in data.
|
|
||||||
comment.children = null;
|
|
||||||
div.data('comment', comment);
|
|
||||||
|
|
||||||
var ul = $('#cl' + (comment.node || comment.parent));
|
|
||||||
var siblings = getChildren(ul);
|
|
||||||
|
|
||||||
var li = $(document.createElement('li'));
|
|
||||||
li.hide();
|
|
||||||
|
|
||||||
// Determine where in the parents children list to insert this comment.
|
|
||||||
for(i=0; i < siblings.length; i++) {
|
|
||||||
if (comp(comment, siblings[i]) <= 0) {
|
|
||||||
$('#cd' + siblings[i].id)
|
|
||||||
.parent()
|
|
||||||
.before(li.html(div));
|
|
||||||
li.slideDown('fast');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we get here, this comment rates lower than all the others,
|
|
||||||
// or it is the only comment in the list.
|
|
||||||
ul.append(li.html(div));
|
|
||||||
li.slideDown('fast');
|
|
||||||
}
|
|
||||||
|
|
||||||
function acceptComment(id) {
|
|
||||||
$.ajax({
|
|
||||||
type: 'POST',
|
|
||||||
url: opts.acceptCommentURL,
|
|
||||||
data: {id: id},
|
|
||||||
success: function(data, textStatus, request) {
|
|
||||||
$('#cm' + id).fadeOut('fast');
|
|
||||||
$('#cd' + id).removeClass('moderate');
|
|
||||||
},
|
|
||||||
error: function(request, textStatus, error) {
|
|
||||||
showError('Oops, there was a problem accepting the comment.');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function deleteComment(id) {
|
|
||||||
$.ajax({
|
|
||||||
type: 'POST',
|
|
||||||
url: opts.deleteCommentURL,
|
|
||||||
data: {id: id},
|
|
||||||
success: function(data, textStatus, request) {
|
|
||||||
var div = $('#cd' + id);
|
|
||||||
if (data == 'delete') {
|
|
||||||
// Moderator mode: remove the comment and all children immediately
|
|
||||||
div.slideUp('fast', function() {
|
|
||||||
div.remove();
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// User mode: only mark the comment as deleted
|
|
||||||
div
|
|
||||||
.find('span.user-id:first')
|
|
||||||
.text('[deleted]').end()
|
|
||||||
.find('div.comment-text:first')
|
|
||||||
.text('[deleted]').end()
|
|
||||||
.find('#cm' + id + ', #dc' + id + ', #ac' + id + ', #rc' + id +
|
|
||||||
', #sp' + id + ', #hp' + id + ', #cr' + id + ', #rl' + id)
|
|
||||||
.remove();
|
|
||||||
var comment = div.data('comment');
|
|
||||||
comment.username = '[deleted]';
|
|
||||||
comment.text = '[deleted]';
|
|
||||||
div.data('comment', comment);
|
|
||||||
},
|
|
||||||
error: function(request, textStatus, error) {
|
|
||||||
showError('Oops, there was a problem deleting the comment.');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function showProposal(id) {
|
|
||||||
$('#sp' + id).hide();
|
|
||||||
$('#hp' + id).show();
|
|
||||||
$('#pr' + id).slideDown('fast');
|
|
||||||
}
|
|
||||||
|
|
||||||
function hideProposal(id) {
|
|
||||||
$('#hp' + id).hide();
|
|
||||||
$('#sp' + id).show();
|
|
||||||
$('#pr' + id).slideUp('fast');
|
|
||||||
}
|
|
||||||
|
|
||||||
function showProposeChange(id) {
|
|
||||||
$('#pc' + id).hide();
|
|
||||||
$('#hc' + id).show();
|
|
||||||
var textarea = $('#pt' + id);
|
|
||||||
textarea.val(textarea.data('source'));
|
|
||||||
$.fn.autogrow.resize(textarea[0]);
|
|
||||||
textarea.slideDown('fast');
|
|
||||||
}
|
|
||||||
|
|
||||||
function hideProposeChange(id) {
|
|
||||||
$('#hc' + id).hide();
|
|
||||||
$('#pc' + id).show();
|
|
||||||
var textarea = $('#pt' + id);
|
|
||||||
textarea.val('').removeAttr('disabled');
|
|
||||||
textarea.slideUp('fast');
|
|
||||||
}
|
|
||||||
|
|
||||||
function toggleCommentMarkupBox(id) {
|
|
||||||
$('#mb' + id).toggle();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Handle when the user clicks on a sort by link. */
|
|
||||||
function handleReSort(link) {
|
|
||||||
var classes = link.attr('class').split(/\s+/);
|
|
||||||
for (var i=0; i<classes.length; i++) {
|
|
||||||
if (classes[i] != 'sort-option') {
|
|
||||||
by = classes[i].substring(2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setComparator();
|
|
||||||
// Save/update the sortBy cookie.
|
|
||||||
var expiration = new Date();
|
|
||||||
expiration.setDate(expiration.getDate() + 365);
|
|
||||||
document.cookie= 'sortBy=' + escape(by) +
|
|
||||||
';expires=' + expiration.toUTCString();
|
|
||||||
$('ul.comment-ul').each(function(index, ul) {
|
|
||||||
var comments = getChildren($(ul), true);
|
|
||||||
comments = sortComments(comments);
|
|
||||||
appendComments(comments, $(ul).empty());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to process a vote when a user clicks an arrow.
|
|
||||||
*/
|
|
||||||
function handleVote(link) {
|
|
||||||
if (!opts.voting) {
|
|
||||||
showError("You'll need to login to vote.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var id = link.attr('id');
|
|
||||||
if (!id) {
|
|
||||||
// Didn't click on one of the voting arrows.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// If it is an unvote, the new vote value is 0,
|
|
||||||
// Otherwise it's 1 for an upvote, or -1 for a downvote.
|
|
||||||
var value = 0;
|
|
||||||
if (id.charAt(1) != 'u') {
|
|
||||||
value = id.charAt(0) == 'u' ? 1 : -1;
|
|
||||||
}
|
|
||||||
// The data to be sent to the server.
|
|
||||||
var d = {
|
|
||||||
comment_id: id.substring(2),
|
|
||||||
value: value
|
|
||||||
};
|
|
||||||
|
|
||||||
// Swap the vote and unvote links.
|
|
||||||
link.hide();
|
|
||||||
$('#' + id.charAt(0) + (id.charAt(1) == 'u' ? 'v' : 'u') + d.comment_id)
|
|
||||||
.show();
|
|
||||||
|
|
||||||
// The div the comment is displayed in.
|
|
||||||
var div = $('div#cd' + d.comment_id);
|
|
||||||
var data = div.data('comment');
|
|
||||||
|
|
||||||
// If this is not an unvote, and the other vote arrow has
|
|
||||||
// already been pressed, unpress it.
|
|
||||||
if ((d.value !== 0) && (data.vote === d.value * -1)) {
|
|
||||||
$('#' + (d.value == 1 ? 'd' : 'u') + 'u' + d.comment_id).hide();
|
|
||||||
$('#' + (d.value == 1 ? 'd' : 'u') + 'v' + d.comment_id).show();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the comments rating in the local data.
|
|
||||||
data.rating += (data.vote === 0) ? d.value : (d.value - data.vote);
|
|
||||||
data.vote = d.value;
|
|
||||||
div.data('comment', data);
|
|
||||||
|
|
||||||
// Change the rating text.
|
|
||||||
div.find('.rating:first')
|
|
||||||
.text(data.rating + ' point' + (data.rating == 1 ? '' : 's'));
|
|
||||||
|
|
||||||
// Send the vote information to the server.
|
|
||||||
$.ajax({
|
|
||||||
type: "POST",
|
|
||||||
url: opts.processVoteURL,
|
|
||||||
data: d,
|
|
||||||
error: function(request, textStatus, error) {
|
|
||||||
showError('Oops, there was a problem casting that vote.');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Open a reply form used to reply to an existing comment.
|
|
||||||
*/
|
|
||||||
function openReply(id) {
|
|
||||||
// Swap out the reply link for the hide link
|
|
||||||
$('#rl' + id).hide();
|
|
||||||
$('#cr' + id).show();
|
|
||||||
|
|
||||||
// Add the reply li to the children ul.
|
|
||||||
var div = $(renderTemplate(replyTemplate, {id: id})).hide();
|
|
||||||
$('#cl' + id)
|
|
||||||
.prepend(div)
|
|
||||||
// Setup the submit handler for the reply form.
|
|
||||||
.find('#rf' + id)
|
|
||||||
.submit(function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
addComment($('#rf' + id));
|
|
||||||
closeReply(id);
|
|
||||||
})
|
|
||||||
.find('input[type=button]')
|
|
||||||
.click(function() {
|
|
||||||
closeReply(id);
|
|
||||||
});
|
|
||||||
div.slideDown('fast', function() {
|
|
||||||
$('#rf' + id).find('textarea').focus();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close the reply form opened with openReply.
|
|
||||||
*/
|
|
||||||
function closeReply(id) {
|
|
||||||
// Remove the reply div from the DOM.
|
|
||||||
$('#rd' + id).slideUp('fast', function() {
|
|
||||||
$(this).remove();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Swap out the hide link for the reply link
|
|
||||||
$('#cr' + id).hide();
|
|
||||||
$('#rl' + id).show();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recursively sort a tree of comments using the comp comparator.
|
|
||||||
*/
|
|
||||||
function sortComments(comments) {
|
|
||||||
comments.sort(comp);
|
|
||||||
$.each(comments, function() {
|
|
||||||
this.children = sortComments(this.children);
|
|
||||||
});
|
|
||||||
return comments;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the children comments from a ul. If recursive is true,
|
|
||||||
* recursively include childrens' children.
|
|
||||||
*/
|
|
||||||
function getChildren(ul, recursive) {
|
|
||||||
var children = [];
|
|
||||||
ul.children().children("[id^='cd']")
|
|
||||||
.each(function() {
|
|
||||||
var comment = $(this).data('comment');
|
|
||||||
if (recursive)
|
|
||||||
comment.children = getChildren($(this).find('#cl' + comment.id), true);
|
|
||||||
children.push(comment);
|
|
||||||
});
|
|
||||||
return children;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Create a div to display a comment in. */
|
|
||||||
function createCommentDiv(comment) {
|
|
||||||
if (!comment.displayed && !opts.moderator) {
|
|
||||||
return $('<div class="moderate">Thank you! Your comment will show up '
|
|
||||||
+ 'once it is has been approved by a moderator.</div>');
|
|
||||||
}
|
|
||||||
// Prettify the comment rating.
|
|
||||||
comment.pretty_rating = comment.rating + ' point' +
|
|
||||||
(comment.rating == 1 ? '' : 's');
|
|
||||||
// Make a class (for displaying not yet moderated comments differently)
|
|
||||||
comment.css_class = comment.displayed ? '' : ' moderate';
|
|
||||||
// Create a div for this comment.
|
|
||||||
var context = $.extend({}, opts, comment);
|
|
||||||
var div = $(renderTemplate(commentTemplate, context));
|
|
||||||
|
|
||||||
// If the user has voted on this comment, highlight the correct arrow.
|
|
||||||
if (comment.vote) {
|
|
||||||
var direction = (comment.vote == 1) ? 'u' : 'd';
|
|
||||||
div.find('#' + direction + 'v' + comment.id).hide();
|
|
||||||
div.find('#' + direction + 'u' + comment.id).show();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opts.moderator || comment.text != '[deleted]') {
|
|
||||||
div.find('a.reply').show();
|
|
||||||
if (comment.proposal_diff)
|
|
||||||
div.find('#sp' + comment.id).show();
|
|
||||||
if (opts.moderator && !comment.displayed)
|
|
||||||
div.find('#cm' + comment.id).show();
|
|
||||||
if (opts.moderator || (opts.username == comment.username))
|
|
||||||
div.find('#dc' + comment.id).show();
|
|
||||||
}
|
|
||||||
return div;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A simple template renderer. Placeholders such as <%id%> are replaced
|
|
||||||
* by context['id'] with items being escaped. Placeholders such as <#id#>
|
|
||||||
* are not escaped.
|
|
||||||
*/
|
|
||||||
function renderTemplate(template, context) {
|
|
||||||
var esc = $(document.createElement('div'));
|
|
||||||
|
|
||||||
function handle(ph, escape) {
|
|
||||||
var cur = context;
|
|
||||||
$.each(ph.split('.'), function() {
|
|
||||||
cur = cur[this];
|
|
||||||
});
|
|
||||||
return escape ? esc.text(cur || "").html() : cur;
|
|
||||||
}
|
|
||||||
|
|
||||||
return template.replace(/<([%#])([\w\.]*)\1>/g, function() {
|
|
||||||
return handle(arguments[2], arguments[1] == '%' ? true : false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Flash an error message briefly. */
|
|
||||||
function showError(message) {
|
|
||||||
$(document.createElement('div')).attr({'class': 'popup-error'})
|
|
||||||
.append($(document.createElement('div'))
|
|
||||||
.attr({'class': 'error-message'}).text(message))
|
|
||||||
.appendTo('body')
|
|
||||||
.fadeIn("slow")
|
|
||||||
.delay(2000)
|
|
||||||
.fadeOut("slow");
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Add a link the user uses to open the comments popup. */
|
|
||||||
$.fn.comment = function() {
|
|
||||||
return this.each(function() {
|
|
||||||
var id = $(this).attr('id').substring(1);
|
|
||||||
var count = COMMENT_METADATA[id];
|
|
||||||
var title = count + ' comment' + (count == 1 ? '' : 's');
|
|
||||||
var image = count > 0 ? opts.commentBrightImage : opts.commentImage;
|
|
||||||
var addcls = count == 0 ? ' nocomment' : '';
|
|
||||||
$(this)
|
|
||||||
.append(
|
|
||||||
$(document.createElement('a')).attr({
|
|
||||||
href: '#',
|
|
||||||
'class': 'sphinx-comment-open' + addcls,
|
|
||||||
id: 'ao' + id
|
|
||||||
})
|
|
||||||
.append($(document.createElement('img')).attr({
|
|
||||||
src: image,
|
|
||||||
alt: 'comment',
|
|
||||||
title: title
|
|
||||||
}))
|
|
||||||
.click(function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
show($(this).attr('id').substring(2));
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.append(
|
|
||||||
$(document.createElement('a')).attr({
|
|
||||||
href: '#',
|
|
||||||
'class': 'sphinx-comment-close hidden',
|
|
||||||
id: 'ah' + id
|
|
||||||
})
|
|
||||||
.append($(document.createElement('img')).attr({
|
|
||||||
src: opts.closeCommentImage,
|
|
||||||
alt: 'close',
|
|
||||||
title: 'close'
|
|
||||||
}))
|
|
||||||
.click(function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
hide($(this).attr('id').substring(2));
|
|
||||||
})
|
|
||||||
);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
var opts = {
|
|
||||||
processVoteURL: '/_process_vote',
|
|
||||||
addCommentURL: '/_add_comment',
|
|
||||||
getCommentsURL: '/_get_comments',
|
|
||||||
acceptCommentURL: '/_accept_comment',
|
|
||||||
deleteCommentURL: '/_delete_comment',
|
|
||||||
commentImage: '/static/_static/comment.png',
|
|
||||||
closeCommentImage: '/static/_static/comment-close.png',
|
|
||||||
loadingImage: '/static/_static/ajax-loader.gif',
|
|
||||||
commentBrightImage: '/static/_static/comment-bright.png',
|
|
||||||
upArrow: '/static/_static/up.png',
|
|
||||||
downArrow: '/static/_static/down.png',
|
|
||||||
upArrowPressed: '/static/_static/up-pressed.png',
|
|
||||||
downArrowPressed: '/static/_static/down-pressed.png',
|
|
||||||
voting: false,
|
|
||||||
moderator: false
|
|
||||||
};
|
|
||||||
|
|
||||||
if (typeof COMMENT_OPTIONS != "undefined") {
|
|
||||||
opts = jQuery.extend(opts, COMMENT_OPTIONS);
|
|
||||||
}
|
|
||||||
|
|
||||||
var popupTemplate = '\
|
|
||||||
<div class="sphinx-comments" id="sc<%id%>">\
|
|
||||||
<p class="sort-options">\
|
|
||||||
Sort by:\
|
|
||||||
<a href="#" class="sort-option byrating">best rated</a>\
|
|
||||||
<a href="#" class="sort-option byascage">newest</a>\
|
|
||||||
<a href="#" class="sort-option byage">oldest</a>\
|
|
||||||
</p>\
|
|
||||||
<div class="comment-header">Comments</div>\
|
|
||||||
<div class="comment-loading" id="cn<%id%>">\
|
|
||||||
loading comments... <img src="<%loadingImage%>" alt="" /></div>\
|
|
||||||
<ul id="cl<%id%>" class="comment-ul"></ul>\
|
|
||||||
<div id="ca<%id%>">\
|
|
||||||
<p class="add-a-comment">Add a comment\
|
|
||||||
(<a href="#" class="comment-markup" id="ab<%id%>">markup</a>):</p>\
|
|
||||||
<div class="comment-markup-box" id="mb<%id%>">\
|
|
||||||
reStructured text markup: <i>*emph*</i>, <b>**strong**</b>, \
|
|
||||||
<tt>``code``</tt>, \
|
|
||||||
code blocks: <tt>::</tt> and an indented block after blank line</div>\
|
|
||||||
<form method="post" id="cf<%id%>" class="comment-form" action="">\
|
|
||||||
<textarea name="comment" cols="80"></textarea>\
|
|
||||||
<p class="propose-button">\
|
|
||||||
<a href="#" id="pc<%id%>" class="show-propose-change">\
|
|
||||||
Propose a change ▹\
|
|
||||||
</a>\
|
|
||||||
<a href="#" id="hc<%id%>" class="hide-propose-change">\
|
|
||||||
Propose a change ▿\
|
|
||||||
</a>\
|
|
||||||
</p>\
|
|
||||||
<textarea name="proposal" id="pt<%id%>" cols="80"\
|
|
||||||
spellcheck="false"></textarea>\
|
|
||||||
<input type="submit" value="Add comment" />\
|
|
||||||
<input type="hidden" name="node" value="<%id%>" />\
|
|
||||||
<input type="hidden" name="parent" value="" />\
|
|
||||||
</form>\
|
|
||||||
</div>\
|
|
||||||
</div>';
|
|
||||||
|
|
||||||
var commentTemplate = '\
|
|
||||||
<div id="cd<%id%>" class="sphinx-comment<%css_class%>">\
|
|
||||||
<div class="vote">\
|
|
||||||
<div class="arrow">\
|
|
||||||
<a href="#" id="uv<%id%>" class="vote" title="vote up">\
|
|
||||||
<img src="<%upArrow%>" />\
|
|
||||||
</a>\
|
|
||||||
<a href="#" id="uu<%id%>" class="un vote" title="vote up">\
|
|
||||||
<img src="<%upArrowPressed%>" />\
|
|
||||||
</a>\
|
|
||||||
</div>\
|
|
||||||
<div class="arrow">\
|
|
||||||
<a href="#" id="dv<%id%>" class="vote" title="vote down">\
|
|
||||||
<img src="<%downArrow%>" id="da<%id%>" />\
|
|
||||||
</a>\
|
|
||||||
<a href="#" id="du<%id%>" class="un vote" title="vote down">\
|
|
||||||
<img src="<%downArrowPressed%>" />\
|
|
||||||
</a>\
|
|
||||||
</div>\
|
|
||||||
</div>\
|
|
||||||
<div class="comment-content">\
|
|
||||||
<p class="tagline comment">\
|
|
||||||
<span class="user-id"><%username%></span>\
|
|
||||||
<span class="rating"><%pretty_rating%></span>\
|
|
||||||
<span class="delta"><%time.delta%></span>\
|
|
||||||
</p>\
|
|
||||||
<div class="comment-text comment"><#text#></div>\
|
|
||||||
<p class="comment-opts comment">\
|
|
||||||
<a href="#" class="reply hidden" id="rl<%id%>">reply ▹</a>\
|
|
||||||
<a href="#" class="close-reply" id="cr<%id%>">reply ▿</a>\
|
|
||||||
<a href="#" id="sp<%id%>" class="show-proposal">proposal ▹</a>\
|
|
||||||
<a href="#" id="hp<%id%>" class="hide-proposal">proposal ▿</a>\
|
|
||||||
<a href="#" id="dc<%id%>" class="delete-comment hidden">delete</a>\
|
|
||||||
<span id="cm<%id%>" class="moderation hidden">\
|
|
||||||
<a href="#" id="ac<%id%>" class="accept-comment">accept</a>\
|
|
||||||
</span>\
|
|
||||||
</p>\
|
|
||||||
<pre class="proposal" id="pr<%id%>">\
|
|
||||||
<#proposal_diff#>\
|
|
||||||
</pre>\
|
|
||||||
<ul class="comment-children" id="cl<%id%>"></ul>\
|
|
||||||
</div>\
|
|
||||||
<div class="clearleft"></div>\
|
|
||||||
</div>\
|
|
||||||
</div>';
|
|
||||||
|
|
||||||
var replyTemplate = '\
|
|
||||||
<li>\
|
|
||||||
<div class="reply-div" id="rd<%id%>">\
|
|
||||||
<form id="rf<%id%>">\
|
|
||||||
<textarea name="comment" cols="80"></textarea>\
|
|
||||||
<input type="submit" value="Add reply" />\
|
|
||||||
<input type="button" value="Cancel" />\
|
|
||||||
<input type="hidden" name="parent" value="<%id%>" />\
|
|
||||||
<input type="hidden" name="node" value="" />\
|
|
||||||
</form>\
|
|
||||||
</div>\
|
|
||||||
</li>';
|
|
||||||
|
|
||||||
$(document).ready(function() {
|
|
||||||
init();
|
|
||||||
});
|
|
||||||
})(jQuery);
|
|
||||||
|
|
||||||
$(document).ready(function() {
|
|
||||||
// add comment anchors for all paragraphs that are commentable
|
|
||||||
$('.sphinx-has-comment').comment();
|
|
||||||
|
|
||||||
// highlight search words in search results
|
|
||||||
$("div.context").each(function() {
|
|
||||||
var params = $.getQueryParameters();
|
|
||||||
var terms = (params.q) ? params.q[0].split(/\s+/) : [];
|
|
||||||
var result = $(this);
|
|
||||||
$.each(terms, function() {
|
|
||||||
result.highlightText(this.toLowerCase(), 'highlighted');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// directly open comment window if requested
|
|
||||||
var anchor = document.location.hash;
|
|
||||||
if (anchor.substring(0, 9) == '#comment-') {
|
|
||||||
$('#ao' + anchor.substring(9)).click();
|
|
||||||
document.location.hash = '#s' + anchor.substring(9);
|
|
||||||
}
|
|
||||||
});
|
|