Commit a7b3397b authored by Ken Manheimer's avatar Ken Manheimer

- regress is a regression testing script,

- *.stx are (mostly arbitrary) reference structured text files, and

- *.ref are previously processed output from the corresponding *.stx files.

Here's the in-depth explanation:

The directory has a bunch of .stx files (ones found on the zope.org
site, plus an 'examples.stx' file, for accumulating a body of
examples) plus corresponding .ref files, previously produced by a
prior, established StructuredText version.  The script 'regress'
applies the new ../StructuredText.py version to produce .new files,
and then compares the .ref files and the .new files, complaining if
any differences are found.

The intended procedure is to make your changes in ../StructuredText.py,
iron them out as best you can, and then try the regress script to
identify any unexpected functionality changes/backwards-compatability
losses.  (We also need to develop the body of reference text and examples.)
parent 587a5c22
This diff is collapsed.
Acquisition
"Copyright (C) 1996-1998, Digital Creations":COPYRIGHT.html.
Acquisition [1] is a mechanism that allows objects to obtain
attributes from their environment. It is similar to inheritence,
except that, rather than traversing an inheritence hierarchy
to obtain attributes, a containment hierarchy is traversed.
The "ExtensionClass":ExtensionClass.html. release includes mix-in
extension base classes that can be used to add acquisition as a
feature to extension subclasses. These mix-in classes use the
context-wrapping feature of ExtensionClasses to implement
acquisition. Consider the following example::
import ExtensionClass, Acquisition
class C(ExtensionClass.Base):
color='red'
class A(Acquisition.Implicit):
def report(self):
print self.color
a=A()
c=C()
c.a=A()
c.a.report() # prints 'red'
d=C()
d.color='green'
d.a=a
d.a.report() # prints 'green'
a.report() # raises an attribute error
The class 'A' inherits acquisition behavior from
'Acquisition.Implicit'. The object, 'a', "has" the color of
objects 'c' and 'd' when it is accessed through them, but it
has no color by itself. The object 'a' obtains attributes
from it's environment, where it's environment is defined by
the access path used to reach 'a'.
Acquisition wrappers
When an object that supports acquisition is accessed through
an extension class instance, a special object, called an
acquisition wrapper, is returned. In the example above, the
expression 'c.a' returns an acquisition wrapper that
contains references to both 'c' and 'a'. It is this wrapper
that performs attribute lookup in 'c' when an attribute
cannot be found in 'a'.
Aquisition wrappers provide access to the wrapped objects
through the attributes 'aq_parent', 'aq_self', 'aq_base'.
In the example above, the expressions::
'c.a.aq_parent is c'
and::
'c.a.aq_self is a'
both evaluate to true, but the expression::
'c.a is a'
evaluates to false, because the expression 'c.a' evaluates
to an acquisition wrapper around 'c' and 'a', not 'a' itself.
The attribute 'aq_base' is similar to 'aq_self'. Wrappers may be
nested and 'aq_self' may be a wrapped object. The 'aq_base'
attribute is the underlying object with all wrappers removed.
Acquisition Control
Two styles of acquisition are supported in the current
ExtensionClass release, implicit and explicit aquisition.
Implicit acquisition
Implicit acquisition is so named because it searches for
attributes from the environment automatically whenever an
attribute cannot be obtained directly from an object or
through inheritence.
An attribute may be implicitly acquired if it's name does
not begin with an underscore, '_'.
To support implicit acquisition, an object should inherit
from the mix-in class 'Acquisition.Implicit'.
Explicit Acquisition
When explicit acquisition is used, attributes are not
automatically obtained from the environment. Instead, the
method 'aq_aquire' must be used, as in::
print c.a.aq_acquire('color')
To support explicit acquisition, an object should inherit
from the mix-in class 'Acquisition.Explicit'.
Controlled Acquisition
A class (or instance) can provide attribute by attribute control
over acquisition. This is done by:
- subclassing from 'Acquisition.Explicit', and
- setting all attributes that should be acquired to the special
value: 'Acquisition.Acquired'. Setting an attribute to this
value also allows inherited attributes to be overridden with
acquired ones.
For example, in::
class C(Acquisition.Explicit):
id=1
secret=2
color=Acquisition.Acquired
__roles__=Acquisition.Acquired
The *only* attributes that are automatically acquired from
containing objects are 'color', and '__roles__'. Note also
that the '__roles__' attribute is acquired even though it's
name begins with an underscore. In fact, the special
'Acquisition.Acquired' value can be used in
'Acquisition.Implicit' objects to implicitly acquire selected
objects that smell like private objects.
Filtered Acquisition
The acquisition method, 'aq_acquire', accepts two optional
arguments. The first of the additional arguments is a
"filtering" function that is used when considering whether to
acquire an object. The second of the additional arguments is an
object that is passed as extra data when calling the filtering
function and which defaults to 'None'.
The filter function is called with five arguments:
- The object that the 'aq_acquire' method was called on,
- The object where an object was found,
- The name of the object, as passed to 'aq_acquire',
- The object found, and
- The extra data passed to 'aq_acquire'.
If the filter returns a true object that the object found is
returned, otherwise, the acquisition search continues.
For example, in::
from Acquisition import Explicit
class HandyForTesting:
def __init__(self, name): self.name=name
def __str__(self):
return "%s(%s)" % (self.name, self.__class__.__name__)
__repr__=__str__
class E(Explicit, HandyForTesting): pass
class Nice(HandyForTesting):
isNice=1
def __str__(self):
return HandyForTesting.__str__(self)+' and I am nice!'
__repr__=__str__
a=E('a')
a.b=E('b')
a.b.c=E('c')
a.p=Nice('spam')
a.b.p=E('p')
def find_nice(self, ancestor, name, object, extra):
return hasattr(object,'isNice') and object.isNice
print a.b.c.aq_acquire('p', find_nice)
The filtered acquisition in the last line skips over the first
attribute it finds with the name 'p', because the attribute
doesn't satisfy the condition given in the filter. The output of
the last line is::
spam(Nice) and I am nice!
Acquisition and methods
Python methods of objects that support acquisition can use
acquired attributes as in the 'report' method of the first example
above. When a Python method is called on an object that is
wrapped by an acquisition wrapper, the wrapper is passed to the
method as the first argument. This rule also applies to
user-defined method types and to C methods defined in pure mix-in
classes.
Unfortunately, C methods defined in extension base classes that
define their own data structures, cannot use aquired attributes at
this time. This is because wrapper objects do not conform to the
data structures expected by these methods.
Acquiring Acquiring objects
Consider the following example::
from Acquisition import Implicit
class C(Implicit):
def __init__(self, name): self.name=name
def __str__(self):
return "%s(%s)" % (self.name, self.__class__.__name__)
__repr__=__str__
a=C("a")
a.b=C("b")
a.b.pref="spam"
a.b.c=C("c")
a.b.c.color="red"
a.b.c.pref="eggs"
a.x=C("x")
o=a.b.c.x
The expression 'o.color' might be expected to return '"red"'. In
earlier versions of ExtensionClass, however, this expression
failed. Acquired acquiring objects did not acquire from the
environment they were accessed in, because objects were only
wrapped when they were first found, and were not rewrapped as they
were passed down the acquisition tree.
In the current release of ExtensionClass, the expression "o.color"
does indeed return '"red"'.
When searching for an attribute in 'o', objects are searched in
the order 'x', 'a', 'b', 'c'. So, for example, the expression,
'o.pref' returns '"spam"', not '"eggs"'. In earlier releases of
ExtensionClass, the attempt to get the 'pref' attribute from 'o'
would have failed.
If desired, the current rules for looking up attributes in complex
expressions can best be understood through repeated application of
the '__of__' method:
'a.x' -- 'x.__of__(a)'
'a.b' -- 'b.__of__(a)'
'a.b.x' -- 'x.__of__(a).__of__(b.__of__(a))'
'a.b.c' -- 'c.__of__(b.__of__(a))'
'a.b.c.x' --
'x.__of__(a).__of__(b.__of__(a)).__of__(c.__of__(b.__of__(a)))'
and by keeping in mind that attribute lookup in a wrapper
is done by trying to lookup the attribute in the wrapped object
first and then in the parent object. In the expressions above
involving the '__of__' method, lookup proceeds from left to right.
Note that heuristics are used to avoid most of the repeated
lookups. For example, in the expression: 'a.b.c.x.foo', the object
'a' is searched no more than once, even though it is wrapped three
times.
.. [1] Gil, J., Lorenz, D.,
"Environmental Acquisition--A New Inheritance-Like Abstraction Mechanism",
http://www.bell-labs.com/people/cope/oopsla/Oopsla96TechnicalProgramAbstracts.html#GilLorenz,
OOPSLA '96 Proceedings, ACM SIG-PLAN, October, 1996
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
<h1>Small Trials for Structured Text Formatting</h1>
<p> This paragraph should be preceded by a level 1 header. It should
not, itself, be made into a header, just a regular paragraph.</p>
<p> Here are a few presentation styles, in a list <a href="#1">[1]</a>:</p>
<ul><li><p>A word: <em>emphasized</em>.</p>
<li><p>A word: <u>underlined</u>.</p>
<li><p>A word <strong>strong</strong>.</p>
</ul>
<p> .. <a href="#1">[1]</a> (The referring text should be a paragraph, not a header, and
should contain a reference to this footnote, footnote "[1]".)</p>
<p> Some hrefs, in a definition list:</p>
<dl><dt> <u>Regular</u><dd><p><a href="http://www.zope.org">http://www.zope.org/</a></p>
<dt> <u>W/trailing punctuation</u><dd><p><a href="http://www.zope.org">http://www.zope.org/</a>.</p>
<dt> <u>W protocol implicit</u><dd><p><a href="locallink">locallink</a></p>
<dt> <u>W protocol implicit</u>, alternate<dd><p><a href="locallink">locallink</a>
</p>
</dl>
Small Trials for Structured Text Formatting
This paragraph should be preceded by a level 1 header. It should
not, itself, be made into a header, just a regular paragraph.
Here are a few presentation styles, in a list [1]:
- A word: *emphasized*.
- A word: _underlined_.
- A word **strong**.
.. [1] (The referring text should be a paragraph, not a header, and
should contain a reference to this footnote, footnote "[1]".)
Some hrefs, in a definition list:
_Regular_ -- "http://www.zope.org/":http://www.zope.org
_W/trailing punctuation_ -- "http://www.zope.org/":http://www.zope.org.
_W protocol implicit_ -- "locallink"::locallink
_W protocol implicit_, alternate -- "locallink", :locallink
<p>
Extension Class</p>
<p> <a href="COPYRIGHT.html">Copyright (C) 1996-1998, Digital Creations</a>.</p>
<p> A lightweight mechanism has been developed for making Python
extension types more class-like. Classes can be developed in an
extension language, such as C or C++, and these classes can be
treated like other python classes:</p>
<ul><li><p>They can be sub-classed in python,</p>
<li><p>They provide access to method documentation strings, and</p>
<li><p>They can be used to directly create new instances.</p>
</ul>
<p> Extension classes provide additional extensions to class and
instance semantics, including:</p>
<ul><li><p>A protocol for accessing subobjects "in the context of" their
containers. This is used to implement custom method types
and <a href="Acquisition.html">environmental acquisition</a>.</p>
<li><p>A protocol for overriding method call semantics. This is used
to implement "synchonized" classes and could be used to
implement argument type checking.</p>
<li><p>A protocol for class initialization that supports execution of a
special <code>__class_init__</code> method after a class has been
initialized.</p>
</ul>
<p> Extension classes illustrate how the Python class mechanism can be
extended and may provide a basis for improved or specialized class
models. </p>
<h1>Releases</h1>
<p> The current release is <a href="ExtensionClass-1.2.tar.gz">1.2</a>
To find out what's changed in this release,
see the <a href="release.html">release notes</a>.</p>
<p> Documentation is available <a href="ExtensionClass.html">on-line</a>.</p>
<h1>Windows Binaries</h1>
<p> A win32 binary release, <a href="ec12.zip">ec12.zip</a> is available. This
release includes all of the ExtensionClass modules built as
Windows extension modules (.pyd) files. These were built for
Python 1.5.1 using Microsoft Visual C++ 5.0 in "Release" mode.</p>
<p></p>
Extension Class
"Copyright (C) 1996-1998, Digital Creations":COPYRIGHT.html.
A lightweight mechanism has been developed for making Python
extension types more class-like. Classes can be developed in an
extension language, such as C or C++, and these classes can be
treated like other python classes:
- They can be sub-classed in python,
- They provide access to method documentation strings, and
- They can be used to directly create new instances.
Extension classes provide additional extensions to class and
instance semantics, including:
- A protocol for accessing subobjects "in the context of" their
containers. This is used to implement custom method types
and "environmental acquisition":Acquisition.html.
- A protocol for overriding method call semantics. This is used
to implement "synchonized" classes and could be used to
implement argument type checking.
- A protocol for class initialization that supports execution of a
special '__class_init__' method after a class has been
initialized.
Extension classes illustrate how the Python class mechanism can be
extended and may provide a basis for improved or specialized class
models.
Releases
The current release is "1.2":ExtensionClass-1.2.tar.gz,
To find out what's changed in this release,
see the "release notes":release.html.
Documentation is available "on-line":ExtensionClass.html.
Windows Binaries
A win32 binary release, "ec12.zip":ec12.zip, is available. This
release includes all of the ExtensionClass modules built as
Windows extension modules (.pyd) files. These were built for
Python 1.5.1 using Microsoft Visual C++ 5.0 in "Release" mode.
#!/bin/bash
# Compare current StructuredText.py processing against prior versions.
# You should see no output if there's no discrepancies.
for i in *.stx; do
stx=$i
base=${i%.stx}
ref=$base.ref
new=$base.new
python ../StructuredText.py $stx > $new
if cmp $ref $new; then
:
else
echo ... so there are differences in the processing
fi
done
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment