<commit_before>"""
Copyright (c) 2004, CherryPy Team (team@cherrypy.org)
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 the CherryPy Team 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 OWNER 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.
"""

"""
A module containing a few utility classes/functions used by CherryPy
"""

import sys
import traceback
import time
import os
import os.path
import cherrypy

class EmptyClass:
    """ An empty class """
    pass

def getObjectTrail():
    """ Return all objects from the currenct object to cherrypy """
    root = getattr(cherrypy, 'root', None)
    if root:
        objectTrail = [root]
        # Try object path
        try:
            path = cherrypy.request.objectPath or cherrypy.request.path
        except AttributeError:
            path = '/'
        if path:
            pathList = path.split('/')[1:]

            # Successively get objects from the path
            for newObj in pathList:
                try:
                    root = getattr(root, newObj)
                    objectTrail.append(root)
                except AttributeError:
                    break

        return objectTrail
    return None

def getSpecialAttribute(name):
    """Return the special attribute. A special attribute is one that
    applies to all of the children from where it is defined, such as
    _cpFilterList."""

    # First, we look in the right-most object if this special attribute is implemented.
    # If not, then we try the previous object and so on until we reach cherrypy.root
    # If it's still not there, we use the implementation from this module.

    objectList = getObjectTrail()
    if objectList:

        objectList.reverse()
        for obj in objectList:
            attr = getattr(obj, name, None)
            if attr != None:
                return attr

    try:
        return globals()[name]
    except KeyError:
        raise cherrypy.InternalError("Special attribute %s could not be found"
                                     % repr(name))

def getSpecialAttributePath(name):
    """ Return the path to the special attribute """
    objectList = getObjectTrail()
    if objectList:
        pathList = cherrypy.request.objectPath or cherrypy.request.path
        pathList = pathList.split("/")[1:]
        for i in xrange(len(objectList) - 1, -1, -1):
            if hasattr(objectList[i], name):
                return "/" + "/".join(pathList[:i] + [name])
    raise cherrypy.InternalError("Special attribute %s could not be found"
                                 % repr(name))

def logtime():
    return '%04d/%02d/%02d %02d:%02d:%02d' % time.localtime(time.time())[:6]

def _cpLogAccess():
    """ Default method for logging access """

    tmpl = '%(h)s %(l)s %(u)s [%(t)s] "%(r)s" %(s)s %(b)s'
    s = tmpl % {'h': cherrypy.request.remoteHost,
                'l': '-',
                'u': getattr(cherrypy.request, "login", None) or "-",
                't': logtime(),
                'r': cherrypy.request.requestLine,
                's': cherrypy.response.status.split(" ", 1)[0],
                'b': cherrypy.response.headerMap.get('Content-Length', '') or "-",
                }

    if cherrypy.config.get('server.logToScreen', True):
        print s

    fname = cherrypy.config.get('server.logAccessFile', '')
    if fname:
        f = open(fname, 'ab')
        f.write(s + '\n')
        f.close()

_log_severity_levels = {0: "INFO", 1: "WARNING", 2: "ERROR"}

def _cpLogMessage(msg, context = '', severity = 0):
    """ Default method for logging messages (error log)"""

    level = _log_severity_levels.get(severity, "UNKNOWN")
    s = logtime() + ' ' + context + ' ' + level + ' ' + msg

    if cherrypy.config.get('server.logToScreen', True):
        print s

    fname = cherrypy.config.get('server.logFile', '')
    logdir = os.path.dirname(fname)
    print logdir
    if logdir and not os.path.exists(logdir):
        os.makedirs(logdir)
    if fname:
        f = open(fname, 'ab')
        f.write(s + '\n')
        f.close()

def formatExc(exc=None):
    """formatExc(exc=None) -> exc (or sys.exc_info), formatted."""
    if exc is None:
        exc = sys.exc_info()
    return "".join(traceback.format_exception(*exc))

def _cpOnError():
    """ Default _cpOnError method """
    defaultOn = (cherrypy.config.get('server.environment') == 'development')
    if cherrypy.config.get("showTracebacks", defaultOn):
        cherrypy.response.body = [formatExc()]
    else:
        cherrypy.response.body = "Unrecoverable error in the application."
    cherrypy.response.headerMap['Content-Type'] = 'text/plain'
    if cherrypy.response.headerMap.has_key('Content-Encoding'):
        del cherrypy.response.headerMap['Content-Encoding']

_cpFilterList = []

# Filters that are always included
from cherrypy.lib.filter import baseurlfilter, cachefilter, \
    decodingfilter, encodingfilter, gzipfilter, logdebuginfofilter, \
    staticfilter, nsgmlsfilter, tidyfilter, \
    virtualhostfilter, xmlrpcfilter, sessionauthenticatefilter, \
    sessionfilter

# this contains the classes for each filter type
# we do not store the instances here because the test
# suite must reinitilize the filters without restarting
# the server
_cpDefaultFilterClasses = {
    'BaseUrlFilter'      : baseurlfilter.BaseUrlFilter,
    'CacheFilter'        : cachefilter.CacheFilter,
    'DecodingFilter'     : decodingfilter.DecodingFilter,
    'EncodingFilter'     : encodingfilter.EncodingFilter,
    'GzipFilter'         : gzipfilter.GzipFilter,
    'LogDebugInfoFilter' : logdebuginfofilter.LogDebugInfoFilter,
    'NsgmlsFilter'       : nsgmlsfilter.NsgmlsFilter,
    'SessionAuthenticateFilter' : sessionauthenticatefilter.SessionAuthenticateFilter,
    'SessionFilter'      : sessionfilter.SessionFilter,
    'StaticFilter'       : staticfilter.StaticFilter,
    'TidyFilter'         : tidyfilter.TidyFilter,
    'VirtualHostFilter'  : virtualhostfilter.VirtualHostFilter,
    'XmlRpcFilter'       : xmlrpcfilter.XmlRpcFilter,
}

# this is where the actuall filter instances are first stored
_cpDefaultFilterInstances = {}

# These are in order for a reason!
# They must be strings matching keys in _cpDefaultFilterClasses
__cpDefaultInputFilters = [
    'CacheFilter',
    'LogDebugInfoFilter',
    'VirtualHostFilter',
    'BaseUrlFilter',
    'DecodingFilter',
    'SessionFilter',
    'SessionAuthenticateFilter',
    'StaticFilter',
    'NsgmlsFilter',
    'TidyFilter',
    'XmlRpcFilter',
]

__cpDefaultOutputFilters = [
    'XmlRpcFilter',
    'EncodingFilter',
    'TidyFilter',
    'NsgmlsFilter',
    'LogDebugInfoFilter',
    'GzipFilter',
    'SessionFilter',
    'CacheFilter',
]

# these are the lists cp internally uses to access the filters
# they are populated when _cpInitDefaultFilters is called
_cpDefaultInputFilterList  = []
_cpDefaultOutputFilterList = []

# initilize the default filters
def _cpInitDefaultFilters():
    global _cpDefaultInputFilterList, _cpDefaultOutputFilterList
    global _cpDefaultFilterInstances
    _cpDefaultInputFilterList  = []
    _cpDefaultOutputFilterList = []
    _cpDefaultFilterInstances = {}

    for filterName in __cpDefaultInputFilters:
        filterClass = _cpDefaultFilterClasses[filterName]
        filterInstance = _cpDefaultFilterInstances[filterName] = filterClass()
        _cpDefaultInputFilterList.append(filterInstance)

    for filterName in __cpDefaultOutputFilters:
        filterClass = _cpDefaultFilterClasses[filterName]
        filterInstance = _cpDefaultFilterInstances.setdefault(filterName, filterClass())
        _cpDefaultOutputFilterList.append(filterInstance)

def _cpInitUserDefinedFilters():
    filtersRoot = cherrypy.config.get('server.filtersRoot', [])
    inputFiltersDict = cherrypy.config.get('server.inputFiltersDict', {})
    outputFiltersDict = cherrypy.config.get('server.outputFiltersDict', {})

    if len(filtersRoot) == 0:
        return

    sys.path.extend(filtersRoot)

    for filterName, filterClassname in inputFiltersDict.items():
        filterModule = __import__(filterName, globals(),  locals(), [])
        filterClass = getattr(filterModule, filterClassname, None)
        filterInstance = filterClass()
        _cpDefaultInputFilterList.append(filterInstance)

    for filterName, filterClassname in outputFiltersDict.items():
        filterModule = __import__(filterName, globals(),  locals(), [])
        filterClass = getattr(filterModule, filterClassname, None)
        filterInstance = filterClass()
        _cpDefaultOutputFilterList.append(filterInstance)

    # Avoid pollution of the system path
    for path in filtersRoot:
        sys.path.remove(path)

# public domain "unrepr" implementation, found on the web and then improved.
import compiler

def getObj(s):
    s = "a=" + s
    p = compiler.parse(s)
    return p.getChildren()[1].getChildren()[0].getChildren()[1]

class UnknownType(Exception):

    # initialize the built-in filters
    for n in xrange(len(_cpDefaultInputFilterList)):
        try:
            _cpDefaultInputFilterList[n] = _cpDefaultInputFilterList[n]()
        except:
            pass

    for n in xrange(len(_cpDefaultOutputFilterList)):
        try:
            _cpDefaultOutputFilterList[n] = _cpDefaultOutputFilterList[n]()
        except:
            pass

class Builder:

    def build(self, o):
        m = getattr(self, 'build_' + o.__class__.__name__, None)
        if m is None:
            raise UnknownType(o.__class__.__name__)
        return m(o)

    def build_List(self, o):
        return map(self.build, o.getChildren())

    def build_Const(self, o):
        return o.value

    def build_Dict(self, o):
        d = {}
        i = iter(map(self.build, o.getChildren()))
        for el in i:
            d[el] = i.next()
        return d

    def build_Tuple(self, o):
        return tuple(self.build_List(o))

    def build_Name(self, o):
        if o.name == 'None':
            return None
        if o.name == 'True':
            return True
        if o.name == 'False':
            return False

        # See if the Name is a package or module
        try:
            return modules(o.name)
        except ImportError:
            pass

        raise UnknownType(o.name)

    def build_Add(self, o):
        real, imag = map(self.build_Const, o.getChildren())
        try:
            real = float(real)
        except TypeError:
            raise UnknownType('Add')
        if not isinstance(imag, complex) or imag.real != 0.0:
            raise UnknownType('Add')
        return real+imag

    def build_Getattr(self, o):
        parent = self.build(o.expr)
        return getattr(parent, o.attrname)

def unrepr(s):
    if not s:
        return s
    try:
        return Builder().build(getObj(s))
    except:
        raise cherrypy.WrongUnreprValue(repr(s))

def modules(modulePath):
    """Load a module and retrieve a reference to that module."""
    try:
        mod = sys.modules[modulePath]
        if mod is None:
            raise KeyError()
    except KeyError:
        # The last [''] is important.
        mod = __import__(modulePath, globals(), locals(), [''])
    return mod

def attributes(fullAttributeName):
    """Load a module and retrieve an attribute of that module."""

    # Parse out the path, module, and attribute
    lastDot = fullAttributeName.rfind(u".")
    attrName = fullAttributeName[lastDot + 1:]
    modPath = fullAttributeName[:lastDot]

    aMod = modules(modPath)
    # Let an AttributeError propagate outward.
    try:
        attr = getattr(aMod, attrName)
    except AttributeError:
        raise AttributeError("'%s' object has no attribute '%s'"
                             % (modPath, attrName))

    # Return a reference to the attribute.
    return attr
<commit_msg><commit_after>"""
Copyright (c) 2004, CherryPy Team (team@cherrypy.org)
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 the CherryPy Team 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 OWNER 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.
"""

"""
A module containing a few utility classes/functions used by CherryPy
"""

import sys
import traceback
import time
import os
import os.path
import cherrypy

class EmptyClass:
    """ An empty class """
    pass

def getObjectTrail():
    """ Return all objects from the currenct object to cherrypy """
    root = getattr(cherrypy, 'root', None)
    if root:
        objectTrail = [root]
        # Try object path
        try:
            path = cherrypy.request.objectPath or cherrypy.request.path
        except AttributeError:
            path = '/'
        if path:
            pathList = path.split('/')[1:]

            # Successively get objects from the path
            for newObj in pathList:
                try:
                    root = getattr(root, newObj)
                    objectTrail.append(root)
                except AttributeError:
                    break

        return objectTrail
    return None

def getSpecialAttribute(name):
    """Return the special attribute. A special attribute is one that
    applies to all of the children from where it is defined, such as
    _cpFilterList."""

    # First, we look in the right-most object if this special attribute is implemented.
    # If not, then we try the previous object and so on until we reach cherrypy.root
    # If it's still not there, we use the implementation from this module.

    objectList = getObjectTrail()
    if objectList:

        objectList.reverse()
        for obj in objectList:
            attr = getattr(obj, name, None)
            if attr != None:
                return attr

    try:
        return globals()[name]
    except KeyError:
        raise cherrypy.InternalError("Special attribute %s could not be found"
                                     % repr(name))

def getSpecialAttributePath(name):
    """ Return the path to the special attribute """
    objectList = getObjectTrail()
    if objectList:
        pathList = cherrypy.request.objectPath or cherrypy.request.path
        pathList = pathList.split("/")[1:]
        for i in xrange(len(objectList) - 1, -1, -1):
            if hasattr(objectList[i], name):
                return "/" + "/".join(pathList[:i] + [name])
    raise cherrypy.InternalError("Special attribute %s could not be found"
                                 % repr(name))

def logtime():
    return '%04d/%02d/%02d %02d:%02d:%02d' % time.localtime(time.time())[:6]

def _cpLogAccess():
    """ Default method for logging access """

    tmpl = '%(h)s %(l)s %(u)s [%(t)s] "%(r)s" %(s)s %(b)s'
    s = tmpl % {'h': cherrypy.request.remoteHost,
                'l': '-',
                'u': getattr(cherrypy.request, "login", None) or "-",
                't': logtime(),
                'r': cherrypy.request.requestLine,
                's': cherrypy.response.status.split(" ", 1)[0],
                'b': cherrypy.response.headerMap.get('Content-Length', '') or "-",
                }

    if cherrypy.config.get('server.logToScreen', True):
        print s

    fname = cherrypy.config.get('server.logAccessFile', '')
    if fname:
        f = open(fname, 'ab')
        f.write(s + '\n')
        f.close()

_log_severity_levels = {0: "INFO", 1: "WARNING", 2: "ERROR"}

def _cpLogMessage(msg, context = '', severity = 0):
    """ Default method for logging messages (error log)"""

    level = _log_severity_levels.get(severity, "UNKNOWN")
    s = logtime() + ' ' + context + ' ' + level + ' ' + msg

    if cherrypy.config.get('server.logToScreen', True):
        print s

    fname = cherrypy.config.get('server.logFile', '')
    logdir = os.path.dirname(fname)
    if logdir and not os.path.exists(logdir):
        os.makedirs(logdir)
    if fname:
        f = open(fname, 'ab')
        f.write(s + '\n')
        f.close()

def formatExc(exc=None):
    """formatExc(exc=None) -> exc (or sys.exc_info), formatted."""
    if exc is None:
        exc = sys.exc_info()
    return "".join(traceback.format_exception(*exc))

def _cpOnError():
    """ Default _cpOnError method """
    defaultOn = (cherrypy.config.get('server.environment') == 'development')
    if cherrypy.config.get("showTracebacks", defaultOn):
        cherrypy.response.body = [formatExc()]
    else:
        cherrypy.response.body = "Unrecoverable error in the application."
    cherrypy.response.headerMap['Content-Type'] = 'text/plain'
    if cherrypy.response.headerMap.has_key('Content-Encoding'):
        del cherrypy.response.headerMap['Content-Encoding']

_cpFilterList = []

# Filters that are always included
from cherrypy.lib.filter import baseurlfilter, cachefilter, \
    decodingfilter, encodingfilter, gzipfilter, logdebuginfofilter, \
    staticfilter, nsgmlsfilter, tidyfilter, \
    virtualhostfilter, xmlrpcfilter, sessionauthenticatefilter, \
    sessionfilter

# this contains the classes for each filter type
# we do not store the instances here because the test
# suite must reinitilize the filters without restarting
# the server
_cpDefaultFilterClasses = {
    'BaseUrlFilter'      : baseurlfilter.BaseUrlFilter,
    'CacheFilter'        : cachefilter.CacheFilter,
    'DecodingFilter'     : decodingfilter.DecodingFilter,
    'EncodingFilter'     : encodingfilter.EncodingFilter,
    'GzipFilter'         : gzipfilter.GzipFilter,
    'LogDebugInfoFilter' : logdebuginfofilter.LogDebugInfoFilter,
    'NsgmlsFilter'       : nsgmlsfilter.NsgmlsFilter,
    'SessionAuthenticateFilter' : sessionauthenticatefilter.SessionAuthenticateFilter,
    'SessionFilter'      : sessionfilter.SessionFilter,
    'StaticFilter'       : staticfilter.StaticFilter,
    'TidyFilter'         : tidyfilter.TidyFilter,
    'VirtualHostFilter'  : virtualhostfilter.VirtualHostFilter,
    'XmlRpcFilter'       : xmlrpcfilter.XmlRpcFilter,
}

# this is where the actuall filter instances are first stored
_cpDefaultFilterInstances = {}

# These are in order for a reason!
# They must be strings matching keys in _cpDefaultFilterClasses
__cpDefaultInputFilters = [
    'CacheFilter',
    'LogDebugInfoFilter',
    'VirtualHostFilter',
    'BaseUrlFilter',
    'DecodingFilter',
    'SessionFilter',
    'SessionAuthenticateFilter',
    'StaticFilter',
    'NsgmlsFilter',
    'TidyFilter',
    'XmlRpcFilter',
]

__cpDefaultOutputFilters = [
    'XmlRpcFilter',
    'EncodingFilter',
    'TidyFilter',
    'NsgmlsFilter',
    'LogDebugInfoFilter',
    'GzipFilter',
    'SessionFilter',
    'CacheFilter',
]

# these are the lists cp internally uses to access the filters
# they are populated when _cpInitDefaultFilters is called
_cpDefaultInputFilterList  = []
_cpDefaultOutputFilterList = []

# initilize the default filters
def _cpInitDefaultFilters():
    global _cpDefaultInputFilterList, _cpDefaultOutputFilterList
    global _cpDefaultFilterInstances
    _cpDefaultInputFilterList  = []
    _cpDefaultOutputFilterList = []
    _cpDefaultFilterInstances = {}

    for filterName in __cpDefaultInputFilters:
        filterClass = _cpDefaultFilterClasses[filterName]
        filterInstance = _cpDefaultFilterInstances[filterName] = filterClass()
        _cpDefaultInputFilterList.append(filterInstance)

    for filterName in __cpDefaultOutputFilters:
        filterClass = _cpDefaultFilterClasses[filterName]
        filterInstance = _cpDefaultFilterInstances.setdefault(filterName, filterClass())
        _cpDefaultOutputFilterList.append(filterInstance)

