diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..ff0b3c71d --- /dev/null +++ b/.editorconfig @@ -0,0 +1,24 @@ +# EditorConfig is awesome: http://EditorConfig.org + +# top-most EditorConfig file +root = true + +[*] +charset = utf-8 +indent_size = 4 +end_of_line = lf +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +# config files +[*.{ini,yaml,yml}] +indent_size = 2 + +# Xml project files +[*.{csproj,config,build,config}] +indent_size = 2 + +# Solution +[*.sln] +indent_style = tab diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 000000000..2758080dc --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,25 @@ +### Environment + +- Pythonnet version: +- Python version: +- Operating System: + +### Details + +- Describe what you were trying to get done. + + _TODO_ + +- What commands did you run to trigger this issue? If you can provide a + [Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve) + this will help us understand the issue. + +```python + print('TODO') +``` + +- If there was a crash, please include the traceback here. + +```python + print('TODO') +``` diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..8b030e040 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,20 @@ +### What does this implement/fix? Explain your changes. + +... + +### Does this close any currently open issues? + +... + +### Any other comments? + +... + +### Checklist + +Check all those that are applicable and complete. + +- [ ] Make sure to include one or more tests for your change +- [ ] If an enhancement PR, please create docs and at best an example +- [ ] Add yourself to [`AUTHORS`](../blob/master/AUTHORS.md) +- [ ] Updated the [`CHANGELOG`](../blob/master/CHANGELOG.md) diff --git a/.gitignore b/.gitignore index 8f598f0df..968a5c66a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,56 @@ -*.suo -*.pdb -[Oo]bj/ -[Bb]in/ +# General binaries and Build results *.dll -*.pyd *.exe -*.pyc -packages/* -dist -pythonnet.egg-info +*.pdb + +### JetBrains ### +.idea/ + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] + +# Distribution / packaging +build/ +dist/ +*.egg-info/ + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +coverage.xml + +### CSharp ### +# User-specific files +*.suo +*.user +*.vcxproj.filters *.userprefs +*.DotSettings.user + +# Build results +[Bb]in/ +[Oo]bj/ + +# Visual Studio cache/options directory +.vs/ + +# NUNIT +*.VisualState.xml +TestResult.xml + +# OpenCover +/results.xml + +# NuGet Packages +**/packages/* + +# VS Project upgrade log files +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm diff --git a/.travis.yml b/.travis.yml index 06b150a0e..b24531f93 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,13 @@ sudo: required language: python + python: - - 2.6 - 2.7 - - 3.2 + - 3.3 - 3.4 - 3.5 + - 3.6 + before_install: - sudo add-apt-repository -y "deb http://archive.ubuntu.com/ubuntu/ trusty main universe" - sudo apt-get install software-properties-common @@ -19,6 +21,11 @@ install: - pip install six - pip install pycparser - python setup.py build_ext --inplace + script: - export PYTHONPATH=`pwd`:$PYTHONPATH - python src/tests/runtests.py + # - nunit-console src/embed_tests/bin/x64/ReleaseMono/Python.EmbeddingTest.dll + +notifications: + email: false diff --git a/AUTHORS.md b/AUTHORS.md new file mode 100644 index 000000000..2a2110f26 --- /dev/null +++ b/AUTHORS.md @@ -0,0 +1,41 @@ +# Credits + +## Development Lead + +- Barton Cline ([@BartonCline](https://github.com/BartonCline)) +- Benedikt Reinartz ([@filmor](https://github.com/filmor)) +- Brian Lloyd ([@brianlloyd](https://github.com/brianlloyd)) +- David Anthoff ([@davidanthoff](https://github.com/davidanthoff)) +- Denis Akhiyarov ([@denfromufa](https://github.com/denfromufa)) +- Tony Roberts ([@tonyroberts](https://github.com/tonyroberts)) +- Victor Uriarte ([@vmuriart](https://github.com/vmuriart)) + +## Contributors + +- Bradley Friedman ([@leith-bartrich](https://github.com/leith-bartrich)) +- Christian Heimes ([@tiran](https://github.com/tiran)) +- Christoph Gohlke ([@cgohlke](https://github.com/cgohlke)) +- Daniel Santana ([@dgsantana](https://github.com/dgsantana)) +- David Lechner ([@dlech](https://github.com/dlech)) +- He-chien Tsai ([@t3476](https://github.com/t3476)) +- Jeff Reback ([@jreback](https://github.com/jreback)) +- Joe Frayne ([@jfrayne](https://github.com/jfrayne)) +- John Burnett ([@johnburnett](https://github.com/johnburnett)) +- Luke Stratman ([@lstratman](https://github.com/lstratman)) +- Matthias Dittrich ([@matthid](https://github.com/matthid)) +- Patrick Stewart ([@patstew](https://github.com/patstew)) +- Raphael Nestler ([@rnestler](https://github.com/rnestler)) +- Sam Winstanley ([@swinstanley](https://github.com/swinstanley)) +- Sean Freitag ([@cowboygneox](https://github.com/cowboygneox)) +- Serge Weinstock ([@sweinst](https://github.com/sweinst)) +- Virgil Dupras ([@hsoft](https://github.com/hsoft)) +- Xavier Dupré ([@sdpython](https://github.com/sdpython)) +- Zane Purvis ([@zanedp](https://github.com/zanedp)) +- ([@ArvidJB](https://github.com/ArvidJB)) +- ([@bltribble](https://github.com/bltribble)) +- ([@dmitriyse](https://github.com/dmitriyse)) +- ([@fdanny](https://github.com/fdanny)) +- ([@omnicognate](https://github.com/omnicognate)) +- ([@rico-chet](https://github.com/rico-chet)) +- ([@rmadsen-ks](https://github.com/rmadsen-ks)) +- ([@stonebig](https://github.com/stonebig)) diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..7185e7c1f --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,470 @@ +# Changelog + +All notable changes to Python for .NET will be documented in this file. +This project adheres to [Semantic Versioning][]. + +This document follows the conventions laid out in [Keep a CHANGELOG][]. + +## [2.2.1][] - 2017-01-26 + +`v2.2.0` had a release issue on pypi. Bumped to `v2.2.1` + +### Added + +- Python 3.6 support (#310) +- Added `__version__` to module (#312) +- Added `conda` recipe (#281) +- Nuget update on build (#268) +- Added `__cause__` attribute on exception (#287) + +### Changed + +- License to MIT (#314) +- Project clean-up (#320) +- Refactor `#if` directives +- Rename Decref/Incref to XDecref/XIncre (#275) +- Remove printing if Decref is called with NULL (#275) + +### Removed + +- Python 3.2 support +- Python 3.3 support + +### Fixed + +- Fixed `isinstance` refcount_leak (#273) + +## [2.2.0-dev1][] - 2016-09-19 + +- Switch to C# 6.0 (#219) +- Relative imports (#219) +- Recursive types (#250) +- Demo fix - stream reading (#225) +- setup.py improvements for locating build tools (#208) +- unmanaged exports updated (#206) +- Mono update pinned to 4.2.4.4 (#233) + +## [2.1.0][] - 2016-04-12 + +### Added + +- Added Python 3.x support. + +### Removed + +- Implicit Type Casting. + +## [2.0.0][] - 2015-06-26 + + Release + +## 2.0.0-alpha.2 + +### Changed + +- First work on Python 2.5 compatibility. The destination version can be + set by defining PYTHON24 or PYTHON25. Python 2.6 compatibility is in + work. + +- Added VS 2005 solution and project files including a UnitTest + configuration which runs the unit test suite. + +- Enhanced unit test suite. All test cases are combined in a single + test suite now. + +- Fixed bugs in generics support for all Python versions. + +- Fixed exception bugs for Python 2.5+. When compiled for Python 2.5+ all + managed exceptions are based on Python's `exceptions.Exception` class. + +- Added deprecation warnings for importing from `CLR.*` and the CLR module. + +- Implemented support for methods with variable arguments + `spam(params object[] egg)` + +- Fixed Mono support by adding a custom marshaler for UCS-4 unicode, + fixing a some ref counter bugs and creating a new makefile.mono. + +- Added a standard python extension to load the clr environment. + The `src/monoclr/` directory contains additional sample code like a + Python binary linked against `libpython2.x.so` and some example code + how to embed Mono and PythonNet in a C application. + +- Added yet another python prompt. This time it's a C application that + embedds both Python and Mono. It may be useful as an example app for + others and I need it to debug a nasty bug. + +- Implemented `ModuleFunctionAttribute` and added + `ForbidPythonThreadsAttribute`. The latter is required for module + functions which invoke Python methods. + +- Added `clr.setPreload()`, `clr.getPreload()`, + `clr.AddReference("assembly name")`, `clr.FindAssembly("name")` + and `clr.ListAssemblies(verbose)`. Automatic preloading can be enabled + with clr.setPreload/True). Preloading is automatically enabled for + interactive Python shells and disabled in all other cases. + +- New Makefile that works for Windows and Mono and autodetects the Python + version and UCS 2/4 setting. + +- Added code for Python 2.3. PythonNet can be build for Python 2.3 again + but it is not fully supported. + +- Changed the PythonException.Message value so it displays the name of + the exception class `Exception` instead of its representation + ``. + +- Added `Python.Runtime.dll.config`. + +## 2.0.0-alpha.1 + +### Changed + +- Moved the Python for .NET project to Sourceforge and moved version + control to Subversion. + +- Removed `CallConvCdecl` attributes and the IL hack that they supported. + .NET 2.x now supports `UnmanagedFunctionPointer`, which does the right + thing without the hackery required in 1.x. This removes a dependency + on ILASM to build the package and better supports Mono (in theory). + +- Refactored import and assembly management machinery. The old `CLR.` + syntax for import is deprecated, but still supported until 3.x. The + recommended style now is to use `from System import xxx`, etc. We + also now support `from X import *` correctly. + +- Implemented a (lowercase) `clr` module to match IronPython for code + compatibility. Methods of this module should be used to explicitly + load assemblies. Implicit (name-based) assembly loading will still + work until 3.x, but it is deprecated. + +- Implemented support for generic types and generic methods using the + same patterns and syntax as IronPython. See the documentation for + usage details. + +- Many small and large performance improvements, switched to generic + collections for some internals, better algorithms for assembly + scanning, etc. + +- Fixed an unboxing issue in generated delegate implementation code + that affected delegates that return value types. + +## [1.0.0][] - 2006-04-08 + +### Changed + +- Backported the refactored import and assembly management from the 2.x + line, mainly to improve the possibility of code-compatibility with + IronPython. + +## 1.0.0-rc.2 + +### Changed + +- 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). + +## 1.0.0-rc.1 + +### Changed + +- 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. + +## 1.0.0-beta.5 + +### Changed + +- 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. + +## 1.0.0-beta.4 + +### Changed + +- 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. + +## 1.0.0-beta.3 + +### Changed + +- 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. + +## 1.0.0-beta.2 + +### Changed + +- 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. + +## 1.0.0-beta.1 + +### Changed + +- 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. + +## 1.0.0-alpha.2 + +### Changed + +- 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! :) + +## 1.0.0-alpha.1 + +### Added + +- Initial (mostly) working experimental release. + +[keep a changelog]: http://keepachangelog.com/ + +[semantic versioning]: http://semver.org/ + +[unreleased]: ../../compare/v2.2.1...HEAD + +[2.2.1]: ../../compare/v2.2.0-dev1...v2.2.1 + +[2.2.0-dev1]: ../../compare/v2.1.0...v2.2.0-dev1 + +[2.1.0]: ../../compare/v2.0.0...v2.1.0 + +[2.0.0]: ../../compare/1.0...v2.0.0 + +[1.0.0]: https://github.com/pythonnet/pythonnet/releases/tag/1.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 671c0bc48..ea0f3408e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,38 +3,41 @@ PythonNet is developed and maintained by unpaid community members so well written, documented and tested pull requests are encouraged. +By submitting a pull request for this project, you agree to license your +contribution under the MIT license to this project. + ## Getting Started -* Make sure you have a [GitHub account](https://github.com/signup/free) -* Submit a ticket for your issue, assuming one does not already exist. - * Clearly describe the issue including steps to reproduce when it is a bug. - * Make sure you include what Python version and operating system you are using. -* Fork the repository on GitHub +- Make sure you have a [GitHub account](https://github.com/signup/free) +- Submit a ticket for your issue, assuming one does not already exist. + - Clearly describe the issue including steps to reproduce the bug. + - Include what Python version and operating system you are using. +- Fork the repository on GitHub ## Making Changes -* Create a topic branch from where you want to base your work. - * This is usually the master branch. - * Only target release branches if you are certain your fix must be on that - branch. - * To quickly create a topic branch based on master; `git checkout -b - fix/develop/my_contribution master`. Please avoid working directly on the - `master` branch for anything other than trivial changes. -* Make commits of logical units. -* Check for unnecessary whitespace with `git diff --check` before committing. -* Make sure your commit messages are in the proper format. -* Make sure you have added the necessary tests for your changes. -* Run _all_ the tests to assure nothing else was accidentally broken. - +- Create a topic branch from where you want to base your work. + - This is usually the master branch. + - Only target release branches if you are certain your fix must be on + that branch. + - To quickly create a topic branch based on master; + `git checkout -b fix/develop/my_contribution master`. + Please avoid working directly on the `master` branch for anything + other than trivial changes. +- Make commits of logical units. +- Check for unnecessary whitespace with `git diff --check` before committing. +- Make sure your commit messages are in the proper format. +- Make sure you have added the necessary tests for your changes. +- Run _all_ the tests to assure nothing else was accidentally broken. ## Submitting Changes -* Merge your topic branch into master and push to your fork of the repository. -* Submit a pull request to the repository in the pythonnet organization. -* After feedback has been given we expect responses within two weeks. After two - weeks we may close the pull request if it isn't showing any activity. +- Merge the topic branch into master and push to your fork of the repository. +- Submit a pull request to the repository in the pythonnet organization. +- After feedback has been given we expect responses within two weeks. After + two weeks we may close the pull request if it isn't showing any activity. # Additional Resources -* [General GitHub documentation](https://help.github.com/) -* [GitHub pull request documentation](https://help.github.com/send-pull-requests/) +- [General GitHub documentation](https://help.github.com/) +- [GitHub pull request documentation](https://help.github.com/send-pull-requests/) diff --git a/LICENSE b/LICENSE index 44e0648b3..0535829ff 100644 --- a/LICENSE +++ b/LICENSE @@ -1,59 +1,21 @@ -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. +MIT License + +Copyright (c) 2017 the contributors of the "Python for .NET" project + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/Python.Runtime.dll.config b/Python.Runtime.dll.config index e9821a8a9..228c1417a 100644 --- a/Python.Runtime.dll.config +++ b/Python.Runtime.dll.config @@ -9,21 +9,14 @@ For more information read: --> - - - - - - - - - + + - + + - diff --git a/README.md b/README.md index fa3c7c102..0b6abe756 100644 --- a/README.md +++ b/README.md @@ -1,65 +1,89 @@ -pythonnet -========= +# pythonnet - Python for .NET -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. It allows Python code to interact with the CLR, and may also be used to embed Python into a .NET application. +[![appveyor shield][]](https://ci.appveyor.com/project/pythonnet/pythonnet/branch/master) +[![travis shield][]](https://travis-ci.org/pythonnet/pythonnet) +[![license shield][]](./LICENSE) +[![pypi package version][]](https://pypi.python.org/pypi/pythonnet) +[![python supported shield][]](https://pypi.python.org/pypi/pythonnet) -[![Build Status](https://travis-ci.org/pythonnet/pythonnet.png?branch=master)](https://travis-ci.org/pythonnet/pythonnet) +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. +It allows Python code to interact with the CLR, and may also be used to +embed Python into a .NET application. -[![Build status](https://ci.appveyor.com/api/projects/status/c8k0miljb3n1c7be/branch/master)](https://ci.appveyor.com/project/TonyRoberts/pythonnet-480xs) +## Calling .NET code from Python -**Calling .NET code from Python** - -Python for .NET allows CLR namespaces to be treated essentially as Python packages. +Python for .NET allows CLR namespaces to be treated essentially +as Python packages. ```python - import clr - from System import String - from System.Collections import * +import clr +from System import String +from System.Collections import * ``` -To load an assembly, use the "AddReference" function in the "clr" module: + +To load an assembly, use the `AddReference` function in the `clr` module: ```python - import clr - clr.AddReference("System.Windows.Forms") - from System.Windows.Forms import Form +import clr +clr.AddReference("System.Windows.Forms") +from System.Windows.Forms import Form ``` -**Embedding Python in .NET** +## Embedding Python in .NET + +- All calls to python should be inside + a `using (Py.GIL()) {/_ Your code here _/}` block. +- Import python modules using `dynamic mod = Py.Import("mod")`, + then you can call functions as normal, eg `mod.func(args)`. +- Use `mod.func(args, Py.kw("keywordargname", keywordargvalue))` + to apply keyword arguments. +- All python objects should be declared as `dynamic` type. +- Mathematical operations involving python and literal/managed types must + have the python object first, eg `np.pi_2` works, `2_np.pi` doesn't. -+ All calls to python should be inside a "using (Py.GIL()) {/* Your code here */}" block. -+ Import python modules using dynamic mod = Py.Import("mod"), then you can call functions as normal, eg mod.func(args). -+ Use mod.func(args, Py.kw("keywordargname", keywordargvalue)) to apply keyword arguments. -+ All python objects should be declared as 'dynamic' type. -+ Mathematical operations involving python and literal/managed types must have the python object first, eg np.pi*2 works, 2*np.pi doesn't +### Example -EG: ```csharp static void Main(string[] args) { - using (Py.GIL()) { - dynamic np = Py.Import("numpy"); - dynamic sin = np.sin; - Console.WriteLine(np.cos(np.pi*2)); - Console.WriteLine(sin(5)); - double c = np.cos(5) + sin(5); - Console.WriteLine(c); - /* this block is temporarily disabled due to regression - dynamic a = np.array(new List { 1, 2, 3 }); - dynamic b = np.array(new List { 6, 5, 4 }, Py.kw("dtype", np.int32)); - Console.WriteLine(a.dtype); - Console.WriteLine(b.dtype); - Console.WriteLine(a * b); - */ - Console.ReadKey(); - } + using (Py.GIL()) + { + dynamic np = Py.Import("numpy"); + dynamic sin = np.sin; + Console.WriteLine(np.cos(np.pi*2)); + Console.WriteLine(sin(5)); + double c = np.cos(5) + sin(5); + Console.WriteLine(c); + /* this block is temporarily disabled due to regression + dynamic a = np.array(new List { 1, 2, 3 }); + dynamic b = np.array(new List { 6, 5, 4 }, Py.kw("dtype", np.int32)); + Console.WriteLine(a.dtype); + Console.WriteLine(b.dtype); + Console.WriteLine(a * b); */ + Console.ReadKey(); + } } ``` -outputs: -``` + +Output: + +```c 1.0 -0.958924274663 -0.6752620892 float64 int32 -[ 6. 10. 12.] +[6. 10. 12.] ``` + +[appveyor shield]: https://img.shields.io/appveyor/ci/pythonnet/pythonnet/master.svg?label=AppVeyor + +[license shield]: https://img.shields.io/badge/license-MIT-blue.svg + +[pypi package version]: https://img.shields.io/pypi/v/pythonnet.svg + +[python supported shield]: https://img.shields.io/pypi/pyversions/pythonnet.svg + +[travis shield]: https://img.shields.io/travis/pythonnet/pythonnet/master.svg?label=Travis diff --git a/VS_README.txt b/VS_README.txt deleted file mode 100644 index d66cbc379..000000000 --- a/VS_README.txt +++ /dev/null @@ -1,43 +0,0 @@ -Visual Studio 2005 -================== - -pythonnet contains a new solution file for Visual Studio 2005: pythonnet.sln -It should make development under Windows much easier since you don't have to -install MSys or Cygwin to run the makefile. - -The solution file should work with the free VS .NET Express Edition. - -Available configurations ------------------------- - -Every configuration copies the dll, pdf and exe files to the root directory -of the project. - - * Release - Builds Python.Runtime, Python.Tests, clr.pyd and python.exe. The console - project starts a Python console - - * Debug - Same as Release but creates a build with debug symbols - - * UnitTest - Builds a Debug build. The console project invokes runtests.py instead of - opening a Python shell. - - * EmbeddingTest - Builds Python.EmbeddingTests and its dependencies. The configuration - requires the NUunit framework. - -Python version --------------- - -You can switch the destination version by defining either PYTHON24 or PYTHON25 -inside the Python.Runtime project. - - ** Don't forget to force a rebuild after you have altered the setting! ** - -MS VS doesn't take changes to define into account. - -Thanks to Virgil Duprasfor his original VS howto! - -Christian 'Tiran' Heimes diff --git a/appveyor.yml b/appveyor.yml index 02807b816..5f6a0a842 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,34 +1,64 @@ -os: Windows Server 2012 +version: 2.2.1-build{build} + +platform: + - x86 + - x64 environment: global: - PYTHONPATH: c:\testdir - PYTHONWARNINGS: 'ignore:::pip.pep425tags:' + PYTHONPATH: "C:\\testdir" + PYTHONWARNINGS: "ignore:::wheel.pep425tags:" + CONDA_BLD_VERSION: "3.5" + CONDA_BLD: "C:\\conda" + NUNIT: "nunit-console" + + # SDK v7.0 MSVC Express 2008's SetEnv.cmd script will fail if the + # /E:ON and /V:ON options are not enabled in the batch script interpreter + # See: http://stackoverflow.com/a/13751649/163740 + CMD_IN_ENV: "cmd /E:ON /V:ON /C .\\ci\\run_with_env.cmd" matrix: - # http://www.appveyor.com/docs/installed-software#python - - PYTHON: "C:\\Python27" - - PYTHON: "C:\\Python27-x64" - - PYTHON: "C:\\Python33" - - PYTHON: "C:\\Python33-x64" - - PYTHON: "C:\\Python34" - - PYTHON: "C:\\Python34-x64" - - PYTHON: "C:\\Python35" - - PYTHON: "C:\\Python35-x64" + - PYTHON_VERSION: "2.7" + - PYTHON_VERSION: "3.3" + - PYTHON_VERSION: "3.4" + - PYTHON_VERSION: "3.5" + - PYTHON_VERSION: "3.6" + +init: + # Prepare environment + - mkdir C:\testdir + + # Set environment variables depending based on build cfg + - SET CONDA_PY=%PYTHON_VERSION:.=% + - SET CONDA_BLD_ARCH=%PLATFORM:x=% + - SET PYTHON=C:\PYTHON%CONDA_PY% + - IF %PLATFORM%==x86 (SET CONDA_BLD_ARCH=32) + - IF %PLATFORM%==x86 (SET NUNIT=%NUNIT%-x86) + - IF %PLATFORM%==x64 (SET PYTHON=%PYTHON%-x64) install: -- "%PYTHON%\\python.exe -m pip install --upgrade pip" -- "%PYTHON%\\python.exe -m pip install wheel" -- "%PYTHON%\\python.exe -m pip install six" + # install conda and deps + - ps: .\ci\install_miniconda.ps1 + + # install for wheels + - "%PYTHON%\\python.exe -m pip install --upgrade pip" + - "%PYTHON%\\python.exe -m pip install wheel" + - "%PYTHON%\\python.exe -m pip install six" build_script: -- "%PYTHON%\\python.exe setup.py bdist_wheel" + # build clean sdist & wheel + - "%PYTHON%\\python.exe setup.py sdist bdist_wheel" + + # build and dist conda package + - cmd: "%CMD_IN_ENV% %CONDA_BLD%\\Scripts\\conda build conda.recipe" + - ps: $CONDA_PKG=(& "$env:CONDA_BLD\\Scripts\\conda" build conda.recipe --output -q) + - ps: copy-item $CONDA_PKG "$env:APPVEYOR_BUILD_FOLDER\\dist\\" test_script: - - ps: '& "$env:PYTHON\\Scripts\\pip.exe" install --no-cache-dir --force-reinstall --ignore-installed ("dist\\" + (gci dist)[0].Name)' - - mkdir c:\testdir - - ps: copy-item (gci -path build -re -include Python.Test.dll)[0].FullName c:\testdir + - ps: '& "$env:PYTHON\\Scripts\\pip.exe" install --no-cache-dir --force-reinstall --ignore-installed ("dist\\" + (gci dist\*.whl)[0].Name)' + - ps: copy-item (gci -path build -re -include Python.Test.dll)[0].FullName C:\testdir - "%PYTHON%\\python.exe src\\tests\\runtests.py" + # - "%NUNIT% src/embed_tests/bin/%PLATFORM%/ReleaseWin/Python.EmbeddingTest.dll" artifacts: # bdist_wheel puts your built wheel in the dist directory diff --git a/ci/install_miniconda.ps1 b/ci/install_miniconda.ps1 new file mode 100644 index 000000000..5c87ca894 --- /dev/null +++ b/ci/install_miniconda.ps1 @@ -0,0 +1,95 @@ +# Sample script to install Miniconda under Windows +# Authors: Olivier Grisel, Jonathan Helmus and Kyle Kastner, Robert McGibbon +# License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/ + +$MINICONDA_URL = "http://repo.continuum.io/miniconda/" + + +function DownloadMiniconda($python_version, $platform_suffix) { + $webclient = New-Object System.Net.WebClient + $filename = "Miniconda3-latest-Windows-" + $platform_suffix + ".exe" + $url = $MINICONDA_URL + $filename + + $basedir = $pwd.Path + "\" + $filepath = $basedir + $filename + if (Test-Path $filename) { + Write-Host "Reusing" $filepath + return $filepath + } + + # Download and retry up to 3 times in case of network transient errors. + Write-Host "Downloading" $filename "from" $url + $retry_attempts = 2 + for ($i=0; $i -lt $retry_attempts; $i++) { + try { + $webclient.DownloadFile($url, $filepath) + break + } + catch [Exception] { + Start-Sleep 1 + } + } + + if (Test-Path $filepath) { + Write-Host "File saved at" $filepath + } else { + # Retry once to get the error message if any at the last try + $webclient.DownloadFile($url, $filepath) + } + return $filepath +} + + +function InstallMiniconda($python_version, $architecture, $python_home) { + Write-Host "Installing Python $python_version $architecture bit to $python_home" + if (Test-Path $python_home) { + Write-Host "$python_home already exists, skipping." + } + if ($architecture -match "32") { + $platform_suffix = "x86" + } else { + $platform_suffix = "x86_64" + } + + $filepath = DownloadMiniconda $python_version $platform_suffix + Write-Host "Installing $filepath to $python_home" + $install_log = $python_home + ".log" + $args = "/S /D=$python_home" + Write-Host $filepath $args + Start-Process -FilePath $filepath -ArgumentList $args -Wait -Passthru + if (Test-Path $python_home) { + Write-Host "Python $python_version $architecture bit installation complete" + } else { + Write-Host "Failed to install Python in $python_home" + Get-Content -Path $install_log + Exit 1 + } +} + + +function InstallCondaPackages($python_home, $spec) { + $conda_path = $python_home + "\Scripts\conda.exe" + $args = "install --yes " + $spec + Write-Host ("conda " + $args) -ForegroundColor "Green" + Start-Process -FilePath "$conda_path" -ArgumentList $args -Wait -Passthru +} + + +function UpdateConda($python_home) { + $conda_path = $python_home + "\Scripts\conda.exe" + Write-Host "Updating conda..." -ForegroundColor "Green" + $args = "update --yes conda" + Write-Host $conda_path $args + Start-Process -FilePath "$conda_path" -ArgumentList $args -Wait -Passthru +} + + +function main() { + Write-Host "Starting install_miniconda.ps1" -ForegroundColor "Green" + InstallMiniconda $env:CONDA_BLD_VERSION $env:CONDA_BLD_ARCH $env:CONDA_BLD + UpdateConda $env:CONDA_BLD + InstallCondaPackages $env:CONDA_BLD "conda-build jinja2 anaconda-client" + Write-Host "Completed install_miniconda.ps1" -ForegroundColor "Green" +} + +main diff --git a/ci/run_with_env.cmd b/ci/run_with_env.cmd new file mode 100644 index 000000000..c88489f2c --- /dev/null +++ b/ci/run_with_env.cmd @@ -0,0 +1,85 @@ +:: EXPECTED ENV VARS: PYTHON_ARCH (either x86 or x64) +:: CONDA_PY (either 27, 33, 35 etc. - only major version is extracted) +:: +:: +:: To build extensions for 64 bit Python 3, we need to configure environment +:: variables to use the MSVC 2010 C++ compilers from GRMSDKX_EN_DVD.iso of: +:: MS Windows SDK for Windows 7 and .NET Framework 4 (SDK v7.1) +:: +:: To build extensions for 64 bit Python 2, we need to configure environment +:: variables to use the MSVC 2008 C++ compilers from GRMSDKX_EN_DVD.iso of: +:: MS Windows SDK for Windows 7 and .NET Framework 3.5 (SDK v7.0) +:: +:: 32 bit builds, and 64-bit builds for 3.5 and beyond, do not require specific +:: environment configurations. +:: +:: Note: this script needs to be run with the /E:ON and /V:ON flags for the +:: cmd interpreter, at least for (SDK v7.0) +:: +:: More details at: +:: https://github.com/cython/cython/wiki/64BitCythonExtensionsOnWindows +:: http://stackoverflow.com/a/13751649/163740 +:: +:: Author: Phil Elson +:: Original Author: Olivier Grisel (https://github.com/ogrisel/python-appveyor-demo) +:: License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/ +:: +:: Notes about batch files for Python people: +:: +:: Quotes in values are literally part of the values: +:: SET FOO="bar" +:: FOO is now five characters long: " b a r " +:: If you don't want quotes, don't include them on the right-hand side. +:: +:: The CALL lines at the end of this file look redundant, but if you move them +:: outside of the IF clauses, they do not run properly in the SET_SDK_64==Y +:: case, I don't know why. +:: originally from https://github.com/pelson/Obvious-CI/blob/master/scripts/obvci_appveyor_python_build_env.cmd +:: https://github.com/alimanfoo/zarr/blob/master/build.cmd +:: https://github.com/cython/cython/blob/master/appveyor/run_with_env.cmd +:: https://github.com/cjrh/easycython/blob/master/appveyor/setup_build_env.cmd +@ECHO OFF + +SET COMMAND_TO_RUN=%* +SET WIN_SDK_ROOT=C:\Program Files\Microsoft SDKs\Windows + +:: CONDA_PY style, such as 27, 34 etc. +SET MAJOR_PYTHON_VERSION=%CONDA_PY:~0,1% +SET MINOR_PYTHON_VERSION=%CONDA_PY:~1,1% + +:: Based on the Python version, determine what SDK version to use, and whether +:: to set the SDK for 64-bit. +IF %MAJOR_PYTHON_VERSION% == 2 ( + SET WINDOWS_SDK_VERSION="v7.0" + SET SET_SDK_64=Y +) ELSE IF %MAJOR_PYTHON_VERSION% == 3 ( + SET WINDOWS_SDK_VERSION="v7.1" + IF %MINOR_PYTHON_VERSION% LEQ 4 ( + SET SET_SDK_64=Y + ) ELSE ( + SET SET_SDK_64=N + ) +) ELSE ( + ECHO Unsupported Python version: "%MAJOR_PYTHON_VERSION%" + EXIT /B 1 +) + +IF "%PYTHON_ARCH%"=="64" ( + IF %SET_SDK_64% == Y ( + ECHO Configuring Windows SDK %WINDOWS_SDK_VERSION% for Python %MAJOR_PYTHON_VERSION% on a 64 bit architecture + SET DISTUTILS_USE_SDK=1 + SET MSSdk=1 + "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Setup\WindowsSdkVer.exe" -q -version:%WINDOWS_SDK_VERSION% + "%WIN_SDK_ROOT%\%WINDOWS_SDK_VERSION%\Bin\SetEnv.cmd" /x64 /release + ECHO Executing: %COMMAND_TO_RUN% + call %COMMAND_TO_RUN% || EXIT /B 1 + ) ELSE ( + ECHO Using default MSVC build environment for 64 bit architecture + ECHO Executing: %COMMAND_TO_RUN% + call %COMMAND_TO_RUN% || EXIT /B 1 + ) +) ELSE ( + ECHO Using default MSVC build environment for 32 bit architecture + ECHO Executing: %COMMAND_TO_RUN% + call %COMMAND_TO_RUN% || EXIT /B 1 +) diff --git a/conda.recipe/bld.bat b/conda.recipe/bld.bat new file mode 100644 index 000000000..d846fc738 --- /dev/null +++ b/conda.recipe/bld.bat @@ -0,0 +1,13 @@ +:: build it + +:: set path to modern MSBuild +set PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%PATH% + +%PYTHON% setup.py install + +:: copy our compiled library +set SRC=%RECIPE_DIR%\.. +set DEST=%SP_DIR% + +:: Install step +copy %SRC%\Python.Runtime.dll.config %DEST% diff --git a/conda.recipe/meta.yaml b/conda.recipe/meta.yaml new file mode 100644 index 000000000..da62edc90 --- /dev/null +++ b/conda.recipe/meta.yaml @@ -0,0 +1,28 @@ +package: + name: pythonnet + version: {{ environ.get('GIT_DESCRIBE_TAG', '').replace('-dev', '.dev') }} + +build: + skip: True # [not win] + number: {{ environ.get('GIT_DESCRIBE_NUMBER', 0) }} + {% if environ.get('GIT_DESCRIBE_NUMBER', '0') == '0' %}string: py{{ environ.get('PY_VER').replace('.', '') }}_0 + {% else %}string: py{{ environ.get('PY_VER').replace('.', '') }}_{{ environ.get('GIT_BUILD_STR', 'GIT_STUB') }}{% endif %} + +source: + git_url: ../ + +requirements: + build: + - python + - setuptools + + run: + - python + +test: + imports: + - clr + +about: + home: https://github.com/pythonnet/pythonnet + license: MIT diff --git a/demo/helloform.py b/demo/helloform.py index 834772de6..6e404771a 100644 --- a/demo/helloform.py +++ b/demo/helloform.py @@ -1,3 +1,6 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + import clr SWF = clr.AddReference("System.Windows.Forms") @@ -13,7 +16,7 @@ class HelloApp(WinForms.Form): def __init__(self): self.Text = "Hello World From Python" self.AutoScaleBaseSize = Size(5, 13) - self.ClientSize = Size(392, 117); + self.ClientSize = Size(392, 117) h = WinForms.SystemInformation.CaptionHeight self.MinimumSize = Size(392, (117 + h)) @@ -36,8 +39,8 @@ def __init__(self): # Add the controls to the form self.AcceptButton = self.button - self.Controls.Add(self.button); - self.Controls.Add(self.textbox); + self.Controls.Add(self.button) + self.Controls.Add(self.textbox) def button_Click(self, sender, args): """Button click event handler""" diff --git a/demo/splitter.py b/demo/splitter.py index 319de451f..126499db6 100644 --- a/demo/splitter.py +++ b/demo/splitter.py @@ -1,7 +1,12 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + import clr + +import System import System.Windows.Forms as WinForms + from System.Drawing import Color, Size, Point -import System class Splitter(WinForms.Form): diff --git a/demo/wordpad.py b/demo/wordpad.py index e9373b3eb..876372100 100644 --- a/demo/wordpad.py +++ b/demo/wordpad.py @@ -1,10 +1,14 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + import clr +import System import System.Windows.Forms as WinForms -from System.Threading import Thread, ThreadStart, ApartmentState -from System.Drawing import Color, Size, Point -from System.Text import Encoding + from System.IO import File -import System +from System.Text import Encoding +from System.Drawing import Color, Point, Size +from System.Threading import ApartmentState, Thread, ThreadStart class Wordpad(WinForms.Form): diff --git a/doc/Python.Runtime.dll.config b/doc/Python.Runtime.dll.config deleted file mode 100644 index 3cfe2735a..000000000 --- a/doc/Python.Runtime.dll.config +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - diff --git a/doc/TODO.txt b/doc/TODO.txt deleted file mode 100644 index b13cf1024..000000000 --- a/doc/TODO.txt +++ /dev/null @@ -1,34 +0,0 @@ -TODO list -========= - -For PythonNet 2.0 ------------------ - - * Implement support for ModulePropertyAttribute. - - * Replace CLRModule.preload code with ModulePropertyAttribute specific code. - - * Deprecate implicit loading of assemblies - - * Debug failing unit tests under Mono and report them if they are caused - by incompatibilities in Mono. - -Future and nice-to-have features --------------------------------- - - * Add support for Python's debug builds. Debug builds have additional fields - in the struct, extensive self testing and C assert() are enabled. Py_DEBUG - implies Py_TRACE_REFS and Py_REF_DEBUG which enlarge the PyObject and - PyVarObject based structs. The Py_INCREF and Py_DECREF macros have a larger - payload as well. They keep track of the absolute number of references and - do tests when an object is GCed. - I've taken care of most of the incompatibilities but the Py_DEBUG build - is still broken. Somehow tp_mro of wrapper_descriptor isn't a tuple. - - * Support Python 2.6. The most important feature I was able to isolate is the - PyType_FastSubclass macro and related TypeFlags in interops.cs. - - * Let's talk to the Debian and Ubuntu maintainers for Python in order to convince - them to build Python with --enable-shared. Ubuntu's Python is semi static and not - linked against libpython2.x.so. This causes trouble with clr.so. - diff --git a/doc/changes.txt b/doc/changes.txt deleted file mode 100644 index 7e577d96c..000000000 --- a/doc/changes.txt +++ /dev/null @@ -1,400 +0,0 @@ -Python for .NET Changes ------------------------ - - PythonNet 2.0 alpha 2 - --------------------------------------------------------------------------- - - - First work on Python 2.5 compatibility. The destination version can be - set by defining PYTHON24 or PYTHON25. Python 2.6 compatibility is in - work. [tiran] - - - Added VS 2005 solution and project files including a UnitTest - configuration which runs the unit test suite. [tiran] - - - Enhanced unit test suite. All test cases are combined in a single - test suite now. [tiran] - - - Fixed bugs in generics support for all Python versions. [tiran] - - - Fixed exception bugs for Python 2.5+. When compiled for Python 2.5+ all - managed exceptions are based on Python's exceptions.Exception class. - [tiran] - - - Added deprecation warnings for importing from CLR.* and the CLR module. - [tiran] - - - Implemented support for methods with variable arguments - spam(params object[] egg) [tiran] - - - Fixed Mono support by adding a custom marshaler for UCS-4 unicode, - fixing a some ref counter bugs and creating a new makefile.mono. - [tiran] - - - Added a standard python extension to load the clr environment. - The src/monoclr/ directory contains additional sample code like a - Python binary linked against libpython2.x.so and some example code - how to embed Mono and PythonNet in a C application. - [tiran] - - - Added yet another python prompt. This time it's a C application that - embedds both Python and Mono. It may be useful as an example app for - others and I need it to debug a nasty bug. [tiran] - - - Implemented ModuleFunctionAttribute and added ForbidPythonThreadsAttribute. - The latter is required for module functions which invoke Python methods. - [tiran] - - - Added clr.setPreload(), clr.getPreload(), clr.AddReference("assembly name"), - clr.FindAssembly("name") and clr.ListAssemblies(verbose). Automatic - preloading can be enabled with clr.setPreload/True). Preloading is - automatically enabled for interactive Python shells and disabled in all - other cases. [tiran] - - - New Makefile that works for Windows and Mono and autodetects the Python - version and UCS 2/4 setting. [tiran] - - - Added code for Python 2.3. PythonNet can be build for Python 2.3 again - but it is not fully supported. [tiran] - - - Changed the PythonException.Message value so it displays the name of - the exception class ("Exception") instead of its representation - (""). - - - Added Python.Runtime.dll.config - - - PythonNet 2.0 alpha 1 - --------------------------------------------------------------------------- - - - Moved the Python for .NET project to Sourceforge and moved version - control to Subversion. - - - Removed CallConvCdecl attributes and the IL hack that they supported. - .NET 2.x now supports UnmanagedFunctionPointer, which does the right - thing without the hackery required in 1.x. This removes a dependency - on ILASM to build the package and better supports Mono (in theory). - - - Refactored import and assembly management machinery. The old 'CLR.' - syntax for import is deprecated, but still supported until 3.x. The - recommended style now is to use 'from System import xxx', etc. We - also now support 'from X import *' correctly. - - - Implemented a (lowercase) 'clr' module to match IronPython for code - compatibility. Methods of this module should be used to explicitly - load assemblies. Implicit (name-based) assembly loading will still - work until 3.x, but it is deprecated. - - - Implemented support for generic types and generic methods using the - same patterns and syntax as IronPython. See the documentation for - usage details. - - - Many small and large performance improvements, switched to generic - collections for some internals, better algorithms for assembly - scanning, etc. - - - Fixed an unboxing issue in generated delegate implementation code - that affected delegates that return value types. - - - PythonNet 1.0 final - --------------------------------------------------------------------------- - - - Backported the refactored import and assembly management from the 2.x - line, mainly to improve the possibility of code-compatibility with - IronPython. - - - 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. diff --git a/doc/mono_config.txt b/doc/mono_config.txt deleted file mode 100644 index 2e62ad142..000000000 --- a/doc/mono_config.txt +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - diff --git a/htdocs/index.html b/htdocs/index.html deleted file mode 100755 index a1c362770..000000000 --- a/htdocs/index.html +++ /dev/null @@ -1,149 +0,0 @@ - - - Python for .NET - - - - - - - - - - -
-

