This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
glasnost/shared/common/context.py

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)