def _cpInitUserDefinedFilters():
    filtersRoot = cherrypy.config.get('server.filtersRoot', [])
    inputFiltersDict = cherrypy.config.get('server.inputFiltersDict', {})
    outputFiltersDict = cherrypy.config.get('server.outputFiltersDict', {})

    if len(filtersRoot) == 0:
        return

    sys.path.extend(filtersRoot)

    for filterName, filterClassname in inputFiltersDict.items():
        filterModule = __import__(filterName, globals(),  locals(), [])
        filterClass = getattr(filterModule, filterClassname, None)
        filterInstance = filterClass()
        _cpDefaultInputFilterList.append(filterInstance)

    for filterName, filterClassname in outputFiltersDict.items():
        filterModule = __import__(filterName, globals(),  locals(), [])
        filterClass = getattr(filterModule, filterClassname, None)
        filterInstance = filterClass()
        _cpDefaultOutputFilterList.append(filterInstance)

    # Avoid pollution of the system path
    for path in filtersRoot:
        sys.path.remove(path)

# public domain "unrepr" implementation, found on the web and then improved.
import compiler

def getObj(s):
    s = "a=" + s
    p = compiler.parse(s)
    return p.getChildren()[1].getChildren()[0].getChildren()[1]

class UnknownType(Exception):

    # initialize the built-in filters
    for n in xrange(len(_cpDefaultInputFilterList)):
        try:
            _cpDefaultInputFilterList[n] = _cpDefaultInputFilterList[n]()
        except:
            pass

    for n in xrange(len(_cpDefaultOutputFilterList)):
        try:
            _cpDefaultOutputFilterList[n] = _cpDefaultOutputFilterList[n]()
        except:
            pass

class Builder:

    def build(self, o):
        m = getattr(self, 'build_' + o.__class__.__name__, None)
        if m is None:
            raise UnknownType(o.__class__.__name__)
        return m(o)

    def build_List(self, o):
        return map(self.build, o.getChildren())

    def build_Const(self, o):
        return o.value

    def build_Dict(self, o):
        d = {}
        i = iter(map(self.build, o.getChildren()))
        for el in i:
            d[el] = i.next()
        return d

    def build_Tuple(self, o):
        return tuple(self.build_List(o))

    def build_Name(self, o):
        if o.name == 'None':
            return None
        if o.name == 'True':
            return True
        if o.name == 'False':
            return False

        # See if the Name is a package or module
        try:
            return modules(o.name)
        except ImportError:
            pass

        raise UnknownType(o.name)

    def build_Add(self, o):
        real, imag = map(self.build_Const, o.getChildren())
        try:
            real = float(real)
        except TypeError:
            raise UnknownType('Add')
        if not isinstance(imag, complex) or imag.real != 0.0:
            raise UnknownType('Add')
        return real+imag

    def build_Getattr(self, o):
        parent = self.build(o.expr)
        return getattr(parent, o.attrname)

def unrepr(s):
    if not s:
        return s
    try:
        return Builder().build(getObj(s))
    except:
        raise cherrypy.WrongUnreprValue(repr(s))

def modules(modulePath):
    """Load a module and retrieve a reference to that module."""
    try:
        mod = sys.modules[modulePath]
        if mod is None:
            raise KeyError()
    except KeyError:
        # The last [''] is important.
        mod = __import__(modulePath, globals(), locals(), [''])
    return mod

def attributes(fullAttributeName):
    """Load a module and retrieve an attribute of that module."""

    # Parse out the path, module, and attribute
    lastDot = fullAttributeName.rfind(u".")
    attrName = fullAttributeName[lastDot + 1:]
    modPath = fullAttributeName[:lastDot]

    aMod = modules(modPath)
    # Let an AttributeError propagate outward.
    try:
        attr = getattr(aMod, attrName)
    except AttributeError:
        raise AttributeError("'%s' object has no attribute '%s'"
                             % (modPath, attrName))

    # Return a reference to the attribute.
    return attr
<|endoftext|>


<commit_before>"""A few utility classes/functions used by CherryPy."""

import cgi
import datetime
import sys
import traceback

import cherrypy
from cherrypy.lib import httptools

def get_object_trail(objectpath=None):
    """
    List of (name, object) pairs, from cherrypy.root to the current object.

    If any named objects are unreachable, (name, None) pairs are used.
    """

    if objectpath is None:
        try:
            objectpath = cherrypy.request.objectPath
        except AttributeError:
            pass

    if objectpath is not None:
        objectpath = objectpath.strip('/')

    # Convert the objectpath into a list of names
    if not objectpath:
        nameList = []
    else:
        nameList = objectpath.split('/')

    if nameList == ['global']:
        # Special-case a Request-URI of * to allow for our default handler.
        root = getattr(cherrypy, 'root', None)
        if root is None:
            return [('root', None), ('global_', None), ('index', None)]
        gh = getattr(root, 'global_', _cpGlobalHandler)
        return [('root', cherrypy.root), ('global_', gh), ('index', None)]

    nameList = ['root'] + nameList + ['index']

    # Convert the list of names into a list of objects
    node = cherrypy
    objectTrail = []
    for name in nameList:
        # maps virtual names to Python identifiers (replaces '.' with '_')
        objname = name.replace('.', '_')
        node = getattr(node, objname, None)
        if node is None:
            objectTrail.append((name, node))
        else:
            objectTrail.append((objname, node))

    return objectTrail

def get_special_attribute(name, old_name = None):
    """Return the special attribute. A special attribute is one that
    applies to all of the children from where it is defined, such as
    _cp_filters."""

    # First, we look in the right-most object to see if this special
    # attribute is implemented. If not, then we try the previous object,
    # and so on until we reach cherrypy.root. If it's still not there,
    # we use the implementation from this module.

    objectList = get_object_trail()
    objectList.reverse()
    for objname, obj in objectList:
        if hasattr(obj, name):
            return getattr(obj, name)

    try:
        if old_name:
            return globals()[old_name]
        else:
            return globals()[name]
    except KeyError:
        if old_name:
            return get_special_attribute(name)
        msg = "Special attribute %s could not be found" % repr(name)
        raise cherrypy.HTTPError(500, msg)

def _cpGlobalHandler():
    """Default handler for a Request-URI of '*'."""
    response = cherrypy.response
    response.headers['Content-Type'] = 'text/plain'

    # OPTIONS is defined in HTTP 1.1 and greater
    request = cherrypy.request
    if request.method == 'OPTIONS' and request.version >= 1.1:
        response.headers['Allow'] = 'HEAD, GET, POST, PUT, OPTIONS'
    else:
        response.headers['Allow'] = 'HEAD, GET, POST'
    return ""
_cpGlobalHandler.exposed = True

def logtime():
    now = datetime.datetime.now()
    month = httptools.monthname[now.month][:3].capitalize()
    return '%02d/%s/%04d:%02d:%02d:%02d' % (
        now.day, month, now.year, now.hour, now.minute, now.second)

def _cp_log_access():
    """ Default method for logging access """

    tmpl = '%(h)s %(l)s %(u)s [%(t)s] "%(r)s" %(s)s %(b)s'
    s = tmpl % {'h': cherrypy.request.remoteHost,
                'l': '-',
                'u': getattr(cherrypy.request, "login", None) or "-",
                't': logtime(),
                'r': cherrypy.request.requestLine,
                's': cherrypy.response.status.split(" ", 1)[0],
                'b': cherrypy.response.headers.get('Content-Length', '') or "-",
                }

    if cherrypy.config.get('server.log_to_screen', True):
        print s

    fname = cherrypy.config.get('server.log_access_file', '')
    if fname:
        f = open(fname, 'ab')
        f.write(s + '\n')
        f.close()

_log_severity_levels = {0: "INFO", 1: "WARNING", 2: "ERROR"}

def _cp_log_message(msg, context = '', severity = 0):
    """Default method for logging messages (error log).

    This is not just for errors! Applications may call this at any time to
    log application-specific information.
    """

    level = _log_severity_levels.get(severity, "UNKNOWN")

    s = ' '.join((logtime(), context, level, msg))

    if cherrypy.config.get('server.log_to_screen', True):
        print s

    fname = cherrypy.config.get('server.log_file', '')
    #logdir = os.path.dirname(fname)
    #if logdir and not os.path.exists(logdir):
    #    os.makedirs(logdir)
    if fname:
        f = open(fname, 'ab')
        f.write(s + '\n')
        f.close()

_HTTPErrorTemplate = '''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>%(status)s</title>

%(status)s

%(message)s

%(traceback)s

    Powered by Cherrypy %(version)s

'''

def getErrorPage(status, **kwargs):
    """Return an HTML page, containing a pretty error response.

    status should be an int or a str.
    kwargs will be interpolated into the page template.
    """

    try:
        code, reason, message = httptools.validStatus(status)
    except ValueError, x:
        raise cherrypy.HTTPError(500, x.args[0])

    # We can't use setdefault here, because some
    # callers send None for kwarg values.
    if kwargs.get('status') is None:
        kwargs['status'] = "%s %s" % (code, reason)
    if kwargs.get('message') is None:
        kwargs['message'] = message
    if kwargs.get('traceback') is None:
        kwargs['traceback'] = ''
    if kwargs.get('version') is None:
        kwargs['version'] = cherrypy.__version__
    for k, v in kwargs.iteritems():
        if v is None:
            kwargs[k] = ""
        else:
            kwargs[k] = cgi.escape(kwargs[k])

    template = _HTTPErrorTemplate
    error_page_file = cherrypy.config.get('error_page.%s' % code, '')
    if error_page_file:
        try:
            template = file(error_page_file, 'rb').read()
        except:
            m = kwargs['message']
            if m:
                m += "