Python for .NET

-

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).

-

Note that this package does not 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 IronPython - project, which is in active development.

-

Python for .NET is currently compatible with Python releases 2.5 - and greater. To subscribe to the - Python for .NET mailing list or read the - online archives of the list, see the - mailing list information page. You can also send questions - or comments to me at brian.lloyd@revolution.com - or use the - Python for .NET issue tracker to report issues.

-

My blog site is - also (sometimes) a good source for more information on Python for - .NET ;)

-
    -
  • The README 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.
  • -
  • Checkout the PythonNet - code from Subversion..
  • -
  • - Download releases for various versions of Python and CLR. -
  • -
-
- - diff --git a/htdocs/license.txt b/htdocs/license.txt deleted file mode 100755 index ec12c9f2a..000000000 --- a/htdocs/license.txt +++ /dev/null @@ -1,61 +0,0 @@ -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. - - diff --git a/htdocs/readme.html b/htdocs/readme.html deleted file mode 100755 index d7ae26f04..000000000 --- a/htdocs/readme.html +++ /dev/null @@ -1,672 +0,0 @@ - - - Python for .NET - - - - - - - - - - - -
-

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). -

-

Note that this package does not 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 IronPython - project, which is in active development. -

-

Python for .NET is currently compatible with Python releases 2.3 - and greater. Current releases are available at the - Python for .NET website . To subscribe to the - Python for .NET mailing list or read the - online archives of the list, see the - mailing list information page.

- -

Installation

-

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 - Python for .NET website . 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. -

- -

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. -

-

Running on Linux/Mono: preliminary testing - shows that PythonNet will run under Mono, - 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. -

-

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: -

-
    ln -s /usr/lib/libpython2.4.so ./python24.so
-
- -

Getting Started

-

A key goal for this project has been that Python for .NET should - "work just the way you'd expect in Python", except for cases that - are .NET specific (in which case the goal is to work "just the way - you'd expect in C#"). In addition, with the IronPython project - gaining traction, it is my goal that code written for IronPython - run without modification under Python for .NET. -

-

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. -

-

A good way to start is to run python.exe 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. -

-

Note that if you have installed CLR support into your existing - Python installation (rather than using the included python.exe), - you will need to use the line: "'import clr" (lower-case!) to - initially load the clr extension module before trying the - following examples. -

- -

Importing Modules

-

Python for .NET allows CLR namespaces to be treated essentially - as Python packages.

-

-

-
    from System import String
-    from System.Collections import *
-
-

- Note that earlier releases of Python for .NET required you to - import modules through a special top-level package named CLR. - This is no longer required if you are starting python from the - managed python.exe from this distribution.
- CLR has been deprecated in favor of the more - pythonic clr, though the syntax is still supported - for backward compatibility. -
-

-

Types from any loaded assembly may be imported and used in this - manner. To load an assembly, use the "AddReference" function in - the "clr" module: -

-
-    import clr
-    clr.AddReference("System.Windows.Forms")
-    from System.Windows.Forms import Form
-
-
-

- Note that earlier releases of Python for .NET relied on - "implicit loading" to support automatic loading of assemblies - whose names corresponded to an imported namespace. Implicit - loading still works for backward compatibility, but will be - removed in a future release so it is recommended to use the - clr.AddReference method. - -

-

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 sys.path. -

- -

Using Classes

-

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: -

-
    from System.Drawing import Point
-
-    p = Point(5, 5)
-
-

In most cases, Python for .NET can determine the correct - constructor to call automatically based on the arguments. In some - cases, it may be necessary to call a particular overloaded - constructor, which is supported by a special "__overloads__" - attribute, which will soon be deprecated in favor of iPy - compatible "Overloads", on a class: -

-
    from System import String, Char, Int32
-
-    s = String.Overloads[Char, Int32]('A', 10)
-    s = String.__overloads__[Char, Int32]('A', 10)
-
- -

Using Generics

-

When running under versions of the .NET runtime greater than - 2.0, you can use generic types. A generic type must be bound to - create a concrete type before it can be instantiated. Generic - types support the subscript syntax to create bound types: -

-
    from System.Collections.Generic import Dictionary
-    from System import *
-
-    dict1 = Dictionary[String, String]()
-    dict2 = Dictionary[String, Int32]()
-    dict3 = Dictionary[String, Type]()
-
-

When you pass a list of types using the subscript syntax, you - can also pass a subset of Python types that directly correspond to - .NET types: -

-
    dict1 = Dictionary[str, str]()
-    dict2 = Dictionary[str, int]()
-    dict3 = Dictionary[str, Decimal]()
-
-

This shorthand also works when explicitly selecting generic - methods or specific versions of overloaded methods and - constructors (explained later). -

-

You can also subclass managed classes in Python, though members - of the Python subclass are not visible to .NET code. See the helloform.py - file in the /demo directory of the distribution for - a simple Windows Forms example that demonstrates subclassing a - managed class. -

- -

Fields And Properties

-

You can get and set fields and properties of CLR objects just as - if they were regular attributes: -

-
    from System import Environment
-
-    name = Environment.MachineName
-    Environment.ExitCode = 1
-
- -

Using Indexers

-

If a managed object implements one or more indexers, you can - call the indexer using standard Python indexing syntax: -

-
    from System.Collections import Hashtable
-
-    table = Hashtable()
-    table["key 1"] = "value 1"
-
-

Overloaded indexers are supported, using the same notation one - would use in C#: -

-
    items[0, 2]
-
-    items[0, 2, 3]
-
- -

Using Methods

-

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: -

-
    from System import Environment
-
-    drives = Environment.GetLogicalDrives()
-
-

