This commit is contained in:
Brian Lloyd 2006-03-10 21:14:54 +00:00
Родитель 748f8e2c78
Коммит 614c4b07ff
105 изменённых файлов: 23605 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1 @@
A D/CVSROOT////

210
pythonnet/htdocs/index.html Executable file
Просмотреть файл

@ -0,0 +1,210 @@
<html>
<head>
<title>Python for .NET</title>
<style type="text/css"><!--
body {
font: 8pt/16pt georgia,verdana;
text-decoration: none;
color: #555753;
background: #ffffff;
margin: 0px;
}
p {
font: 8pt/16pt georgia;
}
h1 {
font: bold 14pt;
color: #000044;
background-color: #EFEFFF;
color: #000044;
border-style: solid;
border-width: 1px;
border-color: #555753;
padding: 6px, 2px, 6px, 2px;
}
h2 {
font: bold 14pt;
margin-bottom: 0px;
color: #000044;
}
h3 {
font: bold 12pt;
margin-bottom: 0px;
color: #000044;
}
a:link {
font-weight: bold;
text-decoration: none;
color: #000066;
}
a:visited {
font-weight: bold;
text-decoration: none;
color: #000066;
}
a:hover, a:active {
text-decoration: underline;
color: #000066;
}
pre {
font-family: monospace;
background-color: #EFEFFF;
color: #000044;
border-style: solid;
border-width: 1px;
border-color: #555753;
padding: 6px, 2px, 6px, 2px;
}
li {
font: 8pt/16pt georgia,verdana;
text-decoration: none;
color: #555753;
}
.spacer {
font: bold 14pt;
}
.menu {
background-color: #EFEFFF;
color: #000044;
border-style: solid;
border-width: 1px;
border-color: #555753;
padding: 6px, 2px, 6px, 2px;
font-size: x-small;
}
.menu ul {
margin: 0px;
padding: 0px;
}
//--></style>
</head>
<body>
<table width="98%" border="0" cellspacing="4">
<tr>
<!--
<td align="left" valign="top" width="20%" class="menu">
<h1>Python for .NET</h1>
</td>
-->
<td align="left" valign="top">
<h1>Python for .NET</h1>
<p>
Python for .NET is a package that gives Python programmers nearly seamless
integration with the .NET Common Language Runtime (CLR) and provides a
powerful application scripting tool for .NET developers. Using this package
you can script .NET applications or build entire applications in Python,
using .NET services and components written in any language that targets the
CLR (Managed C++, C#, VB, JScript).
</p>
<p>
Note that this package does <em>not</em> implement Python as a first-class
CLR language - it does not produce managed code (IL) from Python code.
Rather, it is an integration of the C Python engine with the .NET runtime.
This approach allows you to use use CLR services and continue to use existing
Python code and C-based extensions while maintaining native execution speeds
for Python code. If you are interested in a pure managed-code implementation
of the Python language, you should check out the
<a href="http://www.ironpython.com">IronPython</a> project, which is in
active development.
</p>
<p>
Python for .NET is currently compatible with Python releases 2.3 and greater.
To subscribe to the
<a href="http://mail.python.org/mailman/listinfo/pythondotnet">
Python for .NET mailing list
</a> or read the
<a href="http://mail.python.org/pipermail/pythondotnet/">
online archives
</a> of the list, see the
<a href="http://mail.python.org/mailman/listinfo/pythondotnet">
mailing list information
</a> page. You can also send questions or comments to me at
<a href="mailto:brian.lloyd@revolution.com">brian.lloyd@revolution.com</a>
or use the
<a href="http://sourceforge.net/tracker/?group_id=162464">
Python for .NET issue tracker</a> to report issues.
</p>
<p>
My <a href="http://brianlloyd.blogspot.com">blog site</a> is also
(sometimes) a good source for more information on Python for .NET ;)
</p>
<ul>
<li>The <a href="./readme.html">README</a>
provides a detailed overview of Python for .NET, as well as
some basic usage examples. Many other examples can be found
in the demos and unit tests for the package.
</li>
<li>Checkout the
<a href="http://cvs.sourceforge.net/viewcvs.py/pythonnet">PythonNet</a>
code
from CVS. See the <a href="http://sourceforge.net/cvs/?group_id=162464">
instructions on Source Forge</a> for details.
</li>
<li><strong>Python 2.4 Releases</strong>
<br />
<a href="./Releases/pythonnet-1.0-rc2-py2.4-clr1.1.exe">
pythonnet-1.0-rc2-py2.4-clr1.1.exe
</a>
<br />
<a href="./Releases/pythonnet-1.0-rc2-py2.4-clr1.1-src.tgz">
pythonnet-1.0-rc2-py2.4-clr1.1-src.tgz
</a>
</li>
<li><strong>Python 2.3 Releases</strong>
<br />
<a href="./Releases/pythonnet-1.0-rc2-py2.3-clr1.1.exe">
pythonnet-1.0-rc2-py2.3-clr1.1.exe
</a>
<br />
<a href="./Releases/pythonnet-1.0-rc2-py2.3-clr1.1-src.tgz">
pythonnet-1.0-rc2-py2.3-clr1.1-src.tgz
</a>
</li>
</ul>
</td>
</tr>
</table>
</body>
</html>

61
pythonnet/htdocs/license.txt Executable file
Просмотреть файл

@ -0,0 +1,61 @@
Zope Public License (ZPL) Version 2.0
-----------------------------------------------
This software is Copyright (c) Zope Corporation (tm) and
Contributors. All rights reserved.
This license has been certified as open source. It has also
been designated as GPL compatible by the Free Software
Foundation (FSF).
Redistribution and use in source and binary forms, with or
without modification, are permitted provided that the
following conditions are met:
1. Redistributions in source code must retain the above
copyright notice, this list of conditions, and the following
disclaimer.
2. 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.
3. The name Zope Corporation (tm) must not be used to
endorse or promote products derived from this software
without prior written permission from Zope Corporation.
4. The right to distribute this software or to use it for
any purpose does not give you the right to use Servicemarks
(sm) or Trademarks (tm) of Zope Corporation. Use of them is
covered in a separate agreement (see
http://www.zope.com/Marks).
5. If any files are modified, you must cause the modified
files to carry prominent notices stating that you changed
the files and the date of any change.
Disclaimer
THIS SOFTWARE IS PROVIDED BY ZOPE CORPORATION ``AS IS''
AND ANY EXPRESSED 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 ZOPE CORPORATION OR ITS 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.
This software consists of contributions made by Zope
Corporation and many individuals on behalf of Zope
Corporation. Specific attributions are listed in the
accompanying credits file.

870
pythonnet/htdocs/readme.html Executable file
Просмотреть файл

@ -0,0 +1,870 @@
<html>
<head>
<title>Python for .NET</title>
<style type="text/css"><!--
body {
font: 8pt/16pt georgia,verdana;
text-decoration: none;
color: #555753;
background: #ffffff;
margin: 0px;
}
p {
font: 8pt/16pt georgia;
}
h1 {
font: bold 14pt;
color: #000044;
/*
background-color: #EFEFFF;
color: #000044;
border-style: solid;
border-width: 1px;
border-color: #555753;
padding: 6px, 2px, 6px, 2px;
*/
}
h2 {
font: bold 14pt;
margin-bottom: 0px;
color: #000044;
}
h3 {
font: bold 12pt;
margin-bottom: 0px;
color: #000044;
}
a:link {
font-weight: bold;
text-decoration: none;
color: #000066;
}
a:visited {
font-weight: bold;
text-decoration: none;
color: #000066;
}
a:hover, a:active {
text-decoration: underline;
color: #000066;
}
pre {
font-family: monospace;
background-color: #EFEFFF;
color: #000044;
border-style: solid;
border-width: 1px;
border-color: #555753;
padding: 6px, 2px, 6px, 2px;
}
li {
font: 8pt/16pt georgia,verdana;
text-decoration: none;
color: #555753;
}
.spacer {
font: bold 14pt;
}
.menu {
background-color: #EFEFFF;
color: #000044;
border-style: solid;
border-width: 1px;
border-color: #555753;
padding: 6px, 2px, 6px, 2px;
font-size: x-small;
}
.menu ul {
margin: 0px;
padding: 0px;
}
//--></style>
</head>
<body>
<table width="98%" border="0" cellspacing="4">
<tr>
<td align="left" valign="top" width="20%" class="menu">
<h1>Python for .NET</h1>
<ul>
<li><a href="#installation">Installation</a></li>
<li><a href="#getting_started">Getting Started</a></li>
<li><a href="#importing">Importing Modules</a></li>
<li><a href="#classes">Using Classes</a></li>
<li><a href="#fields">Fields and Properties</a></li>
<li><a href="#indexers">Using Indexers</a></li>
<li><a href="#methods">Using Methods</a></li>
<li><a href="#delegates">Delegates and Events</a></li>
<li><a href="#exceptions">Exception Handling</a></li>
<li><a href="#arrays">Using Arrays</a></li>
<li><a href="#collections">Using Collections</a></li>
<li><a href="#com">COM Components</a></li>
<li><a href="#types">Type Conversion</a></li>
<li><a href="#assemblies">Using Assemblies</a></li>
<li><a href="#embedding">Embedding Python</a></li>
<li><a href="#license">License</a></li>
</ul>
</td>
<td align="left" valign="top">
<p>
Python for .NET is a package that gives Python programmers nearly seamless
integration with the .NET Common Language Runtime (CLR) and provides a
powerful application scripting tool for .NET developers. Using this package
you can script .NET applications or build entire applications in Python,
using .NET services and components written in any language that targets the
CLR (Managed C++, C#, VB, JScript).
</p>
<p>
Note that this package does <em>not</em> implement Python as a first-class
CLR language - it does not produce managed code (IL) from Python code.
Rather, it is an integration of the C Python engine with the .NET runtime.
This approach allows you to use use CLR services and continue to use existing
Python code and C-based extensions while maintaining native execution speeds
for Python code. If you are interested in a pure managed-code implementation
of the Python language, you should check out the
<a href="http://www.ironpython.com">IronPython</a> project, which is in
active development.
</p>
<p>
Python for .NET is currently compatible with Python releases 2.3 and greater.
Current releases are available at the
<a href="http://pythonnet.sourceforge.net/">
Python for .NET website
</a>. To subscribe to the
<a href="http://mail.python.org/mailman/listinfo/pythondotnet">
Python for .NET mailing list
</a> or read the
<a href="http://mail.python.org/pipermail/pythondotnet/">
online archives
</a> of the list, see the
<a href="http://mail.python.org/mailman/listinfo/pythondotnet">
mailing list information
</a> page.
</p>
<a name="#installation"></a>
<h2>Installation</h2>
<p>
Python for .NET is available as a source release and as a Windows installer
for various versions of Python and the common language runtime from the
<a href="http://pythonnet.sourceforge.net/">
Python for .NET website
</a>. On Windows platforms, you can choose to install .NET-awareness into
an existing Python installation as well as install Python for .NET as a
standalone package.
</p>
<p>
The source release is a self-contained "private" assembly.
Just unzip the package wherever you want it, cd to that directory and run
python.exe to start using it. Note that the source release does not
include a copy of the CPython runtime, so you will need to have installed
Python on your machine before using the source release.
</p>
<p>
<strong>Running on Linux/Mono:</strong> preliminary testing shows that
PythonNet will run under <a href="http://www.go-mono.com">Mono</a>, though
the Mono runtime is not yet complete so there still may be problems. The
Python for .NET integration layer is 100% managed code, so there should be
no long-term issues under Mono - it should work better and better as the
Mono platform matures.
</p>
<p>
It is not currently possible to *build* PythonNet using only the Mono
tools, due to an issue involving the Mono assembler / disassembler. You
should, however, be able to try the pre-built assembly under Mono (or
compile it yourself with the MS tools and run it under Mono).
</p>
<p>
Note that if you are running under Mono on a *nix system, you will need
to have a compatible version of Python installed. You will also need
to create a symbolic link to the copy of libpython2.x.so (in your existing
Python installation) in the PythonNet directory. This is needed to ensure
that the mono interop dll loader will find it by name. For example:
</p>
<pre>
ln -s /usr/lib/libpython2.4.so ./python24.so
</pre>
<a name="getting_started"></a>
<h2>Getting Started</h2>
<p>
A key goal for this project has been that Python for .NET should &quot;work
just the way you'd expect in Python&quot;, except for cases that are .NET
specific (in which case the goal is to work &quot;just the way you'd expect
in C#&quot;).
</p>
<p>
If you already know Python, you can probably finish this readme and then
refer to .NET docs to figure out anything you need to do. Conversely if
you are familiar with C# or another .NET language, you probably just
need to pick up one of the many good Python books or read the Python
tutorial online to get started.
</p>
<p>
A good way to start is to run <strong>python.exe</strong> and follow along
with the examples in this document. If you get stuck, there are also a
number of demos and unit tests located in the source directory of the
distribution that can be helpful as examples.
</p>
<a name="importing"></a>
<h2>Importing Modules</h2>
<p>
Python for .NET allows CLR namespaces to be treated essentially as
Python packages. The top-level package is named <code>CLR</code>, and
acts as the root for accessing all CLR namespaces:
</p>
<pre>
from CLR.System import String
import CLR.System as System
</pre>
<p>
Types from any loaded assembly may be imported and used in this manner.
The import hook uses "implicit loading" to support automatic loading
of assemblies whose names correspond to an imported namespace:
</p>
<pre>
# This will implicitly load the System.Windows.Forms assembly
from CLR.System.Windows.Forms import Form
</pre>
<p>
Python for .NET uses the PYTHONPATH (sys.path) to look for assemblies
to load, in addition to the usual application base and the GAC. To
ensure that you can implicitly import an assembly, put the directory
containing the assembly in <code>sys.path</code>.
</p>
<p>
To load assemblies with names that do not correspond with a namespace,
you can use the standard mechanisms provided by the CLR:
</p>
<pre>
from CLR.System.Reflection import Assembly
a = Assembly.LoadWithPartialName("SomeAssembly")
# now we can import namespaces defined in that assembly
from CLR.SomeNamespace import Something
</pre>
<p>
Note that CLR modules are "lazy". Because a namespace can contain a
potentially very large number of classes, reflected CLR classes are
created on-demand when they are requested of a CLR module. This means
that using the Python <code>dir()</code> function in the interactive
interpreter will not necessarily show all of the classes available from
a given CLR module (it will only show any classes that have been referenced
to that point in time).
</p>
<p>
It also means that <code>from somemodule import *</code> will not work as
expected. It is possible that it could be made to work in the future,
but for now it would impose a big performance hit and a lot of
complexity to support something that is used relatively rarely and
often considered bad form in Python anyway ;)
</p>
<a name="classes"></a>
<h2>Using Classes</h2>
<p>
Python for .NET allows you to use any non-private classes, structs,
interfaces, enums or delegates from Python. To create an instance of
a managed class, you use the standard instantiation syntax, passing
a set of arguments that match one of its public constructors:
</p>
<pre>
from CLR.System.Drawing import Point
p = Point(5, 5)
</pre>
<p>
You can also subclass managed classes in Python. See the
<code>helloform.py</code> file in the <code>/demo</code> directory of the
distribution for a simple Windows Forms example that demonstrates
subclassing a managed class.
</p>
<a name="fields"></a>
<h2>Fields And Properties</h2>
<p>
You can get and set fields and properties of CLR objects just as if
they were regular attributes:
</p>
<pre>
from CLR.System import Environment
name = Environment.MachineName
Environment.ExitCode = 1
</pre>
<a name="indexers"></a>
<h2>Using Indexers</h2>
<p>
If a managed object implements one or more indexers, you can call
the indexer using standard Python indexing syntax:
</p>
<pre>
from CLR.System.Collections import Hashtable
table = Hashtable()
table["key 1"] = "value 1"
</pre>
<p>
Overloaded indexers are supported, using the same notation one
would use in C#:
</p>
<pre>
items[0, 2]
items[0, 2, 3]
</pre>
<a name="methods"></a>
<h2>Using Methods</h2>
<p>
Methods of CLR objects behave generally like normal Python methods.
Static methods may be called either through the class or through an
instance of the class. All public and protected methods of CLR objects
are accessible to Python:
</p>
<pre>
from CLR.System import Environment
drives = Environment.GetLogicalDrives()
</pre>
<p>
It is also possible to call managed methods <code>unbound</code> (passing the
instance as the first argument) just as with Python methods. This is
most often used to explicitly call methods of a base class.
</p>
<p>
<em>Note that there is one caveat related to calling unbound methods: it
is possible for a managed class to declare a static method and an
instance method with the same name. Since it is not possible for the
runtime to know the intent when such a method is called unbound, the
static method will always be called.</em>
</p>
<p>
The docstring of CLR a method (__doc__) can be used to view the
signature of the method, including overloads if the CLR method is
overloaded. You can also use the Python <code>help</code> method to inspect
a managed class:
</p>
<pre>
from CLR.System import Environment
print Environment.GetFolderPath.__doc__
help(Environment)
</pre>
<a name="delegates"></a>
<h2>Delegates And Events</h2>
<p>
Delegates defined in managed code can be implemented in Python. A
delegate type can be instantiated and passed a callable Python object
to get a delegate instance. The resulting delegate instance is a true
managed delegate that will invoke the given Python callable when it
is called:
</p>
<pre>
def my_handler(source, args):
print 'my_handler called!'
# instantiate a delegate
d = AssemblyLoadEventHandler(my_handler)
# use it as an event handler
AppDomain.CurrentDomain.AssemblyLoad += d
</pre>
<p>
Multicast delegates can be implemented by adding more callable objects
to a delegate instance:
</p>
<pre>
d += self.method1
d += self.method2
d()
</pre>
<p>
Events are treated as first-class objects in Python, and behave in
many ways like methods. Python callbacks can be registered with event
attributes, and an event can be called to fire the event.
</p>
<p>
Note that events support a convenience spelling similar to that used
in C#. You do not need to pass an explicitly instantiated delegate
instance to an event (though you can if you want). Events support the
<code>+=</code> and <code>-=</code> operators in a way very similar to
the C# idiom:
</p>
<pre>
def handler(source, args):
print 'my_handler called!'
# register event handler
object.SomeEvent += handler
# unregister event handler
object.SomeEvent -= handler
# fire the event
result = object.SomeEvent(...)
</pre>
<a name="exceptions"></a>
<h2>Exception Handling</h2>
<p>
You can raise and catch managed exceptions just the same as you would
pure-Python exceptions:
<pre>
from CLR.System import NullReferenceException
try:
raise NullReferenceException("aiieee!")
except NullReferenceException, e:
print e.Message
print e.Source
</pre>
</p>
<a name="arrays"></a>
<h2>Using Arrays</h2>
<p>
Managed arrays support the standard Python sequence protocols:
</p>
<pre>
items = SomeObject.GetArray()
# Get first item
v = items[0]
items[0] = v
# Get last item
v = items[-1]
items[-1] = v
# Get length
l = len(items)
# Containment test
test = v in items
</pre>
<p>
Multidimensional arrays support indexing using the same notation one
would use in C#:
</p>
<pre>
items[0, 2]
items[0, 2, 3]
</pre>
<a name="collections"></a>
<h2>Using Collections</h2>
<p>
Managed arrays and managed objects that implement the IEnumerable
interface can be iterated over using the standard iteration Python
idioms:
</p>
<pre>
domain = System.AppDomain.CurrentDomain
for item in domain.GetAssemblies():
name = item.GetName()
</pre>
<a name="com"></a>
<h2>Using COM Components</h2>
<p>
Using Microsoft-provided tools such as <strong>aximp.exe</strong> and
<strong>tlbimp.exe</strong>, it is possible to generate managed wrappers
for COM libraries. After generating such a wrapper, you can use the
libraries from Python just like any other managed code.
</p>
<p>
Note: currently you need to put the generated wrappers in the GAC,
in the PythonNet assembly directory or on the PYTHONPATH in order
to load them.
</p>
<a name="types"></a>
<h2>Type Conversion</h2>
<p>
Type conversion under Python for .NET is fairly straightforward - most
elemental Python types (string, int, long, etc.) convert automatically
to compatible managed equivalents (String, Int32, etc.) and vice-versa.
Note that all strings returned from the CLR are returned as unicode.
</p>
<p>
Types that do not have a logical equivalent in Python are exposed as
instances of managed classes or structs (System.Decimal is an example).
</p>
<p>
The .NET architecture makes a distinction between <code>value types</code>
and <code>reference types</code>. Reference types are allocated on the heap,
and value types are allocated either on the stack or in-line within an
object.
</p>
<p>
A process called <code>boxing</code> is used in .NET to allow code to treat
a value type as if it were a reference type. Boxing causes a separate
copy of the value type object to be created on the heap, which then
has reference type semantics.
</p>
<p>
Understanding boxing and the distinction between value types and
reference types can be important when using Python for .NET because
the Python language has no value type semantics or syntax - in
Python &quot;everything is a reference&quot;.
</p>
<p>
Here is a simple example that demonstrates an issue. If you are an
experienced C# programmer, you might write the following code:
</p>
<pre>
items = CLR.System.Array.CreateInstance(Point, 3)
for i in range(3):
items[i] = Point(0, 0)
items[0].X = 1 # won't work!!
</pre>
<p>
While the spelling of <code>items[0].X = 1</code> is the same in C# and
Python, there is an important and subtle semantic difference. In C# (and other
compiled-to-IL languages), the compiler knows that Point is a value
type and can do the Right Thing here, changing the value in place.
</p>
<p>
In Python however, "everything's a reference", and there is really no
spelling or semantic to allow it to do the right thing dynamically. The
specific reason that <code>items[0]</code> itself doesn't change is that
when you say <code>items[0]</code>, that getitem operation creates a Python
object that holds a reference to the object at <code>items[0]</code> via a
GCHandle. That causes a ValueType (like Point) to be boxed, so the following
setattr (<code>.X = 1</code>) <em>changes the state of the boxed value, not
the original unboxed value</em>.
</p>
<p>
The rule in Python is essentially: &quot;the result of any attribute or
item access is a boxed value&quot;, and that can be important in how you
approach your code.
</p>
<p>
Because there are no value type semantics or syntax in Python, you
may need to modify your approach. To revisit the previous example,
we can ensure that the changes we want to make to an array item
aren't "lost" by resetting an array member after making changes
to it:
</p>
<pre>
items = CLR.System.Array.CreateInstance(Point, 3)
for i in range(3):
items[i] = Point(0, 0)
# This _will_ work. We get 'item' as a boxed copy of the Point
# object actually stored in the array. After making our changes
# we re-set the array item to update the bits in the array.
item = items[0]
item.X = 1
items[0] = item
</pre>
<p>
This is not unlike some of the cases you can find in C# where you have
to know about boxing behavior to avoid similar kinds of <code>lost
update</code> problems (generally because an implicit boxing happened that
was not taken into account in the code).
</p>
<p>
This is the same thing, just the manifestation is a little different
in Python. See the .NET documentation for more details on boxing and
the differences between value types and reference types.
</p>
<a name="assemblies"></a>
<h2>Using Assemblies</h2>
<p>
The Python for .NET runtime uses Assembly.LoadWithPartialName to do
name-based imports, which will usually load the most recent version of
an assembly that it can find.
</p>
<p>
The CLR's ability to load different versions of assemblies side-by-side
is one of the (relatively few) places where the matching of meta-models
between Python and the CLR breaks down (though it is unclear how often
this happens in practice).
</p>
<p>
Because Python import is name-based and unaware of any concept of
versioned modules, the design goal has been for name-based implicit assembly
loading to do something consistent and reasonable (i.e. load most
recent available based on the name).
</p>
<p>
It <em>is</em> possible to load a specific version of an assembly if you
need to using code similar to the following:
</p>
<pre>
from CLR.System.Reflection import Assembly, AssemblyName
name = AssemblyName(...) # set required version, etc.
assembly = Assembly.Load(name)
# now import namespaces from the loaded assembly
</pre>
<p>
Things get a lot more complicated if you need to load more than one
version of a particular assembly (or more likely, you have a dependency
on some library the does so). In this case, the names you access via
the CLR modules will always come from the first version of the
assembly loaded (which will always win in the internals of the Python
for .NET runtime).
</p>
<p>
You <em>can</em> still use particular versions of objects in this case - you
just have to do more work to get the right versions of objects:
</p>
<pre>
from CLR.System.Reflection import Assembly, AssemblyName
from System import Activator
name = AssemblyName(...) # get the right version
assembly = Assembly.Load(name)
type = assembly.GetType("QualifiedNameOf.TheTypeINeed")
obj = Activator.CreateInstance(type)
</pre>
</p>
<a name="embedding"></a>
<h2>Embedding Python</h2>
<p>
<strong>Note:</strong> because Python code running under Python for .NET
is inherently unverifiable, it runs totally under the radar of the security
infrastructure of the CLR so you should restrict use of the Python assembly
to trusted code.
</p>
<p>
The Python runtime assembly defines a number of public classes that
provide a subset of the functionality provided by the Python C API.
</p>
<p>
These classes include PyObject, PyList, PyDict, etc. The source and
the unit tests are currently the only API documentation.. The rhythym
is very similar to using Python C++ wrapper solutions such as CXX.
</p>
<p>
At a very high level, to embed Python in your application you
will need to:
</p>
<ul>
<li>Reference Python.Runtime.dll in your build environment</li>
<li>Call PythonEngine.Intialize() to initialize Python</li>
<li>Call PythonEngine.ImportModule(name) to import a module</li>
</ul>
<p>
The module you import can either start working with your managed app
environment at the time its imported, or you can explicitly lookup and
call objects in a module you import.
</p>
<p>
For general-purpose information on embedding Python in applications, use
www.python.org or Google to find (C) examples. Because Python for .NET is
so closely integrated with the managed environment, you will generally be
better off importing a module and deferring to Python code as early as
possible rather than writing a lot of managed embedding code.
</p>
<p>
<strong>Important Note for embedders:</strong> Python is not free-threaded
and uses a global interpreter lock to allow multi-threaded applications to
interact safely with the Python interpreter. Much more information about
this is available in the Python C API documentation on the www.python.org
Website.
</p>
<p>
When embedding Python in a managed application, you have to manage the GIL
in just the same way you would when embedding Python in a C or C++
application.
</p>
<p>
Before interacting with any of the objects or APIs provided by the
Python.Runtime namespace, calling code must have acquired the Python
global interpreter lock by calling the <code>PythonEngine.AcquireLock</code>
method. The only exception to this rule is the
<code>PythonEngine.Initialize</code> method, which may be called at startup
without having acquired the GIL.
</p>
<p>
When finished using Python APIs, managed code must call a corresponding
<code>PythonEngine.ReleaseLock</code> to release the GIL and allow other
threads to use Python.
</p>
<p>
The AcquireLock and ReleaseLock methods are thin wrappers over the
unmanaged <code>PyGILState_Ensure</code> and <code>PyGILState_Release</code>
functions from the Python API, and the documentation for those APIs applies
to the managed versions.
</p>
<a name="license" />
<h2>License</h2>
<p>
Python for .NET is released under the open source Zope Public License (ZPL).
A copy of the ZPL is included in the distribution, or you can find a copy
of the
<a href="http://pythonnet.sourceforge.net/license.txt">
ZPL online
</a>. Some distributions of this package include a copy of the C Python
dlls and standard library, which are covered by the
<a href="http://www.python.org/license.html">
Python license
</a>.
</p>
</td>
</tr>
</table>
</body>
</html>

Просмотреть файл

@ -0,0 +1,63 @@
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
#
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
import CLR.System.Windows.Forms as WinForms
from CLR.System.Drawing import Size, Point
class HelloApp(WinForms.Form):
"""A simple hello world app that demonstrates the essentials of
winforms programming and event-based programming in Python."""
def __init__(self):
self.Text = "Hello World From Python"
self.AutoScaleBaseSize = Size(5, 13)
self.ClientSize = Size(392, 117);
h = WinForms.SystemInformation.CaptionHeight
self.MinimumSize = Size(392, (117 + h))
# Create the button
self.button = WinForms.Button()
self.button.Location = Point(256, 64)
self.button.Size = Size(120, 40)
self.button.TabIndex = 2
self.button.Text = "Click Me!"
# Register the event handler
self.button.Click += self.button_Click
# Create the text box
self.textbox = WinForms.TextBox()
self.textbox.Text = "Hello World"
self.textbox.TabIndex = 1
self.textbox.Size = Size(360, 20)
self.textbox.Location = Point(16, 24)
# Add the controls to the form
self.AcceptButton = self.button
self.Controls.Add(self.button);
self.Controls.Add(self.textbox);
def button_Click(self, sender, args):
"""Button click event handler"""
WinForms.MessageBox.Show("Please do not press this button again.")
def run(self):
WinForms.Application.Run(self)
def main():
HelloApp().run()
if __name__ == '__main__':
main()

Просмотреть файл

@ -0,0 +1,99 @@
# Copyright (c) 2003 Zope Corporation and Contributors.
#
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
import CLR.System.Windows.Forms as WinForms
from CLR.System.Drawing import Color, Size, Point
from CLR import System
class Splitter(WinForms.Form):
"""A WinForms example transcribed to Python from the MSDN article:
'Creating a Multipane User Interface with Windows Forms'."""
def __init__(self):
# Create an instance of each control being used.
self.components = System.ComponentModel.Container()
self.treeView1 = WinForms.TreeView()
self.listView1 = WinForms.ListView()
self.richTextBox1 = WinForms.RichTextBox()
self.splitter1 = WinForms.Splitter()
self.splitter2 = WinForms.Splitter()
self.panel1 = WinForms.Panel()
# Set properties of TreeView control.
self.treeView1.Dock = WinForms.DockStyle.Left
self.treeView1.Width = self.ClientSize.Width / 3
self.treeView1.TabIndex = 0
self.treeView1.Nodes.Add("TreeView")
# Set properties of ListView control.
self.listView1.Dock = WinForms.DockStyle.Top
self.listView1.Height = self.ClientSize.Height * 2 / 3
self.listView1.TabIndex = 0
self.listView1.Items.Add("ListView")
# Set properties of RichTextBox control.
self.richTextBox1.Dock = WinForms.DockStyle.Fill
self.richTextBox1.TabIndex = 2
self.richTextBox1.Text = "richTextBox1"
# Set properties of Panel's Splitter control.
self.splitter2.Dock = WinForms.DockStyle.Top
# Width is irrelevant if splitter is docked to Top.
self.splitter2.Height = 3
# Use a different color to distinguish the two splitters.
self.splitter2.BackColor = Color.Blue
self.splitter2.TabIndex = 1
# Set TabStop to false for ease of use when negotiating UI.
self.splitter2.TabStop = 0
# Set properties of Form's Splitter control.
self.splitter1.Location = System.Drawing.Point(121, 0)
self.splitter1.Size = System.Drawing.Size(3, 273)
self.splitter1.BackColor = Color.Red
self.splitter1.TabIndex = 1
# Set TabStop to false for ease of use when negotiating UI.
self.splitter1.TabStop = 0
# Add the appropriate controls to the Panel.
for item in (self.richTextBox1, self.splitter2, self.listView1):
self.panel1.Controls.Add(item)
# Set properties of Panel control.
self.panel1.Dock = WinForms.DockStyle.Fill
self.panel1.TabIndex = 2
# Add the rest of the controls to the form.
for item in (self.panel1, self.splitter1, self.treeView1):
self.Controls.Add(item)
self.Text = "Intricate UI Example"
def Dispose(self):
self.components.Dispose()
WinForms.Form.Dispose(self)
def main():
app = Splitter()
WinForms.Application.Run(app)
app.Dispose()
if __name__ == '__main__':
main()

Просмотреть файл

@ -0,0 +1,432 @@
# Copyright (c) 2003 Zope Corporation and Contributors.
#
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
import CLR.System.Windows.Forms as WinForms
from CLR.System.Drawing import Color, Size, Point
from CLR.System.Text import Encoding
from CLR.System.IO import File
from CLR import System
class Wordpad(WinForms.Form):
"""A simple example winforms application similar to wordpad."""
def __init__(self):
self.filename = ''
self.word_wrap = 1
self.doctype = 1
self.InitializeComponent()
self.NewDocument()
def InitializeComponent(self):
"""Initialize form components."""
self.components = System.ComponentModel.Container()
self.openFileDialog = WinForms.OpenFileDialog()
self.saveFileDialog = WinForms.SaveFileDialog()
self.mainMenu = WinForms.MainMenu()
self.fileMenu = WinForms.MenuItem()
self.menuFileNew = WinForms.MenuItem()
self.menuFileOpen = WinForms.MenuItem()
self.menuFileSave = WinForms.MenuItem()
self.menuFileSaveAs = WinForms.MenuItem()
self.menuFileSep_1 = WinForms.MenuItem()
self.menuFileExit = WinForms.MenuItem()
self.editMenu = WinForms.MenuItem()
self.menuEditUndo = WinForms.MenuItem()
self.menuEditRedo = WinForms.MenuItem()
self.menuEditSep_1 = WinForms.MenuItem()
self.menuEditCut = WinForms.MenuItem()
self.menuEditCopy = WinForms.MenuItem()
self.menuEditPaste = WinForms.MenuItem()
self.menuEditSep_2 = WinForms.MenuItem()
self.menuEditSelectAll = WinForms.MenuItem()
self.formatMenu = WinForms.MenuItem()
self.menuFormatFont = WinForms.MenuItem()
self.menuFormatWordWrap = WinForms.MenuItem()
self.aboutMenu = WinForms.MenuItem()
self.menuHelpAbout = WinForms.MenuItem()
self.richTextBox = WinForms.RichTextBox()
self.statusBarPanel1 = WinForms.StatusBarPanel()
self.statusBar = WinForms.StatusBar()
self.fontDialog = WinForms.FontDialog()
self.statusBarPanel1.BeginInit()
# ===================================================================
# File Menu
# ===================================================================
self.menuFileNew.Text = "&New"
self.menuFileNew.Shortcut = WinForms.Shortcut.CtrlN
self.menuFileNew.ShowShortcut = False
self.menuFileNew.Index = 0
self.menuFileNew.Click += self.OnClickFileNew
self.menuFileOpen.Text = "&Open"
self.menuFileOpen.Shortcut = WinForms.Shortcut.CtrlO
self.menuFileOpen.ShowShortcut = False
self.menuFileOpen.Index = 1
self.menuFileOpen.Click += self.OnClickFileOpen
self.menuFileSave.Text = "&Save"
self.menuFileSave.Shortcut = WinForms.Shortcut.CtrlS
self.menuFileSave.ShowShortcut = False
self.menuFileSave.Index = 2
self.menuFileSave.Click += self.OnClickFileSave
self.menuFileSaveAs.Text = "Save &As"
self.menuFileSaveAs.Index = 3
self.menuFileSaveAs.Click += self.OnClickFileSaveAs
self.menuFileSep_1.Text = "-"
self.menuFileSep_1.Index = 4
self.menuFileExit.Text = "E&xit"
self.menuFileExit.Shortcut = WinForms.Shortcut.AltF4
self.menuFileExit.ShowShortcut = False
self.menuFileExit.Index = 5
self.menuFileExit.Click += self.OnClickFileExit
self.fileMenu.Text = "&File"
self.fileMenu.Index = 0
items = (self.menuFileNew, self.menuFileOpen,
self.menuFileSave, self.menuFileSaveAs,
self.menuFileSep_1, self.menuFileExit)
self.fileMenu.MenuItems.AddRange(items)
# ===================================================================
# Edit menu
# ===================================================================
self.menuEditUndo.Text = "&Undo"
self.menuEditUndo.Shortcut = WinForms.Shortcut.CtrlZ
self.menuEditUndo.Index = 0
self.menuEditUndo.Click += self.OnClickEditUndo
self.menuEditRedo.Text = "&Redo"
self.menuEditRedo.Shortcut = WinForms.Shortcut.CtrlY
self.menuEditRedo.Index = 1
self.menuEditRedo.Click += self.OnClickEditRedo
self.menuEditSep_1.Text = "-"
self.menuEditSep_1.Index = 2
self.menuEditCut.Text = "Cut"
self.menuEditCut.Shortcut = WinForms.Shortcut.CtrlX
self.menuEditCut.Index = 3
self.menuEditCut.Click += self.OnClickEditCut
self.menuEditCopy.Text = "Copy"
self.menuEditCopy.Shortcut = WinForms.Shortcut.CtrlC
self.menuEditCopy.Index = 4
self.menuEditCopy.Click += self.OnClickEditCopy
self.menuEditPaste.Text = "Paste"
self.menuEditPaste.Shortcut = WinForms.Shortcut.CtrlV
self.menuEditPaste.Index = 5
self.menuEditPaste.Click += self.OnClickEditPaste
self.menuEditSelectAll.Text = "Select All"
self.menuEditSelectAll.Shortcut = WinForms.Shortcut.CtrlA
self.menuEditSelectAll.Index = 7
self.menuEditSelectAll.Click += self.OnClickEditSelectAll
self.menuEditSep_2.Text = "-"
self.menuEditSep_2.Index = 6
self.editMenu.Text = "&Edit"
self.editMenu.Index = 1
items = (self.menuEditUndo, self.menuEditRedo,
self.menuEditSep_1, self.menuEditCut,
self.menuEditCopy, self.menuEditPaste,
self.menuEditSep_2, self.menuEditSelectAll)
self.editMenu.MenuItems.AddRange(items)
# ===================================================================
# Format Menu
# ===================================================================
self.menuFormatWordWrap.Text = "Word Wrap"
self.menuFormatWordWrap.Checked = self.word_wrap
self.menuFormatWordWrap.Index = 1
self.menuFormatWordWrap.Click += self.OnClickFormatWordWrap
self.menuFormatFont.Text = "Fo&nt"
self.menuFormatFont.Index = 0
self.menuFormatFont.Click += self.OnClickFormatFont
self.formatMenu.Text = "F&ormat"
self.formatMenu.Index = 2
items = (self.menuFormatWordWrap, self.menuFormatFont)
self.formatMenu.MenuItems.AddRange(items)
# ===================================================================
# About menu
# ===================================================================
self.menuHelpAbout.Text = "&About"
self.menuHelpAbout.Index = 0
self.menuHelpAbout.Click += self.OnClickHelpAbout
self.aboutMenu.Text = "&Help"
self.aboutMenu.Index = 3
self.aboutMenu.MenuItems.Add(self.menuHelpAbout)
self.statusBarPanel1.Dock = WinForms.DockStyle.Fill
self.statusBarPanel1.Text = "Ready"
self.statusBarPanel1.Width = 755
self.richTextBox.Dock = WinForms.DockStyle.Fill
self.richTextBox.Size = System.Drawing.Size(795, 485)
self.richTextBox.TabIndex = 0
self.richTextBox.AutoSize = 1
self.richTextBox.ScrollBars = WinForms.RichTextBoxScrollBars.ForcedBoth
self.richTextBox.Font = System.Drawing.Font("Tahoma", 10)
self.richTextBox.AcceptsTab = 1
self.richTextBox.Location = System.Drawing.Point(0, 0)
self.statusBar.BackColor = System.Drawing.SystemColors.Control
self.statusBar.Location = System.Drawing.Point(0, 518)
self.statusBar.Size = System.Drawing.Size(775, 19)
self.statusBar.TabIndex = 1
self.statusBar.ShowPanels = True
self.statusBar.Panels.Add(self.statusBarPanel1)
items = (self.fileMenu, self.editMenu, self.formatMenu, self.aboutMenu)
self.mainMenu.MenuItems.AddRange(items)
self.openFileDialog.Filter = "Text documents|*.txt|RTF document|*.rtf"
self.openFileDialog.Title = "Open document"
self.saveFileDialog.Filter = "Text Documents|*.txt|" \
"Rich Text Format|*.rtf"
self.saveFileDialog.Title = "Save document"
self.saveFileDialog.FileName = "Untitled"
self.AutoScaleBaseSize = System.Drawing.Size(5, 13)
self.ClientSize = System.Drawing.Size(775, 537)
self.Menu = self.mainMenu
self.Text = "Python Wordpad"
self.Controls.Add(self.statusBar)
self.Controls.Add(self.richTextBox)
self.statusBarPanel1.EndInit()
def Dispose(self):
self.components.Dispose()
WinForms.Form.Dispose(self)
def OnClickFileNew(self, sender, args):
self.SaveChangesDialog()
self.NewDocument()
def OnClickFileOpen(self, sender, args):
self.SaveChangesDialog()
self.OpenDocument()
def OnClickFileSave(self, sender, args):
self.SaveDocument()
def OnClickFileSaveAs(self, sender, args):
self.filename = ''
self.SaveDocument()
def OnClickFileExit(self, sender, args):
self.SaveChangesDialog()
self.Close()
def OnClickEditUndo(self, sender, args):
self.richTextBox.Undo()
def OnClickEditRedo(self, sender, args):
self.richTextBox.Redo()
def OnClickEditCut(self, sender, args):
self.richTextBox.Cut()
def OnClickEditCopy(self, sender, args):
self.richTextBox.Copy()
def OnClickEditPaste(self, sender, args):
self.richTextBox.Paste()
def OnClickEditSelectAll(self, sender, args):
self.richTextBox.SelectAll()
def OnClickFormatWordWrap(self, sender, args):
value = not self.word_wrap
self.richTextBox.WordWrap = value
self.menuFormatWordWrap.Checked = value
self.word_wrap = value
def OnClickFormatFont(self, sender, args):
if self.fontDialog.ShowDialog() == WinForms.DialogResult.OK:
self.richTextBox.SelectionFont = self.fontDialog.Font
def OnClickHelpAbout(self, sender, args):
AboutForm().ShowDialog(self)
def NewDocument(self):
self.doctype = 1
self.richTextBox.Rtf = ''
self.richTextBox.Text = ''
self.Text = 'Python Wordpad - (New Document)'
self.filename = ''
def OpenDocument(self):
if self.openFileDialog.ShowDialog() != WinForms.DialogResult.OK:
return
filename = self.openFileDialog.FileName
stream = File.OpenRead(filename)
buff = System.Array.CreateInstance(System.Byte, 1024)
data = []
read = -1
while (read != 0):
buff.Initialize()
read = stream.Read(buff, 0, 1024)
temp = Encoding.ASCII.GetString(buff, 0, 1024)
data.append(temp)
data = ''.join(data)
stream.Close()
filename = self.filename = filename.lower()
if filename.endswith('.rtf'):
self.richTextBox.Rtf = data
self.doctype = 2
else:
self.richTextBox.Text = data
self.doctype = 1
self.Text = 'Python Wordpad - %s' % filename
self.richTextBox.Select(0, 0)
def SaveDocument(self):
filename = self.filename
if not filename:
if self.saveFileDialog.ShowDialog() != WinForms.DialogResult.OK:
return
filename = self.saveFileDialog.FileName
filename = self.filename = filename.lower()
self.Text = 'Python Wordpad - %s' % filename
self.richTextBox.Select(0, 0)
stream = File.OpenWrite(filename)
if filename.endswith('.rtf'):
data = self.richTextBox.Rtf
else:
data = self.richTextBox.Text
data = System.Text.Encoding.ASCII.GetBytes(System.String(data))
stream.Write(data, 0, data.Length)
stream.Close()
def SaveChangesDialog(self):
if self.richTextBox.Modified:
if WinForms.MessageBox.Show(
"Save changes?", "Word Pad",
WinForms.MessageBoxButtons.OK |
WinForms.MessageBoxButtons.YesNo
) == WinForms.DialogResult.Yes:
self.SaveDocument()
return 1
return 0
class AboutForm(WinForms.Form):
def __init__(self):
self.InitializeComponent()
def InitializeComponent(self):
"""Initialize form components."""
self.Text = "Python Wordpad"
self.components = System.ComponentModel.Container()
self.btnClose = WinForms.Button()
self.label1 = WinForms.Label()
self.SuspendLayout()
self.btnClose.Location = System.Drawing.Point(360, 181)
self.btnClose.Name = "bnClose"
self.btnClose.TabIndex = 1
self.btnClose.Text = "&Close"
self.btnClose.Click += self.OnClickClose
self.label1.Location = System.Drawing.Point(20, 20)
self.label1.Name = "label1"
self.label1.Size = System.Drawing.Size(296, 140)
self.label1.TabIndex = 2
self.label1.Text = "Python Wordpad - an example winforms " \
"application using Python for .NET"
self.AutoScaleBaseSize = System.Drawing.Size(5, 13)
self.ClientSize = System.Drawing.Size(300, 150)
self.Controls.AddRange((self.label1, self.btnClose))
self.FormBorderStyle = WinForms.FormBorderStyle.FixedDialog
self.MaximizeBox = 0
self.MinimizeBox = 0
self.Name = "AboutForm"
self.ShowInTaskbar = False
self.StartPosition = WinForms.FormStartPosition.CenterScreen
self.Text = "About"
self.ResumeLayout(0)
def OnClickClose(self, sender, args):
self.Close()
def main():
app = Wordpad()
WinForms.Application.Run(app)
app.Dispose()
if __name__ == '__main__':
main()

Просмотреть файл

@ -0,0 +1,297 @@
PythonNet Changes
-----------------
PythonNet 1.0 release candidate 2
---------------------------------------------------------------------------
- Changed some uses of Finalize as a static method name that confused the
Mono compiler and people reading the code. Note that this may be a
breaking change if anyone was calling PythonEngine.Finalize(). If so,
you should now use PythonEngine.Shutdown().
- Tweaked assembly lookup to ensure that assemblies can be found in the
current working directory, even after changing directories using things
like os.chdir() from Python.
- Fixed some incorrect finalizers (thanks to Greg Chapman for the report)
that may have caused some threading oddities.
- Tweaked support for out and ref parameters. If a method has a return
type of void and a single ref or out parameter, that parameter will be
returned as the result of the method. This matches the current behavior
of IronPython and makes it more likely that code can be moved between
Python for .NET and IP in the future.
- Refactored part of the assembly manager to remove a potential case of
thread-deadlock in multi-threaded applications.
- Added a __str__ method to managed exceptions that returns the Message
attribute of the exception and the StackTrace (if available).
PythonNet 1.0 release candidate 1
---------------------------------------------------------------------------
- Implemented a workaround for the fact that exceptions cannot be new-style
classes in the CPython interpreter. Managed exceptions can now be raised
and caught naturally from Python (hooray!)
- Implemented support for invoking methods with out and ref parameters.
Because there is no real equivalent to these in Python, methods that
have out or ref parameters will return a tuple. The tuple will contain
the result of the method as its first item, followed by out parameter
values in the order of their declaration in the method signature.
- Fixed a refcount problem that caused a crash when CLR was imported in
an existing installed Python interpreter.
- Added an automatic conversion from Python strings to byte[]. This makes
it easier to pass byte[] data to managed methods (or set properties,
etc.) as a Python string without having to write explicit conversion
code. Also works for sbyte arrays. Note that byte and sbyte arrays
returned from managed methods or obtained from properties or fields
do *not* get converted to Python strings - they remain instances of
Byte[] or SByte[].
- Added conversion of generic Python sequences to object arrays when
appropriate (thanks to Mackenzie Straight for the patch).
- Added a bit of cautionary documentation for embedders, focused on
correct handling of the Python global interpreter lock from managed
code for code that calls into Python.
- PyObject.FromManagedObject now correctly returns the Python None object
if the input is a null reference. Also added a new AsManagedObject
method to PyObject, making it easier to convert a Python-wrapped managed
object to the real managed object.
- Created a simple installer for windows platforms.
PythonNet 1.0 beta 5
---------------------------------------------------------------------------
- Refactored and fixed threading and global interpreter lock handling,
which was badly broken before. Also added a number of threading and
GIL-handling tests.
- Related to the GIL fixes, added a note to embedders in the README
about using the AcquireLock and ReleaseLock methods of the PythonEngine
class to manage the GIL.
- Fixed a problem in Single <--> float conversion for cultures that use
different decimal symbols than Python.
- Added a new ReloadModule method to the PythonEngine class that hooks
Python module reloading (PyImport_ReloadModule).
- Added a new StringAsModule method to the PythonEngine class that can
create a module from a managed string of code.
- Added a default __str__ implementation for Python wrappers of managed
objects that calls the ToString method of the managed object.
PythonNet 1.0 beta 4
---------------------------------------------------------------------------
- Fixed a problem that made it impossible to override "special" methods
like __getitem__ in subclasses of managed classes. Now the tests all
pass, and there is much rejoicing.
- Managed classes reflected to Python now have an __doc__ attribute that
contains a listing of the class constructor signatures.
- Fixed a problem that prevented passing null (None) for array arguments.
- Added a number of new argument conversion tests. Thanks to Laurent
Caumont for giving Python for .NET a good workout with managed DirectX.
- Updated the bundled C Python runtime and libraries to Python 2.4. The
current release is known to also run with Python 2.3. It is known
*not* to work with older versions due to changes in CPython type
object structure.
- Mostly fixed the differences in the way that import works depending
on whether you are using the bundled interpreter or an existing Python
interpreter. The hack I used makes import work uniformly for imports
done in Python modules. Unfortunately, there is still a limitation
when using the interpreter interactively: you need to do 'import CLR'
first before importing any sub-names when running with an existing
Python interpreter.
The reason is that the first import of 'CLR' installs the CLR import
hook, but for an existing interpreter the standard importer is still
in control for the duration of that first import, so sub-names won't
be found until the next import, which will use the now-installed hook.
- Added support to directly iterate over objects that support IEnumerator
(as well as IEnumerable). Thanks to Greg Chapman for prodding me ;)
- Added a section to the README dealing with rebuilding Python for .NET
against other CPython versions.
- Fixed a problem with accessing properties when only the interface for
an object is known. For example, ICollection(ob).Count failed because
Python for .NET mistakenly decided that Count was abstract.
- Fixed some problems with how COM-based objects are exposed and how
members of inherited interfaces are exposed. Thanks to Bruce Dodson
for patches on this.
- Changed the Runtime class to use a const string to target the
appropriate CPython dll in DllImport attributes. Now you only
have to change one line to target a new Python version.
PythonNet 1.0 beta 3
---------------------------------------------------------------------------
- A dumb bug that could cause a crash on startup on some platforms was
fixed. Decided to update the beta for this, as a number of people
were running into the problem.
PythonNet 1.0 beta 2
---------------------------------------------------------------------------
- Exceptions raised as a result of getting or setting properties were
not very helpful (target invokation exception). This has been changed
to pass through the inner exception the way that methods do, which is
much more likely to be the real exception that caused the problem.
- Events were refactored as the implementation was based on some bad
assumptions. As a result, subscription and unsubscription now works
correctly. A change from beta 1 is that event objects are no longer
directly callable - this was not appropriate, since the internal
implementation of an event is private and cant work reliably. Instead,
you should the appropriate OnSomeEvent method published by a class
to fire an event.
- The distribution did not include the key file, making it a pain for
people to build from source. Added the key file to the distribution
buildout for beta 2.
- Assemblies can now be found and loaded if they are on the PYTHONPATH.
Previously only the appbase and the GAC were checked. The system now
checks PYTHONPATH first, then the appbase, then the GAC.
- Fixed a bug in constructor invokation during object instantiation.
PythonNet 1.0 beta 1
---------------------------------------------------------------------------
- Added the baseline of the managed embedding API. Some of the details
are still subject to change based on some real-world use and feedback.
The embedding API is based on the PyObject class, along with a number
of specific PyDict, PyList, (etc.) classes that expose the respective
interfaces of the built-in Python types. The basic structure and usage
is intended be familar to anyone who has used Python / C++ wrapper
libraries like CXX or Boost.
- Started integrating NUnit2 to support unit tests for the embedding
layer - still need to add the embedding tests (many already exist,
but were written for an older version of NUnit).
- Added Python iteration protocol support for arrays and managed objects
that implement IEnumerable. This means that you can now use the Python
idiom 'for item in object:' on any array or IEnumerable object.
- Added automatic conversion from Python sequence types to managed array
types. This means, for example, that you can now call a managed method
like AddRange that expects an array with any Python object that supports
the Python sequence protocol, provided the items of the sequence are
convertible to the item type of the managed array.
- Added new demo scripts, mostly more substantial winforms examples.
- Finished the unit tests for event support, and fixed lots of problems
with events and delegates as a result. This is one of the trickier
parts of the integration layer, and there is good coverage of these
in the unit tests now.
- Did a fair amount of profiling with an eval version of ANTS (which is
quite nice, BTW) and made a few changes as a result.
- Type management was refactored, fixing the issue that caused segfaults
when GC was enabled. Unit tests, stress tests and demo apps now all run
nicely with Python GC enabled. There are one or two things left to fix,
but the fixes should not have any user impact.
- Changed to base PythonNet on Python 2.3.2. This is considered the most
stable release, and a good 25 - 30% faster as well.
- Added a new 'CLR.dll' that acts as an extension module that allows an
existing unmodified Python 2.3 installation to simply 'import CLR' to
bootstrap the managed integration layer.
- A bug was causing managed methods to only expose overloads declared in
a particular class, hiding inherited overloads of the same name. Fixed
the bug and added some unit tests.
- Added a virtual '__doc__' attribute to managed methods that contains
the signature of the method. This also means that the Python 'help'
function now provides signature info when used on a managed class.
- Calling managed methods and events 'unbound' (passing the instance as
the first argument) now works. There is a caveat for methods - if a
class declares both static and instance methods with the same name,
it is not possible to call that instance method unbound (the static
method will always be called).
- Overload selection for overloaded methods is now much better and uses
a method resolution algorithm similar to that used by Jython.
- Changed the managed python.exe wrapper to run as an STA thread, which
seems to be more compatible with winforms apps. This needs a better
solution long-term. One possibility would be a command line switch
so that -sta or -mta could control the python.exe apartment state.
- Added support for the Python boolean type (True, False). Bool values
now appear as True or False to Python.
PythonNet Preview 2
---------------------------------------------------------------------------
- Added a Mono makefile. Thanks to Camilo Uribe for help in testing and
working out problems on Mono. Note that it not currently possible to
build PythonNet using mono, due to the use of some IL attributes that
the mono assembler / disassembler doesn't support yet.
- Preliminary tests show that PythonNet *does* actually run under mono,
though the test suite bombs out before the end with an "out of memory"
error from the mono runtime. It's just a guess at this point, but I
suspect there may be a limited pool for allocating certain reflection
structures, and Python uses the reflection infrastructure quite heavily.
- Removed decoys like the non-working embedding APIs; lots of internal
refactoring.
- Implemented indexer support. Managed instances that implement indexers
can now be used naturally from Python ( e.g. someobject[0] ).
- Implemented sequence protocol support for managed arrays.
- Implemented basic thread state management; calls to managed methods
no longer block Python. I won't go so far as to say the thread
choreography is "finished", as I don't have a comprehensive set of
tests to back that up yet (and it will take some work to write a
sufficiently large and evil set of tests).
- Fixed a bug that caused conversions of managed strings to PyUnicode to
produce mangled values in certain situations.
- Fixed a number of problems related to subclassing a managed class,
including the fact that it didn't work :)
- Fixed all of the bugs that were causing tests to fail. This release
contains all new bugs and new failing tests. Progress! :)
PythonNet Preview 1
---------------------------------------------------------------------------
- Initial (mostly) working experimental release.

Просмотреть файл

@ -0,0 +1,210 @@
<html>
<head>
<title>Python for .NET</title>
<style type="text/css"><!--
body {
font: 8pt/16pt georgia,verdana;
text-decoration: none;
color: #555753;
background: #ffffff;
margin: 0px;
}
p {
font: 8pt/16pt georgia;
}
h1 {
font: bold 14pt;
color: #000044;
background-color: #EFEFFF;
color: #000044;
border-style: solid;
border-width: 1px;
border-color: #555753;
padding: 6px, 2px, 6px, 2px;
}
h2 {
font: bold 14pt;
margin-bottom: 0px;
color: #000044;
}
h3 {
font: bold 12pt;
margin-bottom: 0px;
color: #000044;
}
a:link {
font-weight: bold;
text-decoration: none;
color: #000066;
}
a:visited {
font-weight: bold;
text-decoration: none;
color: #000066;
}
a:hover, a:active {
text-decoration: underline;
color: #000066;
}
pre {
font-family: monospace;
background-color: #EFEFFF;
color: #000044;
border-style: solid;
border-width: 1px;
border-color: #555753;
padding: 6px, 2px, 6px, 2px;
}
li {
font: 8pt/16pt georgia,verdana;
text-decoration: none;
color: #555753;
}
.spacer {
font: bold 14pt;
}
.menu {
background-color: #EFEFFF;
color: #000044;
border-style: solid;
border-width: 1px;
border-color: #555753;
padding: 6px, 2px, 6px, 2px;
font-size: x-small;
}
.menu ul {
margin: 0px;
padding: 0px;
}
//--></style>
</head>
<body>
<table width="98%" border="0" cellspacing="4">
<tr>
<!--
<td align="left" valign="top" width="20%" class="menu">
<h1>Python for .NET</h1>
</td>
-->
<td align="left" valign="top">
<h1>Python for .NET</h1>
<p>
Python for .NET is a package that gives Python programmers nearly seamless
integration with the .NET Common Language Runtime (CLR) and provides a
powerful application scripting tool for .NET developers. Using this package
you can script .NET applications or build entire applications in Python,
using .NET services and components written in any language that targets the
CLR (Managed C++, C#, VB, JScript).
</p>
<p>
Note that this package does <em>not</em> implement Python as a first-class
CLR language - it does not produce managed code (IL) from Python code.
Rather, it is an integration of the C Python engine with the .NET runtime.
This approach allows you to use use CLR services and continue to use existing
Python code and C-based extensions while maintaining native execution speeds
for Python code. If you are interested in a pure managed-code implementation
of the Python language, you should check out the
<a href="http://www.ironpython.com">IronPython</a> project, which is in
active development.
</p>
<p>
Python for .NET is currently compatible with Python releases 2.3 and greater.
To subscribe to the
<a href="http://mail.python.org/mailman/listinfo/pythondotnet">
Python for .NET mailing list
</a> or read the
<a href="http://mail.python.org/pipermail/pythondotnet/">
online archives
</a> of the list, see the
<a href="http://mail.python.org/mailman/listinfo/pythondotnet">
mailing list information
</a> page. You can also send questions or comments to me at
<a href="mailto:brian.lloyd@revolution.com">brian.lloyd@revolution.com</a>
or use the
<a href="http://sourceforge.net/tracker/?group_id=162464">
Python for .NET issue tracker</a> to report issues.
</p>
<p>
My <a href="http://brianlloyd.blogspot.com">blog site</a> is also
(sometimes) a good source for more information on Python for .NET ;)
</p>
<ul>
<li>The <a href="./readme.html">README</a>
provides a detailed overview of Python for .NET, as well as
some basic usage examples. Many other examples can be found
in the demos and unit tests for the package.
</li>
<li>Checkout the
<a href="http://cvs.sourceforge.net/viewcvs.py/pythonnet">PythonNet</a>
code
from CVS. See the <a href="http://sourceforge.net/cvs/?group_id=162464">
instructions on Source Forge</a> for details.
</li>
<li><strong>Python 2.4 Releases</strong>
<br />
<a href="./Releases/pythonnet-1.0-rc2-py2.4-clr1.1.exe">
pythonnet-1.0-rc2-py2.4-clr1.1.exe
</a>
<br />
<a href="./Releases/pythonnet-1.0-rc2-py2.4-clr1.1-src.tgz">
pythonnet-1.0-rc2-py2.4-clr1.1-src.tgz
</a>
</li>
<li><strong>Python 2.3 Releases</strong>
<br />
<a href="./Releases/pythonnet-1.0-rc2-py2.3-clr1.1.exe">
pythonnet-1.0-rc2-py2.3-clr1.1.exe
</a>
<br />
<a href="./Releases/pythonnet-1.0-rc2-py2.3-clr1.1-src.tgz">
pythonnet-1.0-rc2-py2.3-clr1.1-src.tgz
</a>
</li>
</ul>
</td>
</tr>
</table>
</body>
</html>

Просмотреть файл

@ -0,0 +1,61 @@
Zope Public License (ZPL) Version 2.0
-----------------------------------------------
This software is Copyright (c) Zope Corporation (tm) and
Contributors. All rights reserved.
This license has been certified as open source. It has also
been designated as GPL compatible by the Free Software
Foundation (FSF).
Redistribution and use in source and binary forms, with or
without modification, are permitted provided that the
following conditions are met:
1. Redistributions in source code must retain the above
copyright notice, this list of conditions, and the following
disclaimer.
2. 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.
3. The name Zope Corporation (tm) must not be used to
endorse or promote products derived from this software
without prior written permission from Zope Corporation.
4. The right to distribute this software or to use it for
any purpose does not give you the right to use Servicemarks
(sm) or Trademarks (tm) of Zope Corporation. Use of them is
covered in a separate agreement (see
http://www.zope.com/Marks).
5. If any files are modified, you must cause the modified
files to carry prominent notices stating that you changed
the files and the date of any change.
Disclaimer
THIS SOFTWARE IS PROVIDED BY ZOPE CORPORATION ``AS IS''
AND ANY EXPRESSED 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 ZOPE CORPORATION OR ITS 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.
This software consists of contributions made by Zope
Corporation and many individuals on behalf of Zope
Corporation. Specific attributions are listed in the
accompanying credits file.

Просмотреть файл

@ -0,0 +1,870 @@
<html>
<head>
<title>Python for .NET</title>
<style type="text/css"><!--
body {
font: 8pt/16pt georgia,verdana;
text-decoration: none;
color: #555753;
background: #ffffff;
margin: 0px;
}
p {
font: 8pt/16pt georgia;
}
h1 {
font: bold 14pt;
color: #000044;
/*
background-color: #EFEFFF;
color: #000044;
border-style: solid;
border-width: 1px;
border-color: #555753;
padding: 6px, 2px, 6px, 2px;
*/
}
h2 {
font: bold 14pt;
margin-bottom: 0px;
color: #000044;
}
h3 {
font: bold 12pt;
margin-bottom: 0px;
color: #000044;
}
a:link {
font-weight: bold;
text-decoration: none;
color: #000066;
}
a:visited {
font-weight: bold;
text-decoration: none;
color: #000066;
}
a:hover, a:active {
text-decoration: underline;
color: #000066;
}
pre {
font-family: monospace;
background-color: #EFEFFF;
color: #000044;
border-style: solid;
border-width: 1px;
border-color: #555753;
padding: 6px, 2px, 6px, 2px;
}
li {
font: 8pt/16pt georgia,verdana;
text-decoration: none;
color: #555753;
}
.spacer {
font: bold 14pt;
}
.menu {
background-color: #EFEFFF;
color: #000044;
border-style: solid;
border-width: 1px;
border-color: #555753;
padding: 6px, 2px, 6px, 2px;
font-size: x-small;
}
.menu ul {
margin: 0px;
padding: 0px;
}
//--></style>
</head>
<body>
<table width="98%" border="0" cellspacing="4">
<tr>
<td align="left" valign="top" width="20%" class="menu">
<h1>Python for .NET</h1>
<ul>
<li><a href="#installation">Installation</a></li>
<li><a href="#getting_started">Getting Started</a></li>
<li><a href="#importing">Importing Modules</a></li>
<li><a href="#classes">Using Classes</a></li>
<li><a href="#fields">Fields and Properties</a></li>
<li><a href="#indexers">Using Indexers</a></li>
<li><a href="#methods">Using Methods</a></li>
<li><a href="#delegates">Delegates and Events</a></li>
<li><a href="#exceptions">Exception Handling</a></li>
<li><a href="#arrays">Using Arrays</a></li>
<li><a href="#collections">Using Collections</a></li>
<li><a href="#com">COM Components</a></li>
<li><a href="#types">Type Conversion</a></li>
<li><a href="#assemblies">Using Assemblies</a></li>
<li><a href="#embedding">Embedding Python</a></li>
<li><a href="#license">License</a></li>
</ul>
</td>
<td align="left" valign="top">
<p>
Python for .NET is a package that gives Python programmers nearly seamless
integration with the .NET Common Language Runtime (CLR) and provides a
powerful application scripting tool for .NET developers. Using this package
you can script .NET applications or build entire applications in Python,
using .NET services and components written in any language that targets the
CLR (Managed C++, C#, VB, JScript).
</p>
<p>
Note that this package does <em>not</em> implement Python as a first-class
CLR language - it does not produce managed code (IL) from Python code.
Rather, it is an integration of the C Python engine with the .NET runtime.
This approach allows you to use use CLR services and continue to use existing
Python code and C-based extensions while maintaining native execution speeds
for Python code. If you are interested in a pure managed-code implementation
of the Python language, you should check out the
<a href="http://www.ironpython.com">IronPython</a> project, which is in
active development.
</p>
<p>
Python for .NET is currently compatible with Python releases 2.3 and greater.
Current releases are available at the
<a href="http://pythonnet.sourceforge.net/">
Python for .NET website
</a>. To subscribe to the
<a href="http://mail.python.org/mailman/listinfo/pythondotnet">
Python for .NET mailing list
</a> or read the
<a href="http://mail.python.org/pipermail/pythondotnet/">
online archives
</a> of the list, see the
<a href="http://mail.python.org/mailman/listinfo/pythondotnet">
mailing list information
</a> page.
</p>
<a name="#installation"></a>
<h2>Installation</h2>
<p>
Python for .NET is available as a source release and as a Windows installer
for various versions of Python and the common language runtime from the
<a href="http://pythonnet.sourceforge.net/">
Python for .NET website
</a>. On Windows platforms, you can choose to install .NET-awareness into
an existing Python installation as well as install Python for .NET as a
standalone package.
</p>
<p>
The source release is a self-contained "private" assembly.
Just unzip the package wherever you want it, cd to that directory and run
python.exe to start using it. Note that the source release does not
include a copy of the CPython runtime, so you will need to have installed
Python on your machine before using the source release.
</p>
<p>
<strong>Running on Linux/Mono:</strong> preliminary testing shows that
PythonNet will run under <a href="http://www.go-mono.com">Mono</a>, though
the Mono runtime is not yet complete so there still may be problems. The
Python for .NET integration layer is 100% managed code, so there should be
no long-term issues under Mono - it should work better and better as the
Mono platform matures.
</p>
<p>
It is not currently possible to *build* PythonNet using only the Mono
tools, due to an issue involving the Mono assembler / disassembler. You
should, however, be able to try the pre-built assembly under Mono (or
compile it yourself with the MS tools and run it under Mono).
</p>
<p>
Note that if you are running under Mono on a *nix system, you will need
to have a compatible version of Python installed. You will also need
to create a symbolic link to the copy of libpython2.x.so (in your existing
Python installation) in the PythonNet directory. This is needed to ensure
that the mono interop dll loader will find it by name. For example:
</p>
<pre>
ln -s /usr/lib/libpython2.4.so ./python24.so
</pre>
<a name="getting_started"></a>
<h2>Getting Started</h2>
<p>
A key goal for this project has been that Python for .NET should &quot;work
just the way you'd expect in Python&quot;, except for cases that are .NET
specific (in which case the goal is to work &quot;just the way you'd expect
in C#&quot;).
</p>
<p>
If you already know Python, you can probably finish this readme and then
refer to .NET docs to figure out anything you need to do. Conversely if
you are familiar with C# or another .NET language, you probably just
need to pick up one of the many good Python books or read the Python
tutorial online to get started.
</p>
<p>
A good way to start is to run <strong>python.exe</strong> and follow along
with the examples in this document. If you get stuck, there are also a
number of demos and unit tests located in the source directory of the
distribution that can be helpful as examples.
</p>
<a name="importing"></a>
<h2>Importing Modules</h2>
<p>
Python for .NET allows CLR namespaces to be treated essentially as
Python packages. The top-level package is named <code>CLR</code>, and
acts as the root for accessing all CLR namespaces:
</p>
<pre>
from CLR.System import String
import CLR.System as System
</pre>
<p>
Types from any loaded assembly may be imported and used in this manner.
The import hook uses "implicit loading" to support automatic loading
of assemblies whose names correspond to an imported namespace:
</p>
<pre>
# This will implicitly load the System.Windows.Forms assembly
from CLR.System.Windows.Forms import Form
</pre>
<p>
Python for .NET uses the PYTHONPATH (sys.path) to look for assemblies
to load, in addition to the usual application base and the GAC. To
ensure that you can implicitly import an assembly, put the directory
containing the assembly in <code>sys.path</code>.
</p>
<p>
To load assemblies with names that do not correspond with a namespace,
you can use the standard mechanisms provided by the CLR:
</p>
<pre>
from CLR.System.Reflection import Assembly
a = Assembly.LoadWithPartialName("SomeAssembly")
# now we can import namespaces defined in that assembly
from CLR.SomeNamespace import Something
</pre>
<p>
Note that CLR modules are "lazy". Because a namespace can contain a
potentially very large number of classes, reflected CLR classes are
created on-demand when they are requested of a CLR module. This means
that using the Python <code>dir()</code> function in the interactive
interpreter will not necessarily show all of the classes available from
a given CLR module (it will only show any classes that have been referenced
to that point in time).
</p>
<p>
It also means that <code>from somemodule import *</code> will not work as
expected. It is possible that it could be made to work in the future,
but for now it would impose a big performance hit and a lot of
complexity to support something that is used relatively rarely and
often considered bad form in Python anyway ;)
</p>
<a name="classes"></a>
<h2>Using Classes</h2>
<p>
Python for .NET allows you to use any non-private classes, structs,
interfaces, enums or delegates from Python. To create an instance of
a managed class, you use the standard instantiation syntax, passing
a set of arguments that match one of its public constructors:
</p>
<pre>
from CLR.System.Drawing import Point
p = Point(5, 5)
</pre>
<p>
You can also subclass managed classes in Python. See the
<code>helloform.py</code> file in the <code>/demo</code> directory of the
distribution for a simple Windows Forms example that demonstrates
subclassing a managed class.
</p>
<a name="fields"></a>
<h2>Fields And Properties</h2>
<p>
You can get and set fields and properties of CLR objects just as if
they were regular attributes:
</p>
<pre>
from CLR.System import Environment
name = Environment.MachineName
Environment.ExitCode = 1
</pre>
<a name="indexers"></a>
<h2>Using Indexers</h2>
<p>
If a managed object implements one or more indexers, you can call
the indexer using standard Python indexing syntax:
</p>
<pre>
from CLR.System.Collections import Hashtable
table = Hashtable()
table["key 1"] = "value 1"
</pre>
<p>
Overloaded indexers are supported, using the same notation one
would use in C#:
</p>
<pre>
items[0, 2]
items[0, 2, 3]
</pre>
<a name="methods"></a>
<h2>Using Methods</h2>
<p>
Methods of CLR objects behave generally like normal Python methods.
Static methods may be called either through the class or through an
instance of the class. All public and protected methods of CLR objects
are accessible to Python:
</p>
<pre>
from CLR.System import Environment
drives = Environment.GetLogicalDrives()
</pre>
<p>
It is also possible to call managed methods <code>unbound</code> (passing the
instance as the first argument) just as with Python methods. This is
most often used to explicitly call methods of a base class.
</p>
<p>
<em>Note that there is one caveat related to calling unbound methods: it
is possible for a managed class to declare a static method and an
instance method with the same name. Since it is not possible for the
runtime to know the intent when such a method is called unbound, the
static method will always be called.</em>
</p>
<p>
The docstring of CLR a method (__doc__) can be used to view the
signature of the method, including overloads if the CLR method is
overloaded. You can also use the Python <code>help</code> method to inspect
a managed class:
</p>
<pre>
from CLR.System import Environment
print Environment.GetFolderPath.__doc__
help(Environment)
</pre>
<a name="delegates"></a>
<h2>Delegates And Events</h2>
<p>
Delegates defined in managed code can be implemented in Python. A
delegate type can be instantiated and passed a callable Python object
to get a delegate instance. The resulting delegate instance is a true
managed delegate that will invoke the given Python callable when it
is called:
</p>
<pre>
def my_handler(source, args):
print 'my_handler called!'
# instantiate a delegate
d = AssemblyLoadEventHandler(my_handler)
# use it as an event handler
AppDomain.CurrentDomain.AssemblyLoad += d
</pre>
<p>
Multicast delegates can be implemented by adding more callable objects
to a delegate instance:
</p>
<pre>
d += self.method1
d += self.method2
d()
</pre>
<p>
Events are treated as first-class objects in Python, and behave in
many ways like methods. Python callbacks can be registered with event
attributes, and an event can be called to fire the event.
</p>
<p>
Note that events support a convenience spelling similar to that used
in C#. You do not need to pass an explicitly instantiated delegate
instance to an event (though you can if you want). Events support the
<code>+=</code> and <code>-=</code> operators in a way very similar to
the C# idiom:
</p>
<pre>
def handler(source, args):
print 'my_handler called!'
# register event handler
object.SomeEvent += handler
# unregister event handler
object.SomeEvent -= handler
# fire the event
result = object.SomeEvent(...)
</pre>
<a name="exceptions"></a>
<h2>Exception Handling</h2>
<p>
You can raise and catch managed exceptions just the same as you would
pure-Python exceptions:
<pre>
from CLR.System import NullReferenceException
try:
raise NullReferenceException("aiieee!")
except NullReferenceException, e:
print e.Message
print e.Source
</pre>
</p>
<a name="arrays"></a>
<h2>Using Arrays</h2>
<p>
Managed arrays support the standard Python sequence protocols:
</p>
<pre>
items = SomeObject.GetArray()
# Get first item
v = items[0]
items[0] = v
# Get last item
v = items[-1]
items[-1] = v
# Get length
l = len(items)
# Containment test
test = v in items
</pre>
<p>
Multidimensional arrays support indexing using the same notation one
would use in C#:
</p>
<pre>
items[0, 2]
items[0, 2, 3]
</pre>
<a name="collections"></a>
<h2>Using Collections</h2>
<p>
Managed arrays and managed objects that implement the IEnumerable
interface can be iterated over using the standard iteration Python
idioms:
</p>
<pre>
domain = System.AppDomain.CurrentDomain
for item in domain.GetAssemblies():
name = item.GetName()
</pre>
<a name="com"></a>
<h2>Using COM Components</h2>
<p>
Using Microsoft-provided tools such as <strong>aximp.exe</strong> and
<strong>tlbimp.exe</strong>, it is possible to generate managed wrappers
for COM libraries. After generating such a wrapper, you can use the
libraries from Python just like any other managed code.
</p>
<p>
Note: currently you need to put the generated wrappers in the GAC,
in the PythonNet assembly directory or on the PYTHONPATH in order
to load them.
</p>
<a name="types"></a>
<h2>Type Conversion</h2>
<p>
Type conversion under Python for .NET is fairly straightforward - most
elemental Python types (string, int, long, etc.) convert automatically
to compatible managed equivalents (String, Int32, etc.) and vice-versa.
Note that all strings returned from the CLR are returned as unicode.
</p>
<p>
Types that do not have a logical equivalent in Python are exposed as
instances of managed classes or structs (System.Decimal is an example).
</p>
<p>
The .NET architecture makes a distinction between <code>value types</code>
and <code>reference types</code>. Reference types are allocated on the heap,
and value types are allocated either on the stack or in-line within an
object.
</p>
<p>
A process called <code>boxing</code> is used in .NET to allow code to treat
a value type as if it were a reference type. Boxing causes a separate
copy of the value type object to be created on the heap, which then
has reference type semantics.
</p>
<p>
Understanding boxing and the distinction between value types and
reference types can be important when using Python for .NET because
the Python language has no value type semantics or syntax - in
Python &quot;everything is a reference&quot;.
</p>
<p>
Here is a simple example that demonstrates an issue. If you are an
experienced C# programmer, you might write the following code:
</p>
<pre>
items = CLR.System.Array.CreateInstance(Point, 3)
for i in range(3):
items[i] = Point(0, 0)
items[0].X = 1 # won't work!!
</pre>
<p>
While the spelling of <code>items[0].X = 1</code> is the same in C# and
Python, there is an important and subtle semantic difference. In C# (and other
compiled-to-IL languages), the compiler knows that Point is a value
type and can do the Right Thing here, changing the value in place.
</p>
<p>
In Python however, "everything's a reference", and there is really no
spelling or semantic to allow it to do the right thing dynamically. The
specific reason that <code>items[0]</code> itself doesn't change is that
when you say <code>items[0]</code>, that getitem operation creates a Python
object that holds a reference to the object at <code>items[0]</code> via a
GCHandle. That causes a ValueType (like Point) to be boxed, so the following
setattr (<code>.X = 1</code>) <em>changes the state of the boxed value, not
the original unboxed value</em>.
</p>
<p>
The rule in Python is essentially: &quot;the result of any attribute or
item access is a boxed value&quot;, and that can be important in how you
approach your code.
</p>
<p>
Because there are no value type semantics or syntax in Python, you
may need to modify your approach. To revisit the previous example,
we can ensure that the changes we want to make to an array item
aren't "lost" by resetting an array member after making changes
to it:
</p>
<pre>
items = CLR.System.Array.CreateInstance(Point, 3)
for i in range(3):
items[i] = Point(0, 0)
# This _will_ work. We get 'item' as a boxed copy of the Point
# object actually stored in the array. After making our changes
# we re-set the array item to update the bits in the array.
item = items[0]
item.X = 1
items[0] = item
</pre>
<p>
This is not unlike some of the cases you can find in C# where you have
to know about boxing behavior to avoid similar kinds of <code>lost
update</code> problems (generally because an implicit boxing happened that
was not taken into account in the code).
</p>
<p>
This is the same thing, just the manifestation is a little different
in Python. See the .NET documentation for more details on boxing and
the differences between value types and reference types.
</p>
<a name="assemblies"></a>
<h2>Using Assemblies</h2>
<p>
The Python for .NET runtime uses Assembly.LoadWithPartialName to do
name-based imports, which will usually load the most recent version of
an assembly that it can find.
</p>
<p>
The CLR's ability to load different versions of assemblies side-by-side
is one of the (relatively few) places where the matching of meta-models
between Python and the CLR breaks down (though it is unclear how often
this happens in practice).
</p>
<p>
Because Python import is name-based and unaware of any concept of
versioned modules, the design goal has been for name-based implicit assembly
loading to do something consistent and reasonable (i.e. load most
recent available based on the name).
</p>
<p>
It <em>is</em> possible to load a specific version of an assembly if you
need to using code similar to the following:
</p>
<pre>
from CLR.System.Reflection import Assembly, AssemblyName
name = AssemblyName(...) # set required version, etc.
assembly = Assembly.Load(name)
# now import namespaces from the loaded assembly
</pre>
<p>
Things get a lot more complicated if you need to load more than one
version of a particular assembly (or more likely, you have a dependency
on some library the does so). In this case, the names you access via
the CLR modules will always come from the first version of the
assembly loaded (which will always win in the internals of the Python
for .NET runtime).
</p>
<p>
You <em>can</em> still use particular versions of objects in this case - you
just have to do more work to get the right versions of objects:
</p>
<pre>
from CLR.System.Reflection import Assembly, AssemblyName
from System import Activator
name = AssemblyName(...) # get the right version
assembly = Assembly.Load(name)
type = assembly.GetType("QualifiedNameOf.TheTypeINeed")
obj = Activator.CreateInstance(type)
</pre>
</p>
<a name="embedding"></a>
<h2>Embedding Python</h2>
<p>
<strong>Note:</strong> because Python code running under Python for .NET
is inherently unverifiable, it runs totally under the radar of the security
infrastructure of the CLR so you should restrict use of the Python assembly
to trusted code.
</p>
<p>
The Python runtime assembly defines a number of public classes that
provide a subset of the functionality provided by the Python C API.
</p>
<p>
These classes include PyObject, PyList, PyDict, etc. The source and
the unit tests are currently the only API documentation.. The rhythym
is very similar to using Python C++ wrapper solutions such as CXX.
</p>
<p>
At a very high level, to embed Python in your application you
will need to:
</p>
<ul>
<li>Reference Python.Runtime.dll in your build environment</li>
<li>Call PythonEngine.Intialize() to initialize Python</li>
<li>Call PythonEngine.ImportModule(name) to import a module</li>
</ul>
<p>
The module you import can either start working with your managed app
environment at the time its imported, or you can explicitly lookup and
call objects in a module you import.
</p>
<p>
For general-purpose information on embedding Python in applications, use
www.python.org or Google to find (C) examples. Because Python for .NET is
so closely integrated with the managed environment, you will generally be
better off importing a module and deferring to Python code as early as
possible rather than writing a lot of managed embedding code.
</p>
<p>
<strong>Important Note for embedders:</strong> Python is not free-threaded
and uses a global interpreter lock to allow multi-threaded applications to
interact safely with the Python interpreter. Much more information about
this is available in the Python C API documentation on the www.python.org
Website.
</p>
<p>
When embedding Python in a managed application, you have to manage the GIL
in just the same way you would when embedding Python in a C or C++
application.
</p>
<p>
Before interacting with any of the objects or APIs provided by the
Python.Runtime namespace, calling code must have acquired the Python
global interpreter lock by calling the <code>PythonEngine.AcquireLock</code>
method. The only exception to this rule is the
<code>PythonEngine.Initialize</code> method, which may be called at startup
without having acquired the GIL.
</p>
<p>
When finished using Python APIs, managed code must call a corresponding
<code>PythonEngine.ReleaseLock</code> to release the GIL and allow other
threads to use Python.
</p>
<p>
The AcquireLock and ReleaseLock methods are thin wrappers over the
unmanaged <code>PyGILState_Ensure</code> and <code>PyGILState_Release</code>
functions from the Python API, and the documentation for those APIs applies
to the managed versions.
</p>
<a name="license" />
<h2>License</h2>
<p>
Python for .NET is released under the open source Zope Public License (ZPL).
A copy of the ZPL is included in the distribution, or you can find a copy
of the
<a href="http://pythonnet.sourceforge.net/license.txt">
ZPL online
</a>. Some distributions of this package include a copy of the C Python
dlls and standard library, which are covered by the
<a href="http://www.python.org/license.html">
Python license
</a>.
</p>
</td>
</tr>
</table>
</body>
</html>

Просмотреть файл

@ -0,0 +1,73 @@
; --------------------------------------------------------------------------------
; Setup script for Python for .NET (based on InnoSetup 5.0.8)
; --------------------------------------------------------------------------------
[Setup]
SourceDir=..
OutputDir=release
AppName=Python for .NET
AppVerName=Python for .NET 1.0 RC2
AppPublisher=Brian Lloyd
AppCopyright=Copyright © 2005 Zope Corporation
DefaultDirName={pf}\PythonNet
DefaultGroupName=Python for .NET
LicenseFile=installer\license.txt
DisableProgramGroupPage=yes
WizardImageFile=installer\left.bmp
WizardSmallImageFile=installer\top.bmp
WizardImageStretch=no
[Tasks]
Name: "existing"; Description: "Install .NET support in &existing python installation"; Flags: unchecked
Name: "icon"; Description: "Create a &desktop icon"; Flags: unchecked
[Files]
Source: "makefile"; DestDir: "{app}"; Excludes: ".svn*,~*,CVS*"; Flags: ignoreversion
Source: "python.exe"; DestDir: "{app}"; Excludes: ".svn*,~*,CVS*"; Flags: ignoreversion
Source: "*.dll"; DestDir: "{app}"; Excludes: ".svn*,~*,CVS*"; Flags: ignoreversion
Source: "demo\*.*"; DestDir: "{app}\demo"; Excludes: ".svn*,~*,CVS*"; Flags: ignoreversion recursesubdirs
Source: "doc\*.*"; DestDir: "{app}\doc"; Excludes: ".svn*,~*,CVS*"; Flags: ignoreversion recursesubdirs
Source: "src\*.*"; DestDir: "{app}\src"; Excludes: ".svn*,~*,CVS*"; Flags: ignoreversion recursesubdirs
Source: "redist\2.3\*.*"; DestDir: "{app}"; Excludes: ".svn*,~*,CVS*"; Flags: ignoreversion recursesubdirs
Source: "doc/readme.html"; DestDir: "{app}/doc"; Excludes: ".svn*,~*,CVS*"; Flags: ignoreversion isreadme
Source: "*Python.Runtime.dll"; DestDir: "{code:GetPythonDir}"; Excludes: ".svn*,~*,CVS*"; Flags: ignoreversion recursesubdirs; Check: UpdateExisting
Source: "CLR.dll"; DestDir: "{code:GetPythonDir}"; Excludes: ".svn*,~*,CVS*"; Flags: ignoreversion recursesubdirs; Check: UpdateExisting
[Icons]
Name: "{group}\Python for .NET"; Filename: "{app}\python.exe"
Name: "{userdesktop}\Python for .NET"; Filename: "{app}\python.exe"; Tasks: icon
[Code]
function GetPythonDir(Default: String): string;
var
path : string;
begin
path := '';
RegQueryStringValue(HKLM, 'Software\Python\PythonCore\2.3\InstallPath', '', path);
Result := path;
end;
function UpdateExisting(): boolean;
var
temp: string;
res: boolean;
begin
temp := WizardSelectedTasks(False);
res := (Pos('existing', temp) <> 0);
temp := GetPythonDir('');
Result := res and (Pos('Python', temp) <> 0);
end;

Двоичные данные
pythonnet/pythonnet/installer/left.bmp Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 28 KiB

Просмотреть файл

@ -0,0 +1,59 @@
Zope Public License (ZPL) Version 2.0
-----------------------------------------------
This software is Copyright (c) Zope Corporation (tm) and
Contributors. All rights reserved.
This license has been certified as open source. It has also
been designated as GPL compatible by the Free Software
Foundation (FSF).
Redistribution and use in source and binary forms, with or
without modification, are permitted provided that the
following conditions are met:
1. Redistributions in source code must retain the above
copyright notice, this list of conditions, and the following
disclaimer.
2. 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.
3. The name Zope Corporation (tm) must not be used to
endorse or promote products derived from this software
without prior written permission from Zope Corporation.
4. The right to distribute this software or to use it for
any purpose does not give you the right to use Servicemarks
(sm) or Trademarks (tm) of Zope Corporation. Use of them is
covered in a separate agreement (see
http://www.zope.com/Marks).
5. If any files are modified, you must cause the modified
files to carry prominent notices stating that you changed
the files and the date of any change.
Disclaimer
THIS SOFTWARE IS PROVIDED BY ZOPE CORPORATION ``AS IS''
AND ANY EXPRESSED 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 ZOPE CORPORATION OR ITS 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.
This software consists of contributions made by Zope
Corporation and many individuals on behalf of Zope
Corporation. Specific attributions are listed in the
accompanying credits file.

Двоичные данные
pythonnet/pythonnet/installer/top.bmp Executable file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 4.1 KiB

99
pythonnet/pythonnet/makefile Executable file
Просмотреть файл

@ -0,0 +1,99 @@
# Makefile for the PythonRuntime .NET assembly and tests. Thanks to
# Camilo Uribe <kmilo@softhome.net> for contributing Mono support.
RELEASE=pythonnet-1.0-rc2-py2.4-clr1.1-src
RUNNER=
ILDASM=ildasm
ILASM=ilasm
CSC=csc.exe
all: python.exe CLR.dll Python.Test.dll
python.exe: Python.Runtime.dll
cd src; cd console; \
$(CSC) /nologo /target:exe /out:../../python.exe \
/reference:../../Python.Runtime.dll /recurse:*.cs
cd ..; cd ..;
Python.Runtime.dll: callconvutil.exe
cd src; cd runtime; \
$(CSC) /nologo /unsafe /target:library /out:../../Python.Runtime.dll \
/recurse:*.cs
cd ..; cd ..;
$(ILDASM) /nobar Python.Runtime.dll /out=Python.Runtime.il;
$(RUNNER) ./callconvutil.exe;
$(ILASM) /nologo /quiet /dll \
/resource=Python.Runtime.res /output=Python.Runtime.dll \
Python.Runtime.il2;
rm -f Python.Runtime.il;
rm -f Python.Runtime.il2;
rm -f Python.Runtime.res;
rm -f ./callconvutil.exe;
CLR.dll: Python.Runtime.dll
$(ILASM) /nologo /dll /quiet /output=CLR.dll \
./src/runtime/clrmodule.il;
Python.Test.dll: Python.Runtime.dll
cd src; cd testing; \
$(CSC) /nologo /target:library /out:../../Python.Test.dll \
/reference:../../Python.Runtime.dll \
/recurse:*.cs
cd ..; cd ..;
callconvutil.exe:
cd src; cd tools; \
$(CSC) /nologo /target:exe /out:../../callconvutil.exe \
/recurse:*.cs
cd ..; cd ..;
clean:
rm -f python.exe Python*.dll Python*.il Python*.il2 Python*.res
rm -f callconvutil.exe
rm -f CLR.dll
rm -f ./*~
cd src; cd console; rm -f *~; cd ..; cd ..;
cd src; cd runtime; rm -f *~; cd ..; cd ..;
cd src; cd testing; rm -f *~; cd ..; cd ..;
cd src; cd tests; rm -f *~; rm -f *.pyc; cd ..; cd ..;
cd src; cd tools; rm -f *~; cd ..; cd ..;
cd doc; rm -f *~; cd ..;
cd demo; rm -f *~; cd ..;
test:
rm -f ./src/tests/*.pyc
$(RUNNER) ./python.exe ./src/tests/runtests.py
dist: clean
mkdir ./$(RELEASE)
cp -R ./makefile ./$(RELEASE)/
cp -R ./demo ./$(RELEASE)/
cp -R ./doc ./$(RELEASE)/
cp -R ./src ./$(RELEASE)/
make
cp ./python.exe ./$(RELEASE)/
cp ./*.dll ./$(RELEASE)/
tar czf $(RELEASE).tgz ./$(RELEASE)/
mv $(RELEASE).tgz ./release/
rm -rf ./$(RELEASE)/
dis:
$(ILDASM) Python.Runtime.dll /out=Python.Runtime.il
asm:
$(ILASM) /dll /quiet \
/resource=Python.Runtime.res /output=Python.Runtime.dll \
Python.Runtime.il

101
pythonnet/pythonnet/makefile.mono Executable file
Просмотреть файл

@ -0,0 +1,101 @@
# Makefile for the PythonRuntime .NET assembly and tests. Thanks to
# Camilo Uribe <kmilo@softhome.net> for contributing Mono support.
# WARNING: this makefile cannot currently build the Python runtime
# dll under mono, due to use of attributes that the mono assembler /
# disassembler doesn't yet support.
RELEASE=pythonnet-1.0-rc1-py2.3-clr1.1-src
RUNNER=mono
ILDASM=monodis
ILASM=ilasm
CSC=mcs
all: python.exe CLR.dll Python.Test.dll
python.exe: Python.Runtime.dll
cd src; cd console; \
$(CSC) /nologo /target:exe /out:../../python.exe \
/reference:../../Python.Runtime.dll /recurse:*.cs
cd ..; cd ..;
Python.Runtime.dll: callconvutil.exe
cd src; cd runtime; \
$(CSC) /nologo /unsafe /target:library /out:../../Python.Runtime.dll \
/recurse:*.cs
cd ..; cd ..;
$(ILDASM) /nobar Python.Runtime.dll /out=Python.Runtime.il;
$(RUNNER) ./callconvutil.exe;
$(ILASM) /nologo /quiet /dll \
/resource=Python.Runtime.res /output=Python.Runtime.dll \
Python.Runtime.il2;
rm -f Python.Runtime.il;
rm -f Python.Runtime.il2;
rm -f Python.Runtime.res;
rm -f ./callconvutil.exe;
CLR.dll: Python.Runtime.dll
$(ILASM) /nologo /dll /quiet /output=CLR.dll \
./src/runtime/clrmodule.il;
Python.Test.dll: Python.Runtime.dll
cd src; cd testing; \
$(CSC) /nologo /target:library /out:../../Python.Test.dll \
/reference:../../Python.Runtime.dll \
/recurse:*.cs
cd ..; cd ..;
callconvutil.exe:
cd src; cd tools; \
$(CSC) /nologo /target:exe /out:../../callconvutil.exe \
/recurse:*.cs
cd ..; cd ..;
clean:
rm -f python.exe Python*.dll Python*.il Python*.il2 Python*.res
rm -f callconvutil.exe
rm -f CLR.dll
rm -f ./*~
cd src; cd console; rm -f *~; cd ..; cd ..;
cd src; cd runtime; rm -f *~; cd ..; cd ..;
cd src; cd testing; rm -f *~; cd ..; cd ..;
cd src; cd tests; rm -f *~; rm -f *.pyc; cd ..; cd ..;
cd src; cd tools; rm -f *~; cd ..; cd ..;
cd doc; rm -f *~; cd ..;
cd demo; rm -f *~; cd ..;
test:
rm -f ./src/tests/*.pyc
$(RUNNER) ./python.exe ./src/tests/runtests.py
dist: clean
mkdir ./$(RELEASE)
cp -R ./makefile ./$(RELEASE)/
cp -R ./demo ./$(RELEASE)/
cp -R ./doc ./$(RELEASE)/
cp -R ./src ./$(RELEASE)/
make
cp ./python.exe ./$(RELEASE)/
cp ./*.dll ./$(RELEASE)/
tar czf $(RELEASE).tgz ./$(RELEASE)/
mv $(RELEASE).tgz ./release/
rm -rf ./$(RELEASE)/
dis:
$(ILDASM) Python.Runtime.dll /out=Python.Runtime.il
asm:
$(ILASM) /dll /quiet \
/resource=Python.Runtime.res /output=Python.Runtime.dll \
Python.Runtime.il

Просмотреть файл

@ -0,0 +1,26 @@
// Copyright (c) 2004 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Reflection;
using System.Security.Permissions;
using System.Runtime.InteropServices;
[assembly: System.Reflection.AssemblyProduct("Python for .NET")]
[assembly: System.Reflection.AssemblyVersion("1.0.0.0")]
[assembly: AssemblyTitleAttribute("Python Console")]
[assembly: AssemblyDefaultAliasAttribute("python.exe")]
[assembly: CLSCompliant(true)]
[assembly: ComVisible(false)]
[assembly:PermissionSetAttribute(SecurityAction.RequestMinimum,
Name = "FullTrust")]

Просмотреть файл

@ -0,0 +1,34 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using Python.Runtime;
namespace Python.Runtime {
public sealed class PythonConsole {
private PythonConsole() {}
[STAThread]
public static int Main(string[] args) {
string [] cmd = Environment.GetCommandLineArgs();
PythonEngine.Initialize();
int i = Runtime.Py_Main(cmd.Length, cmd);
PythonEngine.Shutdown();
return i;
}
}
}

Просмотреть файл

@ -0,0 +1,251 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Collections;
using System.Reflection;
using System.Runtime.InteropServices;
namespace Python.Runtime {
/// <summary>
/// Implements a Python type for managed arrays. This type is essentially
/// the same as a ClassObject, except that it provides sequence semantics
/// to support natural array usage (indexing) from Python.
/// </summary>
internal class ArrayObject : ClassBase {
internal ArrayObject(Type tp) : base(tp) {}
internal override bool CanSubclass() {
return false;
}
[CallConvCdecl()]
public static IntPtr tp_new(IntPtr ob, IntPtr args, IntPtr kw) {
string message = "cannot instantiate array wrapper";
return Exceptions.RaiseTypeError(message);
}
//====================================================================
// Implements __getitem__ for array types.
//====================================================================
[CallConvCdecl()]
public static IntPtr mp_subscript(IntPtr ob, IntPtr idx) {
CLRObject obj = (CLRObject)ManagedType.GetManagedObject(ob);
Array items = obj.inst as Array;
Type itemType = obj.inst.GetType().GetElementType();
int rank = items.Rank;
int index = 0;
object value;
// Note that CLR 1.0 only supports int indexes - methods to
// support long indices were introduced in 1.1. We could
// support long indices automatically, but given that long
// indices are not backward compatible and a relative edge
// case, we won't bother for now.
// Single-dimensional arrays are the most common case and are
// cheaper to deal with than multi-dimensional, so check first.
if (rank == 1) {
index = (int)Runtime.PyInt_AsLong(idx);
if (Exceptions.ErrorOccurred()) {
return Exceptions.RaiseTypeError("invalid index value");
}
if (index < 0) {
index = items.Length + index;
}
try {
value = items.GetValue(index);
}
catch (IndexOutOfRangeException) {
Exceptions.SetError(Exceptions.IndexError,
"array index out of range"
);
return IntPtr.Zero;
}
return Converter.ToPython(items.GetValue(index), itemType);
}
// Multi-dimensional arrays can be indexed a la: list[1, 2, 3].
if (!Runtime.PyTuple_Check(idx)) {
Exceptions.SetError(Exceptions.TypeError,
"invalid index value"
);
return IntPtr.Zero;
}
int count = Runtime.PyTuple_Size(idx);
Array args = Array.CreateInstance(typeof(Int32), count);
for (int i = 0; i < count; i++) {
IntPtr op = Runtime.PyTuple_GetItem(idx, i);
index = (int)Runtime.PyInt_AsLong(op);
if (Exceptions.ErrorOccurred()) {
return Exceptions.RaiseTypeError("invalid index value");
}
if (index < 0) {
index = items.GetLength(i) + index;
}
args.SetValue(index, i);
}
try {
value = items.GetValue((int[]) args);
}
catch (IndexOutOfRangeException) {
Exceptions.SetError(Exceptions.IndexError,
"array index out of range"
);
return IntPtr.Zero;
}
return Converter.ToPython(value, itemType);
}
//====================================================================
// Implements __setitem__ for array types.
//====================================================================
[CallConvCdecl()]
public static int mp_ass_subscript(IntPtr ob, IntPtr idx, IntPtr v) {
CLRObject obj = (CLRObject)ManagedType.GetManagedObject(ob);
Array items = obj.inst as Array;
Type itemType = obj.inst.GetType().GetElementType();
int rank = items.Rank;
int index = 0;
object value;
if (items.IsReadOnly) {
Exceptions.RaiseTypeError("array is read-only");
return -1;
}
if (!Converter.ToManaged(v, itemType, out value, true)) {
return -1;
}
if (rank == 1) {
index = (int)Runtime.PyInt_AsLong(idx);
if (Exceptions.ErrorOccurred()) {
Exceptions.RaiseTypeError("invalid index value");
return -1;
}
if (index < 0) {
index = items.Length + index;
}
try {
items.SetValue(value, index);
}
catch (IndexOutOfRangeException) {
Exceptions.SetError(Exceptions.IndexError,
"array index out of range"
);
return -1;
}
return 0;
}
if (!Runtime.PyTuple_Check(idx)) {
Exceptions.RaiseTypeError("invalid index value");
return -1;
}
int count = Runtime.PyTuple_Size(idx);
Array args = Array.CreateInstance(typeof(Int32), count);
for (int i = 0; i < count; i++) {
IntPtr op = Runtime.PyTuple_GetItem(idx, i);
index = (int)Runtime.PyInt_AsLong(op);
if (Exceptions.ErrorOccurred()) {
Exceptions.RaiseTypeError("invalid index value");
return -1;
}
if (index < 0) {
index = items.GetLength(i) + index;
}
args.SetValue(index, i);
}
try {
items.SetValue(value, (int[])args);
}
catch (IndexOutOfRangeException) {
Exceptions.SetError(Exceptions.IndexError,
"array index out of range"
);
return -1;
}
return 0;
}
//====================================================================
// Implements __contains__ for array types.
//====================================================================
[CallConvCdecl()]
public static int sq_contains(IntPtr ob, IntPtr v) {
CLRObject obj = (CLRObject)ManagedType.GetManagedObject(ob);
Type itemType = obj.inst.GetType().GetElementType();
IList items = obj.inst as IList;
object value;
if (!Converter.ToManaged(v, itemType, out value, false)) {
return 0;
}
if (items.Contains(value)) {
return 1;
}
return 0;
}
//====================================================================
// Implements __len__ for array types.
//====================================================================
[CallConvCdecl()]
public static int mp_length(IntPtr ob) {
CLRObject self = (CLRObject)ManagedType.GetManagedObject(ob);
Array items = self.inst as Array;
return items.Length;
}
}
}

Просмотреть файл

@ -0,0 +1,26 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Reflection;
using System.Security.Permissions;
using System.Runtime.InteropServices;
[assembly: System.Reflection.AssemblyProduct("Python for .NET")]
[assembly: System.Reflection.AssemblyVersion("1.0.0.0")]
[assembly: AssemblyTitleAttribute("Python.Runtime")]
[assembly: AssemblyDefaultAliasAttribute("Python.Runtime.dll")]
[assembly: CLSCompliant(true)]
[assembly: ComVisible(false)]
[assembly:PermissionSetAttribute(SecurityAction.RequestMinimum,
Name = "FullTrust")]

Просмотреть файл

@ -0,0 +1,300 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.IO;
using System.Collections;
using System.Collections.Specialized;
using System.Reflection;
using System.Reflection.Emit;
namespace Python.Runtime {
/// <summary>
/// The AssemblyManager maintains information about the assemblies and
/// namespaces that have been loaded, and provides a simplified internal
/// interface for finding and obtaining Type objects by qualified names.
/// </summary>
internal class AssemblyManager {
static StringCollection pypath;
static AssemblyLoadEventHandler lh;
static ResolveEventHandler rh;
static Hashtable namespaces;
static ArrayList assemblies;
static Hashtable probed;
static int last;
private AssemblyManager() {}
//===================================================================
// Initialization performed on startup of the Python runtime.
//===================================================================
internal static void Initialize() {
pypath = new StringCollection();
namespaces = new Hashtable();
assemblies = new ArrayList();
probed = new Hashtable();
AppDomain domain = AppDomain.CurrentDomain;
lh = new AssemblyLoadEventHandler(AssemblyLoadHandler);
domain.AssemblyLoad += lh;
rh = new ResolveEventHandler(ResolveHandler);
domain.AssemblyResolve += rh;
Assembly[] items = domain.GetAssemblies();
for (int i = 0; i < items.Length; i++) {
Assembly a = items[i];
assemblies.Add(a);
ScanAssembly(a);
}
}
//===================================================================
// Cleanup resources upon shutdown of the Python runtime.
//===================================================================
internal static void Shutdown() {
AppDomain domain = AppDomain.CurrentDomain;
domain.AssemblyLoad -= lh;
domain.AssemblyResolve -= rh;
}
//===================================================================
// Event handler for assembly load events. At the time the Python
// runtime loads, we scan the app domain to map the assemblies that
// are loaded at the time. We also have to register this event handler
// so that we can know about assemblies that get loaded after the
// Python runtime is initialized.
//===================================================================
static void AssemblyLoadHandler(Object ob, AssemblyLoadEventArgs args){
Assembly assembly = args.LoadedAssembly;
assemblies.Add(assembly);
ScanAssembly(assembly);
}
//===================================================================
// Event handler for assembly resolve events. This is needed because
// we augment the assembly search path with the PYTHONPATH when we
// load an assembly from Python. Because of that, we need to listen
// for failed loads, because they might be dependencies of something
// we loaded from Python which also needs to be found on PYTHONPATH.
//===================================================================
static Assembly ResolveHandler(Object ob, ResolveEventArgs args){
string name = args.Name.ToLower();
for (int i = 0; i < assemblies.Count; i++) {
Assembly a = (Assembly)assemblies[i];
string full = a.FullName.ToLower();
if (full.StartsWith(name)) {
return a;
}
}
Assembly ao = LoadAssemblyPath(args.Name);
return ao;
}
//===================================================================
// We __really__ want to avoid using Python objects or APIs when
// probing for assemblies to load, since our ResolveHandler may be
// called in contexts where we don't have the Python GIL and can't
// even safely try to get it without risking a deadlock ;(
//
// To work around that, we update a managed copy of sys.path (which
// is the main thing we care about) when UpdatePath is called. The
// import hook calls this whenever it knows its about to use the
// assembly manager, which lets us keep up with changes to sys.path
// in a relatively lightweight and low-overhead way.
//===================================================================
internal static void UpdatePath() {
IntPtr list = Runtime.PySys_GetObject("path");
int count = Runtime.PyList_Size(list);
if (count != pypath.Count) {
pypath.Clear();
probed.Clear();
for (int i = 0; i < count; i++) {
IntPtr item = Runtime.PyList_GetItem(list, i);
string path = Runtime.GetManagedString(item);
if (path != null) {
pypath.Add(path);
}
}
}
}
//===================================================================
// Given an assembly name, try to find this assembly file using the
// PYTHONPATH. If not found, return null to indicate implicit load
// using standard load semantics (app base directory then GAC, etc.)
//===================================================================
static string FindAssembly(string name) {
char sep = Path.DirectorySeparatorChar;
string path;
string temp;
for (int i = 0; i < pypath.Count; i++) {
string head = pypath[i];
if (head == null || head.Length == 0) {
path = name;
}
else {
path = head + sep + name;
}
temp = path + ".dll";
if (File.Exists(temp)) {
return temp;
}
temp = path + ".exe";
if (File.Exists(temp)) {
return temp;
}
}
return null;
}
//===================================================================
// Loads an assembly from the application directory or the GAC
// given a simple assembly name. Returns the assembly if loaded.
//===================================================================
public static Assembly LoadAssembly(string name) {
Assembly assembly = null;
try {
assembly = Assembly.LoadWithPartialName(name);
}
catch {
}
return assembly;
}
//===================================================================
// Loads an assembly using an augmented search path (the python path).
//===================================================================
public static Assembly LoadAssemblyPath(string name) {
string path = FindAssembly(name);
Assembly assembly = null;
if (path != null) {
try { assembly = Assembly.LoadFrom(path); }
catch {}
}
return assembly;
}
//===================================================================
// Given a qualified name of the form A.B.C.D, attempt to load
// an assembly named after each of A.B.C.D, A.B.C, A.B, A. This
// will only actually probe for the assembly once for each unique
// namespace. Returns true if any assemblies were loaded.
//===================================================================
public static bool LoadImplicit(string name) {
string[] names = name.Split('.');
bool loaded = false;
string s = "";
for (int i = 0; i < names.Length; i++) {
s = (i == 0) ? names[0] : s + "." + names[i];
if (probed[s] == null) {
if (LoadAssemblyPath(s) != null){
loaded = true;
}
else if (LoadAssembly(s) != null) {
loaded = true;
}
probed[s] = 1;
}
}
return loaded;
}
//===================================================================
// Scans an assembly for exported namespaces, adding them to the
// mapping of valid namespaces. Note that for a given namespace
// a.b.c.d, each of a, a.b, a.b.c and a.b.c.d are considered to
// be valid namespaces (to better match Python import semantics).
//===================================================================
static void ScanAssembly(Assembly assembly) {
// TODO: this is a workaround for a current Mono bug: calling
// GetTypes on a generated assembly will cause it to fall over.
// For now we'll skip generated assemblies, which usually are
// uninteresting support code anyway.
if (assembly is AssemblyBuilder) {
return;
}
Type[] types = assembly.GetTypes();
for (int i = 0; i < types.Length; i++) {
string type_ns = types[i].Namespace;
if ((type_ns != null) && (!namespaces.ContainsKey(type_ns))) {
string[] names = type_ns.Split('.');
string s = "";
for (int n = 0; n < names.Length; n++) {
s = (n == 0) ? names[0] : s + "." + names[n];
if (!namespaces.ContainsKey(s)) {
namespaces.Add(s, String.Empty);
}
}
}
}
}
//===================================================================
// Returns true if the given qualified name matches a namespace
// exported by an assembly loaded in the current app domain.
//===================================================================
public static bool IsValidNamespace(string name) {
return namespaces.ContainsKey(name);
}
//===================================================================
// Returns the System.Type object for a given qualified name,
// looking in the currently loaded assemblies for the named
// type. Returns null if the named type cannot be found.
//===================================================================
public static Type LookupType(string qualifiedName) {
for (int i = 0; i < assemblies.Count; i++) {
Assembly assembly = (Assembly)assemblies[i];
Type type = assembly.GetType(qualifiedName);
if (type != null) {
return type;
}
}
return null;
}
}
}

Просмотреть файл

@ -0,0 +1,173 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Collections;
using System.Reflection;
using System.Security;
using System.Runtime.InteropServices;
namespace Python.Runtime {
/// <summary>
/// Base class for Python types that reflect managed types / classes.
/// Concrete subclasses include ClassObject and DelegateObject. This
/// class provides common attributes and common machinery for doing
/// class initialization (initialization of the class __dict__). The
/// concrete subclasses provide slot implementations appropriate for
/// each variety of reflected type.
/// </summary>
internal class ClassBase : ManagedType {
internal bool is_exception;
internal Indexer indexer;
internal Type type;
internal ClassBase(Type tp) : base() {
is_exception = false;
indexer = null;
type = tp;
}
internal virtual bool CanSubclass() {
return (!this.type.IsEnum);
}
//====================================================================
// Implements __init__ for reflected classes and value types.
//====================================================================
[CallConvCdecl()]
public static int tp_init(IntPtr ob, IntPtr args, IntPtr kw) {
return 0;
}
//====================================================================
// Standard comparison implementation for instances of reflected types.
//====================================================================
[CallConvCdecl()]
public static int tp_compare(IntPtr ob, IntPtr other) {
if (ob == other) {
return 0;
}
CLRObject co1 = GetManagedObject(ob) as CLRObject;
CLRObject co2 = GetManagedObject(other) as CLRObject;
Object o1 = co1.inst;
Object o2 = co2.inst;
if (Object.Equals(o1, o2)) {
return 0;
}
return -1;
}
//====================================================================
// Standard iteration support for instances of reflected types. This
// allows natural iteration over objects that either are IEnumerable
// or themselves support IEnumerator directly.
//====================================================================
[CallConvCdecl()]
public static IntPtr tp_iter(IntPtr ob) {
CLRObject co = GetManagedObject(ob) as CLRObject;
if (co == null) {
return Exceptions.RaiseTypeError("invalid object");
}
IEnumerable e = co.inst as IEnumerable;
IEnumerator o;
if (e != null) {
o = e.GetEnumerator();
}
else {
o = co.inst as IEnumerator;
if (o == null) {
string message = "iteration over non-sequence";
return Exceptions.RaiseTypeError(message);
}
}
return new Iterator(o).pyHandle;
}
//====================================================================
// Standard __hash__ implementation for instances of reflected types.
//====================================================================
[CallConvCdecl()]
public static IntPtr tp_hash(IntPtr ob) {
CLRObject co = GetManagedObject(ob) as CLRObject;
if (co == null) {
return Exceptions.RaiseTypeError("unhashable type");
}
return new IntPtr(co.inst.GetHashCode());
}
//====================================================================
// Standard __str__ implementation for instances of reflected types.
//====================================================================
[CallConvCdecl()]
public static IntPtr tp_str(IntPtr ob) {
CLRObject co = GetManagedObject(ob) as CLRObject;
if (co == null) {
return Exceptions.RaiseTypeError("invalid object");
}
return Runtime.PyString_FromString(co.inst.ToString());
}
//====================================================================
// Default implementations for required Python GC support.
//====================================================================
[CallConvCdecl()]
public static int tp_traverse(IntPtr ob, IntPtr func, IntPtr args) {
return 0;
}
[CallConvCdecl()]
public static int tp_clear(IntPtr ob) {
return 0;
}
[CallConvCdecl()]
public static int tp_is_gc(IntPtr type) {
return 1;
}
//====================================================================
// Standard dealloc implementation for instances of reflected types.
//====================================================================
[CallConvCdecl()]
public static void tp_dealloc(IntPtr ob) {
ManagedType self = GetManagedObject(ob);
IntPtr dict = Marshal.ReadIntPtr(ob, ObjectOffset.ob_dict);
Runtime.Decref(dict);
Runtime.PyObject_GC_UnTrack(self.pyHandle);
Runtime.PyObject_GC_Del(self.pyHandle);
Runtime.Decref(self.tpHandle);
self.gcHandle.Free();
}
}
}

Просмотреть файл

@ -0,0 +1,331 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Runtime.InteropServices;
using System.Collections;
using System.Reflection;
using System.Security;
namespace Python.Runtime {
/// <summary>
/// The ClassManager is responsible for creating and managing instances
/// that implement the Python type objects that reflect managed classes.
///
/// Each managed type reflected to Python is represented by an instance
/// of a concrete subclass of ClassBase. Each instance is associated with
/// a generated Python type object, whose slots point to static methods
/// of the managed instance's class.
/// </summary>
internal class ClassManager {
static Hashtable cache;
static Type dtype;
private ClassManager() {}
static ClassManager() {
cache = new Hashtable();
dtype = typeof(System.Delegate);
}
//====================================================================
// Return the ClassBase-derived instance that implements a particular
// reflected managed type, creating it if it doesn't yet exist.
//====================================================================
internal static ClassBase GetClass(Type type) {
Object ob = cache[type];
if (ob == null) {
ClassBase c = CreateClass(type);
cache.Add(type, c);
return c;
}
return (ClassBase) ob;
}
//====================================================================
// Create a new ClassBase-derived instance that implements a reflected
// managed type. The new object will be associated with a generated
// Python type object.
//====================================================================
private static ClassBase CreateClass(Type type) {
// First, we introspect the managed type and build some class
// information, including generating the member descriptors
// that we'll be putting in the Python class __dict__.
ClassInfo info = GetClassInfo(type);
// Next, select the appropriate managed implementation class.
// Different kinds of types, such as array types or interface
// types, want to vary certain implementation details to make
// sure that the type semantics are consistent in Python.
ClassBase impl;
// Check to see if the given type extends System.Exception. This
// lets us check once (vs. on every lookup) in case we need to
// wrap Exception-derived types in old-style classes
if (type.IsSubclassOf(dtype)) {
impl = new DelegateObject(type);
}
else if (type.IsArray) {
impl = new ArrayObject(type);
}
else if (type.IsInterface) {
impl = new InterfaceObject(type);
}
else {
impl = new ClassObject(type);
if (type == typeof(Exception) || type.IsSubclassOf(typeof(Exception))) {
impl.is_exception = true;
}
}
impl.indexer = info.indexer;
// Now we allocate the Python type object to reflect the given
// managed type, filling the Python type slots with thunks that
// point to the managed methods providing the implementation.
IntPtr tp = TypeManager.GetTypeHandle(impl, type);
impl.tpHandle = tp;
// Finally, initialize the class __dict__ and return the object.
IntPtr dict = Marshal.ReadIntPtr(tp, TypeOffset.tp_dict);
IDictionaryEnumerator iter = info.members.GetEnumerator();
while(iter.MoveNext()) {
ManagedType item = (ManagedType)iter.Value;
string name = (string)iter.Key;
Runtime.PyDict_SetItemString(dict, name, item.pyHandle);
}
// If class has constructors, generate an __doc__ attribute.
ClassObject co = impl as ClassObject;
if (co != null) {
IntPtr doc = co.GetDocString();
Runtime.PyDict_SetItemString(dict, "__doc__", doc);
Runtime.Decref(doc);
}
return impl;
}
private static ClassInfo GetClassInfo(Type type) {
ClassInfo ci = new ClassInfo(type);
Hashtable methods = new Hashtable();
ArrayList list;
MethodInfo meth;
ManagedType ob;
String name;
Object item;
Type tp;
int i, n;
// This is complicated because inheritance in Python is name
// based. We can't just find DeclaredOnly members, because we
// could have a base class A that defines two overloads of a
// method and a class B that defines two more. The name-based
// descriptor Python will find needs to know about inherited
// overloads as well as those declared on the sub class.
BindingFlags flags = BindingFlags.Static |
BindingFlags.Instance |
BindingFlags.Public |
BindingFlags.NonPublic;
MemberInfo[] info = type.GetMembers(flags);
Hashtable local = new Hashtable();
ArrayList items = new ArrayList();
MemberInfo m;
// Loop through once to find out which names are declared
for (i = 0; i < info.Length; i++) {
m = info[i];
if (m.DeclaringType == type) {
local[m.Name] = 1;
}
}
// Now again to filter w/o losing overloaded member info
for (i = 0; i < info.Length; i++) {
m = info[i];
if (local[m.Name] != null) {
items.Add(m);
}
}
if (type.IsInterface) {
// Interface inheritance seems to be a different animal:
// more contractual, less structural. Thus, a Type that
// represents an interface that inherits from another
// interface does not return the inherited interface's
// methods in GetMembers. For example ICollection inherits
// from IEnumerable, but ICollection's GetMemebers does not
// return GetEnumerator.
//
// Not sure if this is the correct way to fix this, but it
// seems to work. Thanks to Bruce Dodson for the fix.
Type[] inheritedInterfaces = type.GetInterfaces();
for (i = 0; i < inheritedInterfaces.Length; ++i) {
Type inheritedType = inheritedInterfaces[i];
MemberInfo[] imembers = inheritedType.GetMembers(flags);
for (n = 0; n < imembers.Length; n++) {
m = imembers[n];
if (local[m.Name] == null) {
items.Add(m);
}
}
}
}
for (i = 0; i < items.Count; i++) {
MemberInfo mi = (MemberInfo)items[i];
switch(mi.MemberType) {
case MemberTypes.Method:
meth = (MethodInfo) mi;
if (!(meth.IsPublic || meth.IsFamily ||
meth.IsFamilyOrAssembly))
continue;
name = meth.Name;
item = methods[name];
if (item == null) {
item = methods[name] = new ArrayList();
}
list = (ArrayList) item;
list.Add(meth);
continue;
case MemberTypes.Property:
PropertyInfo pi = (PropertyInfo) mi;
MethodInfo mm = null;
try {
mm = pi.GetGetMethod(true);
if (mm == null) {
mm = pi.GetSetMethod(true);
}
}
catch (SecurityException) {
// GetGetMethod may try to get a method protected by
// StrongNameIdentityPermission - effectively private.
continue;
}
if (mm == null) {
continue;
}
if (!(mm.IsPublic || mm.IsFamily || mm.IsFamilyOrAssembly))
continue;
// Check for indexer
ParameterInfo[] args = pi.GetIndexParameters();
if (args.GetLength(0) > 0) {
Indexer idx = ci.indexer;
if (idx == null) {
ci.indexer = new Indexer();
idx = ci.indexer;
}
idx.AddProperty(pi);
continue;
}
ob = new PropertyObject(pi);
ci.members[pi.Name] = ob;
continue;
case MemberTypes.Field:
FieldInfo fi = (FieldInfo) mi;
if (!(fi.IsPublic || fi.IsFamily || fi.IsFamilyOrAssembly))
continue;
ob = new FieldObject(fi);
ci.members[mi.Name] = ob;
continue;
case MemberTypes.Event:
EventInfo ei = (EventInfo)mi;
MethodInfo me = ei.GetAddMethod(true);
if (!(me.IsPublic || me.IsFamily || me.IsFamilyOrAssembly))
continue;
ob = new EventObject(ei);
ci.members[ei.Name] = ob;
continue;
case MemberTypes.NestedType:
tp = (Type) mi;
if (!(tp.IsNestedPublic || tp.IsNestedFamily ||
tp.IsNestedFamORAssem))
continue;
ob = ClassManager.GetClass(tp);
ci.members[mi.Name] = ob;
continue;
}
}
IDictionaryEnumerator iter = methods.GetEnumerator();
while(iter.MoveNext()) {
name = (string) iter.Key;
list = (ArrayList) iter.Value;
MethodInfo[] mlist = (MethodInfo[])list.ToArray(
typeof(MethodInfo)
);
ob = new MethodObject(name, mlist);
ci.members[name] = ob;
}
return ci;
}
}
internal class ClassInfo {
internal ClassInfo(Type t) {
members = new Hashtable();
indexer = null;
}
public Hashtable members;
public Indexer indexer;
}
}

Просмотреть файл

@ -0,0 +1,270 @@
// Copyright (c) 2003 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Reflection;
using System.Runtime.InteropServices;
namespace Python.Runtime {
/// <summary>
/// Managed class that provides the implementation for reflected types.
/// Managed classes and value types are represented in Python by actual
/// Python type objects. Each of those type objects is associated with
/// an instance of ClassObject, which provides its implementation.
/// </summary>
internal class ClassObject : ClassBase {
ConstructorBinder binder;
internal ClassObject(Type tp) : base(tp) {
ConstructorInfo[] ctors = type.GetConstructors();
binder = new ConstructorBinder();
for (int i = 0; i < ctors.Length; i++) {
binder.AddMethod(ctors[i]);
}
}
//====================================================================
// Helper to get docstring from reflected constructor info.
//====================================================================
internal IntPtr GetDocString() {
MethodBase[] methods = binder.GetMethods();
string str = "";
for (int i = 0; i < methods.Length; i++) {
if (str.Length > 0)
str += Environment.NewLine;
str += methods[i].ToString();
}
return Runtime.PyString_FromString(str);
}
//====================================================================
// Implements __new__ for reflected classes and value types.
//====================================================================
[CallConvCdecl()]
public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw) {
ClassObject self = GetManagedObject(tp) as ClassObject;
// Sanity check: this ensures a graceful error if someone does
// something intentially wrong like use the managed metatype for
// a class that is not really derived from a managed class.
if (self == null) {
return Exceptions.RaiseTypeError("invalid object");
}
Type type = self.type;
// Primitive types do not have constructors, but they look like
// they do from Python. If the ClassObject represents one of the
// convertible primitive types, just convert the arg directly.
if (type.IsPrimitive || type == typeof(String)) {
if (Runtime.PyTuple_Size(args) != 1) {
Exceptions.SetError(Exceptions.TypeError,
"no constructors match given arguments"
);
return IntPtr.Zero;
}
IntPtr op = Runtime.PyTuple_GetItem(args, 0);
Object result;
if (!Converter.ToManaged(op, type, out result, true)) {
return IntPtr.Zero;
}
return CLRObject.GetInstHandle(result, tp);
}
if (type.IsAbstract) {
Exceptions.SetError(Exceptions.TypeError,
"cannot instantiate abstract class"
);
return IntPtr.Zero;
}
if (type.IsEnum) {
Exceptions.SetError(Exceptions.TypeError,
"cannot instantiate enumeration"
);
return IntPtr.Zero;
}
Object obj = self.binder.InvokeRaw(IntPtr.Zero, args, kw);
if (obj == null) {
// It is possible for __new__ to be invoked on construction
// of a Python subclass of a managed class, so args may
// reflect more args than are required to instantiate the
// class. So if we cant find a ctor that matches, we'll see
// if there is a default constructor and, if so, assume that
// any extra args are intended for the subclass' __init__.
IntPtr eargs = Runtime.PyTuple_New(0);
obj = self.binder.InvokeRaw(IntPtr.Zero, eargs, kw);
Runtime.Decref(eargs);
if (obj == null) {
return IntPtr.Zero;
}
}
return CLRObject.GetInstHandle(obj, tp);
}
//====================================================================
// Implements __getitem__ for reflected classes and value types.
//====================================================================
[CallConvCdecl()]
public static IntPtr mp_subscript(IntPtr ob, IntPtr idx) {
ManagedType self = GetManagedObject(ob);
IntPtr tp = Runtime.PyObject_TYPE(ob);
ClassBase cls = (ClassBase)GetManagedObject(tp);
if (cls.indexer == null || !cls.indexer.CanGet) {
Exceptions.SetError(Exceptions.TypeError,
"unindexable object"
);
return IntPtr.Zero;
}
// Arg may be a tuple in the case of an indexer with multiple
// parameters. If so, use it directly, else make a new tuple
// with the index arg (method binders expect arg tuples).
IntPtr args = idx;
bool free = false;
if (!Runtime.PyTuple_Check(idx)) {
args = Runtime.PyTuple_New(1);
Runtime.Incref(idx);
Runtime.PyTuple_SetItem(args, 0, idx);
free = true;
}
IntPtr value = IntPtr.Zero;
try {
value = cls.indexer.GetItem(ob, args);
}
finally {
if (free) {
Runtime.Decref(args);
}
}
return value;
}
//====================================================================
// Implements __setitem__ for reflected classes and value types.
//====================================================================
[CallConvCdecl()]
public static int mp_ass_subscript(IntPtr ob, IntPtr idx, IntPtr v) {
ManagedType self = GetManagedObject(ob);
IntPtr tp = Runtime.PyObject_TYPE(ob);
ClassBase cls = (ClassBase)GetManagedObject(tp);
if (cls.indexer == null || !cls.indexer.CanSet) {
Exceptions.SetError(Exceptions.TypeError,
"object doesn't support item assignment x"
);
return -1;
}
// Arg may be a tuple in the case of an indexer with multiple
// parameters. If so, use it directly, else make a new tuple
// with the index arg (method binders expect arg tuples).
IntPtr args = idx;
bool free = false;
if (!Runtime.PyTuple_Check(idx)) {
args = Runtime.PyTuple_New(1);
Runtime.Incref(idx);
Runtime.PyTuple_SetItem(args, 0, idx);
free = true;
}
int i = Runtime.PyTuple_Size(args);
IntPtr real = Runtime.PyTuple_New(i + 1);
for (int n = 0; n < i; n++) {
IntPtr item = Runtime.PyTuple_GetItem(args, n);
Runtime.Incref(item);
Runtime.PyTuple_SetItem(real, n, item);
}
Runtime.Incref(v);
Runtime.PyTuple_SetItem(real, i, v);
try {
cls.indexer.SetItem(ob, real);
}
finally {
Runtime.Decref(real);
if (free) {
Runtime.Decref(args);
}
}
if (Exceptions.ErrorOccurred()) {
return -1;
}
return 0;
}
//====================================================================
// This is a hack. Generally, no managed class is considered callable
// from Python - with the exception of System.Delegate. It is useful
// to be able to call a System.Delegate instance directly, especially
// when working with multicast delegates.
//====================================================================
[CallConvCdecl()]
public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) {
ManagedType self = GetManagedObject(ob);
IntPtr tp = Runtime.PyObject_TYPE(ob);
ClassBase cb = (ClassBase)GetManagedObject(tp);
if (cb.type != typeof(System.Delegate)) {
Exceptions.SetError(Exceptions.TypeError,
"object is not callable");
return IntPtr.Zero;
}
CLRObject co = (CLRObject)ManagedType.GetManagedObject(ob);
Delegate d = co.inst as Delegate;
BindingFlags flags = BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Instance |
BindingFlags.Static;
MethodInfo method = d.GetType().GetMethod("Invoke", flags);
MethodBinder binder = new MethodBinder(method);
return binder.Invoke(ob, args, kw);
}
}
}

Просмотреть файл

@ -0,0 +1,85 @@
// Copyright (c) 2003 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
//============================================================================
// This file is a hand-maintained stub - it implements CLR.dll, which can be
// loaded by a standard CPython interpreter as an extension module. When it
// is loaded, it bootstraps the managed runtime integration layer and defers
// to it do initialization and put the CLR module into sys.modules, etc.
//============================================================================
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 )
.ver 1:0:5000:0
}
.assembly extern Python.Runtime
{
.ver 1:0:0:0
}
.assembly CLR
{
// --- The following custom attribute is added automatically, do not uncomment -------
// .custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(bool,
// bool) = ( 01 00 00 01 00 00 )
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module CLR.dll
// MVID: {01BEB897-1638-4D9D-B01C-3638714A76B4}
.imagebase 0x00400000
.subsystem 0x00000003
.file alignment 512
.corflags 0x00000002
.vtfixup [1] int32 fromunmanaged at VT_01
.data VT_01 = int32(0)
.class public auto ansi beforefieldinit CLRModule
extends [mscorlib]System.Object
{
} // end of class CLRModule
.class public auto ansi beforefieldinit CLRModule
extends [mscorlib]System.Object
{
.method public hidebysig static void
modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl)
initCLR() cil managed
{
.vtentry 1:1
.export [1] as initCLR
// Code size 8 (0x8)
.maxstack 0
IL_0000: call void [Python.Runtime]Python.Runtime.PythonEngine::InitExt()
IL_0005: br.s IL_0007
IL_0007: ret
} // end of method CLRModule::initCLR
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 1
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method CLRModule::.ctor
} // end of class CLRModule

Просмотреть файл

@ -0,0 +1,83 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Collections;
using System.Reflection;
using System.Runtime.InteropServices;
namespace Python.Runtime {
internal class CLRObject : ManagedType {
internal Object inst;
internal CLRObject(Object ob, IntPtr tp) : base() {
IntPtr py = Runtime.PyType_GenericAlloc(tp, 0);
int flags = (int)Marshal.ReadIntPtr(tp, TypeOffset.tp_flags);
if ((flags & TypeFlags.Subclass) != 0) {
IntPtr dict = Marshal.ReadIntPtr(py, ObjectOffset.ob_dict);
if (dict == IntPtr.Zero) {
dict = Runtime.PyDict_New();
Marshal.WriteIntPtr(py, ObjectOffset.ob_dict, dict);
}
}
GCHandle gc = GCHandle.Alloc(this);
Marshal.WriteIntPtr(py, ObjectOffset.magic(), (IntPtr)gc);
this.tpHandle = tp;
this.pyHandle = py;
this.gcHandle = gc;
inst = ob;
//DebugUtil.DumpInst(py);
}
internal static CLRObject GetInstance(Object ob, IntPtr pyType) {
return new CLRObject(ob, pyType);
}
internal static CLRObject GetInstance(Object ob) {
ClassBase cc = ClassManager.GetClass(ob.GetType());
return GetInstance(ob, cc.tpHandle);
}
internal static IntPtr GetInstHandle(Object ob, IntPtr pyType) {
CLRObject co = GetInstance(ob, pyType);
return co.pyHandle;
}
internal static IntPtr GetInstHandle(Object ob, Type type) {
ClassBase cc = ClassManager.GetClass(type);
CLRObject co = GetInstance(ob, cc.tpHandle);
return co.pyHandle;
}
internal static IntPtr GetInstHandle(Object ob) {
CLRObject co = GetInstance(ob);
return co.pyHandle;
}
}
}

Просмотреть файл

@ -0,0 +1,65 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Threading;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Collections;
using System.Reflection;
using System.Reflection.Emit;
namespace Python.Runtime {
/// <summary>
/// Several places in the runtime generate code on the fly to support
/// dynamic functionality. The CodeGenerator class manages the dynamic
/// assembly used for code generation and provides utility methods for
/// certain repetitive tasks.
/// </summary>
internal class CodeGenerator {
static AssemblyBuilder aBuilder;
static ModuleBuilder mBuilder;
static CodeGenerator() {
AssemblyName aname = new AssemblyName();
aname.Name = "__CodeGenerator_Assembly";
AssemblyBuilderAccess aa = AssemblyBuilderAccess.Run;
aBuilder = Thread.GetDomain().DefineDynamicAssembly(aname, aa);
mBuilder = aBuilder.DefineDynamicModule("__CodeGenerator_Module");
}
//====================================================================
// DefineType is a shortcut utility to get a new TypeBuilder.
//====================================================================
internal static TypeBuilder DefineType(string name) {
TypeAttributes attrs = TypeAttributes.Public;
return mBuilder.DefineType(name, attrs);
}
//====================================================================
// DefineType is a shortcut utility to get a new TypeBuilder.
//====================================================================
internal static TypeBuilder DefineType(string name, Type basetype) {
TypeAttributes attrs = TypeAttributes.Public;
return mBuilder.DefineType(name, attrs, basetype);
}
}
}

Просмотреть файл

@ -0,0 +1,71 @@
// Copyright (c) 2003 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Reflection;
namespace Python.Runtime {
//========================================================================
// A ConstructorBinder encapsulates information about one or more managed
// constructors, and is responsible for selecting the right constructor
// given a set of Python arguments. This is slightly different than the
// standard MethodBinder because of a difference in invoking constructors
// using reflection (which is seems to be a CLR bug).
//========================================================================
internal class ConstructorBinder : MethodBinder {
internal ConstructorBinder () : base() {}
//====================================================================
// Constructors get invoked when an instance of a wrapped managed
// class or a subclass of a managed class is created. This differs
// from the MethodBinder implementation in that we return the raw
// result of the constructor rather than wrapping it as a Python
// object - the reason is that only the caller knows the correct
// Python type to use when wrapping the result (may be a subclass).
//====================================================================
internal object InvokeRaw(IntPtr inst, IntPtr args, IntPtr kw) {
Binding binding = this.Bind(inst, args, kw);
Object result;
if (binding == null) {
Exceptions.SetError(Exceptions.TypeError,
"no constructor matches given arguments"
);
return null;
}
// Object construction is presumed to be non-blocking and fast
// enough that we shouldn't really need to release the GIL.
ConstructorInfo ci = (ConstructorInfo)binding.info;
try {
result = ci.Invoke(binding.args);
}
catch (Exception e) {
if (e.InnerException != null) {
e = e.InnerException;
}
Exceptions.SetError(e);
return null;
}
return result;
}
}
}

Просмотреть файл

@ -0,0 +1,668 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Globalization;
using System.Security;
namespace Python.Runtime {
//========================================================================
// Performs data conversions between managed types and Python types.
//========================================================================
[SuppressUnmanagedCodeSecurityAttribute()]
internal class Converter {
private Converter() {}
static NumberFormatInfo nfi;
static Type objectType;
static Type stringType;
static Type int32Type;
static Type int64Type;
static Type flagsType;
static Type boolType;
static Type typeType;
static Converter () {
nfi = NumberFormatInfo.InvariantInfo;
objectType = typeof(Object);
stringType = typeof(String);
int32Type = typeof(Int32);
int64Type = typeof(Int64);
flagsType = typeof(FlagsAttribute);
boolType = typeof(Boolean);
typeType = typeof(Type);
}
//====================================================================
// Return a Python object for the given native object, converting
// basic types (string, int, etc.) into equivalent Python objects.
// This always returns a new reference. Note that the System.Decimal
// type has no Python equivalent and converts to a managed instance.
//====================================================================
internal static IntPtr ToPython(Object value, Type type) {
IntPtr result = IntPtr.Zero;
// Null always converts to None in Python.
if (value == null) {
result = Runtime.PyNone;
Runtime.Incref(result);
return result;
}
// hmm - from Python, we almost never care what the declared
// type is. we'd rather have the object bound to the actual
// implementing class.
type = value.GetType();
TypeCode tc = Type.GetTypeCode(type);
switch(tc) {
case TypeCode.Object:
result = CLRObject.GetInstHandle(value, type);
// XXX - hack to make sure we convert new-style class based
// managed exception instances to wrappers ;(
if (Runtime.wrap_exceptions) {
Exception e = value as Exception;
if (e != null) {
return Exceptions.GetExceptionInstanceWrapper(result);
}
}
return result;
case TypeCode.String:
return Runtime.PyUnicode_FromString((string)value);
case TypeCode.Int32:
return Runtime.PyInt_FromInt32((int)value);
case TypeCode.Boolean:
if ((bool)value) {
Runtime.Incref(Runtime.PyTrue);
return Runtime.PyTrue;
}
Runtime.Incref(Runtime.PyFalse);
return Runtime.PyFalse;
case TypeCode.Byte:
return Runtime.PyInt_FromInt32((int)((byte)value));
case TypeCode.Char:
return Runtime.PyUnicode_FromOrdinal((int)((char)value));
case TypeCode.Int16:
return Runtime.PyInt_FromInt32((int)((short)value));
case TypeCode.Int64:
return Runtime.PyLong_FromLongLong((long)value);
case TypeCode.Single:
// return Runtime.PyFloat_FromDouble((double)((float)value));
string ss = ((float)value).ToString(nfi);
IntPtr ps = Runtime.PyString_FromString(ss);
IntPtr op = Runtime.PyFloat_FromString(ps, IntPtr.Zero);
Runtime.Decref(ps);
return op;
case TypeCode.Double:
return Runtime.PyFloat_FromDouble((double)value);
case TypeCode.SByte:
return Runtime.PyInt_FromInt32((int)((sbyte)value));
case TypeCode.UInt16:
return Runtime.PyInt_FromInt32((int)((ushort)value));
case TypeCode.UInt32:
return Runtime.PyLong_FromUnsignedLong((uint)value);
case TypeCode.UInt64:
return Runtime.PyLong_FromUnsignedLongLong((ulong)value);
default:
result = CLRObject.GetInstHandle(value, type);
return result;
}
}
//====================================================================
// In a few situations, we don't have any advisory type information
// when we want to convert an object to Python.
//====================================================================
internal static IntPtr ToPythonImplicit(Object value) {
if (value == null) {
IntPtr result = Runtime.PyNone;
Runtime.Incref(result);
return result;
}
return ToPython(value, objectType);
}
//====================================================================
// Return a managed object for the given Python object, taking funny
// byref types into account.
//====================================================================
internal static bool ToManaged(IntPtr value, Type type,
out object result, bool setError) {
if (type.IsByRef) {
type = type.GetElementType();
}
return Converter.ToManagedValue(value, type, out result, setError);
}
internal static bool ToManagedValue(IntPtr value, Type obType,
out Object result, bool setError) {
// Common case: if the Python value is a wrapped managed object
// instance, just return the wrapped object.
ManagedType mt = ManagedType.GetManagedObject(value);
result = null;
// XXX - hack to support objects wrapped in old-style classes
// (such as exception objects).
if (Runtime.wrap_exceptions) {
if (mt == null) {
if (Runtime.PyObject_IsInstance(
value, Exceptions.Exception
) > 0) {
IntPtr p = Runtime.PyObject_GetAttrString(value, "_inner");
if (p != IntPtr.Zero) {
// This is safe because we know that the __dict__ of
// value holds a reference to _inner.
value = p;
Runtime.Decref(p);
mt = ManagedType.GetManagedObject(value);
}
}
}
}
if (mt != null) {
if (mt is CLRObject) {
object tmp = ((CLRObject)mt).inst;
if (obType.IsInstanceOfType(tmp)) {
result = tmp;
return true;
}
string err = "value cannot be converted to {0}";
err = String.Format(err, obType);
Exceptions.SetError(Exceptions.TypeError, err);
return false;
}
if (mt is ClassBase) {
result = ((ClassBase)mt).type;
return true;
}
// shouldnt happen
return false;
}
if (value == Runtime.PyNone && !obType.IsValueType) {
result = null;
return true;
}
if (obType.IsArray) {
return ToArray(value, obType, out result, setError);
}
if (obType.IsEnum) {
return ToEnum(value, obType, out result, setError);
}
// Conversion to 'Object' is done based on some reasonable
// default conversions (Python string -> managed string,
// Python int -> Int32 etc.).
if (obType == objectType) {
if (Runtime.IsStringType(value)) {
return ToPrimitive(value, stringType, out result,
setError);
}
else if (Runtime.PyBool_Check(value)) {
return ToPrimitive(value, boolType, out result, setError);
}
else if (Runtime.PyInt_Check(value)) {
return ToPrimitive(value, int32Type, out result, setError);
}
else if (Runtime.PyLong_Check(value)) {
return ToPrimitive(value, int64Type, out result, setError);
}
else if (Runtime.PySequence_Check(value)) {
return ToArray(value, typeof(object[]), out result,
setError);
}
if (setError) {
Exceptions.SetError(Exceptions.TypeError,
"value cannot be converted to Object"
);
}
return false;
}
return ToPrimitive(value, obType, out result, setError);
}
//====================================================================
// Convert a Python value to an instance of a primitive managed type.
//====================================================================
static bool ToPrimitive(IntPtr value, Type obType, out Object result,
bool setError) {
IntPtr overflow = Exceptions.OverflowError;
TypeCode tc = Type.GetTypeCode(obType);
result = null;
IntPtr op;
int ival;
switch(tc) {
case TypeCode.String:
string st = Runtime.GetManagedString(value);
if (st == null) {
goto type_error;
}
result = st;
return true;
case TypeCode.Int32:
// Trickery to support 64-bit platforms.
if (IntPtr.Size == 4) {
op = Runtime.PyNumber_Int(value);
// As of Python 2.3, large ints magically convert :(
if (Runtime.PyLong_Check(op) ) {
Runtime.Decref(op);
goto overflow;
}
if (op == IntPtr.Zero) {
if (Exceptions.ExceptionMatches(overflow)) {
goto overflow;
}
goto type_error;
}
ival = (int)Runtime.PyInt_AsLong(op);
Runtime.Decref(op);
result = ival;
return true;
}
else {
op = Runtime.PyNumber_Long(value);
if (op == IntPtr.Zero) {
if (Exceptions.ExceptionMatches(overflow)) {
goto overflow;
}
goto type_error;
}
long ll = (long)Runtime.PyLong_AsLongLong(op);
Runtime.Decref(op);
if ((ll == -1) && Exceptions.ErrorOccurred()) {
goto overflow;
}
if (ll > Int32.MaxValue || ll < Int32.MinValue) {
goto overflow;
}
result = (int)ll;
return true;
}
case TypeCode.Boolean:
result = (Runtime.PyObject_IsTrue(value) != 0);
return true;
case TypeCode.Byte:
if (Runtime.PyObject_TypeCheck(value, Runtime.PyStringType)) {
if (Runtime.PyString_Size(value) == 1) {
op = Runtime.PyString_AS_STRING(value);
result = (byte)Marshal.ReadByte(op);
return true;
}
goto type_error;
}
op = Runtime.PyNumber_Int(value);
if (op == IntPtr.Zero) {
if (Exceptions.ExceptionMatches(overflow)) {
goto overflow;
}
goto type_error;
}
ival = (int) Runtime.PyInt_AsLong(op);
Runtime.Decref(op);
if (ival > Byte.MaxValue || ival < Byte.MinValue) {
goto overflow;
}
byte b = (byte) ival;
result = b;
return true;
case TypeCode.SByte:
if (Runtime.PyObject_TypeCheck(value, Runtime.PyStringType)) {
if (Runtime.PyString_Size(value) == 1) {
op = Runtime.PyString_AS_STRING(value);
result = (sbyte)Marshal.ReadByte(op);
return true;
}
goto type_error;
}
op = Runtime.PyNumber_Int(value);
if (op == IntPtr.Zero) {
if (Exceptions.ExceptionMatches(overflow)) {
goto overflow;
}
goto type_error;
}
ival = (int) Runtime.PyInt_AsLong(op);
Runtime.Decref(op);
if (ival > SByte.MaxValue || ival < SByte.MinValue) {
goto overflow;
}
sbyte sb = (sbyte) ival;
result = sb;
return true;
case TypeCode.Char:
if (Runtime.PyObject_TypeCheck(value, Runtime.PyStringType)) {
if (Runtime.PyString_Size(value) == 1) {
op = Runtime.PyString_AS_STRING(value);
result = (char)Marshal.ReadByte(op);
return true;
}
goto type_error;
}
else if (Runtime.PyObject_TypeCheck(value,
Runtime.PyUnicodeType)) {
if (Runtime.PyUnicode_GetSize(value) == 1) {
op = Runtime.PyUnicode_AS_UNICODE(value);
result = (char)Marshal.ReadInt16(op);
return true;
}
goto type_error;
}
op = Runtime.PyNumber_Int(value);
if (op == IntPtr.Zero) {
goto type_error;
}
ival = Runtime.PyInt_AsLong(op);
if (ival > Char.MaxValue || ival < Char.MinValue) {
goto overflow;
}
Runtime.Decref(op);
result = (char)ival;
return true;
case TypeCode.Int16:
op = Runtime.PyNumber_Int(value);
if (op == IntPtr.Zero) {
if (Exceptions.ExceptionMatches(overflow)) {
goto overflow;
}
goto type_error;
}
ival = (int) Runtime.PyInt_AsLong(op);
Runtime.Decref(op);
if (ival > Int16.MaxValue || ival < Int16.MinValue) {
goto overflow;
}
short s = (short) ival;
result = s;
return true;
case TypeCode.Int64:
op = Runtime.PyNumber_Long(value);
if (op == IntPtr.Zero) {
if (Exceptions.ExceptionMatches(overflow)) {
goto overflow;
}
goto type_error;
}
long l = (long)Runtime.PyLong_AsLongLong(op);
Runtime.Decref(op);
if ((l == -1) && Exceptions.ErrorOccurred()) {
goto overflow;
}
result = l;
return true;
case TypeCode.UInt16:
op = Runtime.PyNumber_Int(value);
if (op == IntPtr.Zero) {
if (Exceptions.ExceptionMatches(overflow)) {
goto overflow;
}
goto type_error;
}
ival = (int) Runtime.PyInt_AsLong(op);
Runtime.Decref(op);
if (ival > UInt16.MaxValue || ival < UInt16.MinValue) {
goto overflow;
}
ushort us = (ushort) ival;
result = us;
return true;
case TypeCode.UInt32:
op = Runtime.PyNumber_Long(value);
if (op == IntPtr.Zero) {
if (Exceptions.ExceptionMatches(overflow)) {
goto overflow;
}
goto type_error;
}
uint ui = (uint)Runtime.PyLong_AsUnsignedLong(op);
Runtime.Decref(op);
if (Exceptions.ErrorOccurred()) {
goto overflow;
}
result = ui;
return true;
case TypeCode.UInt64:
op = Runtime.PyNumber_Long(value);
if (op == IntPtr.Zero) {
if (Exceptions.ExceptionMatches(overflow)) {
goto overflow;
}
goto type_error;
}
ulong ul = (ulong)Runtime.PyLong_AsUnsignedLongLong(op);
Runtime.Decref(op);
if (Exceptions.ErrorOccurred()) {
goto overflow;
}
result = ul;
return true;
case TypeCode.Single:
op = Runtime.PyNumber_Float(value);
if (op == IntPtr.Zero) {
if (Exceptions.ExceptionMatches(overflow)) {
goto overflow;
}
goto type_error;
}
double dd = Runtime.PyFloat_AsDouble(value);
if (dd > Single.MaxValue || dd < Single.MinValue) {
goto overflow;
}
result = (float)dd;
return true;
case TypeCode.Double:
op = Runtime.PyNumber_Float(value);
if (op == IntPtr.Zero) {
goto type_error;
}
double d = Runtime.PyFloat_AsDouble(op);
Runtime.Decref(op);
if (d > Double.MaxValue || d < Double.MinValue) {
goto overflow;
}
result = d;
return true;
}
type_error:
if (setError) {
string format = "'{0}' value cannot be converted to {1}";
string tpName = Runtime.PyObject_GetTypeName(value);
string error = String.Format(format, tpName, obType);
Exceptions.SetError(Exceptions.TypeError, error);
}
return false;
overflow:
if (setError) {
string error = "value too large to convert";
Exceptions.SetError(Exceptions.OverflowError, error);
}
return false;
}
static void SetConversionError(IntPtr value, Type target) {
IntPtr ob = Runtime.PyObject_Repr(value);
string src = Runtime.GetManagedString(ob);
Runtime.Decref(ob);
string error = String.Format(
"Cannot convert {0} to {1}", src, target
);
Exceptions.SetError(Exceptions.TypeError, error);
}
//====================================================================
// Convert a Python value to a correctly typed managed array instance.
// The Python value must support the Python sequence protocol and the
// items in the sequence must be convertible to the target array type.
//====================================================================
static bool ToArray(IntPtr value, Type obType, out Object result,
bool setError) {
Type elementType = obType.GetElementType();
int size = Runtime.PySequence_Size(value);
result = null;
if (size < 0) {
if (setError) {
SetConversionError(value, obType);
}
return false;
}
Array items = Array.CreateInstance(elementType, size);
for (int i = 0; i < size; i++) {
Object obj = null;
IntPtr item = Runtime.PySequence_GetItem(value, i);
if (item == IntPtr.Zero) {
if (setError) {
SetConversionError(value, obType);
return false;
}
}
if (!Converter.ToManaged(item, elementType, out obj, true)) {
Runtime.Decref(item);
return false;
}
items.SetValue(obj, i);
Runtime.Decref(item);
}
result = items;
return true;
}
//====================================================================
// Convert a Python value to a correctly typed managed enum instance.
//====================================================================
static bool ToEnum(IntPtr value, Type obType, out Object result,
bool setError) {
Type etype = Enum.GetUnderlyingType(obType);
result = null;
if (!ToPrimitive(value, etype, out result, setError)) {
return false;
}
if (Enum.IsDefined(obType, result)) {
result = Enum.ToObject(obType, result);
return true;
}
if (obType.GetCustomAttributes(flagsType, true).Length > 0) {
result = Enum.ToObject(obType, result);
return true;
}
if (setError) {
string error = "invalid enumeration value";
Exceptions.SetError(Exceptions.ValueError, error);
}
return false;
}
}
}

Просмотреть файл

@ -0,0 +1,123 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Collections;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Threading;
namespace Python.Runtime {
/// <summary>
/// Debugging helper utilities.
/// </summary>
internal class DebugUtil {
public static void Print(string msg, params IntPtr[] args) {
string result = msg;
result += " ";
for (int i = 0; i < args.Length; i++) {
if (args[i] == IntPtr.Zero) {
Console.WriteLine("null arg to print");
}
IntPtr ob = Runtime.PyObject_Repr(args[i]);
result += Runtime.GetManagedString(ob);
Runtime.Decref(ob);
result += " ";
}
Console.WriteLine(result);
return;
}
internal static void DumpType(IntPtr type) {
IntPtr op = Marshal.ReadIntPtr(type, TypeOffset.tp_name);
string name = Marshal.PtrToStringAnsi(op);
Console.WriteLine("Dump type: {0}", name);
op = Marshal.ReadIntPtr(type, TypeOffset.ob_type);
DebugUtil.Print(" type: ", op);
op = Marshal.ReadIntPtr(type, TypeOffset.tp_base);
DebugUtil.Print(" base: ", op);
op = Marshal.ReadIntPtr(type, TypeOffset.tp_bases);
DebugUtil.Print(" bases: ", op);
//op = Marshal.ReadIntPtr(type, TypeOffset.tp_mro);
//DebugUtil.Print(" mro: ", op);
FieldInfo[] slots = typeof(TypeOffset).GetFields();
int size = IntPtr.Size;
for (int i = 0; i < slots.Length; i++) {
int offset = i * size;
name = slots[i].Name;
op = Marshal.ReadIntPtr(type, offset);
Console.WriteLine(" {0}: {1}", name, op);
}
Console.WriteLine("");
Console.WriteLine("");
op = Marshal.ReadIntPtr(type, TypeOffset.tp_dict);
if (op == IntPtr.Zero) {
Console.WriteLine(" dict: null");
}
else {
DebugUtil.Print(" dict: ", op);
}
}
internal static void DumpInst(IntPtr ob) {
IntPtr tp = Runtime.PyObject_TYPE(ob);
int sz = (int)Marshal.ReadIntPtr(tp, TypeOffset.tp_basicsize);
for (int i = 0; i < sz; i += IntPtr.Size) {
IntPtr pp = new IntPtr(ob.ToInt64() + i);
IntPtr v = Marshal.ReadIntPtr(pp);
Console.WriteLine("offset {0}: {1}", i, v);
}
Console.WriteLine("");
Console.WriteLine("");
}
internal static void debug(string msg) {
StackTrace st = new StackTrace(1, true);
StackFrame sf = st.GetFrame(0);
MethodBase mb = sf.GetMethod();
Type mt = mb.DeclaringType;
string caller = mt.Name + "." + sf.GetMethod().Name;
Thread t = Thread.CurrentThread;
string tid = t.GetHashCode().ToString();
Console.WriteLine("thread {0} : {1}", tid, caller);
Console.WriteLine(" {0}", msg);
return;
}
}
}

Просмотреть файл

@ -0,0 +1,286 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Threading;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Collections;
using System.Reflection;
using System.Reflection.Emit;
namespace Python.Runtime {
/// <summary>
/// The DelegateManager class manages the creation of true managed
/// delegate instances that dispatch calls to Python methods.
/// </summary>
internal class DelegateManager {
static Hashtable cache;
static Type basetype;
static Type listtype;
static Type voidtype;
static Type typetype;
static Type ptrtype;
static DelegateManager() {
basetype = typeof(Dispatcher);
listtype = typeof(ArrayList);
voidtype = typeof(void);
typetype = typeof(Type);
ptrtype = typeof(IntPtr);
cache = new Hashtable();
}
//====================================================================
// Given a true delegate instance, return the PyObject handle of the
// Python object implementing the delegate (or IntPtr.Zero if the
// delegate is not implemented in Python code.
//====================================================================
public static IntPtr GetPythonHandle(Delegate d) {
if ((d != null) && (d.Target is Dispatcher)) {
Dispatcher disp = d.Target as Dispatcher;
return disp.target;
}
return IntPtr.Zero;
}
//====================================================================
// GetDispatcher is responsible for creating a class that provides
// an appropriate managed callback method for a given delegate type.
//====================================================================
private static Type GetDispatcher(Type dtype) {
// If a dispatcher type for the given delegate type has already
// been generated, get it from the cache. The cache maps delegate
// types to generated dispatcher types. A possible optimization
// for the future would be to generate dispatcher types based on
// unique signatures rather than delegate types, since multiple
// delegate types with the same sig could use the same dispatcher.
Object item = cache[dtype];
if (item != null) {
return (Type)item;
}
string name = "__" + dtype.FullName + "Dispatcher";
name = name.Replace('.', '_');
name = name.Replace('+', '_');
TypeBuilder tb = CodeGenerator.DefineType(name, basetype);
// Generate a constructor for the generated type that calls the
// appropriate constructor of the Dispatcher base type.
MethodAttributes ma = MethodAttributes.Public |
MethodAttributes.HideBySig |
MethodAttributes.SpecialName |
MethodAttributes.RTSpecialName;
CallingConventions cc = CallingConventions.Standard;
Type[] args = {ptrtype, typetype};
ConstructorBuilder cb = tb.DefineConstructor(ma, cc, args);
ConstructorInfo ci = basetype.GetConstructor(args);
ILGenerator il = cb.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldarg_2);
il.Emit(OpCodes.Call, ci);
il.Emit(OpCodes.Ret);
// Method generation: we generate a method named "Invoke" on the
// dispatcher type, whose signature matches the delegate type for
// which it is generated. The method body simply packages the
// arguments and hands them to the Dispatch() method, which deals
// with converting the arguments, calling the Python method and
// converting the result of the call.
MethodInfo method = dtype.GetMethod("Invoke");
ParameterInfo[] pi = method.GetParameters();
Type[] signature = new Type[pi.Length];
for (int i = 0; i < pi.Length; i++) {
signature[i] = pi[i].ParameterType;
}
MethodBuilder mb = tb.DefineMethod(
"Invoke",
MethodAttributes.Public,
method.ReturnType,
signature
);
ConstructorInfo ctor = listtype.GetConstructor(Type.EmptyTypes);
MethodInfo dispatch = basetype.GetMethod("Dispatch");
MethodInfo add = listtype.GetMethod("Add");
il = mb.GetILGenerator();
il.DeclareLocal(listtype);
il.Emit(OpCodes.Newobj, ctor);
il.Emit(OpCodes.Stloc_0);
for (int c = 0; c < signature.Length; c++) {
Type t = signature[c];
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Ldarg_S, (byte)(c + 1));
if (t.IsValueType) {
il.Emit(OpCodes.Box, t);
}
il.Emit(OpCodes.Callvirt, add);
il.Emit(OpCodes.Pop);
}
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldloc_0);
il.Emit(OpCodes.Call, dispatch);
if (method.ReturnType == voidtype) {
il.Emit(OpCodes.Pop);
}
il.Emit(OpCodes.Ret);
Type disp = tb.CreateType();
cache[dtype] = disp;
return disp;
}
//====================================================================
// Given a delegate type and a callable Python object, GetDelegate
// returns an instance of the delegate type. The delegate instance
// returned will dispatch calls to the given Python object.
//====================================================================
internal static Delegate GetDelegate(Type dtype, IntPtr callable) {
Type dispatcher = GetDispatcher(dtype);
object[] args = {callable, dtype};
object o = Activator.CreateInstance(dispatcher, args);
return Delegate.CreateDelegate(dtype, o, "Invoke");
}
}
/* When a delegate instance is created that has a Python implementation,
the delegate manager generates a custom subclass of Dispatcher and
instantiates it, passing the IntPtr of the Python callable.
The "real" delegate is created using CreateDelegate, passing the
instance of the generated type and the name of the (generated)
implementing method (Invoke).
The true delegate instance holds the only reference to the dispatcher
instance, which ensures that when the delegate dies, the finalizer
of the referenced instance will be able to decref the Python
callable.
A possible alternate strategy would be to create custom subclasses
of the required delegate type, storing the IntPtr in it directly.
This would be slightly cleaner, but I'm not sure if delegates are
too "special" for this to work. It would be more work, so for now
the 80/20 rule applies :)
*/
public class Dispatcher {
public IntPtr target;
public Type dtype;
public Dispatcher(IntPtr target, Type dtype) {
Runtime.Incref(target);
this.target = target;
this.dtype = dtype;
}
~Dispatcher() {
// Note: the managed GC thread can run and try to free one of
// these *after* the Python runtime has been finalized!
if (Runtime.Py_IsInitialized() > 0) {
IntPtr gs = PythonEngine.AcquireLock();
Runtime.Decref(target);
PythonEngine.ReleaseLock(gs);
}
}
public object Dispatch(ArrayList args) {
IntPtr gs = PythonEngine.AcquireLock();
object ob = null;
try {
ob = TrueDispatch(args);
}
catch (Exception e) {
PythonEngine.ReleaseLock(gs);
throw e;
}
PythonEngine.ReleaseLock(gs);
return ob;
}
public object TrueDispatch(ArrayList args) {
MethodInfo method = dtype.GetMethod("Invoke");
ParameterInfo[] pi = method.GetParameters();
IntPtr pyargs = Runtime.PyTuple_New(pi.Length);
Type rtype = method.ReturnType;
for (int i = 0; i < pi.Length; i++) {
// Here we own the reference to the Python value, and we
// give the ownership to the arg tuple.
IntPtr arg = Converter.ToPython(args[i], pi[i].ParameterType);
int r = Runtime.PyTuple_SetItem(pyargs, i, arg);
}
IntPtr op = Runtime.PyObject_Call(target, pyargs, IntPtr.Zero);
Runtime.Decref(pyargs);
if (op == IntPtr.Zero) {
PythonException e = new PythonException();
throw e;
}
if (rtype == typeof(void)) {
return null;
}
Object result = null;
if (!Converter.ToManaged(op, rtype, out result, false)) {
string s = "could not convert Python result to " +
rtype.ToString();
Runtime.Decref(op);
throw new ConversionException(s);
}
Runtime.Decref(op);
return result;
}
}
public class ConversionException : System.Exception {
public ConversionException() : base() {}
public ConversionException(string msg) : base(msg) {}
}
}

Просмотреть файл

@ -0,0 +1,125 @@
// Copyright (c) 2003 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Reflection;
namespace Python.Runtime {
/// <summary>
/// Managed class that provides the implementation for reflected delegate
/// types. Delegates are represented in Python by generated type objects.
/// Each of those type objects is associated an instance of this class,
/// which provides its implementation.
/// </summary>
internal class DelegateObject : ClassBase {
MethodBinder binder;
internal DelegateObject(Type tp) : base(tp) {
binder = new MethodBinder(tp.GetMethod("Invoke"));
}
//====================================================================
// Given a PyObject pointer to an instance of a delegate type, return
// the true managed delegate the Python object represents (or null).
//====================================================================
private static Delegate GetTrueDelegate(IntPtr op) {
CLRObject o = GetManagedObject(op) as CLRObject;
if (o != null) {
Delegate d = o.inst as Delegate;
return d;
}
return null;
}
internal override bool CanSubclass() {
return false;
}
//====================================================================
// DelegateObject __new__ implementation. The result of this is a new
// PyObject whose type is DelegateObject and whose ob_data is a handle
// to an actual delegate instance. The method wrapped by the actual
// delegate instance belongs to an object generated to relay the call
// to the Python callable passed in.
//====================================================================
[CallConvCdecl()]
public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw) {
DelegateObject self = (DelegateObject)GetManagedObject(tp);
if (Runtime.PyTuple_Size(args) != 1) {
string message = "class takes exactly one argument";
return Exceptions.RaiseTypeError(message);
}
IntPtr method = Runtime.PyTuple_GetItem(args, 0);
if (Runtime.PyCallable_Check(method) != 1) {
return Exceptions.RaiseTypeError("argument must be callable");
}
Delegate d = DelegateManager.GetDelegate(self.type, method);
return CLRObject.GetInstHandle(d, self.pyHandle);
}
//====================================================================
// Implements __call__ for reflected delegate types.
//====================================================================
[CallConvCdecl()]
public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) {
// todo: add fast type check!
IntPtr pytype = Runtime.PyObject_TYPE(ob);
DelegateObject self = (DelegateObject)GetManagedObject(pytype);
CLRObject o = GetManagedObject(ob) as CLRObject;
if (o == null) {
return Exceptions.RaiseTypeError("invalid argument");
}
Delegate d = o.inst as Delegate;
if (d == null) {
return Exceptions.RaiseTypeError("invalid argument");
}
return self.binder.Invoke(ob, args, kw);
}
//====================================================================
// Implements __cmp__ for reflected delegate types.
//====================================================================
[CallConvCdecl()]
public static new int tp_compare(IntPtr ob, IntPtr other) {
Delegate d1 = GetTrueDelegate(ob);
Delegate d2 = GetTrueDelegate(other);
if (d1 == d2) {
return 0;
}
return -1;
}
}
}

Просмотреть файл

@ -0,0 +1,139 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
namespace Python.Runtime {
//========================================================================
// Implements a Python event binding type, similar to a method binding.
//========================================================================
internal class EventBinding : ExtensionType {
EventObject e;
IntPtr target;
public EventBinding(EventObject e, IntPtr target) : base() {
Runtime.Incref(target);
this.target = target;
this.e = e;
}
//====================================================================
// EventBinding += operator implementation.
//====================================================================
[CallConvCdecl()]
public static IntPtr nb_inplace_add(IntPtr ob, IntPtr arg) {
EventBinding self = (EventBinding)GetManagedObject(ob);
if (Runtime.PyCallable_Check(arg) < 1) {
Exceptions.SetError(Exceptions.TypeError,
"event handlers must be callable"
);
return IntPtr.Zero;
}
if(!self.e.AddEventHandler(self.target, arg)) {
return IntPtr.Zero;
}
Runtime.Incref(self.pyHandle);
return self.pyHandle;
}
//====================================================================
// EventBinding -= operator implementation.
//====================================================================
[CallConvCdecl()]
public static IntPtr nb_inplace_subtract(IntPtr ob, IntPtr arg) {
EventBinding self = (EventBinding)GetManagedObject(ob);
if (Runtime.PyCallable_Check(arg) < 1) {
Exceptions.SetError(Exceptions.TypeError,
"invalid event handler"
);
return IntPtr.Zero;
}
if (!self.e.RemoveEventHandler(self.target, arg)) {
return IntPtr.Zero;
}
Runtime.Incref(self.pyHandle);
return self.pyHandle;
}
//====================================================================
// EventBinding __hash__ implementation.
//====================================================================
[CallConvCdecl()]
public static IntPtr tp_hash(IntPtr ob) {
EventBinding self = (EventBinding)GetManagedObject(ob);
long x = 0;
long y = 0;
if (self.target != IntPtr.Zero) {
x = Runtime.PyObject_Hash(self.target).ToInt64();
if (x == -1) {
return new IntPtr(-1);
}
}
y = Runtime.PyObject_Hash(self.e.pyHandle).ToInt64();
if (y == -1) {
return new IntPtr(-1);
}
x ^= y;
if (x == -1) {
x = -1;
}
return new IntPtr(x);
}
//====================================================================
// EventBinding __repr__ implementation.
//====================================================================
[CallConvCdecl()]
public static IntPtr tp_repr(IntPtr ob) {
EventBinding self = (EventBinding)GetManagedObject(ob);
string type = (self.target == IntPtr.Zero) ? "unbound" : "bound";
string s = String.Format("<{0} event '{1}'>", type, self.e.name);
return Runtime.PyString_FromString(s);
}
//====================================================================
// EventBinding dealloc implementation.
//====================================================================
[CallConvCdecl()]
public static new void tp_dealloc(IntPtr ob) {
EventBinding self = (EventBinding)GetManagedObject(ob);
Runtime.Decref(self.target);
ExtensionType.FinalizeObject(self);
}
}
}

Просмотреть файл

@ -0,0 +1,236 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Collections;
using System.Reflection;
namespace Python.Runtime {
//========================================================================
// Implements a Python descriptor type that provides access to CLR events.
//========================================================================
internal class EventObject : ExtensionType {
internal string name;
internal EventBinding unbound;
internal EventInfo info;
internal Hashtable reg;
public EventObject(EventInfo info) : base() {
this.name = info.Name;
this.info = info;
}
//====================================================================
// Register a new Python object event handler with the event.
//====================================================================
internal bool AddEventHandler(IntPtr target, IntPtr handler) {
Object obj = null;
if (target != IntPtr.Zero) {
CLRObject co = (CLRObject)ManagedType.GetManagedObject(target);
obj = co.inst;
}
// Create a true delegate instance of the appropriate type to
// wrap the Python handler. Note that wrapper delegate creation
// always succeeds, though calling the wrapper may fail.
Type type = this.info.EventHandlerType;
Delegate d = DelegateManager.GetDelegate(type, handler);
// Now register the handler in a mapping from instance to pairs
// of (handler hash, delegate) so we can lookup to remove later.
// All this is done lazily to avoid overhead until an event is
// actually subscribed to by a Python event handler.
if (reg == null) {
reg = new Hashtable();
}
object key = (obj != null) ? obj : this.info.ReflectedType;
ArrayList list = reg[key] as ArrayList;
if (list == null) {
list = new ArrayList();
reg[key] = list;
}
list.Add(new Handler(Runtime.PyObject_Hash(handler), d));
// Note that AddEventHandler helper only works for public events,
// so we have to get the underlying add method explicitly.
object[] args = { d };
MethodInfo mi = this.info.GetAddMethod(true);
mi.Invoke(obj, BindingFlags.Default, null, args, null);
return true;
}
//====================================================================
// Remove the given Python object event handler.
//====================================================================
internal bool RemoveEventHandler(IntPtr target, IntPtr handler) {
Object obj = null;
if (target != IntPtr.Zero) {
CLRObject co = (CLRObject)ManagedType.GetManagedObject(target);
obj = co.inst;
}
IntPtr hash = Runtime.PyObject_Hash(handler);
if (Exceptions.ErrorOccurred() || (reg == null)) {
Exceptions.SetError(Exceptions.ValueError,
"unknown event handler"
);
return false;
}
object key = (obj != null) ? obj : this.info.ReflectedType;
ArrayList list = reg[key] as ArrayList;
if (list == null) {
Exceptions.SetError(Exceptions.ValueError,
"unknown event handler"
);
return false;
}
object[] args = { null };
MethodInfo mi = this.info.GetRemoveMethod(true);
for (int i = 0; i < list.Count; i++) {
Handler item = (Handler)list[i];
if (item.hash != hash) {
continue;
}
args[0] = item.del;
try {
mi.Invoke(obj, BindingFlags.Default, null, args, null);
}
catch {
continue;
}
list.RemoveAt(i);
return true;
}
Exceptions.SetError(Exceptions.ValueError,
"unknown event handler"
);
return false;
}
//====================================================================
// Descriptor __get__ implementation. A getattr on an event returns
// a "bound" event that keeps a reference to the object instance.
//====================================================================
[CallConvCdecl()]
public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) {
EventObject self = GetManagedObject(ds) as EventObject;
EventBinding binding;
if (self == null) {
return Exceptions.RaiseTypeError("invalid argument");
}
// If the event is accessed through its type (rather than via
// an instance) we return an 'unbound' EventBinding that will
// be cached for future accesses through the type.
if (ob == IntPtr.Zero) {
if (self.unbound == null) {
self.unbound = new EventBinding(self, IntPtr.Zero);
}
binding = self.unbound;
Runtime.Incref(binding.pyHandle);
return binding.pyHandle;
}
if (Runtime.PyObject_IsInstance(ob, tp) < 1) {
return Exceptions.RaiseTypeError("invalid argument");
}
binding = new EventBinding(self, ob);
return binding.pyHandle;
}
//====================================================================
// Descriptor __set__ implementation. This actually never allows you
// to set anything; it exists solely to support the '+=' spelling of
// event handler registration. The reason is that given code like:
// 'ob.SomeEvent += method', Python will attempt to set the attribute
// SomeEvent on ob to the result of the '+=' operation.
//====================================================================
[CallConvCdecl()]
public static new int tp_descr_set(IntPtr ds, IntPtr ob, IntPtr val) {
EventBinding e = GetManagedObject(val) as EventBinding;
if (e != null) {
return 0;
}
string message = "cannot set event attributes";
Exceptions.RaiseTypeError(message);
return -1;
}
//====================================================================
// Descriptor __repr__ implementation.
//====================================================================
[CallConvCdecl()]
public static IntPtr tp_repr(IntPtr ob) {
EventObject self = (EventObject)GetManagedObject(ob);
string s = String.Format("<event '{0}'>", self.name);
return Runtime.PyString_FromString(s);
}
//====================================================================
// Descriptor dealloc implementation.
//====================================================================
[CallConvCdecl()]
public static new void tp_dealloc(IntPtr ob) {
EventObject self = (EventObject)GetManagedObject(ob);
if (self.unbound != null) {
Runtime.Decref(self.unbound.pyHandle);
}
ExtensionType.FinalizeObject(self);
}
}
internal class Handler {
public IntPtr hash;
public Delegate del;
public Handler(IntPtr hash, Delegate d) {
this.hash = hash;
this.del = d;
}
}
}

Просмотреть файл

@ -0,0 +1,381 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Reflection;
using System.Collections;
using System.Runtime.InteropServices;
namespace Python.Runtime {
/// <summary>
/// Encapsulates the Python exception APIs.
/// </summary>
public class Exceptions {
private Exceptions() {}
//===================================================================
// Initialization performed on startup of the Python runtime.
//===================================================================
internal static void Initialize() {
IntPtr module = Runtime.PyImport_ImportModule("exceptions");
Type type = typeof(Exceptions);
foreach (FieldInfo fi in type.GetFields(BindingFlags.Public |
BindingFlags.Static)) {
IntPtr op = Runtime.PyObject_GetAttrString(module, fi.Name);
if (op != IntPtr.Zero) {
fi.SetValue(type, op);
}
}
Runtime.Decref(module);
Runtime.PyErr_Clear();
if (Runtime.wrap_exceptions) {
SetupExceptionHack();
}
}
//===================================================================
// Cleanup resources upon shutdown of the Python runtime.
//===================================================================
internal static void Shutdown() {
Type type = typeof(Exceptions);
foreach (FieldInfo fi in type.GetFields(BindingFlags.Public |
BindingFlags.Static)) {
IntPtr op = (IntPtr)fi.GetValue(type);
Runtime.Decref(op);
}
}
// Versions of CPython up to 2.4 do not allow exceptions to be
// new-style classes. To get around that restriction and provide
// a consistent user experience for programmers, we wrap managed
// exceptions in an old-style class that (through some dont-try-
// this-at-home hackery) delegates to the managed exception and
// obeys the conventions of both Python and managed exceptions.
static IntPtr ns_exc; // new-style class for System.Exception
static IntPtr os_exc; // old-style class for System.Exception
static Hashtable cache;
internal static void SetupExceptionHack() {
ns_exc = ClassManager.GetClass(typeof(Exception)).pyHandle;
cache = new Hashtable();
string code =
"import exceptions\n" +
"class Exception(exceptions.Exception):\n" +
" _class = None\n" +
" _inner = None\n" +
"\n" +
" def __init__(self, *args, **kw):\n" +
" inst = self.__class__._class(*args, **kw)\n" +
" self.__dict__['_inner'] = inst\n" +
" exceptions.Exception.__init__(self, *args, **kw)\n" +
"\n" +
" def __getattr__(self, name, _marker=[]):\n" +
" inner = self.__dict__['_inner']\n" +
" v = getattr(inner, name, _marker)\n" +
" if v is not _marker:\n" +
" return v\n" +
" v = self.__dict__.get(name, _marker)\n" +
" if v is not _marker:\n" +
" return v\n" +
" raise AttributeError(name)\n" +
"\n" +
" def __setattr__(self, name, value):\n" +
" inner = self.__dict__['_inner']\n" +
" setattr(inner, name, value)\n" +
"\n" +
" def __str__(self):\n" +
" inner = self.__dict__.get('_inner')\n" +
" msg = getattr(inner, 'Message', '')\n" +
" st = getattr(inner, 'StackTrace', '')\n" +
" st = st and '\\n' + st or ''\n" +
" return msg + st\n" +
"\n";
IntPtr dict = Runtime.PyDict_New();
IntPtr builtins = Runtime.PyEval_GetBuiltins();
Runtime.PyDict_SetItemString(dict, "__builtins__", builtins);
IntPtr namestr = Runtime.PyString_FromString("CLR.System");
Runtime.PyDict_SetItemString(dict, "__name__", namestr);
Runtime.Decref(namestr);
Runtime.PyDict_SetItemString(dict, "__file__", Runtime.PyNone);
Runtime.PyDict_SetItemString(dict, "__doc__", Runtime.PyNone);
IntPtr flag = Runtime.Py_file_input;
IntPtr done = Runtime.PyRun_String(code, flag, dict, dict);
os_exc = Runtime.PyDict_GetItemString(dict, "Exception");
Runtime.PyObject_SetAttrString(os_exc, "_class", ns_exc);
Runtime.PyErr_Clear();
}
internal static IntPtr GenerateExceptionClass(IntPtr real) {
if (real == ns_exc) {
return os_exc;
}
IntPtr nbases = Runtime.PyObject_GetAttrString(real, "__bases__");
if (Runtime.PyTuple_Size(nbases) != 1) {
throw new SystemException("Invalid __bases__");
}
IntPtr nsbase = Runtime.PyTuple_GetItem(nbases, 0);
Runtime.Decref(nbases);
IntPtr osbase = GetExceptionClassWrapper(nsbase);
IntPtr baselist = Runtime.PyTuple_New(1);
Runtime.Incref(osbase);
Runtime.PyTuple_SetItem(baselist, 0, osbase);
IntPtr name = Runtime.PyObject_GetAttrString(real, "__name__");
IntPtr dict = Runtime.PyDict_New();
IntPtr mod = Runtime.PyObject_GetAttrString(real, "__module__");
Runtime.PyDict_SetItemString(dict, "__module__", mod);
Runtime.Decref(mod);
IntPtr subc = Runtime.PyClass_New(baselist, dict, name);
Runtime.Decref(baselist);
Runtime.Decref(dict);
Runtime.Decref(name);
Runtime.PyObject_SetAttrString(subc, "_class", real);
return subc;
}
internal static IntPtr GetExceptionClassWrapper(IntPtr real) {
// Given the pointer to a new-style class representing a managed
// exception, return an appropriate old-style class wrapper that
// maintains all of the expectations and delegates to the wrapped
// class.
object ob = cache[real];
if (ob == null) {
IntPtr op = GenerateExceptionClass(real);
cache[real] = op;
return op;
}
return (IntPtr)ob;
}
internal static IntPtr GetExceptionInstanceWrapper(IntPtr real) {
// Given the pointer to a new-style class instance representing a
// managed exception, return an appropriate old-style class
// wrapper instance that delegates to the wrapped instance.
IntPtr tp = Runtime.PyObject_TYPE(real);
if (Runtime.PyObject_TYPE(tp) == Runtime.PyInstanceType) {
return real;
}
// Get / generate a class wrapper, instantiate it and set its
// _inner attribute to the real new-style exception instance.
IntPtr ct = GetExceptionClassWrapper(tp);
IntPtr op = Runtime.PyInstance_NewRaw(ct, IntPtr.Zero);
IntPtr d = Runtime.PyObject_GetAttrString(op, "__dict__");
Runtime.PyDict_SetItemString(d, "_inner", real);
Runtime.Decref(d);
return op;
}
/// <summary>
/// GetException Method
/// </summary>
///
/// <remarks>
/// Retrieve Python exception information as a PythonException
/// instance. The properties of the PythonException may be used
/// to access the exception type, value and traceback info.
/// </remarks>
public static PythonException GetException() {
// TODO: implement this.
return null;
}
/// <summary>
/// ExceptionMatches Method
/// </summary>
///
/// <remarks>
/// Returns true if the current Python exception matches the given
/// Python object. This is a wrapper for PyErr_ExceptionMatches.
/// </remarks>
public static bool ExceptionMatches(IntPtr ob) {
return Runtime.PyErr_ExceptionMatches(ob) != 0;
}
/// <summary>
/// ExceptionMatches Method
/// </summary>
///
/// <remarks>
/// Returns true if the given Python exception matches the given
/// Python object. This is a wrapper for PyErr_GivenExceptionMatches.
/// </remarks>
public static bool ExceptionMatches(IntPtr exc, IntPtr ob) {
int i = Runtime.PyErr_GivenExceptionMatches(exc, ob);
return (i != 0);
}
/// <summary>
/// SetError Method
/// </summary>
///
/// <remarks>
/// Sets the current Python exception given a native string.
/// This is a wrapper for the Python PyErr_SetString call.
/// </remarks>
public static void SetError(IntPtr ob, string value) {
Runtime.PyErr_SetString(ob, value);
}
/// <summary>
/// SetError Method
/// </summary>
///
/// <remarks>
/// Sets the current Python exception given a Python object.
/// This is a wrapper for the Python PyErr_SetObject call.
/// </remarks>
public static void SetError(IntPtr ob, IntPtr value) {
Runtime.PyErr_SetObject(ob, value);
}
/// <summary>
/// SetError Method
/// </summary>
///
/// <remarks>
/// Sets the current Python exception given a CLR exception
/// object. The CLR exception instance is wrapped as a Python
/// object, allowing it to be handled naturally from Python.
/// </remarks>
public static void SetError(Exception e) {
// Because delegates allow arbitrary nestings of Python calling
// managed calling Python calling... etc. it is possible that we
// might get a managed exception raised that is a wrapper for a
// Python exception. In that case we'd rather have the real thing.
PythonException pe = e as PythonException;
if (pe != null) {
Runtime.PyErr_SetObject(pe.Type, pe.Value);
return;
}
IntPtr op = CLRObject.GetInstHandle(e);
// XXX - hack to raise a compatible old-style exception ;(
if (Runtime.wrap_exceptions) {
op = GetExceptionInstanceWrapper(op);
}
IntPtr etype = Runtime.PyObject_GetAttrString(op, "__class__");
Runtime.PyErr_SetObject(etype, op);
Runtime.Decref(etype);
}
/// <summary>
/// ErrorOccurred Method
/// </summary>
///
/// <remarks>
/// Returns true if an exception occurred in the Python runtime.
/// This is a wrapper for the Python PyErr_Occurred call.
/// </remarks>
public static bool ErrorOccurred() {
return Runtime.PyErr_Occurred() != 0;
}
/// <summary>
/// Clear Method
/// </summary>
///
/// <remarks>
/// Clear any exception that has been set in the Python runtime.
/// </remarks>
public static void Clear() {
Runtime.PyErr_Clear();
}
//====================================================================
// Internal helper methods for common error handling scenarios.
//====================================================================
internal static IntPtr RaiseTypeError(string message) {
Exceptions.SetError(Exceptions.TypeError, message);
return IntPtr.Zero;
}
public static IntPtr ArithmeticError;
public static IntPtr AssertionError;
public static IntPtr AttributeError;
public static IntPtr DeprecationWarning;
public static IntPtr EOFError;
public static IntPtr EnvironmentError;
public static IntPtr Exception;
public static IntPtr FloatingPointError;
public static IntPtr IOError;
public static IntPtr ImportError;
public static IntPtr IndentationError;
public static IntPtr IndexError;
public static IntPtr KeyError;
public static IntPtr KeyboardInterrupt;
public static IntPtr LookupError;
public static IntPtr MemoryError;
public static IntPtr NameError;
public static IntPtr NotImplementedError;
public static IntPtr OSError;
public static IntPtr OverflowError;
public static IntPtr OverflowWarning;
public static IntPtr ReferenceError;
public static IntPtr RuntimeError;
public static IntPtr RuntimeWarning;
public static IntPtr StandardError;
public static IntPtr StopIteration;
public static IntPtr SyntaxError;
public static IntPtr SyntaxWarning;
public static IntPtr SystemError;
public static IntPtr SystemExit;
public static IntPtr TabError;
public static IntPtr TypeError;
public static IntPtr UnboundLocalError;
public static IntPtr UnicodeError;
public static IntPtr UserWarning;
public static IntPtr ValueError;
public static IntPtr Warning;
public static IntPtr WindowsError;
public static IntPtr ZeroDivisionError;
}
}

Просмотреть файл

@ -0,0 +1,137 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Runtime.InteropServices;
using System.Collections;
using System.Reflection;
namespace Python.Runtime {
/// <summary>
/// Base class for extensions whose instances *share* a single Python
/// type object, such as the types that represent CLR methods, fields,
/// etc. Instances implemented by this class do not support subtyping.
/// </summary>
internal abstract class ExtensionType : ManagedType {
public ExtensionType() : base() {
// Create a new PyObject whose type is a generated type that is
// implemented by the particuar concrete ExtensionType subclass.
// The Python instance object is related to an instance of a
// particular concrete subclass with a hidden CLR gchandle.
IntPtr tp = TypeManager.GetTypeHandle(this.GetType());
// int rc = (int)Marshal.ReadIntPtr(tp, TypeOffset.ob_refcnt);
// if (rc > 1050) {
// DebugUtil.Print("tp is: ", tp);
// DebugUtil.DumpType(tp);
// }
IntPtr py = Runtime.PyType_GenericAlloc(tp, 0);
GCHandle gc = GCHandle.Alloc(this);
Marshal.WriteIntPtr(py, ObjectOffset.magic(), (IntPtr)gc);
// We have to support gc because the type machinery makes it very
// hard not to - but we really don't have a need for it in most
// concrete extension types, so untrack the object to save calls
// from Python into the managed runtime that are pure overhead.
Runtime.PyObject_GC_UnTrack(py);
this.tpHandle = tp;
this.pyHandle = py;
this.gcHandle = gc;
}
//====================================================================
// Common finalization code to support custom tp_deallocs.
//====================================================================
public static void FinalizeObject(ManagedType self) {
Runtime.PyObject_GC_Del(self.pyHandle);
Runtime.Decref(self.tpHandle);
self.gcHandle.Free();
}
//====================================================================
// Type __setattr__ implementation.
//====================================================================
[CallConvCdecl()]
public static int tp_setattro(IntPtr ob, IntPtr key, IntPtr val) {
string message = "type does not support setting attributes";
if (val == IntPtr.Zero) {
message = "readonly attribute";
}
Exceptions.SetError(Exceptions.TypeError, message);
return -1;
}
//====================================================================
// Default __set__ implementation - this prevents descriptor instances
// being silently replaced in a type __dict__ by default __setattr__.
//====================================================================
[CallConvCdecl()]
public static int tp_descr_set(IntPtr ds, IntPtr ob, IntPtr val) {
string message = "attribute is read-only";
Exceptions.SetError(Exceptions.AttributeError, message);
return -1;
}
//====================================================================
// Required Python GC support.
//====================================================================
[CallConvCdecl()]
public static int tp_traverse(IntPtr ob, IntPtr func, IntPtr args) {
return 0;
}
[CallConvCdecl()]
public static int tp_clear(IntPtr ob) {
return 0;
}
[CallConvCdecl()]
public static int tp_is_gc(IntPtr type) {
return 1;
}
//====================================================================
// Default dealloc implementation.
//====================================================================
[CallConvCdecl()]
public static void tp_dealloc(IntPtr ob) {
// Clean up a Python instance of this extension type. This
// frees the allocated Python object and decrefs the type.
ManagedType self = GetManagedObject(ob);
FinalizeObject(self);
}
}
}

Просмотреть файл

@ -0,0 +1,154 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Collections;
using System.Reflection;
namespace Python.Runtime {
//========================================================================
// Implements a Python descriptor type that provides access to CLR fields.
//========================================================================
internal class FieldObject : ExtensionType {
FieldInfo info;
public FieldObject(FieldInfo info) : base() {
this.info = info;
}
//====================================================================
// Descriptor __get__ implementation. This method returns the
// value of the field on the given object. The returned value
// is converted to an appropriately typed Python object.
//====================================================================
[CallConvCdecl()]
public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) {
FieldObject self = (FieldObject)GetManagedObject(ds);
Object result;
if (self == null) {
return IntPtr.Zero;
}
FieldInfo info = self.info;
if ((ob == IntPtr.Zero) || (ob == Runtime.PyNone)) {
if (!info.IsStatic) {
Exceptions.SetError(Exceptions.TypeError,
"instance attribute must be accessed " +
"through a class instance"
);
return IntPtr.Zero;
}
try {
result = info.GetValue(null);
return Converter.ToPython(result, info.FieldType);
}
catch(Exception e) {
Exceptions.SetError(Exceptions.TypeError, e.Message);
return IntPtr.Zero;
}
}
try {
CLRObject co = (CLRObject)GetManagedObject(ob);
result = info.GetValue(co.inst);
return Converter.ToPython(result, info.FieldType);
}
catch(Exception e) {
Exceptions.SetError(Exceptions.TypeError, e.Message);
return IntPtr.Zero;
}
}
//====================================================================
// Descriptor __set__ implementation. This method sets the value of
// a field based on the given Python value. The Python value must be
// convertible to the type of the field.
//====================================================================
[CallConvCdecl()]
public static new int tp_descr_set(IntPtr ds, IntPtr ob, IntPtr val) {
FieldObject self = (FieldObject)GetManagedObject(ds);
Object newval;
if (self == null) {
return -1;
}
if (val == IntPtr.Zero) {
Exceptions.SetError(Exceptions.TypeError,
"cannot delete field"
);
return -1;
}
FieldInfo info = self.info;
if (info.IsLiteral || info.IsInitOnly) {
Exceptions.SetError(Exceptions.TypeError,
"field is read-only"
);
return -1;
}
bool is_static = info.IsStatic;
if ((ob == IntPtr.Zero) || (ob == Runtime.PyNone)) {
if (!is_static) {
Exceptions.SetError(Exceptions.TypeError,
"instance attribute must be set " +
"through a class instance"
);
return -1;
}
}
if (!Converter.ToManaged(val, info.FieldType, out newval,
true)) {
return -1;
}
try {
if (!is_static) {
CLRObject co = (CLRObject)GetManagedObject(ob);
info.SetValue(co.inst, newval);
}
else {
info.SetValue(null, newval);
}
return 0;
}
catch(Exception e) {
Exceptions.SetError(Exceptions.TypeError, e.Message);
return -1;
}
}
//====================================================================
// Descriptor __repr__ implementation.
//====================================================================
[CallConvCdecl()]
public static IntPtr tp_repr(IntPtr ob) {
FieldObject self = (FieldObject)GetManagedObject(ob);
string s = String.Format("<field '{0}'>", self.info.Name);
return Runtime.PyString_FromStringAndSize(s, s.Length);
}
}
}

Просмотреть файл

@ -0,0 +1,190 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Collections;
namespace Python.Runtime {
//========================================================================
// Implements the "import hook" used to integrate Python with the CLR.
//========================================================================
internal class ImportHook {
static IntPtr py_import;
static ModuleObject root;
static MethodWrapper hook;
//===================================================================
// Initialization performed on startup of the Python runtime.
//===================================================================
internal static void Initialize() {
// Initialize the Python <--> CLR module hook. We replace the
// built-in Python __import__ with our own. This isn't ideal,
// but it provides the most "Pythonic" way of dealing with CLR
// modules (Python doesn't provide a way to emulate packages).
IntPtr dict = Runtime.PyImport_GetModuleDict();
IntPtr mod = Runtime.PyDict_GetItemString(dict, "__builtin__");
py_import = Runtime.PyObject_GetAttrString(mod, "__import__");
hook = new MethodWrapper(typeof(ImportHook), "__import__");
Runtime.PyObject_SetAttrString(mod, "__import__", hook.ptr);
Runtime.Decref(hook.ptr);
root = new ModuleObject("");
Runtime.PyDict_SetItemString(dict, "CLR", root.pyHandle);
}
//===================================================================
// Cleanup resources upon shutdown of the Python runtime.
//===================================================================
internal static void Shutdown() {
Runtime.Decref(root.pyHandle);
Runtime.Decref(py_import);
}
//===================================================================
// The actual import hook that ties Python to the managed world.
//===================================================================
[CallConvCdecl()]
public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw) {
// Replacement for the builtin __import__. The original import
// hook is saved as this.importFunc. This version handles CLR
// import and defers to the normal builtin for everything else.
int num_args = Runtime.PyTuple_Size(args);
if (num_args < 1) {
Exceptions.SetError(
Exceptions.TypeError,
"__import__() takes at least 1 argument (0 given)"
);
return IntPtr.Zero;
}
// borrowed reference
IntPtr py_mod_name = Runtime.PyTuple_GetItem(args, 0);
if ((py_mod_name == IntPtr.Zero) ||
(!Runtime.IsStringType(py_mod_name))) {
Exceptions.SetError(Exceptions.TypeError, "string expected");
return IntPtr.Zero;
}
// If not a CLR module, defer to the standard Python import.
// Could use Python here to avoid a string conversion.
string mod_name = Runtime.GetManagedString(py_mod_name);
if (!(mod_name.StartsWith("CLR.") || mod_name == "CLR")) {
return Runtime.PyObject_Call(py_import, args, kw);
}
// Check whether the import is of the form 'from x import y'.
// This determines whether we return the head or tail module.
bool from_list = false;
if (num_args >= 4) {
IntPtr fromList = Runtime.PyTuple_GetItem(args, 3);
if ((fromList != IntPtr.Zero) &&
(Runtime.PyObject_IsTrue(fromList) == 1)) {
from_list = true;
}
}
// See if sys.modules for this interpreter already has the
// requested module. If so, just return the exising module.
IntPtr sys_modules = Runtime.PyImport_GetModuleDict();
IntPtr module = Runtime.PyDict_GetItem(sys_modules, py_mod_name);
if (module != IntPtr.Zero) {
if (from_list) {
Runtime.Incref(module);
return module;
}
Runtime.Incref(root.pyHandle);
return root.pyHandle;
}
// Now we know we are looking for a CLR module and are likely
// going to have to ask the AssemblyManager. The assembly mgr
// tries really hard not to use Python objects or APIs, because
// parts of it can run recursively and on strange threads, etc.
//
// It does need an opportunity from time to time to check to
// see if sys.path has changed, in a context that is safe. Here
// we know we have the GIL, so we'll let it update if needed.
AssemblyManager.UpdatePath();
// Special case handling: if the qualified module name would
// cause an implicit assembly load, we need to do that first
// to make sure that each of the steps in the qualified name
// is recognized as a valid namespace. Otherwise the import
// process can encounter unknown namespaces before it gets to
// load the assembly that would make them valid.
if (mod_name.StartsWith("CLR.")) {
string real_name = mod_name.Substring(4);
AssemblyManager.LoadImplicit(real_name);
}
// Traverse the qualified module name to get the requested
// module and place references in sys.modules as we go.
string[] names = mod_name.Split('.');
ModuleObject tail = root;
for (int i = 0; i < names.Length; i++) {
string name = names[i];
if (name == "CLR") {
tail = root;
}
else {
ManagedType mt = tail.GetAttribute(name);
if (!(mt is ModuleObject)) {
string error = String.Format("No module named {0}",
name
);
Exceptions.SetError(Exceptions.ImportError, error);
return IntPtr.Zero;
}
tail = (ModuleObject) mt;
}
Runtime.PyDict_SetItemString(
sys_modules, tail.ModuleName, tail.pyHandle
);
}
ModuleObject mod = from_list ? tail : root;
Runtime.Incref(mod.pyHandle);
return mod.pyHandle;
}
}
}

Просмотреть файл

@ -0,0 +1,70 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Collections;
using System.Reflection;
using System.Security.Permissions;
namespace Python.Runtime {
//========================================================================
// Bundles the information required to support an indexer property.
//========================================================================
internal class Indexer {
public MethodBinder GetterBinder;
public MethodBinder SetterBinder;
public Indexer() {
GetterBinder = new MethodBinder();
SetterBinder = new MethodBinder();
}
public bool CanGet {
get {
return GetterBinder.Count > 0;
}
}
public bool CanSet {
get {
return SetterBinder.Count > 0;
}
}
public void AddProperty(PropertyInfo pi) {
MethodInfo getter = pi.GetGetMethod(true);
MethodInfo setter = pi.GetSetMethod(true);
if (getter != null) {
GetterBinder.AddMethod(getter);
}
if (setter != null) {
SetterBinder.AddMethod(setter);
}
}
internal IntPtr GetItem(IntPtr inst, IntPtr args) {
return GetterBinder.Invoke(inst, args, IntPtr.Zero);
}
internal void SetItem(IntPtr inst, IntPtr args) {
SetterBinder.Invoke(inst, args, IntPtr.Zero);
}
}
}

Просмотреть файл

@ -0,0 +1,92 @@
// Copyright (c) 2003 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Reflection;
using System.Runtime.InteropServices;
namespace Python.Runtime {
/// <summary>
/// Provides the implementation for reflected interface types. Managed
/// interfaces are represented in Python by actual Python type objects.
/// Each of those type objects is associated with an instance of this
/// class, which provides the implementation for the Python type.
/// </summary>
internal class InterfaceObject : ClassBase {
internal ConstructorInfo ctor;
internal InterfaceObject(Type tp) : base(tp) {
CoClassAttribute coclass = (CoClassAttribute)
Attribute.GetCustomAttribute(tp, cc_attr);
if (coclass != null) {
ctor = coclass.CoClass.GetConstructor(Type.EmptyTypes);
}
}
static Type cc_attr;
static InterfaceObject() {
cc_attr = typeof(CoClassAttribute);
}
//====================================================================
// Implements __new__ for reflected interface types.
//====================================================================
[CallConvCdecl()]
public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw) {
InterfaceObject self = (InterfaceObject)GetManagedObject(tp);
int nargs = Runtime.PyTuple_Size(args);
Type type = self.type;
Object obj;
if (nargs == 1) {
IntPtr inst = Runtime.PyTuple_GetItem(args, 0);
CLRObject co = GetManagedObject(inst) as CLRObject;
if ((co == null) || (!type.IsInstanceOfType(co.inst))) {
string msg = "object does not implement " + type.Name;
Exceptions.SetError(Exceptions.TypeError, msg);
return IntPtr.Zero;
}
obj = co.inst;
}
else if ((nargs == 0) && (self.ctor != null)) {
obj = self.ctor.Invoke(null);
if (obj == null || !type.IsInstanceOfType(obj)) {
Exceptions.SetError(Exceptions.TypeError,
"CoClass default constructor failed"
);
return IntPtr.Zero;
}
}
else {
Exceptions.SetError(Exceptions.TypeError,
"interface takes exactly one argument"
);
return IntPtr.Zero;
}
return CLRObject.GetInstHandle(obj, self.pyHandle);
}
}
}

Просмотреть файл

@ -0,0 +1,408 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Runtime.InteropServices;
using System.Reflection;
namespace Python.Runtime {
//=======================================================================
// This file defines objects to support binary interop with the Python
// runtime. Generally, the definitions here need to be kept up to date
// when moving to new Python versions.
//=======================================================================
[Serializable()]
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Delegate)]
internal class CallConvCdeclAttribute : Attribute {
public CallConvCdeclAttribute() {}
}
[Serializable()]
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Delegate)]
internal class PythonMethodAttribute : Attribute {
public PythonMethodAttribute() {}
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
internal class ObjectOffset {
static ObjectOffset() {
int size = IntPtr.Size;
ob_refcnt = 0;
ob_type = 1 * size;
ob_dict = 2 * size;
ob_data = 3 * size;
}
public static int magic() {
return ob_data;
}
public static int Size() {
return 4 * IntPtr.Size;
}
public static int ob_refcnt;
public static int ob_type;
public static int ob_dict;
public static int ob_data;
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
internal class TypeOffset {
static TypeOffset() {
Type type = typeof(TypeOffset);
FieldInfo[] fi = type.GetFields();
int size = IntPtr.Size;
for (int i = 0; i < fi.Length; i++) {
fi[i].SetValue(null, i * size);
}
}
public static int magic() {
return ob_size;
}
public static int ob_refcnt = 0;
public static int ob_type = 0;
public static int ob_size = 0;
public static int tp_name = 0;
public static int tp_basicsize = 0;
public static int tp_itemsize = 0;
public static int tp_dealloc = 0;
public static int tp_print = 0;
public static int tp_getattr = 0;
public static int tp_setattr = 0;
public static int tp_compare = 0;
public static int tp_repr = 0;
public static int tp_as_number = 0;
public static int tp_as_sequence = 0;
public static int tp_as_mapping = 0;
public static int tp_hash = 0;
public static int tp_call = 0;
public static int tp_str = 0;
public static int tp_getattro = 0;
public static int tp_setattro = 0;
public static int tp_as_buffer = 0;
public static int tp_flags = 0;
public static int tp_doc = 0;
public static int tp_traverse = 0;
public static int tp_clear = 0;
public static int tp_richcompare = 0;
public static int tp_weaklistoffset = 0;
public static int tp_iter = 0;
public static int tp_iternext = 0;
public static int tp_methods = 0;
public static int tp_members = 0;
public static int tp_getset = 0;
public static int tp_base = 0;
public static int tp_dict = 0;
public static int tp_descr_get = 0;
public static int tp_descr_set = 0;
public static int tp_dictoffset = 0;
public static int tp_init = 0;
public static int tp_alloc = 0;
public static int tp_new = 0;
public static int tp_free = 0;
public static int tp_is_gc = 0;
public static int tp_bases = 0;
public static int tp_mro = 0;
public static int tp_cache = 0;
public static int tp_subclasses = 0;
public static int tp_weaklist = 0;
public static int tp_del = 0;
public static int nb_add = 0;
public static int nb_subtract = 0;
public static int nb_multiply = 0;
public static int nb_divide = 0;
public static int nb_remainder = 0;
public static int nb_divmod = 0;
public static int nb_power = 0;
public static int nb_negative = 0;
public static int nb_positive = 0;
public static int nb_absolute = 0;
public static int nb_nonzero = 0;
public static int nb_invert = 0;
public static int nb_lshift = 0;
public static int nb_rshift = 0;
public static int nb_and = 0;
public static int nb_xor = 0;
public static int nb_or = 0;
public static int nb_coerce = 0;
public static int nb_int = 0;
public static int nb_long = 0;
public static int nb_float = 0;
public static int nb_oct = 0;
public static int nb_hex = 0;
public static int nb_inplace_add = 0;
public static int nb_inplace_subtract = 0;
public static int nb_inplace_multiply = 0;
public static int nb_inplace_divide = 0;
public static int nb_inplace_remainder = 0;
public static int nb_inplace_power = 0;
public static int nb_inplace_lshift = 0;
public static int nb_inplace_rshift = 0;
public static int nb_inplace_and = 0;
public static int nb_inplace_xor = 0;
public static int nb_inplace_or = 0;
public static int nb_floor_divide = 0;
public static int nb_true_divide = 0;
public static int nb_inplace_floor_divide = 0;
public static int nb_inplace_true_divide = 0;
public static int mp_length = 0;
public static int mp_subscript = 0;
public static int mp_ass_subscript = 0;
public static int sq_length = 0;
public static int sq_concat = 0;
public static int sq_repeat = 0;
public static int sq_item = 0;
public static int sq_slice = 0;
public static int sq_ass_item = 0;
public static int sq_ass_slice = 0;
public static int sq_contains = 0;
public static int sq_inplace_concat = 0;
public static int sq_inplace_repeat = 0;
public static int bf_getreadbuffer = 0;
public static int bf_getwritebuffer = 0;
public static int bf_getsegcount = 0;
public static int bf_getcharbuffer = 0;
public static int name = 0;
public static int slots = 0;
public static int members = 0;
}
internal class TypeFlags {
public static int HaveGetCharBuffer = (1 << 0);
public static int HaveSequenceIn = (1 << 1);
public static int GC = 0;
public static int HaveInPlaceOps = (1 << 3);
public static int CheckTypes = (1 << 4);
public static int HaveRichCompare = (1 << 5);
public static int HaveWeakRefs = (1 << 6);
public static int HaveIter = (1 << 7);
public static int HaveClass = (1 << 8);
public static int HeapType = (1 << 9);
public static int BaseType = (1 << 10);
public static int Ready = (1 << 12);
public static int Readying = (1 << 13);
public static int HaveGC = (1 << 14);
public static int Managed = (1 << 29);
public static int Subclass = (1 << 30);
public static int Default = (1 << 0) |
(1 << 1) |
(1 << 3) |
(1 << 5) |
(1 << 6) |
(1 << 7) |
(1 << 8) | 0;
}
// This class defines the function prototypes (delegates) used for low
// level integration with the CPython runtime. It also provides name
// based lookup of the correct prototype for a particular Python type
// slot and utilities for generating method thunks for managed methods.
internal class Interop {
static ArrayList keepAlive;
static Hashtable pmap;
static IntPtr temp;
static Interop() {
// Here we build a mapping of PyTypeObject slot names to the
// appropriate prototype (delegate) type to use for the slot.
Type[] items = typeof(Interop).GetNestedTypes();
Hashtable p = new Hashtable();
for (int i = 0; i < items.Length; i++) {
Type item = items[i];
p[item.Name] = item;
}
keepAlive = new ArrayList();
temp = Marshal.AllocHGlobal(IntPtr.Size);
pmap = new Hashtable();
pmap["tp_dealloc"] = p["DestructorFunc"];
pmap["tp_print"] = p["PrintFunc"];
pmap["tp_getattr"] = p["BinaryFunc"];
pmap["tp_setattr"] = p["ObjObjArgFunc"];
pmap["tp_compare"] = p["ObjObjFunc"];
pmap["tp_repr"] = p["UnaryFunc"];
pmap["tp_hash"] = p["UnaryFunc"];
pmap["tp_call"] = p["TernaryFunc"];
pmap["tp_str"] = p["UnaryFunc"];
pmap["tp_getattro"] = p["BinaryFunc"];
pmap["tp_setattro"] = p["ObjObjArgFunc"];
pmap["tp_traverse"] = p["ObjObjArgFunc"];
pmap["tp_clear"] = p["InquiryFunc"];
pmap["tp_richcompare"] = p["RichCmpFunc"];
pmap["tp_iter"] = p["UnaryFunc"];
pmap["tp_iternext"] = p["UnaryFunc"];
pmap["tp_descr_get"] = p["TernaryFunc"];
pmap["tp_descr_set"] = p["ObjObjArgFunc"];
pmap["tp_init"] = p["ObjObjArgFunc"];
pmap["tp_alloc"] = p["IntArgFunc"];
pmap["tp_new"] = p["TernaryFunc"];
pmap["tp_free"] = p["DestructorFunc"];
pmap["tp_is_gc"] = p["InquiryFunc"];
pmap["nb_add"] = p["BinaryFunc"];
pmap["nb_subtract"] = p["BinaryFunc"];
pmap["nb_multiply"] = p["BinaryFunc"];
pmap["nb_divide"] = p["BinaryFunc"];
pmap["nb_remainder"] = p["BinaryFunc"];
pmap["nb_divmod"] = p["BinaryFunc"];
pmap["nb_power"] = p["TernaryFunc"];
pmap["nb_negative"] = p["UnaryFunc"];
pmap["nb_positive"] = p["UnaryFunc"];
pmap["nb_absolute"] = p["UnaryFunc"];
pmap["nb_nonzero"] = p["InquiryFunc"];
pmap["nb_invert"] = p["UnaryFunc"];
pmap["nb_lshift"] = p["BinaryFunc"];
pmap["nb_rshift"] = p["BinaryFunc"];
pmap["nb_and"] = p["BinaryFunc"];
pmap["nb_xor"] = p["BinaryFunc"];
pmap["nb_or"] = p["BinaryFunc"];
pmap["nb_coerce"] = p["ObjObjFunc"];
pmap["nb_int"] = p["UnaryFunc"];
pmap["nb_long"] = p["UnaryFunc"];
pmap["nb_float"] = p["UnaryFunc"];
pmap["nb_oct"] = p["UnaryFunc"];
pmap["nb_hex"] = p["UnaryFunc"];
pmap["nb_inplace_add"] = p["BinaryFunc"];
pmap["nb_inplace_subtract"] = p["BinaryFunc"];
pmap["nb_inplace_multiply"] = p["BinaryFunc"];
pmap["nb_inplace_divide"] = p["BinaryFunc"];
pmap["nb_inplace_remainder"] = p["BinaryFunc"];
pmap["nb_inplace_power"] = p["TernaryFunc"];
pmap["nb_inplace_lshift"] = p["BinaryFunc"];
pmap["nb_inplace_rshift"] = p["BinaryFunc"];
pmap["nb_inplace_and"] = p["BinaryFunc"];
pmap["nb_inplace_xor"] = p["BinaryFunc"];
pmap["nb_inplace_or"] = p["BinaryFunc"];
pmap["nb_floor_divide"] = p["BinaryFunc"];
pmap["nb_true_divide"] = p["BinaryFunc"];
pmap["nb_inplace_floor_divide"] = p["BinaryFunc"];
pmap["nb_inplace_true_divide"] = p["BinaryFunc"];
pmap["sq_length"] = p["InquiryFunc"];
pmap["sq_concat"] = p["BinaryFunc"];
pmap["sq_repeat"] = p["IntArgFunc"];
pmap["sq_item"] = p["IntArgFunc"];
pmap["sq_slice"] = p["IntIntArgFunc"];
pmap["sq_ass_item"] = p["IntObjArgFunc"];
pmap["sq_ass_slice"] = p["IntIntObjArgFunc"];
pmap["sq_contains"] = p["ObjObjFunc"];
pmap["sq_inplace_concat"] = p["BinaryFunc"];
pmap["sq_inplace_repeat"] = p["IntArgFunc"];
pmap["mp_length"] = p["InquiryFunc"];
pmap["mp_subscript"] = p["BinaryFunc"];
pmap["mp_ass_subscript"] = p["ObjObjArgFunc"];
pmap["bf_getreadbuffer"] = p["IntObjArgFunc"];
pmap["bf_getwritebuffer"] = p["IntObjArgFunc"];
pmap["bf_getsegcount"] = p["ObjObjFunc"];
pmap["bf_getcharbuffer"] = p["IntObjArgFunc"];
pmap["__import__"] = p["TernaryFunc"];
}
internal static Type GetPrototype(string name) {
return pmap[name] as Type;
}
internal static IntPtr GetThunk(MethodInfo method) {
Type dt = Interop.GetPrototype(method.Name);
if (dt != null) {
IntPtr tmp = Marshal.AllocHGlobal(IntPtr.Size);
Delegate d = Delegate.CreateDelegate(dt, method);
Thunk cb = new Thunk(d);
Marshal.StructureToPtr(cb, tmp, false);
IntPtr fp = Marshal.ReadIntPtr(tmp, 0);
Marshal.FreeHGlobal(tmp);
keepAlive.Add(d);
return fp;
}
return IntPtr.Zero;
}
[CallConvCdecl()]
public delegate IntPtr UnaryFunc(IntPtr ob);
[CallConvCdecl()]
public delegate IntPtr BinaryFunc(IntPtr ob, IntPtr arg);
[CallConvCdecl()]
public delegate IntPtr TernaryFunc(IntPtr ob, IntPtr a1, IntPtr a2);
[CallConvCdecl()]
public delegate int InquiryFunc(IntPtr ob);
[CallConvCdecl()]
public delegate IntPtr IntArgFunc(IntPtr ob, int arg);
[CallConvCdecl()]
public delegate IntPtr IntIntArgFunc(IntPtr ob, int a1, int a2);
[CallConvCdecl()]
public delegate int IntObjArgFunc(IntPtr ob, int a1, IntPtr a2);
[CallConvCdecl()]
public delegate int IntIntObjArgFunc(IntPtr o, int a, int b, IntPtr c);
[CallConvCdecl()]
public delegate int ObjObjArgFunc(IntPtr o, IntPtr a, IntPtr b);
[CallConvCdecl()]
public delegate int ObjObjFunc(IntPtr ob, IntPtr arg);
[CallConvCdecl()]
public delegate void DestructorFunc(IntPtr ob);
[CallConvCdecl()]
public delegate int PrintFunc(IntPtr ob, IntPtr a, int b);
[CallConvCdecl()]
public delegate IntPtr RichCmpFunc(IntPtr ob, IntPtr a, int b);
}
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
internal struct Thunk {
public Delegate fn;
public Thunk(Delegate d) {
fn = d;
}
}
}

Просмотреть файл

@ -0,0 +1,71 @@
// ===========================================================================
//
// Copyright (c) 2005 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
//
// ===========================================================================
using System;
namespace Python.Runtime {
//========================================================================
// Internal interface for objects that are convertable to a Python object
// representation. The outputs of this interface are generally expected to
// be platform-compatible pointers meaningful to the CPython runtime.
//========================================================================
internal interface IPythonConvertable {
//=====================================================================
// Given an arbitrary managed object, return a valid PyObject pointer
// or null if the given object cannot be converted to a Python object.
//=====================================================================
IntPtr GetPythonObjectPtr(object o);
//=====================================================================
// Given an arbitrary managed object, return a valid PyType_Object
// pointer representing the Python version of the type of that object,
// or null if the object has no meaningful Python type.
//=====================================================================
IntPtr GetPythonTypePtr(object o);
//=====================================================================
// Given an arbitrary managed type object, return a valid PyType_Object
// pointer representing the Python version of that type, or null if the
// given type cannot be converted to a meaningful Python type.
//=====================================================================
IntPtr GetPythonTypePtr(Type t);
//=====================================================================
// Given an arbitrary python object, return the managed object that
// the python object wraps, or null if the python object does not wrap
// a valid managed object.
//=====================================================================
object GetManagedObject(IntPtr op);
//=====================================================================
// Given an arbitrary python object, return a valid managed Type object
// representing the type of the python wrapper object, or null if the
// python object does not wrap a managed type.
//=====================================================================
Type GetManagedType(IntPtr op);
}
}

Просмотреть файл

@ -0,0 +1,57 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Collections;
using System.Reflection;
namespace Python.Runtime {
//========================================================================
// Implements a generic Python iterator for IEnumerable objects and
// managed array objects. This supports 'for i in object:' in Python.
//========================================================================
internal class Iterator : ExtensionType {
IEnumerator iter;
public Iterator(IEnumerator e) : base() {
this.iter = e;
}
//====================================================================
// Implements support for the Python iteration protocol.
//====================================================================
[CallConvCdecl()]
public static IntPtr tp_iternext(IntPtr ob) {
Iterator self = GetManagedObject(ob) as Iterator;
if (!self.iter.MoveNext()) {
Exceptions.SetError(Exceptions.StopIteration, Runtime.PyNone);
return IntPtr.Zero;
}
object item = self.iter.Current;
return Converter.ToPythonImplicit(item);
}
[CallConvCdecl()]
public static IntPtr tp_iter(IntPtr ob) {
Runtime.Incref(ob);
return ob;
}
}
}

Просмотреть файл

@ -0,0 +1,87 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Runtime.InteropServices;
using System.Collections;
using System.Reflection;
namespace Python.Runtime {
//========================================================================
// Common base class for all objects that are implemented in managed
// code. It defines the common fields that associate CLR and Python
// objects and common utilities to convert between those identities.
//========================================================================
internal abstract class ManagedType {
internal GCHandle gcHandle; // Native handle
internal IntPtr pyHandle; // PyObject *
internal IntPtr tpHandle; // PyType *
//====================================================================
// Given a Python object, return the associated managed object or null.
//====================================================================
internal static ManagedType GetManagedObject(IntPtr ob) {
if (ob != IntPtr.Zero) {
IntPtr tp = Runtime.PyObject_TYPE(ob);
if (tp == Runtime.PyTypeType || tp == Runtime.PyCLRMetaType) {
tp = ob;
}
int flags = (int)Marshal.ReadIntPtr(tp, TypeOffset.tp_flags);
if ((flags & TypeFlags.Managed) != 0) {
IntPtr op = (tp == ob) ?
Marshal.ReadIntPtr(tp, TypeOffset.magic()) :
Marshal.ReadIntPtr(ob, ObjectOffset.magic());
GCHandle gc = (GCHandle)op;
return (ManagedType)gc.Target;
}
}
return null;
}
internal static ManagedType GetManagedObjectErr(IntPtr ob) {
ManagedType result = GetManagedObject(ob);
if (result == null) {
Exceptions.SetError(Exceptions.TypeError,
"invalid argument, expected CLR type"
);
}
return result;
}
internal static bool IsManagedType(IntPtr ob) {
if (ob != IntPtr.Zero) {
IntPtr tp = Runtime.PyObject_TYPE(ob);
if (tp == Runtime.PyTypeType || tp == Runtime.PyCLRMetaType) {
tp = ob;
}
int flags = (int)Marshal.ReadIntPtr(tp, TypeOffset.tp_flags);
if ((flags & TypeFlags.Managed) != 0) {
return true;
}
}
return false;
}
}
}

Просмотреть файл

@ -0,0 +1,261 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Runtime.InteropServices;
using System.Collections;
using System.Reflection;
namespace Python.Runtime {
//========================================================================
// The managed metatype. This object implements the type of all reflected
// types. It also provides support for single-inheritance from reflected
// managed types.
//========================================================================
internal class MetaType : ManagedType {
static IntPtr PyCLRMetaType;
//====================================================================
// Metatype initialization. This bootstraps the CLR metatype to life.
//====================================================================
public static IntPtr Initialize() {
PyCLRMetaType = TypeManager.CreateMetaType(typeof(MetaType));
return PyCLRMetaType;
}
//====================================================================
// Metatype __new__ implementation. This is called to create a new
// class / type when a reflected class is subclassed.
//====================================================================
[CallConvCdecl()]
public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw) {
int len = Runtime.PyTuple_Size(args);
if (len < 3) {
return Exceptions.RaiseTypeError("invalid argument list");
}
IntPtr name = Runtime.PyTuple_GetItem(args, 0);
IntPtr bases = Runtime.PyTuple_GetItem(args, 1);
IntPtr dict = Runtime.PyTuple_GetItem(args, 2);
// We do not support multiple inheritance, so the bases argument
// should be a 1-item tuple containing the type we are subtyping.
// That type must itself have a managed implementation. We check
// that by making sure its metatype is the CLR metatype.
if (Runtime.PyTuple_Size(bases) != 1) {
return Exceptions.RaiseTypeError(
"cannot use multiple inheritance with managed classes"
);
}
IntPtr base_type = Runtime.PyTuple_GetItem(bases, 0);
IntPtr mt = Runtime.PyObject_TYPE(base_type);
if (!((mt == PyCLRMetaType) || (mt == Runtime.PyTypeType))) {
return Exceptions.RaiseTypeError("invalid metatype");
}
// Ensure that the reflected type is appropriate for subclassing,
// disallowing subclassing of delegates, enums and array types.
ClassBase cb = GetManagedObject(base_type) as ClassBase;
if (cb != null) {
if (! cb.CanSubclass() ) {
return Exceptions.RaiseTypeError(
"delegates, enums and array types cannot be subclassed"
);
}
}
IntPtr slots = Runtime.PyDict_GetItemString(dict, "__slots__");
if (slots != IntPtr.Zero) {
return Exceptions.RaiseTypeError(
"subclasses of managed classes do not support __slots__"
);
}
// hack for now... fix for 1.0
//return TypeManager.CreateSubType(args);
// right way
IntPtr func = Marshal.ReadIntPtr(Runtime.PyTypeType,
TypeOffset.tp_new);
IntPtr type = NativeCall.Call_3(func, tp, args, kw);
if (type == IntPtr.Zero) {
return IntPtr.Zero;
}
int flags = TypeFlags.Default;
flags |= TypeFlags.Managed;
flags |= TypeFlags.HeapType;
flags |= TypeFlags.BaseType;
flags |= TypeFlags.Subclass;
flags |= TypeFlags.HaveGC;
Marshal.WriteIntPtr(type, TypeOffset.tp_flags, (IntPtr)flags);
TypeManager.CopySlot(base_type, type, TypeOffset.tp_dealloc);
// Hmm - the standard subtype_traverse, clear look at ob_size to
// do things, so to allow gc to work correctly we need to move
// our hidden handle out of ob_size. Then, in theory we can
// comment this out and still not crash.
TypeManager.CopySlot(base_type, type, TypeOffset.tp_traverse);
TypeManager.CopySlot(base_type, type, TypeOffset.tp_clear);
// for now, move up hidden handle...
IntPtr gc = Marshal.ReadIntPtr(base_type, TypeOffset.magic());
Marshal.WriteIntPtr(type, TypeOffset.magic(), gc);
//DebugUtil.DumpType(base_type);
//DebugUtil.DumpType(type);
return type;
}
[CallConvCdecl()]
public static IntPtr tp_alloc(IntPtr mt, int n) {
IntPtr type = Runtime.PyType_GenericAlloc(mt, n);
return type;
}
[CallConvCdecl()]
public static void tp_free(IntPtr tp) {
Runtime.PyObject_GC_Del(tp);
}
//====================================================================
// Metatype __call__ implementation. This is needed to ensure correct
// initialization (__init__ support), because the tp_call we inherit
// from PyType_Type won't call __init__ for metatypes it doesnt know.
//====================================================================
[CallConvCdecl()]
public static IntPtr tp_call(IntPtr tp, IntPtr args, IntPtr kw) {
IntPtr func = Marshal.ReadIntPtr(tp, TypeOffset.tp_new);
if (func == IntPtr.Zero) {
return Exceptions.RaiseTypeError("invalid object");
}
IntPtr obj = NativeCall.Call_3(func, tp, args, kw);
if (obj == IntPtr.Zero) {
return IntPtr.Zero;
}
IntPtr py__init__ = Runtime.PyString_FromString("__init__");
IntPtr type = Runtime.PyObject_TYPE(obj);
IntPtr init = Runtime._PyType_Lookup(type, py__init__);
Runtime.Decref(py__init__);
Runtime.PyErr_Clear();
if (init != IntPtr.Zero) {
IntPtr bound = Runtime.GetBoundArgTuple(obj, args);
if (bound == IntPtr.Zero) {
Runtime.Decref(obj);
return IntPtr.Zero;
}
IntPtr result = Runtime.PyObject_Call(init, bound, kw);
Runtime.Decref(bound);
if (result == IntPtr.Zero) {
Runtime.Decref(obj);
return IntPtr.Zero;
}
Runtime.Decref(result);
}
return obj;
}
//====================================================================
// Type __setattr__ implementation for reflected types. Note that this
// is slightly different than the standard setattr implementation for
// the normal Python metatype (PyTypeType). We need to look first in
// the type object of a reflected type for a descriptor in order to
// support the right setattr behavior for static fields and properties.
//====================================================================
[CallConvCdecl()]
public static int tp_setattro(IntPtr tp, IntPtr name, IntPtr value) {
IntPtr descr = Runtime._PyType_Lookup(tp, name);
if (descr != IntPtr.Zero) {
IntPtr dt = Runtime.PyObject_TYPE(descr);
IntPtr fp = Marshal.ReadIntPtr(dt, TypeOffset.tp_descr_set);
if (fp != IntPtr.Zero) {
return NativeCall.Impl.Int_Call_3(fp, descr, name, value);
}
Exceptions.SetError(Exceptions.AttributeError,
"attribute is read-only");
return -1;
}
if (Runtime.PyObject_GenericSetAttr(tp, name, value) < 0) {
return -1;
}
return 0;
}
//====================================================================
// Dealloc implementation. This is called when a Python type generated
// by this metatype is no longer referenced from the Python runtime.
//====================================================================
[CallConvCdecl()]
public static void tp_dealloc(IntPtr tp) {
// Fix this when we dont cheat on the handle for subclasses!
int flags = (int)Marshal.ReadIntPtr(tp, TypeOffset.tp_flags);
if ((flags & TypeFlags.Subclass) == 0) {
IntPtr gc = Marshal.ReadIntPtr(tp, TypeOffset.magic());
((GCHandle)gc).Free();
}
IntPtr op = Marshal.ReadIntPtr(tp, TypeOffset.ob_type);
Runtime.Decref(op);
// Delegate the rest of finalization the Python metatype. Note
// that the PyType_Type implementation of tp_dealloc will call
// tp_free on the type of the type being deallocated - in this
// case our CLR metatype. That is why we implement tp_free.
op = Marshal.ReadIntPtr(Runtime.PyTypeType, TypeOffset.tp_dealloc);
NativeCall.Void_Call_1(op, tp);
return;
}
}
}

Просмотреть файл

@ -0,0 +1,295 @@
// Copyright (c) 2003 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Collections;
using System.Reflection;
namespace Python.Runtime {
//========================================================================
// A MethodBinder encapsulates information about a (possibly overloaded)
// managed method, and is responsible for selecting the right method given
// a set of Python arguments. This is also used as a base class for the
// ConstructorBinder, a minor variation used to invoke constructors.
//========================================================================
internal class MethodBinder {
public ArrayList list;
public MethodBase[] methods;
public bool init = false;
internal MethodBinder () {
this.list = new ArrayList();
}
internal MethodBinder(MethodInfo mi) : base () {
this.list = new ArrayList();
this.list.Add(mi);
}
public int Count {
get { return this.list.Count; }
}
internal void AddMethod(MethodBase m) {
this.list.Add(m);
}
//====================================================================
// Return the array of MethodInfo for this method. The result array
// is arranged in order of precendence (done lazily to avoid doing it
// at all for methods that are never called).
//====================================================================
internal MethodBase[] GetMethods() {
if (!init) {
// I'm sure this could be made more efficient.
list.Sort(new MethodSorter());
methods = (MethodBase[])list.ToArray(typeof(MethodBase));
init = true;
}
return methods;
}
//====================================================================
// Precedence algorithm largely lifted from jython - the concerns are
// generally the same so we'll start w/this and tweak as necessary.
//====================================================================
internal static int GetPrecedence(MethodBase mi) {
ParameterInfo[] pi = mi.GetParameters();
int val = mi.IsStatic ? 3000 : 0;
int num = pi.Length;
for (int i = 0; i < num; i++) {
val += ArgPrecedence(pi[i].ParameterType);
}
return val;
}
//====================================================================
// Return a precedence value for a particular Type object.
//====================================================================
internal static int ArgPrecedence(Type t) {
Type objectType = typeof(Object);
if (t == objectType) return 3000;
TypeCode tc = Type.GetTypeCode(t);
if (tc == TypeCode.Object) return 1;
if (tc == TypeCode.UInt64) return 10;
if (tc == TypeCode.UInt32) return 11;
if (tc == TypeCode.UInt16) return 12;
if (tc == TypeCode.Int64) return 13;
if (tc == TypeCode.Int32) return 14;
if (tc == TypeCode.Int16) return 15;
if (tc == TypeCode.Char) return 16;
if (tc == TypeCode.SByte) return 17;
if (tc == TypeCode.Byte) return 18;
if (tc == TypeCode.Single) return 20;
if (tc == TypeCode.Double) return 21;
if (tc == TypeCode.String) return 30;
if (tc == TypeCode.Boolean) return 40;
if (t.IsArray) {
Type e = t.GetElementType();
if (e == objectType)
return 2500;
return 100 + ArgPrecedence(e);
}
return 2000;
}
//====================================================================
// Bind the given Python instance and arguments to a particular method
// overload and return a structure that contains the converted Python
// instance, converted arguments and the correct method to call.
//====================================================================
internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw) {
// loop to find match, return invoker w/ or /wo error
int nargs = Runtime.PyTuple_Size(args);
object arg;
MethodBase[] _methods = GetMethods();
for (int i = 0; i < _methods.Length; i++) {
MethodBase mi = _methods[i];
ParameterInfo[] pi = mi.GetParameters();
int count = pi.Length;
int outs = 0;
if ( nargs == count ) {
Object[] margs = new Object[count];
for (int n = 0; n < count; n++) {
IntPtr op = Runtime.PyTuple_GetItem(args, n);
Type type = pi[n].ParameterType;
if (pi[n].IsOut || type.IsByRef) {
outs++;
}
if (!Converter.ToManaged(op, type, out arg, false)) {
Exceptions.Clear();
margs = null;
break;
}
margs[n] = arg;
}
if (margs == null) {
continue;
}
Object target = null;
if ((!mi.IsStatic) && (inst != IntPtr.Zero)) {
CLRObject co = (CLRObject)ManagedType.GetManagedObject(
inst
);
target = co.inst;
}
return new Binding(mi, target, margs, outs);
}
}
return null;
}
internal virtual IntPtr Invoke(IntPtr inst, IntPtr args, IntPtr kw) {
Binding binding = this.Bind(inst, args, kw);
Object result;
if (binding == null) {
Exceptions.SetError(Exceptions.TypeError,
"no method matches given arguments"
);
return IntPtr.Zero;
}
IntPtr ts = PythonEngine.BeginAllowThreads();
try {
result = binding.info.Invoke(binding.inst,
BindingFlags.Default,
null,
binding.args,
null);
}
catch (Exception e) {
if (e.InnerException != null) {
e = e.InnerException;
}
PythonEngine.EndAllowThreads(ts);
Exceptions.SetError(e);
return IntPtr.Zero;
}
PythonEngine.EndAllowThreads(ts);
// If there are out parameters, we return a tuple containing
// the result followed by the out parameters. If there is only
// one out parameter and the return type of the method is void,
// we return the out parameter as the result to Python (for
// code compatibility with ironpython).
MethodInfo mi = (MethodInfo)binding.info;
if ((binding.outs == 1) && (mi.ReturnType == typeof(void))) {
}
if (binding.outs > 0) {
ParameterInfo[] pi = mi.GetParameters();
int c = pi.Length;
int n = 0;
IntPtr t = Runtime.PyTuple_New(binding.outs + 1);
IntPtr v = Converter.ToPython(result, mi.ReturnType);
Runtime.PyTuple_SetItem(t, n, v);
n++;
for (int i=0; i < c; i++) {
Type pt = pi[i].ParameterType;
if (pi[i].IsOut || pt.IsByRef) {
v = Converter.ToPython(binding.args[i], pt);
Runtime.PyTuple_SetItem(t, n, v);
n++;
}
}
if ((binding.outs == 1) && (mi.ReturnType == typeof(void))) {
v = Runtime.PyTuple_GetItem(t, 1);
Runtime.Incref(v);
Runtime.Decref(t);
return v;
}
return t;
}
return Converter.ToPython(result, mi.ReturnType);
}
}
//========================================================================
// Utility class to sort method info by parameter type precedence.
//========================================================================
internal class MethodSorter : IComparer {
int IComparer.Compare(Object m1, Object m2) {
int p1 = MethodBinder.GetPrecedence((MethodBase)m1);
int p2 = MethodBinder.GetPrecedence((MethodBase)m2);
if (p1 < p2) return -1;
if (p1 > p2) return 1;
return 0;
}
}
//========================================================================
// A Binding is a utility instance that bundles together a MethodInfo
// representing a method to call, a (possibly null) target instance for
// the call, and the arguments for the call (all as managed values).
//========================================================================
internal class Binding {
public MethodBase info;
public Object[] args;
public Object inst;
public int outs;
internal Binding(MethodBase info, Object inst, Object[] args,
int outs) {
this.info = info;
this.inst = inst;
this.args = args;
this.outs = outs;
}
}
}

Просмотреть файл

@ -0,0 +1,149 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
namespace Python.Runtime {
//========================================================================
// Implements a Python binding type for CLR methods. These work much like
// standard Python method bindings, but the same type is used to bind
// both static and instance methods.
//========================================================================
internal class MethodBinding : ExtensionType {
MethodObject m;
IntPtr target;
public MethodBinding(MethodObject m, IntPtr target) : base() {
Runtime.Incref(target);
this.target = target;
this.m = m;
}
//====================================================================
// MethodBinding __getattribute__ implementation.
//====================================================================
[CallConvCdecl()]
public static IntPtr tp_getattro(IntPtr ob, IntPtr key) {
MethodBinding self = (MethodBinding)GetManagedObject(ob);
if (!Runtime.PyString_Check(key)) {
Exceptions.SetError(Exceptions.TypeError, "string expected");
return IntPtr.Zero;
}
string name = Runtime.GetManagedString(key);
if (name == "__doc__") {
IntPtr doc = self.m.GetDocString();
Runtime.Incref(doc);
return doc;
}
return Runtime.PyObject_GenericGetAttr(ob, key);
}
//====================================================================
// MethodBinding __call__ implementation.
//====================================================================
[CallConvCdecl()]
public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) {
MethodBinding self = (MethodBinding)GetManagedObject(ob);
// This supports calling a method 'unbound', passing the instance
// as the first argument. Note that this is not supported if any
// of the overloads are static since we can't know if the intent
// was to call the static method or the unbound instance method.
if ((self.target == IntPtr.Zero) && (!self.m.IsStatic())) {
if (Runtime.PyTuple_Size(args) < 1) {
Exceptions.SetError(Exceptions.TypeError,
"not enough arguments"
);
return IntPtr.Zero;
}
int len = Runtime.PyTuple_Size(args);
IntPtr uargs = Runtime.PyTuple_GetSlice(args, 1, len);
IntPtr inst = Runtime.PyTuple_GetItem(args, 0);
Runtime.Incref(inst);
IntPtr r = self.m.Invoke(inst, uargs, kw);
Runtime.Decref(inst);
return r;
}
return self.m.Invoke(self.target, args, kw);
}
//====================================================================
// MethodBinding __hash__ implementation.
//====================================================================
[CallConvCdecl()]
public static IntPtr tp_hash(IntPtr ob) {
MethodBinding self = (MethodBinding)GetManagedObject(ob);
long x = 0;
long y = 0;
if (self.target != IntPtr.Zero) {
x = Runtime.PyObject_Hash(self.target).ToInt64();
if (x == -1) {
return new IntPtr(-1);
}
}
y = Runtime.PyObject_Hash(self.m.pyHandle).ToInt64();
if (y == -1) {
return new IntPtr(-1);
}
x ^= y;
if (x == -1) {
x = -1;
}
return new IntPtr(x);
}
//====================================================================
// MethodBinding __repr__ implementation.
//====================================================================
[CallConvCdecl()]
public static IntPtr tp_repr(IntPtr ob) {
MethodBinding self = (MethodBinding)GetManagedObject(ob);
string type = (self.target == IntPtr.Zero) ? "unbound" : "bound";
string s = String.Format("<{0} method '{1}'>", type, self.m.name);
return Runtime.PyString_FromStringAndSize(s, s.Length);
}
//====================================================================
// MethodBinding dealloc implementation.
//====================================================================
[CallConvCdecl()]
public static new void tp_dealloc(IntPtr ob) {
MethodBinding self = (MethodBinding)GetManagedObject(ob);
Runtime.Decref(self.target);
ExtensionType.FinalizeObject(self);
}
}
}

Просмотреть файл

@ -0,0 +1,171 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Collections;
using System.Reflection;
namespace Python.Runtime {
//========================================================================
// Implements a Python type that provides access to CLR object methods.
//========================================================================
internal class MethodObject : ExtensionType {
internal MethodInfo[] info;
internal string name;
internal MethodBinding unbound;
internal MethodBinder binder;
internal IntPtr doc;
public MethodObject(string name, MethodInfo[] info) : base() {
this.name = name;
this.info = info;
binder = new MethodBinder();
for (int i = 0; i < info.Length; i++) {
binder.AddMethod((MethodInfo)info[i]);
}
}
public virtual IntPtr Invoke(IntPtr target, IntPtr args, IntPtr kw) {
return binder.Invoke(target, args, kw);
}
//====================================================================
// Helper to get docstrings from reflected method / param info.
//====================================================================
internal IntPtr GetDocString() {
if (doc != IntPtr.Zero) {
return doc;
}
MethodBase[] methods = binder.GetMethods();
string str = "";
for (int i = 0; i < methods.Length; i++) {
if (str.Length > 0)
str += Environment.NewLine;
str += methods[i].ToString();
}
doc = Runtime.PyString_FromString(str);
return doc;
}
//====================================================================
// This is a little tricky: a class can actually have a static method
// and instance methods all with the same name. That makes it tough
// to support calling a method 'unbound' (passing the instance as the
// first argument), because in this case we can't know whether to call
// the instance method unbound or call the static method.
//
// The rule we is that if there are both instance and static methods
// with the same name, then we always call the static method. So this
// method returns true if any of the methods that are represented by
// the descriptor are static methods (called by MethodBinding).
//====================================================================
internal bool IsStatic() {
MethodBase[] methods = binder.GetMethods();
for (int i = 0; i < methods.Length; i++) {
if (methods[i].IsStatic)
return true;
}
return false;
}
//====================================================================
// Descriptor __getattribute__ implementation.
//====================================================================
[CallConvCdecl()]
public static IntPtr tp_getattro(IntPtr ob, IntPtr key) {
MethodObject self = (MethodObject)GetManagedObject(ob);
if (!Runtime.PyString_Check(key)) {
return Exceptions.RaiseTypeError("string expected");
}
string name = Runtime.GetManagedString(key);
if (name == "__doc__") {
IntPtr doc = self.GetDocString();
Runtime.Incref(doc);
return doc;
}
return Runtime.PyObject_GenericGetAttr(ob, key);
}
//====================================================================
// Descriptor __get__ implementation. Accessing a CLR method returns
// a "bound" method similar to a Python bound method.
//====================================================================
[CallConvCdecl()]
public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) {
MethodObject self = (MethodObject)GetManagedObject(ds);
MethodBinding binding;
// If the method is accessed through its type (rather than via
// an instance) we return an 'unbound' MethodBinding that will
// cached for future accesses through the type.
if (ob == IntPtr.Zero) {
if (self.unbound == null) {
self.unbound = new MethodBinding(self, IntPtr.Zero);
}
binding = self.unbound;
Runtime.Incref(binding.pyHandle);;
return binding.pyHandle;
}
if (Runtime.PyObject_IsInstance(ob, tp) < 1) {
return Exceptions.RaiseTypeError("invalid argument");
}
binding = new MethodBinding(self, ob);
return binding.pyHandle;
}
//====================================================================
// Descriptor __repr__ implementation.
//====================================================================
[CallConvCdecl()]
public static IntPtr tp_repr(IntPtr ob) {
MethodObject self = (MethodObject)GetManagedObject(ob);
string s = String.Format("<method '{0}'>", self.name);
return Runtime.PyString_FromStringAndSize(s, s.Length);
}
//====================================================================
// Descriptor dealloc implementation.
//====================================================================
[CallConvCdecl()]
public static new void tp_dealloc(IntPtr ob) {
MethodObject self = (MethodObject)GetManagedObject(ob);
Runtime.Decref(self.doc);
if (self.unbound != null) {
Runtime.Decref(self.unbound.pyHandle);
}
ExtensionType.FinalizeObject(self);
}
}
}

Просмотреть файл

@ -0,0 +1,63 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Collections;
using System.Runtime.InteropServices;
namespace Python.Runtime {
/// <summary>
/// A MethodWrapper wraps a static method of a managed type,
/// making it callable by Python as a PyCFunction object. This is
/// currently used mainly to implement special cases like the CLR
/// import hook.
/// </summary>
internal class MethodWrapper {
public IntPtr mdef;
public IntPtr ptr;
public MethodWrapper(Type type, string name) {
// Turn the managed method into a function pointer
IntPtr fp = Interop.GetThunk(type.GetMethod(name));
// XXX - here we create a Python string object, then take the
// char * of the internal string to pass to our methoddef
// structure. Its a hack, and the name is leaked!
IntPtr ps = Runtime.PyString_FromString(name);
IntPtr sp = Runtime.PyString_AS_STRING(ps);
// Allocate and initialize a PyMethodDef structure to represent
// the managed method, then create a PyCFunction.
mdef = Runtime.PyMem_Malloc(4 * IntPtr.Size);
Marshal.WriteIntPtr(mdef, sp);
Marshal.WriteIntPtr(mdef, (1 * IntPtr.Size), fp);
Marshal.WriteIntPtr(mdef, (2 * IntPtr.Size), (IntPtr)0x0002);
Marshal.WriteIntPtr(mdef, (3 * IntPtr.Size), IntPtr.Zero);
ptr = Runtime.PyCFunction_New(mdef, IntPtr.Zero);
}
public IntPtr Call(IntPtr args, IntPtr kw) {
return Runtime.PyCFunction_Call(ptr, args, kw);
}
}
}

Просмотреть файл

@ -0,0 +1,250 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Runtime.InteropServices;
using System.Collections.Specialized;
using System.Collections;
using System.Reflection;
namespace Python.Runtime {
// TODO: decide whether to support __all__ and / or whether to impl
// a 'preload' method to force names to be pre-loaded.
//========================================================================
// Implements a Python type that provides access to CLR namespaces. The
// type behaves like a Python module, and can contain other sub-modules.
//========================================================================
internal class ModuleObject : ExtensionType {
string moduleName;
string _namespace;
Hashtable cache;
static bool hacked;
IntPtr dict;
public ModuleObject(string name) : base() {
moduleName = (name == String.Empty) ? "CLR" : "CLR." + name;
cache = new Hashtable();
_namespace = name;
dict = Runtime.PyDict_New();
IntPtr pyname = Runtime.PyString_FromString(moduleName);
Runtime.PyDict_SetItemString(dict, "__name__", pyname);
Runtime.PyDict_SetItemString(dict, "__file__", Runtime.PyNone);
Runtime.PyDict_SetItemString(dict, "__doc__", Runtime.PyNone);
Runtime.Decref(pyname);
Marshal.WriteIntPtr(this.pyHandle, ObjectOffset.ob_dict, dict);
// This hackery is required in order to allow a plain Python to
// import the managed runtime via the CLR bootstrapper module.
// The standard Python machinery in control at the time of the
// import requires the module to pass PyModule_Check. :(
if (!hacked) {
IntPtr type = this.tpHandle;
IntPtr mro = Marshal.ReadIntPtr(type, TypeOffset.tp_mro);
IntPtr ext = Runtime.ExtendTuple(mro, Runtime.PyModuleType);
Marshal.WriteIntPtr(type, TypeOffset.tp_mro, ext);
Runtime.Decref(mro);
hacked = true;
}
}
public string ModuleName {
get {
return moduleName;
}
}
//===================================================================
// Returns a ClassBase object representing a type that appears in
// this module's namespace or a ModuleObject representing a child
// namespace (or null if the name is not found). This method does
// not increment the Python refcount of the returned object.
//===================================================================
public ManagedType GetAttribute(string name) {
Object ob = this.cache[name];
if (ob != null) {
return (ManagedType) ob;
}
string qname = (_namespace == String.Empty) ? name :
_namespace + "." + name;
ModuleObject m;
ClassBase c;
// If the fully-qualified name of the requested attribute is
// a namespace exported by a currently loaded assembly, return
// a new ModuleObject representing that namespace.
if (AssemblyManager.IsValidNamespace(qname)) {
m = new ModuleObject(qname);
StoreAttribute(name, m);
return (ManagedType) m;
}
// Look for a type in the current namespace. Note that this
// includes types, delegates, enums, interfaces and structs.
// Only public namespace members are exposed to Python.
Type type = AssemblyManager.LookupType(qname);
if (type != null) {
if (!type.IsPublic) {
return null;
}
c = ClassManager.GetClass(type);
StoreAttribute(name, c);
return (ManagedType) c;
}
// This is a little repetitive, but it ensures that the right
// thing happens with implicit assembly loading at a reasonable
// cost. Ask the AssemblyManager to do implicit loading for each
// of the steps in the qualified name, then try it again.
if (AssemblyManager.LoadImplicit(qname)) {
if (AssemblyManager.IsValidNamespace(qname)) {
m = new ModuleObject(qname);
StoreAttribute(name, m);
return (ManagedType) m;
}
type = AssemblyManager.LookupType(qname);
if (type != null) {
if (!type.IsPublic) {
return null;
}
c = ClassManager.GetClass(type);
StoreAttribute(name, c);
return (ManagedType) c;
}
}
return null;
}
//===================================================================
// Stores an attribute in the instance dict for future lookups.
//===================================================================
private void StoreAttribute(string name, ManagedType ob) {
Runtime.PyDict_SetItemString(dict, name, ob.pyHandle);
cache[name] = ob;
}
[PythonMethod]
public static IntPtr _preload(IntPtr ob, IntPtr args, IntPtr kw) {
ModuleObject self = (ModuleObject)GetManagedObject(ob);
string module_ns = self._namespace;
AppDomain domain = AppDomain.CurrentDomain;
Assembly[] assemblies = domain.GetAssemblies();
for (int i = 0; i < assemblies.Length; i++) {
Assembly assembly = assemblies[i];
Type[] types = assembly.GetTypes();
for (int n = 0; n < types.Length; n++) {
Type type = types[n];
string ns = type.Namespace;
if ((ns != null) && (ns == module_ns)) {
if (type.IsPublic) {
ClassBase c = ClassManager.GetClass(type);
self.StoreAttribute(type.Name, c);
}
}
}
}
Runtime.Incref(Runtime.PyNone);
return Runtime.PyNone;
}
//====================================================================
// ModuleObject __getattribute__ implementation. Module attributes
// are always either classes or sub-modules representing subordinate
// namespaces. CLR modules implement a lazy pattern - the sub-modules
// and classes are created when accessed and cached for future use.
//====================================================================
[CallConvCdecl()]
public static IntPtr tp_getattro(IntPtr ob, IntPtr key) {
ModuleObject self = (ModuleObject)GetManagedObject(ob);
if (!Runtime.PyString_Check(key)) {
Exceptions.SetError(Exceptions.TypeError, "string expected");
return IntPtr.Zero;
}
IntPtr op = Runtime.PyDict_GetItem(self.dict, key);
if (op != IntPtr.Zero) {
Runtime.Incref(op);
return op;
}
string name = Runtime.GetManagedString(key);
if (name == "__dict__") {
Runtime.Incref(self.dict);
return self.dict;
}
ManagedType attr = self.GetAttribute(name);
if (attr == null) {
Exceptions.SetError(Exceptions.AttributeError, name);
return IntPtr.Zero;
}
// XXX - hack required to recognize exception types. These types
// may need to be wrapped in old-style class wrappers in versions
// of Python where new-style classes cannot be used as exceptions.
if (Runtime.wrap_exceptions) {
if (attr is ClassBase) {
ClassBase c = attr as ClassBase;
if (c.is_exception) {
IntPtr p = attr.pyHandle;
IntPtr r = Exceptions.GetExceptionClassWrapper(p);
Runtime.PyDict_SetItemString(self.dict, name, r);
Runtime.Incref(r);
return r;
}
}
}
Runtime.Incref(attr.pyHandle);
return attr.pyHandle;
}
//====================================================================
// ModuleObject __repr__ implementation.
//====================================================================
[CallConvCdecl()]
public static IntPtr tp_repr(IntPtr ob) {
ModuleObject self = (ModuleObject)GetManagedObject(ob);
string s = String.Format("<module '{0}'>", self.moduleName);
return Runtime.PyString_FromString(s);
}
}
}

Просмотреть файл

@ -0,0 +1,168 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Threading;
using System.Runtime.InteropServices;
using System.Collections;
using System.Reflection;
using System.Reflection.Emit;
namespace Python.Runtime {
/// <summary>
/// Provides support for calling native code indirectly through
/// function pointers. Most of the important parts of the Python
/// C API can just be wrapped with p/invoke, but there are some
/// situations (specifically, calling functions through Python
/// type structures) where we need to call functions indirectly.
///
/// This class uses Reflection.Emit to generate IJW thunks that
/// support indirect calls to native code using various common
/// call signatures. This is mainly a workaround for the fact
/// that you can't spell an indirect call in C# (but can in IL).
///
/// Another approach that would work is for this to be turned
/// into a separate utility program that could be run during the
/// build process to generate the thunks as a separate assembly
/// that could then be referenced by the main Python runtime.
/// </summary>
internal class NativeCall {
static AssemblyBuilder aBuilder;
static ModuleBuilder mBuilder;
public static INativeCall Impl;
static NativeCall() {
// The static constructor is responsible for generating the
// assembly and the methods that implement the IJW thunks.
//
// To do this, we actually use reflection on the INativeCall
// interface (defined below) and generate the required thunk
// code based on the method signatures.
AssemblyName aname = new AssemblyName();
aname.Name = "e__NativeCall_Assembly";
AssemblyBuilderAccess aa = AssemblyBuilderAccess.Run;
aBuilder = Thread.GetDomain().DefineDynamicAssembly(aname, aa);
mBuilder = aBuilder.DefineDynamicModule("e__NativeCall_Module");
TypeAttributes ta = TypeAttributes.Public;
TypeBuilder tBuilder = mBuilder.DefineType("e__NativeCall", ta);
Type iType = typeof(INativeCall);
tBuilder.AddInterfaceImplementation(iType);
// Use reflection to loop over the INativeCall interface methods,
// calling GenerateThunk to create a managed thunk for each one.
foreach (MethodInfo method in iType.GetMethods()) {
GenerateThunk(tBuilder, method);
}
Type theType = tBuilder.CreateType();
Impl = (INativeCall)Activator.CreateInstance(theType);
}
private static void GenerateThunk(TypeBuilder tb, MethodInfo method) {
ParameterInfo[] pi = method.GetParameters();
int count = pi.Length;
int argc = count - 1;
Type[] args = new Type[count];
for (int i = 0; i < count; i++) {
args[i] = pi[i].ParameterType;
}
MethodBuilder mb = tb.DefineMethod(
method.Name,
MethodAttributes.Public |
MethodAttributes.Virtual,
method.ReturnType,
args
);
// Build the method signature for the actual native function.
// This is essentially the signature of the wrapper method
// minus the first argument (the passed in function pointer).
Type[] nargs = new Type[argc];
for (int i = 1; i < count; i++) {
nargs[(i - 1)] = args[i];
}
// IL generation: the (implicit) first argument of the method
// is the 'this' pointer and the second is the function pointer.
// This code pushes the real args onto the stack, followed by
// the function pointer, then the calli opcode to make the call.
ILGenerator il = mb.GetILGenerator();
for (int i = 0; i < argc; i++) {
il.Emit(OpCodes.Ldarg_S, (i + 2));
}
il.Emit(OpCodes.Ldarg_1);
il.EmitCalli(OpCodes.Calli,
CallingConvention.Cdecl,
method.ReturnType,
nargs
);
il.Emit(OpCodes.Ret);
tb.DefineMethodOverride(mb, method);
return;
}
public static void Void_Call_1(IntPtr fp, IntPtr a1) {
Impl.Void_Call_1(fp, a1);
}
public static IntPtr Call_3(IntPtr fp, IntPtr a1, IntPtr a2,
IntPtr a3) {
return Impl.Call_3(fp, a1, a2, a3);
}
public static int Int_Call_3(IntPtr fp, IntPtr a1, IntPtr a2,
IntPtr a3) {
return Impl.Int_Call_3(fp, a1, a2, a3);
}
}
/// <summary>
/// Defines native call signatures to be generated by NativeCall.
/// </summary>
public interface INativeCall {
void Void_Call_0(IntPtr funcPtr);
void Void_Call_1(IntPtr funcPtr, IntPtr arg1);
int Int_Call_3(IntPtr funcPtr, IntPtr t, IntPtr n, IntPtr v);
IntPtr Call_3(IntPtr funcPtr, IntPtr a1, IntPtr a2, IntPtr a3);
}
}

Просмотреть файл

@ -0,0 +1,171 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Collections;
using System.Reflection;
using System.Security.Permissions;
namespace Python.Runtime {
//========================================================================
// Implements a Python descriptor type that manages CLR properties.
//========================================================================
internal class PropertyObject : ExtensionType {
PropertyInfo info;
MethodInfo getter;
MethodInfo setter;
[StrongNameIdentityPermissionAttribute(SecurityAction.Assert)]
public PropertyObject(PropertyInfo md) : base() {
getter = md.GetGetMethod(true);
setter = md.GetSetMethod(true);
info = md;
}
//====================================================================
// Descriptor __get__ implementation. This method returns the
// value of the property on the given object. The returned value
// is converted to an appropriately typed Python object.
//====================================================================
[CallConvCdecl()]
public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) {
PropertyObject self = (PropertyObject)GetManagedObject(ds);
MethodInfo getter = self.getter;
IntPtr ts = IntPtr.Zero;
Object result;
if (getter == null) {
return Exceptions.RaiseTypeError("property cannot be read");
}
if ((ob == IntPtr.Zero) || (ob == Runtime.PyNone)) {
if (!(getter.IsStatic)) {
Exceptions.SetError(Exceptions.TypeError,
"instance property must be accessed through " +
"a class instance"
);
return IntPtr.Zero;
}
try {
result = self.info.GetValue(null, null);
return Converter.ToPython(result, self.info.PropertyType);
}
catch(Exception e) {
return Exceptions.RaiseTypeError(e.Message);
}
}
CLRObject co = GetManagedObject(ob) as CLRObject;
if (co == null) {
return Exceptions.RaiseTypeError("invalid target");
}
try {
result = self.info.GetValue(co.inst, null);
return Converter.ToPython(result, self.info.PropertyType);
}
catch(Exception e) {
if (e.InnerException != null) {
e = e.InnerException;
}
Exceptions.SetError(e);
return IntPtr.Zero;
}
}
//====================================================================
// Descriptor __set__ implementation. This method sets the value of
// a property based on the given Python value. The Python value must
// be convertible to the type of the property.
//====================================================================
[CallConvCdecl()]
public static new int tp_descr_set(IntPtr ds, IntPtr ob, IntPtr val) {
PropertyObject self = (PropertyObject)GetManagedObject(ds);
MethodInfo setter = self.setter;
IntPtr ts = IntPtr.Zero;
Object newval;
if (val == IntPtr.Zero) {
Exceptions.RaiseTypeError("cannot delete property");
return -1;
}
if (setter == null) {
Exceptions.RaiseTypeError("property is read-only");
return -1;
}
if (!Converter.ToManaged(val, self.info.PropertyType, out newval,
true)) {
return -1;
}
bool is_static = setter.IsStatic;
if ((ob == IntPtr.Zero) || (ob == Runtime.PyNone)) {
if (!(is_static)) {
Exceptions.RaiseTypeError(
"instance property must be set on an instance"
);
return -1;
}
}
try {
if (!is_static) {
CLRObject co = GetManagedObject(ob) as CLRObject;
if (co == null) {
Exceptions.RaiseTypeError("invalid target");
return -1;
}
self.info.SetValue(co.inst, newval, null);
}
else {
self.info.SetValue(null, newval, null);
}
return 0;
}
catch(Exception e) {
if (e.InnerException != null) {
e = e.InnerException;
}
Exceptions.SetError(e);
return -1;
}
}
//====================================================================
// Descriptor __repr__ implementation.
//====================================================================
[CallConvCdecl()]
public static IntPtr tp_repr(IntPtr ob) {
PropertyObject self = (PropertyObject)GetManagedObject(ob);
string s = String.Format("<property '{0}'>", self.info.Name);
return Runtime.PyString_FromStringAndSize(s, s.Length);
}
}
}

Просмотреть файл

@ -0,0 +1,210 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Runtime.InteropServices;
namespace Python.Runtime {
/// <summary>
/// Represents a Python dictionary object. See the documentation at
/// http://www.python.org/doc/current/api/dictObjects.html for details.
/// </summary>
public class PyDict : PyObject {
/// <summary>
/// PyDict Constructor
/// </summary>
///
/// <remarks>
/// Creates a new PyDict from an existing object reference. Note
/// that the instance assumes ownership of the object reference.
/// The object reference is not checked for type-correctness.
/// </remarks>
public PyDict(IntPtr ptr) : base(ptr) {}
/// <summary>
/// PyDict Constructor
/// </summary>
///
/// <remarks>
/// Creates a new Python dictionary object.
/// </remarks>
public PyDict() : base() {
obj = Runtime.PyDict_New();
if (obj == IntPtr.Zero) {
throw new PythonException();
}
}
/// <summary>
/// PyDict Constructor
/// </summary>
///
/// <remarks>
/// Copy constructor - obtain a PyDict from a generic PyObject. An
/// ArgumentException will be thrown if the given object is not a
/// Python dictionary object.
/// </remarks>
public PyDict(PyObject o) : base() {
if (!IsDictType(o)) {
throw new ArgumentException("object is not a dict");
}
Runtime.Incref(o.obj);
obj = o.obj;
}
/// <summary>
/// IsDictType Method
/// </summary>
///
/// <remarks>
/// Returns true if the given object is a Python dictionary.
/// </remarks>
public static bool IsDictType(PyObject value) {
return Runtime.PyDict_Check(value.obj);
}
/// <summary>
/// HasKey Method
/// </summary>
///
/// <remarks>
/// Returns true if the object key appears in the dictionary.
/// </remarks>
public bool HasKey(PyObject key) {
return (Runtime.PyMapping_HasKey(obj, key.obj) != 0);
}
/// <summary>
/// HasKey Method
/// </summary>
///
/// <remarks>
/// Returns true if the string key appears in the dictionary.
/// </remarks>
public bool HasKey(string key) {
return HasKey(new PyString(key));
}
/// <summary>
/// Keys Method
/// </summary>
///
/// <remarks>
/// Returns a sequence containing the keys of the dictionary.
/// </remarks>
public PyObject Keys() {
IntPtr items = Runtime.PyDict_Keys(obj);
if (items == IntPtr.Zero) {
throw new PythonException();
}
return new PyObject(items);
}
/// <summary>
/// Values Method
/// </summary>
///
/// <remarks>
/// Returns a sequence containing the values of the dictionary.
/// </remarks>
public PyObject Values() {
IntPtr items = Runtime.PyDict_Values(obj);
if (items == IntPtr.Zero) {
throw new PythonException();
}
return new PyObject(items);
}
/// <summary>
/// Items Method
/// </summary>
///
/// <remarks>
/// Returns a sequence containing the items of the dictionary.
/// </remarks>
public PyObject Items() {
IntPtr items = Runtime.PyDict_Items(obj);
if (items == IntPtr.Zero) {
throw new PythonException();
}
return new PyObject(items);
}
/// <summary>
/// Copy Method
/// </summary>
///
/// <remarks>
/// Returns a copy of the dictionary.
/// </remarks>
public PyDict Copy() {
IntPtr op = Runtime.PyDict_Copy(obj);
if (op == IntPtr.Zero) {
throw new PythonException();
}
return new PyDict(op);
}
/// <summary>
/// Update Method
/// </summary>
///
/// <remarks>
/// Update the dictionary from another dictionary.
/// </remarks>
public void Update(PyObject other) {
int result = Runtime.PyDict_Update(obj, other.obj);
if (result < 0) {
throw new PythonException();
}
}
/// <summary>
/// Clear Method
/// </summary>
///
/// <remarks>
/// Clears the dictionary.
/// </remarks>
public void Clear() {
Runtime.PyDict_Clear(obj);
}
}
}

Просмотреть файл

@ -0,0 +1,124 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Runtime.InteropServices;
namespace Python.Runtime {
/// <summary>
/// Represents a Python float object. See the documentation at
/// http://www.python.org/doc/current/api/floatObjects.html
/// </summary>
public class PyFloat : PyNumber {
/// <summary>
/// PyFloat Constructor
/// </summary>
///
/// <remarks>
/// Creates a new PyFloat from an existing object reference. Note
/// that the instance assumes ownership of the object reference.
/// The object reference is not checked for type-correctness.
/// </remarks>
public PyFloat(IntPtr ptr) : base(ptr) {}
/// <summary>
/// PyFloat Constructor
/// </summary>
///
/// <remarks>
/// Copy constructor - obtain a PyFloat from a generic PyObject. An
/// ArgumentException will be thrown if the given object is not a
/// Python float object.
/// </remarks>
public PyFloat(PyObject o) : base() {
if (!IsFloatType(o)) {
throw new ArgumentException("object is not a float");
}
Runtime.Incref(o.obj);
obj = o.obj;
}
/// <summary>
/// PyFloat Constructor
/// </summary>
///
/// <remarks>
/// Creates a new Python float from a double value.
/// </remarks>
public PyFloat(double value) : base() {
obj = Runtime.PyFloat_FromDouble(value);
if (obj == IntPtr.Zero) {
throw new PythonException();
}
}
/// <summary>
/// PyFloat Constructor
/// </summary>
///
/// <remarks>
/// Creates a new Python float from a string value.
/// </remarks>
public PyFloat(string value) : base() {
PyString s = new PyString(value);
obj = Runtime.PyFloat_FromString(s.obj, IntPtr.Zero);
if (obj == IntPtr.Zero) {
throw new PythonException();
}
}
/// <summary>
/// IsFloatType Method
/// </summary>
///
/// <remarks>
/// Returns true if the given object is a Python float.
/// </remarks>
public static bool IsFloatType(PyObject value) {
return Runtime.PyFloat_Check(value.obj);
}
/// <summary>
/// AsFloat Method
/// </summary>
///
/// <remarks>
/// <remarks>
/// Convert a Python object to a Python float if possible, raising
/// a PythonException if the conversion is not possible. This is
/// equivalent to the Python expression "float(object)".
/// </remarks>
public static PyFloat AsFloat(PyObject value) {
IntPtr op = Runtime.PyNumber_Float(value.obj);
if (op == IntPtr.Zero) {
throw new PythonException();
}
return new PyFloat(op);
}
}
}

Просмотреть файл

@ -0,0 +1,259 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Runtime.InteropServices;
namespace Python.Runtime {
/// <summary>
/// Represents a Python integer object. See the documentation at
/// http://www.python.org/doc/current/api/intObjects.html for details.
/// </summary>
public class PyInt : PyNumber {
/// <summary>
/// PyInt Constructor
/// </summary>
///
/// <remarks>
/// Creates a new PyInt from an existing object reference. Note
/// that the instance assumes ownership of the object reference.
/// The object reference is not checked for type-correctness.
/// </remarks>
public PyInt(IntPtr ptr) : base(ptr) {}
/// <summary>
/// PyInt Constructor
/// </summary>
///
/// <remarks>
/// Copy constructor - obtain a PyInt from a generic PyObject. An
/// ArgumentException will be thrown if the given object is not a
/// Python int object.
/// </remarks>
public PyInt(PyObject o) : base() {
if (!IsIntType(o)) {
throw new ArgumentException("object is not an int");
}
Runtime.Incref(o.obj);
obj = o.obj;
}
/// <summary>
/// PyInt Constructor
/// </summary>
///
/// <remarks>
/// Creates a new Python int from an int32 value.
/// </remarks>
public PyInt(int value) : base() {
obj = Runtime.PyInt_FromInt32(value);
if (obj == IntPtr.Zero) {
throw new PythonException();
}
}
/// <summary>
/// PyInt Constructor
/// </summary>
///
/// <remarks>
/// Creates a new Python int from a uint32 value.
/// </remarks>
[CLSCompliant(false)]
public PyInt(uint value) : base(IntPtr.Zero) {
obj = Runtime.PyInt_FromInt64((long)value);
if (obj == IntPtr.Zero) {
throw new PythonException();
}
}
/// <summary>
/// PyInt Constructor
/// </summary>
///
/// <remarks>
/// Creates a new Python int from an int64 value.
/// </remarks>
public PyInt(long value) : base(IntPtr.Zero) {
obj = Runtime.PyInt_FromInt64(value);
if (obj == IntPtr.Zero) {
throw new PythonException();
}
}
/// <summary>
/// PyInt Constructor
/// </summary>
///
/// <remarks>
/// Creates a new Python int from a uint64 value.
/// </remarks>
[CLSCompliant(false)]
public PyInt(ulong value) : base(IntPtr.Zero) {
obj = Runtime.PyInt_FromInt64((long)value);
if (obj == IntPtr.Zero) {
throw new PythonException();
}
}
/// <summary>
/// PyInt Constructor
/// </summary>
///
/// <remarks>
/// Creates a new Python int from an int16 value.
/// </remarks>
public PyInt(short value) : this((int)value) {}
/// <summary>
/// PyInt Constructor
/// </summary>
///
/// <remarks>
/// Creates a new Python int from a uint16 value.
/// </remarks>
[CLSCompliant(false)]
public PyInt(ushort value) : this((int)value) {}
/// <summary>
/// PyInt Constructor
/// </summary>
///
/// <remarks>
/// Creates a new Python int from a byte value.
/// </remarks>
public PyInt(byte value) : this((int)value) {}
/// <summary>
/// PyInt Constructor
/// </summary>
///
/// <remarks>
/// Creates a new Python int from an sbyte value.
/// </remarks>
[CLSCompliant(false)]
public PyInt(sbyte value) : this((int)value) {}
/// <summary>
/// PyInt Constructor
/// </summary>
///
/// <remarks>
/// Creates a new Python int from a string value.
/// </remarks>
public PyInt(string value) : base() {
obj = Runtime.PyInt_FromString(value, IntPtr.Zero, 0);
if (obj == IntPtr.Zero) {
throw new PythonException();
}
}
/// <summary>
/// IsIntType Method
/// </summary>
///
/// <remarks>
/// Returns true if the given object is a Python int.
/// </remarks>
public static bool IsIntType(PyObject value) {
return Runtime.PyInt_Check(value.obj);
}
/// <summary>
/// AsInt Method
/// </summary>
///
/// <remarks>
/// <remarks>
/// Convert a Python object to a Python int if possible, raising
/// a PythonException if the conversion is not possible. This is
/// equivalent to the Python expression "int(object)".
/// </remarks>
public static PyInt AsInt(PyObject value) {
IntPtr op = Runtime.PyNumber_Int(value.obj);
if (op == IntPtr.Zero) {
throw new PythonException();
}
return new PyInt(op);
}
/// <summary>
/// ToInt16 Method
/// </summary>
///
/// <remarks>
/// Return the value of the Python int object as an int16.
/// </remarks>
public short ToInt16() {
return System.Convert.ToInt16(this.ToInt32());
}
/// <summary>
/// ToInt32 Method
/// </summary>
///
/// <remarks>
/// Return the value of the Python int object as an int32.
/// </remarks>
public int ToInt32() {
return Runtime.PyInt_AsLong(obj);
}
/// <summary>
/// ToInt64 Method
/// </summary>
///
/// <remarks>
/// Return the value of the Python int object as an int64.
/// </remarks>
public long ToInt64() {
return System.Convert.ToInt64(this.ToInt32());
}
}
}

Просмотреть файл

@ -0,0 +1,191 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
namespace Python.Runtime {
/// <summary>
/// Represents a standard Python list object. See the documentation at
/// http://www.python.org/doc/current/api/listObjects.html for details.
/// </summary>
public class PyList : PySequence {
/// <summary>
/// PyList Constructor
/// </summary>
///
/// <remarks>
/// Creates a new PyList from an existing object reference. Note
/// that the instance assumes ownership of the object reference.
/// The object reference is not checked for type-correctness.
/// </remarks>
public PyList(IntPtr ptr) : base(ptr) {}
/// <summary>
/// PyList Constructor
/// </summary>
///
/// <remarks>
/// Copy constructor - obtain a PyList from a generic PyObject. An
/// ArgumentException will be thrown if the given object is not a
/// Python list object.
/// </remarks>
public PyList(PyObject o) : base() {
if (!IsListType(o)) {
throw new ArgumentException("object is not a list");
}
Runtime.Incref(o.obj);
obj = o.obj;
}
/// <summary>
/// PyList Constructor
/// </summary>
///
/// <remarks>
/// Creates a new empty Python list object.
/// </remarks>
public PyList() : base() {
obj = Runtime.PyList_New(0);
if (obj == IntPtr.Zero) {
throw new PythonException();
}
}
/// <summary>
/// PyList Constructor
/// </summary>
///
/// <remarks>
/// Creates a new Python list object from an array of PyObjects.
/// </remarks>
public PyList(PyObject[] items) : base() {
int count = items.Length;
obj = Runtime.PyList_New(count);
for (int i = 0; i < count; i++) {
IntPtr ptr = items[i].obj;
Runtime.Incref(ptr);
int r = Runtime.PyList_SetItem(obj, i, ptr);
if (r < 0) {
throw new PythonException();
}
}
}
/// <summary>
/// IsListType Method
/// </summary>
///
/// <remarks>
/// Returns true if the given object is a Python list.
/// </remarks>
public static bool IsListType(PyObject value) {
return Runtime.PyList_Check(value.obj);
}
/// <summary>
/// AsList Method
/// </summary>
///
/// <remarks>
/// Converts a Python object to a Python list if possible, raising
/// a PythonException if the conversion is not possible. This is
/// equivalent to the Python expression "list(object)".
/// </remarks>
public static PyList AsList(PyObject value) {
IntPtr op = Runtime.PySequence_List(value.obj);
if (op == IntPtr.Zero) {
throw new PythonException();
}
return new PyList(op);
}
/// <summary>
/// Append Method
/// </summary>
///
/// <remarks>
/// Append an item to the list object.
/// </remarks>
public void Append(PyObject item) {
int r = Runtime.PyList_Append(obj, item.obj);
if (r < 0) {
throw new PythonException();
}
}
/// <summary>
/// Insert Method
/// </summary>
///
/// <remarks>
/// Insert an item in the list object at the given index.
/// </remarks>
public void Insert(int index, PyObject item) {
int r = Runtime.PyList_Insert(obj, index, item.obj);
if (r < 0) {
throw new PythonException();
}
}
/// <summary>
/// Reverse Method
/// </summary>
///
/// <remarks>
/// Reverse the order of the list object in place.
/// </remarks>
public void Reverse() {
int r = Runtime.PyList_Reverse(obj);
if (r < 0) {
throw new PythonException();
}
}
/// <summary>
/// Sort Method
/// </summary>
///
/// <remarks>
/// Sort the list in place.
/// </remarks>
public void Sort() {
int r = Runtime.PyList_Sort(obj);
if (r < 0) {
throw new PythonException();
}
}
}
}

Просмотреть файл

@ -0,0 +1,254 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
namespace Python.Runtime {
/// <summary>
/// Represents a Python long int object. See the documentation at
/// http://www.python.org/doc/current/api/longObjects.html
/// </summary>
public class PyLong : PyNumber {
/// <summary>
/// PyLong Constructor
/// </summary>
///
/// <remarks>
/// Creates a new PyLong from an existing object reference. Note
/// that the instance assumes ownership of the object reference.
/// The object reference is not checked for type-correctness.
/// </remarks>
public PyLong(IntPtr ptr) : base(ptr) {}
/// <summary>
/// PyLong Constructor
/// </summary>
///
/// <remarks>
/// Copy constructor - obtain a PyLong from a generic PyObject. An
/// ArgumentException will be thrown if the given object is not a
/// Python long object.
/// </remarks>
public PyLong(PyObject o) : base() {
if (!IsLongType(o)) {
throw new ArgumentException("object is not a long");
}
Runtime.Incref(o.obj);
obj = o.obj;
}
/// <summary>
/// PyLong Constructor
/// </summary>
///
/// <remarks>
/// Creates a new PyLong from an int32 value.
/// </remarks>
public PyLong(int value) : base() {
obj = Runtime.PyLong_FromLong((long)value);
if (obj == IntPtr.Zero) {
throw new PythonException();
}
}
/// <summary>
/// PyLong Constructor
/// </summary>
///
/// <remarks>
/// Creates a new PyLong from a uint32 value.
/// </remarks>
[CLSCompliant(false)]
public PyLong(uint value) : base() {
obj = Runtime.PyLong_FromLong((long)value);
if (obj == IntPtr.Zero) {
throw new PythonException();
}
}
/// <summary>
/// PyLong Constructor
/// </summary>
///
/// <remarks>
/// Creates a new PyLong from an int64 value.
/// </remarks>
public PyLong(long value) : base() {
obj = Runtime.PyLong_FromLong(value);
if (obj == IntPtr.Zero) {
throw new PythonException();
}
}
/// <summary>
/// PyLong Constructor
/// </summary>
///
/// <remarks>
/// Creates a new PyLong from a uint64 value.
/// </remarks>
[CLSCompliant(false)]
public PyLong(ulong value) : base() {
obj = Runtime.PyLong_FromUnsignedLongLong(value);
if (obj == IntPtr.Zero) {
throw new PythonException();
}
}
/// <summary>
/// PyLong Constructor
/// </summary>
///
/// <remarks>
/// Creates a new PyLong from an int16 value.
/// </remarks>
public PyLong(short value) : base() {
obj = Runtime.PyLong_FromLong((long)value);
if (obj == IntPtr.Zero) {
throw new PythonException();
}
}
/// <summary>
/// PyLong Constructor
/// </summary>
///
/// <remarks>
/// Creates a new PyLong from an uint16 value.
/// </remarks>
[CLSCompliant(false)]
public PyLong(ushort value) : base() {
obj = Runtime.PyLong_FromLong((long)value);
if (obj == IntPtr.Zero) {
throw new PythonException();
}
}
/// <summary>
/// PyLong Constructor
/// </summary>
///
/// <remarks>
/// Creates a new PyLong from a byte value.
/// </remarks>
public PyLong(byte value) : base() {
obj = Runtime.PyLong_FromLong((long)value);
if (obj == IntPtr.Zero) {
throw new PythonException();
}
}
/// <summary>
/// PyLong Constructor
/// </summary>
///
/// <remarks>
/// Creates a new PyLong from an sbyte value.
/// </remarks>
[CLSCompliant(false)]
public PyLong(sbyte value) : base() {
obj = Runtime.PyLong_FromLong((long)value);
if (obj == IntPtr.Zero) {
throw new PythonException();
}
}
/// <summary>
/// PyLong Constructor
/// </summary>
///
/// <remarks>
/// Creates a new PyLong from an double value.
/// </remarks>
public PyLong(double value) : base() {
obj = Runtime.PyLong_FromDouble(value);
if (obj == IntPtr.Zero) {
throw new PythonException();
}
}
/// <summary>
/// PyLong Constructor
/// </summary>
///
/// <remarks>
/// Creates a new PyLong from a string value.
/// </remarks>
public PyLong(string value) : base() {
obj = Runtime.PyLong_FromString(value, IntPtr.Zero, 0);
if (obj == IntPtr.Zero) {
throw new PythonException();
}
}
/// <summary>
/// IsLongType Method
/// </summary>
///
/// <remarks>
/// Returns true if the given object is a Python long.
/// </remarks>
public static bool IsLongType(PyObject value) {
return Runtime.PyLong_Check(value.obj);
}
/// <summary>
/// AsLong Method
/// </summary>
///
/// <remarks>
/// <remarks>
/// Convert a Python object to a Python long if possible, raising
/// a PythonException if the conversion is not possible. This is
/// equivalent to the Python expression "long(object)".
/// </remarks>
public static PyLong AsLong(PyObject value) {
IntPtr op = Runtime.PyNumber_Long(value.obj);
if (op == IntPtr.Zero) {
throw new PythonException();
}
return new PyLong(op);
}
}
}

Просмотреть файл

@ -0,0 +1,49 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
namespace Python.Runtime {
/// <summary>
/// Represents a generic Python number. The methods of this class are
/// equivalent to the Python "abstract number API". See
/// http://www.python.org/doc/current/api/number.html for details.
/// </summary>
public class PyNumber : PyObject {
protected PyNumber(IntPtr ptr) : base(ptr) {}
protected PyNumber() : base() {}
/// <summary>
/// IsNumberType Method
/// </summary>
///
/// <remarks>
/// Returns true if the given object is a Python numeric type.
/// </remarks>
public static bool IsNumberType(PyObject value) {
return Runtime.PyNumber_Check(value.obj);
}
// TODO: add all of the PyNumber_XXX methods.
}
}

Просмотреть файл

@ -0,0 +1,873 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
namespace Python.Runtime {
/// <summary>
/// Represents a generic Python object. The methods of this class are
/// generally equivalent to the Python "abstract object API". See
/// http://www.python.org/doc/current/api/object.html for details.
/// </summary>
public class PyObject : IDisposable {
protected internal IntPtr obj = IntPtr.Zero;
private bool disposed = false;
/// <summary>
/// PyObject Constructor
/// </summary>
///
/// <remarks>
/// Creates a new PyObject from an IntPtr object reference. Note that
/// the PyObject instance assumes ownership of the object reference
/// and the reference will be DECREFed when the PyObject is garbage
/// collected or explicitly disposed.
/// </remarks>
public PyObject(IntPtr ptr) {
obj = ptr;
}
// Protected default constructor to allow subclasses to manage
// initialization in different ways as appropriate.
protected PyObject() {}
// Ensure that encapsulated Python object is decref'ed appropriately
// when the managed wrapper is garbage-collected.
~PyObject() {
Dispose();
}
/// <summary>
/// Handle Property
/// </summary>
///
/// <remarks>
/// Gets the native handle of the underlying Python object. This
/// value is generally for internal use by the PythonNet runtime.
/// </remarks>
public IntPtr Handle {
get { return obj; }
}
/// <summary>
/// FromManagedObject Method
/// </summary>
///
/// <remarks>
/// Given an arbitrary managed object, return a Python instance that
/// reflects the managed object.
/// </remarks>
public static PyObject FromManagedObject(object ob) {
// Special case: if ob is null, we return None.
if (ob == null) {
Runtime.Incref(Runtime.PyNone);
return new PyObject(Runtime.PyNone);
}
IntPtr op = CLRObject.GetInstHandle(ob);
return new PyObject(op);
}
/// <summary>
/// AsManagedObject Method
/// </summary>
///
/// <remarks>
/// Return a managed object of the given type, based on the
/// value of the Python object.
/// </remarks>
public object AsManagedObject(Type t) {
Object result;
if (!Converter.ToManaged(this.Handle, t, out result, false)) {
throw new InvalidCastException(
"cannot convert object to target type"
);
}
return result;
}
/// <summary>
/// Dispose Method
/// </summary>
///
/// <remarks>
/// The Dispose method provides a way to explicitly release the
/// Python object represented by a PyObject instance. It is a good
/// idea to call Dispose on PyObjects that wrap resources that are
/// limited or need strict lifetime control. Otherwise, references
/// to Python objects will not be released until a managed garbage
/// collection occurs.
/// </remarks>
public void Dispose() {
if (!disposed) {
if (Runtime.Py_IsInitialized() > 0) {
IntPtr gs = PythonEngine.AcquireLock();
Runtime.Decref(obj);
obj = IntPtr.Zero;
PythonEngine.ReleaseLock(gs);
}
GC.SuppressFinalize(this);
disposed = true;
}
}
/// <summary>
/// GetPythonType Method
/// </summary>
///
/// <remarks>
/// Returns the Python type of the object. This method is equivalent
/// to the Python expression: type(object).
/// </remarks>
public PyObject GetPythonType() {
IntPtr tp = Runtime.PyObject_Type(obj);
return new PyObject(tp);
}
/// <summary>
/// TypeCheck Method
/// </summary>
///
/// <remarks>
/// Returns true if the object o is of type typeOrClass or a subtype
/// of typeOrClass.
/// </remarks>
public bool TypeCheck(PyObject typeOrClass) {
return Runtime.PyObject_TypeCheck(obj, typeOrClass.obj);
}
/// <summary>
/// HasAttr Method
/// </summary>
///
/// <remarks>
/// Returns true if the object has an attribute with the given name.
/// </remarks>
public bool HasAttr(string name) {
return (Runtime.PyObject_HasAttrString(obj, name) != 0);
}
/// <summary>
/// HasAttr Method
/// </summary>
///
/// <remarks>
/// Returns true if the object has an attribute with the given name,
/// where name is a PyObject wrapping a string or unicode object.
/// </remarks>
public bool HasAttr(PyObject name) {
return (Runtime.PyObject_HasAttr(obj, name.obj) != 0);
}
/// <summary>
/// GetAttr Method
/// </summary>
///
/// <remarks>
/// Returns the named attribute of the Python object, or raises a
/// PythonException if the attribute access fails.
/// </remarks>
public PyObject GetAttr(string name) {
IntPtr op = Runtime.PyObject_GetAttrString(obj, name);
if (op == IntPtr.Zero) {
throw new PythonException();
}
return new PyObject(op);
}
/// <summary>
/// GetAttr Method
/// </summary>
///
/// <remarks>
/// Returns the named attribute of the Python object, or the given
/// default object if the attribute access fails.
/// </remarks>
public PyObject GetAttr(string name, PyObject _default) {
IntPtr op = Runtime.PyObject_GetAttrString(obj, name);
if (op == IntPtr.Zero) {
Runtime.PyErr_Clear();
return _default;
}
return new PyObject(op);
}
/// <summary>
/// GetAttr Method
/// </summary>
///
/// <remarks>
/// Returns the named attribute of the Python object or raises a
/// PythonException if the attribute access fails. The name argument
/// is a PyObject wrapping a Python string or unicode object.
/// </remarks>
public PyObject GetAttr(PyObject name) {
IntPtr op = Runtime.PyObject_GetAttr(obj, name.obj);
if (op == IntPtr.Zero) {
throw new PythonException();
}
return new PyObject(op);
}
/// <summary>
/// GetAttr Method
/// </summary>
///
/// <remarks>
/// Returns the named attribute of the Python object, or the given
/// default object if the attribute access fails. The name argument
/// is a PyObject wrapping a Python string or unicode object.
/// </remarks>
public PyObject GetAttr(PyObject name, PyObject _default) {
IntPtr op = Runtime.PyObject_GetAttr(obj, name.obj);
if (op == IntPtr.Zero) {
Runtime.PyErr_Clear();
return _default;
}
return new PyObject(op);
}
/// <summary>
/// SetAttr Method
/// </summary>
///
/// <remarks>
/// Set an attribute of the object with the given name and value. This
/// method throws a PythonException if the attribute set fails.
/// </remarks>
public void SetAttr(string name, PyObject value) {
int r = Runtime.PyObject_SetAttrString(obj, name, value.obj);
if (r < 0) {
throw new PythonException();
}
}
/// <summary>
/// SetAttr Method
/// </summary>
///
/// <remarks>
/// Set an attribute of the object with the given name and value,
/// where the name is a Python string or unicode object. This method
/// throws a PythonException if the attribute set fails.
/// </remarks>
public void SetAttr(PyObject name, PyObject value) {
int r = Runtime.PyObject_SetAttr(obj, name.obj, value.obj);
if (r < 0) {
throw new PythonException();
}
}
/// <summary>
/// DelAttr Method
/// </summary>
///
/// <remarks>
/// Delete the named attribute of the Python object. This method
/// throws a PythonException if the attribute set fails.
/// </remarks>
public void DelAttr(string name) {
int r = Runtime.PyObject_SetAttrString(obj, name, IntPtr.Zero);
if (r < 0) {
throw new PythonException();
}
}
/// <summary>
/// DelAttr Method
/// </summary>
///
/// <remarks>
/// Delete the named attribute of the Python object, where name is a
/// PyObject wrapping a Python string or unicode object. This method
/// throws a PythonException if the attribute set fails.
/// </remarks>
public void DelAttr(PyObject name) {
int r = Runtime.PyObject_SetAttr(obj, name.obj, IntPtr.Zero);
if (r < 0) {
throw new PythonException();
}
}
/// <summary>
/// GetItem Method
/// </summary>
///
/// <remarks>
/// For objects that support the Python sequence or mapping protocols,
/// return the item at the given object index. This method raises a
/// PythonException if the indexing operation fails.
/// </remarks>
public virtual PyObject GetItem(PyObject key) {
IntPtr op = Runtime.PyObject_GetItem(obj, key.obj);
if (op == IntPtr.Zero) {
throw new PythonException();
}
return new PyObject(op);
}
/// <summary>
/// GetItem Method
/// </summary>
///
/// <remarks>
/// For objects that support the Python sequence or mapping protocols,
/// return the item at the given string index. This method raises a
/// PythonException if the indexing operation fails.
/// </remarks>
public virtual PyObject GetItem(string key) {
return GetItem(new PyString(key));
}
/// <summary>
/// GetItem Method
/// </summary>
///
/// <remarks>
/// For objects that support the Python sequence or mapping protocols,
/// return the item at the given numeric index. This method raises a
/// PythonException if the indexing operation fails.
/// </remarks>
public virtual PyObject GetItem(int index) {
PyInt key = new PyInt(index);
return GetItem((PyObject)key);
}
/// <summary>
/// SetItem Method
/// </summary>
///
/// <remarks>
/// For objects that support the Python sequence or mapping protocols,
/// set the item at the given object index to the given value. This
/// method raises a PythonException if the set operation fails.
/// </remarks>
public virtual void SetItem(PyObject key, PyObject value) {
int r = Runtime.PyObject_SetItem(obj, key.obj, value.obj);
if (r < 0) {
throw new PythonException();
}
}
/// <summary>
/// SetItem Method
/// </summary>
///
/// <remarks>
/// For objects that support the Python sequence or mapping protocols,
/// set the item at the given string index to the given value. This
/// method raises a PythonException if the set operation fails.
/// </remarks>
public virtual void SetItem(string key, PyObject value) {
SetItem(new PyString(key), value);
}
/// <summary>
/// SetItem Method
/// </summary>
///
/// <remarks>
/// For objects that support the Python sequence or mapping protocols,
/// set the item at the given numeric index to the given value. This
/// method raises a PythonException if the set operation fails.
/// </remarks>
public virtual void SetItem(int index, PyObject value) {
SetItem(new PyInt(index), value);
}
/// <summary>
/// DelItem Method
/// </summary>
///
/// <remarks>
/// For objects that support the Python sequence or mapping protocols,
/// delete the item at the given object index. This method raises a
/// PythonException if the delete operation fails.
/// </remarks>
public virtual void DelItem(PyObject key) {
int r = Runtime.PyObject_DelItem(obj, key.obj);
if (r < 0) {
throw new PythonException();
}
}
/// <summary>
/// DelItem Method
/// </summary>
///
/// <remarks>
/// For objects that support the Python sequence or mapping protocols,
/// delete the item at the given string index. This method raises a
/// PythonException if the delete operation fails.
/// </remarks>
public virtual void DelItem(string key) {
DelItem(new PyString(key));
}
/// <summary>
/// DelItem Method
/// </summary>
///
/// <remarks>
/// For objects that support the Python sequence or mapping protocols,
/// delete the item at the given numeric index. This method raises a
/// PythonException if the delete operation fails.
/// </remarks>
public virtual void DelItem(int index) {
DelItem(new PyInt(index));
}
/// <summary>
/// Length Method
/// </summary>
///
/// <remarks>
/// Returns the length for objects that support the Python sequence
/// protocol, or 0 if the object does not support the protocol.
/// </remarks>
public virtual int Length() {
int s = Runtime.PyObject_Size(obj);
if (s < 0) {
Runtime.PyErr_Clear();
return 0;
}
return s;
}
/// <summary>
/// String Indexer
/// </summary>
///
/// <remarks>
/// Provides a shorthand for the string versions of the GetItem and
/// SetItem methods.
/// </remarks>
public virtual PyObject this[string key] {
get { return GetItem(key); }
set { SetItem(key, value); }
}
/// <summary>
/// PyObject Indexer
/// </summary>
///
/// <remarks>
/// Provides a shorthand for the object versions of the GetItem and
/// SetItem methods.
/// </remarks>
public virtual PyObject this[PyObject key] {
get { return GetItem(key); }
set { SetItem(key, value); }
}
/// <summary>
/// Numeric Indexer
/// </summary>
///
/// <remarks>
/// Provides a shorthand for the numeric versions of the GetItem and
/// SetItem methods.
/// </remarks>
public virtual PyObject this[int index] {
get { return GetItem(index); }
set { SetItem(index, value); }
}
/// <summary>
/// GetIterator Method
/// </summary>
///
/// <remarks>
/// Return a new (Python) iterator for the object. This is equivalent
/// to the Python expression "iter(object)". A PythonException will be
/// raised if the object cannot be iterated.
/// </remarks>
public PyObject GetIterator() {
IntPtr r = Runtime.PyObject_GetIter(obj);
if (r == IntPtr.Zero) {
throw new PythonException();
}
return new PyObject(r);
}
/// <summary>
/// Invoke Method
/// </summary>
///
/// <remarks>
/// Invoke the callable object with the given arguments, passed as a
/// PyObject[]. A PythonException is raised if the invokation fails.
/// </remarks>
public PyObject Invoke(params PyObject[] args) {
PyTuple t = new PyTuple(args);
IntPtr r = Runtime.PyObject_Call(obj, t.obj, IntPtr.Zero);
t.Dispose();
if (r == IntPtr.Zero) {
throw new PythonException();
}
return new PyObject(r);
}
/// <summary>
/// Invoke Method
/// </summary>
///
/// <remarks>
/// Invoke the callable object with the given arguments, passed as a
/// Python tuple. A PythonException is raised if the invokation fails.
/// </remarks>
public PyObject Invoke(PyTuple args) {
IntPtr r = Runtime.PyObject_Call(obj, args.obj, IntPtr.Zero);
if (r == IntPtr.Zero) {
throw new PythonException();
}
return new PyObject(r);
}
/// <summary>
/// Invoke Method
/// </summary>
///
/// <remarks>
/// Invoke the callable object with the given positional and keyword
/// arguments. A PythonException is raised if the invokation fails.
/// </remarks>
public PyObject Invoke(PyObject[] args, PyDict kw) {
PyTuple t = new PyTuple(args);
IntPtr r = Runtime.PyObject_Call(obj, t.obj, kw.obj);
t.Dispose();
if (r == IntPtr.Zero) {
throw new PythonException();
}
return new PyObject(r);
}
/// <summary>
/// Invoke Method
/// </summary>
///
/// <remarks>
/// Invoke the callable object with the given positional and keyword
/// arguments. A PythonException is raised if the invokation fails.
/// </remarks>
public PyObject Invoke(PyTuple args, PyDict kw) {
IntPtr r = Runtime.PyObject_Call(obj, args.obj, kw.obj);
if (r == IntPtr.Zero) {
throw new PythonException();
}
return new PyObject(r);
}
/// <summary>
/// InvokeMethod Method
/// </summary>
///
/// <remarks>
/// Invoke the named method of the object with the given arguments.
/// A PythonException is raised if the invokation is unsuccessful.
/// </remarks>
public PyObject InvokeMethod(string name, params PyObject[] args) {
PyObject method = GetAttr(name);
PyObject result = method.Invoke(args);
method.Dispose();
return result;
}
/// <summary>
/// InvokeMethod Method
/// </summary>
///
/// <remarks>
/// Invoke the named method of the object with the given arguments.
/// A PythonException is raised if the invokation is unsuccessful.
/// </remarks>
public PyObject InvokeMethod(string name, PyTuple args) {
PyObject method = GetAttr(name);
PyObject result = method.Invoke(args);
method.Dispose();
return result;
}
/// <summary>
/// InvokeMethod Method
/// </summary>
///
/// <remarks>
/// Invoke the named method of the object with the given arguments
/// and keyword arguments. Keyword args are passed as a PyDict object.
/// A PythonException is raised if the invokation is unsuccessful.
/// </remarks>
public PyObject InvokeMethod(string name, PyObject[] args, PyDict kw) {
PyObject method = GetAttr(name);
PyObject result = method.Invoke(args, kw);
method.Dispose();
return result;
}
/// <summary>
/// InvokeMethod Method
/// </summary>
///
/// <remarks>
/// Invoke the named method of the object with the given arguments
/// and keyword arguments. Keyword args are passed as a PyDict object.
/// A PythonException is raised if the invokation is unsuccessful.
/// </remarks>
public PyObject InvokeMethod(string name, PyTuple args, PyDict kw) {
PyObject method = GetAttr(name);
PyObject result = method.Invoke(args, kw);
method.Dispose();
return result;
}
/// <summary>
/// IsInstance Method
/// </summary>
///
/// <remarks>
/// Return true if the object is an instance of the given Python type
/// or class. This method always succeeds.
/// </remarks>
public bool IsInstance(PyObject typeOrClass) {
int r = Runtime.PyObject_IsInstance(obj, typeOrClass.obj);
if (r < 0) {
Runtime.PyErr_Clear();
return false;
}
return (r != 0);
}
/// <summary>
/// IsSubclass Method
/// </summary>
///
/// <remarks>
/// Return true if the object is identical to or derived from the
/// given Python type or class. This method always succeeds.
/// </remarks>
public bool IsSubclass(PyObject typeOrClass) {
int r = Runtime.PyObject_IsSubclass(obj, typeOrClass.obj);
if (r < 0) {
Runtime.PyErr_Clear();
return false;
}
return (r != 0);
}
/// <summary>
/// IsCallable Method
/// </summary>
///
/// <remarks>
/// Returns true if the object is a callable object. This method
/// always succeeds.
/// </remarks>
public bool IsCallable() {
return (Runtime.PyCallable_Check(obj) != 0);
}
/// <summary>
/// IsTrue Method
/// </summary>
///
/// <remarks>
/// Return true if the object is true according to Python semantics.
/// This method always succeeds.
/// </remarks>
public bool IsTrue() {
return (Runtime.PyObject_IsTrue(obj) != 0);
}
/// <summary>
/// Dir Method
/// </summary>
///
/// <remarks>
/// Return a list of the names of the attributes of the object. This
/// is equivalent to the Python expression "dir(object)".
/// </remarks>
public PyList Dir() {
IntPtr r = Runtime.PyObject_Dir(obj);
if (r == IntPtr.Zero) {
throw new PythonException();
}
return new PyList(r);
}
/// <summary>
/// Repr Method
/// </summary>
///
/// <remarks>
/// Return a string representation of the object. This method is
/// the managed equivalent of the Python expression "repr(object)".
/// </remarks>
public string Repr() {
IntPtr strval = Runtime.PyObject_Repr(obj);
string result = Runtime.GetManagedString(strval);
Runtime.Decref(strval);
return result;
}
/// <summary>
/// ToString Method
/// </summary>
///
/// <remarks>
/// Return the string representation of the object. This method is
/// the managed equivalent of the Python expression "str(object)".
/// </remarks>
public override string ToString() {
IntPtr strval = Runtime.PyObject_Str(obj);
string result = Runtime.GetManagedString(strval);
Runtime.Decref(strval);
return result;
}
/// <summary>
/// Equals Method
/// </summary>
///
/// <remarks>
/// Return true if this object is equal to the given object. This
/// method is based on Python equality semantics.
/// </remarks>
public override bool Equals(object o) {
if (!(o is PyObject)) {
return false;
}
if (obj == ((PyObject) o).obj) {
return true;
}
int r = Runtime.PyObject_Compare(obj, ((PyObject) o).obj);
if (Exceptions.ErrorOccurred()) {
throw new PythonException();
}
return (r == 0);
}
/// <summary>
/// GetHashCode Method
/// </summary>
///
/// <remarks>
/// Return a hashcode based on the Python object. This returns the
/// hash as computed by Python, equivalent to the Python expression
/// "hash(obj)".
/// </remarks>
public override int GetHashCode() {
return Runtime.PyObject_Hash(obj).ToInt32();
}
}
}

Просмотреть файл

@ -0,0 +1,167 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
namespace Python.Runtime {
/// <summary>
/// Represents a generic Python sequence. The methods of this class are
/// equivalent to the Python "abstract sequence API". See
/// http://www.python.org/doc/current/api/sequence.html for details.
/// </summary>
public class PySequence : PyObject {
protected PySequence(IntPtr ptr) : base(ptr) {}
protected PySequence() : base() {}
/// <summary>
/// IsSequenceType Method
/// </summary>
///
/// <remarks>
/// Returns true if the given object implements the sequence protocol.
/// </remarks>
public static bool IsSequenceType(PyObject value) {
return Runtime.PySequence_Check(value.obj);
}
/// <summary>
/// GetSlice Method
/// </summary>
///
/// <remarks>
/// Return the slice of the sequence with the given indices.
/// </remarks>
public PyObject GetSlice(int i1, int i2) {
IntPtr op = Runtime.PySequence_GetSlice(obj, i1, i2);
if (op == IntPtr.Zero) {
throw new PythonException();
}
return new PyObject(op);
}
/// <summary>
/// SetSlice Method
/// </summary>
///
/// <remarks>
/// Sets the slice of the sequence with the given indices.
/// </remarks>
public void SetSlice(int i1, int i2, PyObject v) {
int r = Runtime.PySequence_SetSlice(obj, i1, i2, v.obj);
if (r < 0) {
throw new PythonException();
}
}
/// <summary>
/// DelSlice Method
/// </summary>
///
/// <remarks>
/// Deletes the slice of the sequence with the given indices.
/// </remarks>
public void DelSlice(int i1, int i2) {
int r = Runtime.PySequence_DelSlice(obj, i1, i2);
if (r < 0) {
throw new PythonException();
}
}
/// <summary>
/// Index Method
/// </summary>
///
/// <remarks>
/// Return the index of the given item in the sequence, or -1 if
/// the item does not appear in the sequence.
/// </remarks>
public int Index(PyObject item) {
int r = Runtime.PySequence_Index(obj, item.obj);
if (r < 0) {
Runtime.PyErr_Clear();
return -1;
}
return r;
}
/// <summary>
/// Contains Method
/// </summary>
///
/// <remarks>
/// Return true if the sequence contains the given item. This method
/// throws a PythonException if an error occurs during the check.
/// </remarks>
public bool Contains(PyObject item) {
int r = Runtime.PySequence_Contains(obj, item.obj);
if (r < 0) {
throw new PythonException();
}
return (r != 0);
}
/// <summary>
/// Concat Method
/// </summary>
///
/// <remarks>
/// Return the concatenation of the sequence object with the passed in
/// sequence object.
/// </remarks>
public PyObject Concat(PyObject other) {
IntPtr op = Runtime.PySequence_Concat(obj, other.obj);
if (op == IntPtr.Zero) {
throw new PythonException();
}
return new PyObject(op);
}
/// <summary>
/// Repeat Method
/// </summary>
///
/// <remarks>
/// Return the sequence object repeated N times. This is equivalent
/// to the Python expression "object * count".
/// </remarks>
public PyObject Repeat(int count) {
IntPtr op = Runtime.PySequence_Repeat(obj, count);
if (op == IntPtr.Zero) {
throw new PythonException();
}
return new PyObject(op);
}
}
}

Просмотреть файл

@ -0,0 +1,86 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
namespace Python.Runtime {
/// <summary>
/// Represents a Python (ansi) string object. See the documentation at
/// http://www.python.org/doc/current/api/stringObjects.html for details.
/// </summary>
public class PyString : PySequence {
/// <summary>
/// PyString Constructor
/// </summary>
///
/// <remarks>
/// Creates a new PyString from an existing object reference. Note
/// that the instance assumes ownership of the object reference.
/// The object reference is not checked for type-correctness.
/// </remarks>
public PyString(IntPtr ptr) : base(ptr) {}
/// <summary>
/// PyString Constructor
/// </summary>
///
/// <remarks>
/// Copy constructor - obtain a PyString from a generic PyObject.
/// An ArgumentException will be thrown if the given object is not
/// a Python string object.
/// </remarks>
public PyString(PyObject o) : base() {
if (!IsStringType(o)) {
throw new ArgumentException("object is not a string");
}
Runtime.Incref(o.obj);
obj = o.obj;
}
/// <summary>
/// PyString Constructor
/// </summary>
///
/// <remarks>
/// Creates a Python string from a managed string.
/// </remarks>
public PyString(string s) : base() {
obj = Runtime.PyString_FromStringAndSize(s, s.Length);
if (obj == IntPtr.Zero) {
throw new PythonException();
}
}
/// <summary>
/// IsStringType Method
/// </summary>
///
/// <remarks>
/// Returns true if the given object is a Python string.
/// </remarks>
public static bool IsStringType(PyObject value) {
return Runtime.PyString_Check(value.obj);
}
}
}

Просмотреть файл

@ -0,0 +1,339 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Threading;
namespace Python.Runtime {
/// <summary>
/// This class provides the public interface of the Python runtime.
/// </summary>
public class PythonEngine {
private static bool initialized;
#region Properties
public static bool IsInitialized {
get {
return initialized;
}
}
public static string ProgramName {
get {
string result = Runtime.Py_GetProgramName();
if (result == null) {
return "";
}
return result;
}
set {
Runtime.Py_SetProgramName(value);
}
}
public static string PythonHome {
get {
string result = Runtime.Py_GetPythonHome();
if (result == null) {
return "";
}
return result;
}
set {
Runtime.Py_SetPythonHome(value);
}
}
public static string Version {
get {
return Runtime.Py_GetVersion();
}
}
public static string BuildInfo {
get {
return Runtime.Py_GetBuildInfo();
}
}
public static string Platform {
get {
return Runtime.Py_GetPlatform();
}
}
public static string Copyright {
get {
return Runtime.Py_GetCopyright();
}
}
public static int RunSimpleString(string code) {
return Runtime.PyRun_SimpleString(code);
}
#endregion
/// <summary>
/// Initialize Method
/// </summary>
///
/// <remarks>
/// Initialize the Python runtime. It is safe to call this method
/// more than once, though initialization will only happen on the
/// first call. It is *not* necessary to hold the Python global
/// interpreter lock (GIL) to call this method.
/// </remarks>
public static void Initialize() {
if (!initialized) {
Runtime.Initialize();
initialized = true;
Exceptions.Clear();
}
}
//====================================================================
// A helper to perform initialization from the context of an active
// CPython interpreter process - this bootstraps the managed runtime
// when it is imported by the CLR extension module.
//====================================================================
public static void InitExt() {
Initialize();
// Trickery - when the import hook is installed into an already
// running Python, the standard import machinery is still in
// control for the duration of the import that caused bootstrap.
//
// That is problematic because the std machinery tries to get
// sub-names directly from the module __dict__ rather than going
// through our module object's getattr hook. This workaround is
// evil ;) We essentially climb up the stack looking for the
// import that caused the bootstrap to happen, then re-execute
// the import explicitly after our hook has been installed. By
// doing this, the original outer import should work correctly.
//
// Note that this is only needed during the execution of the
// first import that installs the CLR import hook. This hack
// still doesn't work if you use the interactive interpreter,
// since there is no line info to get the import line ;(
string code =
"import traceback\n" +
"for item in traceback.extract_stack():\n" +
" line = item[3]\n" +
" if line is not None:\n" +
" if line.startswith('import CLR') or \\\n" +
" line.startswith('from CLR'):\n" +
" exec line\n" +
" break\n";
PyObject r = PythonEngine.RunString(code);
if (r != null) {
r.Dispose();
}
}
/// <summary>
/// Shutdown Method
/// </summary>
///
/// <remarks>
/// Shutdown and release resources held by the Python runtime. The
/// Python runtime can no longer be used in the current process
/// after calling the Shutdown method.
/// </remarks>
public static void Shutdown() {
if (initialized) {
Runtime.Shutdown();
initialized = false;
}
}
/// <summary>
/// AcquireLock Method
/// </summary>
///
/// <remarks>
/// Acquire the Python global interpreter lock (GIL). Managed code
/// *must* call this method before using any objects or calling any
/// methods on objects in the Python.Runtime namespace. The only
/// exception is PythonEngine.Initialize, which may be called without
/// first calling AcquireLock.
///
/// Each call to AcquireLock must be matched by a corresponding call
/// to ReleaseLock, passing the token obtained from AcquireLock.
///
/// For more information, see the "Extending and Embedding" section
/// of the Python documentation on www.python.org.
/// </remarks>
public static IntPtr AcquireLock() {
return Runtime.PyGILState_Ensure();
}
/// <summary>
/// ReleaseLock Method
/// </summary>
///
/// <remarks>
/// Release the Python global interpreter lock using a token obtained
/// from a previous call to AcquireLock.
///
/// For more information, see the "Extending and Embedding" section
/// of the Python documentation on www.python.org.
/// </remarks>
public static void ReleaseLock(IntPtr gs) {
Runtime.PyGILState_Release(gs);
}
/// <summary>
/// BeginAllowThreads Method
/// </summary>
///
/// <remarks>
/// Release the Python global interpreter lock to allow other threads
/// to run. This is equivalent to the Py_BEGIN_ALLOW_THREADS macro
/// provided by the C Python API.
///
/// For more information, see the "Extending and Embedding" section
/// of the Python documentation on www.python.org.
/// </remarks>
public static IntPtr BeginAllowThreads() {
return Runtime.PyEval_SaveThread();
}
/// <summary>
/// EndAllowThreads Method
/// </summary>
///
/// <remarks>
/// Re-aquire the Python global interpreter lock for the current
/// thread. This is equivalent to the Py_END_ALLOW_THREADS macro
/// provided by the C Python API.
///
/// For more information, see the "Extending and Embedding" section
/// of the Python documentation on www.python.org.
/// </remarks>
public static void EndAllowThreads(IntPtr ts) {
Runtime.PyEval_RestoreThread(ts);
}
/// <summary>
/// ImportModule Method
/// </summary>
///
/// <remarks>
/// Given a fully-qualified module or package name, import the
/// module and return the resulting module object as a PyObject
/// or null if an exception is raised.
/// </remarks>
public static PyObject ImportModule(string name) {
IntPtr op = Runtime.PyImport_ImportModule(name);
if (op == IntPtr.Zero) {
return null;
}
return new PyObject(op);
}
/// <summary>
/// ReloadModule Method
/// </summary>
///
/// <remarks>
/// Given a PyObject representing a previously loaded module, reload
/// the module.
/// </remarks>
public static PyObject ReloadModule(PyObject module) {
IntPtr op = Runtime.PyImport_ReloadModule(module.Handle);
if (op == IntPtr.Zero) {
throw new PythonException();
}
return new PyObject(op);
}
/// <summary>
/// ModuleFromString Method
/// </summary>
///
/// <remarks>
/// Given a string module name and a string containing Python code,
/// execute the code in and return a module of the given name.
/// </remarks>
public static PyObject ModuleFromString(string name, string code) {
IntPtr c = Runtime.Py_CompileString(code, "none", (IntPtr)257);
if (c == IntPtr.Zero) {
throw new PythonException();
}
IntPtr m = Runtime.PyImport_ExecCodeModule(name, c);
if (m == IntPtr.Zero) {
throw new PythonException();
}
return new PyObject(m);
}
/// <summary>
/// RunString Method
/// </summary>
///
/// <remarks>
/// Run a string containing Python code. Returns the result of
/// executing the code string as a PyObject instance, or null if
/// an exception was raised.
/// </remarks>
public static PyObject RunString(string code) {
IntPtr globals = Runtime.PyEval_GetGlobals();
IntPtr locals = Runtime.PyDict_New();
IntPtr builtins = Runtime.PyEval_GetBuiltins();
Runtime.PyDict_SetItemString(locals, "__builtins__", builtins);
IntPtr flag = (IntPtr)257; /* Py_file_input */
IntPtr result = Runtime.PyRun_String(code, flag, globals, locals);
Runtime.Decref(locals);
if (result == IntPtr.Zero) {
return null;
}
return new PyObject(result);
}
}
}

Просмотреть файл

@ -0,0 +1,126 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
namespace Python.Runtime {
/// <summary>
/// Provides a managed interface to exceptions thrown by the Python
/// runtime.
/// </summary>
public class PythonException : System.Exception {
private IntPtr excType = IntPtr.Zero;
private IntPtr excValue = IntPtr.Zero;
private IntPtr excTb = IntPtr.Zero;
private bool disposed = false;
public PythonException() : base() {
Runtime.PyErr_Fetch(ref excType, ref excValue, ref excTb);
Runtime.Incref(excType);
Runtime.Incref(excValue);
Runtime.Incref(excTb);
}
// Ensure that encapsulated Python objects are decref'ed appropriately
// when the managed exception wrapper is garbage-collected.
~PythonException() {
Dispose();
}
/// <summary>
/// Type Property
/// </summary>
///
/// <remarks>
/// Returns the exception type as a Python object.
/// </remarks>
public IntPtr Type {
get {
return excType;
}
}
/// <summary>
/// Value Property
/// </summary>
///
/// <remarks>
/// Returns the exception value as a Python object.
/// </remarks>
public IntPtr Value {
get {
return excValue;
}
}
/// <summary>
/// Traceback Property
/// </summary>
///
/// <remarks>
/// Returns the exception traceback as a Python object.
/// </remarks>
public IntPtr Traceback {
get {
return excTb;
}
}
/// <summary>
/// Dispose Method
/// </summary>
///
/// <remarks>
/// The Dispose method provides a way to explicitly release the
/// Python objects represented by a PythonException.
/// </remarks>
public void Dispose() {
if (!disposed) {
if (Runtime.Py_IsInitialized() > 0) {
IntPtr gs = PythonEngine.AcquireLock();
Runtime.Decref(excType);
Runtime.Decref(excValue);
Runtime.Decref(excTb);
PythonEngine.ReleaseLock(gs);
}
GC.SuppressFinalize(this);
disposed = true;
}
}
/// <summary>
/// Matches Method
/// </summary>
///
/// <remarks>
/// Returns true if the Python exception type represented by the
/// PythonException instance matches the given exception type.
/// </remarks>
public static bool Matches(IntPtr ob) {
return Runtime.PyErr_ExceptionMatches(ob) != 0;
}
}
}

Просмотреть файл

@ -0,0 +1,128 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
namespace Python.Runtime {
/// <summary>
/// Represents a Python tuple object. See the documentation at
/// http://www.python.org/doc/current/api/tupleObjects.html for details.
/// </summary>
public class PyTuple : PySequence {
/// <summary>
/// PyTuple Constructor
/// </summary>
///
/// <remarks>
/// Creates a new PyTuple from an existing object reference. Note
/// that the instance assumes ownership of the object reference.
/// The object reference is not checked for type-correctness.
/// </remarks>
public PyTuple(IntPtr ptr) : base(ptr) {}
/// <summary>
/// PyTuple Constructor
/// </summary>
///
/// <remarks>
/// Copy constructor - obtain a PyTuple from a generic PyObject. An
/// ArgumentException will be thrown if the given object is not a
/// Python tuple object.
/// </remarks>
public PyTuple(PyObject o) : base() {
if (!IsTupleType(o)) {
throw new ArgumentException("object is not a tuple");
}
Runtime.Incref(o.obj);
obj = o.obj;
}
/// <summary>
/// PyTuple Constructor
/// </summary>
///
/// <remarks>
/// Creates a new empty PyTuple.
/// </remarks>
public PyTuple() : base() {
obj = Runtime.PyTuple_New(0);
if (obj == IntPtr.Zero) {
throw new PythonException();
}
}
/// <summary>
/// PyTuple Constructor
/// </summary>
///
/// <remarks>
/// Creates a new PyTuple from an array of PyObject instances.
/// </remarks>
public PyTuple(PyObject[] items) : base() {
int count = items.Length;
obj = Runtime.PyTuple_New(count);
for (int i = 0; i < count; i++) {
IntPtr ptr = items[i].obj;
Runtime.Incref(ptr);
int r = Runtime.PyTuple_SetItem(obj, i, ptr);
if (r < 0) {
throw new PythonException();
}
}
}
/// <summary>
/// IsTupleType Method
/// </summary>
///
/// <remarks>
/// Returns true if the given object is a Python tuple.
/// </remarks>
public static bool IsTupleType(PyObject value) {
return Runtime.PyTuple_Check(value.obj);
}
/// <summary>
/// AsTuple Method
/// </summary>
///
/// <remarks>
/// Convert a Python object to a Python tuple if possible, raising
/// a PythonException if the conversion is not possible. This is
/// equivalent to the Python expression "tuple(object)".
/// </remarks>
public static PyTuple AsTuple(PyObject value) {
IntPtr op = Runtime.PySequence_Tuple(value.obj);
if (op == IntPtr.Zero) {
throw new PythonException();
}
return new PyTuple(op);
}
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,444 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Runtime.InteropServices;
using System.Reflection.Emit;
using System.Collections;
using System.Reflection;
using System.Threading;
namespace Python.Runtime {
//=======================================================================
// The TypeManager class is responsible for building binary-compatible
// Python type objects that are implemented in managed code.
//=======================================================================
internal class TypeManager {
static BindingFlags tbFlags;
static Hashtable cache;
static int obSize;
static TypeManager() {
tbFlags = BindingFlags.Public | BindingFlags.Static;
obSize = 4 * IntPtr.Size;
cache = new Hashtable();
}
//====================================================================
// Given a managed Type derived from ExtensionType, get the handle to
// a Python type object that delegates its implementation to the Type
// object. These Python type instances are used to implement internal
// descriptor and utility types like ModuleObject, PropertyObject, etc.
//====================================================================
internal static IntPtr GetTypeHandle(Type type) {
// Note that these types are cached with a refcount of 1, so they
// effectively exist until the CPython runtime is finalized. We
Object ob = cache[type];
if (ob != null) {
return (IntPtr) ob;
}
IntPtr tp = CreateType(type);
cache[type] = tp;
return tp;
}
//====================================================================
// Get the handle of a Python type that reflects the given CLR type.
// The given ManagedType instance is a managed object that implements
// the appropriate semantics in Python for the reflected managed type.
//====================================================================
internal static IntPtr GetTypeHandle(ManagedType obj, Type clrType) {
Object ob = cache[clrType];
if (ob != null) {
return (IntPtr) ob;
}
IntPtr tp = CreateType(obj, clrType);
cache[clrType] = tp;
return tp;
}
//====================================================================
// The following CreateType implementations do the necessary work to
// create Python types to represent managed extension types, reflected
// types, subclasses of reflected types and the managed metatype. The
// dance is slightly different for each kind of type due to different
// behavior needed and the desire to have the existing Python runtime
// do as much of the allocation and initialization work as possible.
//====================================================================
internal static IntPtr CreateType(Type impl) {
IntPtr type = AllocateTypeObject(impl.Name);
// Set tp_basicsize to the size of our managed instance objects.
Marshal.WriteIntPtr(type, TypeOffset.tp_basicsize, (IntPtr)obSize);
IntPtr offset = (IntPtr)ObjectOffset.ob_dict;
Marshal.WriteIntPtr(type, TypeOffset.tp_dictoffset, offset);
InitializeSlots(type, impl);
int flags = TypeFlags.Default | TypeFlags.Managed |
TypeFlags.HeapType | TypeFlags.HaveGC;
Marshal.WriteIntPtr(type, TypeOffset.tp_flags, (IntPtr)flags);
Runtime.PyType_Ready(type);
IntPtr dict = Marshal.ReadIntPtr(type, TypeOffset.tp_dict);
IntPtr mod = Runtime.PyString_FromString("CLR");
Runtime.PyDict_SetItemString(dict, "__module__", mod);
InitMethods(type, impl);
return type;
}
internal static IntPtr CreateType(ManagedType impl, Type clrType) {
// Cleanup the type name to get rid of funny nested type names.
string name = "CLR." + clrType.FullName;
int i = name.LastIndexOf('+');
if (i > -1) {
name = name.Substring(i + 1);
}
i = name.LastIndexOf('.');
if (i > -1) {
name = name.Substring(i + 1);
}
IntPtr base_ = IntPtr.Zero;
if (clrType.BaseType != null) {
ClassBase bc = ClassManager.GetClass(clrType.BaseType);
base_ = bc.pyHandle;
}
IntPtr type = AllocateTypeObject(name);
Marshal.WriteIntPtr(type,TypeOffset.ob_type,Runtime.PyCLRMetaType);
Runtime.Incref(Runtime.PyCLRMetaType);
Marshal.WriteIntPtr(type, TypeOffset.tp_basicsize, (IntPtr)obSize);
Marshal.WriteIntPtr(type, TypeOffset.tp_itemsize, IntPtr.Zero);
IntPtr offset = (IntPtr)ObjectOffset.ob_dict;
Marshal.WriteIntPtr(type, TypeOffset.tp_dictoffset, offset);
InitializeSlots(type, impl.GetType());
if (base_ != IntPtr.Zero) {
Marshal.WriteIntPtr(type, TypeOffset.tp_base, base_);
Runtime.Incref(base_);
}
int flags = TypeFlags.Default;
flags |= TypeFlags.Managed;
flags |= TypeFlags.HeapType;
flags |= TypeFlags.BaseType;
flags |= TypeFlags.HaveGC;
Marshal.WriteIntPtr(type, TypeOffset.tp_flags, (IntPtr)flags);
// Leverage followup initialization from the Python runtime. Note
// that the type of the new type must PyType_Type at the time we
// call this, else PyType_Ready will skip some slot initialization.
Runtime.PyType_Ready(type);
IntPtr dict = Marshal.ReadIntPtr(type, TypeOffset.tp_dict);
string mn = "CLR." + clrType.Namespace;
IntPtr mod = Runtime.PyString_FromString(mn);
Runtime.PyDict_SetItemString(dict, "__module__", mod);
// Hide the gchandle of the implementation in a magic type slot.
GCHandle gc = GCHandle.Alloc(impl);
Marshal.WriteIntPtr(type, TypeOffset.magic(), (IntPtr)gc);
// Set the handle attributes on the implementing instance.
impl.tpHandle = Runtime.PyCLRMetaType;
impl.gcHandle = gc;
impl.pyHandle = type;
//DebugUtil.DumpType(type);
return type;
}
internal static IntPtr CreateSubType(IntPtr args) {
IntPtr py_name = Runtime.PyTuple_GetItem(args, 0);
IntPtr bases = Runtime.PyTuple_GetItem(args, 1);
IntPtr dict = Runtime.PyTuple_GetItem(args, 2);
IntPtr base_ = Runtime.PyTuple_GetItem(bases, 0);
string name = Runtime.GetManagedString(py_name);
IntPtr type = AllocateTypeObject(name);
Marshal.WriteIntPtr(type,TypeOffset.ob_type,Runtime.PyCLRMetaType);
Runtime.Incref(Runtime.PyCLRMetaType);
Marshal.WriteIntPtr(type, TypeOffset.tp_basicsize, (IntPtr)obSize);
Marshal.WriteIntPtr(type, TypeOffset.tp_itemsize, IntPtr.Zero);
IntPtr offset = (IntPtr)ObjectOffset.ob_dict;
Marshal.WriteIntPtr(type, TypeOffset.tp_dictoffset, offset);
IntPtr dc = Runtime.PyDict_Copy(dict);
Marshal.WriteIntPtr(type, TypeOffset.tp_dict, dc);
Marshal.WriteIntPtr(type, TypeOffset.tp_base, base_);
Runtime.Incref(base_);
int flags = TypeFlags.Default;
flags |= TypeFlags.Managed;
flags |= TypeFlags.HeapType;
flags |= TypeFlags.BaseType;
flags |= TypeFlags.Subclass;
flags |= TypeFlags.HaveGC;
Marshal.WriteIntPtr(type, TypeOffset.tp_flags, (IntPtr)flags);
CopySlot(base_, type, TypeOffset.tp_traverse);
CopySlot(base_, type, TypeOffset.tp_clear);
CopySlot(base_, type, TypeOffset.tp_is_gc);
Runtime.PyType_Ready(type);
IntPtr tp_dict = Marshal.ReadIntPtr(type, TypeOffset.tp_dict);
IntPtr mod = Runtime.PyString_FromString("CLR");
Runtime.PyDict_SetItemString(tp_dict, "__module__", mod);
// for now, move up hidden handle...
IntPtr gc = Marshal.ReadIntPtr(base_, TypeOffset.magic());
Marshal.WriteIntPtr(type, TypeOffset.magic(), gc);
return type;
}
internal static IntPtr CreateMetaType(Type impl) {
// The managed metatype is functionally little different than the
// standard Python metatype (PyType_Type). It overrides certain of
// the standard type slots, and has to subclass PyType_Type for
// certain functions in the C runtime to work correctly with it.
IntPtr type = AllocateTypeObject("CLR Metatype");
IntPtr py_type = Runtime.PyTypeType;
Marshal.WriteIntPtr(type, TypeOffset.tp_base, py_type);
Runtime.Incref(py_type);
// Copy gc and other type slots from the base Python metatype.
CopySlot(py_type, type, TypeOffset.tp_basicsize);
CopySlot(py_type, type, TypeOffset.tp_itemsize);
CopySlot(py_type, type, TypeOffset.tp_dictoffset);
CopySlot(py_type, type, TypeOffset.tp_weaklistoffset);
CopySlot(py_type, type, TypeOffset.tp_traverse);
CopySlot(py_type, type, TypeOffset.tp_clear);
CopySlot(py_type, type, TypeOffset.tp_is_gc);
// Override type slots with those of the managed implementation.
InitializeSlots(type, impl);
int flags = TypeFlags.Default;
flags |= TypeFlags.Managed;
flags |= TypeFlags.HeapType;
flags |= TypeFlags.HaveGC;
Marshal.WriteIntPtr(type, TypeOffset.tp_flags, (IntPtr)flags);
Runtime.PyType_Ready(type);
IntPtr dict = Marshal.ReadIntPtr(type, TypeOffset.tp_dict);
IntPtr mod = Runtime.PyString_FromString("CLR");
Runtime.PyDict_SetItemString(dict, "__module__", mod);
//DebugUtil.DumpType(type);
return type;
}
internal static IntPtr BasicSubType(string name, IntPtr base_,
Type impl) {
// Utility to create a subtype of a std Python type, but with
// a managed type able to override implementation
IntPtr type = AllocateTypeObject(name);
//Marshal.WriteIntPtr(type, TypeOffset.tp_basicsize, (IntPtr)obSize);
//Marshal.WriteIntPtr(type, TypeOffset.tp_itemsize, IntPtr.Zero);
//IntPtr offset = (IntPtr)ObjectOffset.ob_dict;
//Marshal.WriteIntPtr(type, TypeOffset.tp_dictoffset, offset);
//IntPtr dc = Runtime.PyDict_Copy(dict);
//Marshal.WriteIntPtr(type, TypeOffset.tp_dict, dc);
Marshal.WriteIntPtr(type, TypeOffset.tp_base, base_);
Runtime.Incref(base_);
int flags = TypeFlags.Default;
flags |= TypeFlags.Managed;
flags |= TypeFlags.HeapType;
flags |= TypeFlags.HaveGC;
Marshal.WriteIntPtr(type, TypeOffset.tp_flags, (IntPtr)flags);
CopySlot(base_, type, TypeOffset.tp_traverse);
CopySlot(base_, type, TypeOffset.tp_clear);
CopySlot(base_, type, TypeOffset.tp_is_gc);
InitializeSlots(type, impl);
Runtime.PyType_Ready(type);
IntPtr tp_dict = Marshal.ReadIntPtr(type, TypeOffset.tp_dict);
IntPtr mod = Runtime.PyString_FromString("CLR");
Runtime.PyDict_SetItemString(tp_dict, "__module__", mod);
return type;
}
//====================================================================
// Utility method to allocate a type object & do basic initialization.
//====================================================================
internal static IntPtr AllocateTypeObject(string name) {
IntPtr type = Runtime.PyType_GenericAlloc(Runtime.PyTypeType, 0);
// Cheat a little: we'll set tp_name to the internal char * of
// the Python version of the type name - otherwise we'd have to
// allocate the tp_name and would have no way to free it.
IntPtr temp = Runtime.PyString_FromString(name);
IntPtr raw = Runtime.PyString_AS_STRING(temp);
Marshal.WriteIntPtr(type, TypeOffset.tp_name, raw);
Marshal.WriteIntPtr(type, TypeOffset.name, temp);
long ptr = type.ToInt64(); // 64-bit safe
temp = new IntPtr(ptr + TypeOffset.nb_add);
Marshal.WriteIntPtr(type, TypeOffset.tp_as_number, temp);
temp = new IntPtr(ptr + TypeOffset.sq_length);
Marshal.WriteIntPtr(type, TypeOffset.tp_as_sequence, temp);
temp = new IntPtr(ptr + TypeOffset.mp_length);
Marshal.WriteIntPtr(type, TypeOffset.tp_as_mapping, temp);
temp = new IntPtr(ptr + TypeOffset.bf_getreadbuffer);
Marshal.WriteIntPtr(type, TypeOffset.tp_as_buffer, temp);
return type;
}
//====================================================================
// Given a newly allocated Python type object and a managed Type that
// provides the implementation for the type, connect the type slots of
// the Python object to the managed methods of the implementing Type.
//====================================================================
internal static void InitializeSlots(IntPtr type, Type impl) {
Hashtable seen = new Hashtable(8);
Type offsetType = typeof(TypeOffset);
while (impl != null) {
MethodInfo[] methods = impl.GetMethods(tbFlags);
for (int i = 0; i < methods.Length; i++) {
MethodInfo method = methods[i];
string name = method.Name;
if (! (name.StartsWith("tp_") ||
name.StartsWith("nb_") ||
name.StartsWith("sq_") ||
name.StartsWith("mp_") ||
name.StartsWith("bf_")
) ) {
continue;
}
if (seen[name] != null) {
continue;
}
FieldInfo fi = offsetType.GetField(name);
int offset = (int)fi.GetValue(offsetType);
IntPtr slot = Interop.GetThunk(method);
Marshal.WriteIntPtr(type, offset, slot);
seen[name] = 1;
}
impl = impl.BaseType;
}
}
//====================================================================
// Given a newly allocated Python type object and a managed Type that
// implements it, initialize any methods defined by the Type that need
// to appear in the Python type __dict__ (based on custom attribute).
//====================================================================
private static void InitMethods(IntPtr pytype, Type type) {
IntPtr dict = Marshal.ReadIntPtr(pytype, TypeOffset.tp_dict);
Type marker = typeof(PythonMethodAttribute);
BindingFlags flags = BindingFlags.Public | BindingFlags.Static;
while (type != null) {
MethodInfo[] methods = type.GetMethods(flags);
for (int i = 0; i < methods.Length; i++) {
MethodInfo method = methods[i];
object[] attrs = method.GetCustomAttributes(marker, false);
if (attrs.Length > 0) {
string method_name = method.Name;
MethodInfo[] mi = new MethodInfo[1];
mi[0] = method;
MethodObject m = new TypeMethod(method_name, mi);
Runtime.PyDict_SetItemString(dict, method_name,
m.pyHandle);
}
}
type = type.BaseType;
}
}
//====================================================================
// Utility method to copy slots from a given type to another type.
//====================================================================
internal static void CopySlot(IntPtr from, IntPtr to, int offset) {
IntPtr fp = Marshal.ReadIntPtr(from, offset);
Marshal.WriteIntPtr(to, offset, fp);
}
}
}

Просмотреть файл

@ -0,0 +1,53 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Collections;
using System.Reflection;
namespace Python.Runtime {
//========================================================================
// Implements a Python type that provides access to CLR object methods.
//========================================================================
internal class TypeMethod : MethodObject {
public TypeMethod(string name, MethodInfo[] info) :
base(name, info) {}
public override IntPtr Invoke(IntPtr ob, IntPtr args, IntPtr kw) {
MethodInfo mi = this.info[0];
Object[] arglist = new Object[3];
arglist[0] = ob;
arglist[1] = args;
arglist[2] = kw;
try {
Object inst = null;
if (ob != IntPtr.Zero) {
inst = GetManagedObject(ob);
}
return (IntPtr)mi.Invoke(inst, BindingFlags.Default, null, arglist,
null);
}
catch (Exception e) {
Exceptions.SetError(e);
return IntPtr.Zero;
}
}
}
}

Просмотреть файл

@ -0,0 +1,333 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Collections;
namespace Python.Test {
//========================================================================
// Supports units tests for indexer access.
//========================================================================
public class PublicArrayTest {
public int[] items;
public PublicArrayTest() {
items = new int[5] {0, 1, 2, 3, 4};
}
}
public class ProtectedArrayTest {
protected int[] items;
public ProtectedArrayTest() {
items = new int[5] {0, 1, 2, 3, 4};
}
}
public class InternalArrayTest {
internal int[] items;
public InternalArrayTest() {
items = new int[5] {0, 1, 2, 3, 4};
}
}
public class PrivateArrayTest {
private int[] items;
public PrivateArrayTest() {
items = new int[5] {0, 1, 2, 3, 4};
}
}
public class BooleanArrayTest {
public bool[] items;
public BooleanArrayTest() {
items = new bool[5] {true, false, true, false, true};
}
}
public class ByteArrayTest {
public byte[] items;
public ByteArrayTest() {
items = new byte[5] {0, 1, 2, 3, 4};
}
}
public class SByteArrayTest {
public sbyte[] items;
public SByteArrayTest() {
items = new sbyte[5] {0, 1, 2, 3, 4};
}
}
public class CharArrayTest {
public char[] items;
public CharArrayTest() {
items = new char[5] {'a', 'b', 'c', 'd', 'e'};
}
}
public class Int16ArrayTest {
public short[] items;
public Int16ArrayTest() {
items = new short[5] {0, 1, 2, 3, 4};
}
}
public class Int32ArrayTest {
public int[] items;
public Int32ArrayTest() {
items = new int[5] {0, 1, 2, 3, 4};
}
}
public class Int64ArrayTest {
public long[] items;
public Int64ArrayTest() {
items = new long[5] {0, 1, 2, 3, 4};
}
}
public class UInt16ArrayTest {
public ushort[] items;
public UInt16ArrayTest() {
items = new ushort[5] {0, 1, 2, 3, 4};
}
}
public class UInt32ArrayTest {
public uint[] items;
public UInt32ArrayTest() {
items = new uint[5] {0, 1, 2, 3, 4};
}
}
public class UInt64ArrayTest {
public ulong[] items;
public UInt64ArrayTest() {
items = new ulong[5] {0, 1, 2, 3, 4};
}
}
public class SingleArrayTest {
public float[] items;
public SingleArrayTest() {
items = new float[5] {0.0F, 1.0F, 2.0F, 3.0F, 4.0F};
}
}
public class DoubleArrayTest {
public double[] items;
public DoubleArrayTest() {
items = new double[5] {0.0, 1.0, 2.0, 3.0, 4.0};
}
}
public class DecimalArrayTest {
public decimal[] items;
public DecimalArrayTest() {
items = new decimal[5] {0, 1, 2, 3, 4};
}
}
public class StringArrayTest {
public string[] items;
public StringArrayTest() {
items = new string[5] {"0", "1", "2", "3", "4"};
}
}
public class EnumArrayTest {
public ShortEnum[] items;
public EnumArrayTest() {
items = new ShortEnum[5]
{ ShortEnum.Zero,
ShortEnum.One,
ShortEnum.Two,
ShortEnum.Three,
ShortEnum.Four};
}
}
public class NullArrayTest {
public object[] items;
public object[] empty;
public NullArrayTest() {
items = new object[5] {null, null, null, null, null};
empty = new object[0] {};
}
}
public class ObjectArrayTest {
public object[] items;
public ObjectArrayTest() {
items = new object[5];
items[0] = new Spam("0");
items[1] = new Spam("1");
items[2] = new Spam("2");
items[3] = new Spam("3");
items[4] = new Spam("4");
}
}
public class InterfaceArrayTest {
public ISpam[] items;
public InterfaceArrayTest() {
items = new ISpam[5];
items[0] = new Spam("0");
items[1] = new Spam("1");
items[2] = new Spam("2");
items[3] = new Spam("3");
items[4] = new Spam("4");
}
}
public class TypedArrayTest {
public Spam[] items;
public TypedArrayTest() {
items = new Spam[5];
items[0] = new Spam("0");
items[1] = new Spam("1");
items[2] = new Spam("2");
items[3] = new Spam("3");
items[4] = new Spam("4");
}
}
public class MultiDimensionalArrayTest {
public int[,] items;
public MultiDimensionalArrayTest() {
items = new int[5, 5] {
{0, 1, 2, 3, 4},
{5, 6, 7, 8, 9},
{10, 11, 12, 13, 14},
{15, 16, 17, 18, 19},
{20, 21, 22, 23, 24}
};
}
}
public class ArrayConversionTest {
public static Spam[] EchoRange(Spam[] items) {
return items;
}
public static Spam[,] EchoRangeMD(Spam[,] items) {
return items;
}
public static Spam[][] EchoRangeAA(Spam[][] items) {
return items;
}
}
}

Просмотреть файл

@ -0,0 +1,75 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Collections;
using System.Windows.Forms;
namespace Python.Test {
//========================================================================
// Supports CLR class unit tests.
//========================================================================
public class ClassTest {
public static ArrayList GetArrayList() {
ArrayList list = new ArrayList();
for (int i = 0; i < 10; i++) {
list.Add(i);
}
return list;
}
public static Hashtable GetHashtable() {
Hashtable dict = new Hashtable();
dict.Add("one", 1);
dict.Add("two", 2);
dict.Add("three", 3);
dict.Add("four", 4);
dict.Add("five", 5);
return dict;
}
public static IEnumerator GetEnumerator() {
string temp = "test string";
return temp.GetEnumerator();
}
}
public class ClassCtorTest1 {
public string value;
public ClassCtorTest1() {
value = "default";
}
}
public class ClassCtorTest2 {
public string value;
public ClassCtorTest2(string v) {
value = v;
}
}
internal class InternalClass {
}
}

Просмотреть файл

@ -0,0 +1,67 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Collections;
using System.Windows.Forms;
using System.IO;
namespace Python.Test {
//========================================================================
// These classes support the CLR constructor unit tests.
//========================================================================
public class EnumConstructorTest {
public TypeCode value;
public EnumConstructorTest(TypeCode v) {
this.value = v;
}
}
public class FlagsConstructorTest {
public FileAccess value;
public FlagsConstructorTest(FileAccess v) {
this.value = v;
}
}
public class StructConstructorTest {
public Guid value;
public StructConstructorTest(Guid v) {
this.value = v;
}
}
public class SubclassConstructorTest {
public Control value;
public SubclassConstructorTest(Control v) {
this.value = v;
}
}
}

Просмотреть файл

@ -0,0 +1,70 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
namespace Python.Test {
//========================================================================
// Supports units tests for field access.
//========================================================================
public class ConversionTest {
public ConversionTest() {
EnumField = ShortEnum.Zero;
SpamField = new Spam("spam");
StringField = "spam";
}
public bool BooleanField = false;
public byte ByteField = 0;
public sbyte SByteField = 0;
public char CharField = 'A';
public short Int16Field = 0;
public int Int32Field = 0;
public long Int64Field = 0;
public ushort UInt16Field = 0;
public uint UInt32Field = 0;
public ulong UInt64Field = 0;
public float SingleField = 0.0F;
public double DoubleField = 0.0;
public decimal DecimalField = 0;
public string StringField;
public ShortEnum EnumField;
public object ObjectField = null;
public ISpam SpamField;
public byte[] ByteArrayField;
public sbyte[] SByteArrayField;
}
public interface ISpam {
string GetValue();
}
public class Spam : ISpam {
string value;
public Spam(string value) {
this.value = value;
}
public string GetValue() {
return value;
}
}
}

Просмотреть файл

@ -0,0 +1,60 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
namespace Python.Test {
//========================================================================
// Supports CLR class unit tests.
//========================================================================
public delegate void PublicDelegate();
internal delegate void InternalDelegate();
public delegate DelegateTest ObjectDelegate();
public delegate string StringDelegate();
public class DelegateTest {
public delegate void PublicDelegate();
protected delegate void ProtectedDelegate();
internal delegate void InternalDelegate();
private delegate void PrivateDelegate();
public StringDelegate stringDelegate;
public ObjectDelegate objectDelegate;
public DelegateTest() {
}
public string SayHello() {
return "hello";
}
public static string StaticSayHello() {
return "hello";
}
public string CallStringDelegate(StringDelegate d) {
return d();
}
public DelegateTest CallObjectDelegate(ObjectDelegate d) {
return d();
}
}
}

Просмотреть файл

@ -0,0 +1,93 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
namespace Python.Test {
//========================================================================
// Supports CLR enum unit tests.
//========================================================================
public enum ByteEnum : byte {
Zero,
One,
Two,
Three,
Four,
Five
}
public enum SByteEnum : sbyte {
Zero,
One,
Two,
Three,
Four,
Five
}
public enum ShortEnum : short {
Zero,
One,
Two,
Three,
Four,
Five
}
public enum UShortEnum : ushort {
Zero,
One,
Two,
Three,
Four,
Five
}
public enum IntEnum : int{
Zero,
One,
Two,
Three,
Four,
Five
}
public enum UIntEnum : uint {
Zero,
One,
Two,
Three,
Four,
Five
}
public enum LongEnum : long {
Zero,
One,
Two,
Three,
Four,
Five
}
public enum ULongEnum : ulong {
Zero,
One,
Two,
Three,
Four,
Five
}
}

Просмотреть файл

@ -0,0 +1,132 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Windows.Forms;
namespace Python.Test {
//========================================================================
// Supports CLR event unit tests.
//========================================================================
public delegate void TestEventHandler(object sender, TestEventArgs e);
public class EventTest {
public void WinFormTest() {
EventTest e = new EventTest();
EventHandler h = new EventHandler(e.ClickHandler);
Form f = new Form();
f.Click += h;
//f.Click(null, new EventArgs());
f.Click -= h;
}
public void ClickHandler(object sender, EventArgs e) {
Console.WriteLine("click");
}
public static event TestEventHandler PublicStaticEvent;
protected static event TestEventHandler ProtectedStaticEvent;
internal static event TestEventHandler InternalStaticEvent;
private static event TestEventHandler PrivateStaticEvent;
public event TestEventHandler PublicEvent;
protected event TestEventHandler ProtectedEvent;
internal event TestEventHandler InternalEvent;
private event TestEventHandler PrivateEvent;
public static int s_value;
public int value;
public EventTest () {
this.value = 0;
}
static EventTest () {
s_value = 0;
}
public void OnPublicEvent(TestEventArgs e) {
if (PublicEvent != null) {
PublicEvent(this, e);
}
}
public void OnProtectedEvent(TestEventArgs e) {
if (ProtectedEvent != null) {
ProtectedEvent(this, e);
}
}
public static void OnPublicStaticEvent(TestEventArgs e) {
if (PublicStaticEvent != null) {
PublicStaticEvent(null, e);
}
}
protected static void OnProtectedStaticEvent(TestEventArgs e) {
if (ProtectedStaticEvent != null) {
ProtectedStaticEvent(null, e);
}
}
public void GenericHandler(object sender, TestEventArgs e) {
this.value = e.value;
}
public static void StaticHandler(object sender, TestEventArgs e) {
s_value = e.value;
}
public static void ShutUpCompiler() {
// Quiet compiler warnings.
EventTest e = new EventTest();
TestEventHandler f = new TestEventHandler(e.GenericHandler);
ProtectedStaticEvent += f;
InternalStaticEvent += f;
PrivateStaticEvent += f;
e.ProtectedEvent += f;
e.InternalEvent += f;
e.PrivateEvent += f;
}
}
public class TestEventArgs : EventArgs {
public int value;
public TestEventArgs(int v) {
this.value = v;
}
}
}

Просмотреть файл

@ -0,0 +1,96 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
namespace Python.Test {
//========================================================================
// Supports CLR Exception unit tests.
//========================================================================
public class ExceptionTest {
public int ThrowProperty {
get {
throw new OverflowException("error");
}
set {
throw new OverflowException("error");
}
}
public static Exception GetBaseException() {
return new Exception("error");
}
public static OverflowException GetExplicitException() {
return new OverflowException("error");
}
public static Exception GetWidenedException() {
return new OverflowException("error");
}
public static ExtendedException GetExtendedException() {
return new ExtendedException("error");
}
public static bool SetBaseException(Exception e) {
return typeof(Exception).IsInstanceOfType(e);
}
public static bool SetExplicitException(OverflowException e) {
return typeof(OverflowException).IsInstanceOfType(e);
}
public static bool SetWidenedException(Exception e) {
return typeof(Exception).IsInstanceOfType(e);
}
public static bool ThrowException() {
throw new OverflowException("error");
}
}
public class ExtendedException : OverflowException {
public ExtendedException() : base() {}
public ExtendedException(string m) : base(m) {}
public string extra = "extra";
public string ExtraProperty {
get {
return extra;
}
set {
extra = value;
}
}
public string GetExtraInfo() {
return extra;
}
}
}

Просмотреть файл

@ -0,0 +1,68 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
namespace Python.Test {
//========================================================================
// Supports units tests for field access.
//========================================================================
public class FieldTest {
public FieldTest() {
EnumField = ShortEnum.Zero;
SpamField = new Spam("spam");
StringField = "spam";
}
public void Shutup() {
int i = PrivateStaticField;
int j = PrivateField;
}
public static readonly int ReadOnlyStaticField = 0;
protected static int ProtectedStaticField = 0;
internal static int InternalStaticField = 0;
private static int PrivateStaticField = 0;
public static int PublicStaticField = 0;
public const int ConstField = 0;
public readonly int ReadOnlyField = 0;
internal int InternalField = 0;
protected int ProtectedField = 0;
private int PrivateField = 0;
public int PublicField = 0;
public bool BooleanField = false;
public byte ByteField = 0;
public sbyte SByteField = 0;
public char CharField = 'A';
public short Int16Field = 0;
public int Int32Field = 0;
public long Int64Field = 0;
public ushort UInt16Field = 0;
public uint UInt32Field = 0;
public ulong UInt64Field = 0;
public float SingleField = 0.0F;
public double DoubleField = 0.0;
public decimal DecimalField = 0;
public string StringField;
public ShortEnum EnumField;
public object ObjectField;
public ISpam SpamField;
}
}

Просмотреть файл

@ -0,0 +1,20 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
//========================================================================
// Supports units tests for access to types without a namespace.
//========================================================================
public class NoNamespaceType {}

Просмотреть файл

@ -0,0 +1,356 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Collections;
namespace Python.Test {
//========================================================================
// Supports units tests for indexer access.
//========================================================================
public class IndexerBase {
protected Hashtable t;
protected IndexerBase() {
t = new Hashtable();
}
protected string GetValue(object index) {
if (index == null) {
return null;
}
object value = t[index];
if (value != null) {
return (string)value;
}
return null;
}
}
public class PublicIndexerTest : IndexerBase {
public PublicIndexerTest() : base () {}
public string this [int index] {
get { return GetValue(index); }
set { t[index] = value; }
}
}
public class ProtectedIndexerTest : IndexerBase {
public ProtectedIndexerTest() : base () {}
protected string this [int index] {
get { return GetValue(index); }
set { t[index] = value; }
}
}
public class InternalIndexerTest : IndexerBase {
public InternalIndexerTest() : base () {}
internal string this [int index] {
get { return GetValue(index); }
set { t[index] = value; }
}
}
public class PrivateIndexerTest : IndexerBase {
public PrivateIndexerTest() : base () {}
private string this [int index] {
get { return GetValue(index); }
set { t[index] = value; }
}
}
public class BooleanIndexerTest : IndexerBase {
public BooleanIndexerTest() : base() {}
public string this [bool index] {
get { return GetValue(index); }
set { t[index] = value; }
}
}
public class ByteIndexerTest : IndexerBase {
public ByteIndexerTest() : base() {}
public string this [byte index] {
get { return GetValue(index); }
set { t[index] = value; }
}
}
public class SByteIndexerTest : IndexerBase {
public SByteIndexerTest() : base() {}
public string this [sbyte index] {
get { return GetValue(index); }
set { t[index] = value; }
}
}
public class CharIndexerTest : IndexerBase {
public CharIndexerTest() : base() {}
public string this [char index] {
get { return GetValue(index); }
set { t[index] = value; }
}
}
public class Int16IndexerTest : IndexerBase {
public Int16IndexerTest() : base() {}
public string this [short index] {
get { return GetValue(index); }
set { t[index] = value; }
}
}
public class Int32IndexerTest : IndexerBase {
public Int32IndexerTest() : base() {}
public string this [int index] {
get { return GetValue(index); }
set { t[index] = value; }
}
}
public class Int64IndexerTest : IndexerBase {
public Int64IndexerTest() : base() {}
public string this [long index] {
get { return GetValue(index); }
set { t[index] = value; }
}
}
public class UInt16IndexerTest : IndexerBase {
public UInt16IndexerTest() : base() {}
public string this [ushort index] {
get { return GetValue(index); }
set { t[index] = value; }
}
}
public class UInt32IndexerTest : IndexerBase {
public UInt32IndexerTest() : base() {}
public string this [uint index] {
get { return GetValue(index); }
set { t[index] = value; }
}
}
public class UInt64IndexerTest : IndexerBase {
public UInt64IndexerTest() : base() {}
public string this [ulong index] {
get { return GetValue(index); }
set { t[index] = value; }
}
}
public class SingleIndexerTest : IndexerBase {
public SingleIndexerTest() : base() {}
public string this [float index] {
get { return GetValue(index); }
set { t[index] = value; }
}
}
public class DoubleIndexerTest : IndexerBase {
public DoubleIndexerTest() : base() {}
public string this [double index] {
get { return GetValue(index); }
set { t[index] = value; }
}
}
public class DecimalIndexerTest : IndexerBase {
public DecimalIndexerTest() : base() {}
public string this [decimal index] {
get { return GetValue(index); }
set { t[index] = value; }
}
}
public class StringIndexerTest : IndexerBase {
public StringIndexerTest() : base() {}
public string this [string index] {
get { return GetValue(index); }
set { t[index] = value; }
}
}
public class EnumIndexerTest : IndexerBase {
public EnumIndexerTest() : base() {}
public string this [ShortEnum index] {
get { return GetValue(index); }
set { t[index] = value; }
}
}
public class ObjectIndexerTest : IndexerBase {
public ObjectIndexerTest() : base() {}
public string this [object index] {
get { return GetValue(index); }
set { t[index] = value; }
}
}
public class InterfaceIndexerTest : IndexerBase {
public InterfaceIndexerTest() : base() {}
public string this [ISpam index] {
get { return GetValue(index); }
set { t[index] = value; }
}
}
public class TypedIndexerTest : IndexerBase {
public TypedIndexerTest() : base() {}
public string this [Spam index] {
get { return GetValue(index); }
set { t[index] = value; }
}
}
public class MultiArgIndexerTest : IndexerBase {
public MultiArgIndexerTest() : base() {}
public string this [int index1, int index2] {
get {
string key = index1.ToString() + index2.ToString();
object value = t[key];
if (value != null) {
return (string)value;
}
return null;
}
set {
string key = index1.ToString() + index2.ToString();
t[key] = value;
}
}
}
public class MultiTypeIndexerTest : IndexerBase {
public MultiTypeIndexerTest() : base() {}
public string this [int i1, string i2, ISpam i3] {
get {
string key = i1.ToString() + i2.ToString() +
i3.GetHashCode().ToString();
object value = t[key];
if (value != null) {
return (string)value;
}
return null;
}
set {
string key = i1.ToString() + i2.ToString() +
i3.GetHashCode().ToString();
t[key] = value;
}
}
}
}

Просмотреть файл

@ -0,0 +1,61 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
namespace Python.Test {
//========================================================================
// Supports CLR class unit tests.
//========================================================================
public interface IPublicInterface {}
internal interface IInternalInterface {}
public interface ISayHello1 {
string SayHello();
}
public interface ISayHello2 {
string SayHello();
}
public class InterfaceTest : ISayHello1, ISayHello2{
public InterfaceTest() {}
public string HelloProperty {
get { return "hello"; }
}
string ISayHello1.SayHello() {
return "hello 1";
}
string ISayHello2.SayHello() {
return "hello 2";
}
public interface IPublic {}
protected interface IProtected {}
internal interface IInternal {}
private interface IPrivate {}
}
}

Просмотреть файл

@ -0,0 +1,146 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.IO;
using System.Windows.Forms;
namespace Python.Test {
//========================================================================
// Supports units tests for method access.
//========================================================================
public class MethodTest {
public MethodTest() {}
public string PublicMethod() {
return "public";
}
public static string PublicStaticMethod() {
return "public static";
}
protected string ProtectedMethod() {
return "protected";
}
protected static string ProtectedStaticMethod() {
return "protected static";
}
internal string InternalMethod() {
return "internal";
}
internal static string InternalStaticMethod() {
return "internal static";
}
private string PrivateMethod() {
return "private";
}
private static string PrivateStaticMethod() {
return "private static";
}
//===================================================================
// Methods to support specific argument conversion unit tests
//===================================================================
public TypeCode TestEnumConversion(TypeCode v) {
return v;
}
public FileAccess TestFlagsConversion(FileAccess v) {
return v;
}
public Guid TestStructConversion(Guid v) {
return v;
}
public Control TestSubclassConversion(Control v) {
return v;
}
public Type[] TestNullArrayConversion(Type [] v) {
return v;
}
public static bool TestStringOutParams (string s, out string s1) {
s1 = "output string";
return true;
}
public static bool TestStringRefParams (string s, ref string s1) {
s1 = "output string";
return true;
}
public static bool TestValueOutParams (string s, out int i1) {
i1 = 42;
return true;
}
public static bool TestValueRefParams (string s, ref int i1) {
i1 = 42;
return true;
}
public static bool TestObjectOutParams (object o, out object o1) {
o1 = new System.Exception("test");
return true;
}
public static bool TestObjectRefParams (object o, ref object o1) {
o1 = new System.Exception("test");
return true;
}
public static bool TestStructOutParams (object o, out Guid o1) {
o1 = Guid.NewGuid();
return true;
}
public static bool TestStructRefParams (object o, ref Guid o1) {
o1 = Guid.NewGuid();
return true;
}
public static void TestVoidSingleOutParam (out int i) {
i = 42;
}
public static void TestVoidSingleRefParam (ref int i) {
i = 42;
}
}
public class MethodTestSub : MethodTest {
public MethodTestSub() : base() {}
public string PublicMethod(string echo) {
return echo;
}
}
}

Просмотреть файл

@ -0,0 +1,81 @@
// Copyright (c) 2001, 2002 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
namespace Python.Test {
//========================================================================
// Supports units tests for property access.
//========================================================================
public class PropertyTest {
public PropertyTest() {}
int _public_property = 0;
public int PublicProperty {
get { return _public_property; }
set { _public_property = value; }
}
static int _public_static_property = 0;
public static int PublicStaticProperty {
get { return _public_static_property; }
set { _public_static_property = value; }
}
int _protected_property = 0;
protected int ProtectedProperty {
get { return _protected_property; }
set { _protected_property = value; }
}
static int _protected_static_property = 0;
protected static int ProtectedStaticProperty {
get { return _protected_static_property; }
set { _protected_static_property = value; }
}
int _internal_property = 0;
internal int InternalProperty {
get { return _internal_property; }
set { _internal_property = value; }
}
static int _internal_static_property = 0;
internal static int InternalStaticProperty {
get { return _internal_static_property; }
set { _internal_static_property = value; }
}
int _private_property = 0;
private int PrivateProperty {
get { return _private_property; }
set { _private_property = value; }
}
static int _private_static_property = 0;
private static int PrivateStaticProperty {
get { return _private_static_property; }
set { _private_static_property = value; }
}
ShortEnum _enum_property = ShortEnum.Zero;
public ShortEnum EnumProperty {
get { return _enum_property; }
set { _enum_property = value; }
}
}
}

Просмотреть файл

@ -0,0 +1,79 @@
// Copyright (c) 2005 Zope Corporation and Contributors.
//
// All Rights Reserved.
//
// This software is subject to the provisions of the Zope Public License,
// Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
// THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
// WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
// FOR A PARTICULAR PURPOSE.
using System;
using System.Collections;
using Python.Runtime;
namespace Python.Test {
//========================================================================
// Supports CLR threading / reentrancy unit tests.
//========================================================================
public class ThreadTest {
private static PyObject module;
private static string testmod =
"import CLR\n" +
"from CLR.Python.Test import ThreadTest\n" +
"\n" +
"def echostring(value):\n" +
" return value\n" +
"\n" +
"def echostring2(value):\n" +
" return ThreadTest.CallEchoString(value)\n" +
"\n";
// This method calls back into the CPython runtime - tests
// call this from Python to check that we don't hang on
// nested transitions from managed to Python code and back.
public static string CallEchoString(string arg) {
IntPtr gs = PythonEngine.AcquireLock();
if (module == null) {
module = PythonEngine.ModuleFromString("tt", testmod);
}
PyObject func = module.GetAttr("echostring");
PyString parg = new PyString(arg);
PyObject temp = func.Invoke(parg);
string result = (string)temp.AsManagedObject(typeof(String));
func.Dispose();
parg.Dispose();
temp.Dispose();
PythonEngine.ReleaseLock(gs);
return result;
}
public static string CallEchoString2(string arg) {
IntPtr gs = PythonEngine.AcquireLock();
if (module == null) {
module = PythonEngine.ModuleFromString("tt", testmod);
}
PyObject func = module.GetAttr("echostring2");
PyString parg = new PyString(arg);
PyObject temp = func.Invoke(parg);
string result = (string)temp.AsManagedObject(typeof(String));
func.Dispose();
parg.Dispose();
temp.Dispose();
PythonEngine.ReleaseLock(gs);
return result;
}
}
}

Просмотреть файл

@ -0,0 +1,424 @@
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
#
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
import CLR.System as System
import gc
class LeakTest:
"""A leak-check test for the objects implemented in the managed
runtime. For each kind of object tested, memory should reach
a particular level after warming up and stay essentially the
same, net of minor fluctuation induced by GC."""
def __init__(self):
self.count = 50000
self.quiet = 0
self._ws = 0
def notify(self, msg):
if not self.quiet:
print msg
def start_test(self):
System.GC.Collect(System.GC.MaxGeneration)
gc.collect()
self._ws = System.Environment.WorkingSet
def end_test(self):
start = self._ws
System.GC.Collect(System.GC.MaxGeneration)
gc.collect()
end = System.Environment.WorkingSet
diff = end - start
if diff > 0:
diff = '+%d' % diff
else:
diff = '%d' % diff
print " start: %d end: %d diff: %s" % (start, end, diff)
print ""
def run(self):
self.testModules()
self.testClasses()
self.testEnumerations()
self.testEvents()
self.testDelegates()
def report(self):
import sys, gc
gc.collect()
dicttype = type({})
for item in gc.get_objects():
if type(item) != dicttype:
print item, sys.getrefcount(item)
def testModules(self):
self.notify("Running module leak check...")
for i in xrange(self.count):
if i == 10:
self.start_test()
__import__('CLR')
__import__('CLR.System')
__import__('CLR.System.IO')
__import__('CLR.System.Net')
__import__('CLR.System.Xml')
self.end_test()
def testClasses(self):
from CLR.System.Collections import Hashtable
from CLR.Python.Test import StringDelegate
from CLR.System import Int32
self.notify("Running class leak check...")
for i in xrange(self.count):
if i == 10:
self.start_test()
# Reference type
x = Hashtable()
del x
# Value type
x = Int32(99)
del x
# Delegate type
x = StringDelegate(hello)
del x
self.end_test()
def testEnumerations(self):
from CLR.Python import Test
self.notify("Running enum leak check...")
for i in xrange(self.count):
if i == 10:
self.start_test()
x = Test.ByteEnum.Zero
del x
x = Test.SByteEnum.Zero
del x
x = Test.ShortEnum.Zero
del x
x = Test.UShortEnum.Zero
del x
x = Test.IntEnum.Zero
del x
x = Test.UIntEnum.Zero
del x
x = Test.LongEnum.Zero
del x
x = Test.ULongEnum.Zero
del x
self.end_test()
def testEvents(self):
from CLR.Python.Test import EventTest, TestEventArgs
self.notify("Running event leak check...")
for i in xrange(self.count):
if i == 10:
self.start_test()
testob = EventTest()
# Instance method event handler
handler = GenericHandler()
testob.PublicEvent += handler.handler
testob.PublicEvent(testob, TestEventArgs(10))
testob.PublicEvent -= handler.handler
del handler
# Vararg method event handler
handler = VariableArgsHandler()
testob.PublicEvent += handler.handler
testob.PublicEvent(testob, TestEventArgs(10))
testob.PublicEvent -= handler.handler
del handler
# Callable object event handler
handler = CallableHandler()
testob.PublicEvent += handler
testob.PublicEvent(testob, TestEventArgs(10))
testob.PublicEvent -= handler
del handler
# Callable vararg event handler
handler = VarCallableHandler()
testob.PublicEvent += handler
testob.PublicEvent(testob, TestEventArgs(10))
testob.PublicEvent -= handler
del handler
# Static method event handler
handler = StaticMethodHandler()
StaticMethodHandler.value = None
testob.PublicEvent += handler.handler
testob.PublicEvent(testob, TestEventArgs(10))
testob.PublicEvent -= handler.handler
del handler
# Class method event handler
handler = ClassMethodHandler()
ClassMethodHandler.value = None
testob.PublicEvent += handler.handler
testob.PublicEvent(testob, TestEventArgs(10))
testob.PublicEvent -= handler.handler
del handler
# Managed instance event handler
testob.PublicEvent += testob.GenericHandler
testob.PublicEvent(testob, TestEventArgs(10))
testob.PublicEvent -= testob.GenericHandler
# Static managed event handler
testob.PublicEvent += EventTest.StaticHandler
testob.PublicEvent(testob, TestEventArgs(10))
testob.PublicEvent -= EventTest.StaticHandler
# Function event handler
dict = {'value':None}
def handler(sender, args, dict=dict):
dict['value'] = args.value
testob.PublicEvent += handler
testob.PublicEvent(testob, TestEventArgs(10))
testob.PublicEvent -= handler
del handler
self.end_test()
def testDelegates(self):
from CLR.Python.Test import DelegateTest, StringDelegate
from CLR import System
self.notify("Running delegate leak check...")
for i in xrange(self.count):
if i == 10:
self.start_test()
# Delegate from function
testob = DelegateTest()
d = StringDelegate(hello)
testob.CallStringDelegate(d)
testob.stringDelegate = d
testob.stringDelegate()
testob.stringDelegate = None
del testob
del d
# Delegate from instance method
inst = Hello()
testob = DelegateTest()
d = StringDelegate(inst.hello)
testob.CallStringDelegate(d)
testob.stringDelegate = d
testob.stringDelegate()
testob.stringDelegate = None
del testob
del inst
del d
# Delegate from static method
testob = DelegateTest()
d = StringDelegate(Hello.s_hello)
testob.CallStringDelegate(d)
testob.stringDelegate = d
testob.stringDelegate()
testob.stringDelegate = None
del testob
del d
# Delegate from class method
testob = DelegateTest()
d = StringDelegate(Hello.c_hello)
testob.CallStringDelegate(d)
testob.stringDelegate = d
testob.stringDelegate()
testob.stringDelegate = None
del testob
del d
# Delegate from callable object
inst = Hello()
testob = DelegateTest()
d = StringDelegate(inst)
testob.CallStringDelegate(d)
testob.stringDelegate = d
testob.stringDelegate()
testob.stringDelegate = None
del testob
del inst
del d
# Delegate from managed instance method
testob = DelegateTest()
d = StringDelegate(testob.SayHello)
testob.CallStringDelegate(d)
testob.stringDelegate = d
testob.stringDelegate()
testob.stringDelegate = None
del testob
del d
# Delegate from managed static method
testob = DelegateTest()
d = StringDelegate(DelegateTest.StaticSayHello)
testob.CallStringDelegate(d)
testob.stringDelegate = d
testob.stringDelegate()
testob.stringDelegate = None
del testob
del d
# Nested delegates
testob = DelegateTest()
d1 = StringDelegate(hello)
d2 = StringDelegate(d1)
testob.CallStringDelegate(d2)
testob.stringDelegate = d2
testob.stringDelegate()
testob.stringDelegate = None
del testob
del d1
del d2
# Multicast delegates
testob = DelegateTest()
d1 = StringDelegate(hello)
d2 = StringDelegate(hello)
md = System.Delegate.Combine(d1, d2)
testob.CallStringDelegate(md)
testob.stringDelegate = md
testob.stringDelegate()
testob.stringDelegate = None
del testob
del d1
del d2
del md
self.end_test()
class GenericHandler:
"""A generic handler to test event callbacks."""
def __init__(self):
self.value = None
def handler(self, sender, args):
self.value = args.value
class VariableArgsHandler:
"""A variable args handler to test event callbacks."""
def __init__(self):
self.value = None
def handler(self, *args):
ob, eventargs = args
self.value = eventargs.value
class CallableHandler:
"""A callable handler to test event callbacks."""
def __init__(self):
self.value = None
def __call__(self, sender, args):
self.value = args.value
class VarCallableHandler:
"""A variable args callable handler to test event callbacks."""
def __init__(self):
self.value = None
def __call__(self, *args):
ob, eventargs = args
self.value = eventargs.value
class StaticMethodHandler(object):
"""A static method handler to test event callbacks."""
value = None
def handler(sender, args):
StaticMethodHandler.value = args.value
handler = staticmethod(handler)
class ClassMethodHandler(object):
"""A class method handler to test event callbacks."""
value = None
def handler(cls, sender, args):
cls.value = args.value
handler = classmethod(handler)
class Hello:
def hello(self):
return "hello"
def __call__(self):
return "hello"
def s_hello():
return "hello"
s_hello = staticmethod(s_hello)
def c_hello(cls):
return "hello"
c_hello = classmethod(c_hello)
def hello():
return "hello"
if __name__ == '__main__':
test = LeakTest()
test.run()
test.report()

Просмотреть файл

@ -0,0 +1,33 @@
"""Run all of the unit tests for this package over and over,
in order to provide for better profiling."""
def main():
import sys, os, gc, time
dirname = os.path.split(__file__)
sys.path.append(dirname)
import runtests
gc.set_debug(gc.DEBUG_LEAK)
start = time.clock()
for i in range(50):
print 'iteration: %d' % i
runtests.main()
stop = time.clock()
took = str(stop - start)
print 'Total Time: %s' % took
for item in gc.get_objects():
print item, sys.getrefcount(item)
if __name__ == '__main__':
main()
sys.exit(0)

Просмотреть файл

@ -0,0 +1,38 @@
"""Run all of the unit tests for this package."""
import time
test_modules = (
'test_exceptions',
'test_module',
'test_conversion',
'test_class',
'test_interface',
'test_enum',
'test_field',
'test_property',
'test_indexer',
'test_event',
'test_method',
'test_delegate',
'test_array',
'test_thread',
)
def main():
start = time.clock()
for name in test_modules:
module = __import__(name)
module.main()
stop = time.clock()
took = str(stop - start)
print 'Total Time: %s' % took
if __name__ == '__main__':
main()

Просмотреть файл

@ -0,0 +1,82 @@
# Copyright (c) 2005 Zope Corporation and Contributors.
#
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
"""
Run all of the unit tests for this package multiple times in a highly
multithreaded way to stress the system. This makes it possible to look
for memory leaks and threading issues and provides a good target for a
profiler to accumulate better data.
"""
import sys, os, gc, time, threading, thread
class StressTest:
def __init__(self):
self.dirname = os.path.split(__file__)[0]
sys.path.append(self.dirname)
gc.set_debug(gc.DEBUG_LEAK)
import runtests
self.module = runtests
self.done = []
def dprint(self, msg):
# Debugging helper to trace thread-related tests.
if 1: print msg
def markStart(self):
self._start = time.clock()
def markFinish(self):
self._finish = time.clock()
def elapsed(self):
return self._finish - self._start
def printGCReport(self):
for item in gc.get_objects():
print item, sys.getrefcount(item)
def runThread(self, iterations):
thread_id = thread.get_ident()
self.dprint("thread %s starting..." % thread_id)
time.sleep(0.1)
for i in range(iterations):
self.dprint("thread %s iter %d start" % (thread_id, i))
self.module.main()
self.dprint("thread %s iter %d end" % (thread_id, i))
self.done.append(None)
self.dprint("thread %s done" % thread_id)
def stressTest(self, iterations=1, threads=1):
args = (iterations,)
self.markStart()
for i in range(threads):
thread = threading.Thread(target=self.runThread, args=args)
thread.start()
while len(self.done) < (iterations * threads):
self.dprint(len(self.done))
time.sleep(0.1)
self.markFinish()
took = self.elapsed()
self.printGCReport()
def main():
test = StressTest()
test.stressTest(2, 10)
if __name__ == '__main__':
main()
sys.exit(0)

Просмотреть файл

@ -0,0 +1,41 @@
"""Basic stress test."""
def main():
import time
start = time.clock()
for i in range(2000):
print i
for name in (
'test_module',
'test_conversion',
#'test_class',
'test_interface',
'test_enum',
'test_field',
'test_property',
'test_indexer',
'test_event',
'test_method',
#'test_delegate',
'test_array',
):
module = __import__(name)
module.main()
#import pdb; pdb.set_trace()
stop = time.clock()
took = str(stop - start)
print 'Total Time: %s' % took
import gc
for i in gc.get_objects():
print i
if __name__ == '__main__':
main()

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,246 @@
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
#
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
from CLR.System.Collections import Hashtable
from CLR.Python.Test import ClassTest
import sys, os, string, unittest, types
import CLR.Python.Test as Test
import CLR.System as System
class ClassTests(unittest.TestCase):
"""Test CLR class support."""
def testBasicReferenceType(self):
"""Test usage of CLR defined reference types."""
String = System.String
self.assertEquals(String.Empty, "")
def testBasicValueType(self):
"""Test usage of CLR defined value types."""
Int32 = System.Int32
self.assertEquals(Int32.MaxValue, 2147483647)
def testClassStandardAttrs(self):
"""Test standard class attributes."""
self.failUnless(ClassTest.__name__ == 'ClassTest')
self.failUnless(ClassTest.__module__ == 'CLR.Python.Test')
self.failUnless(type(ClassTest.__dict__) == types.DictProxyType)
self.failUnless(len(ClassTest.__doc__) > 0)
def testClassDocstrings(self):
"""Test standard class docstring generation"""
value = 'Void .ctor()'
self.failUnless(ClassTest.__doc__ == value)
def testClassDefaultStr(self):
"""Test the default __str__ implementation for managed objects."""
s = System.String("this is a test")
self.failUnless(str(s) == "this is a test")
def testClassDefaultRepr(self):
"""Test the default __repr__ implementation for managed objects."""
s = System.String("this is a test")
self.failUnless(repr(s).startswith("<CLR.System.String object"))
def testNonPublicClass(self):
"""Test that non-public classes are inaccessible."""
from CLR.Python import Test
def test():
from CLR.Python.Test import InternalClass
self.failUnlessRaises(ImportError, test)
def test():
x = Test.InternalClass
self.failUnlessRaises(AttributeError, test)
def testBasicSubclass(self):
"""Test basic subclass of a managed class."""
class MyTable(Hashtable):
def howMany(self):
return self.Count
table = MyTable()
self.failUnless(table.__class__.__name__.endswith('MyTable'))
self.failUnless(type(table).__name__.endswith('MyTable'))
self.failUnless(len(table.__class__.__bases__) == 1)
self.failUnless(table.__class__.__bases__[0] == Hashtable)
self.failUnless(table.howMany() == 0)
self.failUnless(table.Count == 0)
table.set_Item('one', 'one')
self.failUnless(table.howMany() == 1)
self.failUnless(table.Count == 1)
MyTable = None
def testSubclassWithNoArgConstructor(self):
"""Test subclass of a managed class with a no-arg constructor."""
from CLR.Python.Test import ClassCtorTest1
class SubClass(ClassCtorTest1):
def __init__(self, name):
self.name = name
# This failed in earlier versions
inst = SubClass('test')
def testSubclassWithVariousConstructors(self):
"""Test subclass of a managed class with various constructors."""
from CLR.Python.Test import ClassCtorTest2
class SubClass(ClassCtorTest2):
def __init__(self, v):
ClassCtorTest2.__init__(self)
self.value = v
inst = SubClass('test')
self.failUnless(inst.value == 'test')
class SubClass2(ClassCtorTest2):
def __init__(self, v):
ClassCtorTest2.__init__(self)
self.value = v
inst = SubClass2('test')
self.failUnless(inst.value == 'test')
def testStructConstruction(self):
"""Test construction of structs."""
from CLR.System.Drawing import Point
def test():
p = Point()
self.failUnlessRaises(TypeError, test)
p = Point(0, 0)
self.failUnless(p.X == 0)
self.failUnless(p.Y == 0)
p.X = 10
p.Y = 10
self.failUnless(p.X == 10)
self.failUnless(p.Y == 10)
# test strange __new__ interactions
# test weird metatype
# test recursion
# test
def testIEnumerableIteration(self):
"""Test iteration over objects supporting IEnumerable."""
list = Test.ClassTest.GetArrayList()
for item in list:
self.failUnless((item > -1) and (item < 10))
dict = Test.ClassTest.GetHashtable()
for item in dict:
cname = item.__class__.__name__
self.failUnless(cname.endswith('DictionaryEntry'))
def testIEnumeratorIteration(self):
"""Test iteration over objects supporting IEnumerator."""
chars = Test.ClassTest.GetEnumerator()
for item in chars:
self.failUnless(item in 'test string')
def testOverrideGetItem(self):
"""Test managed subclass overriding __getitem__."""
class MyTable(Hashtable):
def __getitem__(self, key):
value = Hashtable.__getitem__(self, key)
return 'my ' + str(value)
table = MyTable()
table['one'] = 'one'
table['two'] = 'two'
table['three'] = 'three'
self.failUnless(table['one'] == 'my one')
self.failUnless(table['two'] == 'my two')
self.failUnless(table['three'] == 'my three')
self.failUnless(table.Count == 3)
def testOverrideSetItem(self):
"""Test managed subclass overriding __setitem__."""
class MyTable(Hashtable):
def __setitem__(self, key, value):
value = 'my ' + str(value)
Hashtable.__setitem__(self, key, value)
table = MyTable()
table['one'] = 'one'
table['two'] = 'two'
table['three'] = 'three'
self.failUnless(table['one'] == 'my one')
self.failUnless(table['two'] == 'my two')
self.failUnless(table['three'] == 'my three')
self.failUnless(table.Count == 3)
class ClassicClass:
def kind(self):
return 'classic'
class NewStyleClass(object):
def kind(self):
return 'new-style'
def test_suite():
return unittest.makeSuite(ClassTests)
def main():
unittest.TextTestRunner().run(test_suite())
if __name__ == '__main__':
testcase.setup()
main()

Просмотреть файл

@ -0,0 +1,70 @@
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
#
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
import sys, os, string, unittest, types
import CLR.Python.Test as Test
import CLR.System as System
class ConstructorTests(unittest.TestCase):
"""Test CLR class constructor support."""
def testEnumConstructor(self):
"""Test enum constructor args"""
from Test import EnumConstructorTest
ob = EnumConstructorTest(TypeCode.Int32)
self.failUnless(ob.value == TypeCode.Int32)
def testFlagsConstructor(self):
"""Test flags constructor args"""
from Test import FlagsConstructorTest
from System.IO import FileAccess
flags = FileAccess.Read | FileAccess.Write
ob = FlagsConstructorTest(flags)
self.failUnless(ob.value == flags)
def testStructConstructor(self):
"""Test struct constructor args"""
from Test import StructConstructorTest
guid = Guid.NewGuid()
ob = StructConstructorTest(guid)
self.failUnless(ob.value == guid)
def testSubclassConstructor(self):
"""Test subclass constructor args"""
from Test import SubclassConstructorTest
from System.Windows.Forms import Form, Control
class sub(Form):
pass
form = sub()
ob = SubclassConstructorTest(form)
self.failUnless(isinstance(ob.value, Control))
def test_suite():
return unittest.makeSuite(ConstructorTests)
def main():
unittest.TextTestRunner().run(test_suite())
if __name__ == '__main__':
testcase.setup()
main()

Просмотреть файл

@ -0,0 +1,876 @@
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
#
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
import sys, os, string, unittest, types
from CLR.Python.Test import ConversionTest
from CLR import System
class ConversionTests(unittest.TestCase):
"""Test CLR <-> Python type conversions."""
def testBoolConversion(self):
"""Test bool conversion."""
object = ConversionTest()
self.failUnless(object.BooleanField == False)
self.failUnless(object.BooleanField is False)
self.failUnless(object.BooleanField == 0)
object.BooleanField = True
self.failUnless(object.BooleanField == True)
self.failUnless(object.BooleanField is True)
self.failUnless(object.BooleanField == 1)
object.BooleanField = False
self.failUnless(object.BooleanField == False)
self.failUnless(object.BooleanField is False)
self.failUnless(object.BooleanField == 0)
object.BooleanField = 1
self.failUnless(object.BooleanField == True)
self.failUnless(object.BooleanField is True)
self.failUnless(object.BooleanField == 1)
object.BooleanField = 0
self.failUnless(object.BooleanField == False)
self.failUnless(object.BooleanField is False)
self.failUnless(object.BooleanField == 0)
object.BooleanField = System.Boolean(None)
self.failUnless(object.BooleanField == False)
self.failUnless(object.BooleanField is False)
self.failUnless(object.BooleanField == 0)
object.BooleanField = System.Boolean('')
self.failUnless(object.BooleanField == False)
self.failUnless(object.BooleanField is False)
self.failUnless(object.BooleanField == 0)
object.BooleanField = System.Boolean(0)
self.failUnless(object.BooleanField == False)
self.failUnless(object.BooleanField is False)
self.failUnless(object.BooleanField == 0)
object.BooleanField = System.Boolean(1)
self.failUnless(object.BooleanField == True)
self.failUnless(object.BooleanField is True)
self.failUnless(object.BooleanField == 1)
object.BooleanField = System.Boolean('a')
self.failUnless(object.BooleanField == True)
self.failUnless(object.BooleanField is True)
self.failUnless(object.BooleanField == 1)
def testSByteConversion(self):
"""Test sbyte conversion."""
self.failUnless(System.SByte.MaxValue == 127)
self.failUnless(System.SByte.MinValue == -128)
object = ConversionTest()
self.failUnless(object.SByteField == 0)
object.SByteField = 127
self.failUnless(object.SByteField == 127)
object.SByteField = -128
self.failUnless(object.SByteField == -128)
object.SByteField = System.SByte(127)
self.failUnless(object.SByteField == 127)
object.SByteField = System.SByte(-128)
self.failUnless(object.SByteField == -128)
def test():
ConversionTest().SByteField = "spam"
self.failUnlessRaises(TypeError, test)
def test():
ConversionTest().SByteField = None
self.failUnlessRaises(TypeError, test)
def test():
ConversionTest().SByteField = 128
self.failUnlessRaises(OverflowError, test)
def test():
ConversionTest().SByteField = -129
self.failUnlessRaises(OverflowError, test)
def test():
value = System.SByte(128)
self.failUnlessRaises(OverflowError, test)
def test():
value = System.SByte(-129)
self.failUnlessRaises(OverflowError, test)
def testByteConversion(self):
"""Test byte conversion."""
self.failUnless(System.Byte.MaxValue == 255)
self.failUnless(System.Byte.MinValue == 0)
object = ConversionTest()
self.failUnless(object.ByteField == 0)
object.ByteField = 255
self.failUnless(object.ByteField == 255)
object.ByteField = 0
self.failUnless(object.ByteField == 0)
object.ByteField = System.Byte(255)
self.failUnless(object.ByteField == 255)
object.ByteField = System.Byte(0)
self.failUnless(object.ByteField == 0)
def test():
ConversionTest().ByteField = "spam"
self.failUnlessRaises(TypeError, test)
def test():
ConversionTest().ByteField = None
self.failUnlessRaises(TypeError, test)
def test():
ConversionTest().ByteField = 256
self.failUnlessRaises(OverflowError, test)
def test():
ConversionTest().ByteField = -1
self.failUnlessRaises(OverflowError, test)
def test():
value = System.Byte(256)
self.failUnlessRaises(OverflowError, test)
def test():
value = System.Byte(-1)
self.failUnlessRaises(OverflowError, test)
def testCharConversion(self):
"""Test char conversion."""
self.failUnless(System.Char.MaxValue == unichr(65535))
self.failUnless(System.Char.MinValue == unichr(0))
object = ConversionTest()
self.failUnless(object.CharField == u'A')
object.CharField = 'B'
self.failUnless(object.CharField == u'B')
object.CharField = u'B'
self.failUnless(object.CharField == u'B')
object.CharField = 67
self.failUnless(object.CharField == u'C')
def test():
ConversionTest().CharField = 65536
self.failUnlessRaises(OverflowError, test)
def test():
ConversionTest().CharField = -1
self.failUnlessRaises(OverflowError, test)
def test():
ConversionTest().CharField = None
self.failUnlessRaises(TypeError, test)
def testInt16Conversion(self):
"""Test int16 conversion."""
self.failUnless(System.Int16.MaxValue == 32767)
self.failUnless(System.Int16.MinValue == -32768)
object = ConversionTest()
self.failUnless(object.Int16Field == 0)
object.Int16Field = 32767
self.failUnless(object.Int16Field == 32767)
object.Int16Field = -32768
self.failUnless(object.Int16Field == -32768)
object.Int16Field = System.Int16(32767)
self.failUnless(object.Int16Field == 32767)
object.Int16Field = System.Int16(-32768)
self.failUnless(object.Int16Field == -32768)
def test():
ConversionTest().Int16Field = "spam"
self.failUnlessRaises(TypeError, test)
def test():
ConversionTest().Int16Field = None
self.failUnlessRaises(TypeError, test)
def test():
ConversionTest().Int16Field = 32768
self.failUnlessRaises(OverflowError, test)
def test():
ConversionTest().Int16Field = -32769
self.failUnlessRaises(OverflowError, test)
def test():
value = System.Int16(32768)
self.failUnlessRaises(OverflowError, test)
def test():
value = System.Int16(-32769)
self.failUnlessRaises(OverflowError, test)
def testInt32Conversion(self):
"""Test int32 conversion."""
self.failUnless(System.Int32.MaxValue == 2147483647)
self.failUnless(System.Int32.MinValue == -2147483648)
object = ConversionTest()
self.failUnless(object.Int32Field == 0)
object.Int32Field = 2147483647
self.failUnless(object.Int32Field == 2147483647)
object.Int32Field = -2147483648
self.failUnless(object.Int32Field == -2147483648)
object.Int32Field = System.Int32(2147483647)
self.failUnless(object.Int32Field == 2147483647)
object.Int32Field = System.Int32(-2147483648)
self.failUnless(object.Int32Field == -2147483648)
def test():
ConversionTest().Int32Field = "spam"
self.failUnlessRaises(TypeError, test)
def test():
ConversionTest().Int32Field = None
self.failUnlessRaises(TypeError, test)
def test():
ConversionTest().Int32Field = 2147483648
self.failUnlessRaises(OverflowError, test)
def test():
ConversionTest().Int32Field = -2147483649
self.failUnlessRaises(OverflowError, test)
def test():
value = System.Int32(2147483648)
self.failUnlessRaises(OverflowError, test)
def test():
value = System.Int32(-2147483649)
self.failUnlessRaises(OverflowError, test)
def testInt64Conversion(self):
"""Test int64 conversion."""
self.failUnless(System.Int64.MaxValue == 9223372036854775807L)
self.failUnless(System.Int64.MinValue == -9223372036854775808L)
object = ConversionTest()
self.failUnless(object.Int64Field == 0)
object.Int64Field = 9223372036854775807L
self.failUnless(object.Int64Field == 9223372036854775807L)
object.Int64Field = -9223372036854775808L
self.failUnless(object.Int64Field == -9223372036854775808L)
object.Int64Field = System.Int64(9223372036854775807L)
self.failUnless(object.Int64Field == 9223372036854775807L)
object.Int64Field = System.Int64(-9223372036854775808L)
self.failUnless(object.Int64Field == -9223372036854775808L)
def test():
ConversionTest().Int64Field = "spam"
self.failUnlessRaises(TypeError, test)
def test():
ConversionTest().Int64Field = None
self.failUnlessRaises(TypeError, test)
def test():
ConversionTest().Int64Field = 9223372036854775808L
self.failUnlessRaises(OverflowError, test)
def test():
ConversionTest().Int64Field = -9223372036854775809L
self.failUnlessRaises(OverflowError, test)
def test():
value = System.Int64(9223372036854775808L)
self.failUnlessRaises(OverflowError, test)
def test():
value = System.Int64(-9223372036854775809L)
self.failUnlessRaises(OverflowError, test)
def testUInt16Conversion(self):
"""Test uint16 conversion."""
self.failUnless(System.UInt16.MaxValue == 65535)
self.failUnless(System.UInt16.MinValue == 0)
object = ConversionTest()
self.failUnless(object.UInt16Field == 0)
object.UInt16Field = 65535
self.failUnless(object.UInt16Field == 65535)
object.UInt16Field = -0
self.failUnless(object.UInt16Field == 0)
object.UInt16Field = System.UInt16(65535)
self.failUnless(object.UInt16Field == 65535)
object.UInt16Field = System.UInt16(0)
self.failUnless(object.UInt16Field == 0)
def test():
ConversionTest().UInt16Field = "spam"
self.failUnlessRaises(TypeError, test)
def test():
ConversionTest().UInt16Field = None
self.failUnlessRaises(TypeError, test)
def test():
ConversionTest().UInt16Field = 65536
self.failUnlessRaises(OverflowError, test)
def test():
ConversionTest().UInt16Field = -1
self.failUnlessRaises(OverflowError, test)
def test():
value = System.UInt16(65536)
self.failUnlessRaises(OverflowError, test)
def test():
value = System.UInt16(-1)
self.failUnlessRaises(OverflowError, test)
def testUInt32Conversion(self):
"""Test uint32 conversion."""
self.failUnless(System.UInt32.MaxValue == 4294967295L)
self.failUnless(System.UInt32.MinValue == 0)
object = ConversionTest()
self.failUnless(object.UInt32Field == 0)
object.UInt32Field = 4294967295L
self.failUnless(object.UInt32Field == 4294967295L)
object.UInt32Field = -0
self.failUnless(object.UInt32Field == 0)
object.UInt32Field = System.UInt32(4294967295L)
self.failUnless(object.UInt32Field == 4294967295L)
object.UInt32Field = System.UInt32(0)
self.failUnless(object.UInt32Field == 0)
def test():
ConversionTest().UInt32Field = "spam"
self.failUnlessRaises(TypeError, test)
def test():
ConversionTest().UInt32Field = None
self.failUnlessRaises(TypeError, test)
def test():
ConversionTest().UInt32Field = 4294967296L
self.failUnlessRaises(OverflowError, test)
def test():
ConversionTest().UInt32Field = -1
self.failUnlessRaises(OverflowError, test)
def test():
value = System.UInt32(4294967296L)
self.failUnlessRaises(OverflowError, test)
def test():
value = System.UInt32(-1)
self.failUnlessRaises(OverflowError, test)
def testUInt64Conversion(self):
"""Test uint64 conversion."""
self.failUnless(System.UInt64.MaxValue == 18446744073709551615L)
self.failUnless(System.UInt64.MinValue == 0)
object = ConversionTest()
self.failUnless(object.UInt64Field == 0)
object.UInt64Field = 18446744073709551615L
self.failUnless(object.UInt64Field == 18446744073709551615L)
object.UInt64Field = -0
self.failUnless(object.UInt64Field == 0)
object.UInt64Field = System.UInt64(18446744073709551615L)
self.failUnless(object.UInt64Field == 18446744073709551615L)
object.UInt64Field = System.UInt64(0)
self.failUnless(object.UInt64Field == 0)
def test():
ConversionTest().UInt64Field = "spam"
self.failUnlessRaises(TypeError, test)
def test():
ConversionTest().UInt64Field = None
self.failUnlessRaises(TypeError, test)
def test():
ConversionTest().UInt64Field = 18446744073709551616L
self.failUnlessRaises(OverflowError, test)
def test():
ConversionTest().UInt64Field = -1
self.failUnlessRaises(OverflowError, test)
def test():
value = System.UInt64(18446744073709551616L)
self.failUnlessRaises(OverflowError, test)
def test():
value = System.UInt64(-1)
self.failUnlessRaises(OverflowError, test)
def testSingleConversion(self):
"""Test single conversion."""
self.failUnless(System.Single.MaxValue == 3.402823e38)
self.failUnless(System.Single.MinValue == -3.402823e38)
object = ConversionTest()
self.failUnless(object.SingleField == 0.0)
object.SingleField = 3.402823e38
self.failUnless(object.SingleField == 3.402823e38)
object.SingleField = -3.402823e38
self.failUnless(object.SingleField == -3.402823e38)
object.SingleField = System.Single(3.402823e38)
self.failUnless(object.SingleField == 3.402823e38)
object.SingleField = System.Single(-3.402823e38)
self.failUnless(object.SingleField == -3.402823e38)
def test():
ConversionTest().SingleField = "spam"
self.failUnlessRaises(TypeError, test)
def test():
ConversionTest().SingleField = None
self.failUnlessRaises(TypeError, test)
def test():
ConversionTest().SingleField = 3.402824e38
self.failUnlessRaises(OverflowError, test)
def test():
ConversionTest().SingleField = -3.402824e38
self.failUnlessRaises(OverflowError, test)
def test():
value = System.Single(3.402824e38)
self.failUnlessRaises(OverflowError, test)
def test():
value = System.Single(-3.402824e38)
self.failUnlessRaises(OverflowError, test)
def testDoubleConversion(self):
"""Test double conversion."""
self.failUnless(System.Double.MaxValue == 1.7976931348623157e308)
self.failUnless(System.Double.MinValue == -1.7976931348623157e308)
object = ConversionTest()
self.failUnless(object.DoubleField == 0.0)
object.DoubleField = 1.7976931348623157e308
self.failUnless(object.DoubleField == 1.7976931348623157e308)
object.DoubleField = -1.7976931348623157e308
self.failUnless(object.DoubleField == -1.7976931348623157e308)
object.DoubleField = System.Double(1.7976931348623157e308)
self.failUnless(object.DoubleField == 1.7976931348623157e308)
object.DoubleField = System.Double(-1.7976931348623157e308)
self.failUnless(object.DoubleField == -1.7976931348623157e308)
def test():
ConversionTest().DoubleField = "spam"
self.failUnlessRaises(TypeError, test)
def test():
ConversionTest().DoubleField = None
self.failUnlessRaises(TypeError, test)
def test():
ConversionTest().DoubleField = 1.7976931348623159e308
self.failUnlessRaises(OverflowError, test)
def test():
ConversionTest().DoubleField = -1.7976931348623159e308
self.failUnlessRaises(OverflowError, test)
def test():
value = System.Double(1.7976931348623159e308)
self.failUnlessRaises(OverflowError, test)
def test():
value = System.Double(-1.7976931348623159e308)
self.failUnlessRaises(OverflowError, test)
def testDecimalConversion(self):
"""Test decimal conversion."""
from CLR.System import Decimal
max_d = Decimal.Parse("79228162514264337593543950335")
min_d = Decimal.Parse("-79228162514264337593543950335")
self.failUnless(Decimal.ToInt64(Decimal(10)) == 10L)
object = ConversionTest()
self.failUnless(object.DecimalField == Decimal(0))
object.DecimalField = Decimal(10)
self.failUnless(object.DecimalField == Decimal(10))
object.DecimalField = Decimal.One
self.failUnless(object.DecimalField == Decimal.One)
object.DecimalField = Decimal.Zero
self.failUnless(object.DecimalField == Decimal.Zero)
object.DecimalField = max_d
self.failUnless(object.DecimalField == max_d)
object.DecimalField = min_d
self.failUnless(object.DecimalField == min_d)
def test():
ConversionTest().DecimalField = None
self.failUnlessRaises(TypeError, test)
def test():
ConversionTest().DecimalField = "spam"
self.failUnlessRaises(TypeError, test)
def test():
ConversionTest().DecimalField = 1
self.failUnlessRaises(TypeError, test)
def testStringConversion(self):
"""Test string / unicode conversion."""
object = ConversionTest()
self.failUnless(object.StringField == "spam")
self.failUnless(object.StringField == u"spam")
object.StringField = "eggs"
self.failUnless(object.StringField == "eggs")
self.failUnless(object.StringField == u"eggs")
object.StringField = u"spam"
self.failUnless(object.StringField == "spam")
self.failUnless(object.StringField == u"spam")
object.StringField = u'\uffff\uffff'
self.failUnless(object.StringField == u'\uffff\uffff')
object.StringField = System.String("spam")
self.failUnless(object.StringField == "spam")
self.failUnless(object.StringField == u"spam")
object.StringField = System.String(u'\uffff\uffff')
self.failUnless(object.StringField == u'\uffff\uffff')
object.StringField = None
self.failUnless(object.StringField == None)
def test():
ConversionTest().StringField = 1
self.failUnlessRaises(TypeError, test)
def testInterfaceConversion(self):
"""Test interface conversion."""
from CLR.Python.Test import Spam, ISpam
object = ConversionTest()
self.failUnless(ISpam(object.SpamField).GetValue() == "spam")
self.failUnless(object.SpamField.GetValue() == "spam")
object.SpamField = Spam("eggs")
self.failUnless(ISpam(object.SpamField).GetValue() == "eggs")
self.failUnless(object.SpamField.GetValue() == "eggs")
# need to test spam subclass here.
object.SpamField = None
self.failUnless(object.SpamField == None)
def test():
object = ConversionTest()
object.SpamField = System.String("bad")
self.failUnlessRaises(TypeError, test)
def test():
object = ConversionTest()
object.SpamField = System.Int32(1)
self.failUnlessRaises(TypeError, test)
def testObjectConversion(self):
"""Test object conversion."""
from CLR.Python.Test import Spam
object = ConversionTest()
self.failUnless(object.ObjectField == None)
object.ObjectField = Spam("eggs")
self.failUnless(object.ObjectField.__class__.__name__ == "Spam")
self.failUnless(object.ObjectField.GetValue() == "eggs")
object.ObjectField = None
self.failUnless(object.ObjectField == None)
object.ObjectField = System.String("spam")
self.failUnless(object.ObjectField == "spam")
object.ObjectField = System.Int32(1)
self.failUnless(object.ObjectField == 1)
# need to test subclass here
def test():
object = ConversionTest()
object.ObjectField = self
self.failUnlessRaises(TypeError, test)
def testEnumConversion(self):
"""Test enum conversion."""
from CLR.Python.Test import ShortEnum
object = ConversionTest()
self.failUnless(object.EnumField == ShortEnum.Zero)
object.EnumField = ShortEnum.One
self.failUnless(object.EnumField == ShortEnum.One)
object.EnumField = 0
self.failUnless(object.EnumField == ShortEnum.Zero)
self.failUnless(object.EnumField == 0)
object.EnumField = 1
self.failUnless(object.EnumField == ShortEnum.One)
self.failUnless(object.EnumField == 1)
def test():
object = ConversionTest()
object.EnumField = 10
self.failUnlessRaises(ValueError, test)
def test():
object = ConversionTest()
object.EnumField = 255
self.failUnlessRaises(ValueError, test)
def test():
object = ConversionTest()
object.EnumField = 1000000
self.failUnlessRaises(OverflowError, test)
def test():
object = ConversionTest()
object.EnumField = "spam"
self.failUnlessRaises(TypeError, test)
def testNullConversion(self):
"""Test null conversion."""
object = ConversionTest()
object.StringField = None
self.failUnless(object.StringField == None)
object.ObjectField = None
self.failUnless(object.ObjectField == None)
object.SpamField = None
self.failUnless(object.SpamField == None)
# Primitive types and enums should not be set to null.
def test():
ConversionTest().Int32Field = None
self.failUnlessRaises(TypeError, test)
def test():
ConversionTest().EnumField = None
self.failUnlessRaises(TypeError, test)
def testByteArrayConversion(self):
"""Test byte array conversion."""
object = ConversionTest()
self.failUnless(object.ByteArrayField == None)
object.ByteArrayField = [0, 1, 2 , 3, 4]
array = object.ByteArrayField
self.failUnless(len(array) == 5)
self.failUnless(array[0] == 0)
self.failUnless(array[4] == 4)
value = "testing"
object.ByteArrayField = value
array = object.ByteArrayField
for i in range(len(value)):
self.failUnless(array[i] == ord(value[i]))
def testSByteArrayConversion(self):
"""Test sbyte array conversion."""
object = ConversionTest()
self.failUnless(object.SByteArrayField == None)
object.SByteArrayField = [0, 1, 2 , 3, 4]
array = object.SByteArrayField
self.failUnless(len(array) == 5)
self.failUnless(array[0] == 0)
self.failUnless(array[4] == 4)
value = "testing"
object.SByteArrayField = value
array = object.SByteArrayField
for i in range(len(value)):
self.failUnless(array[i] == ord(value[i]))
def test_suite():
return unittest.makeSuite(ConversionTests)
def main():
unittest.TextTestRunner().run(test_suite())
if __name__ == '__main__':
testcase.setup()
main()

Просмотреть файл

@ -0,0 +1,325 @@
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
#
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
from CLR.Python.Test import DelegateTest, PublicDelegate
from CLR.Python.Test import StringDelegate, ObjectDelegate
import sys, os, string, unittest, types
import CLR.Python.Test as Test
import CLR.System as System
class DelegateTests(unittest.TestCase):
"""Test CLR delegate support."""
def testDelegateStandardAttrs(self):
"""Test standard delegate attributes."""
self.failUnless(PublicDelegate.__name__ == 'PublicDelegate')
self.failUnless(PublicDelegate.__module__ == 'CLR.Python.Test')
self.failUnless(type(PublicDelegate.__dict__) == types.DictProxyType)
self.failUnless(PublicDelegate.__doc__ == None)
def testGlobalDelegateVisibility(self):
"""Test visibility of module-level delegates."""
from CLR.Python.Test import PublicDelegate
self.failUnless(PublicDelegate.__name__ == 'PublicDelegate')
self.failUnless(Test.PublicDelegate.__name__ == 'PublicDelegate')
def test():
from CLR.Python.Test import InternalDelegate
self.failUnlessRaises(ImportError, test)
def test():
i = Test.InternalDelegate
self.failUnlessRaises(AttributeError, test)
def testNestedDelegateVisibility(self):
"""Test visibility of nested delegates."""
ob = DelegateTest.PublicDelegate
self.failUnless(ob.__name__ == 'PublicDelegate')
ob = DelegateTest.ProtectedDelegate
self.failUnless(ob.__name__ == 'ProtectedDelegate')
def test():
ob = DelegateTest.InternalDelegate
self.failUnlessRaises(AttributeError, test)
def test():
ob = DelegateTest.PrivateDelegate
self.failUnlessRaises(AttributeError, test)
def testDelegateFromFunction(self):
"""Test delegate implemented with a Python function."""
def sayhello():
return "hello"
d = StringDelegate(sayhello)
ob = DelegateTest()
self.failUnless(ob.CallStringDelegate(d) == "hello")
self.failUnless(d() == "hello")
ob.stringDelegate = d
self.failUnless(ob.CallStringDelegate(ob.stringDelegate) == "hello")
self.failUnless(ob.stringDelegate() == "hello")
def testDelegateFromMethod(self):
"""Test delegate implemented with a Python instance method."""
class Hello:
def sayhello(self):
return "hello"
inst = Hello()
d = StringDelegate(inst.sayhello)
ob = DelegateTest()
self.failUnless(ob.CallStringDelegate(d) == "hello")
self.failUnless(d() == "hello")
ob.stringDelegate = d
self.failUnless(ob.CallStringDelegate(ob.stringDelegate) == "hello")
self.failUnless(ob.stringDelegate() == "hello")
def testDelegateFromUnboundMethod(self):
"""Test failure mode for unbound methods."""
class Hello:
def sayhello(self):
return "hello"
def test():
d = StringDelegate(Hello.sayhello)
d()
self.failUnlessRaises(TypeError, test)
def testDelegateFromStaticMethod(self):
"""Test delegate implemented with a Python static method."""
class Hello:
def sayhello():
return "hello"
sayhello = staticmethod(sayhello)
d = StringDelegate(Hello.sayhello)
ob = DelegateTest()
self.failUnless(ob.CallStringDelegate(d) == "hello")
self.failUnless(d() == "hello")
ob.stringDelegate = d
self.failUnless(ob.CallStringDelegate(ob.stringDelegate) == "hello")
self.failUnless(ob.stringDelegate() == "hello")
inst = Hello()
d = StringDelegate(inst.sayhello)
ob = DelegateTest()
self.failUnless(ob.CallStringDelegate(d) == "hello")
self.failUnless(d() == "hello")
ob.stringDelegate = d
self.failUnless(ob.CallStringDelegate(ob.stringDelegate) == "hello")
self.failUnless(ob.stringDelegate() == "hello")
def testDelegateFromClassMethod(self):
"""Test delegate implemented with a Python class method."""
class Hello:
def sayhello(self):
return "hello"
sayhello = classmethod(sayhello)
d = StringDelegate(Hello.sayhello)
ob = DelegateTest()
self.failUnless(ob.CallStringDelegate(d) == "hello")
self.failUnless(d() == "hello")
ob.stringDelegate = d
self.failUnless(ob.CallStringDelegate(ob.stringDelegate) == "hello")
self.failUnless(ob.stringDelegate() == "hello")
inst = Hello()
d = StringDelegate(inst.sayhello)
ob = DelegateTest()
self.failUnless(ob.CallStringDelegate(d) == "hello")
self.failUnless(d() == "hello")
ob.stringDelegate = d
self.failUnless(ob.CallStringDelegate(ob.stringDelegate) == "hello")
self.failUnless(ob.stringDelegate() == "hello")
def testDelegateFromCallable(self):
"""Test delegate implemented with a Python callable object."""
class Hello:
def __call__(self):
return "hello"
inst = Hello()
d = StringDelegate(inst)
ob = DelegateTest()
self.failUnless(ob.CallStringDelegate(d) == "hello")
self.failUnless(d() == "hello")
ob.stringDelegate = d
self.failUnless(ob.CallStringDelegate(ob.stringDelegate) == "hello")
self.failUnless(ob.stringDelegate() == "hello")
def testDelegateFromManagedInstanceMethod(self):
"""Test delegate implemented with a managed instance method."""
ob = DelegateTest()
d = StringDelegate(ob.SayHello)
self.failUnless(ob.CallStringDelegate(d) == "hello")
self.failUnless(d() == "hello")
ob.stringDelegate = d
self.failUnless(ob.CallStringDelegate(ob.stringDelegate) == "hello")
self.failUnless(ob.stringDelegate() == "hello")
def testDelegateFromManagedStaticMethod(self):
"""Test delegate implemented with a managed static method."""
d = StringDelegate(DelegateTest.StaticSayHello)
ob = DelegateTest()
self.failUnless(ob.CallStringDelegate(d) == "hello")
self.failUnless(d() == "hello")
ob.stringDelegate = d
self.failUnless(ob.CallStringDelegate(ob.stringDelegate) == "hello")
self.failUnless(ob.stringDelegate() == "hello")
def testDelegateFromDelegate(self):
"""Test delegate implemented with another delegate."""
def sayhello():
return "hello"
d1 = StringDelegate(sayhello)
d2 = StringDelegate(d1)
ob = DelegateTest()
self.failUnless(ob.CallStringDelegate(d2) == "hello")
self.failUnless(d2() == "hello")
ob.stringDelegate = d2
self.failUnless(ob.CallStringDelegate(ob.stringDelegate) == "hello")
self.failUnless(ob.stringDelegate() == "hello")
def testDelegateWithInvalidArgs(self):
"""Test delegate instantiation with invalid (non-callable) args."""
def test():
d = StringDelegate(None)
self.failUnlessRaises(TypeError, test)
def test():
d = StringDelegate("spam")
self.failUnlessRaises(TypeError, test)
def test():
d = StringDelegate(1)
self.failUnlessRaises(TypeError, test)
def testMulticastDelegate(self):
"""Test multicast delegates."""
class Multi:
def __init__(self):
self.value = 0
def count(self):
self.value += 1
return 'ok'
inst = Multi()
d1 = StringDelegate(inst.count)
d2 = StringDelegate(inst.count)
md = System.Delegate.Combine(d1, d2)
ob = DelegateTest()
self.failUnless(ob.CallStringDelegate(md) == "ok")
self.failUnless(inst.value == 2)
self.failUnless(md() == "ok")
self.failUnless(inst.value == 4)
def testSubclassDelegateFails(self):
"""Test that subclassing of a delegate type fails."""
def test():
class Boom(PublicDelegate):
pass
self.failUnlessRaises(TypeError, test)
def testDelegateEquality(self):
"""Test delegate equality."""
def sayhello():
return "hello"
d = StringDelegate(sayhello)
ob = DelegateTest()
ob.stringDelegate = d
self.failUnless(ob.stringDelegate == d)
# test async delegates
# test multicast delegates
# test explicit op_
# test sig mismatch, both on managed and Python side
# test return wrong type
def test_suite():
return unittest.makeSuite(DelegateTests)
def main():
unittest.TextTestRunner().run(test_suite())
if __name__ == '__main__':
testcase.setup()
main()

Просмотреть файл

@ -0,0 +1,56 @@
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
#
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
import sys, os, string, unittest, types, CLR
from CLR.Python.Runtime import PythonEngine
class EngineTests(unittest.TestCase):
"""Test PythonEngine embedding APIs."""
def testMultipleCallsToInitialize(self):
"""Test that multiple initialize calls are harmless."""
PythonEngine.Initialize();
PythonEngine.Initialize();
PythonEngine.Initialize();
def testImportModule(self):
"""Test module import."""
m = PythonEngine.ImportModule("sys")
n = m.GetAttr("__name__")
self.failUnless(n.AsManagedObject(CLR.System.String) == "sys")
def testRunString(self):
"""Test the RunString method."""
PythonEngine.AcquireLock()
code = "import sys; sys.singleline_worked = 1"
PythonEngine.RunString(code)
self.failUnless(sys.singleline_worked == 1)
code = "import sys\nsys.multiline_worked = 1"
PythonEngine.RunString(code)
self.failUnless(sys.multiline_worked == 1)
PythonEngine.ReleaseLock()
def test_suite():
return unittest.makeSuite(EngineTests)
def main():
unittest.TextTestRunner().run(test_suite())
if __name__ == '__main__':
testcase.setup()
main()

Просмотреть файл

@ -0,0 +1,174 @@
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
#
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
import sys, os, string, unittest, types
from CLR.System import DayOfWeek
from CLR.Python import Test
class EnumTests(unittest.TestCase):
"""Test CLR enum support."""
def testEnumStandardAttrs(self):
"""Test standard enum attributes."""
self.failUnless(DayOfWeek.__name__ == 'DayOfWeek')
self.failUnless(DayOfWeek.__module__ == 'CLR.System')
self.failUnless(type(DayOfWeek.__dict__) == types.DictProxyType)
self.failUnless(DayOfWeek.__doc__ == '')
def testEnumGetMember(self):
"""Test access to enum members."""
self.failUnless(DayOfWeek.Sunday == 0)
self.failUnless(DayOfWeek.Monday == 1)
self.failUnless(DayOfWeek.Tuesday == 2)
self.failUnless(DayOfWeek.Wednesday == 3)
self.failUnless(DayOfWeek.Thursday == 4)
self.failUnless(DayOfWeek.Friday == 5)
self.failUnless(DayOfWeek.Saturday == 6)
def testByteEnum(self):
"""Test byte enum."""
self.failUnless(Test.ByteEnum.Zero == 0)
self.failUnless(Test.ByteEnum.One == 1)
self.failUnless(Test.ByteEnum.Two == 2)
def testSByteEnum(self):
"""Test sbyte enum."""
self.failUnless(Test.SByteEnum.Zero == 0)
self.failUnless(Test.SByteEnum.One == 1)
self.failUnless(Test.SByteEnum.Two == 2)
def testShortEnum(self):
"""Test short enum."""
self.failUnless(Test.ShortEnum.Zero == 0)
self.failUnless(Test.ShortEnum.One == 1)
self.failUnless(Test.ShortEnum.Two == 2)
def testUShortEnum(self):
"""Test ushort enum."""
self.failUnless(Test.UShortEnum.Zero == 0)
self.failUnless(Test.UShortEnum.One == 1)
self.failUnless(Test.UShortEnum.Two == 2)
def testIntEnum(self):
"""Test int enum."""
self.failUnless(Test.IntEnum.Zero == 0)
self.failUnless(Test.IntEnum.One == 1)
self.failUnless(Test.IntEnum.Two == 2)
def testUIntEnum(self):
"""Test uint enum."""
self.failUnless(Test.UIntEnum.Zero == 0L)
self.failUnless(Test.UIntEnum.One == 1L)
self.failUnless(Test.UIntEnum.Two == 2L)
def testLongEnum(self):
"""Test long enum."""
self.failUnless(Test.LongEnum.Zero == 0L)
self.failUnless(Test.LongEnum.One == 1L)
self.failUnless(Test.LongEnum.Two == 2L)
def testULongEnum(self):
"""Test ulong enum."""
self.failUnless(Test.ULongEnum.Zero == 0L)
self.failUnless(Test.ULongEnum.One == 1L)
self.failUnless(Test.ULongEnum.Two == 2L)
def testInstantiateEnumFails(self):
"""Test that instantiation of an enum class fails."""
def test():
ob = DayOfWeek()
self.failUnlessRaises(TypeError, test)
def testSubclassEnumFails(self):
"""Test that subclassing of an enumeration fails."""
def test():
class Boom(DayOfWeek):
pass
self.failUnlessRaises(TypeError, test)
def testEnumSetMemberFails(self):
"""Test that setattr operations on enumerations fail."""
def test():
DayOfWeek.Sunday = 13
self.failUnlessRaises(TypeError, test)
def test():
del DayOfWeek.Sunday
self.failUnlessRaises(TypeError, test)
def testEnumWithFlagsAttrConversion(self):
"""Test enumeration conversion with FlagsAttribute set."""
from CLR.System.Windows.Forms import Label
# This works because the AnchorStyles enum has FlagsAttribute.
label = Label()
label.Anchor = 99
# This should fail because our test enum doesn't have it.
def test():
Test.FieldTest().EnumField = 99
self.failUnlessRaises(ValueError, test)
def testEnumConversion(self):
"""Test enumeration conversion."""
object = Test.FieldTest()
self.failUnless(object.EnumField == 0)
object.EnumField = Test.ShortEnum.One
self.failUnless(object.EnumField == 1)
def test():
Test.FieldTest().EnumField = 20
self.failUnlessRaises(ValueError, test)
def test():
Test.FieldTest().EnumField = 100000
self.failUnlessRaises(OverflowError, test)
def test():
Test.FieldTest().EnumField = "str"
self.failUnlessRaises(TypeError, test)
def test_suite():
return unittest.makeSuite(EnumTests)
def main():
unittest.TextTestRunner().run(test_suite())
if __name__ == '__main__':
testcase.setup()
main()

Просмотреть файл

@ -0,0 +1,723 @@
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
#
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
import sys, os, string, unittest, types
from CLR.Python.Test import EventTest, TestEventHandler
from CLR.Python.Test import TestEventArgs
class EventTests(unittest.TestCase):
"""Test CLR event support."""
def testPublicInstanceEvent(self):
"""Test public instance events."""
object = EventTest()
handler = GenericHandler()
self.failUnless(handler.value == None)
object.PublicEvent += handler.handler
object.OnPublicEvent(TestEventArgs(10))
self.failUnless(handler.value == 10)
object.PublicEvent -= handler.handler
def testPublicStaticEvent(self):
"""Test public static events."""
handler = GenericHandler()
self.failUnless(handler.value == None)
EventTest.PublicStaticEvent += handler.handler
EventTest.OnPublicStaticEvent(TestEventArgs(10))
self.failUnless(handler.value == 10)
def testProtectedInstanceEvent(self):
"""Test protected instance events."""
object = EventTest()
handler = GenericHandler()
self.failUnless(handler.value == None)
object.ProtectedEvent += handler.handler
object.OnProtectedEvent(TestEventArgs(10))
self.failUnless(handler.value == 10)
object.ProtectedEvent -= handler.handler
def testProtectedStaticEvent(self):
"""Test protected static events."""
object = EventTest
handler = GenericHandler()
self.failUnless(handler.value == None)
EventTest.ProtectedStaticEvent += handler.handler
EventTest.OnProtectedStaticEvent(TestEventArgs(10))
self.failUnless(handler.value == 10)
EventTest.ProtectedStaticEvent -= handler.handler
def testInternalEvents(self):
"""Test internal events."""
def test():
f = EventTest().InternalEvent
self.failUnlessRaises(AttributeError, test)
def test():
f = EventTest().InternalStaticEvent
self.failUnlessRaises(AttributeError, test)
def test():
f = EventTest.InternalStaticEvent
self.failUnlessRaises(AttributeError, test)
def testPrivateEvents(self):
"""Test private events."""
def test():
f = EventTest().PrivateEvent
self.failUnlessRaises(AttributeError, test)
def test():
f = EventTest().PrivateStaticEvent
self.failUnlessRaises(AttributeError, test)
def test():
f = EventTest.PrivateStaticEvent
self.failUnlessRaises(AttributeError, test)
def testMulticastEvent(self):
"""Test multicast events."""
object = EventTest()
handler1 = GenericHandler()
handler2 = GenericHandler()
handler3 = GenericHandler()
object.PublicEvent += handler1.handler
object.PublicEvent += handler2.handler
object.PublicEvent += handler3.handler
object.OnPublicEvent(TestEventArgs(10))
self.failUnless(handler1.value == 10)
self.failUnless(handler2.value == 10)
self.failUnless(handler3.value == 10)
object.OnPublicEvent(TestEventArgs(20))
self.failUnless(handler1.value == 20)
self.failUnless(handler2.value == 20)
self.failUnless(handler3.value == 20)
object.PublicEvent -= handler1.handler
object.PublicEvent -= handler2.handler
object.PublicEvent -= handler3.handler
def testInstanceMethodHandler(self):
"""Test instance method handlers."""
object = EventTest()
handler = GenericHandler()
object.PublicEvent += handler.handler
self.failUnless(handler.value == None)
object.OnPublicEvent(TestEventArgs(10))
self.failUnless(handler.value == 10)
object.PublicEvent -= handler.handler
self.failUnless(handler.value == 10)
object.OnPublicEvent(TestEventArgs(20))
self.failUnless(handler.value == 10)
def testVarArgsInstanceMethodHandler(self):
"""Test vararg instance method handlers."""
object = EventTest()
handler = VariableArgsHandler()
object.PublicEvent += handler.handler
self.failUnless(handler.value == None)
object.OnPublicEvent(TestEventArgs(10))
self.failUnless(handler.value == 10)
object.PublicEvent -= handler.handler
self.failUnless(handler.value == 10)
object.OnPublicEvent(TestEventArgs(20))
self.failUnless(handler.value == 10)
def testCallableObjectHandler(self):
"""Test callable object handlers."""
object = EventTest()
handler = CallableHandler()
object.PublicEvent += handler
self.failUnless(handler.value == None)
object.OnPublicEvent(TestEventArgs(10))
self.failUnless(handler.value == 10)
object.PublicEvent -= handler
self.failUnless(handler.value == 10)
object.OnPublicEvent(TestEventArgs(20))
self.failUnless(handler.value == 10)
def testVarArgsCallableHandler(self):
"""Test varargs callable handlers."""
object = EventTest()
handler = VarCallableHandler()
object.PublicEvent += handler
self.failUnless(handler.value == None)
object.OnPublicEvent(TestEventArgs(10))
self.failUnless(handler.value == 10)
object.PublicEvent -= handler
self.failUnless(handler.value == 10)
object.OnPublicEvent(TestEventArgs(20))
self.failUnless(handler.value == 10)
def testStaticMethodHandler(self):
"""Test static method handlers."""
object = EventTest()
handler = StaticMethodHandler()
StaticMethodHandler.value = None
object.PublicEvent += handler.handler
self.failUnless(handler.value == None)
object.OnPublicEvent(TestEventArgs(10))
self.failUnless(handler.value == 10)
object.PublicEvent -= handler.handler
self.failUnless(handler.value == 10)
object.OnPublicEvent(TestEventArgs(20))
self.failUnless(handler.value == 10)
def testClassMethodHandler(self):
"""Test class method handlers."""
object = EventTest()
handler = ClassMethodHandler()
ClassMethodHandler.value = None
object.PublicEvent += handler.handler
self.failUnless(handler.value == None)
object.OnPublicEvent(TestEventArgs(10))
self.failUnless(handler.value == 10)
object.PublicEvent -= handler.handler
self.failUnless(handler.value == 10)
object.OnPublicEvent(TestEventArgs(20))
self.failUnless(handler.value == 10)
def testManagedInstanceMethodHandler(self):
"""Test managed instance method handlers."""
object = EventTest()
object.PublicEvent += object.GenericHandler
self.failUnless(object.value == 0)
object.OnPublicEvent(TestEventArgs(10))
self.failUnless(object.value == 10)
object.PublicEvent -= object.GenericHandler
self.failUnless(object.value == 10)
object.OnPublicEvent(TestEventArgs(20))
self.failUnless(object.value == 10)
def testManagedStaticMethodHandler(self):
"""Test managed static method handlers."""
object = EventTest()
EventTest.s_value = 0
object.PublicEvent += object.StaticHandler
self.failUnless(EventTest.s_value == 0)
object.OnPublicEvent(TestEventArgs(10))
self.failUnless(EventTest.s_value == 10)
object.PublicEvent -= object.StaticHandler
self.failUnless(EventTest.s_value == 10)
object.OnPublicEvent(TestEventArgs(20))
self.failUnless(EventTest.s_value == 10)
def testUnboundMethodHandler(self):
"""Test failure mode for unbound method handlers."""
object = EventTest()
object.PublicEvent += GenericHandler.handler
try:
object.OnPublicEvent(TestEventArgs(10))
except TypeError:
object.PublicEvent -= GenericHandler.handler
return
raise TypeError("should have raised a TypeError")
def testFunctionHandler(self):
"""Test function handlers."""
object = EventTest()
dict = {'value':None}
def handler(sender, args, dict=dict):
dict['value'] = args.value
object.PublicEvent += handler
self.failUnless(dict['value'] == None)
object.OnPublicEvent(TestEventArgs(10))
self.failUnless(dict['value'] == 10)
object.PublicEvent -= handler
self.failUnless(dict['value'] == 10)
object.OnPublicEvent(TestEventArgs(20))
self.failUnless(dict['value'] == 10)
def testAddNonCallableHandler(self):
"""Test handling of attempts to add non-callable handlers."""
def test():
object = EventTest()
object.PublicEvent += 10
self.failUnlessRaises(TypeError, test)
def test():
object = EventTest()
object.PublicEvent += "spam"
self.failUnlessRaises(TypeError, test)
def test():
class spam:
pass
object = EventTest()
object.PublicEvent += spam()
self.failUnlessRaises(TypeError, test)
def testRemoveMultipleHandlers(self):
"""Test removing multiple instances of the same handler."""
object = EventTest()
handler = MultipleHandler()
h1 = handler.handler
object.PublicEvent += h1
h2 = handler.handler
object.PublicEvent += h2
object.OnPublicEvent(TestEventArgs(10))
self.failUnless(handler.value == 20)
object.PublicEvent -= h1
object.OnPublicEvent(TestEventArgs(10))
self.failUnless(handler.value == 30)
object.PublicEvent -= h2
object.OnPublicEvent(TestEventArgs(10))
self.failUnless(handler.value == 30)
# try again, removing in a different order.
object = EventTest()
handler = MultipleHandler()
h1 = handler.handler
object.PublicEvent += h1
h2 = handler.handler
object.PublicEvent += h2
object.OnPublicEvent(TestEventArgs(10))
self.failUnless(handler.value == 20)
object.PublicEvent -= h2
object.OnPublicEvent(TestEventArgs(10))
self.failUnless(handler.value == 30)
object.PublicEvent -= h1
object.OnPublicEvent(TestEventArgs(10))
self.failUnless(handler.value == 30)
def testRemoveMultipleStaticHandlers(self):
"""Test removing multiple instances of a static handler."""
object = EventTest()
handler = MultipleHandler()
h1 = handler.handler
object.PublicStaticEvent += h1
h2 = handler.handler
object.PublicStaticEvent += h2
object.OnPublicStaticEvent(TestEventArgs(10))
self.failUnless(handler.value == 20)
object.PublicStaticEvent -= h1
object.OnPublicStaticEvent(TestEventArgs(10))
self.failUnless(handler.value == 30)
object.PublicStaticEvent -= h2
object.OnPublicStaticEvent(TestEventArgs(10))
self.failUnless(handler.value == 30)
# try again, removing in a different order.
object = EventTest()
handler = MultipleHandler()
h1 = handler.handler
object.PublicStaticEvent += h1
h2 = handler.handler
object.PublicStaticEvent += h2
object.OnPublicStaticEvent(TestEventArgs(10))
self.failUnless(handler.value == 20)
object.PublicStaticEvent -= h2
object.OnPublicStaticEvent(TestEventArgs(10))
self.failUnless(handler.value == 30)
object.PublicStaticEvent -= h1
object.OnPublicStaticEvent(TestEventArgs(10))
self.failUnless(handler.value == 30)
def testRandomMultipleHandlers(self):
"""Test random subscribe / unsubscribe of the same handlers."""
import random
object = EventTest()
handler = MultipleHandler()
handler2 = MultipleHandler()
object.PublicEvent += handler2.handler
object.PublicEvent += handler2.handler
handlers = []
for i in range(30):
method = handler.handler
object.PublicEvent += method
handlers.append(method)
object.OnPublicEvent(TestEventArgs(10))
self.failUnless(handler.value == 300)
self.failUnless(handler2.value == 20)
handler.value = 0
handler2.value = 0
for i in range(30):
item = random.choice(handlers)
handlers.remove(item)
object.PublicEvent -= item
handler.value = 0
object.OnPublicEvent(TestEventArgs(10))
self.failUnless(handler.value == (len(handlers) * 10))
self.failUnless(handler2.value == ((i + 1) * 20))
handler2.value = 0
object.OnPublicEvent(TestEventArgs(10))
self.failUnless(handler2.value == 20)
object.PublicEvent -= handler2.handler
handler2.value = 0
object.OnPublicEvent(TestEventArgs(10))
self.failUnless(handler2.value == 10)
object.PublicEvent -= handler2.handler
handler2.value = 0
object.OnPublicEvent(TestEventArgs(10))
self.failUnless(handler2.value == 0)
def testRemoveInternalCallHandler(self):
"""Test remove on an event sink implemented w/internalcall."""
object = EventTest()
def h(sender, args):
pass
object.PublicEvent += h
object.PublicEvent -= h
from CLR.System.Windows.Forms import Form
f = Form()
f.Click += h
f.Click -= h
f.Dispose()
def testRemoveUnknownHandler(self):
"""Test removing an event handler that was never added."""
def test():
object = EventTest()
handler = GenericHandler()
object.PublicEvent -= handler.handler
self.failUnlessRaises(ValueError, test)
def testHandlerCallbackFailure(self):
"""Test failure mode for inappropriate handlers."""
class BadHandler:
def handler(self, one):
return 'too many'
object = EventTest()
handler = BadHandler()
def test():
object.PublicEvent += handler.handler
object.OnPublicEvent(TestEventArgs(10))
self.failUnlessRaises(TypeError, test)
object.PublicEvent -= handler.handler
class BadHandler:
def handler(self, one, two, three, four, five):
return 'not enough'
object = EventTest()
handler = BadHandler()
def test():
object.PublicEvent += handler.handler
object.OnPublicEvent(TestEventArgs(10))
self.failUnlessRaises(TypeError, test)
object.PublicEvent -= handler.handler
def testIncorrectInvokation(self):
"""Test incorrect invokation of events."""
object = EventTest()
handler = GenericHandler()
object.PublicEvent += handler.handler
def test():
object.OnPublicEvent()
self.failUnlessRaises(TypeError, test)
def test():
object.OnPublicEvent(32)
self.failUnlessRaises(TypeError, test)
object.PublicEvent -= handler.handler
def testExplicitCLSEventRegistration(self):
"""Test explicit CLS event registration."""
object = EventTest()
handler = GenericHandler()
delegate = TestEventHandler(handler.handler)
object.add_PublicEvent(delegate)
self.failUnless(handler.value == None)
object.OnPublicEvent(TestEventArgs(10))
self.failUnless(handler.value == 10)
object.remove_PublicEvent(delegate)
self.failUnless(handler.value == 10)
object.OnPublicEvent(TestEventArgs(20))
self.failUnless(handler.value == 10)
def testImplicitCLSEventRegistration(self):
"""Test implicit CLS event registration."""
def test():
object = EventTest()
handler = GenericHandler()
object.add_PublicEvent(handler.handler)
self.failUnlessRaises(TypeError, test)
def testEventDescriptorAbuse(self):
"""Test event descriptor abuse."""
def test():
del EventTest.PublicEvent
self.failUnlessRaises(TypeError, test)
def test():
del EventTest.__dict__['PublicEvent']
self.failUnlessRaises(TypeError, test)
desc = EventTest.__dict__['PublicEvent']
def test():
desc.__get__(0, 0)
self.failUnlessRaises(TypeError, test)
def test():
desc.__set__(0, 0)
self.failUnlessRaises(TypeError, test)
def test():
object = EventTest()
object.PublicEvent = 0
self.failUnlessRaises(TypeError, test)
def test():
EventTest.PublicStaticEvent = 0
self.failUnlessRaises(TypeError, test)
class GenericHandler:
"""A generic handler to test event callbacks."""
def __init__(self):
self.value = None
def handler(self, sender, args):
self.value = args.value
class VariableArgsHandler:
"""A variable args handler to test event callbacks."""
def __init__(self):
self.value = None
def handler(self, *args):
ob, eventargs = args
self.value = eventargs.value
class CallableHandler:
"""A callable handler to test event callbacks."""
def __init__(self):
self.value = None
def __call__(self, sender, args):
self.value = args.value
class VarCallableHandler:
"""A variable args callable handler to test event callbacks."""
def __init__(self):
self.value = None
def __call__(self, *args):
ob, eventargs = args
self.value = eventargs.value
class StaticMethodHandler(object):
"""A static method handler to test event callbacks."""
value = None
def handler(sender, args):
StaticMethodHandler.value = args.value
handler = staticmethod(handler)
class ClassMethodHandler(object):
"""A class method handler to test event callbacks."""
value = None
def handler(cls, sender, args):
cls.value = args.value
handler = classmethod(handler)
class MultipleHandler:
"""A generic handler to test multiple callbacks."""
def __init__(self):
self.value = 0
def handler(self, sender, args):
self.value += args.value
def test_suite():
return unittest.makeSuite(EventTests)
def main():
unittest.TextTestRunner().run(test_suite())
if __name__ == '__main__':
testcase.setup()
main()

Просмотреть файл

@ -0,0 +1,341 @@
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
#
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
import sys, os, string, unittest, types
from CLR import System
# Note: all of these tests are known to fail because Python currently
# doesn't allow new-style classes to be used as exceptions. I'm leaving
# the tests in place in to document 'how it ought to work' in the hopes
# that they'll all pass one day...
class ExceptionTests(unittest.TestCase):
"""Test exception support."""
def testUnifiedExceptionSemantics(self):
"""Test unified exception semantics."""
from CLR.System import Exception, Object
import exceptions
e = Exception('Something bad happened')
self.failUnless(isinstance(e, exceptions.Exception))
self.failUnless(isinstance(e, Exception))
def testStandardExceptionAttributes(self):
"""Test accessing standard exception attributes."""
from CLR.System import OverflowException
from CLR.Python.Test import ExceptionTest
e = ExceptionTest.GetExplicitException()
self.failUnless(isinstance(e, OverflowException))
self.failUnless(e.Message == 'error')
e.Source = 'Test Suite'
self.failUnless(e.Source == 'Test Suite')
v = e.ToString()
self.failUnless(len(v) > 0)
def testExtendedExceptionAttributes(self):
"""Test accessing extended exception attributes."""
from CLR.Python.Test import ExceptionTest, ExtendedException
from CLR.System import Exception, OverflowException
import exceptions
e = ExceptionTest.GetExtendedException()
self.failUnless(isinstance(e, ExtendedException))
self.failUnless(isinstance(e, OverflowException))
self.failUnless(isinstance(e, Exception))
self.failUnless(e.Message == 'error')
e.Source = 'Test Suite'
self.failUnless(e.Source == 'Test Suite')
v = e.ToString()
self.failUnless(len(v) > 0)
self.failUnless(e.ExtraProperty == 'extra')
e.ExtraProperty = 'changed'
self.failUnless(e.ExtraProperty == 'changed')
self.failUnless(e.GetExtraInfo() == 'changed')
def testRaiseClassException(self):
"""Test class exception propagation."""
from CLR.System import NullReferenceException
def test():
raise NullReferenceException
self.failUnlessRaises(NullReferenceException, test)
try:
raise NullReferenceException
except:
type, value, tb = sys.exc_info()
self.failUnless(type is NullReferenceException)
self.failUnless(isinstance(value, NullReferenceException))
def testRaiseClassExceptionWithValue(self):
"""Test class exception propagation with associated value."""
from CLR.System import NullReferenceException
def test():
raise NullReferenceException, 'Aiiieee!'
self.failUnlessRaises(NullReferenceException, test)
try:
raise NullReferenceException('Aiiieee!')
except:
type, value, tb = sys.exc_info()
self.failUnless(type is NullReferenceException)
self.failUnless(isinstance(value, NullReferenceException))
self.failUnless(value.Message == 'Aiiieee!')
def testRaiseInstanceException(self):
"""Test instance exception propagation."""
from CLR.System import NullReferenceException
def test():
raise NullReferenceException()
self.failUnlessRaises(NullReferenceException, test)
try:
raise NullReferenceException()
except:
type, value, tb = sys.exc_info()
self.failUnless(type is NullReferenceException)
self.failUnless(isinstance(value, NullReferenceException))
self.failUnless(len(value.Message) > 0)
def testRaiseInstanceExceptionWithArgs(self):
"""Test instance exception propagation with args."""
from CLR.System import NullReferenceException
def test():
raise NullReferenceException("Aiieeee!")
self.failUnlessRaises(NullReferenceException, test)
try:
raise NullReferenceException('Aiiieee!')
except:
type, value, tb = sys.exc_info()
self.failUnless(type is NullReferenceException)
self.failUnless(isinstance(value, NullReferenceException))
self.failUnless(value.Message == 'Aiiieee!')
def testManagedExceptionPropagation(self):
"""Test propagation of exceptions raised in managed code."""
from CLR.System import Decimal, OverflowException
def test():
l = Decimal.ToInt64(Decimal.MaxValue)
self.failUnlessRaises(OverflowException, test)
def testManagedExceptionConversion(self):
"""Test conversion of managed exceptions."""
from CLR.System import Exception, OverflowException
from CLR.Python.Test import ExceptionTest
e = ExceptionTest.GetBaseException()
self.failUnless(isinstance(e, Exception))
e = ExceptionTest.GetExplicitException()
self.failUnless(isinstance(e, OverflowException))
self.failUnless(isinstance(e, Exception))
e = ExceptionTest.GetWidenedException()
self.failUnless(isinstance(e, OverflowException))
self.failUnless(isinstance(e, Exception))
v = ExceptionTest.SetBaseException(Exception('error'))
self.failUnless(v)
v = ExceptionTest.SetExplicitException(OverflowException('error'))
self.failUnless(v)
v = ExceptionTest.SetWidenedException(OverflowException('error'))
self.failUnless(v)
def testCatchExceptionFromManagedMethod(self):
"""Test catching an exception from a managed method."""
from CLR.Python.Test import ExceptionTest
from CLR.System import OverflowException
try:
ExceptionTest().ThrowException()
except OverflowException, e:
self.failUnless(isinstance(e, OverflowException))
return
raise SystemError('failed to catch exception from managed method')
def testCatchExceptionFromManagedProperty(self):
"""Test catching an exception from a managed property."""
from CLR.Python.Test import ExceptionTest
from CLR.System import OverflowException
try:
v = ExceptionTest().ThrowProperty
except OverflowException, e:
self.failUnless(isinstance(e, OverflowException))
return
try:
ExceptionTest().ThrowProperty = 1
except OverflowException, e:
self.failUnless(isinstance(e, OverflowException))
return
raise SystemError('failed to catch exception from managed property')
def testCatchExceptionManagedClass(self):
"""Test catching the managed class of an exception."""
from CLR.System import OverflowException
try:
raise OverflowException('overflow')
except OverflowException:
return
raise SystemError('failed to catch managed class exception')
def testCatchExceptionPythonClass(self):
"""Test catching the python class of an exception."""
from CLR.System import OverflowException
from exceptions import Exception
try:
raise OverflowException('overflow')
except Exception:
return
raise SystemError('failed to catch python class exception')
def testCatchExceptionBaseClass(self):
"""Test catching the base of an exception."""
from CLR.System import OverflowException, ArithmeticException
try:
raise OverflowException('overflow')
except ArithmeticException:
return
raise SystemError('failed to catch base exception')
def testCatchExceptionNestedBaseClass(self):
"""Test catching the nested base of an exception."""
from CLR.System import OverflowException, SystemException
try:
raise OverflowException('overflow')
except SystemException:
return
raise SystemError('failed to catch nested base exception')
def testCatchExceptionWithAssignment(self):
"""Test catching an exception with assignment."""
from CLR.System import OverflowException
try:
raise OverflowException('overflow')
except OverflowException, e:
self.failUnless(isinstance(e, OverflowException))
def testCatchExceptionUnqualified(self):
"""Test catching an unqualified exception."""
from CLR.System import OverflowException
try:
raise OverflowException('overflow')
except:
return
raise SystemError('failed to catch unqualified exception')
def testApparentModuleOfException(self):
"""Test the apparent module of an exception."""
from CLR.System import Exception, OverflowException
self.failUnless(Exception.__module__ == 'CLR.System')
self.failUnless(OverflowException.__module__ == 'CLR.System')
def testStrOfException(self):
"""Test the str() representation of an exception."""
from CLR.System import NullReferenceException
from CLR.System import Convert, FormatException
e = NullReferenceException('')
self.failUnless(str(e) == '')
e = NullReferenceException('Something bad happened')
self.failUnless(str(e).startswith('Something bad happened'))
try:
Convert.ToDateTime('this will fail')
except FormatException, e:
self.failUnless(str(e).find('at System.DateTime.Parse') > -1)
def testExceptionIsInstanceOfSystemObject(self):
"""Test behavior of isinstance(<managed exception>, System.Object)."""
# This is an anti-test, in that this is a caveat of the current
# implementation. Because exceptions are not allowed to be new-style
# classes, we wrap managed exceptions in a general-purpose old-style
# class that delegates to the wrapped object. This makes _almost_
# everything work as expected, except that an isinstance check against
# CLR.System.Object will fail for a managed exception (because a new
# style class cannot appear in the __bases__ of an old-style class
# without causing a crash in the CPython interpreter). This test is
# here mainly to remind me to update the caveat in the documentation
# one day when when exceptions can be new-style classes.
from CLR.System import OverflowException
from CLR.System import Object
o = OverflowException('error')
self.failIf(isinstance(o, Object))
def test_suite():
return unittest.makeSuite(ExceptionTests)
def main():
unittest.TextTestRunner().run(test_suite())
if __name__ == '__main__':
testcase.setup()
main()

Просмотреть файл

@ -0,0 +1,467 @@
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
#
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
import sys, os, string, unittest, types
from CLR.Python.Test import FieldTest
from CLR.Python.Test import ShortEnum
from CLR import System
class FieldTests(unittest.TestCase):
"""Test CLR field support."""
def testPublicInstanceField(self):
"""Test public instance fields."""
object = FieldTest();
self.failUnless(object.PublicField == 0)
object.PublicField = 1
self.failUnless(object.PublicField == 1)
def test():
del FieldTest().PublicField
self.failUnlessRaises(TypeError, test)
def testPublicStaticField(self):
"""Test public static fields."""
object = FieldTest();
self.failUnless(FieldTest.PublicStaticField == 0)
FieldTest.PublicStaticField = 1
self.failUnless(FieldTest.PublicStaticField == 1)
self.failUnless(object.PublicStaticField == 1)
object.PublicStaticField = 0
self.failUnless(object.PublicStaticField == 0)
def test():
del FieldTest.PublicStaticField
self.failUnlessRaises(TypeError, test)
def test():
del FieldTest().PublicStaticField
self.failUnlessRaises(TypeError, test)
def testProtectedInstanceField(self):
"""Test protected instance fields."""
object = FieldTest();
self.failUnless(object.ProtectedField == 0)
object.ProtectedField = 1
self.failUnless(object.ProtectedField == 1)
def test():
del FieldTest().ProtectedField
self.failUnlessRaises(TypeError, test)
def testProtectedStaticField(self):
"""Test protected static fields."""
object = FieldTest();
self.failUnless(FieldTest.ProtectedStaticField == 0)
FieldTest.ProtectedStaticField = 1
self.failUnless(FieldTest.ProtectedStaticField == 1)
self.failUnless(object.ProtectedStaticField == 1)
object.ProtectedStaticField = 0
self.failUnless(object.ProtectedStaticField == 0)
def test():
del FieldTest.ProtectedStaticField
self.failUnlessRaises(TypeError, test)
def test():
del FieldTest().ProtectedStaticField
self.failUnlessRaises(TypeError, test)
def testReadOnlyInstanceField(self):
"""Test readonly instance fields."""
self.failUnless(FieldTest().ReadOnlyField == 0)
def test():
FieldTest().ReadOnlyField = 1
self.failUnlessRaises(TypeError, test)
def test():
del FieldTest().ReadOnlyField
self.failUnlessRaises(TypeError, test)
def testReadOnlyStaticField(self):
"""Test readonly static fields."""
object = FieldTest();
self.failUnless(FieldTest.ReadOnlyStaticField == 0)
self.failUnless(object.ReadOnlyStaticField == 0)
def test():
FieldTest.ReadOnlyStaticField = 1
self.failUnlessRaises(TypeError, test)
def test():
FieldTest().ReadOnlyStaticField = 1
self.failUnlessRaises(TypeError, test)
def test():
del FieldTest.ReadOnlyStaticField
self.failUnlessRaises(TypeError, test)
def test():
del FieldTest().ReadOnlyStaticField
self.failUnlessRaises(TypeError, test)
def testConstantField(self):
"""Test const fields."""
object = FieldTest();
self.failUnless(FieldTest.ConstField == 0)
self.failUnless(object.ConstField == 0)
def test():
FieldTest().ConstField = 1
self.failUnlessRaises(TypeError, test)
def test():
FieldTest.ConstField = 1
self.failUnlessRaises(TypeError, test)
def test():
del FieldTest().ConstField
self.failUnlessRaises(TypeError, test)
def test():
del FieldTest.ConstField
self.failUnlessRaises(TypeError, test)
def testInternalField(self):
"""Test internal fields."""
def test():
f = FieldTest().InternalField
self.failUnlessRaises(AttributeError, test)
def test():
f = FieldTest().InternalStaticField
self.failUnlessRaises(AttributeError, test)
def test():
f = FieldTest.InternalStaticField
self.failUnlessRaises(AttributeError, test)
def testPrivateField(self):
"""Test private fields."""
def test():
f = FieldTest().PrivateField
self.failUnlessRaises(AttributeError, test)
def test():
f = FieldTest().PrivateStaticField
self.failUnlessRaises(AttributeError, test)
def test():
f = FieldTest.PrivateStaticField
self.failUnlessRaises(AttributeError, test)
def testFieldDescriptorGetSet(self):
"""Test field descriptor get / set."""
# This test ensures that setting an attribute implemented with
# a descriptor actually goes through the descriptor (rather than
# silently replacing the descriptor in the instance or type dict.
object = FieldTest()
self.failUnless(FieldTest.PublicStaticField == 0)
self.failUnless(object.PublicStaticField == 0)
descriptor = FieldTest.__dict__['PublicStaticField']
self.failUnless(type(descriptor) != types.IntType)
object.PublicStaticField = 0
descriptor = FieldTest.__dict__['PublicStaticField']
self.failUnless(type(descriptor) != types.IntType)
FieldTest.PublicStaticField = 0
descriptor = FieldTest.__dict__['PublicStaticField']
self.failUnless(type(descriptor) != types.IntType)
def testFieldDescriptorWrongType(self):
"""Test setting a field using a value of the wrong type."""
def test():
FieldTest().PublicField = "spam"
self.failUnlessRaises(TypeError, test)
def testFieldDescriptorAbuse(self):
"""Test field descriptor abuse."""
desc = FieldTest.__dict__['PublicField']
def test():
desc.__get__(0, 0)
self.failUnlessRaises(TypeError, test)
def test():
desc.__set__(0, 0)
self.failUnlessRaises(TypeError, test)
def testBooleanField(self):
"""Test boolean fields."""
# change this to true / false later for Python 2.3?
object = FieldTest()
self.failUnless(object.BooleanField == False)
object.BooleanField = True
self.failUnless(object.BooleanField == True)
object.BooleanField = False
self.failUnless(object.BooleanField == False)
object.BooleanField = 1
self.failUnless(object.BooleanField == True)
object.BooleanField = 0
self.failUnless(object.BooleanField == False)
def testSByteField(self):
"""Test sbyte fields."""
object = FieldTest()
self.failUnless(object.SByteField == 0)
object.SByteField = 1
self.failUnless(object.SByteField == 1)
def testByteField(self):
"""Test byte fields."""
object = FieldTest()
self.failUnless(object.ByteField == 0)
object.ByteField = 1
self.failUnless(object.ByteField == 1)
def testCharField(self):
"""Test char fields."""
object = FieldTest()
self.failUnless(object.CharField == u'A')
self.failUnless(object.CharField == 'A')
object.CharField = 'B'
self.failUnless(object.CharField == u'B')
self.failUnless(object.CharField == 'B')
object.CharField = u'C'
self.failUnless(object.CharField == u'C')
self.failUnless(object.CharField == 'C')
def testInt16Field(self):
"""Test int16 fields."""
object = FieldTest()
self.failUnless(object.Int16Field == 0)
object.Int16Field = 1
self.failUnless(object.Int16Field == 1)
def testInt32Field(self):
"""Test int32 fields."""
object = FieldTest()
self.failUnless(object.Int32Field == 0)
object.Int32Field = 1
self.failUnless(object.Int32Field == 1)
def testInt64Field(self):
"""Test int64 fields."""
object = FieldTest()
self.failUnless(object.Int64Field == 0)
object.Int64Field = 1
self.failUnless(object.Int64Field == 1)
def testUInt16Field(self):
"""Test uint16 fields."""
object = FieldTest()
self.failUnless(object.UInt16Field == 0)
object.UInt16Field = 1
self.failUnless(object.UInt16Field == 1)
def testUInt32Field(self):
"""Test uint32 fields."""
object = FieldTest()
self.failUnless(object.UInt32Field == 0)
object.UInt32Field = 1
self.failUnless(object.UInt32Field == 1)
def testUInt64Field(self):
"""Test uint64 fields."""
object = FieldTest()
self.failUnless(object.UInt64Field == 0)
object.UInt64Field = 1
self.failUnless(object.UInt64Field == 1)
def testSingleField(self):
"""Test single fields."""
object = FieldTest()
self.failUnless(object.SingleField == 0.0)
object.SingleField = 1.1
self.failUnless(object.SingleField == 1.1)
def testDoubleField(self):
"""Test double fields."""
object = FieldTest()
self.failUnless(object.DoubleField == 0.0)
object.DoubleField = 1.1
self.failUnless(object.DoubleField == 1.1)
def testDecimalField(self):
"""Test decimal fields."""
object = FieldTest()
self.failUnless(object.DecimalField == System.Decimal(0))
object.DecimalField = System.Decimal(1)
self.failUnless(object.DecimalField == System.Decimal(1))
def testStringField(self):
"""Test string fields."""
object = FieldTest()
self.failUnless(object.StringField == "spam")
object.StringField = "eggs"
self.failUnless(object.StringField == "eggs")
def testInterfaceField(self):
"""Test interface fields."""
from CLR.Python.Test import Spam, ISpam
object = FieldTest()
self.failUnless(ISpam(object.SpamField).GetValue() == "spam")
self.failUnless(object.SpamField.GetValue() == "spam")
object.SpamField = Spam("eggs")
self.failUnless(ISpam(object.SpamField).GetValue() == "eggs")
self.failUnless(object.SpamField.GetValue() == "eggs")
def testObjectField(self):
"""Test object fields."""
object = FieldTest()
self.failUnless(object.ObjectField == None)
object.ObjectField = System.String("spam")
self.failUnless(object.ObjectField == "spam")
object.ObjectField = System.Int32(1)
self.failUnless(object.ObjectField == 1)
object.ObjectField = None
self.failUnless(object.ObjectField == None)
def testEnumField(self):
"""Test enum fields."""
object = FieldTest()
self.failUnless(object.EnumField == ShortEnum.Zero)
object.EnumField = ShortEnum.One
self.failUnless(object.EnumField == ShortEnum.One)
def testNullableField(self):
"""Test nullable fields."""
object = FieldTest()
object.StringField = None
self.failUnless(object.StringField == None)
object.ObjectField = None
self.failUnless(object.ObjectField == None)
object.SpamField = None
self.failUnless(object.SpamField == None)
# Primitive types and enums should not be set to null.
def test():
FieldTest().Int32Field = None
self.failUnlessRaises(TypeError, test)
def test():
FieldTest().EnumField = None
self.failUnlessRaises(TypeError, test)
def test_suite():
return unittest.makeSuite(FieldTests)
def main():
unittest.TextTestRunner().run(test_suite())
if __name__ == '__main__':
testcase.setup()
main()

Просмотреть файл

@ -0,0 +1,707 @@
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
#
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
import sys, os, string, unittest, types
import CLR.Python.Test as Test
class IndexerTests(unittest.TestCase):
"""Test support for indexer properties."""
def testPublicIndexer(self):
"""Test public indexers."""
object = Test.PublicIndexerTest()
object[0] = "zero"
self.failUnless(object[0] == "zero")
object[1] = "one"
self.failUnless(object[1] == "one")
self.failUnless(object[10] == None)
def testProtectedIndexer(self):
"""Test protected indexers."""
object = Test.ProtectedIndexerTest()
object[0] = "zero"
self.failUnless(object[0] == "zero")
object[1] = "one"
self.failUnless(object[1] == "one")
self.failUnless(object[10] == None)
def testInternalIndexer(self):
"""Test internal indexers."""
object = Test.InternalIndexerTest()
def test():
object[0] = "zero"
self.failUnlessRaises(TypeError, test)
def test():
Test.InternalIndexerTest.__getitem__(object, 0)
self.failUnlessRaises(TypeError, test)
def test():
object.__getitem__(0)
self.failUnlessRaises(TypeError, test)
def testPrivateIndexer(self):
"""Test private indexers."""
object = Test.PrivateIndexerTest()
def test():
object[0] = "zero"
self.failUnlessRaises(TypeError, test)
def test():
Test.PrivateIndexerTest.__getitem__(object, 0)
self.failUnlessRaises(TypeError, test)
def test():
object.__getitem__(0)
self.failUnlessRaises(TypeError, test)
def testBooleanIndexer(self):
"""Test boolean indexers."""
object = Test.BooleanIndexerTest()
self.failUnless(object[True] == None)
self.failUnless(object[1] == None)
object[0] = "false"
self.failUnless(object[0] == "false")
object[1] = "true"
self.failUnless(object[1] == "true")
object[False] = "false"
self.failUnless(object[False] == "false")
object[True] = "true"
self.failUnless(object[True] == "true")
def testByteIndexer(self):
"""Test byte indexers."""
object = Test.ByteIndexerTest()
max = 255
min = 0
self.failUnless(object[max] == None)
object[max] = str(max)
self.failUnless(object[max] == str(max))
object[min] = str(min)
self.failUnless(object[min] == str(min))
def test():
object = Test.ByteIndexerTest()
object["wrong"]
self.failUnlessRaises(TypeError, test)
def test():
object = Test.ByteIndexerTest()
object["wrong"] = "wrong"
self.failUnlessRaises(TypeError, test)
def testSByteIndexer(self):
"""Test sbyte indexers."""
object = Test.SByteIndexerTest()
max = 127
min = -128
self.failUnless(object[max] == None)
object[max] = str(max)
self.failUnless(object[max] == str(max))
object[min] = str(min)
self.failUnless(object[min] == str(min))
def test():
object = Test.SByteIndexerTest()
object["wrong"]
self.failUnlessRaises(TypeError, test)
def test():
object = Test.SByteIndexerTest()
object["wrong"] = "wrong"
self.failUnlessRaises(TypeError, test)
def testCharIndexer(self):
"""Test char indexers."""
object = Test.CharIndexerTest()
max = unichr(65535)
min = unichr(0)
self.failUnless(object[max] == None)
object[max] = "max"
self.failUnless(object[max] == "max")
object[min] = "min"
self.failUnless(object[min] == "min")
def test():
object = Test.CharIndexerTest()
object["wrong"]
self.failUnlessRaises(TypeError, test)
def test():
object = Test.CharIndexerTest()
object["wrong"] = "wrong"
self.failUnlessRaises(TypeError, test)
def testInt16Indexer(self):
"""Test Int16 indexers."""
object = Test.Int16IndexerTest()
max = 32767
min = -32768
self.failUnless(object[max] == None)
object[max] = str(max)
self.failUnless(object[max] == str(max))
object[min] = str(min)
self.failUnless(object[min] == str(min))
def test():
object = Test.Int16IndexerTest()
object["wrong"]
self.failUnlessRaises(TypeError, test)
def test():
object = Test.Int16IndexerTest()
object["wrong"] = "wrong"
self.failUnlessRaises(TypeError, test)
def testInt32Indexer(self):
"""Test Int32 indexers."""
object = Test.Int32IndexerTest()
max = 2147483647
min = -2147483648
self.failUnless(object[max] == None)
object[max] = str(max)
self.failUnless(object[max] == str(max))
object[min] = str(min)
self.failUnless(object[min] == str(min))
def test():
object = Test.Int32IndexerTest()
object["wrong"]
self.failUnlessRaises(TypeError, test)
def test():
object = Test.Int32IndexerTest()
object["wrong"] = "wrong"
self.failUnlessRaises(TypeError, test)
def testInt64Indexer(self):
"""Test Int64 indexers."""
object = Test.Int64IndexerTest()
max = 9223372036854775807L
min = -9223372036854775808L
self.failUnless(object[max] == None)
object[max] = str(max)
self.failUnless(object[max] == str(max))
object[min] = str(min)
self.failUnless(object[min] == str(min))
def test():
object = Test.Int64IndexerTest()
object["wrong"]
self.failUnlessRaises(TypeError, test)
def test():
object = Test.Int64IndexerTest()
object["wrong"] = "wrong"
self.failUnlessRaises(TypeError, test)
def testUInt16Indexer(self):
"""Test UInt16 indexers."""
object = Test.UInt16IndexerTest()
max = 65535
min = 0
self.failUnless(object[max] == None)
object[max] = str(max)
self.failUnless(object[max] == str(max))
object[min] = str(min)
self.failUnless(object[min] == str(min))
def test():
object = Test.UInt16IndexerTest()
object["wrong"]
self.failUnlessRaises(TypeError, test)
def test():
object = Test.UInt16IndexerTest()
object["wrong"] = "wrong"
self.failUnlessRaises(TypeError, test)
def testUInt32Indexer(self):
"""Test UInt32 indexers."""
object = Test.UInt32IndexerTest()
max = 4294967295L
min = 0
self.failUnless(object[max] == None)
object[max] = str(max)
self.failUnless(object[max] == str(max))
object[min] = str(min)
self.failUnless(object[min] == str(min))
def test():
object = Test.UInt32IndexerTest()
object["wrong"]
self.failUnlessRaises(TypeError, test)
def test():
object = Test.UInt32IndexerTest()
object["wrong"] = "wrong"
self.failUnlessRaises(TypeError, test)
def testUInt64Indexer(self):
"""Test UInt64 indexers."""
object = Test.UInt64IndexerTest()
max = 18446744073709551615L
min = 0
self.failUnless(object[max] == None)
object[max] = str(max)
self.failUnless(object[max] == str(max))
object[min] = str(min)
self.failUnless(object[min] == str(min))
def test():
object = Test.UInt64IndexerTest()
object["wrong"]
self.failUnlessRaises(TypeError, test)
def test():
object = Test.UInt64IndexerTest()
object["wrong"] = "wrong"
self.failUnlessRaises(TypeError, test)
def testSingleIndexer(self):
"""Test Single indexers."""
object = Test.SingleIndexerTest()
max = 3.402823e38
min = -3.402823e38
self.failUnless(object[max] == None)
object[max] = "max"
self.failUnless(object[max] == "max")
object[min] = "min"
self.failUnless(object[min] == "min")
def test():
object = Test.SingleIndexerTest()
object["wrong"]
self.failUnlessRaises(TypeError, test)
def test():
object = Test.SingleIndexerTest()
object["wrong"] = "wrong"
self.failUnlessRaises(TypeError, test)
def testDoubleIndexer(self):
"""Test Double indexers."""
object = Test.DoubleIndexerTest()
max = 1.7976931348623157e308
min = -1.7976931348623157e308
self.failUnless(object[max] == None)
object[max] = "max"
self.failUnless(object[max] == "max")
object[min] = "min"
self.failUnless(object[min] == "min")
def test():
object = Test.DoubleIndexerTest()
object["wrong"]
self.failUnlessRaises(TypeError, test)
def test():
object = Test.DoubleIndexerTest()
object["wrong"] = "wrong"
self.failUnlessRaises(TypeError, test)
def testDecimalIndexer(self):
"""Test Decimal indexers."""
object = Test.DecimalIndexerTest()
from CLR.System import Decimal
max_d = Decimal.Parse("79228162514264337593543950335")
min_d = Decimal.Parse("-79228162514264337593543950335")
self.failUnless(object[max_d] == None)
object[max_d] = "max"
self.failUnless(object[max_d] == "max")
object[min_d] = "min"
self.failUnless(object[min_d] == "min")
def test():
object = Test.DecimalIndexerTest()
object["wrong"]
self.failUnlessRaises(TypeError, test)
def test():
object = Test.DecimalIndexerTest()
object["wrong"] = "wrong"
self.failUnlessRaises(TypeError, test)
def testStringIndexer(self):
"""Test String indexers."""
object = Test.StringIndexerTest()
self.failUnless(object["spam"] == None)
self.failUnless(object[u"spam"] == None)
object["spam"] = "spam"
self.failUnless(object["spam"] == "spam")
self.failUnless(object["spam"] == u"spam")
self.failUnless(object[u"spam"] == "spam")
self.failUnless(object[u"spam"] == u"spam")
object[u"eggs"] = u"eggs"
self.failUnless(object["eggs"] == "eggs")
self.failUnless(object["eggs"] == u"eggs")
self.failUnless(object[u"eggs"] == "eggs")
self.failUnless(object[u"eggs"] == u"eggs")
def test():
object = Test.StringIndexerTest()
object[1]
self.failUnlessRaises(TypeError, test)
def test():
object = Test.StringIndexerTest()
object[1] = "wrong"
self.failUnlessRaises(TypeError, test)
def testEnumIndexer(self):
"""Test enum indexers."""
object = Test.EnumIndexerTest()
key = Test.ShortEnum.One
self.failUnless(object[key] == None)
object[key] = "spam"
self.failUnless(object[key] == "spam")
object[key] = "eggs"
self.failUnless(object[key] == "eggs")
object[1] = "spam"
self.failUnless(object[1] == "spam")
def test():
object = Test.EnumIndexerTest()
object["wrong"]
self.failUnlessRaises(TypeError, test)
def test():
object = Test.EnumIndexerTest()
object["wrong"] = "wrong"
self.failUnlessRaises(TypeError, test)
def testObjectIndexer(self):
"""Test object indexers."""
object = Test.ObjectIndexerTest()
from CLR.Python.Test import Spam
spam = Spam("spam")
self.failUnless(object[spam] == None)
self.failUnless(object["spam"] == None)
self.failUnless(object[1] == None)
self.failUnless(object[None] == None)
object[spam] = "spam"
self.failUnless(object[spam] == "spam")
object["spam"] = "eggs"
self.failUnless(object["spam"] == "eggs")
object[1] = "one"
self.failUnless(object[1] == "one")
object[1L] = "long"
self.failUnless(object[1L] == "long")
def test():
class eggs:
pass
key = eggs()
object = Test.ObjectIndexerTest()
object[key] = "wrong"
self.failUnlessRaises(TypeError, test)
def testInterfaceIndexer(self):
"""Test interface indexers."""
object = Test.InterfaceIndexerTest()
from CLR.Python.Test import Spam
spam = Spam("spam")
self.failUnless(object[spam] == None)
object[spam] = "spam"
self.failUnless(object[spam] == "spam")
object[spam] = "eggs"
self.failUnless(object[spam] == "eggs")
def test():
object = Test.InterfaceIndexerTest()
object["wrong"]
self.failUnlessRaises(TypeError, test)
def test():
object = Test.InterfaceIndexerTest()
object["wrong"] = "wrong"
self.failUnlessRaises(TypeError, test)
def testTypedIndexer(self):
"""Test typed indexers."""
object = Test.TypedIndexerTest()
from CLR.Python.Test import Spam
spam = Spam("spam")
self.failUnless(object[spam] == None)
object[spam] = "spam"
self.failUnless(object[spam] == "spam")
object[spam] = "eggs"
self.failUnless(object[spam] == "eggs")
def test():
object = Test.TypedIndexerTest()
object["wrong"]
self.failUnlessRaises(TypeError, test)
def test():
object = Test.TypedIndexerTest()
object["wrong"] = "wrong"
self.failUnlessRaises(TypeError, test)
def testMultiArgIndexer(self):
"""Test indexers that take multiple index arguments."""
object = Test.MultiArgIndexerTest()
object[0, 1] = "zero one"
self.failUnless(object[0, 1] == "zero one")
object[1, 9] = "one nine"
self.failUnless(object[1, 9] == "one nine")
self.failUnless(object[10, 50] == None)
def test():
object = Test.MultiArgIndexerTest()
v = object[0, "one"]
self.failUnlessRaises(TypeError, test)
def test():
object = Test.MultiArgIndexerTest()
object[0, "one"] = "wrong"
self.failUnlessRaises(TypeError, test)
def testMultiTypeIndexer(self):
"""Test indexers that take multiple indices of different types."""
object = Test.MultiTypeIndexerTest()
spam = Test.Spam("spam")
object[0, "one", spam] = "zero one spam"
self.failUnless(object[0, "one", spam] == "zero one spam")
object[1, "nine", spam] = "one nine spam"
self.failUnless(object[1, "nine", spam] == "one nine spam")
def test():
object = Test.MultiTypeIndexerTest()
v = object[0, 1, spam]
self.failUnlessRaises(TypeError, test)
def test():
object = Test.MultiTypeIndexerTest()
object[0, 1, spam] = "wrong"
self.failUnlessRaises(TypeError, test)
def testIndexerWrongKeyType(self):
"""Test calling an indexer using a key of the wrong type."""
def test():
object = Test.PublicIndexerTest()
v = object["wrong"]
self.failUnlessRaises(TypeError, test)
def test():
object = Test.PublicIndexerTest()
object["wrong"] = "spam"
self.failUnlessRaises(TypeError, test)
def testIndexerWrongValueType(self):
"""Test calling an indexer using a value of the wrong type."""
def test():
object = Test.PublicIndexerTest()
object[1] = 9993.9
self.failUnlessRaises(TypeError, test)
def testUnboundIndexer(self):
"""Test calling an unbound indexer."""
object = Test.PublicIndexerTest()
Test.PublicIndexerTest.__setitem__(object, 0, "zero")
self.failUnless(object[0] == "zero")
Test.PublicIndexerTest.__setitem__(object, 1, "one")
self.failUnless(object[1] == "one")
self.failUnless(object[10] == None)
def testIndexerAbuse(self):
"""Test indexer abuse."""
_class = Test.PublicIndexerTest
object = Test.PublicIndexerTest()
def test():
del _class.__getitem__
self.failUnlessRaises(AttributeError, test)
def test():
del object.__getitem__
self.failUnlessRaises(AttributeError, test)
def test():
del _class.__setitem__
self.failUnlessRaises(AttributeError, test)
def test():
del object.__setitem__
self.failUnlessRaises(AttributeError, test)
def test_suite():
return unittest.makeSuite(IndexerTests)
def main():
unittest.TextTestRunner().run(test_suite())
if __name__ == '__main__':
testcase.setup()
main()

Просмотреть файл

@ -0,0 +1,93 @@
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
#
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
from CLR.Python.Test import InterfaceTest
import sys, os, string, unittest, types
import CLR.System as System
import CLR.Python.Test as Test
class InterfaceTests(unittest.TestCase):
"""Test CLR interface support."""
def testInterfaceStandardAttrs(self):
"""Test standard class attributes."""
from CLR.Python.Test import IPublicInterface as ip
self.failUnless(ip.__name__ == 'IPublicInterface')
self.failUnless(ip.__module__ == 'CLR.Python.Test')
self.failUnless(type(ip.__dict__) == types.DictProxyType)
def testGlobalInterfaceVisibility(self):
"""Test visibility of module-level interfaces."""
from CLR.Python.Test import IPublicInterface
self.failUnless(IPublicInterface.__name__ == 'IPublicInterface')
def test():
from CLR.Python.Test import IInternalInterface
self.failUnlessRaises(ImportError, test)
def test():
i = Test.IInternalInterface
self.failUnlessRaises(AttributeError, test)
def testNestedInterfaceVisibility(self):
"""Test visibility of nested interfaces."""
ob = InterfaceTest.IPublic
self.failUnless(ob.__name__ == 'IPublic')
ob = InterfaceTest.IProtected
self.failUnless(ob.__name__ == 'IProtected')
def test():
ob = InterfaceTest.IInternal
self.failUnlessRaises(AttributeError, test)
def test():
ob = InterfaceTest.IPrivate
self.failUnlessRaises(AttributeError, test)
def testExplicitCastToInterface(self):
"""Test explicit cast to an interface."""
ob = InterfaceTest()
self.failUnless(type(ob).__name__ == 'InterfaceTest')
self.failUnless(hasattr(ob, 'HelloProperty'))
i1 = Test.ISayHello1(ob)
self.failUnless(type(i1).__name__ == 'ISayHello1')
self.failUnless(hasattr(i1, 'SayHello'))
self.failUnless(i1.SayHello() == 'hello 1')
self.failIf(hasattr(i1, 'HelloProperty'))
i2 = Test.ISayHello2(ob)
self.failUnless(type(i2).__name__ == 'ISayHello2')
self.failUnless(i2.SayHello() == 'hello 2')
self.failUnless(hasattr(i2, 'SayHello'))
self.failIf(hasattr(i2, 'HelloProperty'))
def test_suite():
return unittest.makeSuite(InterfaceTests)
def main():
unittest.TextTestRunner().run(test_suite())
if __name__ == '__main__':
testcase.setup()
main()

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше