1
0
mirror of https://github.com/dkmstr/openuds.git synced 2024-12-22 13:34:04 +03:00

Restored "compiled" documentation

This commit is contained in:
Adolfo Gómez 2014-04-29 14:51:12 +00:00
parent dc78222b88
commit 5b383bb384
136 changed files with 31348 additions and 3 deletions

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,4 @@
# 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

View File

@ -0,0 +1,307 @@
# -*- 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'

View File

@ -0,0 +1,196 @@
# -*- 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 fails, 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
'''

View File

@ -0,0 +1,272 @@
# -*- 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

View File

@ -0,0 +1,236 @@
# -*- 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

View File

@ -0,0 +1,373 @@
# -*- 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

View File

@ -0,0 +1,469 @@
# -*- 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

View File

@ -0,0 +1,44 @@
# -*- 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

View File

@ -0,0 +1,96 @@
<!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 &mdash; 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> &raquo;</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> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright 2012, Virtual Cable S.L.U..
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.2.2.
</div>
</body>
</html>

View File

@ -0,0 +1,136 @@
<!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 &mdash; 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> &raquo;</li>
<li><a href="../index.html" accesskey="U">Module code</a> &raquo;</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 &quot;AS IS&quot;</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">&#39;&#39;&#39;</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">&#39;&#39;&#39;</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> &raquo;</li>
<li><a href="../index.html" >Module code</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright 2012, Virtual Cable S.L.U..
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.2.2.
</div>
</body>
</html>

View File

@ -0,0 +1,146 @@
<!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 &mdash; 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> &raquo;</li>
<li><a href="../../index.html" >Module code</a> &raquo;</li>
<li><a href="../core.html" accesskey="U">uds.core</a> &raquo;</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 &quot;AS IS&quot;</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">&#39;&#39;&#39;</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">&#39;&#39;&#39;</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">&#39;2014-02-19&#39;</span>
<span class="k">def</span> <span class="nf">factory</span><span class="p">():</span>
<span class="sd">&#39;&#39;&#39;</span>
<span class="sd"> Returns factory for register/access to authenticators</span>
<span class="sd"> &#39;&#39;&#39;</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> &raquo;</li>
<li><a href="../../index.html" >Module code</a> &raquo;</li>
<li><a href="../core.html" >uds.core</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright 2012, Virtual Cable S.L.U..
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.2.2.
</div>
</body>
</html>

View File

@ -0,0 +1,152 @@
<!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 &mdash; 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> &raquo;</li>
<li><a href="../../index.html" >Module code</a> &raquo;</li>
<li><a href="../core.html" accesskey="U">uds.core</a> &raquo;</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 &quot;AS IS&quot;</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">&#39;&#39;&#39;</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">&#39;&#39;&#39;</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">&#39;2014-03-22&#39;</span>
<span class="k">def</span> <span class="nf">factory</span><span class="p">():</span>
<span class="sd">&#39;&#39;&#39;</span>
<span class="sd"> Returns factory for register/access to service providers</span>
<span class="sd"> &#39;&#39;&#39;</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> &raquo;</li>
<li><a href="../../index.html" >Module code</a> &raquo;</li>
<li><a href="../core.html" >uds.core</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright 2012, Virtual Cable S.L.U..
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.2.2.
</div>
</body>
</html>

View File

@ -0,0 +1,181 @@
<!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 &mdash; 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> &raquo;</li>
<li><a href="../../../index.html" >Module code</a> &raquo;</li>
<li><a href="../../core.html" >uds.core</a> &raquo;</li>
<li><a href="../services.html" accesskey="U">uds.core.services</a> &raquo;</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 &quot;AS IS&quot;</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">&#39;&#39;&#39;</span>
<span class="sd">.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com</span>
<span class="sd">&#39;&#39;&#39;</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">&#39;2014-03-22&#39;</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">&#39;&#39;&#39;</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"> &#39;&#39;&#39;</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">&#39;&#39;&#39;</span>
<span class="sd"> Reflects that the operation requested can&#39;t be acomplished, i.e. remove an snapshot without snapshot reference, cancel non running operation, etc...</span>
<span class="sd"> &#39;&#39;&#39;</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">&#39;&#39;&#39;</span>
<span class="sd"> Reflects thate the publication can&#39;t be done for causes we don&#39;t know in advance</span>
<span class="sd"> &#39;&#39;&#39;</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">&#39;&#39;&#39;</span>
<span class="sd"> Reflects that a deployment of a service (at cache, or assigned to user) can&#39;t be done for causes we don&#39;t know in advance</span>
<span class="sd"> &#39;&#39;&#39;</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">&#39;&#39;&#39;</span>
<span class="sd"> Reflects that a &quot;cancel&quot; operation can&#39;t be done for some reason</span>
<span class="sd"> &#39;&#39;&#39;</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">&#39;&#39;&#39;</span>
<span class="sd"> Invalid service specified. The service is not ready</span>
<span class="sd"> &#39;&#39;&#39;</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">&#39;&#39;&#39;</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"> &#39;&#39;&#39;</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> &raquo;</li>
<li><a href="../../../index.html" >Module code</a> &raquo;</li>
<li><a href="../../core.html" >uds.core</a> &raquo;</li>
<li><a href="../services.html" >uds.core.services</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright 2012, Virtual Cable S.L.U..
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.2.2.
</div>
</body>
</html>

View File

@ -0,0 +1,940 @@
<!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 &mdash; 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> &raquo;</li>
<li><a href="../../../index.html" >Module code</a> &raquo;</li>
<li><a href="../../core.html" accesskey="U">uds.core</a> &raquo;</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 &quot;AS IS&quot;</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">&#39;&#39;&#39;</span>
<span class="sd">.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com</span>
<span class="sd">&#39;&#39;&#39;</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">&#39;&#39;&#39;</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 &quot;BaseModule&quot;, 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 = &#39;Users&#39;, tooltip = &#39;Select users&#39;,</span>
<span class="sd"> order = 1, values = [&#39;user1&#39;, &#39;user2&#39;, &#39;user3&#39;, &#39;user4&#39;])</span>
<span class="sd"> passw = gui.Password(label=&#39;Pass&#39;, length=32, tooltip=&#39;Password&#39;,</span>
<span class="sd"> order = 2, required = True, defValue = &#39;12345&#39;)</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"> &#39;&#39;&#39;</span>
<span class="c"># : True string value</span>
<span class="n">TRUE</span> <span class="o">=</span> <span class="s">&#39;true&#39;</span>
<span class="c"># : False string value</span>
<span class="n">FALSE</span> <span class="o">=</span> <span class="s">&#39;false&#39;</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">&#39;&#39;&#39;</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"> &#39;&#39;&#39;</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">&#39;id&#39;</span><span class="p">:</span> <span class="n">v</span><span class="p">,</span> <span class="s">&#39;text&#39;</span><span class="p">:</span> <span class="s">&#39;&#39;</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">&#39;&#39;&#39;</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, &#39;id&#39; and &#39;text&#39;</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"> &#39;&#39;&#39;</span>
<span class="k">return</span> <span class="p">{</span><span class="s">&#39;id&#39;</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">&#39;text&#39;</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">&#39;&#39;&#39;</span>
<span class="sd"> Converts the string &quot;true&quot; (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 &quot;true&quot; (case insensitive), False else.</span>
<span class="sd"> &#39;&#39;&#39;</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">&#39;&#39;&#39;</span>
<span class="sd"> Converts a boolean to the string representation. True is converted to</span>
<span class="sd"> &quot;true&quot;, False to &quot;false&quot;.</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"> &quot;true&quot; if bol evals to True, &quot;false&quot; if don&#39;t.</span>
<span class="sd"> &#39;&#39;&#39;</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">&#39;&#39;&#39;</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 &#39;&#39;</span>
<span class="sd"> * defvalue: Default value for the field. Defaults to &#39;&#39; (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 &quot;writable&quot;. 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 &#39;&#39;</span>
<span class="sd"> * type: type of the input field, defaults to &quot;text box&quot; (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&#39;t be modified once it&#39;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 &quot;value&quot; has precedence over &quot;defValue&quot;,</span>
<span class="sd"> so if you use both, the used one will be &quot;value&quot;. This is valid for</span>
<span class="sd"> all form fields.</span>
<span class="sd"> &#39;&#39;&#39;</span>
<span class="n">TEXT_TYPE</span> <span class="o">=</span> <span class="s">&#39;text&#39;</span>
<span class="n">TEXTBOX_TYPE</span> <span class="o">=</span> <span class="s">&#39;textbox&#39;</span>
<span class="n">NUMERIC_TYPE</span> <span class="o">=</span> <span class="s">&#39;numeric&#39;</span>
<span class="n">PASSWORD_TYPE</span> <span class="o">=</span> <span class="s">&#39;password&#39;</span>
<span class="n">HIDDEN_TYPE</span> <span class="o">=</span> <span class="s">&#39;hidden&#39;</span>
<span class="n">CHOICE_TYPE</span> <span class="o">=</span> <span class="s">&#39;choice&#39;</span>
<span class="n">MULTI_CHOICE_TYPE</span> <span class="o">=</span> <span class="s">&#39;multichoice&#39;</span>
<span class="n">EDITABLE_LIST</span> <span class="o">=</span> <span class="s">&#39;editlist&#39;</span>
<span class="n">CHECKBOX_TYPE</span> <span class="o">=</span> <span class="s">&#39;checkbox&#39;</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">&#39;length&#39;</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">&#39;length&#39;</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">&#39;required&#39;</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">&#39;required&#39;</span><span class="p">,</span> <span class="bp">False</span><span class="p">),</span>
<span class="s">&#39;label&#39;</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">&#39;label&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">),</span>
<span class="s">&#39;defvalue&#39;</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">&#39;defvalue&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">)),</span>
<span class="s">&#39;rdonly&#39;</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">&#39;rdonly&#39;</span><span class="p">,</span> <span class="bp">False</span><span class="p">),</span> <span class="c"># This property only affects in &quot;modify&quot; operations</span>
<span class="s">&#39;order&#39;</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">&#39;order&#39;</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span>
<span class="s">&#39;tooltip&#39;</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">&#39;tooltip&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">),</span>
<span class="s">&#39;type&#39;</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">&#39;value&#39;</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">&#39;value&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</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">&#39;&#39;&#39;</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"> &#39;&#39;&#39;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_data</span><span class="p">[</span><span class="s">&#39;type&#39;</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">&#39;&#39;&#39;</span>
<span class="sd"> Returns true if this field is of specified type</span>
<span class="sd"> &#39;&#39;&#39;</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">&#39;type&#39;</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">&#39;&#39;&#39;</span>
<span class="sd"> Obtains the stored value</span>
<span class="sd"> &#39;&#39;&#39;</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">&#39;value&#39;</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">&#39;&#39;&#39;</span>
<span class="sd"> Stores new value (not the default one)</span>
<span class="sd"> &#39;&#39;&#39;</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">&#39;&#39;&#39;</span>
<span class="sd"> So we can override value setting at descendants</span>
<span class="sd"> &#39;&#39;&#39;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_data</span><span class="p">[</span><span class="s">&#39;value&#39;</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">&#39;&#39;&#39;</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&#39;t want to</span>
<span class="sd"> alter original values.</span>
<span class="sd"> &#39;&#39;&#39;</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">&#39;label&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="s">&#39;label&#39;</span><span class="p">]</span> <span class="o">!=</span> <span class="s">&#39;&#39;</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">&#39;label&#39;</span><span class="p">])</span> <span class="ow">or</span> <span class="s">&#39;&#39;</span>
<span class="n">data</span><span class="p">[</span><span class="s">&#39;tooltip&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">data</span><span class="p">[</span><span class="s">&#39;tooltip&#39;</span><span class="p">]</span> <span class="o">!=</span> <span class="s">&#39;&#39;</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">&#39;tooltip&#39;</span><span class="p">])</span> <span class="ow">or</span> <span class="s">&#39;&#39;</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">&#39;&#39;&#39;</span>
<span class="sd"> Returns the default value for this field</span>
<span class="sd"> &#39;&#39;&#39;</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">&#39;defvalue&#39;</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">&#39;&#39;&#39;</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"> &#39;&#39;&#39;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_data</span><span class="p">[</span><span class="s">&#39;defvalue&#39;</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">&#39;label&#39;</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">&#39;&#39;&#39;</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 &quot;Host&quot;, tooltip</span>
<span class="sd"> # &quot;Host name for this module&quot;, 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 = _(&#39;Host&#39;), order = 1,</span>
<span class="sd"> tooltip = _(&#39;Host name for this module&#39;), required = True)</span>
<span class="sd"> # Declares an text form field, with label &quot;Other&quot;,</span>
<span class="sd"> # tooltip &quot;Other info&quot;, 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 = _(&#39;Other&#39;), order = 1,</span>
<span class="sd"> tooltip = _(&#39;Other info&#39;), rdonly = True)</span>
<span class="sd"> &#39;&#39;&#39;</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">&#39;multiline&#39;</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">&gt;</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">&#39;multiline&#39;</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">&#39;&#39;&#39;</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"> # &quot;Port&quot;, that is required,</span>
<span class="sd"> # with tooltip &quot;Port (usually 443)&quot; and order 1</span>
<span class="sd"> num = gui.NumericField(length=5, label = _(&#39;Port&#39;),</span>
<span class="sd"> defvalue = &#39;443&#39;, order = 1, tooltip = _(&#39;Port (usually 443)&#39;),</span>
<span class="sd"> required = True)</span>
<span class="sd"> &#39;&#39;&#39;</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">&#39;&#39;&#39;</span>
<span class="sd"> Return value as integer</span>
<span class="sd"> &#39;&#39;&#39;</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">&#39;&#39;&#39;</span>
<span class="sd"> This represents a password field. It appears with &quot;*&quot; 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 &quot;Password&quot;,</span>
<span class="sd"> # tooltip &quot;Password of the user&quot;, 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 = _(&#39;Password&#39;),</span>
<span class="sd"> order = 4, tooltip = _(&#39;Password of the user&#39;),</span>
<span class="sd"> required = True)</span>
<span class="sd"> &#39;&#39;&#39;</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">&#39;&#39;&#39;</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"> &#39;&#39;&#39;</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">&#39;serializable&#39;</span><span class="p">,</span> <span class="s">&#39;&#39;</span><span class="p">)</span> <span class="o">!=</span> <span class="s">&#39;&#39;</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">&#39;&#39;&#39;</span>
<span class="sd"> This represents a check box field, with values &quot;true&quot; and &quot;false&quot;</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: &quot;true&quot; and &quot;false&quot; (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 &quot;Use SSL&quot;, order 3,</span>
<span class="sd"> # tooltip &quot;If checked, will use a ssl connection&quot;, default value</span>
<span class="sd"> # unchecked (not included, so it&#39;s empty, so it&#39;s not true :-))</span>
<span class="sd"> ssl = gui.CheckBoxField(label = _(&#39;Use SSL&#39;), order = 3,</span>
<span class="sd"> tooltip = _(&#39;If checked, will use a ssl connection&#39;))</span>
<span class="sd"> &#39;&#39;&#39;</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">&#39;&#39;&#39;</span>
<span class="sd"> Checks that the value is true</span>
<span class="sd"> &#39;&#39;&#39;</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">&#39;true&#39;</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">&#39;&#39;&#39;</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 &quot;values&quot; option this way:</span>
<span class="sd"> Example:</span>
<span class="sd"> .. code-block:: python</span>
<span class="sd"> choices = gui.ChoiceField(label=&quot;choices&quot;, values = [ {&#39;id&#39;:&#39;1&#39;,</span>
<span class="sd"> &#39;text&#39;:&#39;Text 1&#39;}, {&#39;id&#39;:&#39;xxx&#39;, &#39;text&#39;:&#39;Text 2&#39;}])</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"> * &#39;callbackName&#39; : 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"> * &#39;function&#39; : 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"> * &#39;parameters&#39; : 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=&quot;Choice 1&quot;, values = ....,</span>
<span class="sd"> fills = { &#39;target&#39;: &#39;choice2&#39;, &#39;callback&#39;: fncValues,</span>
<span class="sd"> &#39;parameters&#39;: [&#39;choice1&#39;, &#39;name&#39;]}</span>
<span class="sd"> )</span>
<span class="sd"> choice2 = ghui.ChoiceField(label=&quot;Choice 2&quot;)</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[&#39;resourcePool&#39;] != &#39;&#39;:</span>
<span class="sd"> # ... do stuff ...</span>
<span class="sd"> data = [ { &#39;name&#39; : &#39;machine&#39;, &#39;values&#39; : &#39;xxxxxx&#39; } ]</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=_(&quot;Resource Pool&quot;), rdonly = False, order = 5,</span>
<span class="sd"> fills = {</span>
<span class="sd"> &#39;callbackName&#39; : &#39;vcFillMachinesFromResource&#39;,</span>
<span class="sd"> &#39;function&#39; : VCHelpers.getMachines,</span>
<span class="sd"> &#39;parameters&#39; : [&#39;vc&#39;, &#39;ev&#39;, &#39;resourcePool&#39;]</span>
<span class="sd"> },</span>
<span class="sd"> tooltip = _(&#39;Resource Pool containing base machine&#39;),</span>
<span class="sd"> required = True</span>
<span class="sd"> )</span>
<span class="sd"> machine = gui.ChoiceField(label = _(&quot;Base Machine&quot;), order = 6,</span>
<span class="sd"> tooltip = _(&#39;Base machine for this service&#39;), required = True )</span>
<span class="sd"> vc = gui.HiddenField()</span>
<span class="sd"> ev = gui.HiddenField() # ....</span>
<span class="sd"> &#39;&#39;&#39;</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">&#39;values&#39;</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">&#39;values&#39;</span><span class="p">,</span> <span class="p">[])</span>
<span class="k">if</span> <span class="s">&#39;fills&#39;</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">&#39;fills&#39;</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">&#39;function&#39;</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">&#39;function&#39;</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">&#39;fills&#39;</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">&#39;callbackName&#39;</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">&#39;&#39;&#39;</span>
<span class="sd"> Set the values for this choice field</span>
<span class="sd"> &#39;&#39;&#39;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_data</span><span class="p">[</span><span class="s">&#39;values&#39;</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">&#39;&#39;&#39;</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"> * &#39;rows&#39; to tell gui how many rows to display (the length of the</span>
<span class="sd"> displayable list)</span>
<span class="sd"> &quot;defvalue&quot; 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 [ { &#39;id&#39; : &#39;a&#39;,</span>
<span class="sd"> &#39;text&#39;: 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 &quot;Datastores&quot;, 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 &quot;Datastores where to put incrementals&quot;,</span>
<span class="sd"> # this field is required and has 2 selectable items: &quot;datastore0&quot;</span>
<span class="sd"> with id &quot;0&quot; and &quot;datastore1&quot; with id &quot;1&quot;</span>
<span class="sd"> datastores = gui.MultiChoiceField(label = _(&quot;Datastores&quot;),</span>
<span class="sd"> rdonly = False, rows = 5, order = 8,</span>
<span class="sd"> tooltip = _(&#39;Datastores where to put incrementals&#39;),</span>
<span class="sd"> required = True,</span>
<span class="sd"> values = [ {&#39;id&#39;: &#39;0&#39;, &#39;text&#39;: &#39;datastore0&#39; },</span>
<span class="sd"> {&#39;id&#39;: &#39;1&#39;, &#39;text&#39;: &#39;datastore1&#39; } ]</span>
<span class="sd"> )</span>
<span class="sd"> &#39;&#39;&#39;</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">&#39;values&#39;</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">&#39;values&#39;</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">&#39;rows&#39;</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">&#39;rows&#39;</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">&#39;&#39;&#39;</span>
<span class="sd"> Set the values for this multi choice field</span>
<span class="sd"> &#39;&#39;&#39;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_data</span><span class="p">[</span><span class="s">&#39;values&#39;</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">&#39;&#39;&#39;</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. [&#39;1&#39;, &#39;2&#39;,</span>
<span class="sd"> &#39;test&#39;, &#39;bebito&#39;, ...]</span>
<span class="sd"> This list don&#39;t have &quot;selected&quot; items, so its defvalue field is simply</span>
<span class="sd"> ignored.</span>
<span class="sd"> We only nee to pass in &quot;label&quot; and, maybe, &quot;values&quot; 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=_(&#39;List of IPS&#39;))</span>
<span class="sd"> &#39;&#39;&#39;</span>
<span class="c"># : Constant for separating values at &quot;value&quot; method</span>
<span class="n">SEPARATOR</span> <span class="o">=</span> <span class="s">&#39;</span><span class="se">\001</span><span class="s">&#39;</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">&#39;values&#39;</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">&#39;values&#39;</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">&#39;&#39;&#39;</span>
<span class="sd"> So we can override value setting at descendants</span>
<span class="sd"> &#39;&#39;&#39;</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">&#39;values&#39;</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">&#39;&#39;&#39;</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"> &#39;&#39;&#39;</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">&#39;_gui&#39;</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">&#39;&#39;&#39;</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"> &#39;&#39;&#39;</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 &quot;field&quot; set, and do not share the &quot;fielset&quot; with others, what can be really dangerous</span>
<span class="c"># Till now, nothing bad happened cause there where being used &quot;serialized&quot;, 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 &quot;gui&quot; 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">&#39;&#39;&#39;</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&#39;t have the</span>
<span class="sd"> data for gui.</span>
<span class="sd"> :note: This method is used as a &quot;trick&quot; 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"> &#39;&#39;&#39;</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">&#39;&#39;&#39;</span>
<span class="sd"> Returns own data needed for user interaction as a dict of key-names -&gt;</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 &quot;host&quot; and second named &quot;port&quot;,</span>
<span class="sd"> we can do something like this:</span>
<span class="sd"> .. code-block:: python</span>
<span class="sd"> return { &#39;host&#39; : self.host, &#39;port&#39; : 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"> &#39;&#39;&#39;</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">&#39;Dict: {0}&#39;</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">&#39;&#39;&#39;</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"> &#39;&#39;&#39;</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">&#39;serializing Key: {0}/{1}&#39;</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">&#39;Field {0} is not serializable&#39;</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">&#39;Serializing value {0}&#39;</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">&#39;</span><span class="se">\001</span><span class="s">&#39;</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">&#39;</span><span class="se">\003</span><span class="s">&#39;</span> <span class="o">+</span> <span class="n">val</span><span class="p">)</span>
<span class="k">return</span> <span class="s">&#39;</span><span class="se">\002</span><span class="s">&#39;</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">&#39;zip&#39;</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">&#39;&#39;&#39;</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"> &#39;&#39;&#39;</span>
<span class="k">if</span> <span class="n">values</span> <span class="o">==</span> <span class="s">&#39;&#39;</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(&#39;Field {0} is not unserializable&#39;.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">&#39;zip&#39;</span><span class="p">)</span>
<span class="k">if</span> <span class="n">values</span> <span class="o">==</span> <span class="s">&#39;&#39;</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">&#39;</span><span class="se">\002</span><span class="s">&#39;</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">&#39;</span><span class="se">\003</span><span class="s">&#39;</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">&#39;</span><span class="se">\001</span><span class="s">&#39;</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">&#39;utf-8&#39;</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">&#39;&#39;</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(&#39;Value for {0}:{1}&#39;.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">&#39;Invalid serialization data on {0} {1}&#39;</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">&#39;hex&#39;</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">&#39;&#39;&#39;</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 &quot;initGui&quot; invoked</span>
<span class="sd"> This will only happen (not to be None) in Services.</span>
<span class="sd"> &#39;&#39;&#39;</span>
<span class="n">logger</span><span class="o">.</span><span class="n">debug</span><span class="p">(</span><span class="s">&#39;Active languaje for gui translation: {0}&#39;</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 &quot;oportunity&quot; 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">&#39;{0} ### {1}&#39;</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">&#39;name&#39;</span><span class="p">:</span> <span class="n">key</span><span class="p">,</span> <span class="s">&#39;gui&#39;</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">&#39;value&#39;</span><span class="p">:</span> <span class="s">&#39;&#39;</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">&#39;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt; Gui Description: {0} -- {1}&#39;</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> &raquo;</li>
<li><a href="../../../index.html" >Module code</a> &raquo;</li>
<li><a href="../../core.html" >uds.core</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright 2012, Virtual Cable S.L.U..
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.2.2.
</div>
</body>
</html>

View File

@ -0,0 +1,183 @@
<!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 &mdash; 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> &raquo;</li>
<li><a href="../index.html" accesskey="U">Module code</a> &raquo;</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 &quot;AS IS&quot;</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">&#39;&#39;&#39;</span>
<span class="sd">.. moduleauthor:: Adolfo Gómez, dkmaster at dkmon dot com</span>
<span class="sd">&#39;&#39;&#39;</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">&#39;2014-04-24&#39;</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> &raquo;</li>
<li><a href="../index.html" >Module code</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright 2012, Virtual Cable S.L.U..
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.2.2.
</div>
</body>
</html>

View File

@ -0,0 +1,9 @@
==============
UDS's core API
==============
.. toctree::
models
modules
/development/samples/samples

View File

@ -0,0 +1,24 @@
===================
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

View File

@ -0,0 +1,25 @@
=============================
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:

View File

@ -0,0 +1,41 @@
============
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:

View File

@ -0,0 +1,33 @@
======================
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:

View File

@ -0,0 +1,18 @@
========================
Transport Related models
========================
.. toctree::
:maxdepth: 2
.. module:: uds.models
.. autoclass:: Transport
:members:
:show-inheritance:
.. autoclass:: Network
:members:
:show-inheritance:

View File

@ -0,0 +1,18 @@
===========
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

View File

@ -0,0 +1,27 @@
=====================
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

View File

@ -0,0 +1,53 @@
===========
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:

View File

@ -0,0 +1,33 @@
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

View File

@ -0,0 +1,53 @@
===============
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

View File

@ -0,0 +1,15 @@
=======================
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:

View File

@ -0,0 +1,9 @@
==================
Service Exceptions
==================
.. toctree::
.. automodule:: uds.core.services.Exceptions
:members:

View File

@ -0,0 +1,27 @@
==================
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:

View File

@ -0,0 +1,30 @@
=====================
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:

View File

@ -0,0 +1,25 @@
=================
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:

View File

@ -0,0 +1,23 @@
========================
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:

View File

@ -0,0 +1,36 @@
==================
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.

View File

@ -0,0 +1,3 @@
===================
Contributing to UDS
===================

View File

@ -0,0 +1,3 @@
==============
UDS Repository
==============

View File

@ -0,0 +1,15 @@
====================
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:

View File

@ -0,0 +1,100 @@
===================
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

View File

@ -0,0 +1,20 @@
==========================
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:

View File

@ -0,0 +1,20 @@
==========================
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:

View File

@ -0,0 +1,19 @@
=======================
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:

View File

@ -0,0 +1,23 @@
==================
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:

View File

@ -0,0 +1,15 @@
==============
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:

View File

@ -0,0 +1,32 @@
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

View File

@ -0,0 +1,71 @@
.. _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.

View File

@ -0,0 +1,46 @@
==============
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... :-)

View File

@ -0,0 +1,32 @@
===============
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>`

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 B

View File

@ -0,0 +1,537 @@
/*
* 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;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

View File

@ -0,0 +1,238 @@
/*
* 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();
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 368 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 363 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 B

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 B

View File

@ -0,0 +1,62 @@
.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 */

View File

@ -0,0 +1,622 @@
/*
* 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();
});

View File

@ -0,0 +1,339 @@
/*
* 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;
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 372 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 363 B

View File

@ -0,0 +1,808 @@
/*
* 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 &#9657;\
</a>\
<a href="#" id="hc<%id%>" class="hide-propose-change">\
Propose a change &#9663;\
</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 &#9657;</a>\
<a href="#" class="close-reply" id="cr<%id%>">reply &#9663;</a>\
<a href="#" id="sp<%id%>" class="show-proposal">proposal &#9657;</a>\
<a href="#" id="hp<%id%>" class="hide-proposal">proposal &#9663;</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);
}
});

View File

@ -0,0 +1,194 @@
<!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>UDSs core API &mdash; 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="next" title="UDS Database Models" href="models.html" />
<link rel="prev" title="UDSs architecture" href="../development/architecture.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 class="right" >
<a href="models.html" title="UDS Database Models"
accesskey="N">next</a> |</li>
<li class="right" >
<a href="../development/architecture.html" title="UDSs architecture"
accesskey="P">previous</a> |</li>
<li><a href="../index.html">UDS 1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="sphinxsidebar">
<div class="sphinxsidebarwrapper">
<h4>Previous topic</h4>
<p class="topless"><a href="../development/architecture.html"
title="previous chapter">UDS&#8217;s architecture</a></p>
<h4>Next topic</h4>
<p class="topless"><a href="models.html"
title="next chapter">UDS Database Models</a></p>
<h3>This Page</h3>
<ul class="this-page-menu">
<li><a href="../_sources/api/index.txt"
rel="nofollow">Show Source</a></li>
</ul>
<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">
<div class="section" id="uds-s-core-api">
<h1>UDS&#8217;s core API<a class="headerlink" href="#uds-s-core-api" title="Permalink to this headline"></a></h1>
<div class="toctree-wrapper compound">
<ul>
<li class="toctree-l1"><a class="reference internal" href="models.html">UDS Database Models</a><ul>
<li class="toctree-l2"><a class="reference internal" href="models/services.html">Service Related models</a><ul class="simple">
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="models/authentication.html">Authentication Related models</a><ul class="simple">
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="models/transport.html">Transport Related models</a><ul class="simple">
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="models/other.html">Other models</a><ul>
<li class="toctree-l3"><a class="reference internal" href="models/other.html#module-uds.models">Environment related</a><ul class="simple">
</ul>
</li>
<li class="toctree-l3"><a class="reference internal" href="models/other.html#module-related">Module related</a></li>
<li class="toctree-l3"><a class="reference internal" href="models/other.html#scheduling-and-background-workers-related">Scheduling and background workers related</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="modules.html">UDS Modules</a><ul>
<li class="toctree-l2"><a class="reference internal" href="modules/BaseModule.html">Base Module</a><ul>
<li class="toctree-l3"><a class="reference internal" href="modules/BaseModule.html#module-uds.core">BaseModule</a></li>
<li class="toctree-l3"><a class="reference internal" href="modules/BaseModule.html#environmentable">Environmentable</a></li>
<li class="toctree-l3"><a class="reference internal" href="modules/BaseModule.html#serializable">Serializable</a></li>
<li class="toctree-l3"><a class="reference internal" href="modules/BaseModule.html#userinterface">UserInterface</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="modules/FormFields.html">Form Fields</a><ul class="simple">
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="modules/ServiceModules.html">Service Modules</a><ul>
<li class="toctree-l3"><a class="reference internal" href="modules/services/Provider.html">Provider interface</a><ul class="simple">
</ul>
</li>
<li class="toctree-l3"><a class="reference internal" href="modules/services/Service.html">Service interface</a><ul class="simple">
</ul>
</li>
<li class="toctree-l3"><a class="reference internal" href="modules/services/Publication.html">Publication interface</a><ul class="simple">
</ul>
</li>
<li class="toctree-l3"><a class="reference internal" href="modules/services/UserDeployment.html">UserDeployment interface</a><ul class="simple">
</ul>
</li>
<li class="toctree-l3"><a class="reference internal" href="modules/services/Exceptions.html">Service Exceptions</a><ul class="simple">
</ul>
</li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="modules/AuthenticatorModule.html">Authenticator Modules</a><ul>
<li class="toctree-l3"><a class="reference internal" href="modules/auths/Authenticator.html">Authenticator Interface</a><ul class="simple">
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../development/samples/samples.html">UDS Modules Samples</a><ul>
<li class="toctree-l2"><a class="reference internal" href="../development/samples/samples.html#service-sample">Service Sample</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../development/samples/services/whatisneeded.html">Needs for a service package</a></li>
<li class="toctree-l3"><a class="reference internal" href="../development/samples/services/Provider.html">Sample Service Provider</a></li>
<li class="toctree-l3"><a class="reference internal" href="../development/samples/services/Service.html">Sample service</a></li>
<li class="toctree-l3"><a class="reference internal" href="../development/samples/services/Publication.html">Sample publication</a></li>
<li class="toctree-l3"><a class="reference internal" href="../development/samples/services/DeployedServiceOne.html">Sample User Deployment One</a></li>
<li class="toctree-l3"><a class="reference internal" href="../development/samples/services/DeployedServiceTwo.html">Sample User Deployment Two</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="../development/samples/samples.html#authenticator-sample">Authenticator Sample</a><ul>
<li class="toctree-l3"><a class="reference internal" href="../development/samples/auths/Authenticator.html">Sample Authenticator</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</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 class="right" >
<a href="models.html" title="UDS Database Models"
>next</a> |</li>
<li class="right" >
<a href="../development/architecture.html" title="UDSs architecture"
>previous</a> |</li>
<li><a href="../index.html">UDS 1.0 documentation</a> &raquo;</li>
</ul>
</div>
<div class="footer">
&copy; Copyright 2012, Virtual Cable S.L.U..
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.2.2.
</div>
</body>
</html>

Some files were not shown because too many files have changed in this diff Show More