"
            m += ("In addition, the custom error page "
                  "failed:\n
%s" % (sys.exc_info()[1]))
            kwargs['message'] = m

    return template % kwargs

def _cp_on_http_error(status, message):
    """ Default _cp_on_http_error method.

    status should be an int.
    """
    tb = formatExc()
    logmsg = ""

    if cherrypy.config.get('server.log_tracebacks', True):
        logmsg = tb
    if cherrypy.config.get('server.log_request_headers', True):
        h = ["  %s: %s" % (k, v) for k, v in cherrypy.request.header_list]
        logmsg += 'Request Headers:\n' + '\n'.join(h)
    if logmsg:
        cherrypy.log(logmsg, "HTTP")

    if not cherrypy.config.get('server.show_tracebacks', False):
        tb = None

    response = cherrypy.response

    # Remove headers which applied to the original content,
    # but do not apply to the error page.
    for key in ["Accept-Ranges", "Age", "ETag", "Location", "Retry-After",
                "Vary", "Content-Encoding", "Content-Length", "Expires",
                "Content-Location", "Content-MD5", "Last-Modified"]:
        if response.headers.has_key(key):
            del response.headers[key]

    if status != 416:
        # A server sending a response with status code 416 (Requested
        # range not satisfiable) SHOULD include a Content-Range field
        # with a byte-range- resp-spec of "*". The instance-length
        # specifies the current length of the selected resource.
        # A response with status code 206 (Partial Content) MUST NOT
        # include a Content-Range field with a byte-range- resp-spec of "*".
        if response.headers.has_key("Content-Range"):
            del response.headers["Content-Range"]

    # In all cases, finalize will be called after this method,
    # so don't bother cleaning up response values here.
    response.status = status
    content = getErrorPage(status, traceback=tb, message=message)
    response.body = content
    response.headers['Content-Length'] = len(content)
    response.headers['Content-Type'] = "text/html"

    be_ie_unfriendly(status)

_ie_friendly_error_sizes = {
    400: 512, 403: 256, 404: 512, 405: 256,
    406: 512, 408: 512, 409: 512, 410: 256,
    500: 512, 501: 512, 505: 512,
    }

def be_ie_unfriendly(status):

    response = cherrypy.response

    # For some statuses, Internet Explorer 5+ shows "friendly error
    # messages" instead of our response.body if the body is smaller
    # than a given size. Fix this by returning a body over that size
    # (by adding whitespace).
    # See http://support.microsoft.com/kb/q218155/
    s = _ie_friendly_error_sizes.get(status, 0)
    if s:
        s += 1
        # Since we are issuing an HTTP error status, we assume that
        # the entity is short, and we should just collapse it.
        content = response.collapse_body()
        l = len(content)
        if l and l < s:
            # IN ADDITION: the response must be written to IE
            # in one chunk or it will still get replaced! Bah.
            content = content + (" " * (s - l))
        response.body = content
        response.headers['Content-Length'] = len(content)

def lower_to_camel(s):
    """Turns lowercase_with_underscore into camelCase."""
    sp = s.split('_')
    new_sp = []
    for i, s in enumerate(sp):
        if i != 0:
            s = s[0].upper() + s[1:]
        new_sp.append(s)
    return ''.join(new_sp)

def formatExc(exc=None):
    """formatExc(exc=None) -> exc (or sys.exc_info if None), formatted."""
    if exc is None:
        exc = sys.exc_info()

    if exc == (None, None, None):
        return ""
    return "".join(traceback.format_exception(*exc))

def bareError(extrabody=None):
    """Produce status, headers, body for a critical error.

    Returns a triple without calling any other questionable functions,
    so it should be as error-free as possible. Call it from an HTTP server
    if you get errors after Request() is done.

    If extrabody is None, a friendly but rather unhelpful error message
    is set in the body. If extrabody is a string, it will be appended
    as-is to the body.
    """

    # The whole point of this function is to be a last line-of-defense
    # in handling errors. That is, it must not raise any errors itself;
    # it cannot be allowed to fail. Therefore, don't add to it!
    # In particular, don't call any other CP functions.

    body = "Unrecoverable error in the server."
    if extrabody is not None:
        body += "\n" + extrabody

    return ("500 Internal Server Error",
            [('Content-Type', 'text/plain'),
             ('Content-Length', str(len(body)))],
            [body])

def _cp_on_error():
    """ Default _cp_on_error method """
    # Allow logging of only *unexpected* HTTPError's.
    if (not cherrypy.config.get('server.log_tracebacks', True)
        and cherrypy.config.get('server.log_unhandled_tracebacks', True)):
        cherrypy.log(formatExc())

    cherrypy.HTTPError(500).set_response()

def headers(headers):
    """ Provides a simple way to add specific headers to page handler
    Any previously set headers provided in the list of tuples will be changed

    headers - a list of tuple : (header_name, header_value)
    """
    def wrapper(func):
        def inner(*args):
            for item in headers:
                headername = item[0]
                headervalue = item[1]
                cherrypy.response.headerMap[headername] = headervalue
            return func(*args)
        return inner
    return wrapper

_cp_filters = []

<commit_msg>Another fix for #405: Try old name first<commit_after>"""A few utility classes/functions used by CherryPy."""

import cgi
import datetime
import sys
import traceback

import cherrypy
from cherrypy.lib import httptools

def get_object_trail(objectpath=None):
    """
    List of (name, object) pairs, from cherrypy.root to the current object.

    If any named objects are unreachable, (name, None) pairs are used.
    """

    if objectpath is None:
        try:
            objectpath = cherrypy.request.objectPath
        except AttributeError:
            pass

    if objectpath is not None:
        objectpath = objectpath.strip('/')

    # Convert the objectpath into a list of names
    if not objectpath:
        nameList = []
    else:
        nameList = objectpath.split('/')

    if nameList == ['global']:
        # Special-case a Request-URI of * to allow for our default handler.
        root = getattr(cherrypy, 'root', None)
        if root is None:
            return [('root', None), ('global_', None), ('index', None)]
        gh = getattr(root, 'global_', _cpGlobalHandler)
        return [('root', cherrypy.root), ('global_', gh), ('index', None)]

    nameList = ['root'] + nameList + ['index']

    # Convert the list of names into a list of objects
    node = cherrypy
    objectTrail = []
    for name in nameList:
        # maps virtual names to Python identifiers (replaces '.' with '_')
        objname = name.replace('.', '_')
        node = getattr(node, objname, None)
        if node is None:
            objectTrail.append((name, node))
        else:
            objectTrail.append((objname, node))

    return objectTrail

def get_special_attribute(name, old_name = None):
    """Return the special attribute. A special attribute is one that
    applies to all of the children from where it is defined, such as
    _cp_filters."""

    # First, we look in the right-most object to see if this special
    # attribute is implemented. If not, then we try the previous object,
    # and so on until we reach cherrypy.root. If it's still not there,
    # we use the implementation from this module.

    objectList = get_object_trail()
    objectList.reverse()
    for objname, obj in objectList:
        if old_name and hasattr(obj, old_name):
            return getattr(obj, old_name)
        elif hasattr(obj, name):
            return getattr(obj, name)

    try:
        if old_name:
            return globals()[old_name]
        else:
            return globals()[name]
    except KeyError:
        if old_name:
            return get_special_attribute(name)
        msg = "Special attribute %s could not be found" % repr(name)
        raise cherrypy.HTTPError(500, msg)

def _cpGlobalHandler():
    """Default handler for a Request-URI of '*'."""
    response = cherrypy.response
    response.headers['Content-Type'] = 'text/plain'

    # OPTIONS is defined in HTTP 1.1 and greater
    request = cherrypy.request
    if request.method == 'OPTIONS' and request.version >= 1.1:
        response.headers['Allow'] = 'HEAD, GET, POST, PUT, OPTIONS'
    else:
        response.headers['Allow'] = 'HEAD, GET, POST'
    return ""
_cpGlobalHandler.exposed = True

def logtime():
    now = datetime.datetime.now()
    month = httptools.monthname[now.month][:3].capitalize()
    return '%02d/%s/%04d:%02d:%02d:%02d' % (
        now.day, month, now.year, now.hour, now.minute, now.second)

def _cp_log_access():
    """ Default method for logging access """

    tmpl = '%(h)s %(l)s %(u)s [%(t)s] "%(r)s" %(s)s %(b)s'
    s = tmpl % {'h': cherrypy.request.remoteHost,
                'l': '-',
                'u': getattr(cherrypy.request, "login", None) or "-",
                't': logtime(),
                'r': cherrypy.request.requestLine,
                's': cherrypy.response.status.split(" ", 1)[0],
                'b': cherrypy.response.headers.get('Content-Length', '') or "-",
                }

    if cherrypy.config.get('server.log_to_screen', True):
        print s

    fname = cherrypy.config.get('server.log_access_file', '')
    if fname:
        f = open(fname, 'ab')
        f.write(s + '\n')
        f.close()

_log_severity_levels = {0: "INFO", 1: "WARNING", 2: "ERROR"}

def _cp_log_message(msg, context = '', severity = 0):
    """Default method for logging messages (error log).

    This is not just for errors! Applications may call this at any time to
    log application-specific information.
    """

    level = _log_severity_levels.get(severity, "UNKNOWN")

    s = ' '.join((logtime(), context, level, msg))

    if cherrypy.config.get('server.log_to_screen', True):
        print s

    fname = cherrypy.config.get('server.log_file', '')
    #logdir = os.path.dirname(fname)
    #if logdir and not os.path.exists(logdir):
    #    os.makedirs(logdir)
    if fname:
        f = open(fname, 'ab')
        f.write(s + '\n')
        f.close()

_HTTPErrorTemplate = '''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title>%(status)s</title>

%(status)s

%(message)s

%(traceback)s

    Powered by Cherrypy %(version)s

'''

def getErrorPage(status, **kwargs):
    """Return an HTML page, containing a pretty error response.

    status should be an int or a str.
    kwargs will be interpolated into the page template.
    """

    try:
        code, reason, message = httptools.validStatus(status)
    except ValueError, x:
        raise cherrypy.HTTPError(500, x.args[0])

    # We can't use setdefault here, because some
    # callers send None for kwarg values.
    if kwargs.get('status') is None:
        kwargs['status'] = "%s %s" % (code, reason)
    if kwargs.get('message') is None:
        kwargs['message'] = message
    if kwargs.get('traceback') is None:
        kwargs['traceback'] = ''
    if kwargs.get('version') is None:
        kwargs['version'] = cherrypy.__version__
    for k, v in kwargs.iteritems():
        if v is None:
            kwargs[k] = ""
        else:
            kwargs[k] = cgi.escape(kwargs[k])

    template = _HTTPErrorTemplate
    error_page_file = cherrypy.config.get('error_page.%s' % code, '')
    if error_page_file:
        try:
            template = file(error_page_file, 'rb').read()
        except:
            m = kwargs['message']
            if m:
                m += "
"
            m += ("In addition, the custom error page "
                  "failed:\n
%s" % (sys.exc_info()[1]))
            kwargs['message'] = m

    return template % kwargs

def _cp_on_http_error(status, message):
    """ Default _cp_on_http_error method.

    status should be an int.
    """
    tb = formatExc()
    logmsg = ""

    if cherrypy.config.get('server.log_tracebacks', True):
        logmsg = tb
    if cherrypy.config.get('server.log_request_headers', True):
        h = ["  %s: %s" % (k, v) for k, v in cherrypy.request.header_list]
        logmsg += 'Request Headers:\n' + '\n'.join(h)
    if logmsg:
        cherrypy.log(logmsg, "HTTP")

    if not cherrypy.config.get('server.show_tracebacks', False):
        tb = None

    response = cherrypy.response

    # Remove headers which applied to the original content,
    # but do not apply to the error page.
    for key in ["Accept-Ranges", "Age", "ETag", "Location", "Retry-After",
                "Vary", "Content-Encoding", "Content-Length", "Expires",
                "Content-Location", "Content-MD5", "Last-Modified"]:
        if response.headers.has_key(key):
            del response.headers[key]

    if status != 416:
        # A server sending a response with status code 416 (Requested
        # range not satisfiable) SHOULD include a Content-Range field
        # with a byte-range- resp-spec of "*". The instance-length
        # specifies the current length of the selected resource.
        # A response with status code 206 (Partial Content) MUST NOT
        # include a Content-Range field with a byte-range- resp-spec of "*".
        if response.headers.has_key("Content-Range"):
            del response.headers["Content-Range"]

    # In all cases, finalize will be called after this method,
    # so don't bother cleaning up response values here.
    response.status = status
    content = getErrorPage(status, traceback=tb, message=message)
    response.body = content
    response.headers['Content-Length'] = len(content)
    response.headers['Content-Type'] = "text/html"

    be_ie_unfriendly(status)

_ie_friendly_error_sizes = {
    400: 512, 403: 256, 404: 512, 405: 256,
    406: 512, 408: 512, 409: 512, 410: 256,
    500: 512, 501: 512, 505: 512,
    }

def be_ie_unfriendly(status):

    response = cherrypy.response

    # For some statuses, Internet Explorer 5+ shows "friendly error
    # messages" instead of our response.body if the body is smaller
    # than a given size. Fix this by returning a body over that size
    # (by adding whitespace).
    # See http://support.microsoft.com/kb/q218155/
    s = _ie_friendly_error_sizes.get(status, 0)
    if s:
        s += 1
        # Since we are issuing an HTTP error status, we assume that
        # the entity is short, and we should just collapse it.
        content = response.collapse_body()
        l = len(content)
        if l and l < s:
            # IN ADDITION: the response must be written to IE
            # in one chunk or it will still get replaced! Bah.
            content = content + (" " * (s - l))
        response.body = content
        response.headers['Content-Length'] = len(content)

def lower_to_camel(s):
    """Turns lowercase_with_underscore into camelCase."""
    sp = s.split('_')
    new_sp = []
    for i, s in enumerate(sp):
        if i != 0:
            s = s[0].upper() + s[1:]
        new_sp.append(s)
    return ''.join(new_sp)

def formatExc(exc=None):
    """formatExc(exc=None) -> exc (or sys.exc_info if None), formatted."""
    if exc is None:
        exc = sys.exc_info()

    if exc == (None, None, None):
        return ""
    return "".join(traceback.format_exception(*exc))

def bareError(extrabody=None):
    """Produce status, headers, body for a critical error.

    Returns a triple without calling any other questionable functions,
    so it should be as error-free as possible. Call it from an HTTP server
    if you get errors after Request() is done.

    If extrabody is None, a friendly but rather unhelpful error message
    is set in the body. If extrabody is a string, it will be appended
    as-is to the body.
    """

    # The whole point of this function is to be a last line-of-defense
    # in handling errors. That is, it must not raise any errors itself;
    # it cannot be allowed to fail. Therefore, don't add to it!
    # In particular, don't call any other CP functions.

    body = "Unrecoverable error in the server."
    if extrabody is not None:
        body += "\n" + extrabody

    return ("500 Internal Server Error",
            [('Content-Type', 'text/plain'),
             ('Content-Length', str(len(body)))],
            [body])

def _cp_on_error():
    """ Default _cp_on_error method """
    # Allow logging of only *unexpected* HTTPError's.
    if (not cherrypy.config.get('server.log_tracebacks', True)
        and cherrypy.config.get('server.log_unhandled_tracebacks', True)):
        cherrypy.log(formatExc())

    cherrypy.HTTPError(500).set_response()

def headers(headers):
    """ Provides a simple way to add specific headers to page handler
    Any previously set headers provided in the list of tuples will be changed

    headers - a list of tuple : (header_name, header_value)
    """
    def wrapper(func):
        def inner(*args):
            for item in headers:
                headername = item[0]
                headervalue = item[1]
                cherrypy.response.headerMap[headername] = headervalue
            return func(*args)
        return inner
    return wrapper

_cp_filters = []

<|endoftext|>


<commit_before>#
# Copyright (c) SAS Institute Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

from xobj import xobj

from testserver import models

class AttrDict(dict):
    def __getattr__(self, attr):
        if attr.startswith('_'):
            return dict.__getattr__(self, attr)
        else:
            return self.__getitem__(attr)

    def __setattr__(self, attr, value):
        if attr.startswith('_'):
            return dict.__setattr__(self, attr, value)
        else:
            return self.__setitem__(attr, value)

class AbstractModelCollection(dict):
    def _nextId(self):
        if not self:
            return 0
        else:
            return max(self) + 1

    def parse(self, xml):
        raise NotImplementedError

    def create(self, xml, uri):
        raise NotImplementedError

    def update(self, idx, xml):
        raise NotImplementedError

    def delete(self, idx):
        raise NotImplementedError

class Employees(AbstractModelCollection):
    def __init__(self):
        AbstractModelCollection.__init__(self)
        self.files = AttrDict()
        self.productRefs = AttrDict()

    def parse(self, xml):
        class Doc(xobj.Document):
            employee = models.Employee
        doc = xobj.parse(xml, documentClass=Doc)
        return doc.employee

    def create(self, xml, uri):
        uri = uri.rstrip('/')
        model = self.parse(xml)

        if getattr(model, 'employeeid', None):
            return self[model.employeeid]

        model.employeeid = self._nextId()
        model.id = '%s/%s' % (uri, model.employeeid)
        model.products = models.ProductsRef()
        model.products.href = '%s/products' % model.id
        model.file = models.File()
        model.file.href = '%s/file' % model.id

        self[model.employeeid] = model
        self.productRefs[model.employeeid] = []
        return model

    def update(self, idx, xml):
        newModel = self.parse(xml)
        oldModel = self[idx]

        immutable = ('employid', 'id')
        for attr in models.Employee.__elements__:
            if attr in immutable:
                continue

            value = getattr(newModel, attr, None)
            if value is not None:
                setattr(oldModel, attr, value)

        return oldModel

    def delete(self, idx):
        self.pop(idx, None)
        self.productRefs.pop(idx, None)
        self.files.pop(idx, None)

class Products(AbstractModelCollection):
    def __init__(self):
        AbstractModelCollection.__init__(self)
        self.employeeRefs = AttrDict()

    def parse(self, xml):
        class Doc(xobj.Document):
            product = models.Product
        doc = xobj.parse(xml, documentClass=Doc)
        return doc.product

    def create(self, xml, uri):
        uri = uri.strip('/')
        model = self.parse(xml)

        if getattr(model, 'productid', None):
            return self[model.productid]

        model.productid = self._nextId()
        model.id = '%s/%s' % (uri, model.productid)
        model.employees = models.EmployeesRef()
        model.employees.href = '%s/employees' % model.id

        self[model.productid] = model
        self.employeeRefs[model.productid] = []
        return model

    def update(self, idx, xml):
        newModel = self.parse(xml)
        oldModel = self[idx]

        immutable = ('productid', 'id')
        for attr in models.Product.__elements__:
            if attr in immutable:
                continue

            value = getattr(newModel, attr, None)
            if value is not None:
                setattr(oldModel, attr, value)

        return oldModel

    def delete(self, idx):
        self.pop(idx)
        self.employeeRefs.pop(idx)

class DataStore(object):
    def __init__(self):
        self.employees = Employees()
        self.products = Products()
<commit_msg>Correctly strip uri in Products.create<commit_after>#
# Copyright (c) SAS Institute Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

from xobj import xobj

from testserver import models

class AttrDict(dict):
    def __getattr__(self, attr):
        if attr.startswith('_'):
            return dict.__getattr__(self, attr)
        else:
            return self.__getitem__(attr)

    def __setattr__(self, attr, value):
        if attr.startswith('_'):
            return dict.__setattr__(self, attr, value)
        else:
            return self.__setitem__(attr, value)

class AbstractModelCollection(dict):
    def _nextId(self):
        if not self:
            return 0
        else:
            return max(self) + 1

    def parse(self, xml):
        raise NotImplementedError

    def create(self, xml, uri):
        raise NotImplementedError

    def update(self, idx, xml):
        raise NotImplementedError

    def delete(self, idx):
        raise NotImplementedError

class Employees(AbstractModelCollection):
    def __init__(self):
        AbstractModelCollection.__init__(self)
        self.files = AttrDict()
        self.productRefs = AttrDict()

    def parse(self, xml):
        class Doc(xobj.Document):
            employee = models.Employee
        doc = xobj.parse(xml, documentClass=Doc)
        return doc.employee

    def create(self, xml, uri):
        uri = uri.rstrip('/')
        model = self.parse(xml)

        if getattr(model, 'employeeid', None):
            return self[model.employeeid]

        model.employeeid = self._nextId()
        model.id = '%s/%s' % (uri, model.employeeid)
        model.products = models.ProductsRef()
        model.products.href = '%s/products' % model.id
        model.file = models.File()
        model.file.href = '%s/file' % model.id

        self[model.employeeid] = model
        self.productRefs[model.employeeid] = []
        return model

    def update(self, idx, xml):
        newModel = self.parse(xml)
        oldModel = self[idx]

        immutable = ('employid', 'id')
        for attr in models.Employee.__elements__:
            if attr in immutable:
                continue

            value = getattr(newModel, attr, None)
            if value is not None:
                setattr(oldModel, attr, value)

        return oldModel

    def delete(self, idx):
        self.pop(idx, None)
        self.productRefs.pop(idx, None)
        self.files.pop(idx, None)

class Products(AbstractModelCollection):
    def __init__(self):
        AbstractModelCollection.__init__(self)
        self.employeeRefs = AttrDict()

    def parse(self, xml):
        class Doc(xobj.Document):
            product = models.Product
        doc = xobj.parse(xml, documentClass=Doc)
        return doc.product

    def create(self, xml, uri):
        uri = uri.rstrip('/')
        model = self.parse(xml)

        if getattr(model, 'productid', None):
            return self[model.productid]

        model.productid = self._nextId()
        model.id = '%s/%s' % (uri, model.productid)
        model.employees = models.EmployeesRef()
        model.employees.href = '%s/employees' % model.id

        self[model.productid] = model
        self.employeeRefs[model.productid] = []
        return model

    def update(self, idx, xml):
        newModel = self.parse(xml)
        oldModel = self[idx]

        immutable = ('productid', 'id')
        for attr in models.Product.__elements__:
            if attr in immutable:
                continue

            value = getattr(newModel, attr, None)
            if value is not None:
                setattr(oldModel, attr, value)

        return oldModel

    def delete(self, idx):
        self.pop(idx)
        self.employeeRefs.pop(idx)

class DataStore(object):
    def __init__(self):
        self.employees = Employees()
        self.products = Products()
<|endoftext|>


<commit_before>"""WSGI interface (see PEP 333)."""

import sys
import cherrypy
from cherrypy import _cpwsgiserver
from cherrypy._cperror import format_exc, bare_error
from cherrypy.lib import http

headerNames = {'HTTP_CGI_AUTHORIZATION': 'Authorization',
               'CONTENT_LENGTH': 'Content-Length',
               'CONTENT_TYPE': 'Content-Type',
               'REMOTE_HOST': 'Remote-Host',
               'REMOTE_ADDR': 'Remote-Addr',
               }

def translate_headers(environ):
    """Translate CGI-environ header names to HTTP header names."""
    for cgiName in environ:
        # We assume all incoming header keys are uppercase already.
        if cgiName in headerNames:
            yield headerNames[cgiName], environ[cgiName]
        elif cgiName[:5] == "HTTP_":
            # Hackish attempt at recovering original header names.
            translatedHeader = cgiName[5:].replace("_", "-")
            yield translatedHeader, environ[cgiName]

def _wsgi_callable(environ, start_response, app):
    request = None
    try:
        env = environ.get
        local = http.Host('', int(env('SERVER_PORT', 80)),
                          env('SERVER_NAME', ''))
        remote = http.Host(env('REMOTE_ADDR', ''),
                           int(env('REMOTE_PORT', -1)),
                           env('REMOTE_HOST', ''))
        request = cherrypy.engine.request(local, remote,
                                          env('wsgi.url_scheme'),
                                          env('ACTUAL_SERVER_PROTOCOL', None))

        # LOGON_USER is served by IIS, and is the name of the
        # user after having been mapped to a local account.
        # Both IIS and Apache set REMOTE_USER, when possible.
        request.login = env('LOGON_USER') or env('REMOTE_USER') or None

        request.multithread = environ['wsgi.multithread']
        request.multiprocess = environ['wsgi.multiprocess']
        request.wsgi_environ = environ

        request.app = app

        path = env('SCRIPT_NAME', '') + env('PATH_INFO', '')
        response = request.run(environ['REQUEST_METHOD'], path,
                               env('QUERY_STRING'),
                               env('SERVER_PROTOCOL'),
                               translate_headers(environ),
                               environ['wsgi.input'])
        s, h, b = response.status, response.header_list, response.body
        exc = None
    except (KeyboardInterrupt, SystemExit), ex:
        try:
            if request:
                request.close()
        except:
            cherrypy.log(traceback=True)
        request = None
        raise ex
    except:
        if cherrypy.config.get("throw_errors", False):
            raise
        tb = format_exc()
        cherrypy.log(tb)
        if not cherrypy.config.get("show_tracebacks", False):
            tb = ""
        s, h, b = bare_error(tb)
        exc = sys.exc_info()

    try:
        start_response(s, h, exc)
        for chunk in b:
            # WSGI requires all data to be of type "str". This coercion should
            # not take any time at all if chunk is already of type "str".
            # If it's unicode, it could be a big performance hit (x ~500).
            if not isinstance(chunk, str):
                chunk = chunk.encode("ISO-8859-1")
            yield chunk
        if request:
            request.close()
        request = None
    except (KeyboardInterrupt, SystemExit), ex:
        try:
            if request:
                request.close()
        except:
            cherrypy.log(traceback=True)
        request = None
        raise ex
    except:
        cherrypy.log(traceback=True)
        try:
            if request:
                request.close()
        except:
            cherrypy.log(traceback=True)
        request = None
        s, h, b = bare_error()
        # CherryPy test suite expects bare_error body to be output,
        # so don't call start_response (which, according to PEP 333,
        # may raise its own error at that point).
        for chunk in b:
            if not isinstance(chunk, str):
                chunk = chunk.encode("ISO-8859-1")
            yield chunk

#                            Server components                            #

class CPHTTPRequest(_cpwsgiserver.HTTPRequest):

    def parse_request(self):
        mhs = int(cherrypy.config.get('server.max_request_header_size',
                                      500 * 1024))
        if mhs > 0:
            self.rfile = http.SizeCheckWrapper(self.rfile, mhs)

        try:
            _cpwsgiserver.HTTPRequest.parse_request(self)
        except http.MaxSizeExceeded:
            self.simple_response("413 Request Entity Too Large")
            cherrypy.log(traceback=True)

    def decode_chunked(self):
        """Decode the 'chunked' transfer coding."""
        if isinstance(self.rfile, http.SizeCheckWrapper):
            self.rfile = self.rfile.rfile
        mbs = int(cherrypy.config.get('server.max_request_body_size',
                                      100 * 1024 * 1024))
        if mbs > 0:
            self.rfile = http.SizeCheckWrapper(self.rfile, mbs)
        try:
            return _cpwsgiserver.HTTPRequest.decode_chunked(self)
        except http.MaxSizeExceeded:
            self.simple_response("413 Request Entity Too Large")
            cherrypy.log(traceback=True)
            return False

class CPHTTPConnection(_cpwsgiserver.HTTPConnection):

    RequestHandlerClass = CPHTTPRequest

class WSGIServer(_cpwsgiserver.CherryPyWSGIServer):

    """Wrapper for _cpwsgiserver.CherryPyWSGIServer.

    _cpwsgiserver has been designed to not reference CherryPy in any way,
    so that it can be used in other frameworks and applications. Therefore,
    we wrap it here, so we can set our own mount points from cherrypy.tree.

    """

    ConnectionClass = CPHTTPConnection

    def __init__(self):
        conf = cherrypy.config.get

        sockFile = conf('server.socket_file')
        if sockFile:
            bind_addr = sockFile
        else:
            bind_addr = (conf('server.socket_host'),
                         conf('server.socket_port'))

        s = _cpwsgiserver.CherryPyWSGIServer
        # We could just pass cherrypy.tree, but by passing tree.apps,
        # we get correct SCRIPT_NAMEs as early as possible.
        s.__init__(self, bind_addr, cherrypy.tree.apps.items(),
                   conf('server.thread_pool'),
                   conf('server.socket_host'),
                   request_queue_size = conf('server.socket_queue_size'),
                   timeout = conf('server.socket_timeout'),
                   )
        s.protocol = conf('server.protocol_version', 'HTTP/1.1')

<commit_msg>Default ACTUAL_SERVER_PROTOCOL to "HTTP/1.1". If None, then Request.run fails with "unsubscriptable object".<commit_after>"""WSGI interface (see PEP 333)."""

import sys
import cherrypy
from cherrypy import _cpwsgiserver
from cherrypy._cperror import format_exc, bare_error
from cherrypy.lib import http

headerNames = {'HTTP_CGI_AUTHORIZATION': 'Authorization',
               'CONTENT_LENGTH': 'Content-Length',
               'CONTENT_TYPE': 'Content-Type',
               'REMOTE_HOST': 'Remote-Host',
               'REMOTE_ADDR': 'Remote-Addr',
               }

def translate_headers(environ):
    """Translate CGI-environ header names to HTTP header names."""
    for cgiName in environ:
        # We assume all incoming header keys are uppercase already.
        if cgiName in headerNames:
            yield headerNames[cgiName], environ[cgiName]
        elif cgiName[:5] == "HTTP_":
            # Hackish attempt at recovering original header names.
            translatedHeader = cgiName[5:].replace("_", "-")
            yield translatedHeader, environ[cgiName]

def _wsgi_callable(environ, start_response, app):
    request = None
    try:
        env = environ.get
        local = http.Host('', int(env('SERVER_PORT', 80)),
                          env('SERVER_NAME', ''))
        remote = http.Host(env('REMOTE_ADDR', ''),
                           int(env('REMOTE_PORT', -1)),
                           env('REMOTE_HOST', ''))
        request = cherrypy.engine.request(local, remote,
                                          env('wsgi.url_scheme'),
                                          env('ACTUAL_SERVER_PROTOCOL', "HTTP/1.1"))

        # LOGON_USER is served by IIS, and is the name of the
        # user after having been mapped to a local account.
        # Both IIS and Apache set REMOTE_USER, when possible.
        request.login = env('LOGON_USER') or env('REMOTE_USER') or None

        request.multithread = environ['wsgi.multithread']
        request.multiprocess = environ['wsgi.multiprocess']
        request.wsgi_environ = environ

        request.app = app

        path = env('SCRIPT_NAME', '') + env('PATH_INFO', '')
        response = request.run(environ['REQUEST_METHOD'], path,
                               env('QUERY_STRING'),
                               env('SERVER_PROTOCOL'),
                               translate_headers(environ),
                               environ['wsgi.input'])
        s, h, b = response.status, response.header_list, response.body
        exc = None
    except (KeyboardInterrupt, SystemExit), ex:
        try:
            if request:
                request.close()
        except:
            cherrypy.log(traceback=True)
        request = None
        raise ex
    except:
        if cherrypy.config.get("throw_errors", False):
            raise
        tb = format_exc()
        cherrypy.log(tb)
        if not cherrypy.config.get("show_tracebacks", False):
            tb = ""
        s, h, b = bare_error(tb)
        exc = sys.exc_info()

    try:
        start_response(s, h, exc)
        for chunk in b:
            # WSGI requires all data to be of type "str". This coercion should
            # not take any time at all if chunk is already of type "str".
            # If it's unicode, it could be a big performance hit (x ~500).
            if not isinstance(chunk, str):
                chunk = chunk.encode("ISO-8859-1")
            yield chunk
        if request:
            request.close()
        request = None
    except (KeyboardInterrupt, SystemExit), ex:
        try:
            if request:
                request.close()
        except:
            cherrypy.log(traceback=True)
        request = None
        raise ex
    except:
        cherrypy.log(traceback=True)
        try:
            if request:
                request.close()
        except:
            cherrypy.log(traceback=True)
        request = None
        s, h, b = bare_error()
        # CherryPy test suite expects bare_error body to be output,
        # so don't call start_response (which, according to PEP 333,
        # may raise its own error at that point).
        for chunk in b:
            if not isinstance(chunk, str):
                chunk = chunk.encode("ISO-8859-1")
            yield chunk

#                            Server components                            #

class CPHTTPRequest(_cpwsgiserver.HTTPRequest):

    def parse_request(self):
        mhs = int(cherrypy.config.get('server.max_request_header_size',
                                      500 * 1024))
        if mhs > 0:
            self.rfile = http.SizeCheckWrapper(self.rfile, mhs)

        try:
            _cpwsgiserver.HTTPRequest.parse_request(self)
        except http.MaxSizeExceeded:
            self.simple_response("413 Request Entity Too Large")
            cherrypy.log(traceback=True)

    def decode_chunked(self):
        """Decode the 'chunked' transfer coding."""
        if isinstance(self.rfile, http.SizeCheckWrapper):
            self.rfile = self.rfile.rfile
        mbs = int(cherrypy.config.get('server.max_request_body_size',
                                      100 * 1024 * 1024))
        if mbs > 0:
            self.rfile = http.SizeCheckWrapper(self.rfile, mbs)
        try:
            return _cpwsgiserver.HTTPRequest.decode_chunked(self)
        except http.MaxSizeExceeded:
            self.simple_response("413 Request Entity Too Large")
            cherrypy.log(traceback=True)
            return False

class CPHTTPConnection(_cpwsgiserver.HTTPConnection):

    RequestHandlerClass = CPHTTPRequest

class WSGIServer(_cpwsgiserver.CherryPyWSGIServer):

    """Wrapper for _cpwsgiserver.CherryPyWSGIServer.

    _cpwsgiserver has been designed to not reference CherryPy in any way,
    so that it can be used in other frameworks and applications. Therefore,
    we wrap it here, so we can set our own mount points from cherrypy.tree.

    """

    ConnectionClass = CPHTTPConnection

    def __init__(self):
        conf = cherrypy.config.get

        sockFile = conf('server.socket_file')
        if sockFile:
            bind_addr = sockFile
        else:
            bind_addr = (conf('server.socket_host'),
                         conf('server.socket_port'))

        s = _cpwsgiserver.CherryPyWSGIServer
        # We could just pass cherrypy.tree, but by passing tree.apps,
        # we get correct SCRIPT_NAMEs as early as possible.
        s.__init__(self, bind_addr, cherrypy.tree.apps.items(),
                   conf('server.thread_pool'),
                   conf('server.socket_host'),
                   request_queue_size = conf('server.socket_queue_size'),
                   timeout = conf('server.socket_timeout'),
                   )
        s.protocol = conf('server.protocol_version', 'HTTP/1.1')

<|endoftext|>


<commit_before>import socket
import unittest
from functools import wraps

import asyncio
from aiohttp import log
from chilero import web

def asynctest(f):

    @wraps(f)
    def wrapper(*args, **kwargs):
        @asyncio.coroutine
        def go():
            yield from f(*args, **kwargs)

        loop = asyncio.get_event_loop()
        loop.run_until_complete(go())
    return wrapper

class WebTestCase(unittest.TestCase):
    application = web.Application
    routes = []

    def setUp(self):
        self.loop = asyncio.new_event_loop()
        asyncio.set_event_loop(self.loop)

        @asyncio.coroutine
        def go():
            self.app = self.application(self.routes)
            yield from self.create_server()

        self.loop.run_until_complete(go())

    def tearDown(self):
        self.app.finish()
        self.loop.close()

    @asyncio.coroutine
    def create_server(self):
        if hasattr(self, 'port'):
            return  # pragma: no cover

        app = getattr(self, 'app')
        assert app is not None, 'Application not initialized'

        self.port = self.find_unused_port()

        self.handler = app.make_handler(
            debug=True, keep_alive_on=False,
            access_log=log.access_logger)
        self.server = yield from self.loop.create_server(
            self.handler, '127.0.0.1', self.port)

    def full_url(self, path):
        return 'http://127.0.0.1:{}{}'.format(self.port, path)

    def find_unused_port(self):
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.bind(('127.0.0.1', 0))
        port = s.getsockname()[1]
        s.close()
        return port
<commit_msg>Specify the current loop in WebTestCase application<commit_after>import socket
import unittest
from functools import wraps

import asyncio
from aiohttp import log
from chilero import web

def asynctest(f):

    @wraps(f)
    def wrapper(*args, **kwargs):
        @asyncio.coroutine
        def go():
            yield from f(*args, **kwargs)

        loop = asyncio.get_event_loop()
        loop.run_until_complete(go())
    return wrapper

class WebTestCase(unittest.TestCase):
    application = web.Application
    routes = []

    def setUp(self):
        self.loop = asyncio.new_event_loop()
        asyncio.set_event_loop(self.loop)

        @asyncio.coroutine
        def go():
            self.app = self.application(self.routes, loop=self.loop)
            yield from self.create_server()

        self.loop.run_until_complete(go())

    def tearDown(self):
        self.app.finish()
        self.loop.close()

    @asyncio.coroutine
    def create_server(self):
        if hasattr(self, 'port'):
            return  # pragma: no cover

        app = getattr(self, 'app')
        assert app is not None, 'Application not initialized'

        self.port = self.find_unused_port()

        self.handler = app.make_handler(
            debug=True, keep_alive_on=False,
            access_log=log.access_logger)
        self.server = yield from self.loop.create_server(
            self.handler, '127.0.0.1', self.port)

    def full_url(self, path):
        return 'http://127.0.0.1:{}{}'.format(self.port, path)

    def find_unused_port(self):
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.bind(('127.0.0.1', 0))
        port = s.getsockname()[1]
        s.close()
        return port
<|endoftext|>


<commit_before><commit_msg>Added WhoisArnesSiParser<commit_after>from .base_scannable import ScannableParserBase
from ..exceptions import ParserError
from ..record import *
from dateutil import parser as timeparser
import re

class WhoisArnesSiParser(ScannableParserBase):

    @property
    def status(self):
        pattern = re.compile("status:\s+(.+)\n")
        match = pattern.search(self.content_for_scanner)

        if match:
            statuses = match.group(1).strip().lower().split(",")
            if 'ok' in statuses or 'serverupdateprohibited' in statuses:
                return 'registered'
            else:
                raise ParserError("Unknown status '%s'." % statuses)
        else:
            return 'available'

    @property
    def available(self):
        return "% No entries found" in self.content_for_scanner

    @property
    def registered(self):
        return not self.available

    @property
    def created_on(self):
        match = re.compile("created:\s+(.*)\n").search(self.content_for_scanner)
        if match:
            return timeparser.parse(match.group(1))

    @property
    def expires_on(self):
        match = re.compile("expire:\s+(.*)\n").search(self.content_for_scanner)
        if match:
            return timeparser.parse(match.group(1))

    @property
    def nameservers(self):
        pattern = re.compile("nameserver:\s+(.+)\n")
        return [Nameserver(name.strip().lower()) for name in pattern.findall(self.content_for_scanner)]
<|endoftext|>


<commit_before># This program contains methods to:
#   - extract x, y and sb values for pvs inside all BPM
#     elements using caget and BPM.get().
#   - plot the x, y BPM coordinates against sb using matplotlib and scisoftpy.
from pkg_resources import DistributionNotFound
try:
    import pkg_resources
    pkg_resources.require('aphla')
    import aphla as ap

    # Setup
    ap.machines.load('SRI21')
    BPMS = ap.getElements('BPM')

except (DistributionNotFound, ImportError) as err:
    print err.errormessage()
    print ''' Error importing one of the libraries: pkg_resources, aphla. '''
    import sys
    sys.exit()

def bpm_enabled(bpm):
    ''' Check if BPM is enabled using caget. '''
    pvs = bpm.pv()
    # Assume that all PVs have the same prefix
    pv_enabled = '{0}:CF:ENABLED_S'.format(pvs[0].split(':')[0])
    return caget(pv_enabled)

def pv_xysb_values(BPMS):
    ''' Method to return lists of values for x, y and sb properties of a BPM '''
    x_bpm_values = list()
    y_bpm_values = list()
    sb_bpm_values = list()

    for BPM in BPMS:
        # Check if the pv is enabled
        if(bpm_enabled(BPM)):
            # Get its value and store it in the list
            x_bpm_values.append(BPM.get('x', handle='readback'))
            y_bpm_values.append(BPM.get('y', handle='readback'))
            sb_bpm_values.append(BPM.sb)
        else:
            print 'Found a BPM which is not enabled'

    return x_bpm_values, y_bpm_values, sb_bpm_values

def pv_xysb_values_with_caget(BPMS):
    ''' Method to return lists of values for x, y and sb properties of a BPM
        using caget '''
    x_bpm_values = list()
    y_bpm_values = list()
    sb_bpm_values = list()

    for BPM in BPMS:
        pvs = BPM.pv()
        # Check if the pv is enabled
        if(bpm_enabled(BPM)):
            # Get its value and store it in the list
            if ':Y' in pvs[0]:
                y_bpm_values.append(pvs[0])
                x_bpm_values.append(pvs[1])
                sb_bpm_values.append(BPM.sb)
            else:
                x_bpm_values.append(pvs[0])
                y_bpm_values.append(pvs[1])
                sb_bpm_values.append(BPM.sb)
        else:
            print "Found a pv value which is not enabled"

    x_bpm_values = caget(x_bpm_values)
    y_bpm_values = caget(y_bpm_values)

    return x_bpm_values, y_bpm_values, sb_bpm_values

def plot_with_scisoftpy():
    a = dnp.arange(1,10.)
    b = dnp.arange(3,14.)
    dnp.plot.line([a,a+12.3]) # plots two lines against array index
    dnp.plot.line(2*a, [a,a+12.3]) # plots two lines against 2*a
    dnp.plot.line([2*a, 3.5*b], [a,b]) # plots two lines against defined x values

def time_function(my_function, my_args):
    ''' Method to time '''
    print 'Timing {0}'.format(my_function.__name__)
    start = time.time()
    x_bpm_values, y_bpm_values, sb_bpm_values = pv_xysb_values_with_caget(my_args)
    end = time.time()
    print (end - start)

    return x_bpm_values, y_bpm_values, sb_bpm_values

try:
    import numpy
    import time
    import matplotlib.pyplot as p
    import time
    from cothread.catools import caget
    print """ Trying to plot the values using Scisoftpy. """
    import scisoftpy.plot as dpl

    x_bpm_values, y_bpm_values, sb_bpm_values = time_function(pv_xysb_values, BPMS)
    x_bpm_values, y_bpm_values, sb_bpm_values = time_function(pv_xysb_values_with_caget, BPMS)

    dpl.plot(numpy.array(sb_bpm_values), [numpy.array(x_bpm_values), numpy.array(y_bpm_values)])
except ImportError as err:
    print str(err)
    print """ Scisoftpy was probably not found. Will try using matplotlib. """
    pkg_resources.require('matplotlib')

    x_bpm_values, y_bpm_values, sb_bpm_values = time_function(pv_xysb_values, BPMS)
    x_bpm_values, y_bpm_values, sb_bpm_values = time_function(pv_xysb_values_with_caget, BPMS)

    p.ylabel('X/Y BPM Values')
    p.xlabel('SB BPM Values')
    p.plot(sb_bpm_values, x_bpm_values, 'r', sb_bpm_values, y_bpm_values, 'g')
    p.show()
<commit_msg>Rearrange import logic.<commit_after># This program contains methods to:
#   - extract x, y and sb values for pvs inside all BPM
#     elements using caget and BPM.get().
#   - plot the x, y BPM coordinates against sb using matplotlib and scisoftpy.
import time
import pkg_resources
try:
    pkg_resources.require('aphla')
    import numpy
    from cothread.catools import caget
    import aphla as ap
    # Setup
    ap.machines.load('SRI21')
except (pkg_resources.DistributionNotFound, ImportError) as err:
    print str(err)
    print ''' Error importing one of the libraries: pkg_resources, aphla. '''
    import sys
    sys.exit()

def bpm_enabled(bpm):
    ''' Check if BPM is enabled using caget. '''
    pvs = bpm.pv()
    # Assume that all PVs have the same prefix
    pv_enabled = '{0}:CF:ENABLED_S'.format(pvs[0].split(':')[0])
    return caget(pv_enabled)

def pv_xysb_values(BPMS):
    ''' Method to return lists of values for x, y and sb properties of a BPM '''
    x_bpm_values = list()
    y_bpm_values = list()
    sb_bpm_values = list()

    for BPM in BPMS:
        # Check if the pv is enabled
        if(bpm_enabled(BPM)):
            # Get its value and store it in the list
            x_bpm_values.append(BPM.get('x', handle='readback'))
            y_bpm_values.append(BPM.get('y', handle='readback'))
            sb_bpm_values.append(BPM.sb)
        else:
            print 'Found a BPM which is not enabled'

    return x_bpm_values, y_bpm_values, sb_bpm_values

def pv_xysb_values_with_caget(BPMS):
    ''' Method to return lists of values for x, y and sb properties of a BPM
        using caget '''
    x_bpm_values = list()
    y_bpm_values = list()
    sb_bpm_values = list()

    for BPM in BPMS:
        pvs = BPM.pv()
        # Check if the pv is enabled
        if(bpm_enabled(BPM)):
            # Get its value and store it in the list
            if ':Y' in pvs[0]:
                y_bpm_values.append(pvs[0])
                x_bpm_values.append(pvs[1])
                sb_bpm_values.append(BPM.sb)
            else:
                x_bpm_values.append(pvs[0])
                y_bpm_values.append(pvs[1])
                sb_bpm_values.append(BPM.sb)
        else:
            print "Found a pv value which is not enabled"

    x_bpm_values = caget(x_bpm_values)
    y_bpm_values = caget(y_bpm_values)

    return x_bpm_values, y_bpm_values, sb_bpm_values

def plot_with_scisoftpy():
    a = dnp.arange(1,10.)
    b = dnp.arange(3,14.)
    dnp.plot.line([a,a+12.3]) # plots two lines against array index
    dnp.plot.line(2*a, [a,a+12.3]) # plots two lines against 2*a
    dnp.plot.line([2*a, 3.5*b], [a,b]) # plots two lines against defined x values

def time_function(my_function, my_args):
    ''' Method to time '''
    print 'Timing {0}'.format(my_function.__name__)
    start = time.time()
    x_bpm_values, y_bpm_values, sb_bpm_values = pv_xysb_values_with_caget(my_args)
    end = time.time()
    print (end - start)

    return x_bpm_values, y_bpm_values, sb_bpm_values

BPMS = ap.getElements('BPM')
x_bpm_values, y_bpm_values, sb_bpm_values = time_function(pv_xysb_values, BPMS)
x_bpm_values, y_bpm_values, sb_bpm_values = time_function(pv_xysb_values_with_caget, BPMS)

try:
    print """ Trying to plot the values using Scisoftpy. """
    import scisoftpy.plot as dpl

    dpl.plot(numpy.array(sb_bpm_values), [numpy.array(x_bpm_values), numpy.array(y_bpm_values)])
except ImportError as err:
    print str(err)
    print """ Scisoftpy was probably not found. Will try using matplotlib. """
    pkg_resources.require('matplotlib')
    import matplotlib.pyplot as p

    p.ylabel('X/Y BPM Values')
    p.xlabel('SB BPM Values')
    p.plot(sb_bpm_values, x_bpm_values, 'r', sb_bpm_values, y_bpm_values, 'g')
    p.show()
<|endoftext|>