spyceTag.py :  » Web-Frameworks » Spyce » spyce-2.1 » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Web Frameworks » Spyce 
Spyce » spyce 2.1 » spyceTag.py
##################################################
# SPYCE - Python-based HTML Scripting
# Copyright (c) 2002 Rimon Barr.
#
# Refer to spyce.py
# CVS: $Id: spyceTag.py 1174 2006-08-29 17:22:17Z ellisj $
##################################################

__doc__ = '''Spyce tags functionality.'''

import sys, inspect
import spyce, spyceUtil
import spyceException, spyceModule

##################################################
# Spyce tag library
#

def invokeSingleton(api, tagname, memoize=False, **kwargs):
  assert isinstance(api, spyce.spyceWrapper), 'expected spyceWrapper; got %s' % api.__class__
  spylambda = api.getModule('spylambda')
  code = '[[ from spyceException import * ]] <%s %s />' % (tagname, ' '.join(['%s="=%s"' % (key, value) for key, value in kwargs.iteritems()]))
  lamb = spylambda.define(','.join(kwargs.iterkeys()), code, memoize)
  lamb(**kwargs)

class spyceTagLibrary:
  "All Spyce tag libraries should subclass this."
  def __init__(self, prefix):
    self._prefix = prefix
    self._taghash = {}
    for tag in self.tags:
      self._taghash[tag.name] = tag
  def getTag(self, api, name, id, context, attrs, paired, parent=None):
    tag = self.getTagClass(name)(id, api, self._prefix, context, attrs, paired, parent)
    tag._lib = self
    return tag
  def getTagClass(self, name):
    return self._taghash[name]

  # functions to override
  tags = []
  def start(self):
    pass
  def finish(self):
    pass

##################################################
# Spyce tag
#

class spyceTag:
  "All Spyce tags should subclass this."
  def __init__(self, id, api, prefix, context, attrs, paired, parent=None):
    "Initialize a tag; prefix = current library prefix"
    self._id = id
    if 0 and api:
      assert isinstance(api, spyce.spyceWrapper)
    self._api = api
    self._prefix = prefix
    self._pair = paired
    self._parent = parent
    self._context = context
    self._out = None
    self._buffered = 0
    if api and 'handler' in attrs:
      # api == None means it's just tagchecker, and parent will always be None
      ftag = self.getParent('form')
      if not ftag:
        raise spyceTagSyntaxException('tags with active handlers must be nested inside form:form')
      if 'action' in ftag._attrs:
        raise spyceTagSyntaxException('parent form action is incompatible with active handlers')
      # delete it before it gets to begin()
      # subclass can always do own attr checking before calling spyceTag.__init__
      del attrs['handler'] 
    self._attrs = self._attrsEval(attrs)
  def _attrsEval(self, attrs):
    if not self._context: # tagchecker passes None
      return attrs
    for key, expr in attrs.items():
      if expr and expr[0] == '=':
        attrs[key] = self.eval(expr[1:])
    return attrs
  def eval(self, expr):
    try:
      return eval(expr, self._context)
    except NameError, e:
      if '.' not in expr:
        raise
      # maybe it's a module reference
      modname = expr.split('.')[0]
      try:
        mod = self._api.getModule(modname)
      except ImportError:
        raise e
      self._context[modname] = mod
      return eval(expr, self._context)
    except TypeError:
      raise 'Expected python code; unable to evaluate %s' % expr
  # setup tag environment (output stream)
  def setOut(self, out):
    "Set output stream"
    self._out = out
  def setBuffered(self, buffered):
    "Set whether tag is running on a buffer wrt. enclosing scope"
    self._buffered = buffered
  # accessors
  def getPrefix(self):
    "Return tag prefix"
    return self._prefix
  def getAttributes(self):
    "Get tag attributes."
    return self._attrs
  def getPaired(self):
    "Return whether this is a paired or singleton tag."
    return self._pair
  def getParent(self, name=None):
    "Get parent tag"
    parent = self._parent
    if name is not None:
      while parent is not None:
        if parent.name == name: 
          break
        parent = parent._parent
    return parent
  def getFullId(self):
    id = ''
    p = self
    # tag compiler restricts handlers to be inside form
    while p and p.__class__.__name__ != 'form_form':
      if p._id:
        id = p._id + id
      p = p._parent
    return id
  def getOut(self):
    "Return output stream"
    return self._out
  def getBuffered(self):
    "Get whether tag is running on a buffer wrt. enclosing scope"
    return self._buffered
  # functions and fields to override
  "Code chunk to insert into calling class (code, ref)" # for use by [[! code blocks in compiled tags
  classcode = None
  "Handlers to insert into calling class"
  handlers = None
  "The name of this tag!"
  name = None
  "Whether this tag wants to buffer its body processing"
  buffer = 0
  "Whether this tag want to conditionally perform body processing"
  conditional = 0
  "Whether this tag wants to possibly loop body processing"
  loops = 0
  "Whether this tag wants to handle exceptions"
  catches = 0
  "Whether end() must (even on exception) get called if begin() completes"
  mustend = 0
  "Whether this tag wants to export values to calling context (overrides export())"
  exports = 0
  def syntax(self):
    "Check tag syntax"
    pass
  def begin(self, **kwargs):
    "Process start tag; return true to process body (if conditional==1)"
    return 1
  def export(self):
    """
    return dict of any key/value pairs tag wants to propagate into spyceProcess locals.
    (Obviously, key must be a string; value may be any object.)
    Used e.g. by <for val="x" ...> to send x into parent scope.
    _Must set class.exports or export method will not be called._
    """
    return None
  def body(self, _contents):
    "Process tag body; return true to repeat (if loops==1)"
    if _contents:
      self.getOut().write(_contents)
    return 0
  def end(self):
    "Process end tag"
    pass
  def catch(self, ex):
    "Process any exception thrown by tag (if catches==1)"
    raise