It is also possible to call managed methods unbound - (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. -

-

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. -

-

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 help method - to inspect a managed class: -

-
    from System import Environment
-
-    print Environment.GetFolderPath.__doc__
-
-    help(Environment)
-
- -

Overloaded and Generic Methods

-

While Python for .NET will generally be able to figure out the - right version of an overloaded method to call automatically, there - are cases where it is desirable to select a particular method - overload explicitly. -

-

Methods of CLR objects have an "__overloads__", which will soon - be deprecated in favor of iPy compatible Overloads, attribute that - can be used for this purpose : -

-
    from System import Console
-
-    Console.WriteLine.Overloads[bool](true)
-    Console.WriteLine.Overloads[str]("true")
-    Console.WriteLine.__overloads__[int](42)
-
-

Similarly, generic methods may be bound at runtime using the - subscript syntax directly on the method: -

-
    someobject.SomeGenericMethod[int](10)
-    someobject.SomeGenericMethod[str]("10")
-
- -

Delegates And Events

-

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: -

-
    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
-
-

Multicast delegates can be implemented by adding more callable - objects to a delegate instance: -

-
    d += self.method1
-    d += self.method2
-    d()
-
-

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. -

-

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 += and -= operators in a - way very similar to the C# idiom: -

-
    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(...)
-
- -

Exception Handling

-

You can raise and catch managed exceptions just the same as you - would pure-Python exceptions: -

-
    from System import NullReferenceException
-
-    try:
-        raise NullReferenceException("aiieee!")
-    except NullReferenceException, e:
-        print e.Message
-        print e.Source
-
-

- -

Using Arrays

-

The type System.Array supports the subscript - syntax in order to make it easy to create managed arrays from - Python: -

-
    from System import Array
-
-    myarray = Array[int](10)
-
-

Managed arrays support the standard Python sequence protocols: -

-
    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
-
-

Multidimensional arrays support indexing using the same notation - one would use in C#: -

-
    items[0, 2]
-
-    items[0, 2, 3]
-
- -

Using Collections

-

Managed arrays and managed objects that implement the - IEnumerable interface can be iterated over using the standard - iteration Python idioms: -

-
    domain = System.AppDomain.CurrentDomain
-
-    for item in domain.GetAssemblies():
-        name = item.GetName()
-
- -

Using COM Components

-

Using Microsoft-provided tools such as aximp.exe - and tlbimp.exe, 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. -

-

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. -

- -

Type Conversion

-

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. -

-

Types that do not have a logical equivalent in Python are - exposed as instances of managed classes or structs (System.Decimal - is an example). -

-

The .NET architecture makes a distinction between value - types and reference types. Reference types - are allocated on the heap, and value types are allocated either on - the stack or in-line within an object. -

-

A process called boxing 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. -

-

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 "everything is a reference". -

-

Here is a simple example that demonstrates an issue. If you are - an experienced C# programmer, you might write the following code: -

-
    items = System.Array.CreateInstance(Point, 3)
-    for i in range(3):
-        items[i] = Point(0, 0)
-
-    items[0].X = 1 # won't work!!
-
-

While the spelling of items[0].X = 1 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. -

-

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 items[0] - itself doesn't change is that when you say items[0], - that getitem operation creates a Python object that holds a - reference to the object at items[0] via a GCHandle. - That causes a ValueType (like Point) to be boxed, so the following - setattr (.X = 1) changes the state of the boxed - value, not the original unboxed value. -

-

The rule in Python is essentially: "the result of any attribute - or item access is a boxed value", and that can be important in how - you approach your code. -

-

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: -

-
    items = 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
-
-

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 lost - update problems (generally because an implicit boxing - happened that was not taken into account in the code). -

-

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. -

- -

Embedding Python

-

Note: 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. -

-

The Python runtime assembly defines a number of public classes - that provide a subset of the functionality provided by the Python - C API. -

-

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. -

-

At a very high level, to embed Python in your application you - will need to: -

-
    -
  • Reference Python.Runtime.dll in your build environment
  • -
  • Call PythonEngine.Intialize() to initialize Python
  • -
  • Call PythonEngine.ImportModule(name) to import a module
  • -
-

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. -

-

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. -

-

Important Note for embedders: 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. -

-

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. -

-

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 PythonEngine.AcquireLock - method. The only exception to this rule is the PythonEngine.Initialize - method, which may be called at startup without having acquired the - GIL. -

-

When finished using Python APIs, managed code must call a - corresponding PythonEngine.ReleaseLock to release - the GIL and allow other threads to use Python. -

-

The AcquireLock and ReleaseLock methods are thin wrappers over - the unmanaged PyGILState_Ensure and PyGILState_Release - functions from the Python API, and the documentation for those - APIs applies to the managed versions. -

- -

License

-
-

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 - ZPL online . Some distributions of this package include a - copy of the C Python dlls and standard library, which are covered - by the Python - license . -

-
- - diff --git a/installer/installer.iss b/installer/installer.iss deleted file mode 100644 index b0aa6ea2b..000000000 --- a/installer/installer.iss +++ /dev/null @@ -1,73 +0,0 @@ -; -------------------------------------------------------------------------------- -; 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; - - diff --git a/installer/left.bmp b/installer/left.bmp deleted file mode 100644 index 424aae680..000000000 Binary files a/installer/left.bmp and /dev/null differ diff --git a/installer/license.txt b/installer/license.txt deleted file mode 100644 index 44e0648b3..000000000 --- a/installer/license.txt +++ /dev/null @@ -1,59 +0,0 @@ -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. diff --git a/installer/top.bmp b/installer/top.bmp deleted file mode 100644 index 370ff89ba..000000000 Binary files a/installer/top.bmp and /dev/null differ diff --git a/monopythonnet.mds b/monopythonnet.mds deleted file mode 100644 index 1d3dc000d..000000000 --- a/monopythonnet.mds +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/pythonnet.build b/pythonnet.build deleted file mode 100644 index 9d0d6584a..000000000 --- a/pythonnet.build +++ /dev/null @@ -1,74 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/pythonnet.sln b/pythonnet.sln index 64bf45fa2..0a4dbe1f7 100644 --- a/pythonnet.sln +++ b/pythonnet.sln @@ -1,4 +1,4 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 VisualStudioVersion = 12.0.30110.0 @@ -89,10 +89,14 @@ Global {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.ReleaseWin|x64.Build.0 = Release|x64 {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.ReleaseWin|x86.ActiveCfg = Release|x86 {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.ReleaseWin|x86.Build.0 = Release|x86 + {86E834DE-1139-4511-96CC-69636A56E7AC}.DebugMono|x64.ActiveCfg = DebugWin|x64 + {86E834DE-1139-4511-96CC-69636A56E7AC}.DebugMono|x86.ActiveCfg = DebugWin|x86 {86E834DE-1139-4511-96CC-69636A56E7AC}.DebugWin|x64.ActiveCfg = DebugWin|x64 {86E834DE-1139-4511-96CC-69636A56E7AC}.DebugWin|x64.Build.0 = DebugWin|x64 {86E834DE-1139-4511-96CC-69636A56E7AC}.DebugWin|x86.ActiveCfg = DebugWin|x86 {86E834DE-1139-4511-96CC-69636A56E7AC}.DebugWin|x86.Build.0 = DebugWin|x86 + {86E834DE-1139-4511-96CC-69636A56E7AC}.ReleaseMono|x64.ActiveCfg = ReleaseWin|x64 + {86E834DE-1139-4511-96CC-69636A56E7AC}.ReleaseMono|x86.ActiveCfg = ReleaseWin|x86 {86E834DE-1139-4511-96CC-69636A56E7AC}.ReleaseWin|x64.ActiveCfg = ReleaseWin|x64 {86E834DE-1139-4511-96CC-69636A56E7AC}.ReleaseWin|x64.Build.0 = ReleaseWin|x64 {86E834DE-1139-4511-96CC-69636A56E7AC}.ReleaseWin|x86.ActiveCfg = ReleaseWin|x86 diff --git a/pythonnet_8.sln b/pythonnet_8.sln deleted file mode 100644 index e30c01be0..000000000 --- a/pythonnet_8.sln +++ /dev/null @@ -1,86 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Python.Runtime", "src\runtime\Python.Runtime.csproj", "{097B4AC0-74E9-4C58-BCF8-C69746EC8271}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Python.Test", "src\testing\Python.Test.csproj", "{6F401A34-273B-450F-9A4C-13550BE0767B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Python.EmbeddingTest", "src\embed_tests\Python.EmbeddingTest.csproj", "{4165C59D-2822-499F-A6DB-EACA4C331EB5}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Console", "src\console\Console.csproj", "{E29DCF0A-5114-4A98-B1DD-71264B6EA349}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - EmbeddingTest|Any CPU = EmbeddingTest|Any CPU - EmbeddingTest|x64 = EmbeddingTest|x64 - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - UnitTests|Any CPU = UnitTests|Any CPU - UnitTests|x64 = UnitTests|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.Debug|Any CPU.Build.0 = Debug|Any CPU - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.Debug|x64.ActiveCfg = Debug|x64 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.Debug|x64.Build.0 = Debug|x64 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.EmbeddingTest|Any CPU.ActiveCfg = Debug|Any CPU - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.EmbeddingTest|Any CPU.Build.0 = Debug|Any CPU - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.EmbeddingTest|x64.ActiveCfg = Debug|x64 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.EmbeddingTest|x64.Build.0 = Debug|x64 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.Release|Any CPU.ActiveCfg = Release|Any CPU - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.Release|Any CPU.Build.0 = Release|Any CPU - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.Release|x64.ActiveCfg = Release|x64 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.Release|x64.Build.0 = Release|x64 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.UnitTests|Any CPU.ActiveCfg = Debug|Any CPU - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.UnitTests|Any CPU.Build.0 = Debug|Any CPU - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.UnitTests|x64.ActiveCfg = Debug|x64 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.UnitTests|x64.Build.0 = Debug|x64 - {6F401A34-273B-450F-9A4C-13550BE0767B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6F401A34-273B-450F-9A4C-13550BE0767B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6F401A34-273B-450F-9A4C-13550BE0767B}.Debug|x64.ActiveCfg = Debug|Any CPU - {6F401A34-273B-450F-9A4C-13550BE0767B}.Debug|x64.Build.0 = Debug|Any CPU - {6F401A34-273B-450F-9A4C-13550BE0767B}.EmbeddingTest|Any CPU.ActiveCfg = Debug|Any CPU - {6F401A34-273B-450F-9A4C-13550BE0767B}.EmbeddingTest|Any CPU.Build.0 = Debug|Any CPU - {6F401A34-273B-450F-9A4C-13550BE0767B}.EmbeddingTest|x64.ActiveCfg = Debug|Any CPU - {6F401A34-273B-450F-9A4C-13550BE0767B}.EmbeddingTest|x64.Build.0 = Debug|Any CPU - {6F401A34-273B-450F-9A4C-13550BE0767B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6F401A34-273B-450F-9A4C-13550BE0767B}.Release|Any CPU.Build.0 = Release|Any CPU - {6F401A34-273B-450F-9A4C-13550BE0767B}.Release|x64.ActiveCfg = Release|Any CPU - {6F401A34-273B-450F-9A4C-13550BE0767B}.Release|x64.Build.0 = Release|Any CPU - {6F401A34-273B-450F-9A4C-13550BE0767B}.UnitTests|Any CPU.ActiveCfg = Debug|Any CPU - {6F401A34-273B-450F-9A4C-13550BE0767B}.UnitTests|Any CPU.Build.0 = Debug|Any CPU - {6F401A34-273B-450F-9A4C-13550BE0767B}.UnitTests|x64.ActiveCfg = Debug|Any CPU - {6F401A34-273B-450F-9A4C-13550BE0767B}.UnitTests|x64.Build.0 = Debug|Any CPU - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.Debug|x64.ActiveCfg = Debug|Any CPU - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.EmbeddingTest|Any CPU.ActiveCfg = Release|Any CPU - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.EmbeddingTest|Any CPU.Build.0 = Release|Any CPU - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.EmbeddingTest|x64.ActiveCfg = Release|Any CPU - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.EmbeddingTest|x64.Build.0 = Release|Any CPU - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.Release|x64.ActiveCfg = Release|Any CPU - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.UnitTests|Any CPU.ActiveCfg = Debug|Any CPU - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.UnitTests|x64.ActiveCfg = Debug|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.Debug|x64.ActiveCfg = Debug|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.Debug|x64.Build.0 = Debug|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.EmbeddingTest|Any CPU.ActiveCfg = EmbeddingTest|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.EmbeddingTest|Any CPU.Build.0 = EmbeddingTest|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.EmbeddingTest|x64.ActiveCfg = EmbeddingTest|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.EmbeddingTest|x64.Build.0 = EmbeddingTest|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.Release|Any CPU.Build.0 = Release|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.Release|x64.ActiveCfg = Release|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.Release|x64.Build.0 = Release|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.UnitTests|Any CPU.ActiveCfg = UnitTests|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.UnitTests|Any CPU.Build.0 = UnitTests|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.UnitTests|x64.ActiveCfg = UnitTests|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.UnitTests|x64.Build.0 = UnitTests|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/pythonnet_9.sln b/pythonnet_9.sln deleted file mode 100644 index 1d11d7fd8..000000000 --- a/pythonnet_9.sln +++ /dev/null @@ -1,87 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Python.Runtime", "src\runtime\Python.Runtime.csproj", "{097B4AC0-74E9-4C58-BCF8-C69746EC8271}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Python.Test", "src\testing\Python.Test.csproj", "{6F401A34-273B-450F-9A4C-13550BE0767B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Python.EmbeddingTest", "src\embed_tests\Python.EmbeddingTest.csproj", "{4165C59D-2822-499F-A6DB-EACA4C331EB5}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Console", "src\console\Console.csproj", "{E29DCF0A-5114-4A98-B1DD-71264B6EA349}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - EmbeddingTest|Any CPU = EmbeddingTest|Any CPU - EmbeddingTest|x64 = EmbeddingTest|x64 - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - UnitTests|Any CPU = UnitTests|Any CPU - UnitTests|x64 = UnitTests|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.Debug|Any CPU.Build.0 = Debug|Any CPU - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.Debug|x64.ActiveCfg = Debug|x64 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.Debug|x64.Build.0 = Debug|x64 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.EmbeddingTest|Any CPU.ActiveCfg = Debug|Any CPU - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.EmbeddingTest|Any CPU.Build.0 = Debug|Any CPU - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.EmbeddingTest|x64.ActiveCfg = Debug|x64 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.EmbeddingTest|x64.Build.0 = Debug|x64 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.Release|Any CPU.ActiveCfg = Release|Any CPU - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.Release|Any CPU.Build.0 = Release|Any CPU - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.Release|x64.ActiveCfg = Release|x64 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.Release|x64.Build.0 = Release|x64 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.UnitTests|Any CPU.ActiveCfg = Debug|Any CPU - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.UnitTests|Any CPU.Build.0 = Debug|Any CPU - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.UnitTests|x64.ActiveCfg = Debug|x64 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271}.UnitTests|x64.Build.0 = Debug|x64 - {6F401A34-273B-450F-9A4C-13550BE0767B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6F401A34-273B-450F-9A4C-13550BE0767B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6F401A34-273B-450F-9A4C-13550BE0767B}.Debug|x64.ActiveCfg = Debug|Any CPU - {6F401A34-273B-450F-9A4C-13550BE0767B}.Debug|x64.Build.0 = Debug|Any CPU - {6F401A34-273B-450F-9A4C-13550BE0767B}.EmbeddingTest|Any CPU.ActiveCfg = Debug|Any CPU - {6F401A34-273B-450F-9A4C-13550BE0767B}.EmbeddingTest|Any CPU.Build.0 = Debug|Any CPU - {6F401A34-273B-450F-9A4C-13550BE0767B}.EmbeddingTest|x64.ActiveCfg = Debug|Any CPU - {6F401A34-273B-450F-9A4C-13550BE0767B}.EmbeddingTest|x64.Build.0 = Debug|Any CPU - {6F401A34-273B-450F-9A4C-13550BE0767B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6F401A34-273B-450F-9A4C-13550BE0767B}.Release|Any CPU.Build.0 = Release|Any CPU - {6F401A34-273B-450F-9A4C-13550BE0767B}.Release|x64.ActiveCfg = Release|Any CPU - {6F401A34-273B-450F-9A4C-13550BE0767B}.Release|x64.Build.0 = Release|Any CPU - {6F401A34-273B-450F-9A4C-13550BE0767B}.UnitTests|Any CPU.ActiveCfg = Debug|Any CPU - {6F401A34-273B-450F-9A4C-13550BE0767B}.UnitTests|Any CPU.Build.0 = Debug|Any CPU - {6F401A34-273B-450F-9A4C-13550BE0767B}.UnitTests|x64.ActiveCfg = Debug|Any CPU - {6F401A34-273B-450F-9A4C-13550BE0767B}.UnitTests|x64.Build.0 = Debug|Any CPU - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.Debug|x64.ActiveCfg = Debug|Any CPU - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.EmbeddingTest|Any CPU.ActiveCfg = Release|Any CPU - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.EmbeddingTest|Any CPU.Build.0 = Release|Any CPU - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.EmbeddingTest|x64.ActiveCfg = Release|Any CPU - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.EmbeddingTest|x64.Build.0 = Release|Any CPU - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.Release|x64.ActiveCfg = Release|Any CPU - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.UnitTests|Any CPU.ActiveCfg = Debug|Any CPU - {4165C59D-2822-499F-A6DB-EACA4C331EB5}.UnitTests|x64.ActiveCfg = Debug|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.Debug|x64.ActiveCfg = Debug|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.Debug|x64.Build.0 = Debug|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.EmbeddingTest|Any CPU.ActiveCfg = EmbeddingTest|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.EmbeddingTest|Any CPU.Build.0 = EmbeddingTest|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.EmbeddingTest|x64.ActiveCfg = EmbeddingTest|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.EmbeddingTest|x64.Build.0 = EmbeddingTest|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.Release|Any CPU.Build.0 = Release|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.Release|x64.ActiveCfg = Release|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.Release|x64.Build.0 = Release|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.UnitTests|Any CPU.ActiveCfg = UnitTests|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.UnitTests|Any CPU.Build.0 = UnitTests|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.UnitTests|x64.ActiveCfg = UnitTests|Any CPU - {E29DCF0A-5114-4A98-B1DD-71264B6EA349}.UnitTests|x64.Build.0 = UnitTests|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/setup.py b/setup.py index 880fdd7fd..9ad4178bd 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,11 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + """ Setup script for building clr.pyd and dependencies using mono and into an egg or wheel. """ + from setuptools import setup, Extension from distutils.command.build_ext import build_ext from distutils.command.install_lib import install_lib @@ -23,7 +27,7 @@ def _find_msbuild_tool(tool="msbuild.exe", use_windows_sdk=False): - """Return full path to one of the microsoft build tools""" + """Return full path to one of the Microsoft build tools""" path = find_executable(tool) if path: return path @@ -82,7 +86,8 @@ def _find_msbuild_tool(tool="msbuild.exe", use_windows_sdk=False): finally: hreg.Close() - # Add Visual C++ for Python as a fallback in case one of the other Windows SDKs isn't installed + # Add Visual C++ for Python as a fall-back in case one + # of the other Windows SDKs isn't installed if use_windows_sdk: localappdata = os.environ["LOCALAPPDATA"] pywinsdk = localappdata + r"\Programs\Common\Microsoft\Visual C++ for Python\9.0\WinSDK\Bin" @@ -110,14 +115,13 @@ def _find_msbuild_tool(tool="msbuild.exe", use_windows_sdk=False): _config = "%sMono" % CONFIG else: - raise NotImplementedError("DevTools %s not supported (use MsDev or Mono)" % DEVTOOLS) + raise NotImplementedError( + "DevTools %s not supported (use MsDev or Mono)" % DEVTOOLS) class PythonNET_BuildExt(build_ext): def build_extension(self, ext): - """ - Builds the .pyd file using msbuild or xbuild. - """ + """Builds the .pyd file using msbuild or xbuild""" if ext.name != "clr": return build_ext.build_extension(self, ext) @@ -129,8 +133,8 @@ def build_extension(self, ext): if not os.path.exists(dest_dir): os.makedirs(dest_dir) - # Up to Python 3.2 sys.maxunicode is used to determine the size of Py_UNICODE - # but from 3.3 onwards Py_UNICODE is a typedef of wchar_t. + # Up to Python 3.2 sys.maxunicode is used to determine the size of + # Py_UNICODE, but from 3.3 onwards Py_UNICODE is a typedef of wchar_t. if sys.version_info[:2] <= (3, 2): unicode_width = 2 if sys.maxunicode < 0x10FFFF else 4 else: @@ -138,7 +142,8 @@ def build_extension(self, ext): unicode_width = ctypes.sizeof(ctypes.c_wchar) defines = [ - "PYTHON%d%s" % (sys.version_info[:2]), + "PYTHON%d%d" % (sys.version_info[:2]), + "PYTHON%d" % (sys.version_info[:1]), # Python Major Version "UCS%d" % unicode_width, ] @@ -153,7 +158,13 @@ def build_extension(self, ext): # Check if --enable-shared was set when Python was built enable_shared = get_config_var("Py_ENABLE_SHARED") - if enable_shared == 0: + if enable_shared: + # Double-check if libpython is linked dynamically with python + lddout = _check_output(["ldd", sys.executable]) + if 'libpython' not in lddout: + enable_shared = False + + if not enable_shared: defines.append("PYTHON_WITHOUT_ENABLE_SHARED") if hasattr(sys, "abiflags"): @@ -197,7 +208,8 @@ def _get_manifest(self, build_dir): if DEVTOOLS == "MsDev" and sys.version_info[:2] > (2, 5): mt = _find_msbuild_tool("mt.exe", use_windows_sdk=True) manifest = os.path.abspath(os.path.join(build_dir, "app.manifest")) - cmd = [mt, '-inputresource:"%s"' % sys.executable, '-out:"%s"' % manifest] + cmd = [mt, '-inputresource:"%s"' % sys.executable, + '-out:"%s"' % manifest] self.announce("Extracting manifest from %s" % sys.executable) check_call(" ".join(cmd), shell=False) return manifest @@ -229,6 +241,10 @@ def _install_packages(self): nuget = "mono %s" % nuget use_shell = True + cmd = "%s update -self" % nuget + self.announce("Updating NuGet: %s" % cmd) + check_call(cmd, shell=use_shell) + cmd = "%s restore pythonnet.sln -o packages" % nuget self.announce("Installing packages: %s" % cmd) check_call(cmd, shell=use_shell) @@ -271,8 +287,7 @@ def run(self): def _check_output(*popenargs, **kwargs): """subprocess.check_output from python 2.7. - Added here to support building for earlier versions - of Python. + Added here to support building for earlier versions of Python. """ process = Popen(stdout=PIPE, *popenargs, **kwargs) output, unused_err = process.communicate() @@ -293,7 +308,7 @@ def _get_interop_filename(): as most windows users won't have Clang installed, which is required to generate the file. """ - interop_file = "interop%d%s%s.cs" % (sys.version_info[0], sys.version_info[1], getattr(sys, "abiflags", "")) + interop_file = "interop%d%d%s.cs" % (sys.version_info[0], sys.version_info[1], getattr(sys, "abiflags", "")) return os.path.join("src", "runtime", interop_file) @@ -312,7 +327,7 @@ def _get_interop_filename(): sources.append(os.path.join(root, filename)) for root, dirnames, filenames in os.walk("tools"): - for ext in (".exe"): + for ext in (".exe", ".py"): for filename in fnmatch.filter(filenames, "*" + ext): sources.append(os.path.join(root, filename)) @@ -323,20 +338,23 @@ def _get_interop_filename(): setup( name="pythonnet", - version="2.2.0-dev1", + version="2.2.1", description=".Net and Mono integration for Python", - url='http://pythonnet.github.io/', - author="Python for .Net developers", + url='https://pythonnet.github.io/', + license='MIT', + author="The Python for .Net developers", classifiers=[ + 'Development Status :: 5 - Production/Stable', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: MIT License', + 'Programming Language :: C#', + 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3.2', + 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', - 'Programming Language :: C#', - 'License :: OSI Approved :: Zope Public License', - 'Development Status :: 5 - Production/Stable', - 'Intended Audience :: Developers', + 'Programming Language :: Python :: 3.6', 'Operating System :: Microsoft :: Windows', 'Operating System :: POSIX :: Linux', 'Operating System :: MacOS :: MacOS X', diff --git a/src/clrmodule/Properties/AssemblyInfo.cs b/src/clrmodule/AssemblyInfo.cs similarity index 95% rename from src/clrmodule/Properties/AssemblyInfo.cs rename to src/clrmodule/AssemblyInfo.cs index c9658c0b5..669183255 100644 --- a/src/clrmodule/Properties/AssemblyInfo.cs +++ b/src/clrmodule/AssemblyInfo.cs @@ -1,5 +1,4 @@ -using System.Reflection; -using System.Runtime.CompilerServices; +using System.Reflection; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following diff --git a/src/clrmodule/ClrModule.cs b/src/clrmodule/ClrModule.cs index 62fdf497f..eca411b30 100644 --- a/src/clrmodule/ClrModule.cs +++ b/src/clrmodule/ClrModule.cs @@ -1,5 +1,5 @@ -//============================================================================ -// This file replaces the hand-maintained stub that used to implement clr.dll. +//============================================================================ +// This file replaces the hand-maintained stub that used to implement clr.dll. // This is a line-by-line port from IL back to C#. // We now use RGiesecke.DllExport on the required static init method so it can be // loaded by a standard CPython interpreter as an extension module. When it @@ -11,31 +11,34 @@ // If defined, the "pythonRuntimeVersionString" variable must be set to // Python.Runtime's current version. - #define USE_PYTHON_RUNTIME_VERSION // If defined, the "PythonRuntimePublicKeyTokenData" data array must be // set to Python.Runtime's public key token. (sn -T Python.Runtin.dll) #define USE_PYTHON_RUNTIME_PUBLIC_KEY_TOKEN -// If DEBUG_PRINT is defined in the Build Properties, a few System.Console.WriteLine +// If DEBUG is defined in the Build Properties, a few Console.WriteLine // calls are made to indicate what's going on during the load... //============================================================================ using System; - +using System.Globalization; +using System.IO; +using System.Reflection; +using System.Runtime.InteropServices; +using RGiesecke.DllExport; public class clrModule { -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) - [RGiesecke.DllExport.DllExport("PyInit_clr", System.Runtime.InteropServices.CallingConvention.StdCall)] +#if PYTHON3 + [DllExport("PyInit_clr", CallingConvention.StdCall)] public static IntPtr PyInit_clr() -#else - [RGiesecke.DllExport.DllExport("initclr", System.Runtime.InteropServices.CallingConvention.StdCall)] +#elif PYTHON2 + [DllExport("initclr", CallingConvention.StdCall)] public static void initclr() #endif { -#if DEBUG_PRINT - System.Console.WriteLine("Attempting to load Python.Runtime using standard binding rules... "); +#if DEBUG + Console.WriteLine("Attempting to load Python.Runtime using standard binding rules... "); #endif #if USE_PYTHON_RUNTIME_PUBLIC_KEY_TOKEN var pythonRuntimePublicKeyTokenData = new byte[] { 0x50, 0x00, 0xfe, 0xa6, 0xcb, 0xa7, 0x02, 0xdd }; @@ -47,26 +50,26 @@ public static void initclr() // - ApplicationBase // - A PrivateBinPath under ApplicationBase // With an unsigned assembly, the GAC is skipped. - var pythonRuntimeName = new System.Reflection.AssemblyName("Python.Runtime") + var pythonRuntimeName = new AssemblyName("Python.Runtime") { #if USE_PYTHON_RUNTIME_VERSION - Version = new System.Version("4.0.0.1"), + Version = new Version("4.0.0.1"), #endif - CultureInfo = System.Globalization.CultureInfo.InvariantCulture, + CultureInfo = CultureInfo.InvariantCulture }; #if USE_PYTHON_RUNTIME_PUBLIC_KEY_TOKEN pythonRuntimeName.SetPublicKeyToken(pythonRuntimePublicKeyTokenData); #endif // We've got the AssemblyName with optional features; try to load it. - System.Reflection.Assembly pythonRuntime; + Assembly pythonRuntime; try { - pythonRuntime = System.Reflection.Assembly.Load(pythonRuntimeName); -#if DEBUG_PRINT - System.Console.WriteLine("Success!"); + pythonRuntime = Assembly.Load(pythonRuntimeName); +#if DEBUG + Console.WriteLine("Success!"); #endif } - catch (System.IO.IOException) + catch (IOException) { try { @@ -79,24 +82,26 @@ public static void initclr() // http://blogs.msdn.com/suzcook/archive/2003/05/29/57143.aspx // http://blogs.msdn.com/suzcook/archive/2003/06/13/57180.aspx - var executingAssembly = System.Reflection.Assembly.GetExecutingAssembly(); - var assemblyDirectory = System.IO.Path.GetDirectoryName(executingAssembly.Location); + Assembly executingAssembly = Assembly.GetExecutingAssembly(); + string assemblyDirectory = Path.GetDirectoryName(executingAssembly.Location); if (assemblyDirectory == null) - throw new System.InvalidOperationException(executingAssembly.Location); - var pythonRuntimeDllPath = System.IO.Path.Combine(assemblyDirectory, "Python.Runtime.dll"); -#if DEBUG_PRINT - System.Console.WriteLine("Attempting to load Python.Runtime from: '{0}'...", pythonRuntimeDllPath); + { + throw new InvalidOperationException(executingAssembly.Location); + } + string pythonRuntimeDllPath = Path.Combine(assemblyDirectory, "Python.Runtime.dll"); +#if DEBUG + Console.WriteLine("Attempting to load Python.Runtime from: '{0}'...", pythonRuntimeDllPath); #endif - pythonRuntime = System.Reflection.Assembly.LoadFrom(pythonRuntimeDllPath); + pythonRuntime = Assembly.LoadFrom(pythonRuntimeDllPath); } - catch (System.InvalidOperationException) + catch (InvalidOperationException) { -#if DEBUG_PRINT - System.Console.WriteLine("Could not load Python.Runtime, so sad."); +#if DEBUG + Console.WriteLine("Could not load Python.Runtime"); #endif -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON3 return IntPtr.Zero; -#else +#elif PYTHON2 return; #endif } @@ -104,12 +109,12 @@ public static void initclr() // Once here, we've successfully loaded SOME version of Python.Runtime // So now we get the PythonEngine and execute the InitExt method on it. - var pythonEngineType = pythonRuntime.GetType("Python.Runtime.PythonEngine"); + Type pythonEngineType = pythonRuntime.GetType("Python.Runtime.PythonEngine"); -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) - return (IntPtr)pythonEngineType.InvokeMember("InitExt", System.Reflection.BindingFlags.InvokeMethod, null, null, null); -#else - pythonEngineType.InvokeMember("InitExt", System.Reflection.BindingFlags.InvokeMethod, null, null, null); +#if PYTHON3 + return (IntPtr)pythonEngineType.InvokeMember("InitExt", BindingFlags.InvokeMethod, null, null, null); +#elif PYTHON2 + pythonEngineType.InvokeMember("InitExt", BindingFlags.InvokeMethod, null, null, null); #endif } -} \ No newline at end of file +} diff --git a/src/clrmodule/clrmodule.csproj b/src/clrmodule/clrmodule.csproj index a062d3bf2..d19646778 100644 --- a/src/clrmodule/clrmodule.csproj +++ b/src/clrmodule/clrmodule.csproj @@ -1,135 +1,130 @@ - - - - Debug - x86 - 8.0.30703 - 2.0 - {86E834DE-1139-4511-96CC-69636A56E7AC} - Library - Properties - clrmodule - clrmodule - v4.0 - 512 - ..\..\ - $(SolutionDir) - true - - - true - bin\x86\DebugMono\ - DEBUG;TRACE - full - x86 - prompt - true - true - false - - - true - bin\x64\DebugMono\ - DEBUG;TRACE - full - x64 - prompt - true - true - false - - - bin\x86\ReleaseMono\ - - - true - pdbonly - x86 - prompt - true - true - false - - - bin\x64\ReleaseMono\ - - - true - pdbonly - x64 - prompt - true - true - false - - - true - bin\x86\DebugWin\ - TRACE;DEBUG;DEBUG_PRINT - full - x86 - prompt - true - false - false - - - true - bin\x64\DebugWin\ - DEBUG;TRACE - full - x64 - prompt - true - true - false - - - bin\x86\ReleaseWin\ - - - true - pdbonly - x86 - prompt - true - true - false - - - bin\x64\ReleaseWin\ - - - true - pdbonly - x64 - prompt - true - true - false - - - - ..\..\packages\UnmanagedExports.1.2.7\lib\net\RGiesecke.DllExport.Metadata.dll - False - - - - - - - - - - - - - $(TargetPath) - $(TargetDir)$(TargetName).pdb - - - - - - - \ No newline at end of file + + + + Debug + x86 + 8.0.30703 + 2.0 + {86E834DE-1139-4511-96CC-69636A56E7AC} + Library + clrmodule + clrmodule + v4.0 + 512 + ..\..\ + $(SolutionDir) + true + + + true + bin\x86\DebugMono\ + TRACE;DEBUG;PYTHON2 + full + x86 + prompt + true + true + false + + + true + bin\x64\DebugMono\ + TRACE;DEBUG;PYTHON2 + full + x64 + prompt + true + true + false + + + bin\x86\ReleaseMono\ + PYTHON2 + true + pdbonly + x86 + prompt + true + true + false + + + bin\x64\ReleaseMono\ + PYTHON2 + true + pdbonly + x64 + prompt + true + true + false + + + true + bin\x86\DebugWin\ + TRACE;DEBUG;PYTHON2 + full + x86 + prompt + true + false + false + + + true + bin\x64\DebugWin\ + TRACE;DEBUG;PYTHON2 + full + x64 + prompt + true + true + false + + + bin\x86\ReleaseWin\ + PYTHON2 + true + pdbonly + x86 + prompt + true + true + false + + + bin\x64\ReleaseWin\ + PYTHON2 + true + pdbonly + x64 + prompt + true + true + false + + + + ..\..\packages\UnmanagedExports.1.2.7\lib\net\RGiesecke.DllExport.Metadata.dll + False + + + + + + + + + + + + + $(TargetPath) + $(TargetDir)$(TargetName).pdb + + + + + + + diff --git a/src/clrmodule/packages.config b/src/clrmodule/packages.config index 03814de1e..01dd53f14 100644 --- a/src/clrmodule/packages.config +++ b/src/clrmodule/packages.config @@ -1,4 +1,4 @@ - + diff --git a/src/console/Console.csproj b/src/console/Console.csproj index 77406e6c5..d2d396341 100644 --- a/src/console/Console.csproj +++ b/src/console/Console.csproj @@ -1,4 +1,4 @@ - + Debug @@ -196,7 +196,7 @@ - Python.Runtime.dll + Python.Runtime.dll @@ -215,4 +215,4 @@ - \ No newline at end of file + diff --git a/src/console/Console.mdp b/src/console/Console.mdp deleted file mode 100644 index 45c23241d..000000000 --- a/src/console/Console.mdp +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/console/assemblyinfo.cs b/src/console/assemblyinfo.cs index 51a280e7a..c7d957326 100644 --- a/src/console/assemblyinfo.cs +++ b/src/console/assemblyinfo.cs @@ -1,18 +1,18 @@ using System; using System.Reflection; -using System.Security.Permissions; -using System.Runtime.InteropServices; using System.Resources; +using System.Runtime.InteropServices; +using System.Security.Permissions; -[assembly: System.Reflection.AssemblyProduct("Python for .NET")] -[assembly: System.Reflection.AssemblyVersion("2.4.2.7")] -[assembly: AssemblyTitleAttribute("Python Console")] -[assembly: AssemblyDefaultAliasAttribute("python.exe")] +[assembly: AssemblyProduct("Python for .NET")] +[assembly: AssemblyVersion("2.4.2.7")] +[assembly: AssemblyTitle("Python Console")] +[assembly: AssemblyDefaultAlias("python.exe")] [assembly: CLSCompliant(true)] [assembly: ComVisible(false)] -[assembly: PermissionSetAttribute(SecurityAction.RequestMinimum, +[assembly: PermissionSet(SecurityAction.RequestMinimum, Name = "FullTrust")] -[assembly: AssemblyDescriptionAttribute("")] -[assembly: AssemblyCopyrightAttribute("Zope Public License, Version 2.0 (ZPL)")] -[assembly: AssemblyFileVersionAttribute("2.0.0.4")] -[assembly: NeutralResourcesLanguageAttribute("en")] \ No newline at end of file +[assembly: AssemblyDescription("")] +[assembly: AssemblyCopyright("MIT License")] +[assembly: AssemblyFileVersion("2.0.0.4")] +[assembly: NeutralResourcesLanguage("en")] diff --git a/src/console/pythonconsole.cs b/src/console/pythonconsole.cs index c97c0943b..a696f62f6 100644 --- a/src/console/pythonconsole.cs +++ b/src/console/pythonconsole.cs @@ -1,12 +1,14 @@ using System; -using System.Reflection; using System.Collections.Generic; +using System.Reflection; using Python.Runtime; namespace Python.Runtime { public sealed class PythonConsole { + private static AssemblyLoader assemblyLoader = new AssemblyLoader(); + private PythonConsole() { } @@ -26,7 +28,7 @@ public static int Main(string[] args) return i; } - // Register a callback function to load embedded assmeblies. + // Register a callback function to load embedded assemblies. // (Python.Runtime.dll is included as a resource) private sealed class AssemblyLoader { @@ -39,7 +41,7 @@ public AssemblyLoader() AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => { string shortName = args.Name.Split(',')[0]; - String resourceName = shortName + ".dll"; + string resourceName = string.Format("{0}.dll", shortName); if (loadedAssemblies.ContainsKey(resourceName)) { @@ -51,7 +53,7 @@ public AssemblyLoader() { if (stream != null) { - Byte[] assemblyData = new Byte[stream.Length]; + var assemblyData = new byte[stream.Length]; stream.Read(assemblyData, 0, assemblyData.Length); Assembly assembly = Assembly.Load(assemblyData); loadedAssemblies[resourceName] = assembly; @@ -62,8 +64,6 @@ public AssemblyLoader() return null; }; } - }; - - private static AssemblyLoader assemblyLoader = new AssemblyLoader(); - }; -} \ No newline at end of file + } + } +} diff --git a/src/console/sourceforge-logo.png b/src/console/sourceforge-logo.png deleted file mode 100644 index 14c4143cc..000000000 Binary files a/src/console/sourceforge-logo.png and /dev/null differ diff --git a/src/embed_tests/Embeddingtest.VisualState.xml b/src/embed_tests/Embeddingtest.VisualState.xml deleted file mode 100644 index 4909bca42..000000000 --- a/src/embed_tests/Embeddingtest.VisualState.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - [0-1000]C:\Users\Barton\Documents\Visual Studio 2008\Projects\PySharp\trunk\pythonnet\src\embed_tests\Embeddingtest.nunit - [0-1003]Python.EmbeddingTest.PyImportTest - false - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/embed_tests/Embeddingtest.nunit b/src/embed_tests/Embeddingtest.nunit deleted file mode 100644 index ab4a73f4e..000000000 --- a/src/embed_tests/Embeddingtest.nunit +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/src/embed_tests/Python.EmbeddingTest.csproj b/src/embed_tests/Python.EmbeddingTest.csproj index 80a4a9820..24645f1bd 100644 --- a/src/embed_tests/Python.EmbeddingTest.csproj +++ b/src/embed_tests/Python.EmbeddingTest.csproj @@ -1,4 +1,4 @@ - + Debug @@ -138,7 +138,7 @@ - + @@ -184,4 +184,4 @@ - \ No newline at end of file + diff --git a/src/embed_tests/packages.config b/src/embed_tests/packages.config index 163c6c929..fdc687a35 100644 --- a/src/embed_tests/packages.config +++ b/src/embed_tests/packages.config @@ -1,5 +1,5 @@ - + - \ No newline at end of file + diff --git a/src/monoclr/clrmod.c b/src/monoclr/clrmod.c index 30a093ce6..4e8027e3a 100644 --- a/src/monoclr/clrmod.c +++ b/src/monoclr/clrmod.c @@ -1,20 +1,18 @@ -// Author: Christian Heimes - #include "pynetclr.h" /* List of functions defined in the module */ static PyMethodDef clr_methods[] = { - {NULL, NULL, 0, NULL} /* Sentinel */ + {NULL, NULL, 0, NULL} /* Sentinel */ }; PyDoc_STRVAR(clr_module_doc, -"clr facade module to initialize the CLR. It's later " -"replaced by the real clr module. This module has a facade " -"attribute to make it distinguishable from the real clr module." + "clr facade module to initialize the CLR. It's later " + "replaced by the real clr module. This module has a facade " + "attribute to make it distinguishable from the real clr module." ); static PyNet_Args *pn_args; -char** environ = NULL; +char **environ = NULL; #if PY_MAJOR_VERSION >= 3 static struct PyModuleDef clrdef = { @@ -30,7 +28,8 @@ static struct PyModuleDef clrdef = { }; #endif -static PyObject *_initclr() { +static PyObject *_initclr() +{ PyObject *m; /* Create the module and add the functions */ @@ -45,7 +44,8 @@ static PyObject *_initclr() { Py_INCREF(Py_True); pn_args = PyNet_Init(1); - if (pn_args->error) { + if (pn_args->error) + { return NULL; } @@ -57,12 +57,14 @@ static PyObject *_initclr() { #if PY_MAJOR_VERSION >= 3 PyMODINIT_FUNC -PyInit_clr(void) { +PyInit_clr(void) +{ return _initclr(); } #else PyMODINIT_FUNC -initclr(void) { +initclr(void) +{ _initclr(); } #endif diff --git a/src/monoclr/pynetclr.h b/src/monoclr/pynetclr.h index fe0d81190..c5e181156 100644 --- a/src/monoclr/pynetclr.h +++ b/src/monoclr/pynetclr.h @@ -1,5 +1,3 @@ -// Author: Christian Heimes - #ifndef PYNET_CLR_H #define PYNET_CLR_H @@ -15,7 +13,8 @@ #define MONO_DOMAIN "Python.Runtime" #define PR_ASSEMBLY "Python.Runtime.dll" -typedef struct { +typedef struct +{ MonoDomain *domain; MonoAssembly *pr_assm; MonoMethod *shutdown; @@ -23,12 +22,12 @@ typedef struct { char *error; char *init_name; char *shutdown_name; - PyObject* module; + PyObject *module; } PyNet_Args; -PyNet_Args* PyNet_Init(int); -void PyNet_Finalize(PyNet_Args*); +PyNet_Args *PyNet_Init(int); +void PyNet_Finalize(PyNet_Args *); void main_thread_handler(gpointer user_data); -char* PyNet_ExceptionToString(MonoObject *); +char *PyNet_ExceptionToString(MonoObject *); #endif // PYNET_CLR_H diff --git a/src/monoclr/pynetinit.c b/src/monoclr/pynetinit.c index 547c6dcd5..ed09d45d7 100644 --- a/src/monoclr/pynetinit.c +++ b/src/monoclr/pynetinit.c @@ -1,5 +1,3 @@ -// Author: Christian Heimes - #include "pynetclr.h" #include "stdlib.h" @@ -12,7 +10,8 @@ // initialize Mono and PythonNet -PyNet_Args* PyNet_Init(int ext) { +PyNet_Args *PyNet_Init(int ext) +{ PyNet_Args *pn_args; pn_args = (PyNet_Args *)malloc(sizeof(PyNet_Args)); pn_args->pr_file = PR_ASSEMBLY; @@ -20,9 +19,12 @@ PyNet_Args* PyNet_Init(int ext) { pn_args->shutdown = NULL; pn_args->module = NULL; - if (ext == 0) { + if (ext == 0) + { pn_args->init_name = "Python.Runtime:Initialize()"; - } else { + } + else + { pn_args->init_name = "Python.Runtime:InitExt()"; } pn_args->shutdown_name = "Python.Runtime:Shutdown()"; @@ -47,32 +49,38 @@ PyNet_Args* PyNet_Init(int ext) { main_thread_handler(pn_args); - if (pn_args->error != NULL) { + if (pn_args->error != NULL) + { PyErr_SetString(PyExc_ImportError, pn_args->error); } return pn_args; } // Shuts down PythonNet and cleans up Mono -void PyNet_Finalize(PyNet_Args *pn_args) { +void PyNet_Finalize(PyNet_Args *pn_args) +{ MonoObject *exception = NULL; - if (pn_args->shutdown) { + if (pn_args->shutdown) + { mono_runtime_invoke(pn_args->shutdown, NULL, NULL, &exception); - if (exception) { + if (exception) + { pn_args->error = PyNet_ExceptionToString(exception); } pn_args->shutdown = NULL; } - if (pn_args->domain) { + if (pn_args->domain) + { mono_jit_cleanup(pn_args->domain); pn_args->domain = NULL; } free(pn_args); } -MonoMethod *getMethodFromClass(MonoClass *cls, char *name) { +MonoMethod *getMethodFromClass(MonoClass *cls, char *name) +{ MonoMethodDesc *mdesc; MonoMethod *method; @@ -83,8 +91,9 @@ MonoMethod *getMethodFromClass(MonoClass *cls, char *name) { return method; } -void main_thread_handler (gpointer user_data) { - PyNet_Args *pn_args=(PyNet_Args *)user_data; +void main_thread_handler(gpointer user_data) +{ + PyNet_Args *pn_args = (PyNet_Args *)user_data; MonoMethod *init; MonoImage *pr_image; MonoClass *pythonengine; @@ -95,15 +104,19 @@ void main_thread_handler (gpointer user_data) { // Get the filename of the python shared object and set // LD_LIBRARY_PATH so Mono can find it. Dl_info dlinfo = {0}; - if (0 != dladdr(&Py_Initialize, &dlinfo)) { - char* fname = alloca(strlen(dlinfo.dli_fname) + 1); + if (0 != dladdr(&Py_Initialize, &dlinfo)) + { + char *fname = alloca(strlen(dlinfo.dli_fname) + 1); strcpy(fname, dlinfo.dli_fname); - char* py_libdir = dirname(fname); - char* ld_library_path = getenv("LD_LIBRARY_PATH"); - if (NULL == ld_library_path) { + char *py_libdir = dirname(fname); + char *ld_library_path = getenv("LD_LIBRARY_PATH"); + if (NULL == ld_library_path) + { setenv("LD_LIBRARY_PATH", py_libdir, 1); - } else { - char* new_ld_library_path = alloca(strlen(py_libdir) + } + else + { + char *new_ld_library_path = alloca(strlen(py_libdir) + strlen(ld_library_path) + 2); strcpy(new_ld_library_path, py_libdir); @@ -114,25 +127,26 @@ void main_thread_handler (gpointer user_data) { } //get python path system variable - PyObject* syspath = PySys_GetObject("path"); - char* runtime_full_path = (char*) malloc(1024); - const char* slash = "/"; + PyObject *syspath = PySys_GetObject("path"); + char *runtime_full_path = (char*) malloc(1024); + const char *slash = "/"; int found = 0; int ii = 0; - for (ii = 0; ii < PyList_Size(syspath); ++ii) { + for (ii = 0; ii < PyList_Size(syspath); ++ii) + { #if PY_MAJOR_VERSION > 2 Py_ssize_t wlen; wchar_t *wstr = PyUnicode_AsWideCharString(PyList_GetItem(syspath, ii), &wlen); - char* pydir = (char*)malloc(wlen + 1); + char *pydir = (char*)malloc(wlen + 1); size_t mblen = wcstombs(pydir, wstr, wlen + 1); if (mblen > wlen) pydir[wlen] = '\0'; PyMem_Free(wstr); #else - const char* pydir = PyString_AsString(PyList_GetItem(syspath, ii)); + const char *pydir = PyString_AsString(PyList_GetItem(syspath, ii)); #endif - char* curdir = (char*) malloc(1024); + char *curdir = (char*) malloc(1024); strncpy(curdir, strlen(pydir) > 0 ? pydir : ".", 1024); strncat(curdir, slash, 1024); @@ -141,12 +155,14 @@ void main_thread_handler (gpointer user_data) { #endif //look in this directory for the pn_args->pr_file - DIR* dirp = opendir(curdir); - if (dirp != NULL) { - + DIR *dirp = opendir(curdir); + if (dirp != NULL) + { struct dirent *dp; - while ((dp = readdir(dirp)) != NULL) { - if (strcmp(dp->d_name, pn_args->pr_file) == 0) { + while ((dp = readdir(dirp)) != NULL) + { + if (strcmp(dp->d_name, pn_args->pr_file) == 0) + { strcpy(runtime_full_path, curdir); strcat(runtime_full_path, pn_args->pr_file); found = 1; @@ -157,21 +173,23 @@ void main_thread_handler (gpointer user_data) { } free(curdir); - if (found) { + if (found) + { pn_args->pr_file = runtime_full_path; break; } } - if (!found) { + if (!found) + { fprintf(stderr, "Could not find assembly %s. \n", pn_args->pr_file); return; } #endif - pn_args->pr_assm = mono_domain_assembly_open(pn_args->domain, pn_args->pr_file); - if (!pn_args->pr_assm) { + if (!pn_args->pr_assm) + { pn_args->error = "Unable to load assembly"; return; } @@ -180,31 +198,36 @@ void main_thread_handler (gpointer user_data) { #endif pr_image = mono_assembly_get_image(pn_args->pr_assm); - if (!pr_image) { + if (!pr_image) + { pn_args->error = "Unable to get image"; return; } pythonengine = mono_class_from_name(pr_image, "Python.Runtime", "PythonEngine"); - if (!pythonengine) { + if (!pythonengine) + { pn_args->error = "Unable to load class PythonEngine from Python.Runtime"; return; } init = getMethodFromClass(pythonengine, pn_args->init_name); - if (!init) { + if (!init) + { pn_args->error = "Unable to fetch Init method from PythonEngine"; return; } pn_args->shutdown = getMethodFromClass(pythonengine, pn_args->shutdown_name); - if (!pn_args->shutdown) { + if (!pn_args->shutdown) + { pn_args->error = "Unable to fetch shutdown method from PythonEngine"; return; } init_result = mono_runtime_invoke(init, NULL, NULL, &exception); - if (exception) { + if (exception) + { pn_args->error = PyNet_ExceptionToString(exception); return; } @@ -213,17 +236,17 @@ void main_thread_handler (gpointer user_data) { if (NULL != init_result) pn_args->module = *(PyObject**)mono_object_unbox(init_result); #endif - } // Get string from a Mono exception -char* PyNet_ExceptionToString(MonoObject *e) { - MonoMethodDesc* mdesc = mono_method_desc_new(":ToString()", FALSE); - MonoMethod* mmethod = mono_method_desc_search_in_class(mdesc, mono_get_object_class()); +char *PyNet_ExceptionToString(MonoObject *e) +{ + MonoMethodDesc *mdesc = mono_method_desc_new(":ToString()", FALSE); + MonoMethod *mmethod = mono_method_desc_search_in_class(mdesc, mono_get_object_class()); mono_method_desc_free(mdesc); mmethod = mono_object_get_virtual_method(e, mmethod); - MonoString* monoString = (MonoString*) mono_runtime_invoke(mmethod, e, NULL, NULL); + MonoString *monoString = (MonoString*) mono_runtime_invoke(mmethod, e, NULL, NULL); mono_runtime_invoke(mmethod, e, NULL, NULL); return mono_string_to_utf8(monoString); } diff --git a/src/runtime/Python.Runtime.csproj b/src/runtime/Python.Runtime.csproj index 1e54d2742..81616448c 100644 --- a/src/runtime/Python.Runtime.csproj +++ b/src/runtime/Python.Runtime.csproj @@ -1,212 +1,211 @@ - - - - Debug - x86 - {097B4AC0-74E9-4C58-BCF8-C69746EC8271} - Library - false - Python.Runtime - Python.Runtime - ..\..\ - $(SolutionDir) - - - bin\x86\ReleaseMono\ - PYTHON27, UCS4 - true - true - pdbonly - x86 - false - true - PYTHON27,UCS2 - - - bin\x64\ReleaseMono\ - PYTHON27, UCS4 - true - true - pdbonly - x64 - false - true - - - bin\x86\ReleaseWin\ - PYTHON27, UCS2 - true - true - pdbonly - x86 - false - true - - - bin\x64\ReleaseWin\ - PYTHON27, UCS2 - true - true - pdbonly - x64 - false - true - - - true - bin\x86\DebugMono\ - TRACE;DEBUG;PYTHON27,UCS4 - true - false - full - x86 - false - false - false - - - true - bin\x64\DebugMono\ - TRACE;DEBUG;PYTHON27,UCS4 - true - false - full - x64 - - - true - bin\x86\DebugWin\ - TRACE;DEBUG;PYTHON27,UCS2 - true - false - full - x86 - false - false - false - - - true - bin\x64\DebugWin\ - TRACE;DEBUG;PYTHON27,UCS2 - true - false - full - x64 - - - - - - False - ..\..\packages\MonoGAC\Mono.Posix\4.0.0.0__0738eb9f132ed756\Mono.Posix.dll - - - - - - - False - ..\..\packages\MonoGAC\Mono.Posix\4.0.0.0__0738eb9f132ed756\Mono.Posix.dll - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - clr.py - - - - - - - - $(TargetPath) - $(TargetDir)$(TargetName).pdb - - - - - - \ No newline at end of file + + + + Debug + x86 + {097B4AC0-74E9-4C58-BCF8-C69746EC8271} + Library + false + Python.Runtime + Python.Runtime + ..\..\ + $(SolutionDir) + + + bin\x86\ReleaseMono\ + PYTHON2;PYTHON27;UCS4 + true + true + pdbonly + x86 + false + true + + + bin\x64\ReleaseMono\ + PYTHON2;PYTHON27;UCS4 + true + true + pdbonly + x64 + false + true + + + bin\x86\ReleaseWin\ + PYTHON2;PYTHON27;UCS2 + true + true + pdbonly + x86 + false + true + + + bin\x64\ReleaseWin\ + PYTHON2;PYTHON27;UCS2 + true + true + pdbonly + x64 + false + true + + + true + bin\x86\DebugMono\ + TRACE;DEBUG;PYTHON2;PYTHON27;UCS4 + true + false + full + x86 + false + false + false + + + true + bin\x64\DebugMono\ + TRACE;DEBUG;PYTHON2;PYTHON27;UCS4 + true + false + full + x64 + + + true + bin\x86\DebugWin\ + TRACE;DEBUG;PYTHON2;PYTHON27;UCS2 + true + false + full + x86 + false + false + false + + + true + bin\x64\DebugWin\ + TRACE;DEBUG;PYTHON2;PYTHON27;UCS2 + true + false + full + x64 + + + + + + False + ..\..\packages\MonoGAC\Mono.Posix\4.0.0.0__0738eb9f132ed756\Mono.Posix.dll + + + + + + + False + ..\..\packages\MonoGAC\Mono.Posix\4.0.0.0__0738eb9f132ed756\Mono.Posix.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + clr.py + + + + + + + + $(TargetPath) + $(TargetDir)$(TargetName).pdb + + + + + + diff --git a/src/runtime/Python.Runtime.mdp b/src/runtime/Python.Runtime.mdp deleted file mode 100644 index 845407ec2..000000000 --- a/src/runtime/Python.Runtime.mdp +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/runtime/assemblyinfo.cs b/src/runtime/assemblyinfo.cs index 609ba342a..49433f0dc 100644 --- a/src/runtime/assemblyinfo.cs +++ b/src/runtime/assemblyinfo.cs @@ -1,35 +1,34 @@ using System; using System.Reflection; -using System.Runtime.InteropServices; using System.Resources; +using System.Runtime.InteropServices; [assembly: AssemblyProduct("Python for .NET")] [assembly: AssemblyVersion("4.0.0.1")] -[assembly: AssemblyDefaultAliasAttribute("Python.Runtime.dll")] +[assembly: AssemblyDefaultAlias("Python.Runtime.dll")] [assembly: CLSCompliant(true)] [assembly: ComVisible(false)] -[assembly: AssemblyCopyrightAttribute("Zope Public License, Version 2.0 (ZPL)")] -[assembly: AssemblyFileVersionAttribute("2.0.0.2")] -[assembly: NeutralResourcesLanguageAttribute("en")] +[assembly: AssemblyCopyright("MIT License")] +[assembly: AssemblyFileVersion("2.0.0.2")] +[assembly: NeutralResourcesLanguage("en")] -#if (PYTHON23) -[assembly: AssemblyTitleAttribute("Python.Runtime for Python 2.3")] -[assembly: AssemblyDescriptionAttribute("Python Runtime for Python 2.3")] +#if PYTHON27 +[assembly: AssemblyTitle("Python.Runtime for Python 2.7")] +[assembly: AssemblyDescription("Python Runtime for Python 2.7")] #endif -#if (PYTHON24) -[assembly: AssemblyTitleAttribute("Python.Runtime for Python 2.4")] -[assembly: AssemblyDescriptionAttribute("Python Runtime for Python 2.4")] +#if PYTHON33 +[assembly: AssemblyTitle("Python.Runtime for Python 3.3")] +[assembly: AssemblyDescription("Python Runtime for Python 3.3")] #endif -#if (PYTHON25) -[assembly: AssemblyTitleAttribute("Python.Runtime for Python 2.5")] -[assembly: AssemblyDescriptionAttribute("Python Runtime for Python 2.5")] +#if PYTHON34 +[assembly: AssemblyTitle("Python.Runtime for Python 3.4")] +[assembly: AssemblyDescription("Python Runtime for Python 3.4")] #endif -#if (PYTHON26) -[assembly: AssemblyTitleAttribute("Python.Runtime for Python 2.6")] -[assembly: AssemblyDescriptionAttribute("Python Runtime for Python 2.6")] +#if PYTHON35 +[assembly: AssemblyTitle("Python.Runtime for Python 3.5")] +[assembly: AssemblyDescription("Python Runtime for Python 3.5")] +#endif +#if PYTHON36 +[assembly: AssemblyTitle("Python.Runtime for Python 3.6")] +[assembly: AssemblyDescription("Python Runtime for Python 3.6")] #endif -#if (PYTHON27) - -[assembly: AssemblyTitle("Python.Runtime for Python 2.7")] -[assembly: AssemblyDescription("Python Runtime for Python 2.7")] -#endif \ No newline at end of file diff --git a/src/runtime/assemblymanager.cs b/src/runtime/assemblymanager.cs index a791b8195..5d9759375 100644 --- a/src/runtime/assemblymanager.cs +++ b/src/runtime/assemblymanager.cs @@ -1,11 +1,11 @@ using System; -using System.IO; using System.Collections; -using System.Collections.Specialized; +using System.IO; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; -using System.Reflection.Emit; +using System.Threading; namespace Python.Runtime { @@ -15,12 +15,16 @@ namespace Python.Runtime /// internal class AssemblyManager { - static Dictionary> namespaces; + // modified from event handlers below, potentially triggered from different .NET threads + // therefore this should be a ConcurrentDictionary + static ConcurrentDictionary> namespaces; //static Dictionary> generics; static AssemblyLoadEventHandler lhandler; static ResolveEventHandler rhandler; + // updated only under GIL? static Dictionary probed; - static List assemblies; + // modified from event handlers below, potentially triggered from different .NET threads + static AssemblyList assemblies; internal static List pypath; private AssemblyManager() @@ -36,10 +40,10 @@ private AssemblyManager() internal static void Initialize() { namespaces = new - Dictionary>(32); + ConcurrentDictionary>(); probed = new Dictionary(32); //generics = new Dictionary>(); - assemblies = new List(16); + assemblies = new AssemblyList(16); pypath = new List(16); AppDomain domain = AppDomain.CurrentDomain; @@ -105,9 +109,8 @@ static void AssemblyLoadHandler(Object ob, AssemblyLoadEventArgs args) static Assembly ResolveHandler(Object ob, ResolveEventArgs args) { string name = args.Name.ToLower(); - for (int i = 0; i < assemblies.Count; i++) + foreach (Assembly a in assemblies) { - Assembly a = (Assembly)assemblies[i]; string full = a.FullName.ToLower(); if (full.StartsWith(name)) { @@ -266,9 +269,8 @@ public static Assembly LoadAssemblyFullPath(string name) public static Assembly FindLoadedAssembly(string name) { - for (int i = 0; i < assemblies.Count; i++) + foreach (Assembly a in assemblies) { - Assembly a = (Assembly)assemblies[i]; if (a.GetName().Name == name) { return a; @@ -295,15 +297,15 @@ public static bool LoadImplicit(string name, bool warn = true) bool loaded = false; string s = ""; Assembly lastAssembly = null; - HashSet assemblies = null; + HashSet assembliesSet = null; for (int i = 0; i < names.Length; i++) { s = (i == 0) ? names[0] : s + "." + names[i]; if (!probed.ContainsKey(s)) { - if (assemblies == null) + if (assembliesSet == null) { - assemblies = new HashSet(AppDomain.CurrentDomain.GetAssemblies()); + assembliesSet = new HashSet(AppDomain.CurrentDomain.GetAssemblies()); } Assembly a = FindLoadedAssembly(s); if (a == null) @@ -314,7 +316,7 @@ public static bool LoadImplicit(string name, bool warn = true) { a = LoadAssembly(s); } - if (a != null && !assemblies.Contains(a)) + if (a != null && !assembliesSet.Contains(a)) { loaded = true; lastAssembly = a; @@ -362,16 +364,13 @@ internal static void ScanAssembly(Assembly assembly) for (int n = 0; n < names.Length; n++) { s = (n == 0) ? names[0] : s + "." + names[n]; - if (!namespaces.ContainsKey(s)) - { - namespaces.Add(s, new Dictionary()); - } + namespaces.TryAdd(s, new ConcurrentDictionary()); } } - if (ns != null && !namespaces[ns].ContainsKey(assembly)) + if (ns != null) { - namespaces[ns].Add(assembly, String.Empty); + namespaces[ns].TryAdd(assembly, String.Empty); } if (ns != null && t.IsGenericTypeDefinition) @@ -383,14 +382,12 @@ internal static void ScanAssembly(Assembly assembly) public static AssemblyName[] ListAssemblies() { - AssemblyName[] names = new AssemblyName[assemblies.Count]; - Assembly assembly; - for (int i = 0; i < assemblies.Count; i++) + List names = new List(assemblies.Count); + foreach (Assembly assembly in assemblies) { - assembly = assemblies[i]; - names.SetValue(assembly.GetName(), i); + names.Add(assembly.GetName()); } - return names; + return names.ToArray(); } //=================================================================== @@ -471,9 +468,8 @@ public static List GetNames(string nsname) public static Type LookupType(string qname) { - for (int i = 0; i < assemblies.Count; i++) + foreach (Assembly assembly in assemblies) { - Assembly assembly = (Assembly)assemblies[i]; Type type = assembly.GetType(qname); if (type != null) { @@ -482,5 +478,92 @@ public static Type LookupType(string qname) } return null; } + + /// + /// Wrapper around List for thread safe access + /// + private class AssemblyList : IEnumerable{ + private readonly List _list; + private readonly ReaderWriterLockSlim _lock; + + public AssemblyList(int capacity) { + _list = new List(capacity); + _lock = new ReaderWriterLockSlim(); + } + + public int Count + { + get + { + _lock.EnterReadLock(); + try { + return _list.Count; + } + finally { + _lock.ExitReadLock(); + } + } + } + + public void Add(Assembly assembly) { + _lock.EnterWriteLock(); + try + { + _list.Add(assembly); + } + finally + { + _lock.ExitWriteLock(); + } + } + + public IEnumerator GetEnumerator() + { + return ((IEnumerable) this).GetEnumerator(); + } + + /// + /// Enumerator wrapping around 's enumerator. + /// Acquires and releases a read lock on during enumeration + /// + private class Enumerator : IEnumerator + { + private readonly AssemblyList _assemblyList; + + private readonly IEnumerator _listEnumerator; + + public Enumerator(AssemblyList assemblyList) + { + _assemblyList = assemblyList; + _assemblyList._lock.EnterReadLock(); + _listEnumerator = _assemblyList._list.GetEnumerator(); + } + + public void Dispose() + { + _listEnumerator.Dispose(); + _assemblyList._lock.ExitReadLock(); + } + + public bool MoveNext() + { + return _listEnumerator.MoveNext(); + } + + public void Reset() + { + _listEnumerator.Reset(); + } + + public Assembly Current { get { return _listEnumerator.Current; } } + + object IEnumerator.Current { get { return Current; } } + } + + IEnumerator IEnumerable.GetEnumerator() + { + return new Enumerator(this); + } + } } } diff --git a/src/runtime/buildclrmodule.bat b/src/runtime/buildclrmodule.bat deleted file mode 100644 index 549902d7f..000000000 --- a/src/runtime/buildclrmodule.bat +++ /dev/null @@ -1,36 +0,0 @@ -:: Call with buildclrmodule.bat - -@echo off - -set TARGET_PLATFORM=%1 -set INPUT_DIRECTORY=%~2 -set INPUT_PATH="%INPUT_DIRECTORY%\clrmodule.il" -set OUTPUT_PATH=%3 - -if %TARGET_PLATFORM%==x86 goto SETUP32 -if %TARGET_PLATFORM%==x64 goto SETUP64 -goto ERROR_BAD_PLATFORM - -:SETUP32 -set INCLUDE_PATH="%INPUT_DIRECTORY%\x86" -goto BUILD_CLR_MODULE - -:SETUP64 -set INCLUDE_PATH="%INPUT_DIRECTORY%\x64" -set ILASM_EXTRA_ARGS=/pe64 /x64 -goto BUILD_CLR_MODULE - -:ERROR_BAD_PLATFORM -echo Unknown target platform: %TARGET_PLATFORM% -exit /b 1 - -:ERROR_MISSING_INPUT -echo Can't find input file: %INPUT_PATH% -exit /b 1 - -:BUILD_CLR_MODULE -if not exist %INPUT_PATH% goto ERROR_MISSING_INPUT -%windir%\Microsoft.NET\Framework\v4.0.30319\ilasm /nologo /quiet /dll %ILASM_EXTRA_ARGS% /include=%INCLUDE_PATH% /output=%OUTPUT_PATH% %INPUT_PATH% - -::: 2.0 or 3.5 -:::%windir%\Microsoft.NET\Framework\v2.0.50727\ilasm /nologo /quiet /dll %ILASM_EXTRA_ARGS% /include=%INCLUDE_PATH% /output=%OUTPUT_PATH% %INPUT_PATH% diff --git a/src/runtime/classbase.cs b/src/runtime/classbase.cs index 68cc91961..3089465e3 100644 --- a/src/runtime/classbase.cs +++ b/src/runtime/classbase.cs @@ -57,7 +57,7 @@ public virtual IntPtr type_subscript(IntPtr idx) { Type t = target.MakeGenericType(types); ManagedType c = (ManagedType)ClassManager.GetClass(t); - Runtime.Incref(c.pyHandle); + Runtime.XIncref(c.pyHandle); return c.pyHandle; } @@ -67,68 +67,108 @@ public virtual IntPtr type_subscript(IntPtr idx) //==================================================================== // Standard comparison implementation for instances of reflected types. //==================================================================== -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) - public static IntPtr tp_richcompare(IntPtr ob, IntPtr other, int op) { - if (op != Runtime.Py_EQ && op != Runtime.Py_NE) - { - Runtime.Incref(Runtime.PyNotImplemented); - return Runtime.PyNotImplemented; - } - - IntPtr pytrue = Runtime.PyTrue; - IntPtr pyfalse = Runtime.PyFalse; - - // swap true and false for NE - if (op != Runtime.Py_EQ) - { - pytrue = Runtime.PyFalse; - pyfalse = Runtime.PyTrue; - } - - if (ob == other) { - Runtime.Incref(pytrue); - return pytrue; - } - - CLRObject co1 = GetManagedObject(ob) as CLRObject; - CLRObject co2 = GetManagedObject(other) as CLRObject; - if (null == co2) { - Runtime.Incref(pyfalse); - return pyfalse; - } - - Object o1 = co1.inst; - Object o2 = co2.inst; - if (Object.Equals(o1, o2)) { - Runtime.Incref(pytrue); - return pytrue; - } - - Runtime.Incref(pyfalse); - return pyfalse; - } -#else - 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)) + public static IntPtr tp_richcompare(IntPtr ob, IntPtr other, int op) { + CLRObject co1; + CLRObject co2; + switch (op) { - return 0; + case Runtime.Py_EQ: + case Runtime.Py_NE: + IntPtr pytrue = Runtime.PyTrue; + IntPtr pyfalse = Runtime.PyFalse; + + // swap true and false for NE + if (op != Runtime.Py_EQ) + { + pytrue = Runtime.PyFalse; + pyfalse = Runtime.PyTrue; + } + + if (ob == other) + { + Runtime.XIncref(pytrue); + return pytrue; + } + + co1 = GetManagedObject(ob) as CLRObject; + co2 = GetManagedObject(other) as CLRObject; + if (null == co2) + { + Runtime.XIncref(pyfalse); + return pyfalse; + } + + Object o1 = co1.inst; + Object o2 = co2.inst; + + if (Object.Equals(o1, o2)) + { + Runtime.XIncref(pytrue); + return pytrue; + } + + Runtime.XIncref(pyfalse); + return pyfalse; + case Runtime.Py_LT: + case Runtime.Py_LE: + case Runtime.Py_GT: + case Runtime.Py_GE: + co1 = GetManagedObject(ob) as CLRObject; + co2 = GetManagedObject(other) as CLRObject; + if(co1 == null || co2 == null) + return Exceptions.RaiseTypeError("Cannot get managed object"); + var co1Comp = co1.inst as IComparable; + if (co1Comp == null) + return Exceptions.RaiseTypeError("Cannot convert object of type " + co1.GetType() + " to IComparable"); + try + { + var cmp = co1Comp.CompareTo(co2.inst); + + IntPtr pyCmp; + if (cmp < 0) + { + if (op == Runtime.Py_LT || op == Runtime.Py_LE) + { + pyCmp = Runtime.PyTrue; + } + else + { + pyCmp = Runtime.PyFalse; + } + } + else if (cmp == 0) + { + if (op == Runtime.Py_LE || op == Runtime.Py_GE) + { + pyCmp = Runtime.PyTrue; + } + else + { + pyCmp = Runtime.PyFalse; + } + } + else + { + if (op == Runtime.Py_GE || op == Runtime.Py_GT) { + pyCmp = Runtime.PyTrue; + } + else { + pyCmp = Runtime.PyFalse; + } + } + Runtime.XIncref(pyCmp); + return pyCmp; + } + catch (ArgumentException e) + { + return Exceptions.RaiseTypeError(e.Message); + } + default: + Runtime.XIncref(Runtime.PyNotImplemented); + return Runtime.PyNotImplemented; } - return -1; } -#endif - //==================================================================== // Standard iteration support for instances of reflected types. This @@ -237,11 +277,11 @@ public static void tp_dealloc(IntPtr ob) IntPtr dict = Marshal.ReadIntPtr(ob, ObjectOffset.DictOffset(ob)); if (dict != IntPtr.Zero) { - Runtime.Decref(dict); + Runtime.XDecref(dict); } Runtime.PyObject_GC_UnTrack(self.pyHandle); Runtime.PyObject_GC_Del(self.pyHandle); - Runtime.Decref(self.tpHandle); + Runtime.XDecref(self.tpHandle); self.gcHandle.Free(); } } diff --git a/src/runtime/classderived.cs b/src/runtime/classderived.cs index 1fd8e04d1..02d734c26 100644 --- a/src/runtime/classderived.cs +++ b/src/runtime/classderived.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using System.Reflection; using System.Reflection.Emit; @@ -81,7 +81,7 @@ internal static IntPtr ToPython(IPythonDerivedType obj) FieldInfo fi = obj.GetType().GetField("__pyobj__"); CLRObject self = (CLRObject)fi.GetValue(obj); - Runtime.Incref(self.pyHandle); + Runtime.XIncref(self.pyHandle); // when the C# constructor creates the python object it starts as a weak // reference with a reference count of 0. Now we're passing this object @@ -153,7 +153,7 @@ internal static Type CreateDerivedType(string name, HashSet pyProperties = new HashSet(); if (py_dict != IntPtr.Zero && Runtime.PyDict_Check(py_dict)) { - Runtime.Incref(py_dict); + Runtime.XIncref(py_dict); using (PyDict dict = new PyDict(py_dict)) using (PyObject keys = dict.Keys()) { @@ -196,7 +196,7 @@ internal static Type CreateDerivedType(string name, // Add any additional methods and properties explicitly exposed from Python. if (py_dict != IntPtr.Zero && Runtime.PyDict_Check(py_dict)) { - Runtime.Incref(py_dict); + Runtime.XIncref(py_dict); using (PyDict dict = new PyDict(py_dict)) using (PyObject keys = dict.Keys()) { @@ -588,11 +588,11 @@ public static T InvokeMethod(IPythonDerivedType obj, string methodName, strin IntPtr gs = Runtime.PyGILState_Ensure(); try { - Runtime.Incref(self.pyHandle); + Runtime.XIncref(self.pyHandle); PyObject pyself = new PyObject(self.pyHandle); disposeList.Add(pyself); - Runtime.Incref(Runtime.PyNone); + Runtime.XIncref(Runtime.PyNone); PyObject pynone = new PyObject(Runtime.PyNone); disposeList.Add(pynone); @@ -649,11 +649,11 @@ public static void InvokeMethodVoid(IPythonDerivedType obj, string methodName, s IntPtr gs = Runtime.PyGILState_Ensure(); try { - Runtime.Incref(self.pyHandle); + Runtime.XIncref(self.pyHandle); PyObject pyself = new PyObject(self.pyHandle); disposeList.Add(pyself); - Runtime.Incref(Runtime.PyNone); + Runtime.XIncref(Runtime.PyNone); PyObject pynone = new PyObject(Runtime.PyNone); disposeList.Add(pynone); @@ -710,7 +710,7 @@ public static T InvokeGetProperty(IPythonDerivedType obj, string propertyName IntPtr gs = Runtime.PyGILState_Ensure(); try { - Runtime.Incref(self.pyHandle); + Runtime.XIncref(self.pyHandle); using (PyObject pyself = new PyObject(self.pyHandle)) using (PyObject pyvalue = pyself.GetAttr(propertyName)) return (T)pyvalue.AsManagedObject(typeof(T)); @@ -732,7 +732,7 @@ public static void InvokeSetProperty(IPythonDerivedType obj, string propertyN IntPtr gs = Runtime.PyGILState_Ensure(); try { - Runtime.Incref(self.pyHandle); + Runtime.XIncref(self.pyHandle); using (PyObject pyself = new PyObject(self.pyHandle)) using (PyObject pyvalue = new PyObject(Converter.ToPythonImplicit(value))) pyself.SetAttr(propertyName, pyvalue); @@ -766,11 +766,11 @@ public static void InvokeCtor(IPythonDerivedType obj, string origCtorName, Objec FieldInfo fi = obj.GetType().GetField("__pyobj__"); fi.SetValue(obj, self); - Runtime.Incref(self.pyHandle); + Runtime.XIncref(self.pyHandle); PyObject pyself = new PyObject(self.pyHandle); disposeList.Add(pyself); - Runtime.Incref(Runtime.PyNone); + Runtime.XIncref(Runtime.PyNone); PyObject pynone = new PyObject(Runtime.PyNone); disposeList.Add(pynone); @@ -806,7 +806,7 @@ public static void InvokeCtor(IPythonDerivedType obj, string origCtorName, Objec // This doesn't actually destroy the object, it just sets the reference to this object // to be a weak reference and it will be destroyed when the C# object is destroyed. if (null != self) - Runtime.Decref(self.pyHandle); + Runtime.XDecref(self.pyHandle); Runtime.PyGILState_Release(gs); } @@ -848,7 +848,7 @@ public static void Finalize(IPythonDerivedType obj) // python object. IntPtr dict = Marshal.ReadIntPtr(self.pyHandle, ObjectOffset.DictOffset(self.pyHandle)); if (dict != IntPtr.Zero) - Runtime.Decref(dict); + Runtime.XDecref(dict); Runtime.PyObject_GC_Del(self.pyHandle); self.gcHandle.Free(); } @@ -860,4 +860,4 @@ public static void Finalize(IPythonDerivedType obj) }); } } -} \ No newline at end of file +} diff --git a/src/runtime/classmanager.cs b/src/runtime/classmanager.cs index d85dd2daa..52fecf39c 100644 --- a/src/runtime/classmanager.cs +++ b/src/runtime/classmanager.cs @@ -160,7 +160,7 @@ private static void InitClassBase(Type type, ClassBase impl) string docStr = attr.DocString; doc = Runtime.PyString_FromString(docStr); Runtime.PyDict_SetItemString(dict, "__doc__", doc); - Runtime.Decref(doc); + Runtime.XDecref(doc); } ClassObject co = impl as ClassObject; @@ -185,7 +185,7 @@ private static void InitClassBase(Type type, ClassBase impl) { doc = co.GetDocString(); Runtime.PyDict_SetItemString(dict, "__doc__", doc); - Runtime.Decref(doc); + Runtime.XDecref(doc); } } } diff --git a/src/runtime/classobject.cs b/src/runtime/classobject.cs index 7e8232463..bd4702c20 100644 --- a/src/runtime/classobject.cs +++ b/src/runtime/classobject.cs @@ -139,7 +139,7 @@ public override IntPtr type_subscript(IntPtr idx) } Type a = t.MakeArrayType(); ClassBase o = ClassManager.GetClass(a); - Runtime.Incref(o.pyHandle); + Runtime.XIncref(o.pyHandle); return o.pyHandle; } @@ -159,7 +159,7 @@ public override IntPtr type_subscript(IntPtr idx) { GenericType g = ClassManager.GetClass(gtype) as GenericType; return g.type_subscript(idx); - /*Runtime.Incref(g.pyHandle); + /*Runtime.XIncref(g.pyHandle); return g.pyHandle;*/ } return Exceptions.RaiseTypeError("unsubscriptable object"); @@ -194,7 +194,7 @@ public static IntPtr mp_subscript(IntPtr ob, IntPtr idx) if (!Runtime.PyTuple_Check(idx)) { args = Runtime.PyTuple_New(1); - Runtime.Incref(idx); + Runtime.XIncref(idx); Runtime.PyTuple_SetItem(args, 0, idx); free = true; } @@ -209,7 +209,7 @@ public static IntPtr mp_subscript(IntPtr ob, IntPtr idx) { if (free) { - Runtime.Decref(args); + Runtime.XDecref(args); } } return value; @@ -243,7 +243,7 @@ public static int mp_ass_subscript(IntPtr ob, IntPtr idx, IntPtr v) if (!Runtime.PyTuple_Check(idx)) { args = Runtime.PyTuple_New(1); - Runtime.Incref(idx); + Runtime.XIncref(idx); Runtime.PyTuple_SetItem(args, 0, idx); free = true; } @@ -257,7 +257,7 @@ public static int mp_ass_subscript(IntPtr ob, IntPtr idx, IntPtr v) for (int n = 0; n < i; n++) { IntPtr item = Runtime.PyTuple_GetItem(args, n); - Runtime.Incref(item); + Runtime.XIncref(item); Runtime.PyTuple_SetItem(real, n, item); } @@ -265,15 +265,15 @@ public static int mp_ass_subscript(IntPtr ob, IntPtr idx, IntPtr v) for (int n = 0; n < numOfDefaultArgs; n++) { IntPtr item = Runtime.PyTuple_GetItem(defaultArgs, n); - Runtime.Incref(item); + Runtime.XIncref(item); Runtime.PyTuple_SetItem(real, n + i, item); } // no longer need defaultArgs - Runtime.Decref(defaultArgs); + Runtime.XDecref(defaultArgs); i = temp; // Add value to argument list - Runtime.Incref(v); + Runtime.XIncref(v); Runtime.PyTuple_SetItem(real, i, v); try @@ -282,11 +282,11 @@ public static int mp_ass_subscript(IntPtr ob, IntPtr idx, IntPtr v) } finally { - Runtime.Decref(real); + Runtime.XDecref(real); if (free) { - Runtime.Decref(args); + Runtime.XDecref(args); } } diff --git a/src/runtime/clrmodule.il b/src/runtime/clrmodule.il deleted file mode 100644 index fb312b1b5..000000000 --- a/src/runtime/clrmodule.il +++ /dev/null @@ -1,297 +0,0 @@ - -//============================================================================ -// This file is a hand-maintained stub - it implements clr.dll, which can be -// loaded by a standard CPython interpreter (on Windows) as an extension module. -// When it is loaded, it bootstraps the managed runtime integration layer and defers -// to it to do initialization and put the clr module into sys.modules, etc. - -// The "USE_PYTHON_RUNTIME_*" defines control what extra evidence is used -// to help the CLR find the appropriate Python.Runtime assembly. - -// If defined, the "pythonRuntimeVersionString" variable must be set to -// Python.Runtime's current version. -#define USE_PYTHON_RUNTIME_VERSION - -// If defined, the "PythonRuntimePublicKeyTokenData" data array must be -// set to Python.Runtime's public key token. (sn -T Python.Runtin.dll) -#define USE_PYTHON_RUNTIME_PUBLIC_KEY_TOKEN - -// If DEBUG_PRINT is defined, a few System.Console.WriteLine calls are made -// to indicate what's going on during the load... -//#define DEBUG_PRINT -//============================================================================ - -.assembly extern mscorlib -{ - .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) - .ver 4:0:0:0 -} - -.assembly extern mscorlib -{ - .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) - .ver 2:0:0:0 -} - -.assembly clr -{ - .hash algorithm 0x00008004 - .ver 4:0:0:1 -} - -.module clr.dll -.imagebase 0x00400000 -.subsystem 0x00000003 -.file alignment 512 - -#ifdef USE_PYTHON_RUNTIME_PUBLIC_KEY_TOKEN -.data PythonRuntimePublicKeyTokenData = bytearray (50 00 fe a6 cb a7 02 dd) -//.data PythonRuntimePublicKeyTokenData = bytearray (64 e1 4e 84 5a bf 2e 60) -#endif - -// This includes the platform-specific IL. The include search path -// is set depending on whether we're compiling 32 or 64 bit. -// This MUST come before any other .data directives! -// Why, oh why, can't ilasm support command line #defines? :( -// - -//#include "clrmodule-platform.il" - -// From the manifest as seen by ildasm -//%windir%\Microsoft.NET\Framework\v4.0.30319\ilasm /dll /pe64 /x64 clrmodule.il -//.corflags 0x00000000 -// Image base: 0x01550000 -// .vtfixup [1] int64 fromunmanaged at D_00004008 // 0000000006000002 - -//%windir%\Microsoft.NET\Framework\v4.0.30319\ilasm /dll clrmodule.il -// .vtfixup [1] int32 fromunmanaged at D_00004008 // 06000002 -//.corflags 0x00000002 // 32BITREQUIRED -// Image base: 0x015A0000 - -// With or without /pe64 /x64 switches. -//{ -// .vtentry 1 : 1 -// .export [1] as initclr -// ... } - - -.class public auto ansi beforefieldinit clrModule extends [mscorlib]System.Object -{ -#ifdef USE_PYTHON_RUNTIME_PUBLIC_KEY_TOKEN - .field static assembly int64 PythonRuntimePublicKeyToken at PythonRuntimePublicKeyTokenData -#endif - - .method public hidebysig specialname rtspecialname instance void - .ctor() cil managed - { - .maxstack 1 - ldarg.0 - call instance void [mscorlib]System.Object::.ctor() - ret - } - - .method public hidebysig static void modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl) - initclr() cil managed - { -// .vtentry 1:1 - .export [1] as initclr - - .maxstack 6 - .locals init ( - class [mscorlib]System.Reflection.Assembly pythonRuntime, - class [mscorlib]System.Reflection.Assembly executingAssembly, - class [mscorlib]System.Reflection.AssemblyName pythonRuntimeName, - class [mscorlib]System.Type pythonEngineType, - int8[] publicKeyToken, - string assemblyDirectory, - string pythonRuntimeVersionString, - string pythonRuntimeDllPath) - - // pythonRuntime = null; - ldnull - stloc pythonRuntime - - .try - { -#ifdef DEBUG_PRINT - ldstr "Attempting to load Python.Runtime using standard binding rules... " - call void [mscorlib]System.Console::Write(string) -#endif - - // Attempt to find and load Python.Runtime using standard assembly binding rules. - // This roughly translates into looking in order: - // - GAC - // - ApplicationBase - // - A PrivateBinPath under ApplicationBase - // With an unsigned assembly, the GAC is skipped. - - // System.Reflection.AssemblyName pythonRuntimeName = new System.Reflection.AssemblyName(); - newobj instance void [mscorlib]System.Reflection.AssemblyName::.ctor() - stloc pythonRuntimeName - - // pythonRuntimeName.Name = "Python.Runtime"; - ldloc pythonRuntimeName - ldstr "Python.Runtime" - callvirt instance void [mscorlib]System.Reflection.AssemblyName::set_Name(string) - -#ifdef USE_PYTHON_RUNTIME_VERSION - // pythonRuntimeVersionString = "..."; - ldstr "4.0.0.1" - stloc pythonRuntimeVersionString - - // pythonRuntimeName.Version = new Version(pythonRuntimeVersionString); - ldloc pythonRuntimeName - ldloc pythonRuntimeVersionString - newobj instance void [mscorlib]System.Version::.ctor(string) - callvirt instance void [mscorlib]System.Reflection.AssemblyName::set_Version(class [mscorlib]System.Version) -#endif - -#ifdef USE_PYTHON_RUNTIME_PUBLIC_KEY_TOKEN - // publicKeyToken = new byte[] { ... }; - ldc.i4.8 - newarr [mscorlib]System.Byte - dup - ldtoken field int64 clrModule::PythonRuntimePublicKeyToken - call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype [mscorlib]System.RuntimeFieldHandle) - stloc publicKeyToken - - // pythonRuntimeName.SetPublicKeyToken(publicKeyToken); - ldloc pythonRuntimeName - ldloc publicKeyToken - callvirt instance void [mscorlib]System.Reflection.AssemblyName::SetPublicKeyToken(uint8[]) -#endif - - // pythonRuntimeName.CultureInfo = System.Globalization.CultureInfo.InvariantCulture; - ldloc pythonRuntimeName - call class [mscorlib]System.Globalization.CultureInfo [mscorlib]System.Globalization.CultureInfo::get_InvariantCulture() - callvirt instance void [mscorlib]System.Reflection.AssemblyName::set_CultureInfo(class [mscorlib]System.Globalization.CultureInfo) - - // return System.Reflection.Assembly.Load(pythonRuntimeName); - ldloc pythonRuntimeName - call class [mscorlib]System.Reflection.Assembly [mscorlib]System.Reflection.Assembly::Load(class [mscorlib]System.Reflection.AssemblyName) - stloc pythonRuntime - -#ifdef DEBUG_PRINT - ldstr "Success!" - call void [mscorlib]System.Console::WriteLine(string) -#endif - leave.s LOADED_PYTHON_RUNTIME - } - catch [mscorlib]System.Object - { -#ifdef DEBUG_PRINT - ldstr "Failed." - call void [mscorlib]System.Console::WriteLine(string) -#endif - leave.s EXIT_CLR_LOAD - } - EXIT_CLR_LOAD: nop - - .try - { - // If the above fails for any reason, we fallback to attempting to load "Python.Runtime.dll" - // from the directory this assembly is running in. "This assembly" is probably "clr.pyd", - // sitting somewhere in PYTHONPATH. This is using Assembly.LoadFrom, and inherits all the - // caveats of that call. See MSDN docs for details. - // Suzanne Cook's blog is also an excellent source of info on this: - // http://blogs.msdn.com/suzcook/ - // http://blogs.msdn.com/suzcook/archive/2003/05/29/57143.aspx - // http://blogs.msdn.com/suzcook/archive/2003/06/13/57180.aspx - // executingAssembly = System.Reflection.Assembly.GetExecutingAssembly(); - call class [mscorlib]System.Reflection.Assembly [mscorlib]System.Reflection.Assembly::GetExecutingAssembly() - stloc executingAssembly - - // assemblyDirectory = System.IO.Path.GetDirectoryName(executingAssembly.Location); - ldloc executingAssembly - callvirt instance string [mscorlib]System.Reflection.Assembly::get_Location() - call string [mscorlib]System.IO.Path::GetDirectoryName(string) - stloc assemblyDirectory - - // pythonRuntimeDllPath = System.IO.Path.Combine(assemblyDirectory, "Python.Runtime.dll"); - ldloc assemblyDirectory - ldstr "Python.Runtime.dll" - call string [mscorlib]System.IO.Path::Combine(string, string) - stloc pythonRuntimeDllPath - -#ifdef DEBUG_PRINT - ldstr "Attempting to load Python.Runtime from: '{0}'... " - ldloc pythonRuntimeDllPath - call void [mscorlib]System.Console::Write(string, object) -#endif - - // pythonRuntime = System.Reflection.Assembly.LoadFrom(pythonRuntimeDllPath); - ldloc pythonRuntimeDllPath - call class [mscorlib]System.Reflection.Assembly [mscorlib]System.Reflection.Assembly::LoadFrom(string) - stloc pythonRuntime - -#ifdef DEBUG_PRINT - ldstr "Success!" - call void [mscorlib]System.Console::WriteLine(string) - - ldloc pythonRuntime - callvirt instance string [mscorlib]System.Reflection.Assembly::get_CodeBase() - call void [mscorlib]System.Console::WriteLine(string) -#endif - leave.s LOADED_PYTHON_RUNTIME - } - catch [mscorlib]System.Object - { -#ifdef DEBUG_PRINT - ldstr "Failed." - call void [mscorlib]System.Console::WriteLine(string) -#endif - leave.s EXIT_PYTHONPATH_LOAD - } - EXIT_PYTHONPATH_LOAD: nop - - // If we get here, we haven't loaded Python.Runtime, so bail. -#ifdef DEBUG_PRINT - ldstr "Could not load Python.Runtime, so sad." - call void [mscorlib]System.Console::WriteLine(string) -#endif - ret; - - // Once here, we've successfully loaded SOME version of Python.Runtime - // So now we get the PythonEngine and execute the InitExt method on it. - LOADED_PYTHON_RUNTIME: nop - .try - { -#ifdef DEBUG_PRINT - ldstr "Running Python.Runtime.PythonEngine.InitExt()" - call void [mscorlib]System.Console::WriteLine(string) -#endif - // pythonEngineType = pythonRuntime.GetType("Python.Runtime.PythonEngine"); - ldloc pythonRuntime - ldstr "Python.Runtime.PythonEngine" - callvirt instance class [mscorlib]System.Type [mscorlib]System.Reflection.Assembly::GetType(string) - stloc pythonEngineType - - // pythonEngineType.InvokeMember("InitExt", System.Reflection.BindingFlags.InvokeMethod, null, null, null); - ldloc pythonEngineType - ldstr "InitExt" - ldc.i4 0x100 - ldnull - ldnull - ldnull - callvirt instance object [mscorlib]System.Type::InvokeMember( string, - valuetype [mscorlib]System.Reflection.BindingFlags, - class [mscorlib]System.Reflection.Binder, - object, - object[]) - pop - leave.s EXIT_TRY_INVOKE - } - catch [mscorlib]System.Object - { -#ifdef DEBUG_PRINT - ldstr "Error calling Python.Runtime.PythonEngine.InitExt()." - call void [mscorlib]System.Console::WriteLine(string) -#endif - leave.s EXIT_TRY_INVOKE - } - EXIT_TRY_INVOKE: nop - - ret - } -} - diff --git a/src/runtime/clrmodule.pp.il b/src/runtime/clrmodule.pp.il deleted file mode 100644 index 27eb78432..000000000 --- a/src/runtime/clrmodule.pp.il +++ /dev/null @@ -1,271 +0,0 @@ - -//============================================================================ -// 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 to do initialization and put the clr module into sys.modules, etc. - -// The "USE_PYTHON_RUNTIME_*" defines control what extra evidence is used -// to help the CLR find the appropriate Python.Runtime assembly. - -// If defined, the "pythonRuntimeVersionString" variable must be set to -// Python.Runtime's current version. -#define USE_PYTHON_RUNTIME_VERSION - -// If defined, the "PythonRuntimePublicKeyTokenData" data array must be -// set to Python.Runtime's public key token. -//#define USE_PYTHON_RUNTIME_PUBLIC_KEY_TOKEN - -// If DEBUG_PRINT is defined, a few System.Console.WriteLine calls are made -// to indicate what's going on during the load... -//#define DEBUG_PRINT -//============================================================================ - -.assembly extern mscorlib -{ - .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) - .ver 2:0:0:0 -} - -.assembly clr -{ - .hash algorithm 0x00008004 - .ver 2:0:0:2 -} - -.module clr.dll -.imagebase 0x00400000 -.subsystem 0x00000003 -.file alignment 512 - -// This includes the platform-specific IL. The include search path -// is set depending on whether we're compiling 32 or 64 bit. -// This MUST come before any other .data directives! -// Why, oh why, can't ilasm support command line #defines? :( - -// Contributed by VIKAS DHIMAN - Handled by /home/barton/Projects/PyDotNet/pythonnet/makefile -// gcc -C -P -x c++ -I $(ARCH) clrmodule.pp.il -o clrmodule.il -// to copy the correct architecture to the clrModule. -// Nice formating, as well - Thanks, Vikas! -#include "clrmodule-platform.il" - -#ifdef USE_PYTHON_RUNTIME_PUBLIC_KEY_TOKEN -.data PythonRuntimePublicKeyTokenData = bytearray (64 e1 4e 84 5a bf 2e 60) -#endif - -.class public auto ansi beforefieldinit clrModule extends [mscorlib]System.Object -{ -#ifdef USE_PYTHON_RUNTIME_PUBLIC_KEY_TOKEN - .field static assembly int64 PythonRuntimePublicKeyToken at PythonRuntimePublicKeyTokenData -#endif - - .method public hidebysig specialname rtspecialname instance void - .ctor() cil managed - { - .maxstack 1 - ldarg.0 - call instance void [mscorlib]System.Object::.ctor() - ret - } - - .method public hidebysig static void modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl) - initclr() cil managed - { - .vtentry 1:1 - .export [1] as initclr - - .maxstack 6 - .locals init ( - class [mscorlib]System.Reflection.Assembly pythonRuntime, - class [mscorlib]System.Reflection.Assembly executingAssembly, - class [mscorlib]System.Reflection.AssemblyName pythonRuntimeName, - class [mscorlib]System.Type pythonEngineType, - int8[] publicKeyToken, - string assemblyDirectory, - string pythonRuntimeVersionString, - string pythonRuntimeDllPath) - - // pythonRuntime = null; - ldnull - stloc pythonRuntime - - .try - { -#ifdef DEBUG_PRINT - ldstr "Attempting to load Python.Runtime using standard binding rules... " - call void [mscorlib]System.Console::Write(string) -#endif - - // Attempt to find and load Python.Runtime using standard assembly binding rules. - // This roughly translates into looking in order: - // - GAC - // - ApplicationBase - // - A PrivateBinPath under ApplicationBase - // With an unsigned assembly, the GAC is skipped. - - // System.Reflection.AssemblyName pythonRuntimeName = new System.Reflection.AssemblyName(); - newobj instance void [mscorlib]System.Reflection.AssemblyName::.ctor() - stloc pythonRuntimeName - - // pythonRuntimeName.Name = "Python.Runtime"; - ldloc pythonRuntimeName - ldstr "Python.Runtime" - callvirt instance void [mscorlib]System.Reflection.AssemblyName::set_Name(string) - -#ifdef USE_PYTHON_RUNTIME_VERSION - // pythonRuntimeVersionString = "..."; - ldstr "2.0.0.2" - stloc pythonRuntimeVersionString - - // pythonRuntimeName.Version = new Version(pythonRuntimeVersionString); - ldloc pythonRuntimeName - ldloc pythonRuntimeVersionString - newobj instance void [mscorlib]System.Version::.ctor(string) - callvirt instance void [mscorlib]System.Reflection.AssemblyName::set_Version(class [mscorlib]System.Version) -#endif - -#ifdef USE_PYTHON_RUNTIME_PUBLIC_KEY_TOKEN - // publicKeyToken = new byte[] { ... }; - ldc.i4.8 - newarr [mscorlib]System.Byte - dup - ldtoken field int64 clrModule::PythonRuntimePublicKeyToken - call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype [mscorlib]System.RuntimeFieldHandle) - stloc publicKeyToken - - // pythonRuntimeName.SetPublicKeyToken(publicKeyToken); - ldloc pythonRuntimeName - ldloc publicKeyToken - callvirt instance void [mscorlib]System.Reflection.AssemblyName::SetPublicKeyToken(uint8[]) -#endif - - // pythonRuntimeName.CultureInfo = System.Globalization.CultureInfo.InvariantCulture; - ldloc pythonRuntimeName - call class [mscorlib]System.Globalization.CultureInfo [mscorlib]System.Globalization.CultureInfo::get_InvariantCulture() - callvirt instance void [mscorlib]System.Reflection.AssemblyName::set_CultureInfo(class [mscorlib]System.Globalization.CultureInfo) - - // return System.Reflection.Assembly.Load(pythonRuntimeName); - ldloc pythonRuntimeName - call class [mscorlib]System.Reflection.Assembly [mscorlib]System.Reflection.Assembly::Load(class [mscorlib]System.Reflection.AssemblyName) - stloc pythonRuntime - -#ifdef DEBUG_PRINT - ldstr "Success!" - call void [mscorlib]System.Console::WriteLine(string) -#endif - leave.s LOADED_PYTHON_RUNTIME - } - catch [mscorlib]System.Object - { -#ifdef DEBUG_PRINT - ldstr "Failed." - call void [mscorlib]System.Console::WriteLine(string) -#endif - leave.s EXIT_CLR_LOAD - } - EXIT_CLR_LOAD: nop - - .try - { - // If the above fails for any reason, we fallback to attempting to load "Python.Runtime.dll" - // from the directory this assembly is running in. "This assembly" is probably "clr.pyd", - // sitting somewhere in PYTHONPATH. This is using Assembly.LoadFrom, and inherits all the - // caveats of that call. See MSDN docs for details. - // Suzanne Cook's blog is also an excellent source of info on this: - // http://blogs.msdn.com/suzcook/ - // http://blogs.msdn.com/suzcook/archive/2003/05/29/57143.aspx - // http://blogs.msdn.com/suzcook/archive/2003/06/13/57180.aspx - // executingAssembly = System.Reflection.Assembly.GetExecutingAssembly(); - call class [mscorlib]System.Reflection.Assembly [mscorlib]System.Reflection.Assembly::GetExecutingAssembly() - stloc executingAssembly - - // assemblyDirectory = System.IO.Path.GetDirectoryName(executingAssembly.Location); - ldloc executingAssembly - callvirt instance string [mscorlib]System.Reflection.Assembly::get_Location() - call string [mscorlib]System.IO.Path::GetDirectoryName(string) - stloc assemblyDirectory - - // pythonRuntimeDllPath = System.IO.Path.Combine(assemblyDirectory, "Python.Runtime.dll"); - ldloc assemblyDirectory - ldstr "Python.Runtime.dll" - call string [mscorlib]System.IO.Path::Combine(string, string) - stloc pythonRuntimeDllPath - -#ifdef DEBUG_PRINT - ldstr "Attempting to load Python.Runtime from: '{0}'... " - ldloc pythonRuntimeDllPath - call void [mscorlib]System.Console::Write(string, object) -#endif - - // pythonRuntime = System.Reflection.Assembly.LoadFrom(pythonRuntimeDllPath); - ldloc pythonRuntimeDllPath - call class [mscorlib]System.Reflection.Assembly [mscorlib]System.Reflection.Assembly::LoadFrom(string) - stloc pythonRuntime - -#ifdef DEBUG_PRINT - ldstr "Success!" - call void [mscorlib]System.Console::WriteLine(string) -#endif - leave.s LOADED_PYTHON_RUNTIME - } - catch [mscorlib]System.Object - { -#ifdef DEBUG_PRINT - ldstr "Failed." - call void [mscorlib]System.Console::WriteLine(string) -#endif - leave.s EXIT_PYTHONPATH_LOAD - } - EXIT_PYTHONPATH_LOAD: nop - - // If we get here, we haven't loaded Python.Runtime, so bail. -#ifdef DEBUG_PRINT - ldstr "Could not load Python.Runtime, so sad." - call void [mscorlib]System.Console::WriteLine(string) -#endif - ret - - // Once here, we've successfully loaded SOME version of Python.Runtime - // So now we get the PythonEngine and execute the InitExt method on it. - LOADED_PYTHON_RUNTIME: nop - .try - { -#ifdef DEBUG_PRINT - ldstr "Running Python.Runtime.PythonEngine.InitExt()" - call void [mscorlib]System.Console::WriteLine(string) -#endif - // pythonEngineType = pythonRuntime.GetType("Python.Runtime.PythonEngine"); - ldloc pythonRuntime - ldstr "Python.Runtime.PythonEngine" - callvirt instance class [mscorlib]System.Type [mscorlib]System.Reflection.Assembly::GetType(string) - stloc pythonEngineType - - // pythonEngineType.InvokeMember("InitExt", System.Reflection.BindingFlags.InvokeMethod, null, null, null); - ldloc pythonEngineType - ldstr "InitExt" - ldc.i4 0x100 - ldnull - ldnull - ldnull - callvirt instance object [mscorlib]System.Type::InvokeMember( string, - valuetype [mscorlib]System.Reflection.BindingFlags, - class [mscorlib]System.Reflection.Binder, - object, - object[]) - pop - leave.s EXIT_TRY_INVOKE - } - catch [mscorlib]System.Object - { -#ifdef DEBUG_PRINT - ldstr "Error calling Python.Runtime.PythonEngine.InitExt()." - call void [mscorlib]System.Console::WriteLine(string) -#endif - leave.s EXIT_TRY_INVOKE - } - EXIT_TRY_INVOKE: nop - - ret - } -} - diff --git a/src/runtime/clrobject.cs b/src/runtime/clrobject.cs index 351c7c51b..e7bb345f8 100644 --- a/src/runtime/clrobject.cs +++ b/src/runtime/clrobject.cs @@ -30,6 +30,10 @@ internal CLRObject(Object ob, IntPtr tp) : base() this.pyHandle = py; this.gcHandle = gc; inst = ob; + + // Fix the BaseException args (and __cause__ in case of Python 3) + // slot if wrapping a CLR exception + Exceptions.SetArgsAndCause(py); } @@ -67,4 +71,4 @@ internal static IntPtr GetInstHandle(Object ob) return co.pyHandle; } } -} \ No newline at end of file +} diff --git a/src/runtime/constructorbinder.cs b/src/runtime/constructorbinder.cs index 1a008cc75..7ea7602b8 100644 --- a/src/runtime/constructorbinder.cs +++ b/src/runtime/constructorbinder.cs @@ -92,7 +92,7 @@ internal object InvokeRaw(IntPtr inst, IntPtr args, IntPtr kw, IntPtr eargs = Runtime.PyTuple_New(0); binding = this.Bind(inst, eargs, kw); - Runtime.Decref(eargs); + Runtime.XDecref(eargs); if (binding == null) { diff --git a/src/runtime/constructorbinding.cs b/src/runtime/constructorbinding.cs index 2921874e1..8710f53bf 100644 --- a/src/runtime/constructorbinding.cs +++ b/src/runtime/constructorbinding.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Reflection; namespace Python.Runtime @@ -30,7 +30,7 @@ internal class ConstructorBinding : ExtensionType public ConstructorBinding(Type type, IntPtr pyTypeHndl, ConstructorBinder ctorBinder) : base() { this.type = type; - Runtime.Incref(pyTypeHndl); + Runtime.XIncref(pyTypeHndl); this.pyTypeHndl = pyTypeHndl; this.ctorBinder = ctorBinder; repr = IntPtr.Zero; @@ -73,7 +73,7 @@ public static IntPtr tp_descr_get(IntPtr op, IntPtr instance, IntPtr owner) return Exceptions.RaiseTypeError("How in the world could that happen!"); } }*/ - Runtime.Incref(self.pyHandle); // Decref'd by the interpreter. + Runtime.XIncref(self.pyHandle); // Decref'd by the interpreter. return self.pyHandle; } @@ -108,7 +108,7 @@ public static IntPtr mp_subscript(IntPtr op, IntPtr key) BoundContructor boundCtor = new BoundContructor(self.type, self.pyTypeHndl, self.ctorBinder, ci); /* Since nothing's chached, do we need the increment??? - Runtime.Incref(boundCtor.pyHandle); // Decref'd by the interpreter??? */ + Runtime.XIncref(boundCtor.pyHandle); // Decref'd by the interpreter??? */ return boundCtor.pyHandle; } @@ -121,7 +121,7 @@ public static IntPtr tp_repr(IntPtr ob) ConstructorBinding self = (ConstructorBinding)GetManagedObject(ob); if (self.repr != IntPtr.Zero) { - Runtime.Incref(self.repr); + Runtime.XIncref(self.repr); return self.repr; } MethodBase[] methods = self.ctorBinder.GetMethods(); @@ -136,7 +136,7 @@ public static IntPtr tp_repr(IntPtr ob) doc += String.Format("{0}{1}", name, str.Substring(idx)); } self.repr = Runtime.PyString_FromString(doc); - Runtime.Incref(self.repr); + Runtime.XIncref(self.repr); return self.repr; } @@ -147,8 +147,8 @@ public static IntPtr tp_repr(IntPtr ob) public static new void tp_dealloc(IntPtr ob) { ConstructorBinding self = (ConstructorBinding)GetManagedObject(ob); - Runtime.Decref(self.repr); - Runtime.Decref(self.pyTypeHndl); + Runtime.XDecref(self.repr); + Runtime.XDecref(self.pyTypeHndl); ExtensionType.FinalizeObject(self); } } @@ -173,7 +173,7 @@ public BoundContructor(Type type, IntPtr pyTypeHndl, ConstructorBinder ctorBinde : base() { this.type = type; - Runtime.Incref(pyTypeHndl); + Runtime.XIncref(pyTypeHndl); this.pyTypeHndl = pyTypeHndl; this.ctorBinder = ctorBinder; ctorInfo = ci; @@ -217,7 +217,7 @@ public static IntPtr tp_repr(IntPtr ob) BoundContructor self = (BoundContructor)GetManagedObject(ob); if (self.repr != IntPtr.Zero) { - Runtime.Incref(self.repr); + Runtime.XIncref(self.repr); return self.repr; } string name = self.type.FullName; @@ -225,7 +225,7 @@ public static IntPtr tp_repr(IntPtr ob) int idx = str.IndexOf("("); str = String.Format("returns a new {0}{1}", name, str.Substring(idx)); self.repr = Runtime.PyString_FromString(str); - Runtime.Incref(self.repr); + Runtime.XIncref(self.repr); return self.repr; } @@ -236,9 +236,9 @@ public static IntPtr tp_repr(IntPtr ob) public static new void tp_dealloc(IntPtr ob) { BoundContructor self = (BoundContructor)GetManagedObject(ob); - Runtime.Decref(self.repr); - Runtime.Decref(self.pyTypeHndl); + Runtime.XDecref(self.repr); + Runtime.XDecref(self.pyTypeHndl); ExtensionType.FinalizeObject(self); } } -} \ No newline at end of file +} diff --git a/src/runtime/converter.cs b/src/runtime/converter.cs index 66ddfad5d..ac1085c18 100644 --- a/src/runtime/converter.cs +++ b/src/runtime/converter.cs @@ -84,7 +84,7 @@ internal static IntPtr GetPythonTypeByAlias(Type op) { return Runtime.PyUnicodeType; } -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON3 else if ((op == int16Type) || (op == int32Type) || (op == int64Type)) { @@ -126,6 +126,12 @@ internal static IntPtr ToPython(T value) internal static IntPtr ToPython(Object value, Type type) { + if(value is PyObject) + { + IntPtr handle = ((PyObject)value).Handle; + Runtime.XIncref(handle); + return handle; + } IntPtr result = IntPtr.Zero; // Null always converts to None in Python. @@ -133,7 +139,7 @@ internal static IntPtr ToPython(Object value, Type type) if (value == null) { result = Runtime.PyNone; - Runtime.Incref(result); + Runtime.XIncref(result); return result; } @@ -156,20 +162,7 @@ internal static IntPtr ToPython(Object value, Type 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; + return CLRObject.GetInstHandle(value, type); case TypeCode.String: return Runtime.PyUnicode_FromString((string)value); @@ -180,10 +173,10 @@ internal static IntPtr ToPython(Object value, Type type) case TypeCode.Boolean: if ((bool)value) { - Runtime.Incref(Runtime.PyTrue); + Runtime.XIncref(Runtime.PyTrue); return Runtime.PyTrue; } - Runtime.Incref(Runtime.PyFalse); + Runtime.XIncref(Runtime.PyFalse); return Runtime.PyFalse; case TypeCode.Byte: @@ -203,7 +196,7 @@ internal static IntPtr ToPython(Object value, Type type) string ss = ((float)value).ToString(nfi); IntPtr ps = Runtime.PyString_FromString(ss); IntPtr op = Runtime.PyFloat_FromString(ps, IntPtr.Zero); - Runtime.Decref(ps); + Runtime.XDecref(ps); return op; case TypeCode.Double: @@ -231,7 +224,7 @@ internal static IntPtr ToPython(Object value, Type type) using (var p = new PyObject(ToPython(o, o?.GetType()))) resultlist.Append(p); } - Runtime.Incref(resultlist.Handle); + Runtime.XIncref(resultlist.Handle); return resultlist.Handle; } } @@ -251,7 +244,7 @@ internal static IntPtr ToPythonImplicit(Object value) if (value == null) { IntPtr result = Runtime.PyNone; - Runtime.Incref(result); + Runtime.XIncref(result); return result; } @@ -278,41 +271,18 @@ internal static bool ToManaged(IntPtr value, Type type, internal static bool ToManagedValue(IntPtr value, Type obType, out Object result, bool setError) { + if (obType == typeof(PyObject)) + { + Runtime.XIncref(value); // PyObject() assumes ownership + result = new PyObject(value); + return true; + } + // 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); - } - } - IntPtr c = Exceptions.UnwrapExceptionClass(value); - if ((c != IntPtr.Zero) && (c != value)) - { - value = c; - Runtime.Decref(c); - mt = ManagedType.GetManagedObject(value); - } - } - } - if (mt != null) { if (mt is CLRObject) @@ -480,7 +450,7 @@ static bool ToPrimitive(IntPtr value, Type obType, out Object result, return true; case TypeCode.Int32: -#if !(PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON2 // Trickery to support 64-bit platforms. if (IntPtr.Size == 4) { @@ -489,7 +459,7 @@ static bool ToPrimitive(IntPtr value, Type obType, out Object result, // As of Python 2.3, large ints magically convert :( if (Runtime.PyLong_Check(op)) { - Runtime.Decref(op); + Runtime.XDecref(op); goto overflow; } @@ -502,13 +472,13 @@ static bool ToPrimitive(IntPtr value, Type obType, out Object result, goto type_error; } ival = (int)Runtime.PyInt_AsLong(op); - Runtime.Decref(op); + Runtime.XDecref(op); result = ival; return true; } else { -#else +#elif PYTHON3 // When using Python3 always use the PyLong API { #endif @@ -523,7 +493,7 @@ static bool ToPrimitive(IntPtr value, Type obType, out Object result, goto type_error; } long ll = (long)Runtime.PyLong_AsLongLong(op); - Runtime.Decref(op); + Runtime.XDecref(op); if ((ll == -1) && Exceptions.ErrorOccurred()) { goto overflow; @@ -541,7 +511,7 @@ static bool ToPrimitive(IntPtr value, Type obType, out Object result, return true; case TypeCode.Byte: -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON3 if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType)) { if (Runtime.PyBytes_Size(value) == 1) @@ -552,7 +522,7 @@ static bool ToPrimitive(IntPtr value, Type obType, out Object result, } goto type_error; } -#else +#elif PYTHON2 if (Runtime.PyObject_TypeCheck(value, Runtime.PyStringType)) { if (Runtime.PyString_Size(value) == 1) @@ -575,7 +545,7 @@ static bool ToPrimitive(IntPtr value, Type obType, out Object result, goto type_error; } ival = (int)Runtime.PyInt_AsLong(op); - Runtime.Decref(op); + Runtime.XDecref(op); if (ival > Byte.MaxValue || ival < Byte.MinValue) { @@ -586,7 +556,7 @@ static bool ToPrimitive(IntPtr value, Type obType, out Object result, return true; case TypeCode.SByte: -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON3 if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType)) { if (Runtime.PyBytes_Size(value) == 1) { op = Runtime.PyBytes_AS_STRING(value); @@ -595,7 +565,7 @@ static bool ToPrimitive(IntPtr value, Type obType, out Object result, } goto type_error; } -#else +#elif PYTHON2 if (Runtime.PyObject_TypeCheck(value, Runtime.PyStringType)) { if (Runtime.PyString_Size(value) == 1) @@ -618,7 +588,7 @@ static bool ToPrimitive(IntPtr value, Type obType, out Object result, goto type_error; } ival = (int)Runtime.PyInt_AsLong(op); - Runtime.Decref(op); + Runtime.XDecref(op); if (ival > SByte.MaxValue || ival < SByte.MinValue) { @@ -629,7 +599,7 @@ static bool ToPrimitive(IntPtr value, Type obType, out Object result, return true; case TypeCode.Char: -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON3 if (Runtime.PyObject_TypeCheck(value, Runtime.PyBytesType)) { if (Runtime.PyBytes_Size(value) == 1) { op = Runtime.PyBytes_AS_STRING(value); @@ -638,7 +608,7 @@ static bool ToPrimitive(IntPtr value, Type obType, out Object result, } goto type_error; } -#else +#elif PYTHON2 if (Runtime.PyObject_TypeCheck(value, Runtime.PyStringType)) { if (Runtime.PyString_Size(value) == 1) @@ -656,7 +626,7 @@ static bool ToPrimitive(IntPtr value, Type obType, out Object result, if (Runtime.PyUnicode_GetSize(value) == 1) { op = Runtime.PyUnicode_AS_UNICODE(value); -#if (!UCS4) +#if !UCS4 // 2011-01-02: Marshal as character array because the cast // result = (char)Marshal.ReadInt16(op); throws an OverflowException // on negative numbers with Check Overflow option set on the project @@ -678,7 +648,7 @@ static bool ToPrimitive(IntPtr value, Type obType, out Object result, goto type_error; } ival = Runtime.PyInt_AsLong(op); - Runtime.Decref(op); + Runtime.XDecref(op); if (ival > Char.MaxValue || ival < Char.MinValue) { goto overflow; @@ -697,7 +667,7 @@ static bool ToPrimitive(IntPtr value, Type obType, out Object result, goto type_error; } ival = (int)Runtime.PyInt_AsLong(op); - Runtime.Decref(op); + Runtime.XDecref(op); if (ival > Int16.MaxValue || ival < Int16.MinValue) { goto overflow; @@ -717,7 +687,7 @@ static bool ToPrimitive(IntPtr value, Type obType, out Object result, goto type_error; } long l = (long)Runtime.PyLong_AsLongLong(op); - Runtime.Decref(op); + Runtime.XDecref(op); if ((l == -1) && Exceptions.ErrorOccurred()) { goto overflow; @@ -736,7 +706,7 @@ static bool ToPrimitive(IntPtr value, Type obType, out Object result, goto type_error; } ival = (int)Runtime.PyInt_AsLong(op); - Runtime.Decref(op); + Runtime.XDecref(op); if (ival > UInt16.MaxValue || ival < UInt16.MinValue) { goto overflow; @@ -759,14 +729,14 @@ static bool ToPrimitive(IntPtr value, Type obType, out Object result, if (Exceptions.ErrorOccurred()) { - Runtime.Decref(op); + Runtime.XDecref(op); goto overflow; } IntPtr check = Runtime.PyLong_FromUnsignedLong(ui); int err = Runtime.PyObject_Compare(check, op); - Runtime.Decref(check); - Runtime.Decref(op); + Runtime.XDecref(check); + Runtime.XDecref(op); if (0 != err || Exceptions.ErrorOccurred()) { goto overflow; @@ -786,7 +756,7 @@ static bool ToPrimitive(IntPtr value, Type obType, out Object result, goto type_error; } ulong ul = (ulong)Runtime.PyLong_AsUnsignedLongLong(op); - Runtime.Decref(op); + Runtime.XDecref(op); if (Exceptions.ErrorOccurred()) { goto overflow; @@ -806,7 +776,7 @@ static bool ToPrimitive(IntPtr value, Type obType, out Object result, goto type_error; } double dd = Runtime.PyFloat_AsDouble(op); - Runtime.Decref(op); + Runtime.XDecref(op); if (dd > Single.MaxValue || dd < Single.MinValue) { goto overflow; @@ -821,7 +791,7 @@ static bool ToPrimitive(IntPtr value, Type obType, out Object result, goto type_error; } double d = Runtime.PyFloat_AsDouble(op); - Runtime.Decref(op); + Runtime.XDecref(op); if (d > Double.MaxValue || d < Double.MinValue) { goto overflow; @@ -859,7 +829,7 @@ static void SetConversionError(IntPtr value, Type target) { IntPtr ob = Runtime.PyObject_Repr(value); string src = Runtime.GetManagedString(ob); - Runtime.Decref(ob); + Runtime.XDecref(ob); string error = String.Format( "Cannot convert {0} to {1}", src, target ); @@ -908,12 +878,12 @@ static bool ToArray(IntPtr value, Type obType, out Object result, if (!Converter.ToManaged(item, elementType, out obj, true)) { - Runtime.Decref(item); + Runtime.XDecref(item); return false; } items.SetValue(obj, i); - Runtime.Decref(item); + Runtime.XDecref(item); } result = items; @@ -965,4 +935,4 @@ public static PyObject ToPython(this object o) return new PyObject(Converter.ToPython(o, o?.GetType())); } } -} \ No newline at end of file +} diff --git a/src/runtime/debughelper.cs b/src/runtime/debughelper.cs index c61dfe5fa..d65300e39 100644 --- a/src/runtime/debughelper.cs +++ b/src/runtime/debughelper.cs @@ -28,7 +28,7 @@ public static void Print(string msg, params IntPtr[] args) } IntPtr ob = Runtime.PyObject_Repr(args[i]); result += Runtime.GetManagedString(ob); - Runtime.Decref(ob); + Runtime.XDecref(ob); result += " "; } Console.WriteLine(result); diff --git a/src/runtime/delegatemanager.cs b/src/runtime/delegatemanager.cs index 9fe2c2882..1e652214b 100644 --- a/src/runtime/delegatemanager.cs +++ b/src/runtime/delegatemanager.cs @@ -203,7 +203,7 @@ public class Dispatcher public Dispatcher(IntPtr target, Type dtype) { - Runtime.Incref(target); + Runtime.XIncref(target); this.target = target; this.dtype = dtype; } @@ -215,7 +215,7 @@ public Dispatcher(IntPtr target, Type dtype) if (Runtime.Py_IsInitialized() > 0) { IntPtr gs = PythonEngine.AcquireLock(); - Runtime.Decref(target); + Runtime.XDecref(target); PythonEngine.ReleaseLock(gs); } } @@ -255,7 +255,7 @@ public object TrueDispatch(ArrayList args) } IntPtr op = Runtime.PyObject_Call(target, pyargs, IntPtr.Zero); - Runtime.Decref(pyargs); + Runtime.XDecref(pyargs); if (op == IntPtr.Zero) { @@ -273,11 +273,11 @@ public object TrueDispatch(ArrayList args) { string s = "could not convert Python result to " + rtype.ToString(); - Runtime.Decref(op); + Runtime.XDecref(op); throw new ConversionException(s); } - Runtime.Decref(op); + Runtime.XDecref(op); return result; } } diff --git a/src/runtime/delegateobject.cs b/src/runtime/delegateobject.cs index cde0af9ab..61e91942b 100644 --- a/src/runtime/delegateobject.cs +++ b/src/runtime/delegateobject.cs @@ -102,11 +102,11 @@ public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) //==================================================================== // Implements __cmp__ for reflected delegate types. //==================================================================== -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON3 public static new IntPtr tp_richcompare(IntPtr ob, IntPtr other, int op) { if (op != Runtime.Py_EQ && op != Runtime.Py_NE) { - Runtime.Incref(Runtime.PyNotImplemented); + Runtime.XIncref(Runtime.PyNotImplemented); return Runtime.PyNotImplemented; } @@ -124,14 +124,14 @@ public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) Delegate d2 = GetTrueDelegate(other); if (d1 == d2) { - Runtime.Incref(pytrue); + Runtime.XIncref(pytrue); return pytrue; } - Runtime.Incref(pyfalse); + Runtime.XIncref(pyfalse); return pyfalse; } -#else +#elif PYTHON2 public static new int tp_compare(IntPtr ob, IntPtr other) { Delegate d1 = GetTrueDelegate(ob); @@ -144,4 +144,4 @@ public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) } #endif } -} \ No newline at end of file +} diff --git a/src/runtime/eventbinding.cs b/src/runtime/eventbinding.cs index d3b22d5bc..6035c8e0b 100644 --- a/src/runtime/eventbinding.cs +++ b/src/runtime/eventbinding.cs @@ -13,7 +13,7 @@ internal class EventBinding : ExtensionType public EventBinding(EventObject e, IntPtr target) : base() { - Runtime.Incref(target); + Runtime.XIncref(target); this.target = target; this.e = e; } @@ -40,7 +40,7 @@ public static IntPtr nb_inplace_add(IntPtr ob, IntPtr arg) return IntPtr.Zero; } - Runtime.Incref(self.pyHandle); + Runtime.XIncref(self.pyHandle); return self.pyHandle; } @@ -66,7 +66,7 @@ public static IntPtr nb_inplace_subtract(IntPtr ob, IntPtr arg) return IntPtr.Zero; } - Runtime.Incref(self.pyHandle); + Runtime.XIncref(self.pyHandle); return self.pyHandle; } @@ -127,7 +127,7 @@ public static IntPtr tp_repr(IntPtr ob) public static new void tp_dealloc(IntPtr ob) { EventBinding self = (EventBinding)GetManagedObject(ob); - Runtime.Decref(self.target); + Runtime.XDecref(self.target); ExtensionType.FinalizeObject(self); } } diff --git a/src/runtime/eventobject.cs b/src/runtime/eventobject.cs index 618734bcb..6523f7e20 100644 --- a/src/runtime/eventobject.cs +++ b/src/runtime/eventobject.cs @@ -160,7 +160,7 @@ public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) self.unbound = new EventBinding(self, IntPtr.Zero); } binding = self.unbound; - Runtime.Incref(binding.pyHandle); + Runtime.XIncref(binding.pyHandle); return binding.pyHandle; } @@ -218,7 +218,7 @@ public static IntPtr tp_repr(IntPtr ob) EventObject self = (EventObject)GetManagedObject(ob); if (self.unbound != null) { - Runtime.Decref(self.unbound.pyHandle); + Runtime.XDecref(self.unbound.pyHandle); } ExtensionType.FinalizeObject(self); } diff --git a/src/runtime/exceptions.cs b/src/runtime/exceptions.cs index 92608ee84..429c09212 100644 --- a/src/runtime/exceptions.cs +++ b/src/runtime/exceptions.cs @@ -23,7 +23,6 @@ internal ExceptionClassObject(Type tp) : base(tp) { } -#if (PYTHON25 || PYTHON26 || PYTHON27 || PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) internal static Exception ToException(IntPtr ob) { CLRObject co = GetManagedObject(ob) as CLRObject; @@ -56,76 +55,12 @@ internal static Exception ToException(IntPtr ob) { message = e.Message; } - if ((e.StackTrace != null) && (e.StackTrace != String.Empty)) + if (!string.IsNullOrEmpty(e.StackTrace)) { message = message + "\n" + e.StackTrace; } return Runtime.PyUnicode_FromString(message); } - - //==================================================================== - // Exception __repr__ implementation. - //==================================================================== - - public static IntPtr tp_repr(IntPtr ob) - { - Exception e = ToException(ob); - if (e == null) - { - return Exceptions.RaiseTypeError("invalid object"); - } - string name = e.GetType().Name; - string message; - if (e.Message != String.Empty) - { - message = String.Format("{0}('{1}',)", name, e.Message); - } - else - { - message = String.Format("{0}()", name); - } - return Runtime.PyUnicode_FromString(message); - } - - //==================================================================== - // Exceptions __getattribute__ implementation. - // handles Python's args and message attributes - //==================================================================== - - public static IntPtr tp_getattro(IntPtr ob, IntPtr key) - { - if (!Runtime.PyString_Check(key)) - { - Exceptions.SetError(Exceptions.TypeError, "string expected"); - return IntPtr.Zero; - } - - string name = Runtime.GetManagedString(key); - if (name == "args") - { - Exception e = ToException(ob); - IntPtr args; - if (e.Message != String.Empty) - { - args = Runtime.PyTuple_New(1); - IntPtr msg = Runtime.PyUnicode_FromString(e.Message); - Runtime.PyTuple_SetItem(args, 0, msg); - } - else - { - args = Runtime.PyTuple_New(0); - } - return args; - } - - if (name == "message") - { - return ExceptionClassObject.tp_str(ob); - } - - return Runtime.PyObject_GenericGetAttr(ob, key); - } -#endif // (PYTHON25 || PYTHON26 || PYTHON27 || PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) } /// @@ -149,9 +84,9 @@ private Exceptions() internal static void Initialize() { -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON3 exceptions_module = Runtime.PyImport_ImportModule("builtins"); -#else +#elif PYTHON2 exceptions_module = Runtime.PyImport_ImportModule("exceptions"); #endif Exceptions.ErrorCheck(exceptions_module); @@ -173,10 +108,6 @@ internal static void Initialize() } } Runtime.PyErr_Clear(); - if (Runtime.wrap_exceptions) - { - SetupExceptionHack(); - } } @@ -195,241 +126,75 @@ internal static void Shutdown() IntPtr op = (IntPtr)fi.GetValue(type); if (op != IntPtr.Zero) { - Runtime.Decref(op); + Runtime.XDecref(op); } } - Runtime.Decref(exceptions_module); + Runtime.XDecref(exceptions_module); Runtime.PyObject_HasAttrString(warnings_module, "xx"); - Runtime.Decref(warnings_module); - } - } - - /// - /// Shortcut for (pointer == NULL) -> throw PythonException - /// - /// Pointer to a Python object - internal unsafe static void ErrorCheck(IntPtr pointer) - { - if (pointer == IntPtr.Zero) - { - throw new PythonException(); + Runtime.XDecref(warnings_module); } } /// - /// Shortcut for (pointer == NULL or ErrorOccurred()) -> throw PythonException + /// Set the 'args' slot on a python exception object that wraps + /// a CLR exception. This is needed for pickling CLR exceptions as + /// BaseException_reduce will only check the slots, bypassing the + /// __getattr__ implementation, and thus dereferencing a NULL + /// pointer. /// - /// Shortcut for (pointer == NULL) -> throw PythonException - internal unsafe static void ErrorOccurredCheck(IntPtr pointer) + /// A CLR exception + /// The python object wrapping + internal static void SetArgsAndCause(IntPtr ob) { - if ((pointer == IntPtr.Zero) || Exceptions.ErrorOccurred()) - { - throw new PythonException(); - } - } - - // 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. - - /// - /// Conditionally initialized variables! - /// - static IntPtr ns_exc; // new-style class for System.Exception - - static IntPtr os_exc; // old-style class for System.Exception - static Hashtable cache; - - /// - /// the lines - /// // XXX - hack to raise a compatible old-style exception ;( - /// if (Runtime.wrap_exceptions) { - /// CallOneOfTheseMethods(); - /// - /// - 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" + - " #@property\n" + - " def message(self):\n" + - " return self.Message\n" + - " message = property(message)\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" + - " def __repr__(self):\n" + - " inner = self.__dict__.get('_inner')\n" + - " msg = getattr(inner, 'Message', '')\n" + - " name = self.__class__.__name__\n" + - " return '%s(\\'%s\\',)' % (name, msg) \n" + - "\n"; - - IntPtr dict = Runtime.PyDict_New(); - - IntPtr builtins = Runtime.PyEval_GetBuiltins(); - Runtime.PyDict_SetItemString(dict, "__builtins__", builtins); - - IntPtr namestr = Runtime.PyString_FromString("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 result = Runtime.PyRun_String(code, flag, dict, dict); - Exceptions.ErrorCheck(result); - Runtime.Decref(result); - - os_exc = Runtime.PyDict_GetItemString(dict, "Exception"); - Runtime.PyObject_SetAttrString(os_exc, "_class", ns_exc); - Runtime.PyErr_Clear(); - } - + var e = ExceptionClassObject.ToException(ob); + if (e == null) + return; - internal static IntPtr GenerateExceptionClass(IntPtr real) - { - if (real == ns_exc) + IntPtr args; + if (!string.IsNullOrEmpty(e.Message)) { - return os_exc; + args = Runtime.PyTuple_New(1); + var msg = Runtime.PyUnicode_FromString(e.Message); + Runtime.PyTuple_SetItem(args, 0, msg); } - - IntPtr nbases = Runtime.PyObject_GetAttrString(real, "__bases__"); - if (Runtime.PyTuple_Size(nbases) != 1) + else { - throw new SystemException("Invalid __bases__"); + args = Runtime.PyTuple_New(0); } - 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; - } + Marshal.WriteIntPtr(ob, ExceptionOffset.args, args); - 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) +#if PYTHON3 + if (e.InnerException != null) { - return real; + IntPtr cause = CLRObject.GetInstHandle(e.InnerException); + Marshal.WriteIntPtr(ob, ExceptionOffset.cause, cause); } - // Get / generate a class wrapper, instantiate it and set its - // _inner attribute to the real new-style exception instance. - IntPtr ct = GetExceptionClassWrapper(tp); - Exceptions.ErrorCheck(ct); - IntPtr op = Runtime.PyInstance_NewRaw(ct, IntPtr.Zero); - Exceptions.ErrorCheck(op); - IntPtr d = Runtime.PyObject_GetAttrString(op, "__dict__"); - Exceptions.ErrorCheck(d); - Runtime.PyDict_SetItemString(d, "_inner", real); - Runtime.Decref(d); - return op; +#endif } - internal static IntPtr UnwrapExceptionClass(IntPtr op) + /// + /// Shortcut for (pointer == NULL) -> throw PythonException + /// + /// Pointer to a Python object + internal unsafe static void ErrorCheck(IntPtr pointer) { - // In some cases its necessary to recognize an exception *class*, - // and obtain the inner (wrapped) exception class. This method - // returns the inner class if found, or a null pointer. - - IntPtr d = Runtime.PyObject_GetAttrString(op, "__dict__"); - if (d == IntPtr.Zero) - { - Exceptions.Clear(); - return IntPtr.Zero; - } - IntPtr c = Runtime.PyDict_GetItemString(d, "_class"); - Runtime.Decref(d); - if (c == IntPtr.Zero) + if (pointer == IntPtr.Zero) { - Exceptions.Clear(); + throw new PythonException(); } - return c; } /// - /// GetException Method + /// Shortcut for (pointer == NULL or ErrorOccurred()) -> throw PythonException /// - /// - /// - /// 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. - /// - public static PythonException GetException() + /// Shortcut for (pointer == NULL) -> throw PythonException + internal unsafe static void ErrorOccurredCheck(IntPtr pointer) { - // TODO: implement this. - return null; + if ((pointer == IntPtr.Zero) || Exceptions.ErrorOccurred()) + { + throw new PythonException(); + } } /// @@ -509,16 +274,10 @@ public static void SetError(Exception e) } 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); - Runtime.Decref(op); + Runtime.XDecref(etype); + Runtime.XDecref(op); } /// @@ -561,14 +320,14 @@ public static void warn(string message, IntPtr exception, int stacklevel) Exceptions.RaiseTypeError("Invalid exception"); } - Runtime.Incref(warnings_module); + Runtime.XIncref(warnings_module); IntPtr warn = Runtime.PyObject_GetAttrString(warnings_module, "warn"); - Runtime.Decref(warnings_module); + Runtime.XDecref(warnings_module); Exceptions.ErrorCheck(warn); IntPtr args = Runtime.PyTuple_New(3); IntPtr msg = Runtime.PyString_FromString(message); - Runtime.Incref(exception); // PyTuple_SetItem steals a reference + Runtime.XIncref(exception); // PyTuple_SetItem steals a reference IntPtr level = Runtime.PyInt_FromInt32(stacklevel); Runtime.PyTuple_SetItem(args, 0, msg); Runtime.PyTuple_SetItem(args, 1, exception); @@ -577,9 +336,9 @@ public static void warn(string message, IntPtr exception, int stacklevel) IntPtr result = Runtime.PyObject_CallObject(warn, args); Exceptions.ErrorCheck(result); - Runtime.Decref(warn); - Runtime.Decref(result); - Runtime.Decref(args); + Runtime.XDecref(warn); + Runtime.XDecref(result); + Runtime.XDecref(args); } public static void warn(string message, IntPtr exception) @@ -612,15 +371,11 @@ internal static IntPtr RaiseTypeError(string message) puplic static variables on the Exceptions class filled in from the python class using reflection in Initialize() looked up by name, not posistion. */ -#if (PYTHON25 || PYTHON26 || PYTHON27 || PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) public static IntPtr BaseException; -#endif public static IntPtr Exception; public static IntPtr StopIteration; -#if (PYTHON25 || PYTHON26 || PYTHON27 || PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) public static IntPtr GeneratorExit; -#endif -#if !(PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON2 public static IntPtr StandardError; #endif public static IntPtr ArithmeticError; @@ -677,10 +432,8 @@ puplic static variables on the Exceptions class filled in from public static IntPtr SyntaxWarning; public static IntPtr RuntimeWarning; public static IntPtr FutureWarning; -#if (PYTHON25 || PYTHON26 || PYTHON27 || PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) public static IntPtr ImportWarning; public static IntPtr UnicodeWarning; //PyAPI_DATA(PyObject *) PyExc_BytesWarning; -#endif } -} \ No newline at end of file +} diff --git a/src/runtime/extensiontype.cs b/src/runtime/extensiontype.cs index cd9db2338..91ff5be2e 100644 --- a/src/runtime/extensiontype.cs +++ b/src/runtime/extensiontype.cs @@ -52,7 +52,7 @@ public ExtensionType() : base() public static void FinalizeObject(ManagedType self) { Runtime.PyObject_GC_Del(self.pyHandle); - Runtime.Decref(self.tpHandle); + Runtime.XDecref(self.tpHandle); self.gcHandle.Free(); } diff --git a/src/runtime/importhook.cs b/src/runtime/importhook.cs index e8ac10f2b..bdef98c27 100644 --- a/src/runtime/importhook.cs +++ b/src/runtime/importhook.cs @@ -14,7 +14,7 @@ internal class ImportHook static CLRModule root; static MethodWrapper hook; -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON3 static IntPtr py_clr_module; static IntPtr module_def; #endif @@ -30,20 +30,20 @@ internal static void Initialize() // 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(); -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON3 IntPtr mod = Runtime.PyImport_ImportModule("builtins"); py_import = Runtime.PyObject_GetAttrString(mod, "__import__"); -#else +#elif PYTHON2 IntPtr mod = Runtime.PyDict_GetItemString(dict, "__builtin__"); py_import = Runtime.PyObject_GetAttrString(mod, "__import__"); #endif hook = new MethodWrapper(typeof(ImportHook), "__import__", "TernaryFunc"); Runtime.PyObject_SetAttrString(mod, "__import__", hook.ptr); - Runtime.Decref(hook.ptr); + Runtime.XDecref(hook.ptr); root = new CLRModule(); -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON3 // create a python module with the same methods as the clr module-like object module_def = ModuleDefOffset.AllocModuleDef("clr"); py_clr_module = Runtime.PyModule_Create2(module_def, 3); @@ -56,8 +56,8 @@ internal static void Initialize() Runtime.PyDict_Update(mod_dict, clr_dict); Runtime.PyDict_SetItemString(dict, "CLR", py_clr_module); Runtime.PyDict_SetItemString(dict, "clr", py_clr_module); -#else - Runtime.Incref(root.pyHandle); // we are using the module two times +#elif PYTHON2 + Runtime.XIncref(root.pyHandle); // we are using the module two times Runtime.PyDict_SetItemString(dict, "CLR", root.pyHandle); Runtime.PyDict_SetItemString(dict, "clr", root.pyHandle); #endif @@ -70,22 +70,22 @@ internal static void Initialize() internal static void Shutdown() { -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON3 if (0 != Runtime.Py_IsInitialized()) { - Runtime.Decref(py_clr_module); - Runtime.Decref(root.pyHandle); + Runtime.XDecref(py_clr_module); + Runtime.XDecref(root.pyHandle); } ModuleDefOffset.FreeModuleDef(module_def); -#else +#elif PYTHON2 if (0 != Runtime.Py_IsInitialized()) { - Runtime.Decref(root.pyHandle); - Runtime.Decref(root.pyHandle); + Runtime.XDecref(root.pyHandle); + Runtime.XDecref(root.pyHandle); } #endif if (0 != Runtime.Py_IsInitialized()) { - Runtime.Decref(py_import); + Runtime.XDecref(py_import); } } @@ -95,7 +95,7 @@ internal static void Shutdown() public static IntPtr GetCLRModule(IntPtr? fromList = null) { root.InitializePreload(); -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON3 // update the module dictionary with the contents of the root dictionary root.LoadNames(); IntPtr py_mod_dict = Runtime.PyModule_GetDict(py_clr_module); @@ -108,9 +108,9 @@ public static IntPtr GetCLRModule(IntPtr? fromList = null) if (fromList != null && fromList != IntPtr.Zero) { if (Runtime.PyTuple_Check(fromList.GetValueOrDefault())) { - Runtime.Incref(py_mod_dict); + Runtime.XIncref(py_mod_dict); using(PyDict mod_dict = new PyDict(py_mod_dict)) { - Runtime.Incref(fromList.GetValueOrDefault()); + Runtime.XIncref(fromList.GetValueOrDefault()); using (PyTuple from = new PyTuple(fromList.GetValueOrDefault())) { foreach (PyObject item in from) { if (mod_dict.HasKey(item)) @@ -124,7 +124,7 @@ public static IntPtr GetCLRModule(IntPtr? fromList = null) if (null == attr) continue; - Runtime.Incref(attr.pyHandle); + Runtime.XIncref(attr.pyHandle); using (PyObject obj = new PyObject(attr.pyHandle)) { mod_dict.SetItem(s, obj); } @@ -134,10 +134,10 @@ public static IntPtr GetCLRModule(IntPtr? fromList = null) } } - Runtime.Incref(py_clr_module); + Runtime.XIncref(py_clr_module); return py_clr_module; -#else - Runtime.Incref(root.pyHandle); +#elif PYTHON2 + Runtime.XIncref(root.pyHandle); return root.pyHandle; #endif } @@ -291,7 +291,7 @@ public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw) { if (fromlist) { - Runtime.Incref(module); + Runtime.XIncref(module); return module; } if (clr_prefix != null) @@ -299,7 +299,7 @@ public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw) return GetCLRModule(fromList); } module = Runtime.PyDict_GetItemString(modules, names[0]); - Runtime.Incref(module); + Runtime.XIncref(module); return module; } Exceptions.Clear(); @@ -361,11 +361,11 @@ public static IntPtr __import__(IntPtr self, IntPtr args, IntPtr kw) { mod.LoadNames(); } - Runtime.Decref(fp); + Runtime.XDecref(fp); } - Runtime.Incref(mod.pyHandle); + Runtime.XIncref(mod.pyHandle); return mod.pyHandle; } } -} \ No newline at end of file +} diff --git a/src/runtime/interop.cs b/src/runtime/interop.cs index f5fbe74b4..0657bc3e6 100644 --- a/src/runtime/interop.cs +++ b/src/runtime/interop.cs @@ -76,7 +76,7 @@ static ObjectOffset() { int size = IntPtr.Size; int n = 0; // Py_TRACE_REFS add two pointers to PyObject_HEAD -#if (Py_DEBUG) +#if Py_DEBUG _ob_next = 0; _ob_prev = 1 * size; n = 2; @@ -89,45 +89,39 @@ static ObjectOffset() public static int magic(IntPtr ob) { -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) if ((Runtime.PyObject_TypeCheck(ob, Exceptions.BaseException) || (Runtime.PyType_Check(ob) && Runtime.PyType_IsSubtype(ob, Exceptions.BaseException)))) { return ExceptionOffset.ob_data; } -#endif return ob_data; } public static int DictOffset(IntPtr ob) { -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) if ((Runtime.PyObject_TypeCheck(ob, Exceptions.BaseException) || (Runtime.PyType_Check(ob) && Runtime.PyType_IsSubtype(ob, Exceptions.BaseException)))) { return ExceptionOffset.ob_dict; } -#endif return ob_dict; } public static int Size(IntPtr ob) { -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) if ((Runtime.PyObject_TypeCheck(ob, Exceptions.BaseException) || (Runtime.PyType_Check(ob) && Runtime.PyType_IsSubtype(ob, Exceptions.BaseException)))) { return ExceptionOffset.Size(); } -#endif -#if (Py_DEBUG) +#if Py_DEBUG return 6 * IntPtr.Size; #else - return 4*IntPtr.Size; + return 4 * IntPtr.Size; #endif } -#if (Py_DEBUG) +#if Py_DEBUG public static int _ob_next; public static int _ob_prev; #endif @@ -137,7 +131,6 @@ public static int Size(IntPtr ob) private static int ob_data; } -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] internal class ExceptionOffset { @@ -161,18 +154,22 @@ public static int Size() // (start after PyObject_HEAD) public static int dict = 0; public static int args = 0; +#if PYTHON2 + public static int message = 0; +#elif PYTHON3 public static int traceback = 0; public static int context = 0; public static int cause = 0; + public static int suppress_context = 0; +#endif // extra c# data public static int ob_dict; public static int ob_data; } -#endif -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON3 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] internal class BytesOffset { @@ -189,7 +186,7 @@ static BytesOffset() /* The *real* layout of a type object when allocated on the heap */ //typedef struct _heaptypeobject { -#if (Py_DEBUG) // #ifdef Py_TRACE_REFS +#if Py_DEBUG // #ifdef Py_TRACE_REFS /* _PyObject_HEAD_EXTRA defines pointers to support a doubly-linked list of all live heap objects. */ public static int _ob_next = 0; public static int _ob_prev = 0; @@ -271,7 +268,7 @@ public static void FreeModuleDef(IntPtr ptr) { /// internal class TypeFlags { -#if (PYTHON23 || PYTHON24 || PYTHON25 || PYTHON26 || PYTHON27) +#if PYTHON2 // these flags were removed in Python 3 public static int HaveGetCharBuffer = (1 << 0); public static int HaveSequenceIn = (1 << 1); @@ -293,10 +290,7 @@ internal class TypeFlags /* XXX Reusing reserved constants */ public static int Managed = (1 << 15); // PythonNet specific public static int Subclass = (1 << 16); // PythonNet specific -#if (PYTHON25 || PYTHON26 || PYTHON27 || PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) public static int HaveIndex = (1 << 17); -#endif -#if (PYTHON26 || PYTHON27 || PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) /* Objects support nb_index in PyNumberMethods */ public static int HaveVersionTag = (1 << 18); public static int ValidVersionTag = (1 << 19); @@ -312,10 +306,9 @@ internal class TypeFlags public static int DictSubclass = (1 << 29); public static int BaseExceptionSubclass = (1 << 30); public static int TypeSubclass = (1 << 31); -#endif -// Default flags for Python 2 -#if (PYTHON23 || PYTHON24 || PYTHON25 || PYTHON26 || PYTHON27) +#if PYTHON2 + // Default flags for Python 2 public static int Default = ( HaveGetCharBuffer | HaveSequenceIn | @@ -325,14 +318,10 @@ internal class TypeFlags HaveIter | HaveClass | HaveStacklessExtension | -#if (PYTHON25 || PYTHON26 || PYTHON27) HaveIndex | -#endif 0); -#endif - -// Default flags for Python 3 -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#elif PYTHON3 + // Default flags for Python 3 public static int Default = ( HaveStacklessExtension | HaveVersionTag); @@ -395,7 +384,7 @@ static Interop() pmap["nb_add"] = p["BinaryFunc"]; pmap["nb_subtract"] = p["BinaryFunc"]; pmap["nb_multiply"] = p["BinaryFunc"]; -#if !(PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON2 pmap["nb_divide"] = p["BinaryFunc"]; #endif pmap["nb_remainder"] = p["BinaryFunc"]; @@ -420,7 +409,7 @@ static Interop() pmap["nb_inplace_add"] = p["BinaryFunc"]; pmap["nb_inplace_subtract"] = p["BinaryFunc"]; pmap["nb_inplace_multiply"] = p["BinaryFunc"]; -#if !(PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON2 pmap["nb_inplace_divide"] = p["BinaryFunc"]; #endif pmap["nb_inplace_remainder"] = p["BinaryFunc"]; @@ -434,9 +423,7 @@ static Interop() pmap["nb_true_divide"] = p["BinaryFunc"]; pmap["nb_inplace_floor_divide"] = p["BinaryFunc"]; pmap["nb_inplace_true_divide"] = p["BinaryFunc"]; -#if (PYTHON25 || PYTHON26 || PYTHON27 || PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) pmap["nb_index"] = p["UnaryFunc"]; -#endif pmap["sq_length"] = p["InquiryFunc"]; pmap["sq_concat"] = p["BinaryFunc"]; @@ -537,4 +524,4 @@ public Thunk(Delegate d) fn = d; } } -} \ No newline at end of file +} diff --git a/src/runtime/interop26.cs b/src/runtime/interop26.cs index a358b9ad6..71e3c5115 100644 --- a/src/runtime/interop26.cs +++ b/src/runtime/interop26.cs @@ -2,8 +2,7 @@ // DO NOT MODIFIY BY HAND. - -#if (PYTHON26) +#if PYTHON26 using System; using System.Collections; using System.Collections.Specialized; @@ -11,21 +10,24 @@ using System.Reflection; using System.Text; -namespace Python.Runtime { - - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)] - internal class TypeOffset { - - static TypeOffset() { +namespace Python.Runtime +{ + [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++) { + for (int i = 0; i < fi.Length; i++) + { fi[i].SetValue(null, i * size); } } - public static int magic() { + public static int magic() + { return ob_size; } @@ -144,4 +146,5 @@ public static int magic() { public static int members = 0; } } -#endif \ No newline at end of file + +#endif diff --git a/src/runtime/interop27.cs b/src/runtime/interop27.cs index 19006ab72..4782e9d3b 100644 --- a/src/runtime/interop27.cs +++ b/src/runtime/interop27.cs @@ -1,7 +1,8 @@ // Auto-generated by geninterop.py. // DO NOT MODIFIY BY HAND. -#if (PYTHON27) + +#if PYTHON27 using System; using System.Collections; using System.Collections.Specialized; @@ -21,7 +22,7 @@ static TypeOffset() int size = IntPtr.Size; for (int i = 0; i < fi.Length; i++) { - fi[i].SetValue(null, i*size); + fi[i].SetValue(null, i * size); } } @@ -146,4 +147,4 @@ public static int magic() } } -#endif \ No newline at end of file +#endif diff --git a/src/runtime/interop32.cs b/src/runtime/interop32.cs index 0c802c725..2f7464233 100644 --- a/src/runtime/interop32.cs +++ b/src/runtime/interop32.cs @@ -2,8 +2,7 @@ // DO NOT MODIFIY BY HAND. - -#if (PYTHON32) +#if PYTHON32 using System; using System.Collections; using System.Collections.Specialized; @@ -11,21 +10,24 @@ using System.Reflection; using System.Text; -namespace Python.Runtime { - - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)] - internal class TypeOffset { - - static TypeOffset() { +namespace Python.Runtime +{ + [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++) { + for (int i = 0; i < fi.Length; i++) + { fi[i].SetValue(null, i * size); } } - public static int magic() { + public static int magic() + { return ob_size; } @@ -135,4 +137,5 @@ public static int magic() { public static int members = 0; } } -#endif \ No newline at end of file + +#endif diff --git a/src/runtime/interop33.cs b/src/runtime/interop33.cs index 88e9022e4..f684df6c6 100644 --- a/src/runtime/interop33.cs +++ b/src/runtime/interop33.cs @@ -1,7 +1,8 @@ - // Auto-generated by geninterop.py. // DO NOT MODIFIY BY HAND. + +#if PYTHON33 using System; using System.Collections; using System.Collections.Specialized; @@ -9,21 +10,24 @@ using System.Reflection; using System.Text; -namespace Python.Runtime { - - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)] - internal class TypeOffset { - - static TypeOffset() { +namespace Python.Runtime +{ + [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++) { + for (int i = 0; i < fi.Length; i++) + { fi[i].SetValue(null, i * size); } } - public static int magic() { + public static int magic() + { return ob_size; } @@ -135,3 +139,5 @@ public static int magic() { public static int members = 0; } } + +#endif diff --git a/src/runtime/interop34.cs b/src/runtime/interop34.cs index 8e3d90bff..6857ff2d0 100644 --- a/src/runtime/interop34.cs +++ b/src/runtime/interop34.cs @@ -2,8 +2,7 @@ // DO NOT MODIFIY BY HAND. - -#if (PYTHON34) +#if PYTHON34 using System; using System.Collections; using System.Collections.Specialized; @@ -11,21 +10,24 @@ using System.Reflection; using System.Text; -namespace Python.Runtime { - - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)] - internal class TypeOffset { - - static TypeOffset() { +namespace Python.Runtime +{ + [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++) { + for (int i = 0; i < fi.Length; i++) + { fi[i].SetValue(null, i * size); } } - public static int magic() { + public static int magic() + { return ob_size; } @@ -138,4 +140,5 @@ public static int magic() { public static int members = 0; } } -#endif \ No newline at end of file + +#endif diff --git a/src/runtime/interop35.cs b/src/runtime/interop35.cs index a0f0f3153..a30bfa4fd 100644 --- a/src/runtime/interop35.cs +++ b/src/runtime/interop35.cs @@ -2,8 +2,7 @@ // DO NOT MODIFIY BY HAND. - -#if (PYTHON35) +#if PYTHON35 using System; using System.Collections; using System.Collections.Specialized; @@ -11,21 +10,24 @@ using System.Reflection; using System.Text; -namespace Python.Runtime { - - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)] - internal class TypeOffset { - - static TypeOffset() { +namespace Python.Runtime +{ + [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++) { + for (int i = 0; i < fi.Length; i++) + { fi[i].SetValue(null, i * size); } } - public static int magic() { + public static int magic() + { return ob_size; } @@ -143,4 +145,5 @@ public static int magic() { public static int members = 0; } } -#endif \ No newline at end of file + +#endif diff --git a/src/runtime/interop36.cs b/src/runtime/interop36.cs new file mode 100644 index 000000000..c46bcc2f5 --- /dev/null +++ b/src/runtime/interop36.cs @@ -0,0 +1,149 @@ +// Auto-generated by geninterop.py. +// DO NOT MODIFIY BY HAND. + + +#if PYTHON36 +using System; +using System.Collections; +using System.Collections.Specialized; +using System.Runtime.InteropServices; +using System.Reflection; +using System.Text; + +namespace Python.Runtime +{ + [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; + } + + // Auto-generated from PyHeapTypeObject in Python.h + 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_as_async = 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 tp_version_tag = 0; + public static int tp_finalize = 0; + public static int am_await = 0; + public static int am_aiter = 0; + public static int am_anext = 0; + public static int nb_add = 0; + public static int nb_subtract = 0; + public static int nb_multiply = 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_bool = 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_int = 0; + public static int nb_reserved = 0; + public static int nb_float = 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_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 nb_index = 0; + public static int nb_matrix_multiply = 0; + public static int nb_inplace_matrix_multiply = 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 was_sq_slice = 0; + public static int sq_ass_item = 0; + public static int was_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_getbuffer = 0; + public static int bf_releasebuffer = 0; + public static int name = 0; + public static int ht_slots = 0; + public static int qualname = 0; + public static int ht_cached_keys = 0; + + /* here are optional user slots, followed by the members. */ + public static int members = 0; + } +} + +#endif diff --git a/src/runtime/iterator.cs b/src/runtime/iterator.cs index 8fc9b0312..c9b232e5e 100644 --- a/src/runtime/iterator.cs +++ b/src/runtime/iterator.cs @@ -37,7 +37,7 @@ public static IntPtr tp_iternext(IntPtr ob) public static IntPtr tp_iter(IntPtr ob) { - Runtime.Incref(ob); + Runtime.XIncref(ob); return ob; } } diff --git a/src/runtime/managedtype.cs b/src/runtime/managedtype.cs index 83131281d..782865f93 100644 --- a/src/runtime/managedtype.cs +++ b/src/runtime/managedtype.cs @@ -41,20 +41,6 @@ internal static ManagedType GetManagedObject(IntPtr ob) GCHandle gc = (GCHandle)op; return (ManagedType)gc.Target; } - - // In certain situations, we need to recognize a wrapped - // exception class and be willing to unwrap the class :( - - if (Runtime.wrap_exceptions) - { - IntPtr e = Exceptions.UnwrapExceptionClass(ob); - if ((e != IntPtr.Zero) && (e != ob)) - { - ManagedType m = GetManagedObject(e); - Runtime.Decref(e); - return m; - } - } } return null; } diff --git a/src/runtime/metatype.cs b/src/runtime/metatype.cs index 8b062ee59..b2ad78078 100644 --- a/src/runtime/metatype.cs +++ b/src/runtime/metatype.cs @@ -92,7 +92,7 @@ public static IntPtr tp_new(IntPtr tp, IntPtr args, IntPtr kw) // into python. if (IntPtr.Zero != dict) { - Runtime.Incref(dict); + Runtime.XIncref(dict); using (PyDict clsDict = new PyDict(dict)) { if (clsDict.HasKey("__assembly__") || clsDict.HasKey("__namespace__")) @@ -171,7 +171,7 @@ public static IntPtr tp_call(IntPtr tp, IntPtr args, IntPtr kw) 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.XDecref(py__init__); Runtime.PyErr_Clear(); if (init != IntPtr.Zero) @@ -179,20 +179,20 @@ public static IntPtr tp_call(IntPtr tp, IntPtr args, IntPtr kw) IntPtr bound = Runtime.GetBoundArgTuple(obj, args); if (bound == IntPtr.Zero) { - Runtime.Decref(obj); + Runtime.XDecref(obj); return IntPtr.Zero; } IntPtr result = Runtime.PyObject_Call(init, bound, kw); - Runtime.Decref(bound); + Runtime.XDecref(bound); if (result == IntPtr.Zero) { - Runtime.Decref(obj); + Runtime.XDecref(obj); return IntPtr.Zero; } - Runtime.Decref(result); + Runtime.XDecref(result); } return obj; @@ -214,22 +214,30 @@ public static int tp_setattro(IntPtr tp, IntPtr name, IntPtr value) if (descr != IntPtr.Zero) { IntPtr dt = Runtime.PyObject_TYPE(descr); - IntPtr fp = Marshal.ReadIntPtr(dt, TypeOffset.tp_descr_set); - if (fp != IntPtr.Zero) + + if (dt == Runtime.PyWrapperDescriptorType + || dt == Runtime.PyMethodType + || typeof(ExtensionType).IsInstanceOfType(GetManagedObject(descr)) + ) { - return NativeCall.Impl.Int_Call_3(fp, descr, name, value); + IntPtr fp = Marshal.ReadIntPtr(dt, TypeOffset.tp_descr_set); + if (fp != IntPtr.Zero) + { + return NativeCall.Impl.Int_Call_3(fp, descr, name, value); + } + else + { + Exceptions.SetError(Exceptions.AttributeError, + "attribute is read-only"); + return -1; + } } - Exceptions.SetError(Exceptions.AttributeError, - "attribute is read-only"); - return -1; } - if (Runtime.PyObject_GenericSetAttr(tp, name, value) < 0) - { - return -1; - } + var res = Runtime.PyObject_GenericSetAttr(tp, name, value); + Runtime.PyType_Modified(tp); - return 0; + return res; } //==================================================================== @@ -264,7 +272,7 @@ public static void tp_dealloc(IntPtr tp) } IntPtr op = Marshal.ReadIntPtr(tp, TypeOffset.ob_type); - Runtime.Decref(op); + Runtime.XDecref(op); // Delegate the rest of finalization the Python metatype. Note // that the PyType_Type implementation of tp_dealloc will call @@ -282,7 +290,10 @@ static IntPtr DoInstanceCheck(IntPtr tp, IntPtr args, bool checkType) ClassBase cb = GetManagedObject(tp) as ClassBase; if (cb == null) + { + Runtime.XIncref(Runtime.PyFalse); return Runtime.PyFalse; + } using (PyList argsObj = new PyList(args)) { @@ -297,11 +308,17 @@ static IntPtr DoInstanceCheck(IntPtr tp, IntPtr args, bool checkType) otherType = arg.GetPythonType(); if (Runtime.PyObject_TYPE(otherType.Handle) != PyCLRMetaType) + { + Runtime.XIncref(Runtime.PyFalse); return Runtime.PyFalse; + } ClassBase otherCb = GetManagedObject(otherType.Handle) as ClassBase; if (otherCb == null) + { + Runtime.XIncref(Runtime.PyFalse); return Runtime.PyFalse; + } return Converter.ToPython(cb.type.IsAssignableFrom(otherCb.type)); } @@ -317,4 +334,4 @@ public static IntPtr __subclasscheck__(IntPtr tp, IntPtr args) return DoInstanceCheck(tp, args, true); } } -} \ No newline at end of file +} diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index 22aaf33e4..c3b3e4a70 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -337,7 +337,7 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, { clrtype = Converter.GetTypeByAlias(pyoptype); } - Runtime.Decref(pyoptype); + Runtime.XDecref(pyoptype); } @@ -372,7 +372,7 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, clrtype = pi[n].ParameterType; } } - Runtime.Decref(pyoptype); + Runtime.XDecref(pyoptype); if (!typematch) { margs = null; @@ -405,7 +405,7 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, { // GetSlice() creates a new reference but GetItem() // returns only a borrow reference. - Runtime.Decref(op); + Runtime.XDecref(op); } margs[n] = arg; } @@ -551,8 +551,8 @@ internal virtual IntPtr Invoke(IntPtr inst, IntPtr args, IntPtr kw, if ((binding.outs == 1) && (mi.ReturnType == typeof(void))) { v = Runtime.PyTuple_GetItem(t, 1); - Runtime.Incref(v); - Runtime.Decref(t); + Runtime.XIncref(v); + Runtime.XDecref(t); return v; } diff --git a/src/runtime/methodbinding.cs b/src/runtime/methodbinding.cs index a5f1a5964..d8fec069c 100644 --- a/src/runtime/methodbinding.cs +++ b/src/runtime/methodbinding.cs @@ -19,10 +19,10 @@ internal class MethodBinding : ExtensionType public MethodBinding(MethodObject m, IntPtr target, IntPtr targetType) : base() { - Runtime.Incref(target); + Runtime.XIncref(target); this.target = target; - Runtime.Incref(targetType); + Runtime.XIncref(targetType); if (targetType == IntPtr.Zero) targetType = Runtime.PyObject_Type(target); this.targetType = targetType; @@ -58,7 +58,7 @@ public static IntPtr mp_subscript(IntPtr tp, IntPtr idx) MethodBinding mb = new MethodBinding(self.m, self.target); mb.info = mi; - Runtime.Incref(mb.pyHandle); + Runtime.XIncref(mb.pyHandle); return mb.pyHandle; } @@ -81,7 +81,7 @@ public static IntPtr tp_getattro(IntPtr ob, IntPtr key) if (name == "__doc__") { IntPtr doc = self.m.GetDocString(); - Runtime.Incref(doc); + Runtime.XIncref(doc); return doc; } @@ -89,7 +89,7 @@ public static IntPtr tp_getattro(IntPtr ob, IntPtr key) if (name == "__overloads__" || name == "Overloads") { OverloadMapper om = new OverloadMapper(self.m, self.target); - Runtime.Incref(om.pyHandle); + Runtime.XIncref(om.pyHandle); return om.pyHandle; } @@ -140,7 +140,7 @@ public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) return IntPtr.Zero; } target = Runtime.PyTuple_GetItem(args, 0); - Runtime.Incref(target); + Runtime.XIncref(target); disposeList.Add(target); args = Runtime.PyTuple_GetSlice(args, 1, len); @@ -166,7 +166,7 @@ public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) MethodBinding baseSelf = GetManagedObject(baseMethod) as MethodBinding; if (baseSelf != null) self = baseSelf; - Runtime.Decref(baseMethod); + Runtime.XDecref(baseMethod); } else { @@ -181,7 +181,7 @@ public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) finally { foreach (IntPtr ptr in disposeList) - Runtime.Decref(ptr); + Runtime.XDecref(ptr); } } @@ -240,8 +240,8 @@ public static IntPtr tp_repr(IntPtr ob) public static new void tp_dealloc(IntPtr ob) { MethodBinding self = (MethodBinding)GetManagedObject(ob); - Runtime.Decref(self.target); - Runtime.Decref(self.targetType); + Runtime.XDecref(self.target); + Runtime.XDecref(self.targetType); ExtensionType.FinalizeObject(self); } } diff --git a/src/runtime/methodobject.cs b/src/runtime/methodobject.cs index 269f8112f..20f757d58 100644 --- a/src/runtime/methodobject.cs +++ b/src/runtime/methodobject.cs @@ -127,7 +127,7 @@ public static IntPtr tp_getattro(IntPtr ob, IntPtr key) if (name == "__doc__") { IntPtr doc = self.GetDocString(); - Runtime.Incref(doc); + Runtime.XIncref(doc); return doc; } @@ -155,7 +155,7 @@ public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) self.unbound = new MethodBinding(self, IntPtr.Zero, tp); } binding = self.unbound; - Runtime.Incref(binding.pyHandle); + Runtime.XIncref(binding.pyHandle); ; return binding.pyHandle; } @@ -202,10 +202,10 @@ public static IntPtr tp_repr(IntPtr ob) public static new void tp_dealloc(IntPtr ob) { MethodObject self = (MethodObject)GetManagedObject(ob); - Runtime.Decref(self.doc); + Runtime.XDecref(self.doc); if (self.unbound != null) { - Runtime.Decref(self.unbound.pyHandle); + Runtime.XDecref(self.unbound.pyHandle); } ExtensionType.FinalizeObject(self); } diff --git a/src/runtime/moduleobject.cs b/src/runtime/moduleobject.cs index c2ddf564b..87e3ed2f1 100644 --- a/src/runtime/moduleobject.cs +++ b/src/runtime/moduleobject.cs @@ -51,9 +51,9 @@ public ModuleObject(string name) : base() Runtime.PyDict_SetItemString(dict, "__file__", pyfilename); Runtime.PyDict_SetItemString(dict, "__doc__", pydocstring); Runtime.PyDict_SetItemString(dict, "__class__", pycls); - Runtime.Decref(pyname); - Runtime.Decref(pyfilename); - Runtime.Decref(pydocstring); + Runtime.XDecref(pyname); + Runtime.XDecref(pyfilename); + Runtime.XDecref(pydocstring); Marshal.WriteIntPtr(this.pyHandle, ObjectOffset.DictOffset(this.pyHandle), dict); @@ -202,20 +202,6 @@ public void LoadNames() if (m == null) { ManagedType attr = this.GetAttribute(name, true); - if (Runtime.wrap_exceptions) - { - if (attr is ExceptionClassObject) - { - ExceptionClassObject c = attr as ExceptionClassObject; - if (c != null) - { - IntPtr p = attr.pyHandle; - IntPtr r = Exceptions.GetExceptionClassWrapper(p); - Runtime.PyDict_SetItemString(dict, name, r); - Runtime.Incref(r); - } - } - } } } } @@ -288,14 +274,14 @@ public static IntPtr tp_getattro(IntPtr ob, IntPtr key) IntPtr op = Runtime.PyDict_GetItem(self.dict, key); if (op != IntPtr.Zero) { - Runtime.Incref(op); + Runtime.XIncref(op); return op; } string name = Runtime.GetManagedString(key); if (name == "__dict__") { - Runtime.Incref(self.dict); + Runtime.XIncref(self.dict); return self.dict; } @@ -307,27 +293,7 @@ public static IntPtr tp_getattro(IntPtr ob, IntPtr key) 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 ExceptionClassObject) - { - ExceptionClassObject c = attr as ExceptionClassObject; - if (c != null) - { - 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); + Runtime.XIncref(attr.pyHandle); return attr.pyHandle; } @@ -371,7 +337,7 @@ public CLRModule() : base("clr") 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); + Runtime.XDecref(mro); hacked = true; } } diff --git a/src/runtime/monosupport.cs b/src/runtime/monosupport.cs index 8a5044829..52c2921da 100644 --- a/src/runtime/monosupport.cs +++ b/src/runtime/monosupport.cs @@ -1,4 +1,4 @@ -#if (UCS4) +#if UCS4 using System; using System.Runtime.InteropServices; using System.Text; @@ -50,4 +50,4 @@ public object MarshalNativeToManaged(IntPtr } } -#endif \ No newline at end of file +#endif diff --git a/src/runtime/oldmodule.il b/src/runtime/oldmodule.il deleted file mode 100644 index b9e3883c9..000000000 --- a/src/runtime/oldmodule.il +++ /dev/null @@ -1,266 +0,0 @@ - -//============================================================================ -// 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 to do initialization and put the clr module into sys.modules, etc. - -// The "USE_PYTHON_RUNTIME_*" defines control what extra evidence is used -// to help the CLR find the appropriate Python.Runtime assembly. - -// If defined, the "pythonRuntimeVersionString" variable must be set to -// Python.Runtime's current version. -#define USE_PYTHON_RUNTIME_VERSION - -// If defined, the "PythonRuntimePublicKeyTokenData" data array must be -// set to Python.Runtime's public key token. -//#define USE_PYTHON_RUNTIME_PUBLIC_KEY_TOKEN - -// If DEBUG_PRINT is defined, a few System.Console.WriteLine calls are made -// to indicate what's going on during the load... -//#define DEBUG_PRINT -//============================================================================ - -.assembly extern mscorlib -{ - .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) - .ver 2:0:0:0 -} - -.assembly clr -{ - .hash algorithm 0x00008004 - .ver 2:0:0:2 -} - -.module clr.dll -.imagebase 0x00400000 -.subsystem 0x00000003 -.file alignment 512 - -// This includes the platform-specific IL. The include search path -// is set depending on whether we're compiling 32 or 64 bit. -// This MUST come before any other .data directives! -// Why, oh why, can't ilasm support command line #defines? :( -#include "clrmodule-platform.il" - -#ifdef USE_PYTHON_RUNTIME_PUBLIC_KEY_TOKEN -.data PythonRuntimePublicKeyTokenData = bytearray (64 e1 4e 84 5a bf 2e 60) -#endif - -.class public auto ansi beforefieldinit clrModule extends [mscorlib]System.Object -{ -#ifdef USE_PYTHON_RUNTIME_PUBLIC_KEY_TOKEN - .field static assembly int64 PythonRuntimePublicKeyToken at PythonRuntimePublicKeyTokenData -#endif - - .method public hidebysig specialname rtspecialname instance void - .ctor() cil managed - { - .maxstack 1 - ldarg.0 - call instance void [mscorlib]System.Object::.ctor() - ret - } - - .method public hidebysig static void modopt([mscorlib]System.Runtime.CompilerServices.CallConvCdecl) - initclr() cil managed - { - .vtentry 1:1 - .export [1] as initclr - - .maxstack 6 - .locals init ( - class [mscorlib]System.Reflection.Assembly pythonRuntime, - class [mscorlib]System.Reflection.Assembly executingAssembly, - class [mscorlib]System.Reflection.AssemblyName pythonRuntimeName, - class [mscorlib]System.Type pythonEngineType, - int8[] publicKeyToken, - string assemblyDirectory, - string pythonRuntimeVersionString, - string pythonRuntimeDllPath) - - // pythonRuntime = null; - ldnull - stloc pythonRuntime - - .try - { -#ifdef DEBUG_PRINT - ldstr "Attempting to load Python.Runtime using standard binding rules... " - call void [mscorlib]System.Console::Write(string) -#endif - - // Attempt to find and load Python.Runtime using standard assembly binding rules. - // This roughly translates into looking in order: - // - GAC - // - ApplicationBase - // - A PrivateBinPath under ApplicationBase - // With an unsigned assembly, the GAC is skipped. - - // System.Reflection.AssemblyName pythonRuntimeName = new System.Reflection.AssemblyName(); - newobj instance void [mscorlib]System.Reflection.AssemblyName::.ctor() - stloc pythonRuntimeName - - // pythonRuntimeName.Name = "Python.Runtime"; - ldloc pythonRuntimeName - ldstr "Python.Runtime" - callvirt instance void [mscorlib]System.Reflection.AssemblyName::set_Name(string) - -#ifdef USE_PYTHON_RUNTIME_VERSION - // pythonRuntimeVersionString = "..."; - ldstr "2.0.0.2" - stloc pythonRuntimeVersionString - - // pythonRuntimeName.Version = new Version(pythonRuntimeVersionString); - ldloc pythonRuntimeName - ldloc pythonRuntimeVersionString - newobj instance void [mscorlib]System.Version::.ctor(string) - callvirt instance void [mscorlib]System.Reflection.AssemblyName::set_Version(class [mscorlib]System.Version) -#endif - -#ifdef USE_PYTHON_RUNTIME_PUBLIC_KEY_TOKEN - // publicKeyToken = new byte[] { ... }; - ldc.i4.8 - newarr [mscorlib]System.Byte - dup - ldtoken field int64 clrModule::PythonRuntimePublicKeyToken - call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype [mscorlib]System.RuntimeFieldHandle) - stloc publicKeyToken - - // pythonRuntimeName.SetPublicKeyToken(publicKeyToken); - ldloc pythonRuntimeName - ldloc publicKeyToken - callvirt instance void [mscorlib]System.Reflection.AssemblyName::SetPublicKeyToken(uint8[]) -#endif - - // pythonRuntimeName.CultureInfo = System.Globalization.CultureInfo.InvariantCulture; - ldloc pythonRuntimeName - call class [mscorlib]System.Globalization.CultureInfo [mscorlib]System.Globalization.CultureInfo::get_InvariantCulture() - callvirt instance void [mscorlib]System.Reflection.AssemblyName::set_CultureInfo(class [mscorlib]System.Globalization.CultureInfo) - - // return System.Reflection.Assembly.Load(pythonRuntimeName); - ldloc pythonRuntimeName - call class [mscorlib]System.Reflection.Assembly [mscorlib]System.Reflection.Assembly::Load(class [mscorlib]System.Reflection.AssemblyName) - stloc pythonRuntime - -#ifdef DEBUG_PRINT - ldstr "Success!" - call void [mscorlib]System.Console::WriteLine(string) -#endif - leave.s LOADED_PYTHON_RUNTIME - } - catch [mscorlib]System.Object - { -#ifdef DEBUG_PRINT - ldstr "Failed." - call void [mscorlib]System.Console::WriteLine(string) -#endif - leave.s EXIT_CLR_LOAD - } - EXIT_CLR_LOAD: nop - - .try - { - // If the above fails for any reason, we fallback to attempting to load "Python.Runtime.dll" - // from the directory this assembly is running in. "This assembly" is probably "clr.pyd", - // sitting somewhere in PYTHONPATH. This is using Assembly.LoadFrom, and inherits all the - // caveats of that call. See MSDN docs for details. - // Suzanne Cook's blog is also an excellent source of info on this: - // http://blogs.msdn.com/suzcook/ - // http://blogs.msdn.com/suzcook/archive/2003/05/29/57143.aspx - // http://blogs.msdn.com/suzcook/archive/2003/06/13/57180.aspx - // executingAssembly = System.Reflection.Assembly.GetExecutingAssembly(); - call class [mscorlib]System.Reflection.Assembly [mscorlib]System.Reflection.Assembly::GetExecutingAssembly() - stloc executingAssembly - - // assemblyDirectory = System.IO.Path.GetDirectoryName(executingAssembly.Location); - ldloc executingAssembly - callvirt instance string [mscorlib]System.Reflection.Assembly::get_Location() - call string [mscorlib]System.IO.Path::GetDirectoryName(string) - stloc assemblyDirectory - - // pythonRuntimeDllPath = System.IO.Path.Combine(assemblyDirectory, "Python.Runtime.dll"); - ldloc assemblyDirectory - ldstr "Python.Runtime.dll" - call string [mscorlib]System.IO.Path::Combine(string, string) - stloc pythonRuntimeDllPath - -#ifdef DEBUG_PRINT - ldstr "Attempting to load Python.Runtime from: '{0}'... " - ldloc pythonRuntimeDllPath - call void [mscorlib]System.Console::Write(string, object) -#endif - - // pythonRuntime = System.Reflection.Assembly.LoadFrom(pythonRuntimeDllPath); - ldloc pythonRuntimeDllPath - call class [mscorlib]System.Reflection.Assembly [mscorlib]System.Reflection.Assembly::LoadFrom(string) - stloc pythonRuntime - -#ifdef DEBUG_PRINT - ldstr "Success!" - call void [mscorlib]System.Console::WriteLine(string) -#endif - leave.s LOADED_PYTHON_RUNTIME - } - catch [mscorlib]System.Object - { -#ifdef DEBUG_PRINT - ldstr "Failed." - call void [mscorlib]System.Console::WriteLine(string) -#endif - leave.s EXIT_PYTHONPATH_LOAD - } - EXIT_PYTHONPATH_LOAD: nop - - // If we get here, we haven't loaded Python.Runtime, so bail. -#ifdef DEBUG_PRINT - ldstr "Could not load Python.Runtime, so sad." - call void [mscorlib]System.Console::WriteLine(string) -#endif - ret; - - // Once here, we've successfully loaded SOME version of Python.Runtime - // So now we get the PythonEngine and execute the InitExt method on it. - LOADED_PYTHON_RUNTIME: nop - .try - { -#ifdef DEBUG_PRINT - ldstr "Running Python.Runtime.PythonEngine.InitExt()" - call void [mscorlib]System.Console::WriteLine(string) -#endif - // pythonEngineType = pythonRuntime.GetType("Python.Runtime.PythonEngine"); - ldloc pythonRuntime - ldstr "Python.Runtime.PythonEngine" - callvirt instance class [mscorlib]System.Type [mscorlib]System.Reflection.Assembly::GetType(string) - stloc pythonEngineType - - // pythonEngineType.InvokeMember("InitExt", System.Reflection.BindingFlags.InvokeMethod, null, null, null); - ldloc pythonEngineType - ldstr "InitExt" - ldc.i4 0x100 - ldnull - ldnull - ldnull - callvirt instance object [mscorlib]System.Type::InvokeMember( string, - valuetype [mscorlib]System.Reflection.BindingFlags, - class [mscorlib]System.Reflection.Binder, - object, - object[]) - pop - leave.s EXIT_TRY_INVOKE - } - catch [mscorlib]System.Object - { -#ifdef DEBUG_PRINT - ldstr "Error calling Python.Runtime.PythonEngine.InitExt()." - call void [mscorlib]System.Console::WriteLine(string) -#endif - leave.s EXIT_TRY_INVOKE - } - EXIT_TRY_INVOKE: nop - - ret - } -} - diff --git a/src/runtime/overload.cs b/src/runtime/overload.cs index 2399e9c63..2a339df66 100644 --- a/src/runtime/overload.cs +++ b/src/runtime/overload.cs @@ -15,7 +15,7 @@ internal class OverloadMapper : ExtensionType public OverloadMapper(MethodObject m, IntPtr target) : base() { - Runtime.Incref(target); + Runtime.XIncref(target); this.target = target; this.m = m; } @@ -47,7 +47,7 @@ public static IntPtr mp_subscript(IntPtr tp, IntPtr idx) MethodBinding mb = new MethodBinding(self.m, self.target); mb.info = mi; - Runtime.Incref(mb.pyHandle); + Runtime.XIncref(mb.pyHandle); return mb.pyHandle; } @@ -59,7 +59,7 @@ public static IntPtr tp_repr(IntPtr op) { OverloadMapper self = (OverloadMapper)GetManagedObject(op); IntPtr doc = self.m.GetDocString(); - Runtime.Incref(doc); + Runtime.XIncref(doc); return doc; } @@ -70,7 +70,7 @@ public static IntPtr tp_repr(IntPtr op) public static new void tp_dealloc(IntPtr ob) { OverloadMapper self = (OverloadMapper)GetManagedObject(ob); - Runtime.Decref(self.target); + Runtime.XDecref(self.target); ExtensionType.FinalizeObject(self); } } diff --git a/src/runtime/pyansistring.cs b/src/runtime/pyansistring.cs index dc83a29a1..1a2cb7955 100644 --- a/src/runtime/pyansistring.cs +++ b/src/runtime/pyansistring.cs @@ -34,7 +34,7 @@ public PyAnsiString(PyObject o) { throw new ArgumentException("object is not a string"); } - Runtime.Incref(o.obj); + Runtime.XIncref(o.obj); obj = o.obj; } diff --git a/src/runtime/pydict.cs b/src/runtime/pydict.cs index 781d965f1..fc8b98377 100644 --- a/src/runtime/pydict.cs +++ b/src/runtime/pydict.cs @@ -55,7 +55,7 @@ public PyDict(PyObject o) : base() { throw new ArgumentException("object is not a dict"); } - Runtime.Incref(o.obj); + Runtime.XIncref(o.obj); obj = o.obj; } diff --git a/src/runtime/pyfloat.cs b/src/runtime/pyfloat.cs index c6bccf5ec..27a13f184 100644 --- a/src/runtime/pyfloat.cs +++ b/src/runtime/pyfloat.cs @@ -38,7 +38,7 @@ public PyFloat(PyObject o) : base() { throw new ArgumentException("object is not a float"); } - Runtime.Incref(o.obj); + Runtime.XIncref(o.obj); obj = o.obj; } diff --git a/src/runtime/pyint.cs b/src/runtime/pyint.cs index d7a6e51e7..935f54a8b 100644 --- a/src/runtime/pyint.cs +++ b/src/runtime/pyint.cs @@ -38,7 +38,7 @@ public PyInt(PyObject o) : base() { throw new ArgumentException("object is not an int"); } - Runtime.Incref(o.obj); + Runtime.XIncref(o.obj); obj = o.obj; } diff --git a/src/runtime/pylist.cs b/src/runtime/pylist.cs index 9ab99deb3..bdbc806fd 100644 --- a/src/runtime/pylist.cs +++ b/src/runtime/pylist.cs @@ -37,7 +37,7 @@ public PyList(PyObject o) : base() { throw new ArgumentException("object is not a list"); } - Runtime.Incref(o.obj); + Runtime.XIncref(o.obj); obj = o.obj; } @@ -73,7 +73,7 @@ public PyList(PyObject[] items) : base() for (int i = 0; i < count; i++) { IntPtr ptr = items[i].obj; - Runtime.Incref(ptr); + Runtime.XIncref(ptr); int r = Runtime.PyList_SetItem(obj, i, ptr); if (r < 0) { diff --git a/src/runtime/pylong.cs b/src/runtime/pylong.cs index a68a5bc7a..63c613402 100644 --- a/src/runtime/pylong.cs +++ b/src/runtime/pylong.cs @@ -37,7 +37,7 @@ public PyLong(PyObject o) : base() { throw new ArgumentException("object is not a long"); } - Runtime.Incref(o.obj); + Runtime.XIncref(o.obj); obj = o.obj; } diff --git a/src/runtime/pyobject.cs b/src/runtime/pyobject.cs index 308e71ffb..781f6313d 100644 --- a/src/runtime/pyobject.cs +++ b/src/runtime/pyobject.cs @@ -73,7 +73,7 @@ public static PyObject FromManagedObject(object ob) // Special case: if ob is null, we return None. if (ob == null) { - Runtime.Incref(Runtime.PyNone); + Runtime.XIncref(Runtime.PyNone); return new PyObject(Runtime.PyNone); } IntPtr op = CLRObject.GetInstHandle(ob); @@ -119,14 +119,14 @@ protected virtual void Dispose(bool disposing) if (Runtime.Py_IsInitialized() > 0) { IntPtr gs = PythonEngine.AcquireLock(); - Runtime.Decref(obj); + Runtime.XDecref(obj); obj = IntPtr.Zero; PythonEngine.ReleaseLock(gs); } disposed = true; } } - + public void Dispose() { Dispose(true); @@ -872,7 +872,7 @@ public string Repr() { IntPtr strval = Runtime.PyObject_Repr(obj); string result = Runtime.GetManagedString(strval); - Runtime.Decref(strval); + Runtime.XDecref(strval); return result; } @@ -889,7 +889,7 @@ public override string ToString() { IntPtr strval = Runtime.PyObject_Unicode(obj); string result = Runtime.GetManagedString(strval); - Runtime.Decref(strval); + Runtime.XDecref(strval); return result; } @@ -968,7 +968,7 @@ private void GetArgs(object[] inargs, out PyTuple args, out PyDict kwargs) if (inargs[i] is PyObject) { ptr = ((PyObject)inargs[i]).Handle; - Runtime.Incref(ptr); + Runtime.XIncref(ptr); } else { diff --git a/src/runtime/pystring.cs b/src/runtime/pystring.cs index 737fa36be..46b8fd657 100644 --- a/src/runtime/pystring.cs +++ b/src/runtime/pystring.cs @@ -38,7 +38,7 @@ public PyString(PyObject o) : base() { throw new ArgumentException("object is not a string"); } - Runtime.Incref(o.obj); + Runtime.XIncref(o.obj); obj = o.obj; } diff --git a/src/runtime/pythonengine.cs b/src/runtime/pythonengine.cs index cf9bfb9ee..4c676d375 100644 --- a/src/runtime/pythonengine.cs +++ b/src/runtime/pythonengine.cs @@ -165,7 +165,7 @@ public static void Initialize() Runtime.PyDict_SetItemString(clr_dict, "_extras", module); foreach (PyObject key in locals.Keys()) { - if (!key.ToString().StartsWith("_")) + if (!key.ToString().StartsWith("_") || key.ToString().Equals("__version__")) { PyObject value = locals[key]; Runtime.PyDict_SetItem(clr_dict, key.Handle, value.Handle); @@ -186,9 +186,9 @@ public static void Initialize() // CPython interpreter process - this bootstraps the managed runtime // when it is imported by the CLR extension module. //==================================================================== -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON3 public static IntPtr InitExt() { -#else +#elif PYTHON2 public static void InitExt() { #endif @@ -234,12 +234,12 @@ public static void InitExt() catch (PythonException e) { e.Restore(); -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON3 return IntPtr.Zero; #endif } -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON3 return Python.Runtime.ImportHook.GetCLRModule(); #endif } @@ -421,7 +421,7 @@ public static PyObject RunString(string code) IntPtr flag = (IntPtr)257; /* Py_file_input */ IntPtr result = Runtime.PyRun_String(code, flag, globals, locals); - Runtime.Decref(locals); + Runtime.XDecref(locals); if (result == IntPtr.Zero) { return null; @@ -491,7 +491,7 @@ public static KeywordArguments kw(params object[] kv) if (Runtime.PyDict_SetItemString(dict.Handle, (string)kv[i], value) != 0) throw new ArgumentException(string.Format("Cannot add key '{0}' to dictionary.", (string)kv[i])); if (!(kv[i + 1] is PyObject)) - Runtime.Decref(value); + Runtime.XDecref(value); } return dict; } @@ -501,4 +501,4 @@ public static PyObject Import(string name) return PythonEngine.ImportModule(name); } } -} \ No newline at end of file +} diff --git a/src/runtime/pythonexception.cs b/src/runtime/pythonexception.cs index b4b50f4f8..2999432c1 100644 --- a/src/runtime/pythonexception.cs +++ b/src/runtime/pythonexception.cs @@ -19,21 +19,21 @@ public PythonException() : base() { IntPtr gs = PythonEngine.AcquireLock(); Runtime.PyErr_Fetch(ref _pyType, ref _pyValue, ref _pyTB); - Runtime.Incref(_pyType); - Runtime.Incref(_pyValue); - Runtime.Incref(_pyTB); + Runtime.XIncref(_pyType); + Runtime.XIncref(_pyValue); + Runtime.XIncref(_pyTB); if ((_pyType != IntPtr.Zero) && (_pyValue != IntPtr.Zero)) { string type; string message; - Runtime.Incref(_pyType); + Runtime.XIncref(_pyType); using (PyObject pyType = new PyObject(_pyType)) using (PyObject pyTypeName = pyType.GetAttr("__name__")) { type = pyTypeName.ToString(); } - Runtime.Incref(_pyValue); + Runtime.XIncref(_pyValue); using (PyObject pyValue = new PyObject(_pyValue)) { message = pyValue.ToString(); @@ -43,7 +43,7 @@ public PythonException() : base() if (_pyTB != IntPtr.Zero) { PyObject tb_module = PythonEngine.ImportModule("traceback"); - Runtime.Incref(_pyTB); + Runtime.XIncref(_pyTB); using (PyObject pyTB = new PyObject(_pyTB)) { _tb = tb_module.InvokeMethod("format_tb", pyTB).ToString(); @@ -149,12 +149,12 @@ public void Dispose() if (Runtime.Py_IsInitialized() > 0) { IntPtr gs = PythonEngine.AcquireLock(); - Runtime.Decref(_pyType); - Runtime.Decref(_pyValue); + Runtime.XDecref(_pyType); + Runtime.XDecref(_pyValue); // XXX Do we ever get TraceBack? // if (_pyTB != IntPtr.Zero) { - Runtime.Decref(_pyTB); + Runtime.XDecref(_pyTB); } PythonEngine.ReleaseLock(gs); } diff --git a/src/runtime/pytuple.cs b/src/runtime/pytuple.cs index 3ab8a7e34..123ad4359 100644 --- a/src/runtime/pytuple.cs +++ b/src/runtime/pytuple.cs @@ -37,7 +37,7 @@ public PyTuple(PyObject o) : base() { throw new ArgumentException("object is not a tuple"); } - Runtime.Incref(o.obj); + Runtime.XIncref(o.obj); obj = o.obj; } @@ -73,7 +73,7 @@ public PyTuple(PyObject[] items) : base() for (int i = 0; i < count; i++) { IntPtr ptr = items[i].obj; - Runtime.Incref(ptr); + Runtime.XIncref(ptr); int r = Runtime.PyTuple_SetItem(obj, i, ptr); if (r < 0) { diff --git a/src/runtime/resources/clr.py b/src/runtime/resources/clr.py index 61d6e76f1..805b0e23b 100644 --- a/src/runtime/resources/clr.py +++ b/src/runtime/resources/clr.py @@ -1,7 +1,9 @@ -""" +""" Code in this module gets loaded into the main clr module. """ +__version__ = "2.2.1" + class clrproperty(object): """ diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index d89994df5..80f62df49 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -7,7 +7,7 @@ #endif -#if (UCS2 && (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35)) +#if (UCS2 && PYTHON3) using System.Text; #endif @@ -139,8 +139,12 @@ public class Runtime public const string pyversion = "3.5"; public const int pyversionnumber = 35; #endif -#if ! (PYTHON23 || PYTHON24 || PYTHON25 || PYTHON26 || PYTHON27 || PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) -#error You must define one of PYTHON23 to PYTHON35 +#if (PYTHON36) + public const string pyversion = "3.6"; + public const int pyversionnumber = 36; +#endif +#if ! (PYTHON23 || PYTHON24 || PYTHON25 || PYTHON26 || PYTHON27 || PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35 || PYTHON36) +#error You must define one of PYTHON23 to PYTHON36 #endif #if (PYTHON23) @@ -171,6 +175,9 @@ public class Runtime #if (PYTHON35) internal const string dllBase = "python3.5"; #endif +#if (PYTHON36) + internal const string dllBase = "python3.6"; +#endif #else #if (PYTHON32) internal const string dllBase = "python32"; @@ -184,6 +191,9 @@ public class Runtime #if (PYTHON35) internal const string dllBase = "python35"; #endif +#if (PYTHON36) + internal const string dllBase = "python36"; +#endif #endif #if (PYTHON_WITH_PYDEBUG) @@ -212,7 +222,6 @@ public class Runtime internal static Object IsFinalizingLock = new Object(); internal static bool IsFinalizing = false; - internal static bool wrap_exceptions; internal static bool is32bit; /// @@ -232,14 +241,14 @@ internal static void Initialize() Runtime.PyEval_InitThreads(); } -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) - IntPtr op = Runtime.PyImport_ImportModule("builtins"); - IntPtr dict = Runtime.PyObject_GetAttrString(op, "__dict__"); - PyNotImplemented = Runtime.PyObject_GetAttrString(op, "NotImplemented"); -#else +#if PYTHON3 + IntPtr op = Runtime.PyImport_ImportModule("builtins"); + IntPtr dict = Runtime.PyObject_GetAttrString(op, "__dict__"); +#elif PYTHON2 IntPtr dict = Runtime.PyImport_GetModuleDict(); IntPtr op = Runtime.PyDict_GetItemString(dict, "__builtin__"); #endif + PyNotImplemented = Runtime.PyObject_GetAttrString(op, "NotImplemented"); PyBaseObjectType = Runtime.PyObject_GetAttrString(op, "object"); PyModuleType = Runtime.PyObject_Type(op); @@ -253,55 +262,62 @@ internal static void Initialize() op = Runtime.PyObject_GetAttrString(dict, "keys"); PyMethodType = Runtime.PyObject_Type(op); - Runtime.Decref(op); - -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) - Runtime.Decref(dict); - Runtime.Decref(op); + Runtime.XDecref(op); + + // For some arcane reason, builtins.__dict__.__setitem__ is *not* + // a wrapper_descriptor, even though dict.__setitem__ is. + // + // object.__init__ seems safe, though. + op = Runtime.PyObject_GetAttrString(PyBaseObjectType, "__init__"); + PyWrapperDescriptorType = Runtime.PyObject_Type(op); + Runtime.XDecref(op); + +#if PYTHON3 + Runtime.XDecref(dict); #endif op = Runtime.PyString_FromString("string"); PyStringType = Runtime.PyObject_Type(op); - Runtime.Decref(op); + Runtime.XDecref(op); op = Runtime.PyUnicode_FromString("unicode"); PyUnicodeType = Runtime.PyObject_Type(op); - Runtime.Decref(op); + Runtime.XDecref(op); -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) - op = Runtime.PyBytes_FromString("bytes"); - PyBytesType = Runtime.PyObject_Type(op); - Runtime.Decref(op); +#if PYTHON3 + op = Runtime.PyBytes_FromString("bytes"); + PyBytesType = Runtime.PyObject_Type(op); + Runtime.XDecref(op); #endif op = Runtime.PyTuple_New(0); PyTupleType = Runtime.PyObject_Type(op); - Runtime.Decref(op); + Runtime.XDecref(op); op = Runtime.PyList_New(0); PyListType = Runtime.PyObject_Type(op); - Runtime.Decref(op); + Runtime.XDecref(op); op = Runtime.PyDict_New(); PyDictType = Runtime.PyObject_Type(op); - Runtime.Decref(op); + Runtime.XDecref(op); op = Runtime.PyInt_FromInt32(0); PyIntType = Runtime.PyObject_Type(op); - Runtime.Decref(op); + Runtime.XDecref(op); op = Runtime.PyLong_FromLong(0); PyLongType = Runtime.PyObject_Type(op); - Runtime.Decref(op); + Runtime.XDecref(op); op = Runtime.PyFloat_FromDouble(0); PyFloatType = Runtime.PyObject_Type(op); - Runtime.Decref(op); + Runtime.XDecref(op); -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON3 PyClassType = IntPtr.Zero; PyInstanceType = IntPtr.Zero; -#else +#elif PYTHON2 IntPtr s = Runtime.PyString_FromString("_temp"); IntPtr d = Runtime.PyDict_New(); @@ -311,15 +327,15 @@ internal static void Initialize() IntPtr i = Runtime.PyInstance_New(c, IntPtr.Zero, IntPtr.Zero); PyInstanceType = Runtime.PyObject_Type(i); - Runtime.Decref(s); - Runtime.Decref(i); - Runtime.Decref(c); - Runtime.Decref(d); + Runtime.XDecref(s); + Runtime.XDecref(i); + Runtime.XDecref(c); + Runtime.XDecref(d); #endif Error = new IntPtr(-1); -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON3 IntPtr dll = IntPtr.Zero; if ("__Internal" != Runtime.dll) { NativeMethods.LoadLibrary(Runtime.dll); @@ -332,25 +348,6 @@ internal static void Initialize() #endif #endif - - // Determine whether we need to wrap exceptions for versions of - // of the Python runtime that do not allow new-style classes to - // be used as exceptions (Python versions 2.4 and lower). - -#if (PYTHON25 || PYTHON26 || PYTHON27 || PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) - wrap_exceptions = false; -#else - IntPtr m = PyImport_ImportModule("exceptions"); - Exceptions.ErrorCheck(m); - op = Runtime.PyObject_GetAttrString(m, "Exception"); - Exceptions.ErrorCheck(op); - if (Runtime.PyObject_TYPE(op) == PyClassType) { - wrap_exceptions = true; - } - Runtime.Decref(op); - Runtime.Decref(m); -#endif - // Initialize modules that depend on the runtime class. AssemblyManager.Initialize(); PyCLRMetaType = MetaType.Initialize(); @@ -363,7 +360,7 @@ internal static void Initialize() IntPtr path = Runtime.PySys_GetObject("path"); IntPtr item = Runtime.PyString_FromString(rtdir); Runtime.PyList_Append(path, item); - Runtime.Decref(item); + Runtime.XDecref(item); AssemblyManager.UpdatePath(); } @@ -395,6 +392,7 @@ internal static int AtExit() internal static IntPtr PyInstanceType; internal static IntPtr PyCLRMetaType; internal static IntPtr PyMethodType; + internal static IntPtr PyWrapperDescriptorType; internal static IntPtr PyUnicodeType; internal static IntPtr PyStringType; @@ -408,23 +406,24 @@ internal static int AtExit() internal static IntPtr PyNoneType; internal static IntPtr PyTypeType; -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) - internal static IntPtr PyBytesType; - internal static IntPtr PyNotImplemented; - internal const int Py_LT = 0; - internal const int Py_LE = 1; - internal const int Py_EQ = 2; - internal const int Py_NE = 3; - internal const int Py_GT = 4; - internal static IntPtr _PyObject_NextNotImplemented; +#if PYTHON3 + internal static IntPtr PyBytesType; + internal static IntPtr _PyObject_NextNotImplemented; #endif + internal static IntPtr PyNotImplemented; + internal const int Py_LT = 0; + internal const int Py_LE = 1; + internal const int Py_EQ = 2; + internal const int Py_NE = 3; + internal const int Py_GT = 4; + internal const int Py_GE = 5; + internal static IntPtr PyTrue; internal static IntPtr PyFalse; internal static IntPtr PyNone; internal static IntPtr Error; - internal static IntPtr GetBoundArgTuple(IntPtr obj, IntPtr args) { if (Runtime.PyObject_TYPE(args) != Runtime.PyTupleType) @@ -435,12 +434,12 @@ internal static IntPtr GetBoundArgTuple(IntPtr obj, IntPtr args) int size = Runtime.PyTuple_Size(args); IntPtr items = Runtime.PyTuple_New(size + 1); Runtime.PyTuple_SetItem(items, 0, obj); - Runtime.Incref(obj); + Runtime.XIncref(obj); for (int i = 0; i < size; i++) { IntPtr item = Runtime.PyTuple_GetItem(args, i); - Runtime.Incref(item); + Runtime.XIncref(item); Runtime.PyTuple_SetItem(items, i + 1, item); } @@ -458,14 +457,14 @@ internal static IntPtr ExtendTuple(IntPtr t, params IntPtr[] args) for (int i = 0; i < size; i++) { item = Runtime.PyTuple_GetItem(t, i); - Runtime.Incref(item); + Runtime.XIncref(item); Runtime.PyTuple_SetItem(items, i, item); } for (int n = 0; n < add; n++) { item = args[n]; - Runtime.Incref(item); + Runtime.XIncref(item); Runtime.PyTuple_SetItem(items, size + n, item); } @@ -488,7 +487,7 @@ internal static Type[] PythonArgsToTypeArray(IntPtr arg, bool mangleObjects) if (!Runtime.PyTuple_Check(arg)) { args = Runtime.PyTuple_New(1); - Runtime.Incref(arg); + Runtime.XIncref(arg); Runtime.PyTuple_SetItem(args, 0, arg); free = true; } @@ -532,7 +531,7 @@ internal static Type[] PythonArgsToTypeArray(IntPtr arg, bool mangleObjects) } if (free) { - Runtime.Decref(args); + Runtime.XDecref(args); } return types; } @@ -543,9 +542,10 @@ internal static Type[] PythonArgsToTypeArray(IntPtr arg, bool mangleObjects) // (mostly for heavily used methods). //=================================================================== - internal unsafe static void Incref(IntPtr op) + internal unsafe static void XIncref(IntPtr op) { #if (Py_DEBUG) + // according to Python doc, Py_IncRef() is Py_XINCREF() Py_IncRef(op); return; #else @@ -564,14 +564,11 @@ internal unsafe static void Incref(IntPtr op) #endif } - internal unsafe static void Decref(IntPtr op) + internal static unsafe void XDecref(IntPtr op) { - if (op == IntPtr.Zero) - { - DebugUtil.Print("Decref(NULL)"); - } #if (Py_DEBUG) - // Py_DecRef calls Python's Py_DECREF + // Py_DecRef calls Python's Py_DECREF + // according to Python doc, Py_DecRef() is Py_XDECREF() Py_DecRef(op); return; #else @@ -710,12 +707,12 @@ internal unsafe static extern void internal unsafe static extern IntPtr PyGILState_GetThisThreadState(); -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON3 [DllImport(Runtime.dll, CallingConvention=CallingConvention.Cdecl, ExactSpelling=true, CharSet=CharSet.Ansi)] public unsafe static extern int Py_Main(int argc, [MarshalAsAttribute(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPWStr)] string[] argv); -#else +#elif PYTHON2 [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, CharSet = CharSet.Ansi)] public unsafe static extern int @@ -778,7 +775,7 @@ internal unsafe static extern IntPtr PyEval_GetLocals(); -#if PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35 +#if PYTHON3 [DllImport(Runtime.dll, CallingConvention=CallingConvention.Cdecl, ExactSpelling=true, CharSet=CharSet.Ansi)] [return: MarshalAs(UnmanagedType.LPWStr)] @@ -811,7 +808,7 @@ internal unsafe static extern string ExactSpelling=true, CharSet=CharSet.Ansi)] internal unsafe static extern void Py_SetPath([MarshalAsAttribute(UnmanagedType.LPWStr)]string home); -#else +#elif PYTHON2 [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, CharSet = CharSet.Ansi)] internal unsafe static extern string @@ -958,7 +955,7 @@ internal unsafe static IntPtr PyObject_Type(IntPtr op) { IntPtr tp = PyObject_TYPE(op); - Runtime.Incref(tp); + Runtime.XIncref(tp); return tp; } @@ -1029,7 +1026,7 @@ internal unsafe static extern IntPtr internal unsafe static extern IntPtr PyObject_CallObject(IntPtr pointer, IntPtr args); -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON3 [DllImport(Runtime.dll, CallingConvention=CallingConvention.Cdecl, ExactSpelling=true, CharSet=CharSet.Ansi)] internal unsafe static extern int @@ -1058,7 +1055,7 @@ internal static int PyObject_Compare(IntPtr value1, IntPtr value2) { Exceptions.SetError(Exceptions.SystemError, "Error comparing objects"); return -1; } -#else +#elif PYTHON2 [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, CharSet = CharSet.Ansi)] internal unsafe static extern int @@ -1111,13 +1108,13 @@ internal unsafe static extern IntPtr internal unsafe static extern IntPtr PyObject_Str(IntPtr pointer); -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON3 [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, EntryPoint="PyObject_Str", ExactSpelling = true, CharSet = CharSet.Ansi)] internal unsafe static extern IntPtr PyObject_Unicode(IntPtr pointer); -#else +#elif PYTHON2 [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, CharSet = CharSet.Ansi)] internal unsafe static extern IntPtr @@ -1134,13 +1131,13 @@ internal unsafe static extern IntPtr // Python number API //==================================================================== -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON3 [DllImport(Runtime.dll, CallingConvention=CallingConvention.Cdecl, EntryPoint = "PyNumber_Long", ExactSpelling=true, CharSet=CharSet.Ansi)] internal unsafe static extern IntPtr PyNumber_Int(IntPtr ob); -#else // Python 2 +#elif PYTHON2 [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, CharSet = CharSet.Ansi)] @@ -1187,7 +1184,7 @@ internal static IntPtr PyInt_FromInt64(long value) return PyInt_FromLong(v); } -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON3 [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, EntryPoint = "PyLong_FromLong", ExactSpelling = true, CharSet = CharSet.Ansi)] @@ -1211,7 +1208,7 @@ internal unsafe static extern IntPtr ExactSpelling=true, CharSet=CharSet.Ansi)] internal unsafe static extern int PyInt_GetMax(); -#else // Python 2 +#elif PYTHON2 [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, CharSet = CharSet.Ansi)] @@ -1535,7 +1532,7 @@ internal static IntPtr PyString_FromString(string value) return PyString_FromStringAndSize(value, value.Length); } -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON3 [DllImport(Runtime.dll, CallingConvention=CallingConvention.Cdecl, ExactSpelling=true, CharSet=CharSet.Ansi)] internal unsafe static extern IntPtr @@ -1566,7 +1563,7 @@ internal static IntPtr PyString_FromStringAndSize(string value, int length) } } -#if (PYTHON33 || PYTHON34 || PYTHON35) +#if (PYTHON33 || PYTHON34 || PYTHON35 || PYTHON36) [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, CharSet = CharSet.Unicode)] internal unsafe static extern IntPtr @@ -1610,7 +1607,7 @@ internal static bool PyUnicode_Check(IntPtr ob) } #if (UCS2) -#if (PYTHON33 || PYTHON34 || PYTHON35) +#if (PYTHON33 || PYTHON34 || PYTHON35 || PYTHON36) [DllImport(Runtime.dll, CallingConvention=CallingConvention.Cdecl, ExactSpelling=true, CharSet=CharSet.Unicode)] internal unsafe static extern IntPtr @@ -1707,7 +1704,7 @@ internal unsafe static string GetManagedString(IntPtr op) IntPtr type = PyObject_TYPE(op); // Python 3 strings are all unicode -#if !(PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON2 if (type == Runtime.PyStringType) { return Marshal.PtrToStringAnsi( @@ -1729,7 +1726,7 @@ internal unsafe static string GetManagedString(IntPtr op) #endif #if (UCS4) -#if (PYTHON33 || PYTHON34 || PYTHON35) +#if (PYTHON33 || PYTHON34 || PYTHON35 || PYTHON36) [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, ExactSpelling=true, CharSet=CharSet.Unicode)] internal unsafe static extern IntPtr @@ -1831,7 +1828,7 @@ internal unsafe static string GetManagedString(IntPtr op) IntPtr type = PyObject_TYPE(op); // Python 3 strings are all unicode -#if !(PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON2 if (type == Runtime.PyStringType) { return Marshal.PtrToStringAnsi( @@ -2049,12 +2046,12 @@ internal unsafe static extern int // Python iterator API //==================================================================== -#if !(PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON2 [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, CharSet = CharSet.Ansi)] internal unsafe static extern bool PyIter_Check(IntPtr pointer); -#else +#elif PYTHON3 internal static bool PyIter_Check(IntPtr pointer) { @@ -2093,7 +2090,7 @@ internal unsafe static extern IntPtr internal unsafe static extern string PyModule_GetFilename(IntPtr module); -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON3 [DllImport(Runtime.dll, CallingConvention=CallingConvention.Cdecl, ExactSpelling=true, CharSet=CharSet.Ansi)] internal unsafe static extern IntPtr @@ -2151,6 +2148,11 @@ internal static bool PyType_Check(IntPtr ob) return PyObject_TypeCheck(ob, Runtime.PyTypeType); } + [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, + ExactSpelling = true, CharSet = CharSet.Ansi)] + internal unsafe static extern void + PyType_Modified(IntPtr type); + [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, ExactSpelling = true, CharSet = CharSet.Ansi)] internal unsafe static extern bool @@ -2317,4 +2319,4 @@ internal unsafe static extern IntPtr internal unsafe static extern IntPtr PyMethod_Function(IntPtr ob); } -} \ No newline at end of file +} diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index 9a76bff2d..40e60336d 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -128,30 +128,26 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) // XXX Hack, use a different base class for System.Exception // Python 2.5+ allows new style class exceptions but they *must* // subclass BaseException (or better Exception). -#if (PYTHON25 || PYTHON26 || PYTHON27 || PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) if (typeof(System.Exception).IsAssignableFrom(clrType)) { - ob_size = ObjectOffset.Size(Exceptions.BaseException); - tp_dictoffset = ObjectOffset.DictOffset(Exceptions.BaseException); + ob_size = ObjectOffset.Size(Exceptions.Exception); + tp_dictoffset = ObjectOffset.DictOffset(Exceptions.Exception); } if (clrType == typeof(System.Exception)) { base_ = Exceptions.Exception; - Runtime.Incref(base_); } - else -#endif - if (clrType.BaseType != null) - { - ClassBase bc = ClassManager.GetClass(clrType.BaseType); - base_ = bc.pyHandle; - } + else 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); + Runtime.XIncref(Runtime.PyCLRMetaType); Marshal.WriteIntPtr(type, TypeOffset.tp_basicsize, (IntPtr)ob_size); Marshal.WriteIntPtr(type, TypeOffset.tp_itemsize, IntPtr.Zero); @@ -162,7 +158,7 @@ internal static IntPtr CreateType(ManagedType impl, Type clrType) if (base_ != IntPtr.Zero) { Marshal.WriteIntPtr(type, TypeOffset.tp_base, base_); - Runtime.Incref(base_); + Runtime.XIncref(base_); } int flags = TypeFlags.Default; @@ -303,7 +299,7 @@ internal static IntPtr CreateMetaType(Type impl) IntPtr py_type = Runtime.PyTypeType; Marshal.WriteIntPtr(type, TypeOffset.tp_base, py_type); - Runtime.Incref(py_type); + Runtime.XIncref(py_type); // Copy gc and other type slots from the base Python metatype. @@ -376,7 +372,7 @@ internal static IntPtr BasicSubType(string name, IntPtr base_, //Marshal.WriteIntPtr(type, TypeOffset.tp_dict, dc); Marshal.WriteIntPtr(type, TypeOffset.tp_base, base_); - Runtime.Incref(base_); + Runtime.XIncref(base_); int flags = TypeFlags.Default; flags |= TypeFlags.Managed; @@ -411,21 +407,21 @@ internal static IntPtr AllocateTypeObject(string name) // 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. -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON3 // For python3 we leak two objects. One for the ascii representation // required for tp_name, and another for the unicode representation // for ht_name. IntPtr temp = Runtime.PyBytes_FromString(name); IntPtr raw = Runtime.PyBytes_AS_STRING(temp); temp = Runtime.PyUnicode_FromString(name); -#else +#elif PYTHON2 IntPtr temp = Runtime.PyString_FromString(name); IntPtr raw = Runtime.PyString_AS_STRING(temp); #endif Marshal.WriteIntPtr(type, TypeOffset.tp_name, raw); Marshal.WriteIntPtr(type, TypeOffset.name, temp); -#if (PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON3 Marshal.WriteIntPtr(type, TypeOffset.qualname, temp); #endif @@ -440,10 +436,10 @@ internal static IntPtr AllocateTypeObject(string name) temp = new IntPtr(ptr + TypeOffset.mp_length); Marshal.WriteIntPtr(type, TypeOffset.tp_as_mapping, temp); -#if (PYTHON32 || PYTHON33 || PYTHON34 || PYTHON35) +#if PYTHON3 temp = new IntPtr(ptr + TypeOffset.bf_getbuffer); Marshal.WriteIntPtr(type, TypeOffset.tp_as_buffer, temp); -#else +#elif PYTHON2 temp = new IntPtr(ptr + TypeOffset.bf_getreadbuffer); Marshal.WriteIntPtr(type, TypeOffset.tp_as_buffer, temp); #endif @@ -548,4 +544,4 @@ internal static void CopySlot(IntPtr from, IntPtr to, int offset) Marshal.WriteIntPtr(to, offset, fp); } } -} \ No newline at end of file +} diff --git a/src/testing/Python.Test.csproj b/src/testing/Python.Test.csproj index 56efda8e3..4566aeccf 100644 --- a/src/testing/Python.Test.csproj +++ b/src/testing/Python.Test.csproj @@ -1,4 +1,4 @@ - + Debug @@ -122,6 +122,7 @@ + @@ -153,4 +154,4 @@ - \ No newline at end of file + diff --git a/src/testing/Python.Test.mdp b/src/testing/Python.Test.mdp deleted file mode 100644 index e8ab5d5cf..000000000 --- a/src/testing/Python.Test.mdp +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/testing/callbacktest.cs b/src/testing/callbacktest.cs index 81389289d..f95cbc602 100644 --- a/src/testing/callbacktest.cs +++ b/src/testing/callbacktest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -28,4 +28,18 @@ public string Call_simpleDefaultArg_WithEmptyArgs(string moduleName) } } } + + //========================================================================== + // Tests calling from Python into C# and back into Python using a PyObject. + // SelfCallbackTest should be inherited by a Python class. + // Used in test_class.py / testCallback + //========================================================================== + public class SelfCallbackTest + { + public void Callback(Runtime.PyObject self) + { + using (Runtime.Py.GIL()) + ((dynamic)self).PyCallback(self); + } + } } diff --git a/src/testing/exceptiontest.cs b/src/testing/exceptiontest.cs index b38182857..414c25d82 100644 --- a/src/testing/exceptiontest.cs +++ b/src/testing/exceptiontest.cs @@ -1,6 +1,5 @@ using System; - namespace Python.Test { //======================================================================== @@ -55,6 +54,25 @@ public static bool ThrowException() { throw new OverflowException("error"); } + + public static void ThrowChainedExceptions() + { + try + { + try + { + throw new Exception("Innermost exception"); + } + catch (Exception exc) + { + throw new Exception("Inner exception", exc); + } + } + catch (Exception exc2) + { + throw new Exception("Outer exception", exc2); + } + } } diff --git a/src/testing/moduletest.cs b/src/testing/moduletest.cs new file mode 100644 index 000000000..ca75a1313 --- /dev/null +++ b/src/testing/moduletest.cs @@ -0,0 +1,25 @@ +using System; +using System.Threading; + +namespace Python.Test { + public class ModuleTest { + private static Thread _thread; + + public static void RunThreads() + { + _thread = new Thread(() => { + var appdomain = AppDomain.CurrentDomain; + var assemblies = appdomain.GetAssemblies(); + foreach (var assembly in assemblies) { + assembly.GetTypes(); + } + }); + _thread.Start(); + } + + public static void JoinThreads() + { + _thread.Join(); + } + } +} diff --git a/src/testing/subclasstest.cs b/src/testing/subclasstest.cs index 4fd271fa7..2b61be254 100644 --- a/src/testing/subclasstest.cs +++ b/src/testing/subclasstest.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -114,4 +114,4 @@ public static int test_event(IInterfaceTest x, int value) return et.value; } } -} \ No newline at end of file +} diff --git a/src/tests/test_class.py b/src/tests/test_class.py index fe8fc982b..9e2af14da 100644 --- a/src/tests/test_class.py +++ b/src/tests/test_class.py @@ -1,9 +1,12 @@ -from System.Collections import Hashtable -from Python.Test import ClassTest -import sys, os, string, unittest, types +import clr +import types +import unittest + import Python.Test as Test import System import six +from Python.Test import ClassTest +from System.Collections import Hashtable if six.PY3: DictProxyType = type(object.__dict__) @@ -198,6 +201,70 @@ def __setitem__(self, key, value): self.assertTrue(table.Count == 3) + def testAddAndRemoveClassAttribute(self): + + from System import TimeSpan + + for i in range(100): + TimeSpan.new_method = lambda self: self.TotalMinutes + ts = TimeSpan.FromHours(1) + self.assertTrue(ts.new_method() == 60) + del TimeSpan.new_method + self.assertFalse(hasattr(ts, "new_method")) + + def testComparisons(self): + from System import DateTimeOffset + + d1 = DateTimeOffset.Parse("2016-11-14") + d2 = DateTimeOffset.Parse("2016-11-15") + + self.assertEqual(d1 == d2, False) + self.assertEqual(d1 != d2, True) + + self.assertEqual(d1 < d2, True) + self.assertEqual(d1 <= d2, True) + self.assertEqual(d1 >= d2, False) + self.assertEqual(d1 > d2, False) + + self.assertEqual(d1 == d1, True) + self.assertEqual(d1 != d1, False) + + self.assertEqual(d1 < d1, False) + self.assertEqual(d1 <= d1, True) + self.assertEqual(d1 >= d1, True) + self.assertEqual(d1 > d1, False) + + self.assertEqual(d2 == d1, False) + self.assertEqual(d2 != d1, True) + + self.assertEqual(d2 < d1, False) + self.assertEqual(d2 <= d1, False) + self.assertEqual(d2 >= d1, True) + self.assertEqual(d2 > d1, True) + + self.assertRaises(TypeError, lambda: d1 < None) + self.assertRaises(TypeError, lambda: d1 < System.Guid()) + + # ClassTest does not implement IComparable + c1 = ClassTest() + c2 = ClassTest() + self.assertRaises(TypeError, lambda: c1 < c2) + + def testSelfCallback(self): + """ Test calling back and forth between this and a c# baseclass.""" + class CallbackUser(Test.SelfCallbackTest): + def DoCallback(self): + self.PyCallbackWasCalled = False + self.SameReference = False + return self.Callback(self) + def PyCallback(self, self2): + self.PyCallbackWasCalled = True + self.SameReference = self == self2 + + testobj = CallbackUser() + testobj.DoCallback() + self.assertTrue(testobj.PyCallbackWasCalled) + self.assertTrue(testobj.SameReference) class ClassicClass: def kind(self): diff --git a/src/tests/test_constructors.py b/src/tests/test_constructors.py index fdc1ef060..6e02528bb 100644 --- a/src/tests/test_constructors.py +++ b/src/tests/test_constructors.py @@ -44,7 +44,6 @@ class sub(System.Exception): instance = sub() ob = SubclassConstructorTest(instance) - print(ob) self.assertTrue(isinstance(ob.value, System.Exception)) diff --git a/src/tests/test_exceptions.py b/src/tests/test_exceptions.py index 4b6386447..eedf2aa61 100644 --- a/src/tests/test_exceptions.py +++ b/src/tests/test_exceptions.py @@ -6,11 +6,6 @@ unicode = str -# 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.""" @@ -300,14 +295,15 @@ def testPythonCompatOfManagedExceptions(self): msg = "A simple message" e = OverflowException(msg) - self.assertEqual(e.message, msg) - self.assertTrue(isinstance(e.message, unicode)) # ??? self.assertEqual(str(e), msg) self.assertEqual(unicode(e), msg) self.assertEqual(e.args, (msg,)) self.assertTrue(isinstance(e.args, tuple)) - self.assertEqual(repr(e), "OverflowException('A simple message',)") + if six.PY2: + self.assertEqual(repr(e), "OverflowException(u'A simple message',)") + else: + self.assertEqual(repr(e), "OverflowException('A simple message',)") def testExceptionIsInstanceOfSystemObject(self): """Test behavior of isinstance(, System.Object).""" @@ -336,6 +332,40 @@ def testExceptionIsInstanceOfSystemObject(self): else: self.assertFalse(isinstance(o, Object)) + def testPicklingExceptions(self): + from System import Exception + try: + import cPickle as pickle + except ImportError: + import pickle + + exc = Exception("test") + dumped = pickle.dumps(exc) + loaded = pickle.loads(dumped) + + self.assertEqual(exc.args, loaded.args) + + def testChainedExceptions(self): + if six.PY3: + from Python.Test import ExceptionTest + + try: + ExceptionTest.ThrowChainedExceptions() + except Exception as exc: + msgs = [ + "Outer exception", + "Inner exception", + "Innermost exception" + ] + + for msg in msgs: + self.assertEqual(exc.Message, msg) + self.assertEqual(exc.__cause__, exc.InnerException) + exc = exc.__cause__ + + else: + self.fail("Test should raise an exception") + def test_suite(): return unittest.makeSuite(ExceptionTests) diff --git a/src/tests/test_module.py b/src/tests/test_module.py index f03954d28..fff044f0c 100644 --- a/src/tests/test_module.py +++ b/src/tests/test_module.py @@ -41,6 +41,10 @@ def test000importClr(self): import clr self.assertTrue(self.isCLRRootModule(clr)) + def testVersionClr(self): + import clr + self.assertTrue(clr.__version__ >= "2.2.0") + def testPreloadVar(self): import clr self.assertTrue(clr.getPreload() is False, clr.getPreload()) @@ -65,8 +69,11 @@ def testModuleInterface(self): import System self.assertEquals(type(System.__dict__), type({})) self.assertEquals(System.__name__, 'System') - # the filename can be any module from the System namespace (eg System.Data.dll or System.dll) - self.assertTrue(fnmatch(System.__file__, "*System*.dll")) + # the filename can be any module from the System namespace + # (eg System.Data.dll or System.dll, but also mscorlib.dll) + system_file = System.__file__ + self.assertTrue(fnmatch(system_file, "*System*.dll") or fnmatch(system_file, "*mscorlib.dll"), + "unexpected System.__file__: " + system_file) self.assertTrue(System.__doc__.startswith("Namespace containing types from the following assemblies:")) self.assertTrue(self.isCLRClass(System.String)) self.assertTrue(self.isCLRClass(System.Int32)) @@ -353,6 +360,22 @@ def test_ClrAddReference(self): self.assertRaises(FileNotFoundException, AddReference, "somethingtotallysilly") + def test_AssemblyLoadThreadSafety(self): + import time + from Python.Test import ModuleTest + # spin up .NET thread which loads assemblies and triggers AppDomain.AssemblyLoad event + ModuleTest.RunThreads() + time.sleep(1e-5) + for i in range(1, 100): + # call import clr, which in AssemblyManager.GetNames iterates through the loaded types + import clr + # import some .NET types + from System import DateTime + from System import Guid + from System.Collections.Generic import Dictionary + dict = Dictionary[Guid,DateTime]() + ModuleTest.JoinThreads() + def test_suite(): return unittest.makeSuite(ModuleTests) diff --git a/src/tests/test_subclass.py b/src/tests/test_subclass.py index 43e8fb7aa..c486a0fc3 100644 --- a/src/tests/test_subclass.py +++ b/src/tests/test_subclass.py @@ -147,6 +147,21 @@ def handler(self, x, args): self.assertEqual(event_handler.value, 3) self.assertEqual(len(d.event_handlers), 1) + def test_isinstance(self): + from System import Object + from System import String + + a = [str(x) for x in range(0, 1000)] + b = [String(x) for x in a] + + for x in a: + self.assertFalse(isinstance(x, Object)) + self.assertFalse(isinstance(x, String)) + + for x in b: + self.assertTrue(isinstance(x, Object)) + self.assertTrue(isinstance(x, String)) + def test_suite(): return unittest.makeSuite(SubClassTests) diff --git a/tools/geninterop/geninterop.py b/tools/geninterop/geninterop.py index c74bc85e9..946e30217 100644 --- a/tools/geninterop/geninterop.py +++ b/tools/geninterop/geninterop.py @@ -1,3 +1,6 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + """ TypeOffset is a C# class that mirrors the in-memory layout of heap allocated Python objects. @@ -9,6 +12,9 @@ - pycparser - clang """ + +from __future__ import print_function + from distutils.sysconfig import get_config_var from subprocess import Popen, CalledProcessError, PIPE from pycparser import c_parser, c_ast @@ -86,8 +92,8 @@ def visit_struct(self, struct): self.__struct_members_stack.pop(0) self.__struct_stack.pop(0) elif self.__ptr_decl_depth: - # the struct is empty, but add it as a member to the current struct - # as the current member maybe a pointer to it. + # the struct is empty, but add it as a member to the current + # struct as the current member maybe a pointer to it. self.__add_struct_member(struct.name) def visit_decl(self, decl): @@ -109,7 +115,8 @@ def __add_struct_member(self, type_name): # add member to current struct current_struct = self.__struct_stack[0] member_name = self.__struct_members_stack[0] - struct_members = self.__struct_members.setdefault(self.__get_struct_name(current_struct), []) + struct_members = self.__struct_members.setdefault( + self.__get_struct_name(current_struct), []) # get the node associated with this type node = None @@ -118,7 +125,8 @@ def __add_struct_member(self, type_name): elif type_name in self.__structs: node = self.__structs[type_name] - # If it's a struct (and not a pointer to a struct) expand it into the current struct definition + # If it's a struct (and not a pointer to a struct) expand + # it into the current struct definition if not self.__ptr_decl_depth and isinstance(node, c_ast.Struct): for decl in node.decls or []: self.__struct_members_stack.insert(0, decl.name) @@ -141,8 +149,7 @@ def __get_struct_name(self, node): def check_output(*popenargs, **kwargs): """subprocess.check_output from python 2.7. - Added here to support building for earlier versions - of Python. + Added here to support building for earlier versions of Python. """ process = Popen(stdout=PIPE, *popenargs, **kwargs) output, unused_err = process.communicate() @@ -161,7 +168,8 @@ def preprocess_python_headers(): """Return Python.h pre-processed, ready for parsing. Requires clang. """ - fake_libc_include = os.path.join(os.path.dirname(__file__), "fake_libc_include") + fake_libc_include = os.path.join(os.path.dirname(__file__), + "fake_libc_include") include_dirs = [fake_libc_include] include_py = get_config_var("INCLUDEPY") @@ -198,7 +206,7 @@ def gen_interop_code(members): """Generate the TypeOffset C# class""" defines = [ - "PYTHON%d%s" % (sys.version_info[:2]) + "PYTHON%d%d" % (sys.version_info[:2]) ] if hasattr(sys, "abiflags"): @@ -212,7 +220,9 @@ def gen_interop_code(members): class_definition = """ // Auto-generated by %s. // DO NOT MODIFIY BY HAND. -#if (%s) + + +#if %s using System; using System.Collections; using System.Collections.Specialized; @@ -220,21 +230,24 @@ def gen_interop_code(members): using System.Reflection; using System.Text; -namespace Python.Runtime { - - [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)] - internal class TypeOffset { - - static TypeOffset() { +namespace Python.Runtime +{ + [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++) { + for (int i = 0; i < fi.Length; i++) + { fi[i].SetValue(null, i * size); } } - public static int magic() { + public static int magic() + { return ob_size; } @@ -252,6 +265,7 @@ def gen_interop_code(members): public static int members = 0; } } + #endif """ return class_definition @@ -272,7 +286,7 @@ def main(): interop_cs = gen_interop_code(members) if len(sys.argv) > 1: - with open(sys.argv[1], "wt") as fh: + with open(sys.argv[1], "w") as fh: fh.write(interop_cs) else: print(interop_cs) diff --git a/tools/nuget/nuget.exe b/tools/nuget/nuget.exe index 9cba6edbf..e42e6d827 100644 Binary files a/tools/nuget/nuget.exe and b/tools/nuget/nuget.exe differ