338 lines
8.8 KiB
Python
338 lines
8.8 KiB
Python
# -*- coding: iso-8859-15 -*-
|
|
|
|
|
|
# Glasnost
|
|
# By: Odile Bénassy <obenassy@entrouvert.com>
|
|
# Romain Chantereau <rchantereau@entrouvert.com>
|
|
# Nicolas Clapiès <nclapies@easter-eggs.org>
|
|
# Pierre-Antoine Dejace <padejace@entrouvert.be>
|
|
# Thierry Dulieu <tdulieu@easter-eggs.com>
|
|
# Florent Monnier <monnier@codelutin.com>
|
|
# Cédric Musso <cmusso@easter-eggs.org>
|
|
# Frédéric Péters <fpeters@entrouvert.be>
|
|
# Benjamin Poussin <poussin@codelutin.com>
|
|
# Emmanuel Raviart <eraviart@entrouvert.com>
|
|
# Sébastien Régnier <regnier@codelutin.com>
|
|
# Emmanuel Saracco <esaracco@easter-eggs.com>
|
|
#
|
|
# Copyright (C) 2000, 2001 Easter-eggs & Emmanuel Raviart
|
|
# Copyright (C) 2002 Odile Bénassy, Code Lutin, Thierry Dulieu, Easter-eggs,
|
|
# Entr'ouvert, Frédéric Péters, Benjamin Poussin, Emmanuel Raviart,
|
|
# Emmanuel Saracco & Théridion
|
|
# Copyright (C) 2003 Odile Bénassy, Romain Chantereau, Nicolas Clapiès,
|
|
# Code Lutin, Pierre-Antoine Dejace, Thierry Dulieu, Easter-eggs,
|
|
# Entr'ouvert, Florent Monnier, Cédric Musso, Ouvaton, Frédéric Péters,
|
|
# Benjamin Poussin, Rodolphe Quiédeville, Emmanuel Raviart, Sébastien
|
|
# Régnier, Emmanuel Saracco, Théridion & Vecam
|
|
#
|
|
# This program is free software; you can redistribute it and/or
|
|
# modify it under the terms of the GNU General Public License
|
|
# as published by the Free Software Foundation; either version 2
|
|
# of the License, or (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
"""Glasnost Context Handling Module.
|
|
|
|
This module contains all context related functions.
|
|
|
|
"""
|
|
|
|
__version__ = '$Revision$'[11:-2]
|
|
|
|
|
|
import threading
|
|
|
|
|
|
class _Context:
|
|
|
|
"""The context.
|
|
|
|
An instance of this class is a Glasnost context.
|
|
|
|
The constructor needs a dictionnay (empty or not) in order to intialize his
|
|
*vars* dictionnary.
|
|
|
|
Attributes
|
|
==========
|
|
|
|
*vars*:
|
|
The context attributes dictionnary. This is where all the context
|
|
variables are saved.
|
|
|
|
*next*:
|
|
A context class instance aggregation. This permit to link contexts.
|
|
|
|
"""
|
|
|
|
next = None
|
|
vars = None
|
|
|
|
def __init__(self, vars):
|
|
self.vars = vars
|
|
|
|
def delVar(self, name):
|
|
"""Remove an variable from the context.
|
|
|
|
If the variable is defined in this context, it is removed, otherwise
|
|
nothing is done.
|
|
"""
|
|
|
|
if self.vars.has_key(name):
|
|
del self.vars[name]
|
|
|
|
def getVar(self, name, default = None):
|
|
"""Return the first value of an variable in the context stack.
|
|
|
|
If no corresponding variable is found, the default value is returned.
|
|
If no default value is specified, None is returned.
|
|
|
|
"""
|
|
|
|
if self.vars.has_key(name):
|
|
return self.vars[name]
|
|
elif self.next is None:
|
|
return default
|
|
else:
|
|
return self.next.getVar(name, default = default)
|
|
|
|
def getVarNames(self):
|
|
"""Return the names of all variables defined in the context stack."""
|
|
|
|
return self.getVarNames2([])
|
|
|
|
def getVarNames2(self, varNames):
|
|
for name in self.vars.keys():
|
|
if not name in varNames:
|
|
varNames.append(name)
|
|
if self.next is None:
|
|
return varNames
|
|
else:
|
|
return self.next.getVarNames2(varNames)
|
|
|
|
def setVar(self, name, value):
|
|
"""Set an variable in the context."""
|
|
|
|
self.vars[name] = value
|
|
|
|
|
|
def clear():
|
|
"""Empty the context stack."""
|
|
|
|
threading.currentThread()._glasnostContext = None
|
|
|
|
|
|
def delVar(name):
|
|
"""Remove an attribute from the top-level context.
|
|
|
|
If the attribute is defined in the top-level context, it is removed from
|
|
it, otherwise nothing is done.
|
|
|
|
Keyword argument
|
|
================
|
|
|
|
*name*:
|
|
The name of the attribute to delete.
|
|
|
|
"""
|
|
|
|
context = get()
|
|
context.delVar(name)
|
|
|
|
|
|
def get(**signatureVars):
|
|
"""Get a context in the context stack.
|
|
|
|
If signatureVars is empty, it returns the first context.
|
|
Otherwise, it returns the first context which contains all signature
|
|
variables (and values).
|
|
|
|
"""
|
|
|
|
thread = threading.currentThread()
|
|
context = thread._glasnostContext
|
|
if not signatureVars:
|
|
return context
|
|
while context is not None:
|
|
vars = context.vars
|
|
for name, value in signatureVars.items():
|
|
if not vars.has_key(name) or vars[name] != value:
|
|
break
|
|
else:
|
|
return context
|
|
context = context.next
|
|
return None
|
|
|
|
|
|
def getVar(name, default = None):
|
|
"""Return the value of the wanted attribute.
|
|
|
|
If no corresponding attribute found, the default value is returned, if no
|
|
default value is specified, None is returned.
|
|
|
|
Keyword arguments
|
|
=================
|
|
|
|
*name*:
|
|
Wanted attribute value title.
|
|
|
|
*default*:
|
|
Default value if no corresponding attribute was found. (default: None).
|
|
|
|
"""
|
|
|
|
context = get()
|
|
return context.getVar(name, default = default)
|
|
|
|
|
|
def getVarNames():
|
|
"""Get the context attribute name sequence.
|
|
|
|
Return all the attribute name stacked in the current context in a sequence.
|
|
|
|
"""
|
|
|
|
context = get()
|
|
return context.getVarNames()
|
|
|
|
|
|
def initFromOther(otherContext):
|
|
"""Set a new current context with the given context as next.
|
|
|
|
The given context is aggregated within the new empty current context. All
|
|
the given context attributes are used by default until an other value is
|
|
set in the current context.
|
|
|
|
Keyword argument
|
|
================
|
|
|
|
*otherContext*:
|
|
The context to aggregate within the new current context.
|
|
|
|
"""
|
|
|
|
context = _Context({})
|
|
context.next = otherContext
|
|
threading.currentThread()._glasnostContext = context
|
|
|
|
|
|
def initThread(thread):
|
|
"""Initialise a new thread context.
|
|
|
|
The given thread context is initialized from the the current context, as
|
|
the *initFromOther* function does.
|
|
|
|
Keyword argument
|
|
================
|
|
|
|
*thread*:
|
|
The thread instance to initialize.
|
|
|
|
"""
|
|
|
|
context = _Context({})
|
|
context.next = threading.currentThread()._glasnostContext
|
|
thread._glasnostContext = context
|
|
|
|
|
|
def isClear():
|
|
"""Test if the current context does not exist
|
|
|
|
If the current thread has the context attribute and it is set to none, the
|
|
current thread is clear.
|
|
|
|
Return
|
|
======
|
|
|
|
*1*:
|
|
The current thread is clear'
|
|
|
|
*0*:
|
|
The current context already exists.
|
|
|
|
"""
|
|
|
|
thread = threading.currentThread()
|
|
return hasattr(thread, '_glasnostContext') \
|
|
and thread._glasnostContext is None
|
|
|
|
|
|
def pull(**signatureVars):
|
|
"""Remove the first context or contexts from the stack.
|
|
|
|
If signatureVars is empty, it removes the first context.
|
|
Otherwise, it removes all the contexts until there is a context which
|
|
contains all signature variables (and values).
|
|
|
|
"""
|
|
|
|
thread = threading.currentThread()
|
|
context = thread._glasnostContext
|
|
while context is not None:
|
|
vars = context.vars
|
|
for name, value in signatureVars.items():
|
|
if not vars.has_key(name) or vars[name] != value:
|
|
break
|
|
else:
|
|
thread._glasnostContext = context.next
|
|
return
|
|
context = context.next
|
|
raise Exception('Unable to find signature in context.')
|
|
|
|
|
|
def push(**contextVars):
|
|
"""Set top level context attributes.
|
|
|
|
A new top level context is instanciated with the given attributes as his
|
|
values.
|
|
All the other context are push down from one level. So the current context
|
|
is aggregated in the new pushed context.
|
|
|
|
Keyword argument
|
|
================
|
|
|
|
*contextVars*:
|
|
The new context variables dictionnary, the key is the variable name,
|
|
the value, his value.
|
|
|
|
"""
|
|
|
|
thread = threading.currentThread()
|
|
context = _Context(contextVars)
|
|
context.next = thread._glasnostContext
|
|
thread._glasnostContext = context
|
|
return context
|
|
|
|
|
|
def set(context):
|
|
"""Set the current context."""
|
|
|
|
threading.currentThread()._glasnostContext = context
|
|
|
|
|
|
def setVar(name, value):
|
|
"""Set a top level context attribute value.
|
|
|
|
If the attribute does not exist, it is created.
|
|
|
|
Keyword arguments
|
|
=================
|
|
|
|
*name*:
|
|
The variable title.
|
|
|
|
*value*:
|
|
The variable value.
|
|
|
|
"""
|
|
|
|
context = get()
|
|
context.setVar(name, value)
|