class spyceTagPlus(spyceTag):
  "An easier spyceTag class to work with..."
  def getModule(self, name): 
    "Return a Spyce module reference" 
    return self._api.getModule(name)

  def parentRequired(self, parentname):
    parent = self.getParent(parentname)
    if not parent:
      raise '%s tag must be used inside a parent %s active tag' % (self.name, parentname)
    return parent
  def syntaxNonEmpty(self, *names):
    for name in names:
      try: value = self._attrs[name]
      except KeyError: return
      if not value:
        raise spyceTagSyntaxException('attribute "%s" should not be empty', name)
  def syntaxNonEmpty(self, *names):
    for name in names:
      try: value = self._attrs[name]
      except KeyError: return
      if not value:
        raise spyceTagSyntaxException('attribute "%s" should not be empty', name)
  def syntaxNonEmpty(self, *names):
    for name in names:
      try: value = self._attrs[name]
      except KeyError: return
      if not value:
        raise spyceTagSyntaxException('attribute "%s" should not be empty', name)
  def syntaxNonEmpty(self, *names):
    for name in names:
      try: value = self._attrs[name]
      except KeyError: return
      if not value:
        raise spyceTagSyntaxException('attribute "%s" should not be empty', name)
  def syntaxNonEmpty(self, *names):
    for name in names:
      try: value = self._attrs[name]
      except KeyError: return
      if not value:
        raise spyceTagSyntaxException('attribute "%s" should not be empty', name)
  def syntaxValidSet(self, name, validSet):
    try: value = self._attrs[name]
    except KeyError: return
    if value not in validSet:
      raise spyceTagSyntaxException('attribute "%s" should be one of: %s'% (name, ', '.join(validSet)))
  def syntaxPairOnly(self):
    "Ensure that this tag is paired i.e. open/close"
    if not self._pair:
      raise spyceTagSyntaxException('singleton tag not allowed')
  def syntaxSingleOnly(self):
    "Ensure that this tag is single i.e. <foo/>"
    if self._pair:
      raise spyceTagSyntaxException('paired tag not allowed')


##################################################
# Spyce tag syntax checking
#

class spyceTagChecker:
  def __init__(self, server):
    self._server = server
    self._taglibs = {}
    self._stack = []
  def loadLib(self, libname, libfrom, libas, rel_file, info=None):
    if not libas: libas = libname
    try: 
      self._taglibs[(libname, libfrom)] = \
        self._server.loadModule(libname, libfrom, rel_file)(libas)
    except (SyntaxError, TypeError):
      raise
    except:
      sys.stdout.write('%s\n' % spyceUtil.exceptionString())
      raise spyceException.spyceSyntaxError(
        'unable to load module: %s (%s)' % (libname, libas), info)
  def getTag(self, (libname,libfrom), name, context, attrs, pair, info):
    lib = self._taglibs[(libname, libfrom)]
    try:
      return lib.getTag(None, name, None, None, attrs, pair, None)
    except:
      spyce.DEBUG(spyceUtil.exceptionString())
      raise spyceException.spyceSyntaxError(
        'unknown tag "%s:%s"'%(libname, name), info)
  def getTagClass(self, (libname, libfrom), name, info):
    lib = self._taglibs[(libname, libfrom)]
    try:
      return lib.getTagClass(name)
    except:
      spyce.DEBUG(spyceUtil.exceptionString())
      s = 'unknown tag "%s:%s" (known tags in %s are: %s)' % (
        libname,
        name,
        libname,
        ','.join([t.name for t in lib.tags]))
      raise spyceException.spyceSyntaxError(s, info)
  def startTag(self, (libname,libfrom), name, attrs, pair, info):
    tag = self.getTag((libname, libfrom), name, None, attrs, pair, info)
    try:
      # standard signature validation
      (args, varargs, varkw, defaults) = inspect.getargspec(tag.begin)
      # args w/ defaults don't need to be checked
      if defaults:
        n_defaults = len(defaults)
      else:
        n_defaults = 0
      L = args[1:len(args) - n_defaults] # assume self is first
      for attr in L: 
        if attr not in attrs:
          raise spyceTagSyntaxException('"%s" tag call missing compulsory "%s" attribute' % (name, attr))
      # extra attrs cause an error, if *args/**kwargs not in signature
      for attr in attrs:
        # spyceCompile checks to make sure 'handler' is ok; tagChecker
        # doesn't have the necessary info to make that decision.
        if attr not in args and not varargs and not varkw and attr != 'handler':
          raise spyceTagSyntaxException('unexpected attribute "%s"' % attr)
      # custom validation
      error = tag.syntax()
    except spyceTagSyntaxException, e:
      spyce.DEBUG(spyceUtil.exceptionString())
      raise spyceException.spyceSyntaxError(str(e), info)
    if error:
      raise spyceException.spyceSyntaxError(error, info)
    if pair:
      self._stack.append( (libname, libfrom, name, info) )
  def endTag(self, (libname,libfrom), name, info):
    try:
      libname1, libfrom1, name1, info1 = self._stack.pop()
    except IndexError:
      raise spyceException.spyceSyntaxError(
        'unmatched close tag', info)
    if (libname1,libfrom1,name1) != (libname,libfrom,name): 
      raise spyceException.spyceSyntaxError(
        'unmatched close tag, expected <%s:%s>' % (libname1,name1), info)
  def finish(self):
    if self._stack:
      libname, libfrom, name, info = self._stack.pop()
      raise spyceException.spyceSyntaxError(
        'unmatched open tag', info)

##################################################
# Spyce tag syntax exception
#

class spyceTagSyntaxException:
  def __init__(self, str):
    self._str = str
  def __repr__(self):
    return self._str

www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.