diff --git a/.bumpversion.cfg b/.bumpversion.cfg new file mode 100644 index 000000000..ac1d31324 --- /dev/null +++ b/.bumpversion.cfg @@ -0,0 +1,29 @@ +[bumpversion] +current_version = 2.4.0.dev0 +parse = (?P\d+)\.(?P\d+)\.(?P\d+)(\.(?P[a-z]+)(?P\d+))? +serialize = + {major}.{minor}.{patch}.{release}{dev} + {major}.{minor}.{patch} + +[bumpversion:part:release] +optional_value = dummy +values = + dev + dummy + +[bumpversion:part:dev] + +[bumpversion:file:setup.py] + +[bumpversion:file:conda.recipe/meta.yaml] + +[bumpversion:file:src/runtime/resources/clr.py] + +[bumpversion:file:src/SharedAssemblyInfo.cs] +serialize = + {major}.{minor}.{patch} + +[bumpversion:file:src/clrmodule/ClrModule.cs] +serialize = + {major}.{minor}.{patch} + diff --git a/.editorconfig b/.editorconfig index ff0b3c71d..2e7c58ffe 100644 --- a/.editorconfig +++ b/.editorconfig @@ -16,9 +16,14 @@ trim_trailing_whitespace = true indent_size = 2 # Xml project files -[*.{csproj,config,build,config}] +[*.{csproj,pyproj,config}] indent_size = 2 # Solution [*.sln] indent_style = tab + +# bumpversion reformats itself after every bump +[.bumpversion.cfg] +trim_trailing_whitespace = false +indent_style = tab diff --git a/.gitignore b/.gitignore index 968a5c66a..6f813dcb0 100644 --- a/.gitignore +++ b/.gitignore @@ -54,3 +54,6 @@ _UpgradeReport_Files/ Backup*/ UpgradeLog*.XML UpgradeLog*.htm + +# Coverity +cov-int/ diff --git a/.travis.yml b/.travis.yml index fcb0f265e..bf336dc9f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,6 +18,7 @@ env: - LD_PRELOAD=/lib/x86_64-linux-gnu/libSegFault.so - SEGFAULT_SIGNALS=all - PYTHONUNBUFFERED=True + - CODECOV_ENV=TRAVIS_PYTHON_VERSION addons: apt: @@ -28,21 +29,28 @@ addons: - mono-devel - ca-certificates-mono +before_install: + # Set-up dll path for embedded tests + - PY_LIBDIR=$(python -c 'import sysconfig; print(sysconfig.get_config_var("LIBDIR"))') + - export LD_LIBRARY_PATH=$PY_LIBDIR:$LD_LIBRARY_PATH + install: - - pip install pycparser coverage codecov - - coverage run setup.py build_ext --inplace + - pip install --upgrade -r requirements.txt + - coverage run setup.py install script: - - export PYTHONPATH=`pwd`:$PYTHONPATH - - python src/tests/runtests.py - # - mono ./packages/NUnit.Runners*/tools/nunit-console.exe src/embed_tests/bin/Python.EmbeddingTest.dll + - python -m pytest + - mono ./packages/NUnit.*/tools/nunit3-console.exe src/embed_tests/bin/Python.EmbeddingTest.dll -after_success: +after_script: # Uncomment if need to geninterop, ie. py37 final # - python tools/geninterop/geninterop.py - # Waiting on mono-cov support or SharpCover - - codecov + # Waiting on mono-coverage, SharpCover or xr.Baboon + - coverage xml -i + - codecov --file coverage.xml --flags setup_linux notifications: email: false + slack: + secure: "UiQdSK1/uNnHl8/gQgfLj/F5JGxtJuaT3QYtKNcw3Ddpr3FX8tfXJ/RjsCsSlRQzDm7AdBAeMzcBQmvH4iRIV2y7qVywLyru5MPiwY4ZjMN6fJK/zaaxetOct9fasIBYzHguNPDAtiBGFh2iK1H1MXTY8rkmU3WZvl18b8EsrP0=" diff --git a/AUTHORS.md b/AUTHORS.md index 2a2110f26..09358586e 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -12,11 +12,14 @@ ## Contributors +- Arvid JB ([@ArvidJB](https://github.com/ArvidJB)) - Bradley Friedman ([@leith-bartrich](https://github.com/leith-bartrich)) - Christian Heimes ([@tiran](https://github.com/tiran)) - Christoph Gohlke ([@cgohlke](https://github.com/cgohlke)) +- Daniel Fernandez ([@fdanny](https://github.com/fdanny)) - Daniel Santana ([@dgsantana](https://github.com/dgsantana)) - David Lechner ([@dlech](https://github.com/dlech)) +- Dmitriy Se ([@dmitriyse](https://github.com/dmitriyse)) - He-chien Tsai ([@t3476](https://github.com/t3476)) - Jeff Reback ([@jreback](https://github.com/jreback)) - Joe Frayne ([@jfrayne](https://github.com/jfrayne)) @@ -29,12 +32,10 @@ - Sean Freitag ([@cowboygneox](https://github.com/cowboygneox)) - Serge Weinstock ([@sweinst](https://github.com/sweinst)) - Virgil Dupras ([@hsoft](https://github.com/hsoft)) +- Wenguang Yang ([@yagweb](https://github.com/yagweb)) - 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)) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0dcf33d7e..f9a3d7a2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,29 +9,78 @@ This document follows the conventions laid out in [Keep a CHANGELOG][]. ### Added -- Code Coverage (#345) -- Added `pysetargv` (#347) +- Added `Foo` feature + +### Changed + +- Changed `Bar` feature + +### Fixed + +- Fixed `FooBar` bug + +## [2.3.0][] - 2017-03-11 + +### Added + +- Added Code Coverage (#345) +- Added `PySys_SetArgvEx` (#347) - Added XML Documentation (#349) -- Added Embedded tests on Appveyor (#353) -- Added PY3 settings to configuration-manager (#346) +- Added `Embedded_Tests` on AppVeyor (#224)(#353) +- Added `Embedded_Tests` on Travis (#224)(#391) +- Added PY3 settings to solution configuration-manager (#346) +- Added `Slack` (#384)(#383)(#386) +- Added function of passing an arbitrary .NET object as the value + of an attribute of `PyObject` (#370)(#373) +- Added `Coverity scan` (#390) +- Added `bumpversion` for version control (#319)(#398) +- Added `tox` for local testing (#345) +- Added `requirements.txt` +- Added to `PythonEngine` methods `Eval` and `Exec` (#389) +- Added implementations of `ICustomMarshal` (#407) +- Added docker images (#322) +- Added hooks in `pyinstaller` and `cx_freeze` for `pythonnet` (#66) ### Changed -- Refactored `setup.py` (#337) -- Upgraded NUnit framework to 2.6.4 (#353) -- Completed refactor of Build Directives on `Runtime.cs` (#339) -- Refactor python unittests (#329) +- Refactored python `unittests` (#329) +- Refactored python `setup.py` (#337) +- Refactored remaining of Build Directives on `runtime.cs` (#339) +- Refactored `Embedded_Tests` to make easier to write tests (#369) +- Changed `unittests` to `pytest` (#368) +- Upgraded NUnit framework from `2.6.3` to `3.5.0` (#341) +- Downgraded NUnit framework from `3.5.0` to `2.6.4` (#353) +- Upgraded NUnit framework from `2.6.4` to `3.6.0` (#371) - Unfroze Mono version on Travis (#345) +- Changed `conda.recipe` build to only pull-requests (#345) +- Combine `Py_DEBUG` and `PYTHON_WITH_PYDEBUG` flags (#362) + +### Deprecated + +- Deprecated `RunString` (#401) ### Fixed -- Fixed crash during Initialization (#343) +- Fixed crash during Initialization (#262)(#343) - Fixed crash during Shutdown (#365) +- Fixed multiple build warnings +- Fixed method signature match for Object Type (#203)(#377) +- Fixed outdated version number in AssemblyInfo (#398) +- Fixed wrong version number in `conda.recipe` (#398) +- Fixed fixture location for Python tests and `Embedded_Tests` +- Fixed `PythonException` crash during Shutdown (#400) +- Fixed `AppDomain` unload during GC (#397)(#400) +- Fixed `Py_Main` & `PySys_SetArgvEx` `no mem error` on `UCS4/PY3` (#399) +- Fixed `Python.Runtime.dll.config` on macOS (#120) +- Fixed crash on `PythonEngine.Version` (#413) +- Fixed `PythonEngine.PythonPath` issues (#179)(#414)(#415) ### Removed -- Removed `six` dependency for unittests (#329) +- Removed `six` dependency for `unittests` (#329) - Removed `Mono.Unix` dependency for `UCS4` (#360) +- Removed need for `Python.Runtime.dll.config` +- Removed PY32 build option `PYTHON_WITH_WIDE_UNICODE` (#417) ## [2.2.2][] - 2017-01-29 @@ -41,7 +90,7 @@ 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` +- `v2.2.0` had a release issue on PyPi. Bumped to `v2.2.1` ### Added @@ -107,7 +156,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][]. ## [2.0.0][] - 2015-06-26 - Release +- Release ## 2.0.0-alpha.2 @@ -508,7 +557,9 @@ This document follows the conventions laid out in [Keep a CHANGELOG][]. [semantic versioning]: http://semver.org/ -[unreleased]: ../../compare/v2.2.2...HEAD +[unreleased]: ../../compare/v2.3.0...HEAD + +[2.3.0]: ../../compare/v2.2.2...v2.3.0 [2.2.2]: ../../compare/v2.2.1...v2.2.2 diff --git a/LICENSE b/LICENSE index 0535829ff..e344a0795 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2017 the contributors of the "Python for .NET" project +Copyright (c) 2006-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"), diff --git a/Python.Runtime.dll.config b/Python.Runtime.dll.config deleted file mode 100644 index 8591f58fe..000000000 --- a/Python.Runtime.dll.config +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/README.md b/README.md index 86825386c..da43abacd 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,13 @@ [![appveyor shield][]](https://ci.appveyor.com/project/pythonnet/pythonnet/branch/master) [![travis shield][]](https://travis-ci.org/pythonnet/pythonnet) [![codecov shield][]](https://codecov.io/github/pythonnet/pythonnet) +[![coverity shield][]](https://scan.coverity.com/projects/pythonnet) + [![license shield][]](./LICENSE) [![pypi package version][]](https://pypi.python.org/pypi/pythonnet) [![python supported shield][]](https://pypi.python.org/pypi/pythonnet) +[![stackexchange shield][]](http://stackoverflow.com/questions/tagged/python.net) +[![slack][]](https://pythonnet.slack.com) Python for .NET is a package that gives Python programmers nearly seamless integration with the .NET Common Language Runtime (CLR) and @@ -35,14 +39,14 @@ from System.Windows.Forms import Form ## Embedding Python in .NET - All calls to python should be inside - a `using (Py.GIL()) {/_ Your code here _/}` block. + 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. + have the python object first, eg. `np.pi * 2` works, `2 * np.pi` doesn't. ### Example @@ -52,17 +56,21 @@ static void Main(string[] args) using (Py.GIL()) { dynamic np = Py.Import("numpy"); + Console.WriteLine(np.cos(np.pi * 2)); + 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); + + dynamic b = np.array(new List { 6, 5, 4 }, Py.kw("dtype", np.int32)); Console.WriteLine(b.dtype); - Console.WriteLine(a * b); */ + + Console.WriteLine(a * b); Console.ReadKey(); } } @@ -76,12 +84,14 @@ Output: -0.6752620892 float64 int32 -[6. 10. 12.] +[ 6. 10. 12.] ``` [appveyor shield]: https://img.shields.io/appveyor/ci/pythonnet/pythonnet/master.svg?label=AppVeyor -[codecov shield]: https://img.shields.io/codecov/c/github/pythonnet/pythonnet/master.svg?label=codecov +[codecov shield]: https://img.shields.io/codecov/c/github/pythonnet/pythonnet/master.svg?label=Codecov + +[coverity shield]: https://img.shields.io/coverity/scan/7830.svg [license shield]: https://img.shields.io/badge/license-MIT-blue.svg?maxAge=3600 @@ -89,4 +99,8 @@ int32 [python supported shield]: https://img.shields.io/pypi/pyversions/pythonnet.svg +[slack]: https://img.shields.io/badge/chat-slack-color.svg?style=social + +[stackexchange shield]: https://img.shields.io/badge/StackOverflow-python.net-blue.svg + [travis shield]: https://img.shields.io/travis/pythonnet/pythonnet/master.svg?label=Travis diff --git a/appveyor.yml b/appveyor.yml index fd5822ac9..c108801e7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -9,15 +9,7 @@ environment: global: PYTHONUNBUFFERED: True PYTHONWARNINGS: 'ignore:::wheel.pep425tags:' - PYTHONPATH: C:\testdir - NUNIT: nunit-console - CONDA_BLD: C:\conda - CONDA_BLD_VERSION: 3.5 - - # 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' + CODECOV_ENV: PYTHON_VERSION, PLATFORM matrix: - PYTHON_VERSION: 2.7 @@ -27,49 +19,44 @@ environment: - 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%PYTHON_VERSION:.=% - - if %PLATFORM%==x86 (set CONDA_BLD_ARCH=32) - - if %PLATFORM%==x86 (set NUNIT=%NUNIT%-x86) + # Update Environment Variables based on matrix/platform + - set PY_VER=%PYTHON_VERSION:.=% + - set PYTHON=C:\PYTHON%PY_VER% - if %PLATFORM%==x64 (set PYTHON=%PYTHON%-x64) - # Prepend newly installed Python to the PATH of this build + # Put desired Python version first in PATH - set PATH=%PYTHON%;%PYTHON%\Scripts;%PATH% - # Check that we have the expected version, architecture for Python - - python --version - - python -c "import struct; print(struct.calcsize('P') * 8)" - - python -c "import ctypes; print(ctypes.sizeof(ctypes.c_wchar))" - install: - # install for wheels & coverage - - pip install --upgrade pip wheel coverage codecov + - pip install --upgrade -r requirements.txt --quiet - # Install OpenCover. Can't put on packages.config; not Linux/Mono compatible - - .\tools\nuget\nuget.exe install OpenCover -OutputDirectory packages + # Install OpenCover. Can't put on `packages.config`, not Mono compatible + - .\tools\nuget\nuget.exe install OpenCover -OutputDirectory packages -Verbosity quiet build_script: - # build clean sdist & wheel with coverage of setup.py, install local wheel - - coverage run setup.py sdist bdist_wheel + # Create clean `sdist`. Only used for releases + - python setup.py --quiet sdist + # Build `wheel` with coverage of `setup.py` + - coverage run setup.py bdist_wheel test_script: - pip install --no-index --find-links=.\dist\ pythonnet - - ps: Copy-Item (Resolve-Path .\build\*\Python.Test.dll) C:\testdir - - # Test runner - ps: .\ci\appveyor_run_tests.ps1 - - # Build conda-recipe on Pull Requests - ps: .\ci\appveyor_build_recipe.ps1 on_finish: - # Upload coverage - - codecov + # Temporary disable multiple upload due to codecov limit of 20 per commit. + # https://docs.codecov.io/blog/week-8-2017 + # - coverage xml -i + # - codecov --file coverage.xml --flags setup_windows + # - codecov --file py.coverage --flags python_tests + # - codecov --file cs.coverage --flags embedded_tests + - codecov --flags setup_windows artifacts: - path: dist\* + +notifications: + - provider: Slack + incoming_webhook: + secure: 2S/t6rGHdbwoxehnvn5KgfsHrBFEtwnPD7M5olGErmz70oWFVpqoWd/EvDwh7rKZGdOTjDmpwcukc2xi5VRaGHbBAqFYS3tAdgAMrcaTNWs= diff --git a/ci/appveyor_build_recipe.ps1 b/ci/appveyor_build_recipe.ps1 index 0c885d88d..84e0bc7c6 100644 --- a/ci/appveyor_build_recipe.ps1 +++ b/ci/appveyor_build_recipe.ps1 @@ -1,6 +1,39 @@ -if ($env:APPVEYOR_PULL_REQUEST_NUMBER) { - Invoke-Expression .\ci\install_miniconda.ps1 - &"$env:CONDA_BLD\Scripts\conda" build conda.recipe --dirty -q - $CONDA_PKG=(&"$env:CONDA_BLD\Scripts\conda" build conda.recipe --output -q) - Copy-Item $CONDA_PKG "$env:APPVEYOR_BUILD_FOLDER\dist\" +# Build `conda.recipe` only if this is a Pull_Request. Saves time for CI. + +$env:CONDA_PY = "$env:PY_VER" +# Use pre-installed miniconda. Note that location differs if 64bit +$env:CONDA_BLD = "C:\miniconda36" + +if ($env:PLATFORM -eq "x86"){ + $env:CONDA_BLD_ARCH=32 +} else { + $env:CONDA_BLD_ARCH=64 + $env:CONDA_BLD = "$env:CONDA_BLD" + "-x64" +} + +if ($env:APPVEYOR_PULL_REQUEST_NUMBER -or $env:APPVEYOR_REPO_TAG_NAME -or $env:FORCE_CONDA_BUILD -eq "True") { + # Update PATH, and keep a copy to restore at end of this PowerShell script + $old_path = $env:path + $env:path = "$env:CONDA_BLD;$env:CONDA_BLD\Scripts;" + $env:path + + Write-Host "Starting conda install" -ForegroundColor "Green" + conda config --set always_yes True + conda config --set changeps1 False + conda config --set auto_update_conda False + conda install conda-build jinja2 anaconda-client --quiet + conda info + + # why `2>&1 | %{ "$_" }`? Redirect STDERR to STDOUT + # see: http://stackoverflow.com/a/20950421/5208670 + Write-Host "Starting conda build recipe" -ForegroundColor "Green" + conda build conda.recipe --quiet 2>&1 | %{ "$_" } + + $CONDA_PKG=(conda build conda.recipe --output) + Copy-Item $CONDA_PKG .\dist\ + Write-Host "Completed conda build recipe" -ForegroundColor "Green" + + # Restore PATH back to original + $env:path = $old_path +} else { + Write-Host "Skipping conda build recipe" -ForegroundColor "Green" } diff --git a/ci/appveyor_run_tests.ps1 b/ci/appveyor_run_tests.ps1 index 300b2caa0..4245d1577 100644 --- a/ci/appveyor_run_tests.ps1 +++ b/ci/appveyor_run_tests.ps1 @@ -1,9 +1,17 @@ -# Script to simplify appveyor configuration and resolve path to tools +# Script to simplify AppVeyor configuration and resolve path to tools + +# Test Runner framework being used for embedded tests +$CS_RUNNER = "nunit3-console" + +# Needed for ARCH specific runners(NUnit2/XUnit3). Skip for NUnit3 +if ($FALSE -and $env:PLATFORM -eq "x86"){ + $CS_RUNNER = $CS_RUNNER + "-x86" +} # Executable paths for OpenCover # Note if OpenCover fails, it won't affect the exit codes. $OPENCOVER = Resolve-Path .\packages\OpenCover.*\tools\OpenCover.Console.exe -$NUNIT = Resolve-Path .\packages\NUnit.Runners*\tools\"$env:NUNIT".exe +$CS_RUNNER = Resolve-Path .\packages\NUnit.*\tools\"$CS_RUNNER".exe $PY = Get-Command python # Can't use ".\build\*\Python.EmbeddingTest.dll". Missing framework files. @@ -11,9 +19,10 @@ $CS_TESTS = ".\src\embed_tests\bin\Python.EmbeddingTest.dll" $RUNTIME_DIR = ".\src\runtime\bin\" # Run python tests with C# coverage -# why `2>&1 | %{ "$_" }`? see: http://stackoverflow.com/a/20950421/5208670 Write-Host ("Starting Python tests") -ForegroundColor "Green" -.$OPENCOVER -register:user -searchdirs:"$RUNTIME_DIR" -output:py.coverage -target:"$PY" -targetargs:src\tests\runtests.py -returntargetcode 2>&1 | %{ "$_" } +.$OPENCOVER -register:user -searchdirs:"$RUNTIME_DIR" -output:py.coverage ` + -target:"$PY" -targetargs:"-m pytest" ` + -returntargetcode $PYTHON_STATUS = $LastExitCode if ($PYTHON_STATUS -ne 0) { Write-Host "Python tests failed, continuing to embedded tests" -ForegroundColor "Red" @@ -21,14 +30,17 @@ if ($PYTHON_STATUS -ne 0) { # Run Embedded tests with C# coverage Write-Host ("Starting embedded tests") -ForegroundColor "Green" -.$OPENCOVER -register:user -searchdirs:"$RUNTIME_DIR" -output:cs.coverage -target:"$NUNIT" -targetargs:"$CS_TESTS" -returntargetcode -$NUNIT_STATUS = $LastExitCode -if ($NUNIT_STATUS -ne 0) { +.$OPENCOVER -register:user -searchdirs:"$RUNTIME_DIR" -output:cs.coverage ` + -target:"$CS_RUNNER" -targetargs:"$CS_TESTS" ` + -filter:"+[*]Python.Runtime*" ` + -returntargetcode +$CS_STATUS = $LastExitCode +if ($CS_STATUS -ne 0) { Write-Host "Embedded tests failed" -ForegroundColor "Red" } # Set exit code to fail if either Python or Embedded tests failed -if ($PYTHON_STATUS -ne 0 -or $NUNIT_STATUS -ne 0) { +if ($PYTHON_STATUS -ne 0 -or $CS_STATUS -ne 0) { Write-Host "Tests failed" -ForegroundColor "Red" $host.SetShouldExit(1) } diff --git a/ci/install_miniconda.ps1 b/ci/install_miniconda.ps1 deleted file mode 100644 index 5c87ca894..000000000 --- a/ci/install_miniconda.ps1 +++ /dev/null @@ -1,95 +0,0 @@ -# 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 deleted file mode 100644 index c88489f2c..000000000 --- a/ci/run_with_env.cmd +++ /dev/null @@ -1,85 +0,0 @@ -:: 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 index d846fc738..1495f877d 100644 --- a/conda.recipe/bld.bat +++ b/conda.recipe/bld.bat @@ -4,10 +4,3 @@ 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 index da62edc90..3641185bb 100644 --- a/conda.recipe/meta.yaml +++ b/conda.recipe/meta.yaml @@ -1,6 +1,6 @@ package: name: pythonnet - version: {{ environ.get('GIT_DESCRIBE_TAG', '').replace('-dev', '.dev') }} + version: "2.4.0.dev0" build: skip: True # [not win] @@ -26,3 +26,4 @@ test: about: home: https://github.com/pythonnet/pythonnet license: MIT + license_file: LICENSE diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..bcceedf25 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,12 @@ +# Requirements for both Travis and AppVeyor +pytest +coverage + +# Platform specific requirements +pip; sys_platform == 'win32' +wheel; sys_platform == 'win32' +pycparser; sys_platform != 'win32' + +# Coverage upload +# codecov v2.0.6 isn't on PyPi +https://github.com/codecov/codecov-python/tarball/v2.0.6 diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 000000000..38aa3eb3d --- /dev/null +++ b/setup.cfg @@ -0,0 +1,10 @@ +# [bumpversion] comments. bumpversion deleted all comments on its file. +# Don't combine `.bumpversion.cfg` with `setup.cfg`. Messes up formatting. +# Don't use `first_value = 1`. It will break `release` bump +# Keep `optional = dummy` needed to bump to release. +# See: https://github.com/peritus/bumpversion/issues/59 + +[tool:pytest] +xfail_strict = True +# -r fsxX: show extra summary info for: (f)ailed, (s)kip, (x)failed, (X)passed +addopts = -r fsxX --color=yes --durations=5 diff --git a/setup.py b/setup.py index f2790ddd3..b9893563a 100644 --- a/setup.py +++ b/setup.py @@ -10,7 +10,6 @@ import fnmatch import glob import os -import platform import subprocess import sys import sysconfig @@ -24,8 +23,9 @@ CONFIG = "Release" # Release or Debug VERBOSITY = "minimal" # quiet, minimal, normal, detailed, diagnostic +is_64bits = sys.maxsize > 2**32 DEVTOOLS = "MsDev" if sys.platform == "win32" else "Mono" -ARCH = "x64" if platform.architecture()[0] == "64bit" else "x86" +ARCH = "x64" if is_64bits else "x86" PY_MAJOR = sys.version_info[0] PY_MINOR = sys.version_info[1] @@ -104,7 +104,7 @@ def _get_interop_filename(): def _get_source_files(): """Walk project and collect the files needed for ext_module""" - for ext in (".sln", ".config"): + for ext in (".sln", ): for path in glob.glob("*" + ext): yield path @@ -162,16 +162,15 @@ def build_extension(self, ext): defines.extend(["DEBUG", "TRACE"]) if sys.platform != "win32" and DEVTOOLS == "Mono": - if sys.platform == "darwin": - defines.append("MONO_OSX") - else: - defines.append("MONO_LINUX") + on_darwin = sys.platform == "darwin" + defines.append("MONO_OSX" if on_darwin else "MONO_LINUX") # Check if --enable-shared was set when Python was built enable_shared = sysconfig.get_config_var("Py_ENABLE_SHARED") if enable_shared: # Double-check if libpython is linked dynamically with python - lddout = _check_output(["ldd", sys.executable]) + ldd_cmd = ["otool", "-L"] if on_darwin else ["ldd"] + lddout = _check_output(ldd_cmd + [sys.executable]) if 'libpython' not in lddout: enable_shared = False @@ -183,8 +182,6 @@ def build_extension(self, ext): defines.append("PYTHON_WITH_PYDEBUG") if "m" in sys.abiflags: defines.append("PYTHON_WITH_PYMALLOC") - if "u" in sys.abiflags: - defines.append("PYTHON_WITH_WIDE_UNICODE") # check the interop file exists, and create it if it doesn't interop_file = _get_interop_filename() @@ -368,7 +365,7 @@ def run(self): setup( name="pythonnet", - version="2.2.2", + version="2.4.0.dev0", description=".Net and Mono integration for Python", url='https://pythonnet.github.io/', license='MIT', @@ -382,7 +379,7 @@ def run(self): data_files=[ ("{install_platlib}", [ "{build_lib}/Python.Runtime.dll", - "Python.Runtime.dll.config"]), + ]), ], cmdclass={ "build_ext": BuildExtPythonnet, diff --git a/src/SharedAssemblyInfo.cs b/src/SharedAssemblyInfo.cs new file mode 100644 index 000000000..c164e75d6 --- /dev/null +++ b/src/SharedAssemblyInfo.cs @@ -0,0 +1,28 @@ +using System; +using System.Reflection; +using System.Resources; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("pythonnet")] +[assembly: AssemblyProduct("Python for .NET")] +[assembly: AssemblyCopyright("Copyright (c) 2006-2017 the contributors of the 'Python for .NET' project")] +[assembly: AssemblyTrademark("")] + +[assembly: AssemblyCulture("")] +[assembly: NeutralResourcesLanguage("")] + +[assembly: CLSCompliant(true)] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// Version Information. Keeping it simple. May need to revisit for Nuget +// See: https://codingforsmarties.wordpress.com/2016/01/21/how-to-version-assemblies-destined-for-nuget/ +// AssemblyVersion can only be numeric +[assembly: AssemblyVersion("2.4.0")] diff --git a/src/clrmodule/AssemblyInfo.cs b/src/clrmodule/AssemblyInfo.cs deleted file mode 100644 index 669183255..000000000 --- a/src/clrmodule/AssemblyInfo.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. - -[assembly: AssemblyTitle("clrmodule")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("clrmodule")] -[assembly: AssemblyCopyright("Copyright © 2013")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. - -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM - -[assembly: Guid("ae10d6a4-55c2-482f-9716-9988e6c169e3")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] - -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/clrmodule/ClrModule.cs b/src/clrmodule/ClrModule.cs index 413b952eb..3bb3a533b 100644 --- a/src/clrmodule/ClrModule.cs +++ b/src/clrmodule/ClrModule.cs @@ -52,7 +52,8 @@ public static void initclr() var pythonRuntimeName = new AssemblyName("Python.Runtime") { #if USE_PYTHON_RUNTIME_VERSION - Version = new Version("4.0.0.1"), + // Has no effect until SNK works. Keep updated anyways. + Version = new Version("2.4.0"), #endif CultureInfo = CultureInfo.InvariantCulture }; diff --git a/src/clrmodule/Properties/AssemblyInfo.cs b/src/clrmodule/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..939f4171f --- /dev/null +++ b/src/clrmodule/Properties/AssemblyInfo.cs @@ -0,0 +1,11 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("clrmodule")] +[assembly: AssemblyDescription("")] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("ae10d6a4-55c2-482f-9716-9988e6c169e3")] diff --git a/src/clrmodule/clrmodule.csproj b/src/clrmodule/clrmodule.csproj index 435630d0e..6e5ff4966 100644 --- a/src/clrmodule/clrmodule.csproj +++ b/src/clrmodule/clrmodule.csproj @@ -13,8 +13,9 @@ 1591 ..\..\ - $(SolutionDir) - + $(SolutionDir)\bin\ + Properties + 6 true prompt @@ -72,7 +73,10 @@ - + + + Properties\SharedAssemblyInfo.cs + diff --git a/src/console/AssemblyInfo.cs b/src/console/AssemblyInfo.cs deleted file mode 100644 index 17d792c7a..000000000 --- a/src/console/AssemblyInfo.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Reflection; -using System.Resources; -using System.Runtime.InteropServices; -using System.Security.Permissions; - -[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: AssemblyDescription("")] -[assembly: AssemblyCopyright("MIT License")] -[assembly: AssemblyFileVersion("2.0.0.4")] -[assembly: NeutralResourcesLanguage("en")] diff --git a/src/console/Console.csproj b/src/console/Console.csproj index cdee6893b..ea88b6356 100644 --- a/src/console/Console.csproj +++ b/src/console/Console.csproj @@ -13,8 +13,9 @@ 1591 ..\..\ - $(SolutionDir) - + $(SolutionDir)\bin\ + Properties + 6 python-clear.ico prompt @@ -30,7 +31,8 @@ full - + + true pdbonly @@ -40,7 +42,8 @@ full - + + true pdbonly @@ -50,7 +53,8 @@ full - + + true pdbonly @@ -60,7 +64,8 @@ full - + + true pdbonly @@ -71,7 +76,10 @@ - + + + Properties\SharedAssemblyInfo.cs + diff --git a/src/console/Properties/AssemblyInfo.cs b/src/console/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..081ae0c94 --- /dev/null +++ b/src/console/Properties/AssemblyInfo.cs @@ -0,0 +1,8 @@ +using System.Reflection; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Python Console")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyDefaultAlias("python.exe")] diff --git a/src/embed_tests/Python.EmbeddingTest.csproj b/src/embed_tests/Python.EmbeddingTest.csproj index 9cca794b4..3ec0d4b57 100644 --- a/src/embed_tests/Python.EmbeddingTest.csproj +++ b/src/embed_tests/Python.EmbeddingTest.csproj @@ -13,8 +13,8 @@ 1591 ..\..\ - $(SolutionDir) - + $(SolutionDir)\bin\ + 6 true prompt @@ -30,7 +30,8 @@ full - + + true pdbonly @@ -40,7 +41,8 @@ full - + + true pdbonly @@ -50,7 +52,8 @@ full - + + true pdbonly @@ -60,13 +63,15 @@ full - + + true pdbonly - - ..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll + + + ..\..\packages\NUnit.3.6.0\lib\net40\nunit.framework.dll @@ -75,13 +80,24 @@ - + - - - - - + + + + + + + + + + + + + + + + diff --git a/src/embed_tests/TestCustomMarshal.cs b/src/embed_tests/TestCustomMarshal.cs new file mode 100644 index 000000000..5860857a3 --- /dev/null +++ b/src/embed_tests/TestCustomMarshal.cs @@ -0,0 +1,35 @@ +using System; +using NUnit.Framework; +using Python.Runtime; + +namespace Python.EmbeddingTest +{ + public class TestCustomMarshal + { + [OneTimeSetUp] + public void SetUp() + { + PythonEngine.Initialize(); + } + + [OneTimeTearDown] + public void Dispose() + { + PythonEngine.Shutdown(); + } + + [Test] + public static void GetManagedStringTwice() + { + const string expected = "FooBar"; + + IntPtr op = Runtime.Runtime.PyUnicode_FromString(expected); + string s1 = Runtime.Runtime.GetManagedString(op); + string s2 = Runtime.Runtime.GetManagedString(op); + + Assert.AreEqual(1, Runtime.Runtime.Refcount(op)); + Assert.AreEqual(expected, s1); + Assert.AreEqual(expected, s2); + } + } +} diff --git a/src/embed_tests/TestExample.cs b/src/embed_tests/TestExample.cs new file mode 100644 index 000000000..0cf795f5d --- /dev/null +++ b/src/embed_tests/TestExample.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using NUnit.Framework; +using Python.Runtime; + +namespace Python.EmbeddingTest +{ + public class TestExample + { + [OneTimeSetUp] + public void SetUp() + { + PythonEngine.Initialize(); + } + + [OneTimeTearDown] + public void Dispose() + { + PythonEngine.Shutdown(); + } + + [Test] + public void TestReadme() + { + dynamic np; + try + { + np = Py.Import("numpy"); + } + catch (PythonException) + { + Assert.Inconclusive("Numpy or dependency not installed"); + return; + } + + Assert.AreEqual("1.0", np.cos(np.pi * 2).ToString()); + + dynamic sin = np.sin; + StringAssert.StartsWith("-0.95892", sin(5).ToString()); + + double c = np.cos(5) + sin(5); + Assert.AreEqual(-0.675262, c, 0.01); + + dynamic a = np.array(new List { 1, 2, 3 }); + Assert.AreEqual("float64", a.dtype.ToString()); + + dynamic b = np.array(new List { 6, 5, 4 }, Py.kw("dtype", np.int32)); + Assert.AreEqual("int32", b.dtype.ToString()); + + Assert.AreEqual("[ 6. 10. 12.]", (a * b).ToString()); + } + } +} diff --git a/src/embed_tests/TestPyAnsiString.cs b/src/embed_tests/TestPyAnsiString.cs new file mode 100644 index 000000000..9ba7d6cc6 --- /dev/null +++ b/src/embed_tests/TestPyAnsiString.cs @@ -0,0 +1,96 @@ +using System; +using NUnit.Framework; +using Python.Runtime; + +namespace Python.EmbeddingTest +{ + public class TestPyAnsiString + { + [OneTimeSetUp] + public void SetUp() + { + PythonEngine.Initialize(); + } + + [OneTimeTearDown] + public void Dispose() + { + PythonEngine.Shutdown(); + } + + [Test] + public void TestStringCtor() + { + const string expected = "foo"; + var actual = new PyAnsiString(expected); + Assert.AreEqual(expected, actual.ToString()); + } + + [Test] + public void TestEmptyStringCtor() + { + const string expected = ""; + var actual = new PyAnsiString(expected); + Assert.AreEqual(expected, actual.ToString()); + } + + [Test] + public void TestPyObjectCtor() + { + const string expected = "Foo"; + + var t = new PyAnsiString(expected); + var actual = new PyAnsiString(t); + + Assert.AreEqual(expected, actual.ToString()); + } + + [Test] + public void TestBadPyObjectCtor() + { + var t = new PyInt(5); + PyAnsiString actual = null; + + var ex = Assert.Throws(() => actual = new PyAnsiString(t)); + + StringAssert.StartsWith("object is not a string", ex.Message); + Assert.IsNull(actual); + } + + [Test] + public void TestCtorPtr() + { + const string expected = "foo"; + + var t = new PyAnsiString(expected); + var actual = new PyAnsiString(t.Handle); + + Assert.AreEqual(expected, actual.ToString()); + } + + [Test] + public void IsStringTrue() + { + var t = new PyAnsiString("foo"); + + Assert.True(PyAnsiString.IsStringType(t)); + } + + [Test] + public void IsStringFalse() + { + var t = new PyInt(5); + + Assert.False(PyAnsiString.IsStringType(t)); + } + + [Test] + [Ignore("Ambiguous behavior between PY2/PY3")] + public void TestUnicode() + { + const string expected = "foo\u00e9"; + PyObject actual = new PyAnsiString(expected); + Assert.AreEqual(expected, actual.ToString()); + } + } +} diff --git a/src/embed_tests/TestPyFloat.cs b/src/embed_tests/TestPyFloat.cs new file mode 100644 index 000000000..f2c85a77f --- /dev/null +++ b/src/embed_tests/TestPyFloat.cs @@ -0,0 +1,138 @@ +using System; +using NUnit.Framework; +using Python.Runtime; + +namespace Python.EmbeddingTest +{ + /// + /// PyFloat implementation isn't complete, thus tests aren't complete. + /// + public class TestPyFloat + { + [OneTimeSetUp] + public void SetUp() + { + PythonEngine.Initialize(); + } + + [OneTimeTearDown] + public void Dispose() + { + PythonEngine.Shutdown(); + } + + [Test] + public void IntPtrCtor() + { + var i = new PyFloat(1); + var ii = new PyFloat(i.Handle); + Assert.AreEqual(i.Handle, ii.Handle); + } + + [Test] + public void FloatCtor() + { + const float a = 4.5F; + var i = new PyFloat(a); + Assert.True(PyFloat.IsFloatType(i)); + // Assert.Assert.AreEqual(i, a.ToInt32()); + } + + [Test] + public void PyObjectCtorGood() + { + var i = new PyFloat(5); + var a = new PyFloat(i); + Assert.True(PyFloat.IsFloatType(a)); + // Assert.Assert.AreEqual(i, a.ToInt32()); + } + + [Test] + public void PyObjectCtorBad() + { + var i = new PyString("Foo"); + PyFloat a = null; + + var ex = Assert.Throws(() => a = new PyFloat(i)); + + StringAssert.StartsWith("object is not a float", ex.Message); + Assert.IsNull(a); + } + + [Test] + public void DoubleCtor() + { + const double a = 4.5; + var i = new PyFloat(a); + Assert.True(PyFloat.IsFloatType(i)); + // Assert.Assert.AreEqual(i, a.ToInt32()); + } + + [Test] + public void StringIntCtor() + { + const string a = "5"; + var i = new PyFloat(a); + Assert.True(PyFloat.IsFloatType(i)); + // Assert.Assert.AreEqual(i, a.ToInt32()); + } + + [Test] + public void StringDoubleCtor() + { + const string a = "4.5"; + var i = new PyFloat(a); + Assert.True(PyFloat.IsFloatType(i)); + // Assert.Assert.AreEqual(i, a.ToInt32()); + } + + [Test] + public void StringBadCtor() + { + const string i = "Foo"; + PyFloat a = null; + + var ex = Assert.Throws(() => a = new PyFloat(i)); + + StringAssert.StartsWith("ValueError : could not convert string to float", ex.Message); + Assert.IsNull(a); + } + + [Test] + public void IsFloatTrue() + { + const double a = 4.5; + var i = new PyFloat(a); + Assert.True(PyFloat.IsFloatType(i)); + } + + [Test] + public void IsFloatFalse() + { + var i = new PyString("Foo"); + Assert.False(PyFloat.IsFloatType(i)); + } + + [Test] + public void AsFloatGood() + { + const double a = 4.5; + var i = new PyFloat(a); + PyFloat s = PyFloat.AsFloat(i); + + Assert.True(PyFloat.IsFloatType(s)); + // Assert.Assert.AreEqual(i, a.ToInt32()); + } + + [Test] + public void AsFloatBad() + { + var s = new PyString("Foo"); + PyFloat a = null; + + var ex = Assert.Throws(() => a = PyFloat.AsFloat(s)); + StringAssert.StartsWith("ValueError : could not convert string to float", ex.Message); + Assert.IsNull(a); + } + } +} diff --git a/src/embed_tests/TestPyInt.cs b/src/embed_tests/TestPyInt.cs new file mode 100644 index 000000000..4117336d8 --- /dev/null +++ b/src/embed_tests/TestPyInt.cs @@ -0,0 +1,190 @@ +using System; +using NUnit.Framework; +using Python.Runtime; + +namespace Python.EmbeddingTest +{ + public class TestPyInt + { + [OneTimeSetUp] + public void SetUp() + { + PythonEngine.Initialize(); + } + + [OneTimeTearDown] + public void Dispose() + { + PythonEngine.Shutdown(); + } + + [Test] + public void TestCtorInt() + { + const int i = 5; + var a = new PyInt(i); + Assert.AreEqual(i, a.ToInt32()); + } + + [Test] + public void TestCtorUInt() + { + const uint i = 5; + var a = new PyInt(i); + Assert.AreEqual(i, a.ToInt32()); + } + + [Test] + public void TestCtorLong() + { + const long i = 5; + var a = new PyInt(i); + Assert.AreEqual(i, a.ToInt32()); + } + + [Test] + public void TestCtorULong() + { + const ulong i = 5; + var a = new PyInt(i); + Assert.AreEqual(i, a.ToInt32()); + } + + [Test] + public void TestCtorShort() + { + const short i = 5; + var a = new PyInt(i); + Assert.AreEqual(i, a.ToInt32()); + } + + [Test] + public void TestCtorUShort() + { + const ushort i = 5; + var a = new PyInt(i); + Assert.AreEqual(i, a.ToInt32()); + } + + [Test] + public void TestCtorByte() + { + const byte i = 5; + var a = new PyInt(i); + Assert.AreEqual(i, a.ToInt32()); + } + + [Test] + public void TestCtorSByte() + { + const sbyte i = 5; + var a = new PyInt(i); + Assert.AreEqual(i, a.ToInt32()); + } + + [Test] + public void TestCtorPtr() + { + var i = new PyInt(5); + var a = new PyInt(i.Handle); + Assert.AreEqual(5, a.ToInt32()); + } + + [Test] + public void TestCtorPyObject() + { + var i = new PyInt(5); + var a = new PyInt(i); + Assert.AreEqual(5, a.ToInt32()); + } + + [Test] + public void TestCtorBadPyObject() + { + var i = new PyString("Foo"); + PyInt a = null; + + var ex = Assert.Throws(() => a = new PyInt(i)); + + StringAssert.StartsWith("object is not an int", ex.Message); + Assert.IsNull(a); + } + + [Test] + public void TestCtorString() + { + const string i = "5"; + var a = new PyInt(i); + Assert.AreEqual(5, a.ToInt32()); + } + + [Test] + public void TestCtorBadString() + { + const string i = "Foo"; + PyInt a = null; + + var ex = Assert.Throws(() => a = new PyInt(i)); + + StringAssert.StartsWith("ValueError : invalid literal for int", ex.Message); + Assert.IsNull(a); + } + + [Test] + public void TestIsIntTypeTrue() + { + var i = new PyInt(5); + Assert.True(PyInt.IsIntType(i)); + } + + [Test] + public void TestIsIntTypeFalse() + { + var s = new PyString("Foo"); + Assert.False(PyInt.IsIntType(s)); + } + + [Test] + public void TestAsIntGood() + { + var i = new PyInt(5); + var a = PyInt.AsInt(i); + Assert.AreEqual(5, a.ToInt32()); + } + + [Test] + public void TestAsIntBad() + { + var s = new PyString("Foo"); + PyInt a = null; + + var ex = Assert.Throws(() => a = PyInt.AsInt(s)); + StringAssert.StartsWith("ValueError : invalid literal for int", ex.Message); + Assert.IsNull(a); + } + + [Test] + public void TestConvertToInt32() + { + var a = new PyInt(5); + Assert.IsInstanceOf(typeof(int), a.ToInt32()); + Assert.AreEqual(5, a.ToInt32()); + } + + [Test] + public void TestConvertToInt16() + { + var a = new PyInt(5); + Assert.IsInstanceOf(typeof(short), a.ToInt16()); + Assert.AreEqual(5, a.ToInt16()); + } + + [Test] + public void TestConvertToInt64() + { + var a = new PyInt(5); + Assert.IsInstanceOf(typeof(long), a.ToInt64()); + Assert.AreEqual(5, a.ToInt64()); + } + } +} diff --git a/src/embed_tests/TestPyList.cs b/src/embed_tests/TestPyList.cs new file mode 100644 index 000000000..e9acfbb45 --- /dev/null +++ b/src/embed_tests/TestPyList.cs @@ -0,0 +1,172 @@ +using System; +using System.Collections.Generic; +using NUnit.Framework; +using Python.Runtime; + +namespace Python.EmbeddingTest +{ + public class TestPyList + { + [OneTimeSetUp] + public void SetUp() + { + PythonEngine.Initialize(); + } + + [OneTimeTearDown] + public void Dispose() + { + PythonEngine.Shutdown(); + } + + [Test] + public void TestStringIsListType() + { + var s = new PyString("foo"); + Assert.False(PyList.IsListType(s)); + } + + [Test] + public void TestListIsListType() + { + var s = new PyList(); + Assert.True(PyList.IsListType(s)); + } + + [Test] + public void TestStringAsListType() + { + var i = new PyInt(5); + PyList t = null; + + var ex = Assert.Throws(() => t = PyList.AsList(i)); + + Assert.AreEqual("TypeError : 'int' object is not iterable", ex.Message); + Assert.IsNull(t); + } + + [Test] + public void TestListAsListType() + { + var l = new PyList(); + PyList t = PyList.AsList(l); + + Assert.IsNotNull(t); + Assert.IsInstanceOf(typeof(PyList), t); + } + + [Test] + public void TestEmptyCtor() + { + var s = new PyList(); + + Assert.IsInstanceOf(typeof(PyList), s); + Assert.AreEqual(0, s.Length()); + } + + [Test] + public void TestPyObjectArrayCtor() + { + var ai = new PyObject[] {new PyInt(3), new PyInt(2), new PyInt(1) }; + var s = new PyList(ai); + + Assert.IsInstanceOf(typeof(PyList), s); + Assert.AreEqual(3, s.Length()); + Assert.AreEqual("3", s[0].ToString()); + Assert.AreEqual("2", s[1].ToString()); + Assert.AreEqual("1", s[2].ToString()); + } + + [Test] + public void TestPyObjectCtor() + { + var a = new PyList(); + var s = new PyList(a); + + Assert.IsInstanceOf(typeof(PyList), s); + Assert.AreEqual(0, s.Length()); + } + + [Test] + public void TestBadPyObjectCtor() + { + var i = new PyInt(5); + PyList t = null; + + var ex = Assert.Throws(() => t = new PyList(i)); + + Assert.AreEqual("object is not a list", ex.Message); + Assert.IsNull(t); + } + + [Test] + public void TestAppend() + { + var ai = new PyObject[] { new PyInt(3), new PyInt(2), new PyInt(1) }; + var s = new PyList(ai); + s.Append(new PyInt(4)); + + Assert.AreEqual(4, s.Length()); + Assert.AreEqual("4", s[3].ToString()); + } + + [Test] + public void TestInsert() + { + var ai = new PyObject[] { new PyInt(3), new PyInt(2), new PyInt(1) }; + var s = new PyList(ai); + s.Insert(0, new PyInt(4)); + + Assert.AreEqual(4, s.Length()); + Assert.AreEqual("4", s[0].ToString()); + } + + [Test] + public void TestReverse() + { + var ai = new PyObject[] { new PyInt(3), new PyInt(1), new PyInt(2) }; + var s = new PyList(ai); + + s.Reverse(); + + Assert.AreEqual(3, s.Length()); + Assert.AreEqual("2", s[0].ToString()); + Assert.AreEqual("1", s[1].ToString()); + Assert.AreEqual("3", s[2].ToString()); + } + + [Test] + public void TestSort() + { + var ai = new PyObject[] { new PyInt(3), new PyInt(1), new PyInt(2) }; + var s = new PyList(ai); + + s.Sort(); + + Assert.AreEqual(3, s.Length()); + Assert.AreEqual("1", s[0].ToString()); + Assert.AreEqual("2", s[1].ToString()); + Assert.AreEqual("3", s[2].ToString()); + } + + [Test] + public void TestOnPyList() + { + var list = new PyList(); + + list.Append(new PyString("foo")); + list.Append(new PyString("bar")); + list.Append(new PyString("baz")); + var result = new List(); + foreach (PyObject item in list) + { + result.Add(item.ToString()); + } + + Assert.AreEqual(3, result.Count); + Assert.AreEqual("foo", result[0]); + Assert.AreEqual("bar", result[1]); + Assert.AreEqual("baz", result[2]); + } + } +} diff --git a/src/embed_tests/TestPyLong.cs b/src/embed_tests/TestPyLong.cs new file mode 100644 index 000000000..fe3e13ef5 --- /dev/null +++ b/src/embed_tests/TestPyLong.cs @@ -0,0 +1,206 @@ +using System; +using NUnit.Framework; +using Python.Runtime; + +namespace Python.EmbeddingTest +{ + public class TestPyLong + { + [OneTimeSetUp] + public void SetUp() + { + PythonEngine.Initialize(); + } + + [OneTimeTearDown] + public void Dispose() + { + PythonEngine.Shutdown(); + } + + [Test] + public void TestToInt64() + { + long largeNumber = 8L * 1024L * 1024L * 1024L; // 8 GB + var pyLargeNumber = new PyLong(largeNumber); + Assert.AreEqual(largeNumber, pyLargeNumber.ToInt64()); + } + + [Test] + public void TestCtorInt() + { + const int i = 5; + var a = new PyLong(i); + Assert.AreEqual(i, a.ToInt32()); + } + + [Test] + public void TestCtorUInt() + { + const uint i = 5; + var a = new PyLong(i); + Assert.AreEqual(i, a.ToInt32()); + } + + [Test] + public void TestCtorLong() + { + const long i = 5; + var a = new PyLong(i); + Assert.AreEqual(i, a.ToInt32()); + } + + [Test] + public void TestCtorULong() + { + const ulong i = 5; + var a = new PyLong(i); + Assert.AreEqual(i, a.ToInt32()); + } + + [Test] + public void TestCtorShort() + { + const short i = 5; + var a = new PyLong(i); + Assert.AreEqual(i, a.ToInt32()); + } + + [Test] + public void TestCtorUShort() + { + const ushort i = 5; + var a = new PyLong(i); + Assert.AreEqual(i, a.ToInt32()); + } + + [Test] + public void TestCtorByte() + { + const byte i = 5; + var a = new PyLong(i); + Assert.AreEqual(i, a.ToInt32()); + } + + [Test] + public void TestCtorSByte() + { + const sbyte i = 5; + var a = new PyLong(i); + Assert.AreEqual(i, a.ToInt32()); + } + + [Test] + public void TestCtorDouble() + { + double i = 5.0; + var a = new PyLong(i); + Assert.AreEqual(i, a.ToInt32()); + } + + [Test] + public void TestCtorPtr() + { + var i = new PyLong(5); + var a = new PyLong(i.Handle); + Assert.AreEqual(5, a.ToInt32()); + } + + [Test] + public void TestCtorPyObject() + { + var i = new PyLong(5); + var a = new PyLong(i); + Assert.AreEqual(5, a.ToInt32()); + } + + [Test] + public void TestCtorBadPyObject() + { + var i = new PyString("Foo"); + PyLong a = null; + + var ex = Assert.Throws(() => a = new PyLong(i)); + + StringAssert.StartsWith("object is not a long", ex.Message); + Assert.IsNull(a); + } + + [Test] + public void TestCtorString() + { + const string i = "5"; + var a = new PyLong(i); + Assert.AreEqual(5, a.ToInt32()); + } + + [Test] + public void TestCtorBadString() + { + const string i = "Foo"; + PyLong a = null; + + var ex = Assert.Throws(() => a = new PyLong(i)); + + StringAssert.StartsWith("ValueError : invalid literal", ex.Message); + Assert.IsNull(a); + } + + [Test] + public void TestIsIntTypeTrue() + { + var i = new PyLong(5); + Assert.True(PyLong.IsLongType(i)); + } + + [Test] + public void TestIsLongTypeFalse() + { + var s = new PyString("Foo"); + Assert.False(PyLong.IsLongType(s)); + } + + [Test] + public void TestAsLongGood() + { + var i = new PyLong(5); + var a = PyLong.AsLong(i); + Assert.AreEqual(5, a.ToInt32()); + } + + [Test] + public void TestAsLongBad() + { + var s = new PyString("Foo"); + PyLong a = null; + + var ex = Assert.Throws(() => a = PyLong.AsLong(s)); + StringAssert.StartsWith("ValueError : invalid literal", ex.Message); + Assert.IsNull(a); + } + + [Test] + public void TestConvertToInt32() + { + var a = new PyLong(5); + Assert.IsInstanceOf(typeof(int), a.ToInt32()); + Assert.AreEqual(5, a.ToInt32()); + } + + [Test] + public void TestConvertToInt16() + { + var a = new PyLong(5); + Assert.IsInstanceOf(typeof(short), a.ToInt16()); + Assert.AreEqual(5, a.ToInt16()); + } + + [Test] + public void TestConvertToInt64() + { + var a = new PyLong(5); + Assert.IsInstanceOf(typeof(long), a.ToInt64()); + Assert.AreEqual(5, a.ToInt64()); + } + } +} diff --git a/src/embed_tests/TestPyNumber.cs b/src/embed_tests/TestPyNumber.cs new file mode 100644 index 000000000..0261c15c1 --- /dev/null +++ b/src/embed_tests/TestPyNumber.cs @@ -0,0 +1,35 @@ +using System; +using NUnit.Framework; +using Python.Runtime; + +namespace Python.EmbeddingTest +{ + public class TestPyNumber + { + [OneTimeSetUp] + public void SetUp() + { + PythonEngine.Initialize(); + } + + [OneTimeTearDown] + public void Dispose() + { + PythonEngine.Shutdown(); + } + + [Test] + public void IsNumberTypeTrue() + { + var i = new PyInt(1); + Assert.True(PyNumber.IsNumberType(i)); + } + + [Test] + public void IsNumberTypeFalse() + { + var s = new PyString("Foo"); + Assert.False(PyNumber.IsNumberType(s)); + } + } +} diff --git a/src/embed_tests/TestPySequence.cs b/src/embed_tests/TestPySequence.cs new file mode 100644 index 000000000..7c175b1ce --- /dev/null +++ b/src/embed_tests/TestPySequence.cs @@ -0,0 +1,95 @@ +using System; +using NUnit.Framework; +using Python.Runtime; + +namespace Python.EmbeddingTest +{ + public class TestPySequence + { + [OneTimeSetUp] + public void SetUp() + { + PythonEngine.Initialize(); + } + + [OneTimeTearDown] + public void Dispose() + { + PythonEngine.Shutdown(); + } + + [Test] + public void TestIsSequenceTrue() + { + var t = new PyString("FooBar"); + Assert.True(PySequence.IsSequenceType(t)); + } + + [Test] + public void TestIsSequenceFalse() + { + var t = new PyInt(5); + Assert.False(PySequence.IsSequenceType(t)); + } + + [Test] + public void TestGetSlice() + { + var t = new PyString("FooBar"); + + PyObject s = t.GetSlice(0, 3); + Assert.AreEqual("Foo", s.ToString()); + + PyObject s2 = t.GetSlice(3, 6); + Assert.AreEqual("Bar", s2.ToString()); + + PyObject s3 = t.GetSlice(0, 6); + Assert.AreEqual("FooBar", s3.ToString()); + + PyObject s4 = t.GetSlice(0, 12); + Assert.AreEqual("FooBar", s4.ToString()); + } + + [Test] + public void TestConcat() + { + var t1 = new PyString("Foo"); + var t2 = new PyString("Bar"); + + PyObject actual = t1.Concat(t2); + + Assert.AreEqual("FooBar", actual.ToString()); + } + + [Test] + public void TestRepeat() + { + var t1 = new PyString("Foo"); + + PyObject actual = t1.Repeat(3); + Assert.AreEqual("FooFooFoo", actual.ToString()); + + actual = t1.Repeat(-3); + Assert.AreEqual("", actual.ToString()); + } + + [Test] + public void TestContains() + { + var t1 = new PyString("FooBar"); + + Assert.True(t1.Contains(new PyString("a"))); + Assert.False(t1.Contains(new PyString("z"))); + } + + [Test] + public void TestIndex() + { + var t1 = new PyString("FooBar"); + + Assert.AreEqual(4, t1.Index(new PyString("a"))); + Assert.AreEqual(5, t1.Index(new PyString("r"))); + Assert.AreEqual(-1, t1.Index(new PyString("z"))); + } + } +} diff --git a/src/embed_tests/TestPyString.cs b/src/embed_tests/TestPyString.cs new file mode 100644 index 000000000..9d1cdb0e9 --- /dev/null +++ b/src/embed_tests/TestPyString.cs @@ -0,0 +1,97 @@ +using System; +using NUnit.Framework; +using Python.Runtime; + +namespace Python.EmbeddingTest +{ + public class TestPyString + { + [OneTimeSetUp] + public void SetUp() + { + PythonEngine.Initialize(); + } + + [OneTimeTearDown] + public void Dispose() + { + PythonEngine.Shutdown(); + } + + [Test] + public void TestStringCtor() + { + const string expected = "foo"; + var actual = new PyString(expected); + Assert.AreEqual(expected, actual.ToString()); + } + + [Test] + public void TestEmptyStringCtor() + { + const string expected = ""; + var actual = new PyString(expected); + Assert.AreEqual(expected, actual.ToString()); + } + + [Test] + [Ignore("Ambiguous behavior between PY2/PY3. Needs remapping")] + public void TestPyObjectCtor() + { + const string expected = "Foo"; + + var t = new PyString(expected); + var actual = new PyString(t); + + Assert.AreEqual(expected, actual.ToString()); + } + + [Test] + public void TestBadPyObjectCtor() + { + var t = new PyInt(5); + PyString actual = null; + + var ex = Assert.Throws(() => actual = new PyString(t)); + + StringAssert.StartsWith("object is not a string", ex.Message); + Assert.IsNull(actual); + } + + [Test] + public void TestCtorPtr() + { + const string expected = "foo"; + + var t = new PyString(expected); + var actual = new PyString(t.Handle); + + Assert.AreEqual(expected, actual.ToString()); + } + + [Test] + [Ignore("Ambiguous behavior between PY2/PY3. Needs remapping")] + public void IsStringTrue() + { + var t = new PyString("foo"); + + Assert.True(PyString.IsStringType(t)); + } + + [Test] + public void IsStringFalse() + { + var t = new PyInt(5); + + Assert.False(PyString.IsStringType(t)); + } + + [Test] + public void TestUnicode() + { + const string expected = "foo\u00e9"; + PyObject actual = new PyString(expected); + Assert.AreEqual(expected, actual.ToString()); + } + } +} diff --git a/src/embed_tests/TestPyTuple.cs b/src/embed_tests/TestPyTuple.cs new file mode 100644 index 000000000..362251049 --- /dev/null +++ b/src/embed_tests/TestPyTuple.cs @@ -0,0 +1,171 @@ +using System; +using NUnit.Framework; +using Python.Runtime; + +namespace Python.EmbeddingTest +{ + public class TestPyTuple + { + [OneTimeSetUp] + public void SetUp() + { + PythonEngine.Initialize(); + } + + [OneTimeTearDown] + public void Dispose() + { + PythonEngine.Shutdown(); + } + + /// + /// Test IsTupleType without having to Initialize a tuple. + /// PyTuple constructor use IsTupleType. This decouples the tests. + /// + [Test] + public void TestStringIsTupleType() + { + var s = new PyString("foo"); + Assert.False(PyTuple.IsTupleType(s)); + } + + /// + /// Test IsTupleType with Tuple. + /// + [Test] + public void TestPyTupleIsTupleType() + { + var t = new PyTuple(); + Assert.True(PyTuple.IsTupleType(t)); + } + + [Test] + public void TestPyTupleEmpty() + { + var t = new PyTuple(); + Assert.AreEqual(0, t.Length()); + } + + [Test] + public void TestPyTupleBadCtor() + { + var i = new PyInt(5); + PyTuple t = null; + + var ex = Assert.Throws(() => t = new PyTuple(i)); + + Assert.AreEqual("object is not a tuple", ex.Message); + Assert.IsNull(t); + } + + [Test] + public void TestPyTupleCtorEmptyArray() + { + var a = new PyObject[] { }; + var t = new PyTuple(a); + + Assert.AreEqual(0, t.Length()); + } + + [Test] + public void TestPyTupleCtorArrayPyIntEmpty() + { + var a = new PyInt[] { }; + var t = new PyTuple(a); + + Assert.AreEqual(0, t.Length()); + } + + [Test] + public void TestPyTupleCtorArray() + { + var a = new PyObject[] { new PyInt(1), new PyString("Foo") }; + var t = new PyTuple(a); + + Assert.AreEqual(2, t.Length()); + } + + /// + /// Test PyTuple.Concat(...) doesn't let invalid appends happen + /// and throws and exception. + /// + /// + /// Test has second purpose. Currently it generated an Exception + /// that the GC failed to remove often and caused AppDomain unload + /// errors at the end of tests. See GH#397 for more info. + /// + /// Curious, on PY27 it gets a Unicode on the ex.Message. On PY3+ its string. + /// + [Test] + public void TestPyTupleInvalidAppend() + { + PyObject s = new PyString("foo"); + var t = new PyTuple(); + + var ex = Assert.Throws(() => t.Concat(s)); + + StringAssert.StartsWith("TypeError : can only concatenate tuple", ex.Message); + Assert.AreEqual(0, t.Length()); + Assert.IsEmpty(t); + } + + [Test] + public void TestPyTupleValidAppend() + { + var t0 = new PyTuple(); + var t = new PyTuple(); + t.Concat(t0); + + Assert.IsNotNull(t); + Assert.IsInstanceOf(typeof(PyTuple), t); + } + + [Test] + public void TestPyTupleStringConvert() + { + PyObject s = new PyString("foo"); + PyTuple t = PyTuple.AsTuple(s); + + Assert.IsNotNull(t); + Assert.IsInstanceOf(typeof(PyTuple), t); + Assert.AreEqual("f", t[0].ToString()); + Assert.AreEqual("o", t[1].ToString()); + Assert.AreEqual("o", t[2].ToString()); + } + + [Test] + public void TestPyTupleValidConvert() + { + var l = new PyList(); + PyTuple t = PyTuple.AsTuple(l); + + Assert.IsNotNull(t); + Assert.IsInstanceOf(typeof(PyTuple), t); + } + + [Test] + public void TestNewPyTupleFromPyTuple() + { + var t0 = new PyTuple(); + var t = new PyTuple(t0); + + Assert.IsNotNull(t); + Assert.IsInstanceOf(typeof(PyTuple), t); + } + + /// + /// TODO: Should this throw ArgumentError instead? + /// + [Test] + public void TestInvalidAsTuple() + { + var i = new PyInt(5); + PyTuple t = null; + + var ex = Assert.Throws(() => t = PyTuple.AsTuple(i)); + + Assert.AreEqual("TypeError : 'int' object is not iterable", ex.Message); + Assert.IsNull(t); + } + } +} diff --git a/src/embed_tests/TestPythonEngineProperties.cs b/src/embed_tests/TestPythonEngineProperties.cs new file mode 100644 index 000000000..01c6ae7e3 --- /dev/null +++ b/src/embed_tests/TestPythonEngineProperties.cs @@ -0,0 +1,187 @@ +using System; +using NUnit.Framework; +using Python.Runtime; + +namespace Python.EmbeddingTest +{ + public class TestPythonEngineProperties + { + [Test] + public static void GetBuildinfoDoesntCrash() + { + using (Py.GIL()) + { + string s = PythonEngine.BuildInfo; + + Assert.True(s.Length > 5); + Assert.True(s.Contains(",")); + } + } + + [Test] + public static void GetCompilerDoesntCrash() + { + using (Py.GIL()) + { + string s = PythonEngine.Compiler; + + Assert.True(s.Length > 0); + Assert.True(s.Contains("[")); + Assert.True(s.Contains("]")); + } + } + + [Test] + public static void GetCopyrightDoesntCrash() + { + using (Py.GIL()) + { + string s = PythonEngine.Copyright; + + Assert.True(s.Length > 0); + Assert.True(s.Contains("Python Software Foundation")); + } + } + + [Test] + public static void GetPlatformDoesntCrash() + { + using (Py.GIL()) + { + string s = PythonEngine.Platform; + + Assert.True(s.Length > 0); + Assert.True(s.Contains("x") || s.Contains("win")); + } + } + + [Test] + public static void GetVersionDoesntCrash() + { + using (Py.GIL()) + { + string s = PythonEngine.Version; + + Assert.True(s.Length > 0); + Assert.True(s.Contains(",")); + } + } + + [Test] + public static void GetPythonPathDefault() + { + PythonEngine.Initialize(); + string s = PythonEngine.PythonPath; + + StringAssert.Contains("python", s.ToLower()); + PythonEngine.Shutdown(); + } + + [Test] + public static void GetProgramNameDefault() + { + PythonEngine.Initialize(); + string s = PythonEngine.PythonHome; + + Assert.NotNull(s); + PythonEngine.Shutdown(); + } + + /// + /// Test default behavior of PYTHONHOME. If ENVVAR is set it will + /// return the same value. If not, returns EmptyString. + /// + /// + /// AppVeyor.yml has been update to tests with ENVVAR set. + /// + [Test] + public static void GetPythonHomeDefault() + { + string envPythonHome = Environment.GetEnvironmentVariable("PYTHONHOME") ?? ""; + + PythonEngine.Initialize(); + string enginePythonHome = PythonEngine.PythonHome; + + Assert.AreEqual(envPythonHome, enginePythonHome); + PythonEngine.Shutdown(); + } + + [Test] + public void SetPythonHome() + { + var pythonHome = "/dummypath/"; + + PythonEngine.PythonHome = pythonHome; + PythonEngine.Initialize(); + + Assert.AreEqual(pythonHome, PythonEngine.PythonHome); + PythonEngine.Shutdown(); + } + + [Test] + public void SetPythonHomeTwice() + { + var pythonHome = "/dummypath/"; + + PythonEngine.PythonHome = "/dummypath2/"; + PythonEngine.PythonHome = pythonHome; + PythonEngine.Initialize(); + + Assert.AreEqual(pythonHome, PythonEngine.PythonHome); + PythonEngine.Shutdown(); + } + + [Test] + public void SetProgramName() + { + var programName = "FooBar"; + + PythonEngine.ProgramName = programName; + PythonEngine.Initialize(); + + Assert.AreEqual(programName, PythonEngine.ProgramName); + PythonEngine.Shutdown(); + } + + [Test] + public void SetPythonPath() + { + if (Runtime.Runtime.pyversion == "2.7") + { + // Assert.Skip outputs as a warning (ie. pending to fix) + Assert.Pass(); + } + + PythonEngine.Initialize(); + string path = PythonEngine.PythonPath; + PythonEngine.Shutdown(); + + PythonEngine.ProgramName = path; + PythonEngine.Initialize(); + + Assert.AreEqual(path, PythonEngine.PythonPath); + PythonEngine.Shutdown(); + } + + [Test] + public void SetPythonPathExceptionOn27() + { + if (Runtime.Runtime.pyversion != "2.7") + { + Assert.Pass(); + } + + // Get previous path to avoid crashing Python + PythonEngine.Initialize(); + string path = PythonEngine.PythonPath; + PythonEngine.Shutdown(); + + var ex = Assert.Throws(() => PythonEngine.PythonPath = "foo"); + Assert.AreEqual("Set PythonPath not supported on Python 2", ex.Message); + + PythonEngine.Initialize(); + Assert.AreEqual(path, PythonEngine.PythonPath); + PythonEngine.Shutdown(); + } + } +} diff --git a/src/embed_tests/TestPythonException.cs b/src/embed_tests/TestPythonException.cs new file mode 100644 index 000000000..5470b246f --- /dev/null +++ b/src/embed_tests/TestPythonException.cs @@ -0,0 +1,44 @@ +using System; +using NUnit.Framework; +using Python.Runtime; + +namespace Python.EmbeddingTest +{ + public class TestPythonException + { + private IntPtr _gs; + + [SetUp] + public void SetUp() + { + PythonEngine.Initialize(); + _gs = PythonEngine.AcquireLock(); + } + + [TearDown] + public void Dispose() + { + PythonEngine.ReleaseLock(_gs); + PythonEngine.Shutdown(); + } + + [Test] + public void TestMessage() + { + var list = new PyList(); + PyObject foo = null; + + var ex = Assert.Throws(() => foo = list[0]); + + Assert.AreEqual("IndexError : list index out of range", ex.Message); + Assert.IsNull(foo); + } + + [Test] + public void TestNoError() + { + var e = new PythonException(); // There is no PyErr to fetch + Assert.AreEqual("", e.Message); + } + } +} diff --git a/src/embed_tests/TestRuntime.cs b/src/embed_tests/TestRuntime.cs new file mode 100644 index 000000000..22e6db0a9 --- /dev/null +++ b/src/embed_tests/TestRuntime.cs @@ -0,0 +1,51 @@ +using System; +using NUnit.Framework; +using Python.Runtime; + +namespace Python.EmbeddingTest +{ + public class TestRuntime + { + [Test] + public static void Py_IsInitializedValue() + { + Runtime.Runtime.Py_Finalize(); // In case another test left it on. + Assert.AreEqual(0, Runtime.Runtime.Py_IsInitialized()); + Runtime.Runtime.Py_Initialize(); + Assert.AreEqual(1, Runtime.Runtime.Py_IsInitialized()); + Runtime.Runtime.Py_Finalize(); + Assert.AreEqual(0, Runtime.Runtime.Py_IsInitialized()); + } + + [Test] + public static void RefCountTest() + { + Runtime.Runtime.Py_Initialize(); + IntPtr op = Runtime.Runtime.PyUnicode_FromString("FooBar"); + + // New object RefCount should be one + Assert.AreEqual(1, Runtime.Runtime.Refcount(op)); + + // Checking refcount didn't change refcount + Assert.AreEqual(1, Runtime.Runtime.Refcount(op)); + + // New reference doesn't increase refcount + IntPtr p = op; + Assert.AreEqual(1, Runtime.Runtime.Refcount(p)); + + // Py_IncRef/Py_DecRef increase and decrease RefCount + Runtime.Runtime.Py_IncRef(op); + Assert.AreEqual(2, Runtime.Runtime.Refcount(op)); + Runtime.Runtime.Py_DecRef(op); + Assert.AreEqual(1, Runtime.Runtime.Refcount(op)); + + // XIncref/XDecref increase and decrease RefCount + Runtime.Runtime.XIncref(op); + Assert.AreEqual(2, Runtime.Runtime.Refcount(op)); + Runtime.Runtime.XDecref(op); + Assert.AreEqual(1, Runtime.Runtime.Refcount(op)); + + Runtime.Runtime.Py_Finalize(); + } + } +} diff --git a/src/embed_tests/dynamic.cs b/src/embed_tests/dynamic.cs new file mode 100644 index 000000000..94397072a --- /dev/null +++ b/src/embed_tests/dynamic.cs @@ -0,0 +1,131 @@ +using System; +using System.Text; +using NUnit.Framework; +using Python.Runtime; + +namespace Python.EmbeddingTest +{ + public class DynamicTest + { + private Py.GILState _gs; + + [SetUp] + public void SetUp() + { + _gs = Py.GIL(); + } + + [TearDown] + public void Dispose() + { + _gs.Dispose(); + } + + /// + /// Set the attribute of a PyObject with a .NET object. + /// + [Test] + public void AssignObject() + { + var stream = new StringBuilder(); + dynamic sys = Py.Import("sys"); + sys.testattr = stream; + // Check whether there are the same object. + dynamic _stream = sys.testattr.AsManagedObject(typeof(StringBuilder)); + Assert.AreEqual(_stream, stream); + + PythonEngine.RunSimpleString( + "import sys\n" + + "sys.testattr.Append('Hello!')\n"); + Assert.AreEqual(stream.ToString(), "Hello!"); + } + + /// + /// Set the attribute of a PyObject to null. + /// + [Test] + public void AssignNone() + { + dynamic sys = Py.Import("sys"); + sys.testattr = new StringBuilder(); + Assert.IsNotNull(sys.testattr); + + sys.testattr = null; + Assert.IsNull(sys.testattr); + } + + /// + /// Check whether we can get the attr of a python object when the + /// value of attr is a PyObject. + /// + /// + /// FIXME: Issue on Travis PY27: Error : Python.EmbeddingTest.dynamicTest.AssignPyObject + /// Python.Runtime.PythonException : ImportError : /home/travis/virtualenv/python2.7.9/lib/python2.7/lib-dynload/_io.so: undefined symbol: _PyLong_AsInt + /// + [Test] + public void AssignPyObject() + { + if (Environment.GetEnvironmentVariable("TRAVIS") == "true" && + Environment.GetEnvironmentVariable("TRAVIS_PYTHON_VERSION") == "2.7") + { + Assert.Ignore("Fails on Travis/PY27: ImportError: ... undefined symbol: _PyLong_AsInt"); + } + + dynamic sys = Py.Import("sys"); + dynamic io = Py.Import("io"); + sys.testattr = io.StringIO(); + dynamic bb = sys.testattr; // Get the PyObject + bb.write("Hello!"); + Assert.AreEqual(bb.getvalue().ToString(), "Hello!"); + } + + /// + /// Pass the .NET object in Python side. + /// + [Test] + public void PassObjectInPython() + { + var stream = new StringBuilder(); + dynamic sys = Py.Import("sys"); + sys.testattr1 = stream; + + // Pass the .NET object in Python side + PythonEngine.RunSimpleString( + "import sys\n" + + "sys.testattr2 = sys.testattr1\n" + ); + + // Compare in Python + PythonEngine.RunSimpleString( + "import sys\n" + + "sys.testattr3 = sys.testattr1 is sys.testattr2\n" + ); + Assert.AreEqual(sys.testattr3.ToString(), "True"); + + // Compare in .NET + Assert.AreEqual(sys.testattr1, sys.testattr2); + } + + /// + /// Pass the PyObject in .NET side + /// + [Test] + public void PassPyObjectInNet() + { + var stream = new StringBuilder(); + dynamic sys = Py.Import("sys"); + sys.testattr1 = stream; + sys.testattr2 = sys.testattr1; + + // Compare in Python + PyObject res = PythonEngine.RunString( + "import sys\n" + + "sys.testattr3 = sys.testattr1 is sys.testattr2\n" + ); + Assert.AreEqual(sys.testattr3.ToString(), "True"); + + // Compare in .NET + Assert.AreEqual(sys.testattr1, sys.testattr2); + } + } +} diff --git a/src/tests/PyImportTest/__init__.py b/src/embed_tests/fixtures/PyImportTest/__init__.py similarity index 100% rename from src/tests/PyImportTest/__init__.py rename to src/embed_tests/fixtures/PyImportTest/__init__.py diff --git a/src/embed_tests/fixtures/PyImportTest/cast_global_var.py b/src/embed_tests/fixtures/PyImportTest/cast_global_var.py new file mode 100644 index 000000000..f9499539e --- /dev/null +++ b/src/embed_tests/fixtures/PyImportTest/cast_global_var.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- + +FOO = 1 + + +def test_foo(): + return FOO diff --git a/src/tests/PyImportTest/sysargv.py b/src/embed_tests/fixtures/PyImportTest/sysargv.py similarity index 100% rename from src/tests/PyImportTest/sysargv.py rename to src/embed_tests/fixtures/PyImportTest/sysargv.py diff --git a/src/tests/PyImportTest/test/__init__.py b/src/embed_tests/fixtures/PyImportTest/test/__init__.py similarity index 100% rename from src/tests/PyImportTest/test/__init__.py rename to src/embed_tests/fixtures/PyImportTest/test/__init__.py diff --git a/src/tests/PyImportTest/test/one.py b/src/embed_tests/fixtures/PyImportTest/test/one.py similarity index 100% rename from src/tests/PyImportTest/test/one.py rename to src/embed_tests/fixtures/PyImportTest/test/one.py diff --git a/src/embed_tests/packages.config b/src/embed_tests/packages.config index 33152fe85..4cb01d3be 100644 --- a/src/embed_tests/packages.config +++ b/src/embed_tests/packages.config @@ -1,5 +1,5 @@ - - + + diff --git a/src/embed_tests/pyimport.cs b/src/embed_tests/pyimport.cs index ebdc5b125..3bb9a34d6 100644 --- a/src/embed_tests/pyimport.cs +++ b/src/embed_tests/pyimport.cs @@ -10,28 +10,27 @@ namespace Python.EmbeddingTest /// /// /// Keeping in old-style SetUp/TearDown due to required SetUp. - /// The required directory structure was added to .\pythonnet\src\tests\ directory: + /// The required directory structure was added to .\pythonnet\src\embed_tests\fixtures\ directory: /// + PyImportTest/ /// | - __init__.py /// | + test/ /// | | - __init__.py /// | | - one.py /// - [TestFixture] public class PyImportTest { - private IntPtr gs; + private IntPtr _gs; [SetUp] public void SetUp() { PythonEngine.Initialize(); - gs = PythonEngine.AcquireLock(); + _gs = PythonEngine.AcquireLock(); /* Append the tests directory to sys.path * using reflection to circumvent the private * modifiers placed on most Runtime methods. */ - const string s = "../../tests"; + const string s = "../fixtures"; string testPath = Path.Combine(TestContext.CurrentContext.TestDirectory, s); IntPtr str = Runtime.Runtime.PyString_FromString(testPath); @@ -40,9 +39,9 @@ public void SetUp() } [TearDown] - public void TearDown() + public void Dispose() { - PythonEngine.ReleaseLock(gs); + PythonEngine.ReleaseLock(_gs); PythonEngine.Shutdown(); } @@ -65,5 +64,20 @@ public void TestSysArgsImportException() PyObject module = PythonEngine.ImportModule("PyImportTest.sysargv"); Assert.IsNotNull(module); } + + /// + /// Test Global Variable casting. GH#420 + /// + [Test] + public void TestCastGlobalVar() + { + dynamic foo = Py.Import("PyImportTest.cast_global_var"); + Assert.AreEqual("1", foo.FOO.ToString()); + Assert.AreEqual("1", foo.test_foo().ToString()); + + foo.FOO = 2; + Assert.AreEqual("2", foo.FOO.ToString()); + Assert.AreEqual("2", foo.test_foo().ToString()); + } } } diff --git a/src/embed_tests/pyinitialize.cs b/src/embed_tests/pyinitialize.cs index bfd95aaab..2f9aae2c7 100644 --- a/src/embed_tests/pyinitialize.cs +++ b/src/embed_tests/pyinitialize.cs @@ -1,3 +1,4 @@ +using System; using NUnit.Framework; using Python.Runtime; @@ -5,16 +6,18 @@ namespace Python.EmbeddingTest { public class PyInitializeTest { + /// + /// Tests issue with multiple simple Initialize/Shutdowns. + /// Fixed by #343 + /// [Test] - public static void LoadSpecificArgs() + public static void StartAndStopTwice() { - var args = new[] { "test1", "test2" }; - using (new PythonEngine(args)) - using (var argv = new PyList(Runtime.Runtime.PySys_GetObject("argv"))) - { - Assert.AreEqual(args[0], argv[0].ToString()); - Assert.AreEqual(args[1], argv[1].ToString()); - } + PythonEngine.Initialize(); + PythonEngine.Shutdown(); + + PythonEngine.Initialize(); + PythonEngine.Shutdown(); } [Test] @@ -28,12 +31,47 @@ public static void LoadDefaultArgs() } [Test] - public static void StartAndStopTwice() + public static void LoadSpecificArgs() { + var args = new[] { "test1", "test2" }; + using (new PythonEngine(args)) + using (var argv = new PyList(Runtime.Runtime.PySys_GetObject("argv"))) + { + Assert.AreEqual(args[0], argv[0].ToString()); + Assert.AreEqual(args[1], argv[1].ToString()); + } + } + + /// + /// Failing test demonstrating current issue with OverflowException (#376) + /// and ArgumentException issue after that one is fixed. + /// More complex version of StartAndStopTwice test + /// + [Test] + [Ignore("GH#376: System.OverflowException : Arithmetic operation resulted in an overflow")] + //[Ignore("System.ArgumentException : Cannot pass a GCHandle across AppDomains")] + public void ReInitialize() + { + var code = "from System import Int32\n"; PythonEngine.Initialize(); + using (Py.GIL()) + { + // Import any class or struct from .NET + PythonEngine.RunSimpleString(code); + } PythonEngine.Shutdown(); PythonEngine.Initialize(); + using (Py.GIL()) + { + // Import a class/struct from .NET + // This class/struct must be imported during the first initialization. + PythonEngine.RunSimpleString(code); + // Create an instance of the class/struct + // System.OverflowException Exception will be raised here. + // If replacing int with Int64, OverflowException will be replaced with AppDomain exception. + PythonEngine.RunSimpleString("Int32(1)"); + } PythonEngine.Shutdown(); } } diff --git a/src/embed_tests/pyiter.cs b/src/embed_tests/pyiter.cs deleted file mode 100644 index b110903f6..000000000 --- a/src/embed_tests/pyiter.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Collections.Generic; -using NUnit.Framework; -using Python.Runtime; - -namespace Python.EmbeddingTest -{ - public class PyIterTest - { - [Test] - public void TestOnPyList() - { - using (Py.GIL()) - { - var list = new PyList(); - list.Append(new PyString("foo")); - list.Append(new PyString("bar")); - list.Append(new PyString("baz")); - var result = new List(); - foreach (PyObject item in list) - { - result.Add(item.ToString()); - } - Assert.AreEqual(3, result.Count); - Assert.AreEqual("foo", result[0]); - Assert.AreEqual("bar", result[1]); - Assert.AreEqual("baz", result[2]); - } - } - } -} diff --git a/src/embed_tests/pylong.cs b/src/embed_tests/pylong.cs deleted file mode 100644 index 37cf1042d..000000000 --- a/src/embed_tests/pylong.cs +++ /dev/null @@ -1,19 +0,0 @@ -using NUnit.Framework; -using Python.Runtime; - -namespace Python.EmbeddingTest -{ - public class PyLongTest - { - [Test] - public void TestToInt64() - { - using (Py.GIL()) - { - long largeNumber = 8L * 1024L * 1024L * 1024L; // 8 GB - var pyLargeNumber = new PyLong(largeNumber); - Assert.AreEqual(largeNumber, pyLargeNumber.ToInt64()); - } - } - } -} diff --git a/src/embed_tests/pyobject.cs b/src/embed_tests/pyobject.cs deleted file mode 100644 index f114d3d9e..000000000 --- a/src/embed_tests/pyobject.cs +++ /dev/null @@ -1,18 +0,0 @@ -using NUnit.Framework; -using Python.Runtime; - -namespace Python.EmbeddingTest -{ - public class PyObjectTest - { - [Test] - public void TestUnicode() - { - using (Py.GIL()) - { - PyObject s = new PyString("foo\u00e9"); - Assert.AreEqual("foo\u00e9", s.ToString()); - } - } - } -} diff --git a/src/embed_tests/pyrunstring.cs b/src/embed_tests/pyrunstring.cs new file mode 100644 index 000000000..81a1b07ca --- /dev/null +++ b/src/embed_tests/pyrunstring.cs @@ -0,0 +1,61 @@ +using System; +using NUnit.Framework; +using Python.Runtime; + +namespace Python.EmbeddingTest +{ + public class RunStringTest + { + private Py.GILState _gs; + + [SetUp] + public void SetUp() + { + _gs = Py.GIL(); + } + + [TearDown] + public void Dispose() + { + _gs.Dispose(); + } + + [Test] + public void TestRunSimpleString() + { + int aa = PythonEngine.RunSimpleString("import sys"); + Assert.AreEqual(0, aa); + + int bb = PythonEngine.RunSimpleString("import 1234"); + Assert.AreEqual(-1, bb); + } + + [Test] + public void TestEval() + { + dynamic sys = Py.Import("sys"); + sys.attr1 = 100; + var locals = new PyDict(); + locals.SetItem("sys", sys); + locals.SetItem("a", new PyInt(10)); + + object b = PythonEngine.Eval("sys.attr1 + a + 1", null, locals.Handle) + .AsManagedObject(typeof(int)); + Assert.AreEqual(111, b); + } + + [Test] + public void TestExec() + { + dynamic sys = Py.Import("sys"); + sys.attr1 = 100; + var locals = new PyDict(); + locals.SetItem("sys", sys); + locals.SetItem("a", new PyInt(10)); + + PythonEngine.Exec("c = sys.attr1 + a + 1", null, locals.Handle); + object c = locals.GetItem("c").AsManagedObject(typeof(int)); + Assert.AreEqual(111, c); + } + } +} diff --git a/src/embed_tests/pythonexception.cs b/src/embed_tests/pythonexception.cs deleted file mode 100644 index 7811bd37b..000000000 --- a/src/embed_tests/pythonexception.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; -using NUnit.Framework; -using Python.Runtime; - -namespace Python.EmbeddingTest -{ - /// - /// Test Python Exceptions - /// - /// - /// Keeping this in the old-style SetUp/TearDown - /// to ensure that setup still works. - /// - [TestFixture] - public class PythonExceptionTest - { - private IntPtr gs; - - [SetUp] - public void SetUp() - { - PythonEngine.Initialize(); - gs = PythonEngine.AcquireLock(); - } - - [TearDown] - public void TearDown() - { - PythonEngine.ReleaseLock(gs); - PythonEngine.Shutdown(); - } - - [Test] - public void TestMessage() - { - var list = new PyList(); - try - { - PyObject junk = list[0]; - } - catch (PythonException e) - { - Assert.AreEqual("IndexError : list index out of range", e.Message); - } - } - - [Test] - public void TestNoError() - { - var e = new PythonException(); // There is no PyErr to fetch - Assert.AreEqual("", e.Message); - } - } -} diff --git a/src/embed_tests/pytuple.cs b/src/embed_tests/pytuple.cs deleted file mode 100644 index 18a6ea344..000000000 --- a/src/embed_tests/pytuple.cs +++ /dev/null @@ -1,93 +0,0 @@ -using NUnit.Framework; -using Python.Runtime; - -namespace Python.EmbeddingTest -{ - public class PyTupleTest - { - [Test] - public void TestPyTupleEmpty() - { - using (Py.GIL()) - { - var t = new PyTuple(); - Assert.AreEqual(0, t.Length()); - } - } - - [Test] - public void TestPyTupleInvalidAppend() - { - using (Py.GIL()) - { - PyObject s = new PyString("foo"); - var t = new PyTuple(); - Assert.Throws(() => t.Concat(s)); - } - } - - [Test] - public void TestPyTupleValidAppend() - { - using (Py.GIL()) - { - var t0 = new PyTuple(); - var t = new PyTuple(); - t.Concat(t0); - Assert.IsNotNull(t); - Assert.IsInstanceOf(typeof(PyTuple), t); - } - } - - [Test] - public void TestPyTupleIsTupleType() - { - using (Py.GIL()) - { - var s = new PyString("foo"); - var t = new PyTuple(); - Assert.IsTrue(PyTuple.IsTupleType(t)); - Assert.IsFalse(PyTuple.IsTupleType(s)); - } - } - - [Test] - public void TestPyTupleStringConvert() - { - using (Py.GIL()) - { - PyObject s = new PyString("foo"); - PyTuple t = PyTuple.AsTuple(s); - Assert.IsNotNull(t); - Assert.IsInstanceOf(typeof(PyTuple), t); - Assert.AreEqual("f", t[0].ToString()); - Assert.AreEqual("o", t[1].ToString()); - Assert.AreEqual("o", t[2].ToString()); - } - } - - [Test] - public void TestPyTupleValidConvert() - { - using (Py.GIL()) - { - var l = new PyList(); - PyTuple t = PyTuple.AsTuple(l); - Assert.IsNotNull(t); - Assert.IsInstanceOf(typeof(PyTuple), t); - } - } - - [Test] - public void TestNewPyTupleFromPyTuple() - { - using (Py.GIL()) - { - var t0 = new PyTuple(); - var t = new PyTuple(t0); - Assert.IsNotNull(t); - Assert.IsInstanceOf(typeof(PyTuple), t); - } - } - } -} diff --git a/src/runtime/AssemblyInfo.cs b/src/runtime/AssemblyInfo.cs deleted file mode 100644 index a357b81d9..000000000 --- a/src/runtime/AssemblyInfo.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System; -using System.Reflection; -using System.Resources; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -[assembly: AssemblyProduct("Python for .NET")] -[assembly: AssemblyVersion("4.0.0.1")] -[assembly: AssemblyDefaultAlias("Python.Runtime.dll")] -[assembly: CLSCompliant(true)] -[assembly: ComVisible(false)] -[assembly: AssemblyCopyright("MIT License")] -[assembly: AssemblyFileVersion("2.0.0.2")] -[assembly: NeutralResourcesLanguage("en")] -[assembly: InternalsVisibleTo("Python.EmbeddingTest")] diff --git a/src/runtime/CustomMarshaler.cs b/src/runtime/CustomMarshaler.cs new file mode 100644 index 000000000..90bb77a71 --- /dev/null +++ b/src/runtime/CustomMarshaler.cs @@ -0,0 +1,240 @@ +using System; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; + +namespace Python.Runtime +{ + /// + /// Abstract class defining boiler plate methods that + /// Custom Marshalers will use. + /// + internal abstract class MarshalerBase : ICustomMarshaler + { + public object MarshalNativeToManaged(IntPtr pNativeData) + { + throw new NotImplementedException(); + } + + public abstract IntPtr MarshalManagedToNative(object managedObj); + + public void CleanUpNativeData(IntPtr pNativeData) + { + Marshal.FreeHGlobal(pNativeData); + } + + public void CleanUpManagedData(object managedObj) + { + // Let GC deal with it + } + + public int GetNativeDataSize() + { + return IntPtr.Size; + } + } + + + /// + /// Custom Marshaler to deal with Managed String to Native + /// conversion differences on UCS2/UCS4. + /// + internal class UcsMarshaler : MarshalerBase + { + private static readonly MarshalerBase Instance = new UcsMarshaler(); + private static readonly Encoding PyEncoding = Runtime.PyEncoding; + + public override IntPtr MarshalManagedToNative(object managedObj) + { + var s = managedObj as string; + + if (s == null) + { + return IntPtr.Zero; + } + + byte[] bStr = PyEncoding.GetBytes(s + "\0"); + IntPtr mem = Marshal.AllocHGlobal(bStr.Length); + try + { + Marshal.Copy(bStr, 0, mem, bStr.Length); + } + catch (Exception) + { + Marshal.FreeHGlobal(mem); + throw; + } + + return mem; + } + + public static ICustomMarshaler GetInstance(string cookie) + { + return Instance; + } + + public static string PtrToStringUni(IntPtr p) + { + if (p == IntPtr.Zero) + { + return null; + } + + int size = GetUnicodeByteLength(p); + var buffer = new byte[size]; + Marshal.Copy(p, buffer, 0, size); + return PyEncoding.GetString(buffer, 0, size); + } + + public static int GetUnicodeByteLength(IntPtr p) + { + var len = 0; + while (true) + { + int c = Runtime.UCS == 2 + ? Marshal.ReadInt16(p, len * 2) + : Marshal.ReadInt32(p, len * 4); + + if (c == 0) + { + return len * Runtime.UCS; + } + checked + { + ++len; + } + } + } + + /// + /// Utility function for Marshaling Unicode on PY3 and AnsiStr on PY2. + /// Use on functions whose Input signatures changed between PY2/PY3. + /// Ex. Py_SetPythonHome + /// + /// Managed String + /// + /// Ptr to Native String ANSI(PY2)/Unicode(PY3/UCS2)/UTF32(PY3/UCS4. + /// + /// + /// You MUST deallocate the IntPtr of the Return when done with it. + /// + public static IntPtr Py3UnicodePy2StringtoPtr(string s) + { + return Runtime.IsPython3 + ? Instance.MarshalManagedToNative(s) + : Marshal.StringToHGlobalAnsi(s); + } + + /// + /// Utility function for Marshaling Unicode IntPtr on PY3 and + /// AnsiStr IntPtr on PY2 to Managed Strings. Use on Python functions + /// whose return type changed between PY2/PY3. + /// Ex. Py_GetPythonHome + /// + /// Native Ansi/Unicode/UTF32 String + /// + /// Managed String + /// + public static string PtrToPy3UnicodePy2String(IntPtr p) + { + return Runtime.IsPython3 + ? PtrToStringUni(p) + : Marshal.PtrToStringAnsi(p); + } + } + + + /// + /// Custom Marshaler to deal with Managed String Arrays to Native + /// conversion differences on UCS2/UCS4. + /// + internal class StrArrayMarshaler : MarshalerBase + { + private static readonly MarshalerBase Instance = new StrArrayMarshaler(); + private static readonly Encoding PyEncoding = Runtime.PyEncoding; + + public override IntPtr MarshalManagedToNative(object managedObj) + { + var argv = managedObj as string[]; + + if (argv == null) + { + return IntPtr.Zero; + } + + int totalStrLength = argv.Sum(arg => arg.Length + 1); + int memSize = argv.Length * IntPtr.Size + totalStrLength * Runtime.UCS; + + IntPtr mem = Marshal.AllocHGlobal(memSize); + try + { + // Preparing array of pointers to strings + IntPtr curStrPtr = mem + argv.Length * IntPtr.Size; + for (var i = 0; i < argv.Length; i++) + { + byte[] bStr = PyEncoding.GetBytes(argv[i] + "\0"); + Marshal.Copy(bStr, 0, curStrPtr, bStr.Length); + Marshal.WriteIntPtr(mem + i * IntPtr.Size, curStrPtr); + curStrPtr += bStr.Length; + } + } + catch (Exception) + { + Marshal.FreeHGlobal(mem); + throw; + } + + return mem; + } + + public static ICustomMarshaler GetInstance(string cookie) + { + return Instance; + } + } + + + /// + /// Custom Marshaler to deal with Managed String to Native + /// conversion on UTF-8. Use on functions that expect UTF-8 encoded + /// strings like `PyUnicode_FromStringAndSize` + /// + /// + /// If instead we used `MarshalAs(UnmanagedType.LPWStr)` the output to + /// `foo` would be `f\x00o\x00o\x00`. + /// + internal class Utf8Marshaler : MarshalerBase + { + private static readonly MarshalerBase Instance = new Utf8Marshaler(); + private static readonly Encoding PyEncoding = Encoding.UTF8; + + public override IntPtr MarshalManagedToNative(object managedObj) + { + var s = managedObj as string; + + if (s == null) + { + return IntPtr.Zero; + } + + byte[] bStr = PyEncoding.GetBytes(s + "\0"); + IntPtr mem = Marshal.AllocHGlobal(bStr.Length); + try + { + Marshal.Copy(bStr, 0, mem, bStr.Length); + } + catch (Exception) + { + Marshal.FreeHGlobal(mem); + throw; + } + + return mem; + } + + public static ICustomMarshaler GetInstance(string cookie) + { + return Instance; + } + } +} diff --git a/src/runtime/Properties/AssemblyInfo.cs b/src/runtime/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..a5d33c7ab --- /dev/null +++ b/src/runtime/Properties/AssemblyInfo.cs @@ -0,0 +1,11 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Python for .NET")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyDefaultAlias("Python.Runtime.dll")] + +[assembly: InternalsVisibleTo("Python.EmbeddingTest")] diff --git a/src/runtime/Python.Runtime.csproj b/src/runtime/Python.Runtime.csproj index f1616dcd6..8580b7f61 100644 --- a/src/runtime/Python.Runtime.csproj +++ b/src/runtime/Python.Runtime.csproj @@ -13,8 +13,9 @@ 1591 ..\..\ - $(SolutionDir) - + $(SolutionDir)\bin\ + Properties + 6 true false ..\pythonnet.snk @@ -73,7 +74,10 @@ - + + + Properties\SharedAssemblyInfo.cs + @@ -85,6 +89,7 @@ + diff --git a/src/runtime/assemblymanager.cs b/src/runtime/assemblymanager.cs index c86e7a473..06a4449a2 100644 --- a/src/runtime/assemblymanager.cs +++ b/src/runtime/assemblymanager.cs @@ -1,9 +1,9 @@ using System; using System.Collections; -using System.IO; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; +using System.IO; using System.Reflection; using System.Threading; @@ -323,9 +323,8 @@ public static bool LoadImplicit(string name, bool warn = true) if (warn && loaded) { string location = Path.GetFileNameWithoutExtension(lastAssembly.Location); - string deprWarning = $@" -The module was found, but not in a referenced namespace. -Implicit loading is deprecated. Please use clr.AddReference(""{location}"")."; + string deprWarning = "The module was found, but not in a referenced namespace.\n" + + $"Implicit loading is deprecated. Please use clr.AddReference('{location}')."; Exceptions.deprecation(deprWarning); } diff --git a/src/runtime/classbase.cs b/src/runtime/classbase.cs index e480b309a..4dd3b5364 100644 --- a/src/runtime/classbase.cs +++ b/src/runtime/classbase.cs @@ -199,8 +199,7 @@ public static IntPtr tp_iter(IntPtr ob) if (o == null) { - var message = "iteration over non-sequence"; - return Exceptions.RaiseTypeError(message); + return Exceptions.RaiseTypeError("iteration over non-sequence"); } } diff --git a/src/runtime/classderived.cs b/src/runtime/classderived.cs index 0f8f156e8..c180f9acc 100644 --- a/src/runtime/classderived.cs +++ b/src/runtime/classderived.cs @@ -737,7 +737,7 @@ public static void InvokeMethodVoid(IPythonDerivedType obj, string methodName, s if (origMethodName == null) { - throw new NotImplementedException("Python object does not have a '" + methodName + "' method"); + throw new NotImplementedException($"Python object does not have a '{methodName}' method"); } obj.GetType().InvokeMember(origMethodName, diff --git a/src/runtime/constructorbinding.cs b/src/runtime/constructorbinding.cs index d17d6ac96..4839f9913 100644 --- a/src/runtime/constructorbinding.cs +++ b/src/runtime/constructorbinding.cs @@ -82,14 +82,11 @@ public static IntPtr tp_descr_get(IntPtr op, IntPtr instance, IntPtr owner) /// /// Implement explicit overload selection using subscript syntax ([]). /// - /// + /// /// ConstructorBinding.GetItem(PyObject *o, PyObject *key) /// Return element of o corresponding to the object key or NULL on failure. /// This is the equivalent of the Python expression o[key]. - /// - /// - /// - /// + /// public static IntPtr mp_subscript(IntPtr op, IntPtr key) { var self = (ConstructorBinding)GetManagedObject(op); @@ -104,8 +101,7 @@ public static IntPtr mp_subscript(IntPtr op, IntPtr key) ConstructorInfo ci = self.type.GetConstructor(types); if (ci == null) { - var msg = "No match found for constructor signature"; - return Exceptions.RaiseTypeError(msg); + return Exceptions.RaiseTypeError("No match found for constructor signature"); } var boundCtor = new BoundContructor(self.type, self.pyTypeHndl, self.ctorBinder, ci); @@ -184,7 +180,7 @@ public BoundContructor(Type type, IntPtr pyTypeHndl, ConstructorBinder ctorBinde /// /// BoundContructor.__call__(PyObject *callable_object, PyObject *args, PyObject *kw) /// - /// PyObject *callable_object + /// PyObject *callable_object /// PyObject *args /// PyObject *kw /// A reference to a new instance of the class by invoking the selected ctor(). diff --git a/src/runtime/converter.cs b/src/runtime/converter.cs index fa5d73c86..e68767da9 100644 --- a/src/runtime/converter.cs +++ b/src/runtime/converter.cs @@ -1,9 +1,10 @@ using System; +using System.Collections; +using System.Collections.Generic; +using System.Globalization; using System.Reflection; using System.Runtime.InteropServices; -using System.Globalization; using System.Security; -using System.Collections; namespace Python.Runtime { @@ -52,62 +53,53 @@ static Converter() /// internal static Type GetTypeByAlias(IntPtr op) { - if (op == Runtime.PyStringType || - op == Runtime.PyUnicodeType) - { + if (op == Runtime.PyStringType) return stringType; - } - else if (op == Runtime.PyIntType) - { + + if (op == Runtime.PyUnicodeType) + return stringType; + + if (op == Runtime.PyIntType) return int32Type; - } - else if (op == Runtime.PyLongType) - { + + if (op == Runtime.PyLongType) return int64Type; - } - else if (op == Runtime.PyFloatType) - { + + if (op == Runtime.PyFloatType) return doubleType; - } - else if (op == Runtime.PyBoolType) - { + + if (op == Runtime.PyBoolType) return boolType; - } + return null; } internal static IntPtr GetPythonTypeByAlias(Type op) { if (op == stringType) - { return Runtime.PyUnicodeType; - } - else if (Runtime.IsPython3 && (op == int16Type || - op == int32Type || - op == int64Type)) - { + if (op == int16Type) return Runtime.PyIntType; - } - else if (op == int16Type || - op == int32Type) - { + if (op == int32Type) return Runtime.PyIntType; - } - else if (op == int64Type) - { + + if (op == int64Type && Runtime.IsPython2) return Runtime.PyLongType; - } - else if (op == doubleType || - op == singleType) - { + + if (op == int64Type) + return Runtime.PyIntType; + + if (op == doubleType) return Runtime.PyFloatType; - } - else if (op == boolType) - { + + if (op == singleType) + return Runtime.PyFloatType; + + if (op == boolType) return Runtime.PyBoolType; - } + return IntPtr.Zero; } @@ -142,6 +134,22 @@ internal static IntPtr ToPython(object value, Type type) return result; } + if (value is IList && value.GetType().IsGenericType) + { + using (var resultlist = new PyList()) + { + foreach (object o in (IEnumerable)value) + { + using (var p = new PyObject(ToPython(o, o?.GetType()))) + { + resultlist.Append(p); + } + } + Runtime.XIncref(resultlist.Handle); + return resultlist.Handle; + } + } + // it the type is a python subclass of a managed type then return the // underlying python object rather than construct a new wrapper object. var pyderived = value as IPythonDerivedType; @@ -292,9 +300,7 @@ internal static bool ToManagedValue(IntPtr value, Type obType, result = tmp; return true; } - var err = "value cannot be converted to {0}"; - err = string.Format(err, obType); - Exceptions.SetError(Exceptions.TypeError, err); + Exceptions.SetError(Exceptions.TypeError, $"value cannot be converted to {obType}"); return false; } if (mt is ClassBase) @@ -331,27 +337,27 @@ internal static bool ToManagedValue(IntPtr value, Type obType, return ToPrimitive(value, stringType, out result, setError); } - else if (Runtime.PyBool_Check(value)) + if (Runtime.PyBool_Check(value)) { return ToPrimitive(value, boolType, out result, setError); } - else if (Runtime.PyInt_Check(value)) + if (Runtime.PyInt_Check(value)) { return ToPrimitive(value, int32Type, out result, setError); } - else if (Runtime.PyLong_Check(value)) + if (Runtime.PyLong_Check(value)) { return ToPrimitive(value, int64Type, out result, setError); } - else if (Runtime.PyFloat_Check(value)) + if (Runtime.PyFloat_Check(value)) { return ToPrimitive(value, doubleType, out result, setError); } - else if (Runtime.PySequence_Check(value)) + if (Runtime.PySequence_Check(value)) { return ToArray(value, typeof(object[]), out result, setError); } @@ -373,31 +379,31 @@ internal static bool ToManagedValue(IntPtr value, Type obType, return true; } - else if (value == Runtime.PyBoolType) + if (value == Runtime.PyBoolType) { result = boolType; return true; } - else if (value == Runtime.PyIntType) + if (value == Runtime.PyIntType) { result = int32Type; return true; } - else if (value == Runtime.PyLongType) + if (value == Runtime.PyLongType) { result = int64Type; return true; } - else if (value == Runtime.PyFloatType) + if (value == Runtime.PyFloatType) { result = doubleType; return true; } - else if (value == Runtime.PyListType || value == Runtime.PyTupleType) + if (value == Runtime.PyListType || value == Runtime.PyTupleType) { result = typeof(object[]); return true; @@ -509,7 +515,7 @@ private static bool ToPrimitive(IntPtr value, Type obType, out object result, bo { if (Runtime.PyString_Size(value) == 1) { - op = Runtime.PyString_AS_STRING(value); + op = Runtime.PyString_AsString(value); result = (byte)Marshal.ReadByte(op); return true; } @@ -554,7 +560,7 @@ private static bool ToPrimitive(IntPtr value, Type obType, out object result, bo { if (Runtime.PyString_Size(value) == 1) { - op = Runtime.PyString_AS_STRING(value); + op = Runtime.PyString_AsString(value); result = (sbyte)Marshal.ReadByte(op); return true; } @@ -599,7 +605,7 @@ private static bool ToPrimitive(IntPtr value, Type obType, out object result, bo { if (Runtime.PyString_Size(value) == 1) { - op = Runtime.PyString_AS_STRING(value); + op = Runtime.PyString_AsString(value); result = (char)Marshal.ReadByte(op); return true; } @@ -610,21 +616,10 @@ private static bool ToPrimitive(IntPtr value, Type obType, out object result, bo { if (Runtime.PyUnicode_GetSize(value) == 1) { - op = Runtime.PyUnicode_AS_UNICODE(value); - if (Runtime.UCS == 2) // Don't trust linter, statement not always true. - { - // 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 - Char[] buff = new Char[1]; - Marshal.Copy(op, buff, 0, 1); - result = buff[0]; - } - else // UCS4 - { - // XXX this is probably NOT correct? - result = (char)Marshal.ReadInt32(op); - } + op = Runtime.PyUnicode_AsUnicode(value); + Char[] buff = new Char[1]; + Marshal.Copy(op, buff, 0, 1); + result = buff[0]; return true; } goto type_error; @@ -793,10 +788,8 @@ private static bool ToPrimitive(IntPtr value, Type obType, out object result, bo if (setError) { - var format = "'{0}' value cannot be converted to {1}"; string tpName = Runtime.PyObject_GetTypeName(value); - string error = string.Format(format, tpName, obType); - Exceptions.SetError(Exceptions.TypeError, error); + Exceptions.SetError(Exceptions.TypeError, $"'{tpName}' value cannot be converted to {obType}"); } return false; @@ -805,8 +798,7 @@ private static bool ToPrimitive(IntPtr value, Type obType, out object result, bo if (setError) { - var error = "value too large to convert"; - Exceptions.SetError(Exceptions.OverflowError, error); + Exceptions.SetError(Exceptions.OverflowError, "value too large to convert"); } return false; @@ -818,8 +810,7 @@ private static void SetConversionError(IntPtr value, Type target) IntPtr ob = Runtime.PyObject_Repr(value); string src = Runtime.GetManagedString(ob); Runtime.XDecref(ob); - string error = string.Format("Cannot convert {0} to {1}", src, target); - Exceptions.SetError(Exceptions.TypeError, error); + Exceptions.SetError(Exceptions.TypeError, $"Cannot convert {src} to {target}"); } @@ -901,8 +892,7 @@ private static bool ToEnum(IntPtr value, Type obType, out object result, bool se if (setError) { - var error = "invalid enumeration value"; - Exceptions.SetError(Exceptions.ValueError, error); + Exceptions.SetError(Exceptions.ValueError, "invalid enumeration value"); } return false; diff --git a/src/runtime/debughelper.cs b/src/runtime/debughelper.cs index 777a61e35..2a91a74b4 100644 --- a/src/runtime/debughelper.cs +++ b/src/runtime/debughelper.cs @@ -115,5 +115,27 @@ internal static void debug(string msg) Console.WriteLine("thread {0} : {1}", tid, caller); Console.WriteLine(" {0}", msg); } + + /// + /// Helper function to inspect/compare managed to native conversions. + /// Especially useful when debugging CustomMarshaler. + /// + /// + [Conditional("DEBUG")] + public static void PrintHexBytes(byte[] bytes) + { + if ((bytes == null) || (bytes.Length == 0)) + { + Console.WriteLine(""); + } + else + { + foreach (byte t in bytes) + { + Console.Write("{0:X2} ", t); + } + Console.WriteLine(); + } + } } } diff --git a/src/runtime/exceptions.cs b/src/runtime/exceptions.cs index b18cd7d69..9023cfcfa 100644 --- a/src/runtime/exceptions.cs +++ b/src/runtime/exceptions.cs @@ -2,7 +2,6 @@ using System.Reflection; using System.Runtime.InteropServices; - namespace Python.Runtime { /// @@ -134,10 +133,10 @@ internal static void Shutdown() /// __getattr__ implementation, and thus dereferencing a NULL /// pointer. /// - /// A CLR exception /// The python object wrapping internal static void SetArgsAndCause(IntPtr ob) { + // e: A CLR Exception Exception e = ExceptionClassObject.ToException(ob); if (e == null) { @@ -171,7 +170,7 @@ internal static void SetArgsAndCause(IntPtr ob) /// Shortcut for (pointer == NULL) -> throw PythonException /// /// Pointer to a Python object - internal static unsafe void ErrorCheck(IntPtr pointer) + internal static void ErrorCheck(IntPtr pointer) { if (pointer == IntPtr.Zero) { @@ -182,7 +181,7 @@ internal static unsafe void ErrorCheck(IntPtr pointer) /// /// Shortcut for (pointer == NULL or ErrorOccurred()) -> throw PythonException /// - internal static unsafe void ErrorOccurredCheck(IntPtr pointer) + internal static void ErrorOccurredCheck(IntPtr pointer) { if (pointer == IntPtr.Zero || ErrorOccurred()) { diff --git a/src/runtime/fieldobject.cs b/src/runtime/fieldobject.cs index 96572e5a5..7c9a466d5 100644 --- a/src/runtime/fieldobject.cs +++ b/src/runtime/fieldobject.cs @@ -136,8 +136,7 @@ public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) public static IntPtr tp_repr(IntPtr ob) { var self = (FieldObject)GetManagedObject(ob); - string s = $""; - return Runtime.PyString_FromStringAndSize(s, s.Length); + return Runtime.PyString_FromString($""); } } } diff --git a/src/runtime/interop.cs b/src/runtime/interop.cs index 14a69591c..4ae4b61e0 100644 --- a/src/runtime/interop.cs +++ b/src/runtime/interop.cs @@ -75,7 +75,7 @@ static ObjectOffset() { int size = IntPtr.Size; var n = 0; // Py_TRACE_REFS add two pointers to PyObject_HEAD -#if Py_DEBUG +#if PYTHON_WITH_PYDEBUG _ob_next = 0; _ob_prev = 1 * size; n = 2; @@ -113,14 +113,14 @@ public static int Size(IntPtr ob) { return ExceptionOffset.Size(); } -#if Py_DEBUG +#if PYTHON_WITH_PYDEBUG return 6 * IntPtr.Size; #else return 4 * IntPtr.Size; #endif } -#if Py_DEBUG +#if PYTHON_WITH_PYDEBUG public static int _ob_next; public static int _ob_prev; #endif @@ -185,7 +185,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 PYTHON_WITH_PYDEBUG /* _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; diff --git a/src/runtime/methodbinder.cs b/src/runtime/methodbinder.cs index 86a76dd82..f0c58f34f 100644 --- a/src/runtime/methodbinder.cs +++ b/src/runtime/methodbinder.cs @@ -167,9 +167,13 @@ internal MethodBase[] GetMethods() } /// - /// Precedence algorithm largely lifted from jython - the concerns are - /// generally the same so we'll start w/this and tweak as necessary. + /// Precedence algorithm largely lifted from Jython - the concerns are + /// generally the same so we'll start with this and tweak as necessary. /// + /// + /// Based from Jython `org.python.core.ReflectedArgs.precedence` + /// See: https://github.com/jythontools/jython/blob/master/src/org/python/core/ReflectedArgs.java#L192 + /// internal static int GetPrecedence(MethodBase mi) { ParameterInfo[] pi = mi.GetParameters(); @@ -198,61 +202,49 @@ internal static int ArgPrecedence(Type t) TypeCode tc = Type.GetTypeCode(t); // TODO: Clean up - if (tc == TypeCode.Object) + switch (tc) { - return 1; - } - if (tc == TypeCode.UInt64) - { - return 10; - } - if (tc == TypeCode.UInt32) - { - return 11; - } - if (tc == TypeCode.UInt16) - { - return 12; - } - if (tc == TypeCode.Int64) - { - return 13; - } - if (tc == TypeCode.Int32) - { - return 14; - } - if (tc == TypeCode.Int16) - { - return 15; - } - if (tc == TypeCode.Char) - { - return 16; - } - if (tc == TypeCode.SByte) - { - return 17; - } - if (tc == TypeCode.Byte) - { - return 18; - } - if (tc == TypeCode.Single) - { - return 20; - } - if (tc == TypeCode.Double) - { - return 21; - } - if (tc == TypeCode.String) - { - return 30; - } - if (tc == TypeCode.Boolean) - { - return 40; + case TypeCode.Object: + return 1; + + case TypeCode.UInt64: + return 10; + + case TypeCode.UInt32: + return 11; + + case TypeCode.UInt16: + return 12; + + case TypeCode.Int64: + return 13; + + case TypeCode.Int32: + return 14; + + case TypeCode.Int16: + return 15; + + case TypeCode.Char: + return 16; + + case TypeCode.SByte: + return 17; + + case TypeCode.Byte: + return 18; + + case TypeCode.Single: + return 20; + + case TypeCode.Double: + return 21; + + case TypeCode.String: + return 30; + + case TypeCode.Boolean: + return 40; } if (t.IsArray) @@ -337,7 +329,7 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth else if (pynargs > clrnargs && clrnargs > 0 && Attribute.IsDefined(pi[clrnargs - 1], typeof(ParamArrayAttribute))) { - // This is a spam(params object[] egg) style method + // This is a `foo(params object[] bar)` style method match = true; arrayStart = clrnargs - 1; } @@ -383,7 +375,7 @@ internal Binding Bind(IntPtr inst, IntPtr args, IntPtr kw, MethodBase info, Meth if (clrtype != null) { var typematch = false; - if (pi[n].ParameterType != clrtype) + if ((pi[n].ParameterType != typeof(object)) && (pi[n].ParameterType != clrtype)) { IntPtr pytype = Converter.GetPythonTypeByAlias(pi[n].ParameterType); pyoptype = Runtime.PyObject_Type(op); diff --git a/src/runtime/methodbinding.cs b/src/runtime/methodbinding.cs index 22b883186..07090a92c 100644 --- a/src/runtime/methodbinding.cs +++ b/src/runtime/methodbinding.cs @@ -55,8 +55,7 @@ public static IntPtr mp_subscript(IntPtr tp, IntPtr idx) return Exceptions.RaiseTypeError("No match found for given type params"); } - var mb = new MethodBinding(self.m, self.target); - mb.info = mi; + var mb = new MethodBinding(self.m, self.target) { info = mi }; Runtime.XIncref(mb.pyHandle); return mb.pyHandle; } @@ -76,22 +75,21 @@ public static IntPtr tp_getattro(IntPtr ob, IntPtr key) } string name = Runtime.GetManagedString(key); - if (name == "__doc__") + switch (name) { - IntPtr doc = self.m.GetDocString(); - Runtime.XIncref(doc); - return doc; + case "__doc__": + IntPtr doc = self.m.GetDocString(); + Runtime.XIncref(doc); + return doc; + // FIXME: deprecate __overloads__ soon... + case "__overloads__": + case "Overloads": + var om = new OverloadMapper(self.m, self.target); + Runtime.XIncref(om.pyHandle); + return om.pyHandle; + default: + return Runtime.PyObject_GenericGetAttr(ob, key); } - - // FIXME: deprecate __overloads__ soon... - if (name == "__overloads__" || name == "Overloads") - { - var om = new OverloadMapper(self.m, self.target); - Runtime.XIncref(om.pyHandle); - return om.pyHandle; - } - - return Runtime.PyObject_GenericGetAttr(ob, key); } @@ -231,8 +229,8 @@ public static IntPtr tp_repr(IntPtr ob) { var self = (MethodBinding)GetManagedObject(ob); string type = self.target == IntPtr.Zero ? "unbound" : "bound"; - string s = string.Format("<{0} method '{1}'>", type, self.m.name); - return Runtime.PyString_FromStringAndSize(s, s.Length); + string name = self.m.name; + return Runtime.PyString_FromString($"<{type} method '{name}'>"); } /// diff --git a/src/runtime/methodobject.cs b/src/runtime/methodobject.cs index d2d821eb5..8df9c8029 100644 --- a/src/runtime/methodobject.cs +++ b/src/runtime/methodobject.cs @@ -187,8 +187,7 @@ public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) public static IntPtr tp_repr(IntPtr ob) { var self = (MethodObject)GetManagedObject(ob); - string s = string.Format("", self.name); - return Runtime.PyString_FromStringAndSize(s, s.Length); + return Runtime.PyString_FromString($""); } /// diff --git a/src/runtime/modulefunctionobject.cs b/src/runtime/modulefunctionobject.cs index aa4c8fb06..8f8692af9 100644 --- a/src/runtime/modulefunctionobject.cs +++ b/src/runtime/modulefunctionobject.cs @@ -33,8 +33,7 @@ public static IntPtr tp_call(IntPtr ob, IntPtr args, IntPtr kw) public new static IntPtr tp_repr(IntPtr ob) { var self = (ModuleFunctionObject)GetManagedObject(ob); - string s = $""; - return Runtime.PyString_FromStringAndSize(s, s.Length); + return Runtime.PyString_FromString($""); } } } diff --git a/src/runtime/moduleobject.cs b/src/runtime/moduleobject.cs index b324e6f3a..258d77bac 100644 --- a/src/runtime/moduleobject.cs +++ b/src/runtime/moduleobject.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using System.Reflection; using System.Runtime.InteropServices; @@ -396,7 +397,7 @@ public static Assembly AddReference(string name) } if (assembly == null) { - throw new System.IO.FileNotFoundException($"Unable to find assembly '{name}'."); + throw new FileNotFoundException($"Unable to find assembly '{name}'."); } return assembly; diff --git a/src/runtime/propertyobject.cs b/src/runtime/propertyobject.cs index 7d758e38e..f2c97f163 100644 --- a/src/runtime/propertyobject.cs +++ b/src/runtime/propertyobject.cs @@ -158,8 +158,7 @@ public static IntPtr tp_descr_get(IntPtr ds, IntPtr ob, IntPtr tp) public static IntPtr tp_repr(IntPtr ob) { var self = (PropertyObject)GetManagedObject(ob); - string s = $""; - return Runtime.PyString_FromStringAndSize(s, s.Length); + return Runtime.PyString_FromString($""); } } } diff --git a/src/runtime/pyansistring.cs b/src/runtime/pyansistring.cs index 4973d8b2a..3d1d6ab68 100644 --- a/src/runtime/pyansistring.cs +++ b/src/runtime/pyansistring.cs @@ -44,11 +44,8 @@ public PyAnsiString(PyObject o) /// public PyAnsiString(string s) { - obj = Runtime.PyString_FromStringAndSize(s, s.Length); - if (obj == IntPtr.Zero) - { - throw new PythonException(); - } + obj = Runtime.PyString_FromString(s); + Runtime.CheckExceptionOccurred(); } diff --git a/src/runtime/pyfloat.cs b/src/runtime/pyfloat.cs index cca436def..edfaca542 100644 --- a/src/runtime/pyfloat.cs +++ b/src/runtime/pyfloat.cs @@ -51,10 +51,7 @@ public PyFloat(PyObject o) public PyFloat(double value) { obj = Runtime.PyFloat_FromDouble(value); - if (obj == IntPtr.Zero) - { - throw new PythonException(); - } + Runtime.CheckExceptionOccurred(); } @@ -69,10 +66,7 @@ public PyFloat(string value) using (var s = new PyString(value)) { obj = Runtime.PyFloat_FromString(s.obj, IntPtr.Zero); - if (obj == IntPtr.Zero) - { - throw new PythonException(); - } + Runtime.CheckExceptionOccurred(); } } @@ -100,10 +94,7 @@ public static bool IsFloatType(PyObject value) public static PyFloat AsFloat(PyObject value) { IntPtr op = Runtime.PyNumber_Float(value.obj); - if (op == IntPtr.Zero) - { - throw new PythonException(); - } + Runtime.CheckExceptionOccurred(); return new PyFloat(op); } } diff --git a/src/runtime/pyint.cs b/src/runtime/pyint.cs index c84939482..f6911d9d7 100644 --- a/src/runtime/pyint.cs +++ b/src/runtime/pyint.cs @@ -51,10 +51,7 @@ public PyInt(PyObject o) public PyInt(int value) { obj = Runtime.PyInt_FromInt32(value); - if (obj == IntPtr.Zero) - { - throw new PythonException(); - } + Runtime.CheckExceptionOccurred(); } @@ -68,10 +65,7 @@ public PyInt(int value) public PyInt(uint value) : base(IntPtr.Zero) { obj = Runtime.PyInt_FromInt64(value); - if (obj == IntPtr.Zero) - { - throw new PythonException(); - } + Runtime.CheckExceptionOccurred(); } @@ -84,10 +78,7 @@ public PyInt(uint value) : base(IntPtr.Zero) public PyInt(long value) : base(IntPtr.Zero) { obj = Runtime.PyInt_FromInt64(value); - if (obj == IntPtr.Zero) - { - throw new PythonException(); - } + Runtime.CheckExceptionOccurred(); } @@ -101,10 +92,7 @@ public PyInt(long value) : base(IntPtr.Zero) public PyInt(ulong value) : base(IntPtr.Zero) { obj = Runtime.PyInt_FromInt64((long)value); - if (obj == IntPtr.Zero) - { - throw new PythonException(); - } + Runtime.CheckExceptionOccurred(); } @@ -163,10 +151,7 @@ public PyInt(sbyte value) : this((int)value) public PyInt(string value) { obj = Runtime.PyInt_FromString(value, IntPtr.Zero, 0); - if (obj == IntPtr.Zero) - { - throw new PythonException(); - } + Runtime.CheckExceptionOccurred(); } @@ -193,10 +178,7 @@ public static bool IsIntType(PyObject value) public static PyInt AsInt(PyObject value) { IntPtr op = Runtime.PyNumber_Int(value.obj); - if (op == IntPtr.Zero) - { - throw new PythonException(); - } + Runtime.CheckExceptionOccurred(); return new PyInt(op); } diff --git a/src/runtime/pylong.cs b/src/runtime/pylong.cs index ade7cb42c..286af40df 100644 --- a/src/runtime/pylong.cs +++ b/src/runtime/pylong.cs @@ -51,10 +51,7 @@ public PyLong(PyObject o) public PyLong(int value) { obj = Runtime.PyLong_FromLong(value); - if (obj == IntPtr.Zero) - { - throw new PythonException(); - } + Runtime.CheckExceptionOccurred(); } @@ -68,10 +65,7 @@ public PyLong(int value) public PyLong(uint value) { obj = Runtime.PyLong_FromLong(value); - if (obj == IntPtr.Zero) - { - throw new PythonException(); - } + Runtime.CheckExceptionOccurred(); } @@ -84,10 +78,7 @@ public PyLong(uint value) public PyLong(long value) { obj = Runtime.PyLong_FromLongLong(value); - if (obj == IntPtr.Zero) - { - throw new PythonException(); - } + Runtime.CheckExceptionOccurred(); } @@ -101,10 +92,7 @@ public PyLong(long value) public PyLong(ulong value) { obj = Runtime.PyLong_FromUnsignedLongLong(value); - if (obj == IntPtr.Zero) - { - throw new PythonException(); - } + Runtime.CheckExceptionOccurred(); } @@ -117,10 +105,7 @@ public PyLong(ulong value) public PyLong(short value) { obj = Runtime.PyLong_FromLong(value); - if (obj == IntPtr.Zero) - { - throw new PythonException(); - } + Runtime.CheckExceptionOccurred(); } @@ -134,10 +119,7 @@ public PyLong(short value) public PyLong(ushort value) { obj = Runtime.PyLong_FromLong(value); - if (obj == IntPtr.Zero) - { - throw new PythonException(); - } + Runtime.CheckExceptionOccurred(); } @@ -150,10 +132,7 @@ public PyLong(ushort value) public PyLong(byte value) { obj = Runtime.PyLong_FromLong(value); - if (obj == IntPtr.Zero) - { - throw new PythonException(); - } + Runtime.CheckExceptionOccurred(); } @@ -167,10 +146,7 @@ public PyLong(byte value) public PyLong(sbyte value) { obj = Runtime.PyLong_FromLong(value); - if (obj == IntPtr.Zero) - { - throw new PythonException(); - } + Runtime.CheckExceptionOccurred(); } @@ -183,10 +159,7 @@ public PyLong(sbyte value) public PyLong(double value) { obj = Runtime.PyLong_FromDouble(value); - if (obj == IntPtr.Zero) - { - throw new PythonException(); - } + Runtime.CheckExceptionOccurred(); } @@ -199,10 +172,7 @@ public PyLong(double value) public PyLong(string value) { obj = Runtime.PyLong_FromString(value, IntPtr.Zero, 0); - if (obj == IntPtr.Zero) - { - throw new PythonException(); - } + Runtime.CheckExceptionOccurred(); } @@ -229,10 +199,7 @@ public static bool IsLongType(PyObject value) public static PyLong AsLong(PyObject value) { IntPtr op = Runtime.PyNumber_Long(value.obj); - if (op == IntPtr.Zero) - { - throw new PythonException(); - } + Runtime.CheckExceptionOccurred(); return new PyLong(op); } diff --git a/src/runtime/pyobject.cs b/src/runtime/pyobject.cs index 3296d81f8..47f413409 100644 --- a/src/runtime/pyobject.cs +++ b/src/runtime/pyobject.cs @@ -887,30 +887,32 @@ public override int GetHashCode() return Runtime.PyObject_Hash(obj).ToInt32(); } - public override bool TryGetMember(GetMemberBinder binder, out object result) + + public long Refcount { - if (this.HasAttr(binder.Name)) - { - result = CheckNone(this.GetAttr(binder.Name)); - return true; - } - else + get { - return base.TryGetMember(binder, out result); + return Runtime.Refcount(obj); } } + + public override bool TryGetMember(GetMemberBinder binder, out object result) + { + result = CheckNone(this.GetAttr(binder.Name)); + return true; + } + public override bool TrySetMember(SetMemberBinder binder, object value) { - if (this.HasAttr(binder.Name)) - { - this.SetAttr(binder.Name, (PyObject)value); - return true; - } - else + IntPtr ptr = Converter.ToPython(value, value?.GetType()); + int r = Runtime.PyObject_SetAttrString(obj, binder.Name, ptr); + if (r < 0) { - return base.TrySetMember(binder, value); + throw new PythonException(); } + Runtime.XDecref(ptr); + return true; } private void GetArgs(object[] inargs, out PyTuple args, out PyDict kwargs) diff --git a/src/runtime/pystring.cs b/src/runtime/pystring.cs index 624de80eb..c9c4f9f5b 100644 --- a/src/runtime/pystring.cs +++ b/src/runtime/pystring.cs @@ -54,10 +54,7 @@ public PyString(PyObject o) public PyString(string s) { obj = Runtime.PyUnicode_FromUnicode(s, s.Length); - if (obj == IntPtr.Zero) - { - throw new PythonException(); - } + Runtime.CheckExceptionOccurred(); } diff --git a/src/runtime/pythonengine.cs b/src/runtime/pythonengine.cs index e9fa888a9..1fd3b239a 100644 --- a/src/runtime/pythonengine.cs +++ b/src/runtime/pythonengine.cs @@ -1,9 +1,9 @@ using System; -using System.IO; -using System.Threading; -using System.Reflection; using System.Collections.Generic; +using System.IO; using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; namespace Python.Runtime { @@ -14,6 +14,9 @@ public class PythonEngine : IDisposable { private static DelegateManager delegateManager; private static bool initialized; + private static IntPtr _pythonHome = IntPtr.Zero; + private static IntPtr _programName = IntPtr.Zero; + private static IntPtr _pythonPath = IntPtr.Zero; public PythonEngine() { @@ -57,62 +60,74 @@ public static string ProgramName { get { - string result = Runtime.Py_GetProgramName(); - if (result == null) - { - return ""; - } - return result; + IntPtr p = Runtime.Py_GetProgramName(); + return UcsMarshaler.PtrToPy3UnicodePy2String(p) ?? ""; + } + set + { + Marshal.FreeHGlobal(_programName); + _programName = UcsMarshaler.Py3UnicodePy2StringtoPtr(value); + Runtime.Py_SetProgramName(_programName); } - set { Runtime.Py_SetProgramName(value); } } public static string PythonHome { get { - string result = Runtime.Py_GetPythonHome(); - if (result == null) - { - return ""; - } - return result; + IntPtr p = Runtime.Py_GetPythonHome(); + return UcsMarshaler.PtrToPy3UnicodePy2String(p) ?? ""; + } + set + { + Marshal.FreeHGlobal(_pythonHome); + _pythonHome = UcsMarshaler.Py3UnicodePy2StringtoPtr(value); + Runtime.Py_SetPythonHome(_pythonHome); } - set { Runtime.Py_SetPythonHome(value); } } public static string PythonPath { get { - string result = Runtime.Py_GetPath(); - if (result == null) + IntPtr p = Runtime.Py_GetPath(); + return UcsMarshaler.PtrToPy3UnicodePy2String(p) ?? ""; + } + set + { + if (Runtime.IsPython2) { - return ""; + throw new NotSupportedException("Set PythonPath not supported on Python 2"); } - return result; + Marshal.FreeHGlobal(_pythonPath); + _pythonPath = UcsMarshaler.Py3UnicodePy2StringtoPtr(value); + Runtime.Py_SetPath(_pythonPath); } - set { Runtime.Py_SetPath(value); } } public static string Version { - get { return Runtime.Py_GetVersion(); } + get { return Marshal.PtrToStringAnsi(Runtime.Py_GetVersion()); } } public static string BuildInfo { - get { return Runtime.Py_GetBuildInfo(); } + get { return Marshal.PtrToStringAnsi(Runtime.Py_GetBuildInfo()); } } public static string Platform { - get { return Runtime.Py_GetPlatform(); } + get { return Marshal.PtrToStringAnsi(Runtime.Py_GetPlatform()); } } public static string Copyright { - get { return Runtime.Py_GetCopyright(); } + get { return Marshal.PtrToStringAnsi(Runtime.Py_GetCopyright()); } + } + + public static string Compiler + { + get { return Marshal.PtrToStringAnsi(Runtime.Py_GetCompiler()); } } public static int RunSimpleString(string code) @@ -122,7 +137,12 @@ public static int RunSimpleString(string code) public static void Initialize() { - Initialize(Enumerable.Empty()); + Initialize(setSysArgv: true); + } + + public static void Initialize(bool setSysArgv = true) + { + Initialize(Enumerable.Empty(), setSysArgv: setSysArgv); } /// @@ -134,7 +154,7 @@ public static void Initialize() /// first call. It is *not* necessary to hold the Python global /// interpreter lock (GIL) to call this method. /// - public static void Initialize(IEnumerable args) + public static void Initialize(IEnumerable args, bool setSysArgv = true) { if (!initialized) { @@ -148,7 +168,10 @@ public static void Initialize(IEnumerable args) initialized = true; Exceptions.Clear(); - Py.SetArgv(args); + if (setSysArgv) + { + Py.SetArgv(args); + } // register the atexit callback (this doesn't use Py_AtExit as the C atexit // callbacks are called after python is fully finalized but the python ones @@ -156,11 +179,7 @@ public static void Initialize(IEnumerable args) string code = "import atexit, clr\n" + "atexit.register(clr._AtExit)\n"; - PyObject r = PythonEngine.RunString(code); - if (r != null) - { - r.Dispose(); - } + PythonEngine.Exec(code); // Load the clr.py resource into the clr module IntPtr clr = Python.Runtime.ImportHook.GetCLRModule(); @@ -180,12 +199,7 @@ public static void Initialize(IEnumerable args) { // add the contents of clr.py to the module string clr_py = reader.ReadToEnd(); - PyObject result = RunString(clr_py, module_globals, locals.Handle); - if (null == result) - { - throw new PythonException(); - } - result.Dispose(); + Exec(clr_py, module_globals, locals.Handle); } // add the imported module to the clr module, and copy the API functions @@ -222,7 +236,7 @@ public static void InitExt() { try { - Initialize(); + Initialize(setSysArgv: false); // Trickery - when the import hook is installed into an already // running Python, the standard import machinery is still in @@ -253,11 +267,7 @@ public static void InitExt() " exec(line)\n" + " break\n"; - PyObject r = PythonEngine.RunString(code); - if (r != null) - { - r.Dispose(); - } + PythonEngine.Exec(code); } catch (PythonException e) { @@ -284,6 +294,13 @@ public static void Shutdown() { if (initialized) { + Marshal.FreeHGlobal(_pythonHome); + _pythonHome = IntPtr.Zero; + Marshal.FreeHGlobal(_programName); + _programName = IntPtr.Zero; + Marshal.FreeHGlobal(_pythonPath); + _pythonPath = IntPtr.Zero; + Runtime.Shutdown(); initialized = false; } @@ -368,7 +385,7 @@ public static void EndAllowThreads(IntPtr ts) public static PyObject ImportModule(string name) { IntPtr op = Runtime.PyImport_ImportModule(name); - Py.Throw(); + Runtime.CheckExceptionOccurred(); return new PyObject(op); } @@ -383,7 +400,7 @@ public static PyObject ImportModule(string name) public static PyObject ReloadModule(PyObject module) { IntPtr op = Runtime.PyImport_ReloadModule(module.Handle); - Py.Throw(); + Runtime.CheckExceptionOccurred(); return new PyObject(op); } @@ -398,24 +415,64 @@ public static PyObject ReloadModule(PyObject module) public static PyObject ModuleFromString(string name, string code) { IntPtr c = Runtime.Py_CompileString(code, "none", (IntPtr)257); - Py.Throw(); + Runtime.CheckExceptionOccurred(); IntPtr m = Runtime.PyImport_ExecCodeModule(name, c); - Py.Throw(); + Runtime.CheckExceptionOccurred(); return new PyObject(m); } /// - /// RunString Method + /// Eval Method + /// + /// + /// Evaluate a Python expression and returns the result. + /// It's a subset of Python eval function. + /// + public static PyObject Eval(string code, IntPtr? globals = null, IntPtr? locals = null) + { + PyObject result = RunString(code, globals, locals, RunFlagType.Eval); + return result; + } + + + /// + /// Exec Method + /// + /// + /// Run a string containing Python code. + /// It's a subset of Python exec function. + /// + public static void Exec(string code, IntPtr? globals = null, IntPtr? locals = null) + { + PyObject result = RunString(code, globals, locals, RunFlagType.File); + if (result.obj != Runtime.PyNone) + { + throw new PythonException(); + } + result.Dispose(); + } + + + /// + /// RunString Method. Function has been deprecated and will be removed. + /// Use Exec/Eval/RunSimpleString instead. + /// + [Obsolete("RunString is deprecated and will be removed. Use Exec/Eval/RunSimpleString instead.")] + public static PyObject RunString(string code, IntPtr? globals = null, IntPtr? locals = null) + { + return RunString(code, globals, locals, RunFlagType.File); + } + + /// + /// Internal RunString Method. /// /// /// Run a string containing Python code. Returns the result of /// executing the code string as a PyObject instance, or null if /// an exception was raised. /// - public static PyObject RunString( - string code, IntPtr? globals = null, IntPtr? locals = null - ) + internal static PyObject RunString(string code, IntPtr? globals, IntPtr? locals, RunFlagType flag) { var borrowedGlobals = true; if (globals == null) @@ -439,15 +496,13 @@ public static PyObject RunString( borrowedLocals = false; } - var flag = (IntPtr)257; /* Py_file_input */ - try { IntPtr result = Runtime.PyRun_String( - code, flag, globals.Value, locals.Value + code, (IntPtr)flag, globals.Value, locals.Value ); - Py.Throw(); + Runtime.CheckExceptionOccurred(); return new PyObject(result); } @@ -465,6 +520,13 @@ public static PyObject RunString( } } + public enum RunFlagType + { + Single = 256, + File = 257, /* Py_file_input */ + Eval = 258 + } + public static class Py { public static GILState GIL() @@ -567,18 +629,7 @@ public static void SetArgv(IEnumerable argv) { string[] arr = argv.ToArray(); Runtime.PySys_SetArgvEx(arr.Length, arr, 0); - Py.Throw(); - } - } - - internal static void Throw() - { - using (GIL()) - { - if (Runtime.PyErr_Occurred() != 0) - { - throw new PythonException(); - } + Runtime.CheckExceptionOccurred(); } } } diff --git a/src/runtime/pythonexception.cs b/src/runtime/pythonexception.cs index 8e2f992f4..4fe07f3cf 100644 --- a/src/runtime/pythonexception.cs +++ b/src/runtime/pythonexception.cs @@ -135,12 +135,14 @@ public override string StackTrace /// /// The Dispose method provides a way to explicitly release the /// Python objects represented by a PythonException. + /// If object not properly disposed can cause AppDomain unload issue. + /// See GH#397 and GH#400. /// public void Dispose() { if (!disposed) { - if (Runtime.Py_IsInitialized() > 0) + if (Runtime.Py_IsInitialized() > 0 && !Runtime.IsFinalizing) { IntPtr gs = PythonEngine.AcquireLock(); Runtime.XDecref(_pyType); diff --git a/src/runtime/pytuple.cs b/src/runtime/pytuple.cs index b3fb95733..45f3d8350 100644 --- a/src/runtime/pytuple.cs +++ b/src/runtime/pytuple.cs @@ -51,10 +51,7 @@ public PyTuple(PyObject o) public PyTuple() { obj = Runtime.PyTuple_New(0); - if (obj == IntPtr.Zero) - { - throw new PythonException(); - } + Runtime.CheckExceptionOccurred(); } @@ -63,6 +60,9 @@ public PyTuple() /// /// /// Creates a new PyTuple from an array of PyObject instances. + /// + /// See caveats about PyTuple_SetItem: + /// https://www.coursehero.com/file/p4j2ogg/important-exceptions-to-this-rule-PyTupleSetItem-and-PyListSetItem-These/ /// public PyTuple(PyObject[] items) { @@ -72,11 +72,8 @@ public PyTuple(PyObject[] items) { IntPtr ptr = items[i].obj; Runtime.XIncref(ptr); - int r = Runtime.PyTuple_SetItem(obj, i, ptr); - if (r < 0) - { - throw new PythonException(); - } + Runtime.PyTuple_SetItem(obj, i, ptr); + Runtime.CheckExceptionOccurred(); } } @@ -104,10 +101,7 @@ public static bool IsTupleType(PyObject value) public static PyTuple AsTuple(PyObject value) { IntPtr op = Runtime.PySequence_Tuple(value.obj); - if (op == IntPtr.Zero) - { - throw new PythonException(); - } + Runtime.CheckExceptionOccurred(); return new PyTuple(op); } } diff --git a/src/runtime/resources/clr.py b/src/runtime/resources/clr.py index c329b1f6d..e708a54ac 100644 --- a/src/runtime/resources/clr.py +++ b/src/runtime/resources/clr.py @@ -2,7 +2,7 @@ Code in this module gets loaded into the main clr module. """ -__version__ = "2.2.2" +__version__ = "2.4.0.dev0" class clrproperty(object): diff --git a/src/runtime/runtime.cs b/src/runtime/runtime.cs index 22b590657..346ea745f 100644 --- a/src/runtime/runtime.cs +++ b/src/runtime/runtime.cs @@ -82,62 +82,50 @@ public class Runtime { #if UCS4 public const int UCS = 4; + + /// + /// EntryPoint to be used in DllImport to map to correct Unicode + /// methods prior to PEP393. Only used for PY27. + /// + private const string PyUnicodeEntryPoint = "PyUnicodeUCS4_"; #elif UCS2 public const int UCS = 2; + + /// + /// EntryPoint to be used in DllImport to map to correct Unicode + /// methods prior to PEP393. Only used for PY27. + /// + private const string PyUnicodeEntryPoint = "PyUnicodeUCS2_"; #else #error You must define either UCS2 or UCS4! #endif #if PYTHON27 public const string pyversion = "2.7"; - public const int pyversionnumber = 27; + public const string pyver = "27"; #elif PYTHON33 public const string pyversion = "3.3"; - public const int pyversionnumber = 33; + public const string pyver = "33"; #elif PYTHON34 public const string pyversion = "3.4"; - public const int pyversionnumber = 34; + public const string pyver = "34"; #elif PYTHON35 public const string pyversion = "3.5"; - public const int pyversionnumber = 35; + public const string pyver = "35"; #elif PYTHON36 public const string pyversion = "3.6"; - public const int pyversionnumber = 36; -#elif PYTHON37 // TODO: Add interop37 after Python3.7 is released + public const string pyver = "36"; +#elif PYTHON37 // TODO: Add `interop37.cs` after PY37 is released public const string pyversion = "3.7"; - public const int pyversionnumber = 37; + public const string pyver = "37"; #else #error You must define one of PYTHON33 to PYTHON37 or PYTHON27 #endif -#if MONO_LINUX || MONO_OSX -#if PYTHON27 - internal const string dllBase = "python27"; -#elif PYTHON33 - internal const string dllBase = "python3.3"; -#elif PYTHON34 - internal const string dllBase = "python3.4"; -#elif PYTHON35 - internal const string dllBase = "python3.5"; -#elif PYTHON36 - internal const string dllBase = "python3.6"; -#elif PYTHON37 - internal const string dllBase = "python3.7"; -#endif +#if MONO_LINUX || MONO_OSX // Linux/macOS use dotted version string + internal const string dllBase = "python" + pyversion; #else // Windows -#if PYTHON27 - internal const string dllBase = "python27"; -#elif PYTHON33 - internal const string dllBase = "python33"; -#elif PYTHON34 - internal const string dllBase = "python34"; -#elif PYTHON35 - internal const string dllBase = "python35"; -#elif PYTHON36 - internal const string dllBase = "python36"; -#elif PYTHON37 - internal const string dllBase = "python37"; -#endif + internal const string dllBase = "python" + pyver; #endif #if PYTHON_WITH_PYDEBUG @@ -150,156 +138,153 @@ public class Runtime #else internal const string dllWithPyMalloc = ""; #endif -#if PYTHON_WITH_WIDE_UNICODE - internal const string dllWithWideUnicode = "u"; -#else - internal const string dllWithWideUnicode = ""; -#endif #if PYTHON_WITHOUT_ENABLE_SHARED - public const string dll = "__Internal"; + public const string PythonDll = "__Internal"; #else - public const string dll = dllBase + dllWithPyDebug + dllWithPyMalloc + dllWithWideUnicode; + public const string PythonDll = dllBase + dllWithPyDebug + dllWithPyMalloc; #endif + public static readonly int pyversionnumber = Convert.ToInt32(pyver); + // set to true when python is finalizing - internal static Object IsFinalizingLock = new Object(); - internal static bool IsFinalizing = false; + internal static object IsFinalizingLock = new object(); + internal static bool IsFinalizing; - internal static bool Is32Bit; - internal static bool IsPython2; - internal static bool IsPython3; + internal static bool Is32Bit = IntPtr.Size == 4; + internal static bool IsPython2 = pyversionnumber < 30; + internal static bool IsPython3 = pyversionnumber >= 30; + + /// + /// Encoding to use to convert Unicode to/from Managed to Native + /// + internal static readonly Encoding PyEncoding = UCS == 2 ? Encoding.Unicode : Encoding.UTF32; /// /// Initialize the runtime... /// internal static void Initialize() { - Is32Bit = IntPtr.Size == 4; - IsPython2 = pyversionnumber < 30; - IsPython3 = pyversionnumber >= 30; - - if (Runtime.Py_IsInitialized() == 0) + if (Py_IsInitialized() == 0) { - Runtime.Py_Initialize(); + Py_Initialize(); } - if (Runtime.PyEval_ThreadsInitialized() == 0) + if (PyEval_ThreadsInitialized() == 0) { - Runtime.PyEval_InitThreads(); + PyEval_InitThreads(); } IntPtr op; IntPtr dict; if (IsPython3) { - op = Runtime.PyImport_ImportModule("builtins"); - dict = Runtime.PyObject_GetAttrString(op, "__dict__"); - + op = PyImport_ImportModule("builtins"); + dict = PyObject_GetAttrString(op, "__dict__"); } else // Python2 { - dict = Runtime.PyImport_GetModuleDict(); - op = Runtime.PyDict_GetItemString(dict, "__builtin__"); + dict = PyImport_GetModuleDict(); + op = PyDict_GetItemString(dict, "__builtin__"); } - PyNotImplemented = Runtime.PyObject_GetAttrString(op, "NotImplemented"); - PyBaseObjectType = Runtime.PyObject_GetAttrString(op, "object"); + PyNotImplemented = PyObject_GetAttrString(op, "NotImplemented"); + PyBaseObjectType = PyObject_GetAttrString(op, "object"); - PyModuleType = Runtime.PyObject_Type(op); - PyNone = Runtime.PyObject_GetAttrString(op, "None"); - PyTrue = Runtime.PyObject_GetAttrString(op, "True"); - PyFalse = Runtime.PyObject_GetAttrString(op, "False"); + PyModuleType = PyObject_Type(op); + PyNone = PyObject_GetAttrString(op, "None"); + PyTrue = PyObject_GetAttrString(op, "True"); + PyFalse = PyObject_GetAttrString(op, "False"); - PyBoolType = Runtime.PyObject_Type(PyTrue); - PyNoneType = Runtime.PyObject_Type(PyNone); - PyTypeType = Runtime.PyObject_Type(PyNoneType); + PyBoolType = PyObject_Type(PyTrue); + PyNoneType = PyObject_Type(PyNone); + PyTypeType = PyObject_Type(PyNoneType); - op = Runtime.PyObject_GetAttrString(dict, "keys"); - PyMethodType = Runtime.PyObject_Type(op); - Runtime.XDecref(op); + op = PyObject_GetAttrString(dict, "keys"); + PyMethodType = PyObject_Type(op); + 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); + op = PyObject_GetAttrString(PyBaseObjectType, "__init__"); + PyWrapperDescriptorType = PyObject_Type(op); + XDecref(op); #if PYTHON3 - Runtime.XDecref(dict); + XDecref(dict); #endif - op = Runtime.PyString_FromString("string"); - PyStringType = Runtime.PyObject_Type(op); - Runtime.XDecref(op); + op = PyString_FromString("string"); + PyStringType = PyObject_Type(op); + XDecref(op); - op = Runtime.PyUnicode_FromString("unicode"); - PyUnicodeType = Runtime.PyObject_Type(op); - Runtime.XDecref(op); + op = PyUnicode_FromString("unicode"); + PyUnicodeType = PyObject_Type(op); + XDecref(op); #if PYTHON3 - op = Runtime.PyBytes_FromString("bytes"); - PyBytesType = Runtime.PyObject_Type(op); - Runtime.XDecref(op); + op = PyBytes_FromString("bytes"); + PyBytesType = PyObject_Type(op); + XDecref(op); #endif - op = Runtime.PyTuple_New(0); - PyTupleType = Runtime.PyObject_Type(op); - Runtime.XDecref(op); + op = PyTuple_New(0); + PyTupleType = PyObject_Type(op); + XDecref(op); - op = Runtime.PyList_New(0); - PyListType = Runtime.PyObject_Type(op); - Runtime.XDecref(op); + op = PyList_New(0); + PyListType = PyObject_Type(op); + XDecref(op); - op = Runtime.PyDict_New(); - PyDictType = Runtime.PyObject_Type(op); - Runtime.XDecref(op); + op = PyDict_New(); + PyDictType = PyObject_Type(op); + XDecref(op); - op = Runtime.PyInt_FromInt32(0); - PyIntType = Runtime.PyObject_Type(op); - Runtime.XDecref(op); + op = PyInt_FromInt32(0); + PyIntType = PyObject_Type(op); + XDecref(op); - op = Runtime.PyLong_FromLong(0); - PyLongType = Runtime.PyObject_Type(op); - Runtime.XDecref(op); + op = PyLong_FromLong(0); + PyLongType = PyObject_Type(op); + XDecref(op); - op = Runtime.PyFloat_FromDouble(0); - PyFloatType = Runtime.PyObject_Type(op); - Runtime.XDecref(op); + op = PyFloat_FromDouble(0); + PyFloatType = PyObject_Type(op); + XDecref(op); #if PYTHON3 PyClassType = IntPtr.Zero; PyInstanceType = IntPtr.Zero; #elif PYTHON2 - IntPtr s = Runtime.PyString_FromString("_temp"); - IntPtr d = Runtime.PyDict_New(); + IntPtr s = PyString_FromString("_temp"); + IntPtr d = PyDict_New(); - IntPtr c = Runtime.PyClass_New(IntPtr.Zero, d, s); - PyClassType = Runtime.PyObject_Type(c); + IntPtr c = PyClass_New(IntPtr.Zero, d, s); + PyClassType = PyObject_Type(c); - IntPtr i = Runtime.PyInstance_New(c, IntPtr.Zero, IntPtr.Zero); - PyInstanceType = Runtime.PyObject_Type(i); + IntPtr i = PyInstance_New(c, IntPtr.Zero, IntPtr.Zero); + PyInstanceType = PyObject_Type(i); - Runtime.XDecref(s); - Runtime.XDecref(i); - Runtime.XDecref(c); - Runtime.XDecref(d); + XDecref(s); + XDecref(i); + XDecref(c); + XDecref(d); #endif Error = new IntPtr(-1); #if PYTHON3 - IntPtr dll = IntPtr.Zero; - if ("__Internal" != Runtime.dll) + IntPtr dllLocal = IntPtr.Zero; + if (PythonDll != "__Internal") { - NativeMethods.LoadLibrary(Runtime.dll); + NativeMethods.LoadLibrary(PythonDll); } - _PyObject_NextNotImplemented = NativeMethods.GetProcAddress(dll, "_PyObject_NextNotImplemented"); + _PyObject_NextNotImplemented = NativeMethods.GetProcAddress(dllLocal, "_PyObject_NextNotImplemented"); #if !(MONO_LINUX || MONO_OSX) - if (IntPtr.Zero != dll) + if (dllLocal != IntPtr.Zero) { - NativeMethods.FreeLibrary(dll); + NativeMethods.FreeLibrary(dllLocal); } #endif #endif @@ -313,10 +298,10 @@ internal static void Initialize() // Need to add the runtime directory to sys.path so that we // can find built-in assemblies like System.Data, et. al. string rtdir = RuntimeEnvironment.GetRuntimeDirectory(); - IntPtr path = Runtime.PySys_GetObject("path"); - IntPtr item = Runtime.PyString_FromString(rtdir); - Runtime.PyList_Append(path, item); - Runtime.XDecref(item); + IntPtr path = PySys_GetObject("path"); + IntPtr item = PyString_FromString(rtdir); + PyList_Append(path, item); + XDecref(item); AssemblyManager.UpdatePath(); } @@ -380,23 +365,38 @@ internal static int AtExit() internal static IntPtr PyNone; internal static IntPtr Error; + /// + /// Check if any Python Exceptions occurred. + /// If any exist throw new PythonException. + /// + /// + /// Can be used instead of `obj == IntPtr.Zero` for example. + /// + internal static void CheckExceptionOccurred() + { + if (PyErr_Occurred() != 0) + { + throw new PythonException(); + } + } + internal static IntPtr GetBoundArgTuple(IntPtr obj, IntPtr args) { - if (Runtime.PyObject_TYPE(args) != Runtime.PyTupleType) + if (PyObject_TYPE(args) != PyTupleType) { Exceptions.SetError(Exceptions.TypeError, "tuple expected"); return IntPtr.Zero; } - int size = Runtime.PyTuple_Size(args); - IntPtr items = Runtime.PyTuple_New(size + 1); - Runtime.PyTuple_SetItem(items, 0, obj); - Runtime.XIncref(obj); + int size = PyTuple_Size(args); + IntPtr items = PyTuple_New(size + 1); + PyTuple_SetItem(items, 0, obj); + XIncref(obj); - for (int i = 0; i < size; i++) + for (var i = 0; i < size; i++) { - IntPtr item = Runtime.PyTuple_GetItem(args, i); - Runtime.XIncref(item); - Runtime.PyTuple_SetItem(items, i + 1, item); + IntPtr item = PyTuple_GetItem(args, i); + XIncref(item); + PyTuple_SetItem(items, i + 1, item); } return items; @@ -405,23 +405,23 @@ internal static IntPtr GetBoundArgTuple(IntPtr obj, IntPtr args) internal static IntPtr ExtendTuple(IntPtr t, params IntPtr[] args) { - int size = Runtime.PyTuple_Size(t); + int size = PyTuple_Size(t); int add = args.Length; IntPtr item; - IntPtr items = Runtime.PyTuple_New(size + add); - for (int i = 0; i < size; i++) + IntPtr items = PyTuple_New(size + add); + for (var i = 0; i < size; i++) { - item = Runtime.PyTuple_GetItem(t, i); - Runtime.XIncref(item); - Runtime.PyTuple_SetItem(items, i, item); + item = PyTuple_GetItem(t, i); + XIncref(item); + PyTuple_SetItem(items, i, item); } - for (int n = 0; n < add; n++) + for (var n = 0; n < add; n++) { item = args[n]; - Runtime.XIncref(item); - Runtime.PyTuple_SetItem(items, size + n, item); + XIncref(item); + PyTuple_SetItem(items, size + n, item); } return items; @@ -438,26 +438,26 @@ internal static Type[] PythonArgsToTypeArray(IntPtr arg, bool mangleObjects) // tuple of (managed or unmanaged) type objects, return a Type[] // containing the CLR Type objects that map to those types. IntPtr args = arg; - bool free = false; + var free = false; - if (!Runtime.PyTuple_Check(arg)) + if (!PyTuple_Check(arg)) { - args = Runtime.PyTuple_New(1); - Runtime.XIncref(arg); - Runtime.PyTuple_SetItem(args, 0, arg); + args = PyTuple_New(1); + XIncref(arg); + PyTuple_SetItem(args, 0, arg); free = true; } - int n = Runtime.PyTuple_Size(args); - Type[] types = new Type[n]; + int n = PyTuple_Size(args); + var types = new Type[n]; Type t = null; - for (int i = 0; i < n; i++) + for (var i = 0; i < n; i++) { - IntPtr op = Runtime.PyTuple_GetItem(args, i); - if (mangleObjects && (!Runtime.PyType_Check(op))) + IntPtr op = PyTuple_GetItem(args, i); + if (mangleObjects && (!PyType_Check(op))) { - op = Runtime.PyObject_TYPE(op); + op = PyObject_TYPE(op); } ManagedType mt = ManagedType.GetManagedObject(op); @@ -487,7 +487,7 @@ internal static Type[] PythonArgsToTypeArray(IntPtr arg, bool mangleObjects) } if (free) { - Runtime.XDecref(args); + XDecref(args); } return types; } @@ -497,14 +497,13 @@ internal static Type[] PythonArgsToTypeArray(IntPtr arg, bool mangleObjects) /// some optimization to avoid managed <--> unmanaged transitions /// (mostly for heavily used methods). /// - internal unsafe static void XIncref(IntPtr op) + internal static unsafe void XIncref(IntPtr op) { -#if Py_DEBUG - // according to Python doc, Py_IncRef() is Py_XINCREF() +#if PYTHON_WITH_PYDEBUG Py_IncRef(op); return; #else - void* p = (void*)op; + var p = (void*)op; if ((void*)0 != p) { if (Is32Bit) @@ -521,13 +520,11 @@ internal unsafe static void XIncref(IntPtr op) internal static unsafe void XDecref(IntPtr op) { -#if Py_DEBUG - // Py_DecRef calls Python's Py_DECREF - // according to Python doc, Py_DecRef() is Py_XDECREF() +#if PYTHON_WITH_PYDEBUG Py_DecRef(op); return; #else - void* p = (void*)op; + var p = (void*)op; if ((void*)0 != p) { if (Is32Bit) @@ -553,322 +550,186 @@ internal static unsafe void XDecref(IntPtr op) return; } NativeCall.Impl.Void_Call_1(new IntPtr(f), op); - return; } } #endif } - internal unsafe static long Refcount(IntPtr op) + internal static unsafe long Refcount(IntPtr op) { - void* p = (void*)op; - if ((void*)0 != p) + var p = (void*)op; + if ((void*)0 == p) { - if (Is32Bit) - { - return (*(int*)p); - } - else - { - return (*(long*)p); - } + return 0; } - return 0; + return Is32Bit ? (*(int*)p) : (*(long*)p); } -#if Py_DEBUG - // Py_IncRef and Py_DecRef are taking care of the extra payload - // in Py_DEBUG builds of Python like _Py_RefTotal - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - private unsafe static extern void - Py_IncRef(IntPtr ob); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - private unsafe static extern void - Py_DecRef(IntPtr ob); -#endif + /// + /// Export of Macro Py_XIncRef. Use XIncref instead. + /// Limit this function usage for Testing and Py_Debug builds + /// + /// PyObject Ptr + [DllImport(PythonDll)] + internal static extern void Py_IncRef(IntPtr ob); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - Py_Initialize(); + /// + /// Export of Macro Py_XDecRef. Use XDecref instead. + /// Limit this function usage for Testing and Py_Debug builds + /// + /// PyObject Ptr + [DllImport(PythonDll)] + internal static extern void Py_DecRef(IntPtr ob); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - Py_IsInitialized(); + [DllImport(PythonDll)] + internal static extern void Py_Initialize(); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - Py_Finalize(); + [DllImport(PythonDll)] + internal static extern int Py_IsInitialized(); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - Py_NewInterpreter(); + [DllImport(PythonDll)] + internal static extern void Py_Finalize(); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - Py_EndInterpreter(IntPtr threadState); + [DllImport(PythonDll)] + internal static extern IntPtr Py_NewInterpreter(); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyThreadState_New(IntPtr istate); + [DllImport(PythonDll)] + internal static extern void Py_EndInterpreter(IntPtr threadState); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyThreadState_Get(); + [DllImport(PythonDll)] + internal static extern IntPtr PyThreadState_New(IntPtr istate); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyThread_get_key_value(IntPtr key); + [DllImport(PythonDll)] + internal static extern IntPtr PyThreadState_Get(); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyThread_get_thread_ident(); + [DllImport(PythonDll)] + internal static extern IntPtr PyThread_get_key_value(IntPtr key); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyThread_set_key_value(IntPtr key, IntPtr value); + [DllImport(PythonDll)] + internal static extern int PyThread_get_thread_ident(); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyThreadState_Swap(IntPtr key); + [DllImport(PythonDll)] + internal static extern int PyThread_set_key_value(IntPtr key, IntPtr value); + [DllImport(PythonDll)] + internal static extern IntPtr PyThreadState_Swap(IntPtr key); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyGILState_Ensure(); + [DllImport(PythonDll)] + internal static extern IntPtr PyGILState_Ensure(); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - PyGILState_Release(IntPtr gs); + [DllImport(PythonDll)] + internal static extern void PyGILState_Release(IntPtr gs); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyGILState_GetThisThreadState(); + [DllImport(PythonDll)] + internal static extern IntPtr PyGILState_GetThisThreadState(); #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); + [DllImport(PythonDll)] + public static extern int Py_Main( + int argc, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StrArrayMarshaler))] string[] argv + ); #elif PYTHON2 - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - public unsafe static extern int - Py_Main(int argc, string[] argv); + [DllImport(PythonDll)] + public static extern int Py_Main(int argc, string[] argv); #endif - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - PyEval_InitThreads(); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyEval_ThreadsInitialized(); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - PyEval_AcquireLock(); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - PyEval_ReleaseLock(); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - PyEval_AcquireThread(IntPtr tstate); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - PyEval_ReleaseThread(IntPtr tstate); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyEval_SaveThread(); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - PyEval_RestoreThread(IntPtr tstate); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyEval_GetBuiltins(); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyEval_GetGlobals(); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyEval_GetLocals(); + [DllImport(PythonDll)] + internal static extern void PyEval_InitThreads(); + [DllImport(PythonDll)] + internal static extern int PyEval_ThreadsInitialized(); -#if PYTHON3 - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - [return: MarshalAs(UnmanagedType.LPWStr)] - internal unsafe static extern string - Py_GetProgramName(); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - Py_SetProgramName([MarshalAsAttribute(UnmanagedType.LPWStr)] string name); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - [return: MarshalAs(UnmanagedType.LPWStr)] - internal unsafe static extern string - Py_GetPythonHome(); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - Py_SetPythonHome([MarshalAsAttribute(UnmanagedType.LPWStr)] string home); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - [return: MarshalAs(UnmanagedType.LPWStr)] - internal unsafe static extern string - Py_GetPath(); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - Py_SetPath([MarshalAsAttribute(UnmanagedType.LPWStr)] string home); -#elif PYTHON2 - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern string - Py_GetProgramName(); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - Py_SetProgramName(string name); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern string - Py_GetPythonHome(); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - Py_SetPythonHome(string home); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern string - Py_GetPath(); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - Py_SetPath(string home); -#endif + [DllImport(PythonDll)] + internal static extern void PyEval_AcquireLock(); + + [DllImport(PythonDll)] + internal static extern void PyEval_ReleaseLock(); + + [DllImport(PythonDll)] + internal static extern void PyEval_AcquireThread(IntPtr tstate); + + [DllImport(PythonDll)] + internal static extern void PyEval_ReleaseThread(IntPtr tstate); + + [DllImport(PythonDll)] + internal static extern IntPtr PyEval_SaveThread(); + + [DllImport(PythonDll)] + internal static extern void PyEval_RestoreThread(IntPtr tstate); + + [DllImport(PythonDll)] + internal static extern IntPtr PyEval_GetBuiltins(); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern string - Py_GetVersion(); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern string - Py_GetPlatform(); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern string - Py_GetCopyright(); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern string - Py_GetCompiler(); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern string - Py_GetBuildInfo(); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyRun_SimpleString(string code); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyRun_String(string code, IntPtr st, IntPtr globals, IntPtr locals); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - Py_CompileString(string code, string file, IntPtr tok); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyImport_ExecCodeModule(string name, IntPtr code); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyCFunction_NewEx(IntPtr ml, IntPtr self, IntPtr mod); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyCFunction_Call(IntPtr func, IntPtr args, IntPtr kw); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyClass_New(IntPtr bases, IntPtr dict, IntPtr name); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyInstance_New(IntPtr cls, IntPtr args, IntPtr kw); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyInstance_NewRaw(IntPtr cls, IntPtr dict); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyMethod_New(IntPtr func, IntPtr self, IntPtr cls); + [DllImport(PythonDll)] + internal static extern IntPtr PyEval_GetGlobals(); + + [DllImport(PythonDll)] + internal static extern IntPtr PyEval_GetLocals(); + + [DllImport(PythonDll)] + internal static extern IntPtr Py_GetProgramName(); + + [DllImport(PythonDll)] + internal static extern void Py_SetProgramName(IntPtr name); + + [DllImport(PythonDll)] + internal static extern IntPtr Py_GetPythonHome(); + + [DllImport(PythonDll)] + internal static extern void Py_SetPythonHome(IntPtr home); + + [DllImport(PythonDll)] + internal static extern IntPtr Py_GetPath(); + + [DllImport(PythonDll)] + internal static extern void Py_SetPath(IntPtr home); + + [DllImport(PythonDll)] + internal static extern IntPtr Py_GetVersion(); + + [DllImport(PythonDll)] + internal static extern IntPtr Py_GetPlatform(); + + [DllImport(PythonDll)] + internal static extern IntPtr Py_GetCopyright(); + + [DllImport(PythonDll)] + internal static extern IntPtr Py_GetCompiler(); + + [DllImport(PythonDll)] + internal static extern IntPtr Py_GetBuildInfo(); + + [DllImport(PythonDll)] + internal static extern int PyRun_SimpleString(string code); + + [DllImport(PythonDll)] + internal static extern IntPtr PyRun_String(string code, IntPtr st, IntPtr globals, IntPtr locals); + + [DllImport(PythonDll)] + internal static extern IntPtr Py_CompileString(string code, string file, IntPtr tok); + + [DllImport(PythonDll)] + internal static extern IntPtr PyImport_ExecCodeModule(string name, IntPtr code); + + [DllImport(PythonDll)] + internal static extern IntPtr PyCFunction_NewEx(IntPtr ml, IntPtr self, IntPtr mod); + + [DllImport(PythonDll)] + internal static extern IntPtr PyCFunction_Call(IntPtr func, IntPtr args, IntPtr kw); + + [DllImport(PythonDll)] + internal static extern IntPtr PyClass_New(IntPtr bases, IntPtr dict, IntPtr name); + + [DllImport(PythonDll)] + internal static extern IntPtr PyInstance_New(IntPtr cls, IntPtr args, IntPtr kw); + + [DllImport(PythonDll)] + internal static extern IntPtr PyInstance_NewRaw(IntPtr cls, IntPtr dict); + + [DllImport(PythonDll)] + internal static extern IntPtr PyMethod_New(IntPtr func, IntPtr self, IntPtr cls); //==================================================================== @@ -880,39 +741,32 @@ internal unsafe static extern IntPtr /// designed to be lean and mean in IL & avoid managed <-> unmanaged /// transitions. Note that this does not incref the type object. /// - internal unsafe static IntPtr - PyObject_TYPE(IntPtr op) + internal static unsafe IntPtr PyObject_TYPE(IntPtr op) { - void* p = (void*)op; + var p = (void*)op; if ((void*)0 == p) { return IntPtr.Zero; } -#if Py_DEBUG - int n = 3; +#if PYTHON_WITH_PYDEBUG + var n = 3; #else - int n = 1; + var n = 1; #endif - if (Is32Bit) - { - return new IntPtr((void*)(*((uint*)p + n))); - } - else - { - return new IntPtr((void*)(*((ulong*)p + n))); - } + return Is32Bit + ? new IntPtr((void*)(*((uint*)p + n))) + : new IntPtr((void*)(*((ulong*)p + n))); } /// /// Managed version of the standard Python C API PyObject_Type call. - /// This version avoids a managed <-> unmanaged transition. This one - /// does incref the returned type object. + /// This version avoids a managed <-> unmanaged transition. + /// This one does incref the returned type object. /// - internal unsafe static IntPtr - PyObject_Type(IntPtr op) + internal static IntPtr PyObject_Type(IntPtr op) { IntPtr tp = PyObject_TYPE(op); - Runtime.XIncref(tp); + XIncref(tp); return tp; } @@ -923,71 +777,45 @@ internal static string PyObject_GetTypeName(IntPtr op) return Marshal.PtrToStringAnsi(ppName); } - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyObject_HasAttrString(IntPtr pointer, string name); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyObject_GetAttrString(IntPtr pointer, string name); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyObject_SetAttrString(IntPtr pointer, string name, IntPtr value); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyObject_HasAttr(IntPtr pointer, IntPtr name); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyObject_GetAttr(IntPtr pointer, IntPtr name); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyObject_SetAttr(IntPtr pointer, IntPtr name, IntPtr value); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyObject_GetItem(IntPtr pointer, IntPtr key); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyObject_SetItem(IntPtr pointer, IntPtr key, IntPtr value); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyObject_DelItem(IntPtr pointer, IntPtr key); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyObject_GetIter(IntPtr op); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyObject_Call(IntPtr pointer, IntPtr args, IntPtr kw); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyObject_CallObject(IntPtr pointer, IntPtr args); + [DllImport(PythonDll)] + internal static extern int PyObject_HasAttrString(IntPtr pointer, string name); + + [DllImport(PythonDll)] + internal static extern IntPtr PyObject_GetAttrString(IntPtr pointer, string name); + + [DllImport(PythonDll)] + internal static extern int PyObject_SetAttrString(IntPtr pointer, string name, IntPtr value); + + [DllImport(PythonDll)] + internal static extern int PyObject_HasAttr(IntPtr pointer, IntPtr name); + + [DllImport(PythonDll)] + internal static extern IntPtr PyObject_GetAttr(IntPtr pointer, IntPtr name); + + [DllImport(PythonDll)] + internal static extern int PyObject_SetAttr(IntPtr pointer, IntPtr name, IntPtr value); + + [DllImport(PythonDll)] + internal static extern IntPtr PyObject_GetItem(IntPtr pointer, IntPtr key); + + [DllImport(PythonDll)] + internal static extern int PyObject_SetItem(IntPtr pointer, IntPtr key, IntPtr value); + + [DllImport(PythonDll)] + internal static extern int PyObject_DelItem(IntPtr pointer, IntPtr key); + + [DllImport(PythonDll)] + internal static extern IntPtr PyObject_GetIter(IntPtr op); + + [DllImport(PythonDll)] + internal static extern IntPtr PyObject_Call(IntPtr pointer, IntPtr args, IntPtr kw); + + [DllImport(PythonDll)] + internal static extern IntPtr PyObject_CallObject(IntPtr pointer, IntPtr args); #if PYTHON3 - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyObject_RichCompareBool(IntPtr value1, IntPtr value2, int opid); + [DllImport(PythonDll)] + internal static extern int PyObject_RichCompareBool(IntPtr value1, IntPtr value2, int opid); internal static int PyObject_Compare(IntPtr value1, IntPtr value2) { @@ -1014,75 +842,47 @@ internal static int PyObject_Compare(IntPtr value1, IntPtr value2) return -1; } #elif PYTHON2 - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyObject_Compare(IntPtr value1, IntPtr value2); + [DllImport(PythonDll)] + internal static extern int PyObject_Compare(IntPtr value1, IntPtr value2); #endif + [DllImport(PythonDll)] + internal static extern int PyObject_IsInstance(IntPtr ob, IntPtr type); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyObject_IsInstance(IntPtr ob, IntPtr type); + [DllImport(PythonDll)] + internal static extern int PyObject_IsSubclass(IntPtr ob, IntPtr type); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyObject_IsSubclass(IntPtr ob, IntPtr type); + [DllImport(PythonDll)] + internal static extern int PyCallable_Check(IntPtr pointer); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyCallable_Check(IntPtr pointer); + [DllImport(PythonDll)] + internal static extern int PyObject_IsTrue(IntPtr pointer); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyObject_IsTrue(IntPtr pointer); + [DllImport(PythonDll)] + internal static extern int PyObject_Not(IntPtr pointer); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyObject_Not(IntPtr pointer); + [DllImport(PythonDll)] + internal static extern int PyObject_Size(IntPtr pointer); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyObject_Size(IntPtr pointer); + [DllImport(PythonDll)] + internal static extern IntPtr PyObject_Hash(IntPtr op); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyObject_Hash(IntPtr op); + [DllImport(PythonDll)] + internal static extern IntPtr PyObject_Repr(IntPtr pointer); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyObject_Repr(IntPtr pointer); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyObject_Str(IntPtr pointer); + [DllImport(PythonDll)] + internal static extern IntPtr PyObject_Str(IntPtr pointer); #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); + [DllImport(PythonDll, EntryPoint = "PyObject_Str")] + internal static extern IntPtr PyObject_Unicode(IntPtr pointer); #elif PYTHON2 - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyObject_Unicode(IntPtr pointer); + [DllImport(PythonDll)] + internal static extern IntPtr PyObject_Unicode(IntPtr pointer); #endif - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyObject_Dir(IntPtr pointer); + [DllImport(PythonDll)] + internal static extern IntPtr PyObject_Dir(IntPtr pointer); //==================================================================== @@ -1090,384 +890,243 @@ internal unsafe static extern IntPtr //==================================================================== #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); + [DllImport(PythonDll, EntryPoint = "PyNumber_Long")] + internal static extern IntPtr PyNumber_Int(IntPtr ob); #elif PYTHON2 - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyNumber_Int(IntPtr ob); + [DllImport(PythonDll)] + internal static extern IntPtr PyNumber_Int(IntPtr ob); #endif - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyNumber_Long(IntPtr ob); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyNumber_Float(IntPtr ob); - + [DllImport(PythonDll)] + internal static extern IntPtr PyNumber_Long(IntPtr ob); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern bool - PyNumber_Check(IntPtr ob); + [DllImport(PythonDll)] + internal static extern IntPtr PyNumber_Float(IntPtr ob); + [DllImport(PythonDll)] + internal static extern bool PyNumber_Check(IntPtr ob); internal static bool PyInt_Check(IntPtr ob) { - return PyObject_TypeCheck(ob, Runtime.PyIntType); + return PyObject_TypeCheck(ob, PyIntType); } internal static bool PyBool_Check(IntPtr ob) { - return PyObject_TypeCheck(ob, Runtime.PyBoolType); + return PyObject_TypeCheck(ob, PyBoolType); } internal static IntPtr PyInt_FromInt32(int value) { - IntPtr v = new IntPtr(value); + var v = new IntPtr(value); return PyInt_FromLong(v); } internal static IntPtr PyInt_FromInt64(long value) { - IntPtr v = new IntPtr(value); + var v = new IntPtr(value); return PyInt_FromLong(v); } #if PYTHON3 - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyLong_FromLong", - ExactSpelling = true, CharSet = CharSet.Ansi)] - private unsafe static extern IntPtr - PyInt_FromLong(IntPtr value); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyLong_AsLong", - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyInt_AsLong(IntPtr value); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyLong_FromString", - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyInt_FromString(string value, IntPtr end, int radix); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyLong_GetMax", - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyInt_GetMax(); + [DllImport(PythonDll, EntryPoint = "PyLong_FromLong")] + private static extern IntPtr PyInt_FromLong(IntPtr value); + + [DllImport(PythonDll, EntryPoint = "PyLong_AsLong")] + internal static extern int PyInt_AsLong(IntPtr value); + + [DllImport(PythonDll, EntryPoint = "PyLong_FromString")] + internal static extern IntPtr PyInt_FromString(string value, IntPtr end, int radix); + + [DllImport(PythonDll, EntryPoint = "PyLong_GetMax")] + internal static extern int PyInt_GetMax(); #elif PYTHON2 + [DllImport(PythonDll)] + private static extern IntPtr PyInt_FromLong(IntPtr value); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - private unsafe static extern IntPtr - PyInt_FromLong(IntPtr value); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyInt_AsLong(IntPtr value); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyInt_FromString(string value, IntPtr end, int radix); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyInt_GetMax(); + [DllImport(PythonDll)] + internal static extern int PyInt_AsLong(IntPtr value); + + [DllImport(PythonDll)] + internal static extern IntPtr PyInt_FromString(string value, IntPtr end, int radix); + + [DllImport(PythonDll)] + internal static extern int PyInt_GetMax(); #endif internal static bool PyLong_Check(IntPtr ob) { - return PyObject_TYPE(ob) == Runtime.PyLongType; + return PyObject_TYPE(ob) == PyLongType; } - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyLong_FromLong(long value); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyLong_FromUnsignedLong(uint value); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyLong_FromDouble(double value); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyLong_FromLongLong(long value); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyLong_FromUnsignedLongLong(ulong value); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyLong_FromString(string value, IntPtr end, int radix); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyLong_AsLong(IntPtr value); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern uint - PyLong_AsUnsignedLong(IntPtr value); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern long - PyLong_AsLongLong(IntPtr value); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern ulong - PyLong_AsUnsignedLongLong(IntPtr value); + [DllImport(PythonDll)] + internal static extern IntPtr PyLong_FromLong(long value); + + [DllImport(PythonDll)] + internal static extern IntPtr PyLong_FromUnsignedLong(uint value); + + [DllImport(PythonDll)] + internal static extern IntPtr PyLong_FromDouble(double value); + + [DllImport(PythonDll)] + internal static extern IntPtr PyLong_FromLongLong(long value); + + [DllImport(PythonDll)] + internal static extern IntPtr PyLong_FromUnsignedLongLong(ulong value); + + [DllImport(PythonDll)] + internal static extern IntPtr PyLong_FromString(string value, IntPtr end, int radix); + + [DllImport(PythonDll)] + internal static extern int PyLong_AsLong(IntPtr value); + [DllImport(PythonDll)] + internal static extern uint PyLong_AsUnsignedLong(IntPtr value); + + [DllImport(PythonDll)] + internal static extern long PyLong_AsLongLong(IntPtr value); + + [DllImport(PythonDll)] + internal static extern ulong PyLong_AsUnsignedLongLong(IntPtr value); internal static bool PyFloat_Check(IntPtr ob) { - return PyObject_TYPE(ob) == Runtime.PyFloatType; + return PyObject_TYPE(ob) == PyFloatType; } - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyFloat_FromDouble(double value); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyFloat_FromString(IntPtr value, IntPtr junk); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern double - PyFloat_AsDouble(IntPtr ob); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyNumber_Add(IntPtr o1, IntPtr o2); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyNumber_Subtract(IntPtr o1, IntPtr o2); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyNumber_Multiply(IntPtr o1, IntPtr o2); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyNumber_Divide(IntPtr o1, IntPtr o2); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyNumber_And(IntPtr o1, IntPtr o2); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyNumber_Xor(IntPtr o1, IntPtr o2); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyNumber_Or(IntPtr o1, IntPtr o2); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyNumber_Lshift(IntPtr o1, IntPtr o2); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyNumber_Rshift(IntPtr o1, IntPtr o2); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyNumber_Power(IntPtr o1, IntPtr o2); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyNumber_Remainder(IntPtr o1, IntPtr o2); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyNumber_InPlaceAdd(IntPtr o1, IntPtr o2); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyNumber_InPlaceSubtract(IntPtr o1, IntPtr o2); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyNumber_InPlaceMultiply(IntPtr o1, IntPtr o2); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyNumber_InPlaceDivide(IntPtr o1, IntPtr o2); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyNumber_InPlaceAnd(IntPtr o1, IntPtr o2); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyNumber_InPlaceXor(IntPtr o1, IntPtr o2); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyNumber_InPlaceOr(IntPtr o1, IntPtr o2); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyNumber_InPlaceLshift(IntPtr o1, IntPtr o2); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyNumber_InPlaceRshift(IntPtr o1, IntPtr o2); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyNumber_InPlacePower(IntPtr o1, IntPtr o2); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyNumber_InPlaceRemainder(IntPtr o1, IntPtr o2); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyNumber_Negative(IntPtr o1); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyNumber_Positive(IntPtr o1); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyNumber_Invert(IntPtr o1); + [DllImport(PythonDll)] + internal static extern IntPtr PyFloat_FromDouble(double value); + + [DllImport(PythonDll)] + internal static extern IntPtr PyFloat_FromString(IntPtr value, IntPtr junk); + + [DllImport(PythonDll)] + internal static extern double PyFloat_AsDouble(IntPtr ob); + + [DllImport(PythonDll)] + internal static extern IntPtr PyNumber_Add(IntPtr o1, IntPtr o2); + + [DllImport(PythonDll)] + internal static extern IntPtr PyNumber_Subtract(IntPtr o1, IntPtr o2); + + [DllImport(PythonDll)] + internal static extern IntPtr PyNumber_Multiply(IntPtr o1, IntPtr o2); + + [DllImport(PythonDll)] + internal static extern IntPtr PyNumber_Divide(IntPtr o1, IntPtr o2); + + [DllImport(PythonDll)] + internal static extern IntPtr PyNumber_And(IntPtr o1, IntPtr o2); + + [DllImport(PythonDll)] + internal static extern IntPtr PyNumber_Xor(IntPtr o1, IntPtr o2); + + [DllImport(PythonDll)] + internal static extern IntPtr PyNumber_Or(IntPtr o1, IntPtr o2); + + [DllImport(PythonDll)] + internal static extern IntPtr PyNumber_Lshift(IntPtr o1, IntPtr o2); + + [DllImport(PythonDll)] + internal static extern IntPtr PyNumber_Rshift(IntPtr o1, IntPtr o2); + + [DllImport(PythonDll)] + internal static extern IntPtr PyNumber_Power(IntPtr o1, IntPtr o2); + + [DllImport(PythonDll)] + internal static extern IntPtr PyNumber_Remainder(IntPtr o1, IntPtr o2); + + [DllImport(PythonDll)] + internal static extern IntPtr PyNumber_InPlaceAdd(IntPtr o1, IntPtr o2); + + [DllImport(PythonDll)] + internal static extern IntPtr PyNumber_InPlaceSubtract(IntPtr o1, IntPtr o2); + + [DllImport(PythonDll)] + internal static extern IntPtr PyNumber_InPlaceMultiply(IntPtr o1, IntPtr o2); + + [DllImport(PythonDll)] + internal static extern IntPtr PyNumber_InPlaceDivide(IntPtr o1, IntPtr o2); + + [DllImport(PythonDll)] + internal static extern IntPtr PyNumber_InPlaceAnd(IntPtr o1, IntPtr o2); + + [DllImport(PythonDll)] + internal static extern IntPtr PyNumber_InPlaceXor(IntPtr o1, IntPtr o2); + + [DllImport(PythonDll)] + internal static extern IntPtr PyNumber_InPlaceOr(IntPtr o1, IntPtr o2); + + [DllImport(PythonDll)] + internal static extern IntPtr PyNumber_InPlaceLshift(IntPtr o1, IntPtr o2); + + [DllImport(PythonDll)] + internal static extern IntPtr PyNumber_InPlaceRshift(IntPtr o1, IntPtr o2); + + [DllImport(PythonDll)] + internal static extern IntPtr PyNumber_InPlacePower(IntPtr o1, IntPtr o2); + + [DllImport(PythonDll)] + internal static extern IntPtr PyNumber_InPlaceRemainder(IntPtr o1, IntPtr o2); + + [DllImport(PythonDll)] + internal static extern IntPtr PyNumber_Negative(IntPtr o1); + + [DllImport(PythonDll)] + internal static extern IntPtr PyNumber_Positive(IntPtr o1); + + [DllImport(PythonDll)] + internal static extern IntPtr PyNumber_Invert(IntPtr o1); + //==================================================================== // Python sequence API //==================================================================== - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern bool - PySequence_Check(IntPtr pointer); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PySequence_GetItem(IntPtr pointer, int index); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PySequence_SetItem(IntPtr pointer, int index, IntPtr value); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PySequence_DelItem(IntPtr pointer, int index); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PySequence_GetSlice(IntPtr pointer, int i1, int i2); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PySequence_SetSlice(IntPtr pointer, int i1, int i2, IntPtr v); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PySequence_DelSlice(IntPtr pointer, int i1, int i2); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PySequence_Size(IntPtr pointer); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PySequence_Contains(IntPtr pointer, IntPtr item); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PySequence_Concat(IntPtr pointer, IntPtr other); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PySequence_Repeat(IntPtr pointer, int count); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PySequence_Index(IntPtr pointer, IntPtr item); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PySequence_Count(IntPtr pointer, IntPtr value); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PySequence_Tuple(IntPtr pointer); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PySequence_List(IntPtr pointer); + [DllImport(PythonDll)] + internal static extern bool PySequence_Check(IntPtr pointer); + + [DllImport(PythonDll)] + internal static extern IntPtr PySequence_GetItem(IntPtr pointer, int index); + + [DllImport(PythonDll)] + internal static extern int PySequence_SetItem(IntPtr pointer, int index, IntPtr value); + + [DllImport(PythonDll)] + internal static extern int PySequence_DelItem(IntPtr pointer, int index); + + [DllImport(PythonDll)] + internal static extern IntPtr PySequence_GetSlice(IntPtr pointer, int i1, int i2); + + [DllImport(PythonDll)] + internal static extern int PySequence_SetSlice(IntPtr pointer, int i1, int i2, IntPtr v); + + [DllImport(PythonDll)] + internal static extern int PySequence_DelSlice(IntPtr pointer, int i1, int i2); + + [DllImport(PythonDll)] + internal static extern int PySequence_Size(IntPtr pointer); + + [DllImport(PythonDll)] + internal static extern int PySequence_Contains(IntPtr pointer, IntPtr item); + + [DllImport(PythonDll)] + internal static extern IntPtr PySequence_Concat(IntPtr pointer, IntPtr other); + + [DllImport(PythonDll)] + internal static extern IntPtr PySequence_Repeat(IntPtr pointer, int count); + + [DllImport(PythonDll)] + internal static extern int PySequence_Index(IntPtr pointer, IntPtr item); + + [DllImport(PythonDll)] + internal static extern int PySequence_Count(IntPtr pointer, IntPtr value); + + [DllImport(PythonDll)] + internal static extern IntPtr PySequence_Tuple(IntPtr pointer); + + [DllImport(PythonDll)] + internal static extern IntPtr PySequence_List(IntPtr pointer); //==================================================================== @@ -1482,7 +1141,7 @@ internal static bool IsStringType(IntPtr op) internal static bool PyString_Check(IntPtr ob) { - return PyObject_TYPE(ob) == Runtime.PyStringType; + return PyObject_TYPE(ob) == PyStringType; } internal static IntPtr PyString_FromString(string value) @@ -1491,409 +1150,191 @@ internal static IntPtr PyString_FromString(string value) } #if PYTHON3 - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyBytes_FromString(string op); + [DllImport(PythonDll)] + internal static extern IntPtr PyBytes_FromString(string op); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyBytes_Size(IntPtr op); + [DllImport(PythonDll)] + internal static extern int PyBytes_Size(IntPtr op); internal static IntPtr PyBytes_AS_STRING(IntPtr ob) { return ob + BytesOffset.ob_sval; } - internal static IntPtr PyString_FromStringAndSize(string value, int length) - { - // copy the string into an unmanaged UTF-8 buffer - int len = Encoding.UTF8.GetByteCount(value); - byte[] buffer = new byte[len + 1]; - Encoding.UTF8.GetBytes(value, 0, value.Length, buffer, 0); - IntPtr nativeUtf8 = Marshal.AllocHGlobal(buffer.Length); - try - { - Marshal.Copy(buffer, 0, nativeUtf8, buffer.Length); - return PyUnicode_FromStringAndSize(nativeUtf8, length); - } - finally - { - Marshal.FreeHGlobal(nativeUtf8); - } - } + [DllImport(PythonDll, EntryPoint = "PyUnicode_FromStringAndSize")] + internal static extern IntPtr PyString_FromStringAndSize( + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(Utf8Marshaler))] string value, + int size + ); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Unicode)] - internal unsafe static extern IntPtr - PyUnicode_FromStringAndSize(IntPtr value, int size); + [DllImport(PythonDll)] + internal static extern IntPtr PyUnicode_FromStringAndSize(IntPtr value, int size); #elif PYTHON2 - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyString_FromStringAndSize(string value, int size); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyString_AsString", - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyString_AS_STRING(IntPtr op); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyString_Size(IntPtr pointer); + [DllImport(PythonDll)] + internal static extern IntPtr PyString_FromStringAndSize(string value, int size); + + [DllImport(PythonDll)] + internal static extern IntPtr PyString_AsString(IntPtr op); + + [DllImport(PythonDll)] + internal static extern int PyString_Size(IntPtr pointer); #endif internal static bool PyUnicode_Check(IntPtr ob) { - return PyObject_TYPE(ob) == Runtime.PyUnicodeType; + return PyObject_TYPE(ob) == PyUnicodeType; } -#if UCS2 && PYTHON3 - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Unicode)] - internal unsafe static extern IntPtr - PyUnicode_FromObject(IntPtr ob); +#if PYTHON3 + [DllImport(PythonDll)] + internal static extern IntPtr PyUnicode_FromObject(IntPtr ob); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Unicode)] - internal unsafe static extern IntPtr - PyUnicode_FromEncodedObject(IntPtr ob, IntPtr enc, IntPtr err); + [DllImport(PythonDll)] + internal static extern IntPtr PyUnicode_FromEncodedObject(IntPtr ob, IntPtr enc, IntPtr err); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyUnicode_FromKindAndData", - ExactSpelling = true, - CharSet = CharSet.Unicode)] - internal unsafe static extern IntPtr - PyUnicode_FromKindAndString(int kind, string s, int size); + [DllImport(PythonDll)] + internal static extern IntPtr PyUnicode_FromKindAndData( + int kind, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UcsMarshaler))] string s, + int size + ); internal static IntPtr PyUnicode_FromUnicode(string s, int size) { - return PyUnicode_FromKindAndString(2, s, size); + return PyUnicode_FromKindAndData(UCS, s, size); } - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Unicode)] - internal unsafe static extern int - PyUnicode_GetSize(IntPtr ob); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Unicode)] - internal unsafe static extern char* - PyUnicode_AsUnicode(IntPtr ob); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyUnicode_AsUnicode", - ExactSpelling = true, CharSet = CharSet.Unicode)] - internal unsafe static extern IntPtr - PyUnicode_AS_UNICODE(IntPtr op); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Unicode)] - internal unsafe static extern IntPtr - PyUnicode_FromOrdinal(int c); -#elif UCS2 && PYTHON2 - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyUnicodeUCS2_FromObject", - ExactSpelling = true, CharSet = CharSet.Unicode)] - internal unsafe static extern IntPtr - PyUnicode_FromObject(IntPtr ob); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyUnicodeUCS2_FromEncodedObject", - ExactSpelling = true, CharSet = CharSet.Unicode)] - internal unsafe static extern IntPtr - PyUnicode_FromEncodedObject(IntPtr ob, IntPtr enc, IntPtr err); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyUnicodeUCS2_FromUnicode", - ExactSpelling = true, CharSet = CharSet.Unicode)] - internal unsafe static extern IntPtr - PyUnicode_FromUnicode(string s, int size); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyUnicodeUCS2_GetSize", - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyUnicode_GetSize(IntPtr ob); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyUnicodeUCS2_AsUnicode", - ExactSpelling = true)] - internal unsafe static extern char* - PyUnicode_AsUnicode(IntPtr ob); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyUnicodeUCS2_AsUnicode", - ExactSpelling = true, CharSet = CharSet.Unicode)] - internal unsafe static extern IntPtr - PyUnicode_AS_UNICODE(IntPtr op); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyUnicodeUCS2_FromOrdinal", - ExactSpelling = true, CharSet = CharSet.Unicode)] - internal unsafe static extern IntPtr - PyUnicode_FromOrdinal(int c); -#elif UCS4 && PYTHON3 - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Unicode)] - internal unsafe static extern IntPtr - PyUnicode_FromObject(IntPtr ob); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Unicode)] - internal unsafe static extern IntPtr - PyUnicode_FromEncodedObject(IntPtr ob, IntPtr enc, IntPtr err); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyUnicode_FromKindAndData", - ExactSpelling = true)] - internal unsafe static extern IntPtr - PyUnicode_FromKindAndString(int kind, - IntPtr s, - int size); - - internal static unsafe IntPtr PyUnicode_FromKindAndString(int kind, - string s, - int size) - { - var bufLength = Math.Max(s.Length, size) * 4; + [DllImport(PythonDll)] + internal static extern int PyUnicode_GetSize(IntPtr ob); - IntPtr mem = Marshal.AllocHGlobal(bufLength); - try - { - fixed (char* ps = s) - { - Encoding.UTF32.GetBytes(ps, s.Length, (byte*)mem, bufLength); - } + [DllImport(PythonDll)] + internal static extern IntPtr PyUnicode_AsUnicode(IntPtr ob); - var result = PyUnicode_FromKindAndString(kind, mem, size); - return result; - } - finally - { - Marshal.FreeHGlobal(mem); - } - } + [DllImport(PythonDll)] + internal static extern IntPtr PyUnicode_FromOrdinal(int c); +#elif PYTHON2 + [DllImport(PythonDll, EntryPoint = PyUnicodeEntryPoint + "FromObject")] + internal static extern IntPtr PyUnicode_FromObject(IntPtr ob); - internal static IntPtr PyUnicode_FromUnicode(string s, int size) - { - return PyUnicode_FromKindAndString(4, s, size); - } + [DllImport(PythonDll, EntryPoint = PyUnicodeEntryPoint + "FromEncodedObject")] + internal static extern IntPtr PyUnicode_FromEncodedObject(IntPtr ob, IntPtr enc, IntPtr err); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyUnicode_GetSize(IntPtr ob); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true)] - internal unsafe static extern IntPtr - PyUnicode_AsUnicode(IntPtr ob); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyUnicode_AsUnicode", - ExactSpelling = true, CharSet = CharSet.Unicode)] - internal unsafe static extern IntPtr - PyUnicode_AS_UNICODE(IntPtr op); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Unicode)] - internal unsafe static extern IntPtr - PyUnicode_FromOrdinal(int c); -#elif UCS4 && PYTHON2 - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyUnicodeUCS4_FromObject", - ExactSpelling = true, CharSet = CharSet.Unicode)] - internal unsafe static extern IntPtr - PyUnicode_FromObject(IntPtr ob); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyUnicodeUCS4_FromEncodedObject", - ExactSpelling = true, CharSet = CharSet.Unicode)] - internal unsafe static extern IntPtr - PyUnicode_FromEncodedObject(IntPtr ob, IntPtr enc, IntPtr err); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyUnicodeUCS4_FromUnicode", - ExactSpelling = true)] - internal unsafe static extern IntPtr - PyUnicode_FromUnicode(IntPtr s, int size); - - internal static unsafe IntPtr PyUnicode_FromUnicode(string s, int size) - { - var bufLength = Math.Max(s.Length, size) * 4; + [DllImport(PythonDll, EntryPoint = PyUnicodeEntryPoint + "FromUnicode")] + internal static extern IntPtr PyUnicode_FromUnicode( + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(UcsMarshaler))] string s, + int size + ); - IntPtr mem = Marshal.AllocHGlobal(bufLength); - try - { - fixed (char* ps = s) - { - Encoding.UTF32.GetBytes(ps, s.Length, (byte*)mem, bufLength); - } + [DllImport(PythonDll, EntryPoint = PyUnicodeEntryPoint + "GetSize")] + internal static extern int PyUnicode_GetSize(IntPtr ob); - var result = PyUnicode_FromUnicode(mem, size); - return result; - } - finally - { - Marshal.FreeHGlobal(mem); - } - } + [DllImport(PythonDll, EntryPoint = PyUnicodeEntryPoint + "AsUnicode")] + internal static extern IntPtr PyUnicode_AsUnicode(IntPtr ob); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyUnicodeUCS4_GetSize", - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyUnicode_GetSize(IntPtr ob); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyUnicodeUCS4_AsUnicode", - ExactSpelling = true)] - internal unsafe static extern IntPtr - PyUnicode_AsUnicode(IntPtr ob); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyUnicodeUCS4_AsUnicode", - ExactSpelling = true, CharSet = CharSet.Unicode)] - internal unsafe static extern IntPtr - PyUnicode_AS_UNICODE(IntPtr op); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - EntryPoint = "PyUnicodeUCS4_FromOrdinal", - ExactSpelling = true, CharSet = CharSet.Unicode)] - internal unsafe static extern IntPtr - PyUnicode_FromOrdinal(int c); + [DllImport(PythonDll, EntryPoint = PyUnicodeEntryPoint + "FromOrdinal")] + internal static extern IntPtr PyUnicode_FromOrdinal(int c); #endif internal static IntPtr PyUnicode_FromString(string s) { - return PyUnicode_FromUnicode(s, (s.Length)); + return PyUnicode_FromUnicode(s, s.Length); } - internal unsafe static string GetManagedString(IntPtr op) + /// + /// Function to access the internal PyUnicode/PyString object and + /// convert it to a managed string with the correct encoding. + /// + /// + /// We can't easily do this through through the CustomMarshaler's on + /// the returns because will have access to the IntPtr but not size. + /// + /// For PyUnicodeType, we can't convert with Marshal.PtrToStringUni + /// since it only works for UCS2. + /// + /// PyStringType or PyUnicodeType object to convert + /// Managed String + internal static string GetManagedString(IntPtr op) { IntPtr type = PyObject_TYPE(op); #if PYTHON2 // Python 3 strings are all Unicode - if (type == Runtime.PyStringType) + if (type == PyStringType) { - return Marshal.PtrToStringAnsi( - PyString_AS_STRING(op), - Runtime.PyString_Size(op) - ); + return Marshal.PtrToStringAnsi(PyString_AsString(op), PyString_Size(op)); } #endif - if (type == Runtime.PyUnicodeType) + if (type == PyUnicodeType) { -#if UCS4 - IntPtr p = Runtime.PyUnicode_AsUnicode(op); - int length = Runtime.PyUnicode_GetSize(op); - int size = length * 4; - byte[] buffer = new byte[size]; + IntPtr p = PyUnicode_AsUnicode(op); + int length = PyUnicode_GetSize(op); + + int size = length * UCS; + var buffer = new byte[size]; Marshal.Copy(p, buffer, 0, size); - return Encoding.UTF32.GetString(buffer, 0, size); -#elif UCS2 - char* p = Runtime.PyUnicode_AsUnicode(op); - int size = Runtime.PyUnicode_GetSize(op); - return new String(p, 0, size); -#endif + return PyEncoding.GetString(buffer, 0, size); } return null; } + //==================================================================== // Python dictionary API //==================================================================== internal static bool PyDict_Check(IntPtr ob) { - return PyObject_TYPE(ob) == Runtime.PyDictType; + return PyObject_TYPE(ob) == PyDictType; } - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyDict_New(); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyDictProxy_New(IntPtr dict); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyDict_GetItem(IntPtr pointer, IntPtr key); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyDict_GetItemString(IntPtr pointer, string key); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyDict_SetItem(IntPtr pointer, IntPtr key, IntPtr value); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyDict_SetItemString(IntPtr pointer, string key, IntPtr value); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyDict_DelItem(IntPtr pointer, IntPtr key); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyDict_DelItemString(IntPtr pointer, string key); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyMapping_HasKey(IntPtr pointer, IntPtr key); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyDict_Keys(IntPtr pointer); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyDict_Values(IntPtr pointer); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyDict_Items(IntPtr pointer); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyDict_Copy(IntPtr pointer); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyDict_Update(IntPtr pointer, IntPtr other); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - PyDict_Clear(IntPtr pointer); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyDict_Size(IntPtr pointer); + [DllImport(PythonDll)] + internal static extern IntPtr PyDict_New(); + + [DllImport(PythonDll)] + internal static extern IntPtr PyDictProxy_New(IntPtr dict); + + [DllImport(PythonDll)] + internal static extern IntPtr PyDict_GetItem(IntPtr pointer, IntPtr key); + + [DllImport(PythonDll)] + internal static extern IntPtr PyDict_GetItemString(IntPtr pointer, string key); + + [DllImport(PythonDll)] + internal static extern int PyDict_SetItem(IntPtr pointer, IntPtr key, IntPtr value); + + [DllImport(PythonDll)] + internal static extern int PyDict_SetItemString(IntPtr pointer, string key, IntPtr value); + + [DllImport(PythonDll)] + internal static extern int PyDict_DelItem(IntPtr pointer, IntPtr key); + + [DllImport(PythonDll)] + internal static extern int PyDict_DelItemString(IntPtr pointer, string key); + + [DllImport(PythonDll)] + internal static extern int PyMapping_HasKey(IntPtr pointer, IntPtr key); + + [DllImport(PythonDll)] + internal static extern IntPtr PyDict_Keys(IntPtr pointer); + + [DllImport(PythonDll)] + internal static extern IntPtr PyDict_Values(IntPtr pointer); + + [DllImport(PythonDll)] + internal static extern IntPtr PyDict_Items(IntPtr pointer); + + [DllImport(PythonDll)] + internal static extern IntPtr PyDict_Copy(IntPtr pointer); + + [DllImport(PythonDll)] + internal static extern int PyDict_Update(IntPtr pointer, IntPtr other); + + [DllImport(PythonDll)] + internal static extern void PyDict_Clear(IntPtr pointer); + + [DllImport(PythonDll)] + internal static extern int PyDict_Size(IntPtr pointer); //==================================================================== @@ -1902,63 +1343,41 @@ internal unsafe static extern int internal static bool PyList_Check(IntPtr ob) { - return PyObject_TYPE(ob) == Runtime.PyListType; + return PyObject_TYPE(ob) == PyListType; } - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyList_New(int size); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyList_AsTuple(IntPtr pointer); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyList_GetItem(IntPtr pointer, int index); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyList_SetItem(IntPtr pointer, int index, IntPtr value); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyList_Insert(IntPtr pointer, int index, IntPtr value); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyList_Append(IntPtr pointer, IntPtr value); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyList_Reverse(IntPtr pointer); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyList_Sort(IntPtr pointer); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyList_GetSlice(IntPtr pointer, int start, int end); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyList_SetSlice(IntPtr pointer, int start, int end, IntPtr value); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyList_Size(IntPtr pointer); + [DllImport(PythonDll)] + internal static extern IntPtr PyList_New(int size); + + [DllImport(PythonDll)] + internal static extern IntPtr PyList_AsTuple(IntPtr pointer); + + [DllImport(PythonDll)] + internal static extern IntPtr PyList_GetItem(IntPtr pointer, int index); + + [DllImport(PythonDll)] + internal static extern int PyList_SetItem(IntPtr pointer, int index, IntPtr value); + + [DllImport(PythonDll)] + internal static extern int PyList_Insert(IntPtr pointer, int index, IntPtr value); + + [DllImport(PythonDll)] + internal static extern int PyList_Append(IntPtr pointer, IntPtr value); + + [DllImport(PythonDll)] + internal static extern int PyList_Reverse(IntPtr pointer); + + [DllImport(PythonDll)] + internal static extern int PyList_Sort(IntPtr pointer); + + [DllImport(PythonDll)] + internal static extern IntPtr PyList_GetSlice(IntPtr pointer, int start, int end); + + [DllImport(PythonDll)] + internal static extern int PyList_SetSlice(IntPtr pointer, int start, int end, IntPtr value); + + [DllImport(PythonDll)] + internal static extern int PyList_Size(IntPtr pointer); //==================================================================== @@ -1967,33 +1386,23 @@ internal unsafe static extern int internal static bool PyTuple_Check(IntPtr ob) { - return PyObject_TYPE(ob) == Runtime.PyTupleType; + return PyObject_TYPE(ob) == PyTupleType; } - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyTuple_New(int size); + [DllImport(PythonDll)] + internal static extern IntPtr PyTuple_New(int size); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyTuple_GetItem(IntPtr pointer, int index); + [DllImport(PythonDll)] + internal static extern IntPtr PyTuple_GetItem(IntPtr pointer, int index); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyTuple_SetItem(IntPtr pointer, int index, IntPtr value); + [DllImport(PythonDll)] + internal static extern int PyTuple_SetItem(IntPtr pointer, int index, IntPtr value); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyTuple_GetSlice(IntPtr pointer, int start, int end); + [DllImport(PythonDll)] + internal static extern IntPtr PyTuple_GetSlice(IntPtr pointer, int start, int end); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyTuple_Size(IntPtr pointer); + [DllImport(PythonDll)] + internal static extern int PyTuple_Size(IntPtr pointer); //==================================================================== @@ -2001,110 +1410,78 @@ internal unsafe static extern int //==================================================================== #if PYTHON2 - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern bool - PyIter_Check(IntPtr pointer); + [DllImport(PythonDll)] + internal static extern bool PyIter_Check(IntPtr pointer); #elif PYTHON3 - internal static bool - PyIter_Check(IntPtr pointer) + internal static bool PyIter_Check(IntPtr pointer) { - IntPtr ob_type = (IntPtr)Marshal.PtrToStructure(pointer + ObjectOffset.ob_type, typeof(IntPtr)); + var ob_type = (IntPtr)Marshal.PtrToStructure(pointer + ObjectOffset.ob_type, typeof(IntPtr)); IntPtr tp_iternext = ob_type + TypeOffset.tp_iternext; return tp_iternext != null && tp_iternext != _PyObject_NextNotImplemented; } #endif - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyIter_Next(IntPtr pointer); + [DllImport(PythonDll)] + internal static extern IntPtr PyIter_Next(IntPtr pointer); + //==================================================================== // Python module API //==================================================================== - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyModule_New(string name); + [DllImport(PythonDll)] + internal static extern IntPtr PyModule_New(string name); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern string - PyModule_GetName(IntPtr module); + [DllImport(PythonDll)] + internal static extern string PyModule_GetName(IntPtr module); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyModule_GetDict(IntPtr module); + [DllImport(PythonDll)] + internal static extern IntPtr PyModule_GetDict(IntPtr module); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern string - PyModule_GetFilename(IntPtr module); + [DllImport(PythonDll)] + internal static extern string PyModule_GetFilename(IntPtr module); #if PYTHON3 - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyModule_Create2(IntPtr module, int apiver); + [DllImport(PythonDll)] + internal static extern IntPtr PyModule_Create2(IntPtr module, int apiver); #endif - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyImport_Import(IntPtr name); + [DllImport(PythonDll)] + internal static extern IntPtr PyImport_Import(IntPtr name); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyImport_ImportModule(string name); + [DllImport(PythonDll)] + internal static extern IntPtr PyImport_ImportModule(string name); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyImport_ReloadModule(IntPtr module); + [DllImport(PythonDll)] + internal static extern IntPtr PyImport_ReloadModule(IntPtr module); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyImport_AddModule(string name); + [DllImport(PythonDll)] + internal static extern IntPtr PyImport_AddModule(string name); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyImport_GetModuleDict(); + [DllImport(PythonDll)] + internal static extern IntPtr PyImport_GetModuleDict(); #if PYTHON3 - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - PySys_SetArgvEx( - int argc, - [MarshalAsAttribute(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)] string[] argv, - int updatepath - ); + [DllImport(PythonDll)] + internal static extern void PySys_SetArgvEx( + int argc, + [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(StrArrayMarshaler))] string[] argv, + int updatepath + ); #elif PYTHON2 - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - PySys_SetArgvEx( - int argc, - string[] argv, - int updatepath - ); + [DllImport(PythonDll)] + internal static extern void PySys_SetArgvEx( + int argc, + string[] argv, + int updatepath + ); #endif - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PySys_GetObject(string name); + [DllImport(PythonDll)] + internal static extern IntPtr PySys_GetObject(string name); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PySys_SetObject(string name, IntPtr ob); + [DllImport(PythonDll)] + internal static extern int PySys_SetObject(string name, IntPtr ob); //==================================================================== @@ -2113,18 +1490,14 @@ internal unsafe static extern int internal static bool PyType_Check(IntPtr ob) { - return PyObject_TypeCheck(ob, Runtime.PyTypeType); + return PyObject_TypeCheck(ob, PyTypeType); } - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - PyType_Modified(IntPtr type); + [DllImport(PythonDll)] + internal static extern void PyType_Modified(IntPtr type); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern bool - PyType_IsSubtype(IntPtr t1, IntPtr t2); + [DllImport(PythonDll)] + internal static extern bool PyType_IsSubtype(IntPtr t1, IntPtr t2); internal static bool PyObject_TypeCheck(IntPtr ob, IntPtr tp) { @@ -2132,159 +1505,103 @@ internal static bool PyObject_TypeCheck(IntPtr ob, IntPtr tp) return (t == tp) || PyType_IsSubtype(t, tp); } - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyType_GenericNew(IntPtr type, IntPtr args, IntPtr kw); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyType_GenericAlloc(IntPtr type, int n); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyType_Ready(IntPtr type); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - _PyType_Lookup(IntPtr type, IntPtr name); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyObject_GenericGetAttr(IntPtr obj, IntPtr name); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyObject_GenericSetAttr(IntPtr obj, IntPtr name, IntPtr value); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - _PyObject_GetDictPtr(IntPtr obj); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyObject_GC_New(IntPtr tp); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - PyObject_GC_Del(IntPtr tp); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - PyObject_GC_Track(IntPtr tp); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - PyObject_GC_UnTrack(IntPtr tp); + [DllImport(PythonDll)] + internal static extern IntPtr PyType_GenericNew(IntPtr type, IntPtr args, IntPtr kw); + + [DllImport(PythonDll)] + internal static extern IntPtr PyType_GenericAlloc(IntPtr type, int n); + + [DllImport(PythonDll)] + internal static extern int PyType_Ready(IntPtr type); + + [DllImport(PythonDll)] + internal static extern IntPtr _PyType_Lookup(IntPtr type, IntPtr name); + + [DllImport(PythonDll)] + internal static extern IntPtr PyObject_GenericGetAttr(IntPtr obj, IntPtr name); + + [DllImport(PythonDll)] + internal static extern int PyObject_GenericSetAttr(IntPtr obj, IntPtr name, IntPtr value); + + [DllImport(PythonDll)] + internal static extern IntPtr _PyObject_GetDictPtr(IntPtr obj); + + [DllImport(PythonDll)] + internal static extern IntPtr PyObject_GC_New(IntPtr tp); + + [DllImport(PythonDll)] + internal static extern void PyObject_GC_Del(IntPtr tp); + + [DllImport(PythonDll)] + internal static extern void PyObject_GC_Track(IntPtr tp); + + [DllImport(PythonDll)] + internal static extern void PyObject_GC_UnTrack(IntPtr tp); //==================================================================== // Python memory API //==================================================================== - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyMem_Malloc(int size); + [DllImport(PythonDll)] + internal static extern IntPtr PyMem_Malloc(int size); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyMem_Realloc(IntPtr ptr, int size); + [DllImport(PythonDll)] + internal static extern IntPtr PyMem_Realloc(IntPtr ptr, int size); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - PyMem_Free(IntPtr ptr); + [DllImport(PythonDll)] + internal static extern void PyMem_Free(IntPtr ptr); //==================================================================== // Python exception API //==================================================================== - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - PyErr_SetString(IntPtr ob, string message); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - PyErr_SetObject(IntPtr ob, IntPtr message); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyErr_SetFromErrno(IntPtr ob); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - PyErr_SetNone(IntPtr ob); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyErr_ExceptionMatches(IntPtr exception); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyErr_GivenExceptionMatches(IntPtr ob, IntPtr val); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - PyErr_NormalizeException(IntPtr ob, IntPtr val, IntPtr tb); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern int - PyErr_Occurred(); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - PyErr_Fetch(ref IntPtr ob, ref IntPtr val, ref IntPtr tb); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - PyErr_Restore(IntPtr ob, IntPtr val, IntPtr tb); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - PyErr_Clear(); - - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern void - PyErr_Print(); + [DllImport(PythonDll)] + internal static extern void PyErr_SetString(IntPtr ob, string message); + + [DllImport(PythonDll)] + internal static extern void PyErr_SetObject(IntPtr ob, IntPtr message); + + [DllImport(PythonDll)] + internal static extern IntPtr PyErr_SetFromErrno(IntPtr ob); + + [DllImport(PythonDll)] + internal static extern void PyErr_SetNone(IntPtr ob); + + [DllImport(PythonDll)] + internal static extern int PyErr_ExceptionMatches(IntPtr exception); + + [DllImport(PythonDll)] + internal static extern int PyErr_GivenExceptionMatches(IntPtr ob, IntPtr val); + + [DllImport(PythonDll)] + internal static extern void PyErr_NormalizeException(IntPtr ob, IntPtr val, IntPtr tb); + + [DllImport(PythonDll)] + internal static extern int PyErr_Occurred(); + + [DllImport(PythonDll)] + internal static extern void PyErr_Fetch(ref IntPtr ob, ref IntPtr val, ref IntPtr tb); + + [DllImport(PythonDll)] + internal static extern void PyErr_Restore(IntPtr ob, IntPtr val, IntPtr tb); + + [DllImport(PythonDll)] + internal static extern void PyErr_Clear(); + + [DllImport(PythonDll)] + internal static extern void PyErr_Print(); //==================================================================== // Miscellaneous //==================================================================== - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyMethod_Self(IntPtr ob); + [DllImport(PythonDll)] + internal static extern IntPtr PyMethod_Self(IntPtr ob); - [DllImport(Runtime.dll, CallingConvention = CallingConvention.Cdecl, - ExactSpelling = true, CharSet = CharSet.Ansi)] - internal unsafe static extern IntPtr - PyMethod_Function(IntPtr ob); + [DllImport(PythonDll)] + internal static extern IntPtr PyMethod_Function(IntPtr ob); } } diff --git a/src/runtime/typemanager.cs b/src/runtime/typemanager.cs index b3b065cc4..6f373f036 100644 --- a/src/runtime/typemanager.cs +++ b/src/runtime/typemanager.cs @@ -415,7 +415,7 @@ internal static IntPtr AllocateTypeObject(string name) temp = Runtime.PyUnicode_FromString(name); #elif PYTHON2 IntPtr temp = Runtime.PyString_FromString(name); - IntPtr raw = Runtime.PyString_AS_STRING(temp); + IntPtr raw = Runtime.PyString_AsString(temp); #endif Marshal.WriteIntPtr(type, TypeOffset.tp_name, raw); Marshal.WriteIntPtr(type, TypeOffset.name, temp); diff --git a/src/testing/Python.Test.csproj b/src/testing/Python.Test.csproj index 4ed9db680..ce8dca10d 100644 --- a/src/testing/Python.Test.csproj +++ b/src/testing/Python.Test.csproj @@ -13,8 +13,8 @@ 1591,0067 ..\..\ - $(SolutionDir) - + $(SolutionDir)\bin\ + 6 false ..\pythonnet.snk prompt @@ -31,7 +31,8 @@ full - + + true pdbonly @@ -41,7 +42,8 @@ full - + + true pdbonly @@ -51,7 +53,8 @@ full - + + true pdbonly @@ -61,7 +64,8 @@ full - + + true pdbonly @@ -103,7 +107,7 @@ $(TargetDir)$(TargetName).pdb - + diff --git a/src/testing/methodtest.cs b/src/testing/methodtest.cs index 7634c4839..83dc907c0 100644 --- a/src/testing/methodtest.cs +++ b/src/testing/methodtest.cs @@ -116,6 +116,71 @@ public static int[] TestOverloadedParams(int v, int[] args) return args; } + public static string TestOverloadedNoObject(int i) + { + return "Got int"; + } + + public static string TestOverloadedObject(int i) + { + return "Got int"; + } + + public static string TestOverloadedObject(object o) + { + return "Got object"; + } + + public static string TestOverloadedObjectTwo(int a, int b) + { + return "Got int-int"; + } + + public static string TestOverloadedObjectTwo(string a, string b) + { + return "Got string-string"; + } + + public static string TestOverloadedObjectTwo(string a, int b) + { + return "Got string-int"; + } + + public static string TestOverloadedObjectTwo(string a, object b) + { + return "Got string-object"; + } + + public static string TestOverloadedObjectTwo(int a, object b) + { + return "Got int-object"; + } + + public static string TestOverloadedObjectTwo(object a, int b) + { + return "Got object-int"; + } + + public static string TestOverloadedObjectTwo(object a, object b) + { + return "Got object-object"; + } + + public static string TestOverloadedObjectTwo(int a, string b) + { + return "Got int-string"; + } + + public static string TestOverloadedObjectThree(object a, int b) + { + return "Got object-int"; + } + + public static string TestOverloadedObjectThree(int a, object b) + { + return "Got int-object"; + } + public static bool TestStringOutParams(string s, out string s1) { s1 = "output string"; @@ -576,6 +641,16 @@ public static int Overloaded(int i, string s) { return i; } + + public static string CaseSensitive() + { + return "CaseSensitive"; + } + + public static string Casesensitive() + { + return "Casesensitive"; + } } diff --git a/src/tests/_compat.py b/src/tests/_compat.py index 3a9d48c7e..3751ca013 100644 --- a/src/tests/_compat.py +++ b/src/tests/_compat.py @@ -6,6 +6,7 @@ """ import operator +import subprocess import sys import types @@ -33,7 +34,7 @@ unicode = str # from nowhere import Nothing - cmp = lambda a, b: (a > b) - (a < b) # No Py3 equivalent + cmp = lambda a, b: (a > b) - (a < b) # No PY3 equivalent map = map range = range zip = zip @@ -63,3 +64,11 @@ map = imap range = xrange zip = izip + + +def check_output(*args, **kwargs): + """Check output wrapper for PY2/PY3 compatibility""" + output = subprocess.check_output(*args, **kwargs) + if PY2: + return output + return output.decode("ascii") diff --git a/src/tests/test_suite/_missing_import.py b/src/tests/_missing_import.py similarity index 100% rename from src/tests/test_suite/_missing_import.py rename to src/tests/_missing_import.py diff --git a/src/tests/conftest.py b/src/tests/conftest.py new file mode 100644 index 000000000..a93326c51 --- /dev/null +++ b/src/tests/conftest.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# TODO: move tests one out of src to project root. +# TODO: travis has numpy on their workers. Maybe add tests? + +"""Helpers for testing.""" + +import ctypes +import os +import sys +import sysconfig + +import pytest +import clr + +# Add path for `Python.Test` +cwd = os.path.dirname(__file__) +fixtures_path = os.path.join(cwd, "fixtures") +sys.path.append(fixtures_path) + +# Add References for tests +clr.AddReference("Python.Test") +clr.AddReference("System.Collections") +clr.AddReference("System.Data") + + +def pytest_report_header(config): + """Generate extra report headers""" + # FIXME: https://github.com/pytest-dev/pytest/issues/2257 + is_64bits = sys.maxsize > 2**32 + arch = "x64" if is_64bits else "x86" + ucs = ctypes.sizeof(ctypes.c_wchar) + libdir = sysconfig.get_config_var("LIBDIR") + shared = bool(sysconfig.get_config_var("Py_ENABLE_SHARED")) + + header = ("Arch: {arch}, UCS: {ucs}, LIBDIR: {libdir}, " + "Py_ENABLE_SHARED: {shared}".format(**locals())) + return header + + +@pytest.fixture() +def filepath(): + """Returns full filepath for file in `fixtures` directory.""" + + def make_filepath(filename): + # http://stackoverflow.com/questions/18011902/parameter-to-a-fixture + return os.path.join(fixtures_path, filename) + + return make_filepath diff --git a/src/tests/fixtures/.gitkeep b/src/tests/fixtures/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/src/tests/fixtures/argv-fixture.py b/src/tests/fixtures/argv-fixture.py new file mode 100644 index 000000000..d56dea4e0 --- /dev/null +++ b/src/tests/fixtures/argv-fixture.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- + +"""Helper script to test argv. +Ensures that argv isn't modified after importing clr. +For more details see GH#404 - argv not found""" + +from __future__ import print_function + +import sys +import clr + +print(sys.argv) diff --git a/src/tests/leaktest.py b/src/tests/leaktest.py index 646cb512e..05b76e867 100644 --- a/src/tests/leaktest.py +++ b/src/tests/leaktest.py @@ -10,10 +10,10 @@ import System -from _compat import range -from utils import (CallableHandler, ClassMethodHandler, GenericHandler, - HelloClass, StaticMethodHandler, VarCallableHandler, - VariableArgsHandler, hello_func) +from ._compat import range +from .utils import (CallableHandler, ClassMethodHandler, GenericHandler, + HelloClass, StaticMethodHandler, VarCallableHandler, + VariableArgsHandler, hello_func) class LeakTest(object): diff --git a/src/tests/profile.py b/src/tests/profile.py index f6576ddce..4af3589e8 100644 --- a/src/tests/profile.py +++ b/src/tests/profile.py @@ -14,7 +14,7 @@ import time import runtests -from _compat import range +from ._compat import range def main(): diff --git a/src/tests/runtests.py b/src/tests/runtests.py index 92d9ecbd0..8011d05e6 100644 --- a/src/tests/runtests.py +++ b/src/tests/runtests.py @@ -5,11 +5,10 @@ from __future__ import print_function -import os import sys -import unittest +import pytest -from _compat import input +from ._compat import input try: import System @@ -22,63 +21,16 @@ clr.AddReference("System.Data") clr.AddReference("System.Management") -test_modules = ( - # has to be first test before other module import clr - 'test_sysargv', - + +def main(verbosity=1): # test_module passes on its own, but not here if # other test modules that import System.Windows.Forms # run first. They must not do module level import/AddReference() # of the System.Windows.Forms namespace. - 'test_module', - - 'test_suite', - 'test_event', - 'test_constructors', - 'test_enum', - 'test_method', - 'test_exceptions', - 'test_compat', - 'test_generic', - 'test_conversion', - 'test_class', - 'test_interface', - 'test_field', - 'test_property', - 'test_indexer', - 'test_delegate', - 'test_array', - 'test_thread', - 'test_docstring', - - # FIXME: Has tests that are being skipped. - 'test_engine', - - # FIXME: Has tests that are being skipped. - 'test_subclass', -) - - -def remove_pyc(): - path = os.path.dirname(os.path.abspath(__file__)) - for name in test_modules: - pyc = os.path.join(path, "{0}.pyc".format(name)) - if os.path.isfile(pyc): - os.unlink(pyc) - - -def main(verbosity=1): - remove_pyc() - - suite = unittest.TestSuite() - - for name in test_modules: - module = __import__(name) - suite.addTests((module.test_suite(),)) - result = unittest.TextTestRunner(verbosity=verbosity).run(suite) - if not result.wasSuccessful(): - raise Exception("Tests failed") + # FIXME: test_engine has tests that are being skipped. + # FIXME: test_subclass has tests that are being skipped. + pytest.main() if __name__ == '__main__': diff --git a/src/tests/stress.py b/src/tests/stress.py index 2ffe06958..c6fa8b7e3 100644 --- a/src/tests/stress.py +++ b/src/tests/stress.py @@ -17,8 +17,8 @@ import threading import time -from _compat import range, thread -from utils import dprint +from ._compat import range, thread +from .utils import dprint class StressTest(object): diff --git a/src/tests/stresstest.py b/src/tests/stresstest.py index 947959239..74b863bdc 100644 --- a/src/tests/stresstest.py +++ b/src/tests/stresstest.py @@ -11,7 +11,7 @@ import unittest # import pdb -from _compat import range +from ._compat import range try: import System diff --git a/src/tests/test_array.py b/src/tests/test_array.py index 36f225c82..7ccadddff 100644 --- a/src/tests/test_array.py +++ b/src/tests/test_array.py @@ -1,1306 +1,1339 @@ # -*- coding: utf-8 -*- -import unittest +"""Test support for managed arrays.""" import Python.Test as Test import System +import pytest -from _compat import PY2, UserList, long, range, unichr +from ._compat import PY2, UserList, long, range, unichr -class ArrayTests(unittest.TestCase): - """Test support for managed arrays.""" +def test_public_array(): + """Test public arrays.""" + ob = Test.PublicArrayTest() + items = ob.items - def test_public_array(self): - """Test public arrays.""" - ob = Test.PublicArrayTest() - items = ob.items + assert len(items) == 5 - self.assertTrue(len(items) == 5) + assert items[0] == 0 + assert items[4] == 4 - self.assertTrue(items[0] == 0) - self.assertTrue(items[4] == 4) + items[0] = 8 + assert items[0] == 8 - items[0] = 8 - self.assertTrue(items[0] == 8) + items[4] = 9 + assert items[4] == 9 - items[4] = 9 - self.assertTrue(items[4] == 9) + items[-4] = 0 + assert items[-4] == 0 - items[-4] = 0 - self.assertTrue(items[-4] == 0) + items[-1] = 4 + assert items[-1] == 4 - items[-1] = 4 - self.assertTrue(items[-1] == 4) - def test_protected_array(self): - """Test protected arrays.""" - ob = Test.ProtectedArrayTest() - items = ob.items +def test_protected_array(): + """Test protected arrays.""" + ob = Test.ProtectedArrayTest() + items = ob.items - self.assertTrue(len(items) == 5) + assert len(items) == 5 - self.assertTrue(items[0] == 0) - self.assertTrue(items[4] == 4) + assert items[0] == 0 + assert items[4] == 4 - items[0] = 8 - self.assertTrue(items[0] == 8) + items[0] = 8 + assert items[0] == 8 - items[4] = 9 - self.assertTrue(items[4] == 9) + items[4] = 9 + assert items[4] == 9 - items[-4] = 0 - self.assertTrue(items[-4] == 0) + items[-4] = 0 + assert items[-4] == 0 - items[-1] = 4 - self.assertTrue(items[-1] == 4) + items[-1] = 4 + assert items[-1] == 4 - def test_internal_array(self): - """Test internal arrays.""" - with self.assertRaises(AttributeError): - ob = Test.InternalArrayTest() - _ = ob.items +def test_internal_array(): + """Test internal arrays.""" - def test_private_array(self): - """Test private arrays.""" + with pytest.raises(AttributeError): + ob = Test.InternalArrayTest() + _ = ob.items - with self.assertRaises(AttributeError): - ob = Test.PrivateArrayTest() - _ = ob.items - def test_array_bounds_checking(self): - """Test array bounds checking.""" +def test_private_array(): + """Test private arrays.""" - ob = Test.Int32ArrayTest() - items = ob.items + with pytest.raises(AttributeError): + ob = Test.PrivateArrayTest() + _ = ob.items - self.assertTrue(items[0] == 0) - self.assertTrue(items[1] == 1) - self.assertTrue(items[2] == 2) - self.assertTrue(items[3] == 3) - self.assertTrue(items[4] == 4) - self.assertTrue(items[-5] == 0) - self.assertTrue(items[-4] == 1) - self.assertTrue(items[-3] == 2) - self.assertTrue(items[-2] == 3) - self.assertTrue(items[-1] == 4) +def test_array_bounds_checking(): + """Test array bounds checking.""" - with self.assertRaises(IndexError): - ob = Test.Int32ArrayTest() - _ = ob.items[5] + ob = Test.Int32ArrayTest() + items = ob.items - with self.assertRaises(IndexError): - ob = Test.Int32ArrayTest() - ob.items[5] = 0 + assert items[0] == 0 + assert items[1] == 1 + assert items[2] == 2 + assert items[3] == 3 + assert items[4] == 4 - with self.assertRaises(IndexError): - ob = Test.Int32ArrayTest() - items[-6] + assert items[-5] == 0 + assert items[-4] == 1 + assert items[-3] == 2 + assert items[-2] == 3 + assert items[-1] == 4 - with self.assertRaises(IndexError): - ob = Test.Int32ArrayTest() - items[-6] = 0 + with pytest.raises(IndexError): + ob = Test.Int32ArrayTest() + _ = ob.items[5] - def test_array_contains(self): - """Test array support for __contains__.""" + with pytest.raises(IndexError): + ob = Test.Int32ArrayTest() + ob.items[5] = 0 + + with pytest.raises(IndexError): + ob = Test.Int32ArrayTest() + items[-6] + with pytest.raises(IndexError): ob = Test.Int32ArrayTest() - items = ob.items + items[-6] = 0 - self.assertTrue(0 in items) - self.assertTrue(1 in items) - self.assertTrue(2 in items) - self.assertTrue(3 in items) - self.assertTrue(4 in items) - self.assertFalse(5 in items) # "H:\Python27\Lib\unittest\case.py", line 592, in deprecated_func, - self.assertFalse(-1 in items) # TypeError: int() argument must be a string or a number, not 'NoneType' - self.assertFalse(None in items) # which threw ^ here which is a little odd. - # But when run from runtests.py. Not when this module ran by itself. +def test_array_contains(): + """Test array support for __contains__.""" - def test_boolean_array(self): - """Test boolean arrays.""" - ob = Test.BooleanArrayTest() - items = ob.items + ob = Test.Int32ArrayTest() + items = ob.items - self.assertTrue(len(items) == 5) + assert 0 in items + assert 1 in items + assert 2 in items + assert 3 in items + assert 4 in items - self.assertTrue(items[0] is True) - self.assertTrue(items[1] is False) - self.assertTrue(items[2] is True) - self.assertTrue(items[3] is False) - self.assertTrue(items[4] is True) + assert not (5 in items) # "H:\Python27\Lib\unittest\case.py", line 592, in deprecated_func, + assert not (-1 in items) # TypeError: int() argument must be a string or a number, not 'NoneType' + assert not (None in items) # which threw ^ here which is a little odd. + # But when run from runtests.py. Not when this module ran by itself. - items[0] = False - self.assertTrue(items[0] is False) - items[0] = True - self.assertTrue(items[0] is True) +def test_boolean_array(): + """Test boolean arrays.""" + ob = Test.BooleanArrayTest() + items = ob.items - with self.assertRaises(TypeError): - ob = Test.ByteArrayTest() - _ = ob.items["wrong"] + assert len(items) == 5 - with self.assertRaises(TypeError): - ob = Test.ByteArrayTest() - ob[0] = "wrong" + assert items[0] is True + assert items[1] is False + assert items[2] is True + assert items[3] is False + assert items[4] is True + + items[0] = False + assert items[0] is False + + items[0] = True + assert items[0] is True + + with pytest.raises(TypeError): + ob = Test.ByteArrayTest() + _ = ob.items["wrong"] - def test_byte_array(self): - """Test byte arrays.""" + with pytest.raises(TypeError): ob = Test.ByteArrayTest() - items = ob.items + ob[0] = "wrong" - self.assertTrue(len(items) == 5) - self.assertTrue(items[0] == 0) - self.assertTrue(items[4] == 4) +def test_byte_array(): + """Test byte arrays.""" + ob = Test.ByteArrayTest() + items = ob.items - max_ = 255 - min_ = 0 + assert len(items) == 5 - items[0] = max_ - self.assertTrue(items[0] == max_) + assert items[0] == 0 + assert items[4] == 4 - items[0] = min_ - self.assertTrue(items[0] == min_) + max_ = 255 + min_ = 0 - items[-4] = max_ - self.assertTrue(items[-4] == max_) + items[0] = max_ + assert items[0] == max_ - items[-1] = min_ - self.assertTrue(items[-1] == min_) + items[0] = min_ + assert items[0] == min_ - with self.assertRaises(OverflowError): - ob = Test.ByteArrayTest() - ob.items[0] = max_ + 1 + items[-4] = max_ + assert items[-4] == max_ - with self.assertRaises(OverflowError): - ob = Test.ByteArrayTest() - ob.items[0] = min_ - 1 + items[-1] = min_ + assert items[-1] == min_ + + with pytest.raises(OverflowError): + ob = Test.ByteArrayTest() + ob.items[0] = max_ + 1 + + with pytest.raises(OverflowError): + ob = Test.ByteArrayTest() + ob.items[0] = min_ - 1 + + with pytest.raises(TypeError): + ob = Test.ByteArrayTest() + _ = ob.items["wrong"] + + with pytest.raises(TypeError): + ob = Test.ByteArrayTest() + ob[0] = "wrong" - with self.assertRaises(TypeError): - ob = Test.ByteArrayTest() - _ = ob.items["wrong"] - with self.assertRaises(TypeError): - ob = Test.ByteArrayTest() - ob[0] = "wrong" +def test_sbyte_array(): + """Test sbyte arrays.""" + ob = Test.SByteArrayTest() + items = ob.items - def test_sbyte_array(self): - """Test sbyte arrays.""" + assert len(items) == 5 + + assert items[0] == 0 + assert items[4] == 4 + + max_ = 127 + min_ = -128 + + items[0] = max_ + assert items[0] == max_ + + items[0] = min_ + assert items[0] == min_ + + items[-4] = max_ + assert items[-4] == max_ + + items[-1] = min_ + assert items[-1] == min_ + + with pytest.raises(OverflowError): + ob = Test.SByteArrayTest() + ob.items[0] = max_ + 1 + + with pytest.raises(OverflowError): + ob = Test.SByteArrayTest() + ob.items[0] = min_ - 1 + + with pytest.raises(TypeError): ob = Test.SByteArrayTest() - items = ob.items + _ = ob.items["wrong"] - self.assertTrue(len(items) == 5) + with pytest.raises(TypeError): + ob = Test.SByteArrayTest() + ob[0] = "wrong" - self.assertTrue(items[0] == 0) - self.assertTrue(items[4] == 4) - max_ = 127 - min_ = -128 +def test_char_array(): + """Test char arrays.""" + ob = Test.CharArrayTest() + items = ob.items - items[0] = max_ - self.assertTrue(items[0] == max_) + assert len(items) == 5 - items[0] = min_ - self.assertTrue(items[0] == min_) + assert items[0] == 'a' + assert items[4] == 'e' - items[-4] = max_ - self.assertTrue(items[-4] == max_) + max_ = unichr(65535) + min_ = unichr(0) - items[-1] = min_ - self.assertTrue(items[-1] == min_) + items[0] = max_ + assert items[0] == max_ - with self.assertRaises(OverflowError): - ob = Test.SByteArrayTest() - ob.items[0] = max_ + 1 + items[0] = min_ + assert items[0] == min_ - with self.assertRaises(OverflowError): - ob = Test.SByteArrayTest() - ob.items[0] = min_ - 1 + items[-4] = max_ + assert items[-4] == max_ - with self.assertRaises(TypeError): - ob = Test.SByteArrayTest() - _ = ob.items["wrong"] + items[-1] = min_ + assert items[-1] == min_ - with self.assertRaises(TypeError): - ob = Test.SByteArrayTest() - ob[0] = "wrong" + with pytest.raises(TypeError): + ob = Test.CharArrayTest() + _ = ob.items["wrong"] - def test_char_array(self): - """Test char arrays.""" + with pytest.raises(TypeError): ob = Test.CharArrayTest() - items = ob.items + ob[0] = "wrong" + + +def test_int16_array(): + """Test Int16 arrays.""" + ob = Test.Int16ArrayTest() + items = ob.items + + assert len(items) == 5 - self.assertTrue(len(items) == 5) + assert items[0] == 0 + assert items[4] == 4 - self.assertTrue(items[0] == 'a') - self.assertTrue(items[4] == 'e') + max_ = 32767 + min_ = -32768 - max_ = unichr(65535) - min_ = unichr(0) + items[0] = max_ + assert items[0] == max_ - items[0] = max_ - self.assertTrue(items[0] == max_) + items[0] = min_ + assert items[0] == min_ - items[0] = min_ - self.assertTrue(items[0] == min_) + items[-4] = max_ + assert items[-4] == max_ - items[-4] = max_ - self.assertTrue(items[-4] == max_) + items[-1] = min_ + assert items[-1] == min_ - items[-1] = min_ - self.assertTrue(items[-1] == min_) + with pytest.raises(OverflowError): + ob = Test.Int16ArrayTest() + ob.items[0] = max_ + 1 - with self.assertRaises(TypeError): - ob = Test.CharArrayTest() - _ = ob.items["wrong"] + with pytest.raises(OverflowError): + ob = Test.Int16ArrayTest() + ob.items[0] = min_ - 1 - with self.assertRaises(TypeError): - ob = Test.CharArrayTest() - ob[0] = "wrong" + with pytest.raises(TypeError): + ob = Test.Int16ArrayTest() + _ = ob.items["wrong"] - def test_int16_array(self): - """Test Int16 arrays.""" + with pytest.raises(TypeError): ob = Test.Int16ArrayTest() - items = ob.items + ob[0] = "wrong" - self.assertTrue(len(items) == 5) - self.assertTrue(items[0] == 0) - self.assertTrue(items[4] == 4) +def test_int32_array(): + """Test Int32 arrays.""" + ob = Test.Int32ArrayTest() + items = ob.items - max_ = 32767 - min_ = -32768 + assert len(items) == 5 - items[0] = max_ - self.assertTrue(items[0] == max_) + assert items[0] == 0 + assert items[4] == 4 - items[0] = min_ - self.assertTrue(items[0] == min_) + max_ = 2147483647 + min_ = -2147483648 - items[-4] = max_ - self.assertTrue(items[-4] == max_) + items[0] = max_ + assert items[0] == max_ - items[-1] = min_ - self.assertTrue(items[-1] == min_) + items[0] = min_ + assert items[0] == min_ - with self.assertRaises(OverflowError): - ob = Test.Int16ArrayTest() - ob.items[0] = max_ + 1 + items[-4] = max_ + assert items[-4] == max_ - with self.assertRaises(OverflowError): - ob = Test.Int16ArrayTest() - ob.items[0] = min_ - 1 + items[-1] = min_ + assert items[-1] == min_ - with self.assertRaises(TypeError): - ob = Test.Int16ArrayTest() - _ = ob.items["wrong"] + with pytest.raises(OverflowError): + ob = Test.Int32ArrayTest() + ob.items[0] = max_ + 1 - with self.assertRaises(TypeError): - ob = Test.Int16ArrayTest() - ob[0] = "wrong" + with pytest.raises(OverflowError): + ob = Test.Int32ArrayTest() + ob.items[0] = min_ - 1 - def test_int32_array(self): - """Test Int32 arrays.""" + with pytest.raises(TypeError): ob = Test.Int32ArrayTest() - items = ob.items + _ = ob.items["wrong"] - self.assertTrue(len(items) == 5) + with pytest.raises(TypeError): + ob = Test.Int32ArrayTest() + ob[0] = "wrong" - self.assertTrue(items[0] == 0) - self.assertTrue(items[4] == 4) - max_ = 2147483647 - min_ = -2147483648 +def test_int64_array(): + """Test Int64 arrays.""" + ob = Test.Int64ArrayTest() + items = ob.items - items[0] = max_ - self.assertTrue(items[0] == max_) + assert len(items) == 5 - items[0] = min_ - self.assertTrue(items[0] == min_) + assert items[0] == 0 + assert items[4] == 4 - items[-4] = max_ - self.assertTrue(items[-4] == max_) + max_ = long(9223372036854775807) + min_ = long(-9223372036854775808) - items[-1] = min_ - self.assertTrue(items[-1] == min_) + items[0] = max_ + assert items[0] == max_ - with self.assertRaises(OverflowError): - ob = Test.Int32ArrayTest() - ob.items[0] = max_ + 1 + items[0] = min_ + assert items[0] == min_ - with self.assertRaises(OverflowError): - ob = Test.Int32ArrayTest() - ob.items[0] = min_ - 1 + items[-4] = max_ + assert items[-4] == max_ - with self.assertRaises(TypeError): - ob = Test.Int32ArrayTest() - _ = ob.items["wrong"] + items[-1] = min_ + assert items[-1] == min_ - with self.assertRaises(TypeError): - ob = Test.Int32ArrayTest() - ob[0] = "wrong" + with pytest.raises(OverflowError): + ob = Test.Int64ArrayTest() + ob.items[0] = max_ + 1 - def test_int64_array(self): - """Test Int64 arrays.""" + with pytest.raises(OverflowError): ob = Test.Int64ArrayTest() - items = ob.items + ob.items[0] = min_ - 1 - self.assertTrue(len(items) == 5) + with pytest.raises(TypeError): + ob = Test.Int64ArrayTest() + _ = ob.items["wrong"] - self.assertTrue(items[0] == 0) - self.assertTrue(items[4] == 4) + with pytest.raises(TypeError): + ob = Test.Int64ArrayTest() + ob[0] = "wrong" - max_ = long(9223372036854775807) - min_ = long(-9223372036854775808) - items[0] = max_ - self.assertTrue(items[0] == max_) +def test_uint16_array(): + """Test UInt16 arrays.""" + ob = Test.UInt16ArrayTest() + items = ob.items - items[0] = min_ - self.assertTrue(items[0] == min_) + assert len(items) == 5 - items[-4] = max_ - self.assertTrue(items[-4] == max_) + assert items[0] == 0 + assert items[4] == 4 - items[-1] = min_ - self.assertTrue(items[-1] == min_) + max_ = 65535 + min_ = 0 - with self.assertRaises(OverflowError): - ob = Test.Int64ArrayTest() - ob.items[0] = max_ + 1 + items[0] = max_ + assert items[0] == max_ - with self.assertRaises(OverflowError): - ob = Test.Int64ArrayTest() - ob.items[0] = min_ - 1 + items[0] = min_ + assert items[0] == min_ - with self.assertRaises(TypeError): - ob = Test.Int64ArrayTest() - _ = ob.items["wrong"] + items[-4] = max_ + assert items[-4] == max_ - with self.assertRaises(TypeError): - ob = Test.Int64ArrayTest() - ob[0] = "wrong" + items[-1] = min_ + assert items[-1] == min_ - def test_uint16_array(self): - """Test UInt16 arrays.""" + with pytest.raises(OverflowError): ob = Test.UInt16ArrayTest() - items = ob.items + ob.items[0] = max_ + 1 - self.assertTrue(len(items) == 5) + with pytest.raises(OverflowError): + ob = Test.UInt16ArrayTest() + ob.items[0] = min_ - 1 + + with pytest.raises(TypeError): + ob = Test.UInt16ArrayTest() + _ = ob.items["wrong"] + + with pytest.raises(TypeError): + ob = Test.UInt16ArrayTest() + ob[0] = "wrong" - self.assertTrue(items[0] == 0) - self.assertTrue(items[4] == 4) - max_ = 65535 - min_ = 0 +def test_uint32_array(): + """Test UInt32 arrays.""" + ob = Test.UInt32ArrayTest() + items = ob.items - items[0] = max_ - self.assertTrue(items[0] == max_) + assert len(items) == 5 - items[0] = min_ - self.assertTrue(items[0] == min_) + assert items[0] == 0 + assert items[4] == 4 - items[-4] = max_ - self.assertTrue(items[-4] == max_) + max_ = long(4294967295) + min_ = 0 - items[-1] = min_ - self.assertTrue(items[-1] == min_) + items[0] = max_ + assert items[0] == max_ - with self.assertRaises(OverflowError): - ob = Test.UInt16ArrayTest() - ob.items[0] = max_ + 1 + items[0] = min_ + assert items[0] == min_ - with self.assertRaises(OverflowError): - ob = Test.UInt16ArrayTest() - ob.items[0] = min_ - 1 + items[-4] = max_ + assert items[-4] == max_ - with self.assertRaises(TypeError): - ob = Test.UInt16ArrayTest() - _ = ob.items["wrong"] + items[-1] = min_ + assert items[-1] == min_ - with self.assertRaises(TypeError): - ob = Test.UInt16ArrayTest() - ob[0] = "wrong" + with pytest.raises(OverflowError): + ob = Test.UInt32ArrayTest() + ob.items[0] = max_ + 1 - def test_uint32_array(self): - """Test UInt32 arrays.""" + with pytest.raises(OverflowError): ob = Test.UInt32ArrayTest() - items = ob.items + ob.items[0] = min_ - 1 - self.assertTrue(len(items) == 5) + with pytest.raises(TypeError): + ob = Test.UInt32ArrayTest() + _ = ob.items["wrong"] - self.assertTrue(items[0] == 0) - self.assertTrue(items[4] == 4) + with pytest.raises(TypeError): + ob = Test.UInt32ArrayTest() + ob[0] = "wrong" - max_ = long(4294967295) - min_ = 0 - items[0] = max_ - self.assertTrue(items[0] == max_) +def test_uint64_array(): + """Test UInt64 arrays.""" + ob = Test.UInt64ArrayTest() + items = ob.items - items[0] = min_ - self.assertTrue(items[0] == min_) + assert len(items) == 5 - items[-4] = max_ - self.assertTrue(items[-4] == max_) + assert items[0] == 0 + assert items[4] == 4 - items[-1] = min_ - self.assertTrue(items[-1] == min_) + max_ = long(18446744073709551615) + min_ = 0 - with self.assertRaises(OverflowError): - ob = Test.UInt32ArrayTest() - ob.items[0] = max_ + 1 + items[0] = max_ + assert items[0] == max_ - with self.assertRaises(OverflowError): - ob = Test.UInt32ArrayTest() - ob.items[0] = min_ - 1 + items[0] = min_ + assert items[0] == min_ - with self.assertRaises(TypeError): - ob = Test.UInt32ArrayTest() - _ = ob.items["wrong"] + items[-4] = max_ + assert items[-4] == max_ - with self.assertRaises(TypeError): - ob = Test.UInt32ArrayTest() - ob[0] = "wrong" + items[-1] = min_ + assert items[-1] == min_ - def test_uint64_array(self): - """Test UInt64 arrays.""" + with pytest.raises(OverflowError): ob = Test.UInt64ArrayTest() - items = ob.items + ob.items[0] = max_ + 1 - self.assertTrue(len(items) == 5) + with pytest.raises(OverflowError): + ob = Test.UInt64ArrayTest() + ob.items[0] = min_ - 1 + + with pytest.raises(TypeError): + ob = Test.UInt64ArrayTest() + _ = ob.items["wrong"] + + with pytest.raises(TypeError): + ob = Test.UInt64ArrayTest() + ob[0] = "wrong" - self.assertTrue(items[0] == 0) - self.assertTrue(items[4] == 4) - max_ = long(18446744073709551615) - min_ = 0 +def test_single_array(): + """Test Single arrays.""" + ob = Test.SingleArrayTest() + items = ob.items - items[0] = max_ - self.assertTrue(items[0] == max_) + assert len(items) == 5 - items[0] = min_ - self.assertTrue(items[0] == min_) + assert items[0] == 0.0 + assert items[4] == 4.0 - items[-4] = max_ - self.assertTrue(items[-4] == max_) + max_ = 3.402823e38 + min_ = -3.402823e38 - items[-1] = min_ - self.assertTrue(items[-1] == min_) + items[0] = max_ + assert items[0] == max_ - with self.assertRaises(OverflowError): - ob = Test.UInt64ArrayTest() - ob.items[0] = max_ + 1 + items[0] = min_ + assert items[0] == min_ - with self.assertRaises(OverflowError): - ob = Test.UInt64ArrayTest() - ob.items[0] = min_ - 1 + items[-4] = max_ + assert items[-4] == max_ - with self.assertRaises(TypeError): - ob = Test.UInt64ArrayTest() - _ = ob.items["wrong"] + items[-1] = min_ + assert items[-1] == min_ - with self.assertRaises(TypeError): - ob = Test.UInt64ArrayTest() - ob[0] = "wrong" + with pytest.raises(TypeError): + ob = Test.SingleArrayTest() + _ = ob.items["wrong"] - def test_single_array(self): - """Test Single arrays.""" + with pytest.raises(TypeError): ob = Test.SingleArrayTest() - items = ob.items + ob[0] = "wrong" - self.assertTrue(len(items) == 5) - self.assertTrue(items[0] == 0.0) - self.assertTrue(items[4] == 4.0) +def test_double_array(): + """Test Double arrays.""" + ob = Test.DoubleArrayTest() + items = ob.items - max_ = 3.402823e38 - min_ = -3.402823e38 + assert len(items) == 5 - items[0] = max_ - self.assertTrue(items[0] == max_) + assert items[0] == 0.0 + assert items[4] == 4.0 - items[0] = min_ - self.assertTrue(items[0] == min_) + max_ = 1.7976931348623157e308 + min_ = -1.7976931348623157e308 - items[-4] = max_ - self.assertTrue(items[-4] == max_) + items[0] = max_ + assert items[0] == max_ - items[-1] = min_ - self.assertTrue(items[-1] == min_) + items[0] = min_ + assert items[0] == min_ - with self.assertRaises(TypeError): - ob = Test.SingleArrayTest() - _ = ob.items["wrong"] + items[-4] = max_ + assert items[-4] == max_ - with self.assertRaises(TypeError): - ob = Test.SingleArrayTest() - ob[0] = "wrong" + items[-1] = min_ + assert items[-1] == min_ + + with pytest.raises(TypeError): + ob = Test.DoubleArrayTest() + _ = ob.items["wrong"] - def test_double_array(self): - """Test Double arrays.""" + with pytest.raises(TypeError): ob = Test.DoubleArrayTest() - items = ob.items + ob[0] = "wrong" - self.assertTrue(len(items) == 5) - self.assertTrue(items[0] == 0.0) - self.assertTrue(items[4] == 4.0) +def test_decimal_array(): + """Test Decimal arrays.""" + ob = Test.DecimalArrayTest() + items = ob.items - max_ = 1.7976931348623157e308 - min_ = -1.7976931348623157e308 + from System import Decimal + max_d = Decimal.Parse("79228162514264337593543950335") + min_d = Decimal.Parse("-79228162514264337593543950335") - items[0] = max_ - self.assertTrue(items[0] == max_) + assert len(items) == 5 - items[0] = min_ - self.assertTrue(items[0] == min_) + assert items[0] == Decimal(0) + assert items[4] == Decimal(4) - items[-4] = max_ - self.assertTrue(items[-4] == max_) + items[0] = max_d + assert items[0] == max_d - items[-1] = min_ - self.assertTrue(items[-1] == min_) + items[0] = min_d + assert items[0] == min_d - with self.assertRaises(TypeError): - ob = Test.DoubleArrayTest() - _ = ob.items["wrong"] + items[-4] = max_d + assert items[-4] == max_d - with self.assertRaises(TypeError): - ob = Test.DoubleArrayTest() - ob[0] = "wrong" + items[-1] = min_d + assert items[-1] == min_d - def test_decimal_array(self): - """Test Decimal arrays.""" + with pytest.raises(TypeError): ob = Test.DecimalArrayTest() - items = ob.items + _ = ob.items["wrong"] - from System import Decimal - max_d = Decimal.Parse("79228162514264337593543950335") - min_d = Decimal.Parse("-79228162514264337593543950335") + with pytest.raises(TypeError): + ob = Test.DecimalArrayTest() + ob[0] = "wrong" - self.assertTrue(len(items) == 5) - self.assertTrue(items[0] == Decimal(0)) - self.assertTrue(items[4] == Decimal(4)) +def test_string_array(): + """Test String arrays.""" + ob = Test.StringArrayTest() + items = ob.items - items[0] = max_d - self.assertTrue(items[0] == max_d) + assert len(items) == 5 - items[0] = min_d - self.assertTrue(items[0] == min_d) + assert items[0] == '0' + assert items[4] == '4' - items[-4] = max_d - self.assertTrue(items[-4] == max_d) + items[0] = "spam" + assert items[0] == "spam" - items[-1] = min_d - self.assertTrue(items[-1] == min_d) + items[0] = "eggs" + assert items[0] == "eggs" - with self.assertRaises(TypeError): - ob = Test.DecimalArrayTest() - _ = ob.items["wrong"] + items[-4] = "spam" + assert items[-4] == "spam" - with self.assertRaises(TypeError): - ob = Test.DecimalArrayTest() - ob[0] = "wrong" + items[-1] = "eggs" + assert items[-1] == "eggs" - def test_string_array(self): - """Test String arrays.""" + with pytest.raises(TypeError): ob = Test.StringArrayTest() - items = ob.items + _ = ob.items["wrong"] + + with pytest.raises(TypeError): + ob = Test.Int64ArrayTest() + ob[0] = 0 + - self.assertTrue(len(items) == 5) +def test_enum_array(): + """Test enum arrays.""" + from Python.Test import ShortEnum + ob = Test.EnumArrayTest() + items = ob.items - self.assertTrue(items[0] == '0') - self.assertTrue(items[4] == '4') + assert len(items) == 5 - items[0] = "spam" - self.assertTrue(items[0] == "spam") + assert items[0] == ShortEnum.Zero + assert items[4] == ShortEnum.Four - items[0] = "eggs" - self.assertTrue(items[0] == "eggs") + items[0] = ShortEnum.Four + assert items[0] == ShortEnum.Four - items[-4] = "spam" - self.assertTrue(items[-4] == "spam") + items[0] = ShortEnum.Zero + assert items[0] == ShortEnum.Zero - items[-1] = "eggs" - self.assertTrue(items[-1] == "eggs") + items[-4] = ShortEnum.Four + assert items[-4] == ShortEnum.Four - with self.assertRaises(TypeError): - ob = Test.StringArrayTest() - _ = ob.items["wrong"] + items[-1] = ShortEnum.Zero + assert items[-1] == ShortEnum.Zero - with self.assertRaises(TypeError): - ob = Test.Int64ArrayTest() - ob[0] = 0 + with pytest.raises(ValueError): + ob = Test.EnumArrayTest() + ob.items[0] = 99 + + with pytest.raises(TypeError): + ob = Test.EnumArrayTest() + _ = ob.items["wrong"] - def test_enum_array(self): - """Test enum arrays.""" - from Python.Test import ShortEnum + with pytest.raises(TypeError): ob = Test.EnumArrayTest() - items = ob.items + ob[0] = "wrong" + - self.assertTrue(len(items) == 5) +def test_object_array(): + """Test ob arrays.""" + from Python.Test import Spam + ob = Test.ObjectArrayTest() + items = ob.items - self.assertTrue(items[0] == ShortEnum.Zero) - self.assertTrue(items[4] == ShortEnum.Four) + assert len(items) == 5 - items[0] = ShortEnum.Four - self.assertTrue(items[0] == ShortEnum.Four) + assert items[0].GetValue() == "0" + assert items[4].GetValue() == "4" - items[0] = ShortEnum.Zero - self.assertTrue(items[0] == ShortEnum.Zero) + items[0] = Spam("4") + assert items[0].GetValue() == "4" - items[-4] = ShortEnum.Four - self.assertTrue(items[-4] == ShortEnum.Four) + items[0] = Spam("0") + assert items[0].GetValue() == "0" - items[-1] = ShortEnum.Zero - self.assertTrue(items[-1] == ShortEnum.Zero) + items[-4] = Spam("4") + assert items[-4].GetValue() == "4" - with self.assertRaises(ValueError): - ob = Test.EnumArrayTest() - ob.items[0] = 99 + items[-1] = Spam("0") + assert items[-1].GetValue() == "0" - with self.assertRaises(TypeError): - ob = Test.EnumArrayTest() - _ = ob.items["wrong"] + items[0] = 99 + assert items[0] == 99 - with self.assertRaises(TypeError): - ob = Test.EnumArrayTest() - ob[0] = "wrong" + items[0] = None + assert items[0] is None - def test_object_array(self): - """Test ob arrays.""" - from Python.Test import Spam + with pytest.raises(TypeError): ob = Test.ObjectArrayTest() - items = ob.items + _ = ob.items["wrong"] - self.assertTrue(len(items) == 5) + with pytest.raises(TypeError): + ob = Test.ObjectArrayTest() + ob.items["wrong"] = "wrong" - self.assertTrue(items[0].GetValue() == "0") - self.assertTrue(items[4].GetValue() == "4") - items[0] = Spam("4") - self.assertTrue(items[0].GetValue() == "4") +def test_null_array(): + """Test null arrays.""" + ob = Test.NullArrayTest() + items = ob.items - items[0] = Spam("0") - self.assertTrue(items[0].GetValue() == "0") + assert len(items) == 5 - items[-4] = Spam("4") - self.assertTrue(items[-4].GetValue() == "4") + assert items[0] is None + assert items[4] is None - items[-1] = Spam("0") - self.assertTrue(items[-1].GetValue() == "0") + items[0] = "spam" + assert items[0] == "spam" - items[0] = 99 - self.assertTrue(items[0] == 99) + items[0] = None + assert items[0] is None - items[0] = None - self.assertTrue(items[0] is None) + items[-4] = "spam" + assert items[-4] == "spam" - with self.assertRaises(TypeError): - ob = Test.ObjectArrayTest() - _ = ob.items["wrong"] + items[-1] = None + assert items[-1] is None - with self.assertRaises(TypeError): - ob = Test.ObjectArrayTest() - ob.items["wrong"] = "wrong" + empty = ob.empty + assert len(empty) == 0 - def test_null_array(self): - """Test null arrays.""" + with pytest.raises(TypeError): ob = Test.NullArrayTest() - items = ob.items + _ = ob.items["wrong"] + - self.assertTrue(len(items) == 5) +def test_interface_array(): + """Test interface arrays.""" + from Python.Test import Spam + ob = Test.InterfaceArrayTest() + items = ob.items - self.assertTrue(items[0] is None) - self.assertTrue(items[4] is None) + assert len(items) == 5 - items[0] = "spam" - self.assertTrue(items[0] == "spam") + assert items[0].GetValue() == "0" + assert items[4].GetValue() == "4" - items[0] = None - self.assertTrue(items[0] is None) + items[0] = Spam("4") + assert items[0].GetValue() == "4" - items[-4] = "spam" - self.assertTrue(items[-4] == "spam") + items[0] = Spam("0") + assert items[0].GetValue() == "0" - items[-1] = None - self.assertTrue(items[-1] is None) + items[-4] = Spam("4") + assert items[-4].GetValue() == "4" - empty = ob.empty - self.assertTrue(len(empty) == 0) + items[-1] = Spam("0") + assert items[-1].GetValue() == "0" - with self.assertRaises(TypeError): - ob = Test.NullArrayTest() - _ = ob.items["wrong"] + items[0] = None + assert items[0] is None - def test_interface_array(self): - """Test interface arrays.""" - from Python.Test import Spam + with pytest.raises(TypeError): ob = Test.InterfaceArrayTest() - items = ob.items + ob.items[0] = 99 - self.assertTrue(len(items) == 5) + with pytest.raises(TypeError): + ob = Test.InterfaceArrayTest() + _ = ob.items["wrong"] + + with pytest.raises(TypeError): + ob = Test.InterfaceArrayTest() + ob.items["wrong"] = "wrong" - self.assertTrue(items[0].GetValue() == "0") - self.assertTrue(items[4].GetValue() == "4") - items[0] = Spam("4") - self.assertTrue(items[0].GetValue() == "4") +def test_typed_array(): + """Test typed arrays.""" + from Python.Test import Spam + ob = Test.TypedArrayTest() + items = ob.items - items[0] = Spam("0") - self.assertTrue(items[0].GetValue() == "0") + assert len(items) == 5 - items[-4] = Spam("4") - self.assertTrue(items[-4].GetValue() == "4") + assert items[0].GetValue() == "0" + assert items[4].GetValue() == "4" - items[-1] = Spam("0") - self.assertTrue(items[-1].GetValue() == "0") + items[0] = Spam("4") + assert items[0].GetValue() == "4" - items[0] = None - self.assertTrue(items[0] is None) + items[0] = Spam("0") + assert items[0].GetValue() == "0" - with self.assertRaises(TypeError): - ob = Test.InterfaceArrayTest() - ob.items[0] = 99 + items[-4] = Spam("4") + assert items[-4].GetValue() == "4" - with self.assertRaises(TypeError): - ob = Test.InterfaceArrayTest() - _ = ob.items["wrong"] + items[-1] = Spam("0") + assert items[-1].GetValue() == "0" - with self.assertRaises(TypeError): - ob = Test.InterfaceArrayTest() - ob.items["wrong"] = "wrong" + items[0] = None + assert items[0] is None - def test_typed_array(self): - """Test typed arrays.""" - from Python.Test import Spam + with pytest.raises(TypeError): ob = Test.TypedArrayTest() - items = ob.items + ob.items[0] = 99 - self.assertTrue(len(items) == 5) + with pytest.raises(TypeError): + ob = Test.TypedArrayTest() + _ = ob.items["wrong"] - self.assertTrue(items[0].GetValue() == "0") - self.assertTrue(items[4].GetValue() == "4") + with pytest.raises(TypeError): + ob = Test.TypedArrayTest() + ob.items["wrong"] = "wrong" + + +def test_multi_dimensional_array(): + """Test multi-dimensional arrays.""" + ob = Test.MultiDimensionalArrayTest() + items = ob.items + + assert len(items) == 25 + + assert items[0, 0] == 0 + assert items[0, 1] == 1 + assert items[0, 2] == 2 + assert items[0, 3] == 3 + assert items[0, 4] == 4 + assert items[1, 0] == 5 + assert items[1, 1] == 6 + assert items[1, 2] == 7 + assert items[1, 3] == 8 + assert items[1, 4] == 9 + assert items[2, 0] == 10 + assert items[2, 1] == 11 + assert items[2, 2] == 12 + assert items[2, 3] == 13 + assert items[2, 4] == 14 + assert items[3, 0] == 15 + assert items[3, 1] == 16 + assert items[3, 2] == 17 + assert items[3, 3] == 18 + assert items[3, 4] == 19 + assert items[4, 0] == 20 + assert items[4, 1] == 21 + assert items[4, 2] == 22 + assert items[4, 3] == 23 + assert items[4, 4] == 24 + + max_ = 2147483647 + min_ = -2147483648 + + items[0, 0] = max_ + assert items[0, 0] == max_ + + items[0, 0] = min_ + assert items[0, 0] == min_ + + items[-4, 0] = max_ + assert items[-4, 0] == max_ + + items[-1, -1] = min_ + assert items[-1, -1] == min_ + + with pytest.raises(OverflowError): + ob = Test.MultiDimensionalArrayTest() + ob.items[0, 0] = max_ + 1 - items[0] = Spam("4") - self.assertTrue(items[0].GetValue() == "4") + with pytest.raises(OverflowError): + ob = Test.MultiDimensionalArrayTest() + ob.items[0, 0] = min_ - 1 - items[0] = Spam("0") - self.assertTrue(items[0].GetValue() == "0") + with pytest.raises(TypeError): + ob = Test.MultiDimensionalArrayTest() + _ = ob.items["wrong", 0] + + with pytest.raises(TypeError): + ob = Test.MultiDimensionalArrayTest() + ob[0, 0] = "wrong" - items[-4] = Spam("4") - self.assertTrue(items[-4].GetValue() == "4") - items[-1] = Spam("0") - self.assertTrue(items[-1].GetValue() == "0") +def test_array_iteration(): + """Test array iteration.""" + items = Test.Int32ArrayTest().items - items[0] = None - self.assertTrue(items[0] is None) + for i in items: + assert (i > -1) and (i < 5) - with self.assertRaises(TypeError): - ob = Test.TypedArrayTest() - ob.items[0] = 99 + items = Test.NullArrayTest().items - with self.assertRaises(TypeError): - ob = Test.TypedArrayTest() - _ = ob.items["wrong"] + for i in items: + assert i is None - with self.assertRaises(TypeError): - ob = Test.TypedArrayTest() - ob.items["wrong"] = "wrong" + empty = Test.NullArrayTest().empty + + for i in empty: + raise TypeError('iteration over empty array') + + +def test_tuple_array_conversion(): + """Test conversion of tuples to array arguments.""" + from Python.Test import ArrayConversionTest + from Python.Test import Spam + + items = [] + for i in range(10): + items.append(Spam(str(i))) + items = tuple(items) + + result = ArrayConversionTest.EchoRange(items) + assert result[0].__class__ == Spam + assert len(result) == 10 + + +def test_tuple_nested_array_conversion(): + """Test conversion of tuples to array-of-array arguments.""" + from Python.Test import ArrayConversionTest + from Python.Test import Spam + + items = [] + for i in range(10): + subs = [] + for _ in range(10): + subs.append(Spam(str(i))) + items.append(tuple(subs)) + items = tuple(items) + + result = ArrayConversionTest.EchoRangeAA(items) + + assert len(result) == 10 + assert len(result[0]) == 10 + assert result[0][0].__class__ == Spam + + +def test_list_array_conversion(): + """Test conversion of lists to array arguments.""" + from Python.Test import ArrayConversionTest + from Python.Test import Spam + + items = [] + for i in range(10): + items.append(Spam(str(i))) + + result = ArrayConversionTest.EchoRange(items) + assert result[0].__class__ == Spam + assert len(result) == 10 + + +def test_list_nested_array_conversion(): + """Test conversion of lists to array-of-array arguments.""" + from Python.Test import ArrayConversionTest + from Python.Test import Spam + + items = [] + for i in range(10): + subs = [] + for _ in range(10): + subs.append(Spam(str(i))) + items.append(subs) + + result = ArrayConversionTest.EchoRangeAA(items) + + assert len(result) == 10 + assert len(result[0]) == 10 + assert result[0][0].__class__ == Spam + + +def test_sequence_array_conversion(): + """Test conversion of sequence-like obs to array arguments.""" + from Python.Test import ArrayConversionTest + from Python.Test import Spam + + items = UserList() + for i in range(10): + items.append(Spam(str(i))) + + result = ArrayConversionTest.EchoRange(items) + assert result[0].__class__ == Spam + assert len(result) == 10 + + +def test_sequence_nested_array_conversion(): + """Test conversion of sequences to array-of-array arguments.""" + from Python.Test import ArrayConversionTest + from Python.Test import Spam + + items = UserList() + for i in range(10): + subs = UserList() + for _ in range(10): + subs.append(Spam(str(i))) + items.append(subs) + + result = ArrayConversionTest.EchoRangeAA(items) + + assert len(result) == 10 + assert len(result[0]) == 10 + assert result[0][0].__class__ == Spam + + +def test_tuple_array_conversion_type_checking(): + """Test error handling for tuple conversion to array arguments.""" + from Python.Test import ArrayConversionTest + from Python.Test import Spam + + # This should work, because null / None is a valid value in an + # array of reference types. + + items = [] + for i in range(10): + items.append(Spam(str(i))) + items[1] = None + items = tuple(items) + + result = ArrayConversionTest.EchoRange(items) + + assert result[0].__class__ == Spam + assert result[1] is None + assert len(result) == 10 + + with pytest.raises(TypeError): + temp = list(items) + temp[1] = 1 + _ = ArrayConversionTest.EchoRange(tuple(temp)) + + with pytest.raises(TypeError): + temp = list(items) + temp[1] = "spam" + _ = ArrayConversionTest.EchoRange(tuple(temp)) + + +def test_list_array_conversion_type_checking(): + """Test error handling for list conversion to array arguments.""" + from Python.Test import ArrayConversionTest + from Python.Test import Spam + + # This should work, because null / None is a valid value in an + # array of reference types. + + items = [] + for i in range(10): + items.append(Spam(str(i))) + items[1] = None + + result = ArrayConversionTest.EchoRange(items) + + assert result[0].__class__ == Spam + assert result[1] is None + assert len(result) == 10 + + with pytest.raises(TypeError): + items[1] = 1 + _ = ArrayConversionTest.EchoRange(items) + + with pytest.raises(TypeError): + items[1] = "spam" + _ = ArrayConversionTest.EchoRange(items) + + +def test_sequence_array_conversion_type_checking(): + """Test error handling for sequence conversion to array arguments.""" + from Python.Test import ArrayConversionTest + from Python.Test import Spam + + # This should work, because null / None is a valid value in an + # array of reference types. + + items = UserList() + for i in range(10): + items.append(Spam(str(i))) + items[1] = None + + result = ArrayConversionTest.EchoRange(items) + + assert result[0].__class__ == Spam + assert result[1] is None + assert len(result) == 10 + + with pytest.raises(TypeError): + items[1] = 1 + _ = ArrayConversionTest.EchoRange(items) + + with pytest.raises(TypeError): + items[1] = "spam" + _ = ArrayConversionTest.EchoRange(items) - def test_multi_dimensional_array(self): - """Test multi-dimensional arrays.""" - ob = Test.MultiDimensionalArrayTest() - items = ob.items - - self.assertTrue(len(items) == 25) - - self.assertTrue(items[0, 0] == 0) - self.assertTrue(items[0, 1] == 1) - self.assertTrue(items[0, 2] == 2) - self.assertTrue(items[0, 3] == 3) - self.assertTrue(items[0, 4] == 4) - self.assertTrue(items[1, 0] == 5) - self.assertTrue(items[1, 1] == 6) - self.assertTrue(items[1, 2] == 7) - self.assertTrue(items[1, 3] == 8) - self.assertTrue(items[1, 4] == 9) - self.assertTrue(items[2, 0] == 10) - self.assertTrue(items[2, 1] == 11) - self.assertTrue(items[2, 2] == 12) - self.assertTrue(items[2, 3] == 13) - self.assertTrue(items[2, 4] == 14) - self.assertTrue(items[3, 0] == 15) - self.assertTrue(items[3, 1] == 16) - self.assertTrue(items[3, 2] == 17) - self.assertTrue(items[3, 3] == 18) - self.assertTrue(items[3, 4] == 19) - self.assertTrue(items[4, 0] == 20) - self.assertTrue(items[4, 1] == 21) - self.assertTrue(items[4, 2] == 22) - self.assertTrue(items[4, 3] == 23) - self.assertTrue(items[4, 4] == 24) - - max_ = 2147483647 - min_ = -2147483648 - - items[0, 0] = max_ - self.assertTrue(items[0, 0] == max_) - - items[0, 0] = min_ - self.assertTrue(items[0, 0] == min_) - - items[-4, 0] = max_ - self.assertTrue(items[-4, 0] == max_) - - items[-1, -1] = min_ - self.assertTrue(items[-1, -1] == min_) - - with self.assertRaises(OverflowError): - ob = Test.MultiDimensionalArrayTest() - ob.items[0, 0] = max_ + 1 - - with self.assertRaises(OverflowError): - ob = Test.MultiDimensionalArrayTest() - ob.items[0, 0] = min_ - 1 - - with self.assertRaises(TypeError): - ob = Test.MultiDimensionalArrayTest() - _ = ob.items["wrong", 0] - - with self.assertRaises(TypeError): - ob = Test.MultiDimensionalArrayTest() - ob[0, 0] = "wrong" - - def test_array_iteration(self): - """Test array iteration.""" - items = Test.Int32ArrayTest().items - - for i in items: - self.assertTrue((i > -1) and (i < 5)) - - items = Test.NullArrayTest().items - - for i in items: - self.assertTrue(i is None) - - empty = Test.NullArrayTest().empty - - for i in empty: - raise TypeError('iteration over empty array') - - def test_tuple_array_conversion(self): - """Test conversion of tuples to array arguments.""" - from Python.Test import ArrayConversionTest - from Python.Test import Spam - - items = [] - for i in range(10): - items.append(Spam(str(i))) - items = tuple(items) - - result = ArrayConversionTest.EchoRange(items) - self.assertTrue(result[0].__class__ == Spam) - self.assertTrue(len(result) == 10) - - def test_tuple_nested_array_conversion(self): - """Test conversion of tuples to array-of-array arguments.""" - from Python.Test import ArrayConversionTest - from Python.Test import Spam - - items = [] - for i in range(10): - subs = [] - for _ in range(10): - subs.append(Spam(str(i))) - items.append(tuple(subs)) - items = tuple(items) - - result = ArrayConversionTest.EchoRangeAA(items) - - self.assertTrue(len(result) == 10) - self.assertTrue(len(result[0]) == 10) - self.assertTrue(result[0][0].__class__ == Spam) - - def test_list_array_conversion(self): - """Test conversion of lists to array arguments.""" - from Python.Test import ArrayConversionTest - from Python.Test import Spam - - items = [] - for i in range(10): - items.append(Spam(str(i))) - - result = ArrayConversionTest.EchoRange(items) - self.assertTrue(result[0].__class__ == Spam) - self.assertTrue(len(result) == 10) - - def test_list_nested_array_conversion(self): - """Test conversion of lists to array-of-array arguments.""" - from Python.Test import ArrayConversionTest - from Python.Test import Spam - items = [] - for i in range(10): - subs = [] - for _ in range(10): - subs.append(Spam(str(i))) - items.append(subs) +def test_md_array_conversion(): + """Test passing of multi-dimensional array arguments.""" + from Python.Test import ArrayConversionTest + from Python.Test import Spam + from System import Array - result = ArrayConversionTest.EchoRangeAA(items) + # Currently, the runtime does not support automagic conversion of + # Python sequences to true multi-dimensional arrays (though it + # does support arrays-of-arrays). This test exists mostly as an + # example of how a multi-dimensional array can be created and used + # with managed code from Python. - self.assertTrue(len(result) == 10) - self.assertTrue(len(result[0]) == 10) - self.assertTrue(result[0][0].__class__ == Spam) - - def test_sequence_array_conversion(self): - """Test conversion of sequence-like obs to array arguments.""" - from Python.Test import ArrayConversionTest - from Python.Test import Spam - - items = UserList() - for i in range(10): - items.append(Spam(str(i))) - - result = ArrayConversionTest.EchoRange(items) - self.assertTrue(result[0].__class__ == Spam) - self.assertTrue(len(result) == 10) - - def test_sequence_nested_array_conversion(self): - """Test conversion of sequences to array-of-array arguments.""" - from Python.Test import ArrayConversionTest - from Python.Test import Spam - - items = UserList() - for i in range(10): - subs = UserList() - for _ in range(10): - subs.append(Spam(str(i))) - items.append(subs) - - result = ArrayConversionTest.EchoRangeAA(items) - - self.assertTrue(len(result) == 10) - self.assertTrue(len(result[0]) == 10) - self.assertTrue(result[0][0].__class__ == Spam) - - def test_tuple_array_conversion_type_checking(self): - """Test error handling for tuple conversion to array arguments.""" - from Python.Test import ArrayConversionTest - from Python.Test import Spam - - # This should work, because null / None is a valid value in an - # array of reference types. - - items = [] - for i in range(10): - items.append(Spam(str(i))) - items[1] = None - items = tuple(items) - - result = ArrayConversionTest.EchoRange(items) - - self.assertTrue(result[0].__class__ == Spam) - self.assertTrue(result[1] is None) - self.assertTrue(len(result) == 10) - - with self.assertRaises(TypeError): - temp = list(items) - temp[1] = 1 - _ = ArrayConversionTest.EchoRange(tuple(temp)) - - with self.assertRaises(TypeError): - temp = list(items) - temp[1] = "spam" - _ = ArrayConversionTest.EchoRange(tuple(temp)) - - def test_list_array_conversion_type_checking(self): - """Test error handling for list conversion to array arguments.""" - from Python.Test import ArrayConversionTest - from Python.Test import Spam - - # This should work, because null / None is a valid value in an - # array of reference types. - - items = [] - for i in range(10): - items.append(Spam(str(i))) - items[1] = None - - result = ArrayConversionTest.EchoRange(items) - - self.assertTrue(result[0].__class__ == Spam) - self.assertTrue(result[1] is None) - self.assertTrue(len(result) == 10) - - with self.assertRaises(TypeError): - items[1] = 1 - _ = ArrayConversionTest.EchoRange(items) - - with self.assertRaises(TypeError): - items[1] = "spam" - _ = ArrayConversionTest.EchoRange(items) - - def test_sequence_array_conversion_type_checking(self): - """Test error handling for sequence conversion to array arguments.""" - from Python.Test import ArrayConversionTest - from Python.Test import Spam - - # This should work, because null / None is a valid value in an - # array of reference types. - - items = UserList() - for i in range(10): - items.append(Spam(str(i))) - items[1] = None - - result = ArrayConversionTest.EchoRange(items) - - self.assertTrue(result[0].__class__ == Spam) - self.assertTrue(result[1] is None) - self.assertTrue(len(result) == 10) - - with self.assertRaises(TypeError): - items[1] = 1 - _ = ArrayConversionTest.EchoRange(items) - - with self.assertRaises(TypeError): - items[1] = "spam" - _ = ArrayConversionTest.EchoRange(items) - - def test_md_array_conversion(self): - """Test passing of multi-dimensional array arguments.""" - from Python.Test import ArrayConversionTest - from Python.Test import Spam - from System import Array - - # Currently, the runtime does not support automagic conversion of - # Python sequences to true multi-dimensional arrays (though it - # does support arrays-of-arrays). This test exists mostly as an - # example of how a multi-dimensional array can be created and used - # with managed code from Python. - - items = Array.CreateInstance(Spam, 5, 5) - - for i in range(5): - for n in range(5): - items.SetValue(Spam(str((i, n))), (i, n)) - - result = ArrayConversionTest.EchoRangeMD(items) - - self.assertTrue(len(result) == 25) - self.assertTrue(result[0, 0].__class__ == Spam) - self.assertTrue(result[0, 0].__class__ == Spam) - - def test_boxed_value_type_mutation_result(self): - """Test behavior of boxed value types.""" - - # This test actually exists mostly as documentation of an important - # concern when dealing with value types. Python does not have any - # value type semantics that can be mapped to the CLR, so it is easy - # to accidentally write code like the following which is not really - # mutating value types in-place but changing boxed copies. - - from System.Drawing import Point - from System import Array - - items = Array.CreateInstance(Point, 5) - - for i in range(5): - items[i] = Point(i, i) - - for i in range(5): - # Boxed items, so set_attr will not change the array member. - self.assertTrue(items[i].X == i) - self.assertTrue(items[i].Y == i) - items[i].X = i + 1 - items[i].Y = i + 1 - self.assertTrue(items[i].X == i) - self.assertTrue(items[i].Y == i) - - for i in range(5): - # Demonstrates the workaround that will change the members. - self.assertTrue(items[i].X == i) - self.assertTrue(items[i].Y == i) - item = items[i] - item.X = i + 1 - item.Y = i + 1 - items[i] = item - self.assertTrue(items[i].X == i + 1) - self.assertTrue(items[i].Y == i + 1) - - def test_special_array_creation(self): - """Test using the Array[] syntax for creating arrays.""" - from Python.Test import ISayHello1, InterfaceTest, ShortEnum - from System import Array - inst = InterfaceTest() - - value = Array[System.Boolean]([True, True]) - self.assertTrue(value[0] is True) - self.assertTrue(value[1] is True) - self.assertTrue(value.Length == 2) - - value = Array[bool]([True, True]) - self.assertTrue(value[0] is True) - self.assertTrue(value[1] is True) - self.assertTrue(value.Length == 2) - - value = Array[System.Byte]([0, 255]) - self.assertTrue(value[0] == 0) - self.assertTrue(value[1] == 255) - self.assertTrue(value.Length == 2) - - value = Array[System.SByte]([0, 127]) - self.assertTrue(value[0] == 0) - self.assertTrue(value[1] == 127) - self.assertTrue(value.Length == 2) - - value = Array[System.Char]([u'A', u'Z']) - self.assertTrue(value[0] == u'A') - self.assertTrue(value[1] == u'Z') - self.assertTrue(value.Length == 2) - - value = Array[System.Char]([0, 65535]) - self.assertTrue(value[0] == unichr(0)) - self.assertTrue(value[1] == unichr(65535)) - self.assertTrue(value.Length == 2) - - value = Array[System.Int16]([0, 32767]) - self.assertTrue(value[0] == 0) - self.assertTrue(value[1] == 32767) - self.assertTrue(value.Length == 2) - - value = Array[System.Int32]([0, 2147483647]) - self.assertTrue(value[0] == 0) - self.assertTrue(value[1] == 2147483647) - self.assertTrue(value.Length == 2) - - value = Array[int]([0, 2147483647]) - self.assertTrue(value[0] == 0) - self.assertTrue(value[1] == 2147483647) - self.assertTrue(value.Length == 2) - - value = Array[System.Int64]([0, long(9223372036854775807)]) - self.assertTrue(value[0] == 0) - self.assertTrue(value[1] == long(9223372036854775807)) - self.assertTrue(value.Length == 2) - - # there's no explicit long type in python3, use System.Int64 instead - if PY2: - value = Array[long]([0, long(9223372036854775807)]) - self.assertTrue(value[0] == 0) - self.assertTrue(value[1] == long(9223372036854775807)) - self.assertTrue(value.Length == 2) - - value = Array[System.UInt16]([0, 65000]) - self.assertTrue(value[0] == 0) - self.assertTrue(value[1] == 65000) - self.assertTrue(value.Length == 2) - - value = Array[System.UInt32]([0, long(4294967295)]) - self.assertTrue(value[0] == 0) - self.assertTrue(value[1] == long(4294967295)) - self.assertTrue(value.Length == 2) - - value = Array[System.UInt64]([0, long(18446744073709551615)]) - self.assertTrue(value[0] == 0) - self.assertTrue(value[1] == long(18446744073709551615)) - self.assertTrue(value.Length == 2) - - value = Array[System.Single]([0.0, 3.402823e38]) - self.assertTrue(value[0] == 0.0) - self.assertTrue(value[1] == 3.402823e38) - self.assertTrue(value.Length == 2) - - value = Array[System.Double]([0.0, 1.7976931348623157e308]) - self.assertTrue(value[0] == 0.0) - self.assertTrue(value[1] == 1.7976931348623157e308) - self.assertTrue(value.Length == 2) - - value = Array[float]([0.0, 1.7976931348623157e308]) - self.assertTrue(value[0] == 0.0) - self.assertTrue(value[1] == 1.7976931348623157e308) - self.assertTrue(value.Length == 2) - - value = Array[System.Decimal]([System.Decimal.Zero, System.Decimal.One]) - self.assertTrue(value[0] == System.Decimal.Zero) - self.assertTrue(value[1] == System.Decimal.One) - self.assertTrue(value.Length == 2) - - value = Array[System.String](["one", "two"]) - self.assertTrue(value[0] == "one") - self.assertTrue(value[1] == "two") - self.assertTrue(value.Length == 2) - - value = Array[str](["one", "two"]) - self.assertTrue(value[0] == "one") - self.assertTrue(value[1] == "two") - self.assertTrue(value.Length == 2) - - value = Array[ShortEnum]([ShortEnum.Zero, ShortEnum.One]) - self.assertTrue(value[0] == ShortEnum.Zero) - self.assertTrue(value[1] == ShortEnum.One) - self.assertTrue(value.Length == 2) - - value = Array[System.Object]([inst, inst]) - self.assertTrue(value[0].__class__ == inst.__class__) - self.assertTrue(value[1].__class__ == inst.__class__) - self.assertTrue(value.Length == 2) - - value = Array[InterfaceTest]([inst, inst]) - self.assertTrue(value[0].__class__ == inst.__class__) - self.assertTrue(value[1].__class__ == inst.__class__) - self.assertTrue(value.Length == 2) - - value = Array[ISayHello1]([inst, inst]) - self.assertTrue(value[0].__class__ == inst.__class__) - self.assertTrue(value[1].__class__ == inst.__class__) - self.assertTrue(value.Length == 2) - - inst = System.Exception("badness") - value = Array[System.Exception]([inst, inst]) - self.assertTrue(value[0].__class__ == inst.__class__) - self.assertTrue(value[1].__class__ == inst.__class__) - self.assertTrue(value.Length == 2) - - def test_array_abuse(self): - """Test array abuse.""" - _class = Test.PublicArrayTest - ob = Test.PublicArrayTest() - - with self.assertRaises(AttributeError): - del _class.__getitem__ - - with self.assertRaises(AttributeError): - del ob.__getitem__ - - with self.assertRaises(AttributeError): - del _class.__setitem__ - - with self.assertRaises(AttributeError): - del ob.__setitem__ - - with self.assertRaises(TypeError): - Test.PublicArrayTest.__getitem__(0, 0) - - with self.assertRaises(TypeError): - Test.PublicArrayTest.__setitem__(0, 0, 0) - - with self.assertRaises(TypeError): - desc = Test.PublicArrayTest.__dict__['__getitem__'] - desc(0, 0) - - with self.assertRaises(TypeError): - desc = Test.PublicArrayTest.__dict__['__setitem__'] - desc(0, 0, 0) - - -def test_suite(): - return unittest.makeSuite(ArrayTests) + items = Array.CreateInstance(Spam, 5, 5) + + for i in range(5): + for n in range(5): + items.SetValue(Spam(str((i, n))), (i, n)) + + result = ArrayConversionTest.EchoRangeMD(items) + + assert len(result) == 25 + assert result[0, 0].__class__ == Spam + assert result[0, 0].__class__ == Spam + + +def test_boxed_value_type_mutation_result(): + """Test behavior of boxed value types.""" + + # This test actually exists mostly as documentation of an important + # concern when dealing with value types. Python does not have any + # value type semantics that can be mapped to the CLR, so it is easy + # to accidentally write code like the following which is not really + # mutating value types in-place but changing boxed copies. + + from System.Drawing import Point + from System import Array + + items = Array.CreateInstance(Point, 5) + + for i in range(5): + items[i] = Point(i, i) + + for i in range(5): + # Boxed items, so set_attr will not change the array member. + assert items[i].X == i + assert items[i].Y == i + items[i].X = i + 1 + items[i].Y = i + 1 + assert items[i].X == i + assert items[i].Y == i + + for i in range(5): + # Demonstrates the workaround that will change the members. + assert items[i].X == i + assert items[i].Y == i + item = items[i] + item.X = i + 1 + item.Y = i + 1 + items[i] = item + assert items[i].X == i + 1 + assert items[i].Y == i + 1 + + +def test_special_array_creation(): + """Test using the Array[] syntax for creating arrays.""" + from Python.Test import ISayHello1, InterfaceTest, ShortEnum + from System import Array + inst = InterfaceTest() + + value = Array[System.Boolean]([True, True]) + assert value[0] is True + assert value[1] is True + assert value.Length == 2 + + value = Array[bool]([True, True]) + assert value[0] is True + assert value[1] is True + assert value.Length == 2 + + value = Array[System.Byte]([0, 255]) + assert value[0] == 0 + assert value[1] == 255 + assert value.Length == 2 + + value = Array[System.SByte]([0, 127]) + assert value[0] == 0 + assert value[1] == 127 + assert value.Length == 2 + + value = Array[System.Char]([u'A', u'Z']) + assert value[0] == u'A' + assert value[1] == u'Z' + assert value.Length == 2 + + value = Array[System.Char]([0, 65535]) + assert value[0] == unichr(0) + assert value[1] == unichr(65535) + assert value.Length == 2 + + value = Array[System.Int16]([0, 32767]) + assert value[0] == 0 + assert value[1] == 32767 + assert value.Length == 2 + + value = Array[System.Int32]([0, 2147483647]) + assert value[0] == 0 + assert value[1] == 2147483647 + assert value.Length == 2 + + value = Array[int]([0, 2147483647]) + assert value[0] == 0 + assert value[1] == 2147483647 + assert value.Length == 2 + + value = Array[System.Int64]([0, long(9223372036854775807)]) + assert value[0] == 0 + assert value[1] == long(9223372036854775807) + assert value.Length == 2 + + # there's no explicit long type in python3, use System.Int64 instead + if PY2: + value = Array[long]([0, long(9223372036854775807)]) + assert value[0] == 0 + assert value[1] == long(9223372036854775807) + assert value.Length == 2 + + value = Array[System.UInt16]([0, 65000]) + assert value[0] == 0 + assert value[1] == 65000 + assert value.Length == 2 + + value = Array[System.UInt32]([0, long(4294967295)]) + assert value[0] == 0 + assert value[1] == long(4294967295) + assert value.Length == 2 + + value = Array[System.UInt64]([0, long(18446744073709551615)]) + assert value[0] == 0 + assert value[1] == long(18446744073709551615) + assert value.Length == 2 + + value = Array[System.Single]([0.0, 3.402823e38]) + assert value[0] == 0.0 + assert value[1] == 3.402823e38 + assert value.Length == 2 + + value = Array[System.Double]([0.0, 1.7976931348623157e308]) + assert value[0] == 0.0 + assert value[1] == 1.7976931348623157e308 + assert value.Length == 2 + + value = Array[float]([0.0, 1.7976931348623157e308]) + assert value[0] == 0.0 + assert value[1] == 1.7976931348623157e308 + assert value.Length == 2 + + value = Array[System.Decimal]([System.Decimal.Zero, System.Decimal.One]) + assert value[0] == System.Decimal.Zero + assert value[1] == System.Decimal.One + assert value.Length == 2 + + value = Array[System.String](["one", "two"]) + assert value[0] == "one" + assert value[1] == "two" + assert value.Length == 2 + + value = Array[str](["one", "two"]) + assert value[0] == "one" + assert value[1] == "two" + assert value.Length == 2 + + value = Array[ShortEnum]([ShortEnum.Zero, ShortEnum.One]) + assert value[0] == ShortEnum.Zero + assert value[1] == ShortEnum.One + assert value.Length == 2 + + value = Array[System.Object]([inst, inst]) + assert value[0].__class__ == inst.__class__ + assert value[1].__class__ == inst.__class__ + assert value.Length == 2 + + value = Array[InterfaceTest]([inst, inst]) + assert value[0].__class__ == inst.__class__ + assert value[1].__class__ == inst.__class__ + assert value.Length == 2 + + value = Array[ISayHello1]([inst, inst]) + assert value[0].__class__ == inst.__class__ + assert value[1].__class__ == inst.__class__ + assert value.Length == 2 + + inst = System.Exception("badness") + value = Array[System.Exception]([inst, inst]) + assert value[0].__class__ == inst.__class__ + assert value[1].__class__ == inst.__class__ + assert value.Length == 2 + + +def test_array_abuse(): + """Test array abuse.""" + _class = Test.PublicArrayTest + ob = Test.PublicArrayTest() + + with pytest.raises(AttributeError): + del _class.__getitem__ + + with pytest.raises(AttributeError): + del ob.__getitem__ + + with pytest.raises(AttributeError): + del _class.__setitem__ + + with pytest.raises(AttributeError): + del ob.__setitem__ + + with pytest.raises(TypeError): + Test.PublicArrayTest.__getitem__(0, 0) + + with pytest.raises(TypeError): + Test.PublicArrayTest.__setitem__(0, 0, 0) + + with pytest.raises(TypeError): + desc = Test.PublicArrayTest.__dict__['__getitem__'] + desc(0, 0) + + with pytest.raises(TypeError): + desc = Test.PublicArrayTest.__dict__['__setitem__'] + desc(0, 0, 0) diff --git a/src/tests/test_callback.py b/src/tests/test_callback.py new file mode 100644 index 000000000..f94a9d52e --- /dev/null +++ b/src/tests/test_callback.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- + +"""Test that callbacks from C# into python work.""" + + +def simpleDefaultArg(arg='test'): + return arg + + +def test_default_for_null(): + """Test that C# can use null for an optional python argument""" + from Python.Test import CallbackTest + + test_instance = CallbackTest() + ret_val = test_instance.Call_simpleDefaultArg_WithNull(__name__) + python_ret_val = simpleDefaultArg(None) + assert ret_val == python_ret_val + + +def test_default_for_none(): + """Test that C# can use no argument for an optional python argument""" + from Python.Test import CallbackTest + + test_instance = CallbackTest() + ret_val = test_instance.Call_simpleDefaultArg_WithEmptyArgs(__name__) + python_ret_val = simpleDefaultArg() + assert ret_val == python_ret_val diff --git a/src/tests/test_class.py b/src/tests/test_class.py index bf3b6f143..68773508b 100644 --- a/src/tests/test_class.py +++ b/src/tests/test_class.py @@ -1,130 +1,138 @@ # -*- coding: utf-8 -*- # TODO: Add tests for ClassicClass, NewStyleClass? -import unittest +"""Test CLR class support.""" import Python.Test as Test import System +import pytest -from _compat import DictProxyType, range +from ._compat import DictProxyType, range -class ClassTests(unittest.TestCase): - """Test CLR class support.""" +def test_basic_reference_type(): + """Test usage of CLR defined reference types.""" + assert System.String.Empty == "" - def test_basic_reference_type(self): - """Test usage of CLR defined reference types.""" - self.assertEquals(System.String.Empty, "") - def test_basic_value_type(self): - """Test usage of CLR defined value types.""" - self.assertEquals(System.Int32.MaxValue, 2147483647) +def test_basic_value_type(): + """Test usage of CLR defined value types.""" + assert System.Int32.MaxValue == 2147483647 - def test_class_standard_attrs(self): - """Test standard class attributes.""" - from Python.Test import ClassTest - self.assertTrue(ClassTest.__name__ == 'ClassTest') - self.assertTrue(ClassTest.__module__ == 'Python.Test') - self.assertTrue(isinstance(ClassTest.__dict__, DictProxyType)) - self.assertTrue(len(ClassTest.__doc__) > 0) +def test_class_standard_attrs(): + """Test standard class attributes.""" + from Python.Test import ClassTest - def test_class_docstrings(self): - """Test standard class docstring generation""" - from Python.Test import ClassTest + assert ClassTest.__name__ == 'ClassTest' + assert ClassTest.__module__ == 'Python.Test' + assert isinstance(ClassTest.__dict__, DictProxyType) + assert len(ClassTest.__doc__) > 0 - value = 'Void .ctor()' - self.assertTrue(ClassTest.__doc__ == value) - def test_class_default_str(self): - """Test the default __str__ implementation for managed objects.""" - s = System.String("this is a test") - self.assertTrue(str(s) == "this is a test") +def test_class_docstrings(): + """Test standard class docstring generation""" + from Python.Test import ClassTest - def test_class_default_repr(self): - """Test the default __repr__ implementation for managed objects.""" - s = System.String("this is a test") - self.assertTrue(repr(s).startswith(" -1) and (item < 10) + + dict_ = ClassTest.GetHashtable() + + for item in dict_: + cname = item.__class__.__name__ + assert cname.endswith('DictionaryEntry') + - for item in list_: - self.assertTrue((item > -1) and (item < 10)) +def test_ienumerator_iteration(): + """Test iteration over objects supporting IEnumerator.""" + from Python.Test import ClassTest - dict_ = ClassTest.GetHashtable() + chars = ClassTest.GetEnumerator() - for item in dict_: - cname = item.__class__.__name__ - self.assertTrue(cname.endswith('DictionaryEntry')) + for item in chars: + assert item in 'test string' - def test_ienumerator_iteration(self): - """Test iteration over objects supporting IEnumerator.""" - from Python.Test import ClassTest - chars = ClassTest.GetEnumerator() +def test_override_get_item(): + """Test managed subclass overriding __getitem__.""" + from System.Collections import Hashtable - for item in chars: - self.assertTrue(item in 'test string') + class MyTable(Hashtable): + def __getitem__(self, key): + value = Hashtable.__getitem__(self, key) + return 'my ' + str(value) - def test_override_get_item(self): - """Test managed subclass overriding __getitem__.""" - from System.Collections import Hashtable + table = MyTable() + table['one'] = 'one' + table['two'] = 'two' + table['three'] = 'three' - class MyTable(Hashtable): - def __getitem__(self, key): - value = Hashtable.__getitem__(self, key) - return 'my ' + str(value) + assert table['one'] == 'my one' + assert table['two'] == 'my two' + assert table['three'] == 'my three' - table = MyTable() - table['one'] = 'one' - table['two'] = 'two' - table['three'] = 'three' + assert table.Count == 3 - self.assertTrue(table['one'] == 'my one') - self.assertTrue(table['two'] == 'my two') - self.assertTrue(table['three'] == 'my three') - self.assertTrue(table.Count == 3) +def test_override_set_item(): + """Test managed subclass overriding __setitem__.""" + from System.Collections import Hashtable - def test_override_set_item(self): - """Test managed subclass overriding __setitem__.""" - from System.Collections import Hashtable + class MyTable(Hashtable): + def __setitem__(self, key, value): + value = 'my ' + str(value) + Hashtable.__setitem__(self, key, value) - class MyTable(Hashtable): - def __setitem__(self, key, value): - value = 'my ' + str(value) - Hashtable.__setitem__(self, key, value) + table = MyTable() + table['one'] = 'one' + table['two'] = 'two' + table['three'] = 'three' - table = MyTable() - table['one'] = 'one' - table['two'] = 'two' - table['three'] = 'three' + assert table['one'] == 'my one' + assert table['two'] == 'my two' + assert table['three'] == 'my three' - self.assertTrue(table['one'] == 'my one') - self.assertTrue(table['two'] == 'my two') - self.assertTrue(table['three'] == 'my three') + assert table.Count == 3 - self.assertTrue(table.Count == 3) - def test_add_and_remove_class_attribute(self): - from System import TimeSpan +def test_add_and_remove_class_attribute(): + from System import TimeSpan - for _ 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")) + for _ in range(100): + TimeSpan.new_method = lambda self_: self_.TotalMinutes + ts = TimeSpan.FromHours(1) + assert ts.new_method() == 60 + del TimeSpan.new_method + assert not hasattr(ts, "new_method") - def test_comparisons(self): - from System import DateTimeOffset - from Python.Test import ClassTest - d1 = DateTimeOffset.Parse("2016-11-14") - d2 = DateTimeOffset.Parse("2016-11-15") +def test_comparisons(): + from System import DateTimeOffset + from Python.Test import ClassTest - self.assertEqual(d1 == d2, False) - self.assertEqual(d1 != d2, True) + d1 = DateTimeOffset.Parse("2016-11-14") + d2 = DateTimeOffset.Parse("2016-11-15") - self.assertEqual(d1 < d2, True) - self.assertEqual(d1 <= d2, True) - self.assertEqual(d1 >= d2, False) - self.assertEqual(d1 > d2, False) + assert (d1 == d2) == False + assert (d1 != d2) == True - self.assertEqual(d1 == d1, True) - self.assertEqual(d1 != d1, False) + assert (d1 < d2) == True + assert (d1 <= d2) == True + assert (d1 >= d2) == False + assert (d1 > d2) == False - self.assertEqual(d1 < d1, False) - self.assertEqual(d1 <= d1, True) - self.assertEqual(d1 >= d1, True) - self.assertEqual(d1 > d1, False) + assert (d1 == d1) == True + assert (d1 != d1) == False - self.assertEqual(d2 == d1, False) - self.assertEqual(d2 != d1, True) + assert (d1 < d1) == False + assert (d1 <= d1) == True + assert (d1 >= d1) == True + assert (d1 > d1) == False - self.assertEqual(d2 < d1, False) - self.assertEqual(d2 <= d1, False) - self.assertEqual(d2 >= d1, True) - self.assertEqual(d2 > d1, True) + assert (d2 == d1) == False + assert (d2 != d1) == True - with self.assertRaises(TypeError): - d1 < None + assert (d2 < d1) == False + assert (d2 <= d1) == False + assert (d2 >= d1) == True + assert (d2 > d1) == True - with self.assertRaises(TypeError): - d1 < System.Guid() + with pytest.raises(TypeError): + d1 < None - # ClassTest does not implement IComparable - c1 = ClassTest() - c2 = ClassTest() - with self.assertRaises(TypeError): - c1 < c2 + with pytest.raises(TypeError): + d1 < System.Guid() - def test_self_callback(self): - """Test calling back and forth between this and a c# baseclass.""" + # ClassTest does not implement IComparable + c1 = ClassTest() + c2 = ClassTest() + with pytest.raises(TypeError): + c1 < c2 - 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 +def test_self_callback(): + """Test calling back and forth between this and a c# baseclass.""" - testobj = CallbackUser() - testobj.DoCallback() - self.assertTrue(testobj.PyCallbackWasCalled) - self.assertTrue(testobj.SameReference) + 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 -def test_suite(): - return unittest.makeSuite(ClassTests) + testobj = CallbackUser() + testobj.DoCallback() + assert testobj.PyCallbackWasCalled + assert testobj.SameReference diff --git a/src/tests/test_compat.py b/src/tests/test_compat.py index cea51ca49..81e7f8143 100644 --- a/src/tests/test_compat.py +++ b/src/tests/test_compat.py @@ -1,233 +1,243 @@ # -*- coding: utf-8 -*- # TODO: Complete removal of methods below. Similar to test_module +"""Backward-compatibility tests for deprecated features.""" + import types -import unittest -from _compat import ClassType, PY2, PY3, range -from utils import is_clr_class, is_clr_module, is_clr_root_module +import pytest +from ._compat import ClassType, PY2, PY3, range +from .utils import is_clr_class, is_clr_module, is_clr_root_module -class CompatibilityTests(unittest.TestCase): - """Backward-compatibility tests for deprecated features.""" - # Tests for old-style CLR-prefixed module naming. +# Tests for old-style CLR-prefixed module naming. +def test_simple_import(): + """Test simple import.""" + import CLR + assert is_clr_root_module(CLR) + assert CLR.__name__ == 'clr' - def test_simple_import(self): - """Test simple import.""" - import CLR - self.assertTrue(is_clr_root_module(CLR)) - self.assertTrue(CLR.__name__ == 'clr') - - import sys - self.assertTrue(isinstance(sys, types.ModuleType)) - self.assertTrue(sys.__name__ == 'sys') - - if PY3: - import http.client - self.assertTrue(isinstance(http.client, types.ModuleType)) - self.assertTrue(http.client.__name__ == 'http.client') - - elif PY2: - import httplib - self.assertTrue(isinstance(httplib, types.ModuleType)) - self.assertTrue(httplib.__name__ == 'httplib') - - def test_simple_import_with_alias(self): - """Test simple import with aliasing.""" - import CLR as myCLR - self.assertTrue(is_clr_root_module(myCLR)) - self.assertTrue(myCLR.__name__ == 'clr') - - import sys as mySys - self.assertTrue(isinstance(mySys, types.ModuleType)) - self.assertTrue(mySys.__name__ == 'sys') - - if PY3: - import http.client as myHttplib - self.assertTrue(isinstance(myHttplib, types.ModuleType)) - self.assertTrue(myHttplib.__name__ == 'http.client') - - elif PY2: - import httplib as myHttplib - self.assertTrue(isinstance(myHttplib, types.ModuleType)) - self.assertTrue(myHttplib.__name__ == 'httplib') - - def test_dotted_name_import(self): - """Test dotted-name import.""" - import CLR.System - self.assertTrue(is_clr_module(CLR.System)) - self.assertTrue(CLR.System.__name__ == 'System') - - import System - self.assertTrue(is_clr_module(System)) - self.assertTrue(System.__name__ == 'System') - - self.assertTrue(System is CLR.System) - - import xml.dom - self.assertTrue(isinstance(xml.dom, types.ModuleType)) - self.assertTrue(xml.dom.__name__ == 'xml.dom') - - def test_dotted_name_import_with_alias(self): - """Test dotted-name import with aliasing.""" - import CLR.System as myCLRSystem - self.assertTrue(is_clr_module(myCLRSystem)) - self.assertTrue(myCLRSystem.__name__ == 'System') - - import System as mySystem - self.assertTrue(is_clr_module(mySystem)) - self.assertTrue(mySystem.__name__ == 'System') - - self.assertTrue(mySystem is myCLRSystem) - - import xml.dom as myDom - self.assertTrue(isinstance(myDom, types.ModuleType)) - self.assertTrue(myDom.__name__ == 'xml.dom') - - def test_simple_import_from(self): - """Test simple 'import from'.""" - from CLR import System - self.assertTrue(is_clr_module(System)) - self.assertTrue(System.__name__ == 'System') - - from xml import dom - self.assertTrue(isinstance(dom, types.ModuleType)) - self.assertTrue(dom.__name__ == 'xml.dom') - - def test_simple_import_from_with_alias(self): - """Test simple 'import from' with aliasing.""" - from CLR import System as mySystem - self.assertTrue(is_clr_module(mySystem)) - self.assertTrue(mySystem.__name__ == 'System') - - from xml import dom as myDom - self.assertTrue(isinstance(myDom, types.ModuleType)) - self.assertTrue(myDom.__name__ == 'xml.dom') - - def test_dotted_name_import_from(self): - """Test dotted-name 'import from'.""" - from CLR.System import Xml - self.assertTrue(is_clr_module(Xml)) - self.assertTrue(Xml.__name__ == 'System.Xml') - - from CLR.System.Xml import XmlDocument - self.assertTrue(is_clr_class(XmlDocument)) - self.assertTrue(XmlDocument.__name__ == 'XmlDocument') - - from xml.dom import pulldom - self.assertTrue(isinstance(pulldom, types.ModuleType)) - self.assertTrue(pulldom.__name__ == 'xml.dom.pulldom') - - from xml.dom.pulldom import PullDOM - self.assertTrue(isinstance(PullDOM, ClassType)) - self.assertTrue(PullDOM.__name__ == 'PullDOM') - - def test_dotted_name_import_from_with_alias(self): - """Test dotted-name 'import from' with aliasing.""" - from CLR.System import Xml as myXml - self.assertTrue(is_clr_module(myXml)) - self.assertTrue(myXml.__name__ == 'System.Xml') - - from CLR.System.Xml import XmlDocument as myXmlDocument - self.assertTrue(is_clr_class(myXmlDocument)) - self.assertTrue(myXmlDocument.__name__ == 'XmlDocument') - - from xml.dom import pulldom as myPulldom - self.assertTrue(isinstance(myPulldom, types.ModuleType)) - self.assertTrue(myPulldom.__name__ == 'xml.dom.pulldom') - - from xml.dom.pulldom import PullDOM as myPullDOM - self.assertTrue(isinstance(myPullDOM, ClassType)) - self.assertTrue(myPullDOM.__name__ == 'PullDOM') - - def test_from_module_import_star(self): - """Test from module import * behavior.""" - count = len(locals().keys()) - m = __import__('CLR.System.Management', globals(), locals(), ['*']) - self.assertTrue(m.__name__ == 'System.Management') - self.assertTrue(is_clr_module(m)) - self.assertTrue(len(locals().keys()) > count + 1) - - m2 = __import__('System.Management', globals(), locals(), ['*']) - self.assertTrue(m2.__name__ == 'System.Management') - self.assertTrue(is_clr_module(m2)) - self.assertTrue(len(locals().keys()) > count + 1) - - self.assertTrue(m is m2) - - def test_explicit_assembly_load(self): - """Test explicit assembly loading using standard CLR tools.""" - from CLR.System.Reflection import Assembly - from CLR import System - import sys - - assembly = Assembly.LoadWithPartialName('System.Data') - self.assertTrue(assembly is not None) - - import CLR.System.Data - self.assertTrue('System.Data' in sys.modules) - - assembly = Assembly.LoadWithPartialName('SpamSpamSpamSpamEggsAndSpam') - self.assertTrue(assembly is None) - - def test_implicit_load_already_valid_namespace(self): - """Test implicit assembly load over an already valid namespace.""" - # In this case, the mscorlib assembly (loaded by default) defines - # a number of types in the System namespace. There is also a System - # assembly, which is _not_ loaded by default, which also contains - # types in the System namespace. The desired behavior is for the - # Python runtime to "do the right thing", allowing types from both - # assemblies to be found in the CLR.System module implicitly. - import CLR.System - self.assertTrue(is_clr_class(CLR.System.UriBuilder)) - - def test_import_non_existant_module(self): - """Test import failure for a non-existent module.""" - with self.assertRaises(ImportError): - import System.SpamSpamSpam - - with self.assertRaises(ImportError): - import CLR.System.SpamSpamSpam - - def test_lookup_no_namespace_type(self): - """Test lookup of types without a qualified namespace.""" - import CLR.Python.Test - import CLR - self.assertTrue(is_clr_class(CLR.NoNamespaceType)) + import sys + assert isinstance(sys, types.ModuleType) + assert sys.__name__ == 'sys' + + if PY3: + import http.client + assert isinstance(http.client, types.ModuleType) + assert http.client.__name__ == 'http.client' + + elif PY2: + import httplib + assert isinstance(httplib, types.ModuleType) + assert httplib.__name__ == 'httplib' + + +def test_simple_import_with_alias(): + """Test simple import with aliasing.""" + import CLR as myCLR + assert is_clr_root_module(myCLR) + assert myCLR.__name__ == 'clr' + + import sys as mySys + assert isinstance(mySys, types.ModuleType) + assert mySys.__name__ == 'sys' + + if PY3: + import http.client as myHttplib + assert isinstance(myHttplib, types.ModuleType) + assert myHttplib.__name__ == 'http.client' + + elif PY2: + import httplib as myHttplib + assert isinstance(myHttplib, types.ModuleType) + assert myHttplib.__name__ == 'httplib' + + +def test_dotted_name_import(): + """Test dotted-name import.""" + import CLR.System + assert is_clr_module(CLR.System) + assert CLR.System.__name__ == 'System' + + import System + assert is_clr_module(System) + assert System.__name__ == 'System' + + assert System is CLR.System + + import xml.dom + assert isinstance(xml.dom, types.ModuleType) + assert xml.dom.__name__ == 'xml.dom' + + +def test_dotted_name_import_with_alias(): + """Test dotted-name import with aliasing.""" + import CLR.System as myCLRSystem + assert is_clr_module(myCLRSystem) + assert myCLRSystem.__name__ == 'System' + + import System as mySystem + assert is_clr_module(mySystem) + assert mySystem.__name__ == 'System' + + assert mySystem is myCLRSystem + + import xml.dom as myDom + assert isinstance(myDom, types.ModuleType) + assert myDom.__name__ == 'xml.dom' + + +def test_simple_import_from(): + """Test simple 'import from'.""" + from CLR import System + assert is_clr_module(System) + assert System.__name__ == 'System' + + from xml import dom + assert isinstance(dom, types.ModuleType) + assert dom.__name__ == 'xml.dom' + + +def test_simple_import_from_with_alias(): + """Test simple 'import from' with aliasing.""" + from CLR import System as mySystem + assert is_clr_module(mySystem) + assert mySystem.__name__ == 'System' + + from xml import dom as myDom + assert isinstance(myDom, types.ModuleType) + assert myDom.__name__ == 'xml.dom' + + +def test_dotted_name_import_from(): + """Test dotted-name 'import from'.""" + from CLR.System import Xml + assert is_clr_module(Xml) + assert Xml.__name__ == 'System.Xml' - def test_module_lookup_recursion(self): - """Test for recursive lookup handling.""" - with self.assertRaises(ImportError): - from CLR import CLR + from CLR.System.Xml import XmlDocument + assert is_clr_class(XmlDocument) + assert XmlDocument.__name__ == 'XmlDocument' - with self.assertRaises(AttributeError): - import CLR - _ = CLR.CLR + from xml.dom import pulldom + assert isinstance(pulldom, types.ModuleType) + assert pulldom.__name__ == 'xml.dom.pulldom' - def test_module_get_attr(self): - """Test module getattr behavior.""" - import CLR.System as System + from xml.dom.pulldom import PullDOM + assert isinstance(PullDOM, ClassType) + assert PullDOM.__name__ == 'PullDOM' - int_type = System.Int32 - self.assertTrue(is_clr_class(int_type)) - module = System.Xml - self.assertTrue(is_clr_module(module)) +def test_dotted_name_import_from_with_alias(): + """Test dotted-name 'import from' with aliasing.""" + from CLR.System import Xml as myXml + assert is_clr_module(myXml) + assert myXml.__name__ == 'System.Xml' - with self.assertRaises(AttributeError): - _ = System.Spam + from CLR.System.Xml import XmlDocument as myXmlDocument + assert is_clr_class(myXmlDocument) + assert myXmlDocument.__name__ == 'XmlDocument' - with self.assertRaises(TypeError): - _ = getattr(System, 1) + from xml.dom import pulldom as myPulldom + assert isinstance(myPulldom, types.ModuleType) + assert myPulldom.__name__ == 'xml.dom.pulldom' - def test_multiple_imports(self): - # import CLR did raise a Seg Fault once - # test if the Exceptions.warn() method still causes it - for _ in range(100): - import CLR - _ = CLR + from xml.dom.pulldom import PullDOM as myPullDOM + assert isinstance(myPullDOM, ClassType) + assert myPullDOM.__name__ == 'PullDOM' -def test_suite(): - return unittest.makeSuite(CompatibilityTests) +def test_from_module_import_star(): + """Test from module import * behavior.""" + count = len(locals().keys()) + m = __import__('CLR.System.Management', globals(), locals(), ['*']) + assert m.__name__ == 'System.Management' + assert is_clr_module(m) + assert len(locals().keys()) > count + 1 + + m2 = __import__('System.Management', globals(), locals(), ['*']) + assert m2.__name__ == 'System.Management' + assert is_clr_module(m2) + assert len(locals().keys()) > count + 1 + + assert m is m2 + + +def test_explicit_assembly_load(): + """Test explicit assembly loading using standard CLR tools.""" + from CLR.System.Reflection import Assembly + from CLR import System + import sys + + assembly = Assembly.LoadWithPartialName('System.Data') + assert assembly is not None + + import CLR.System.Data + assert 'System.Data' in sys.modules + + assembly = Assembly.LoadWithPartialName('SpamSpamSpamSpamEggsAndSpam') + assert assembly is None + + +def test_implicit_load_already_valid_namespace(): + """Test implicit assembly load over an already valid namespace.""" + # In this case, the mscorlib assembly (loaded by default) defines + # a number of types in the System namespace. There is also a System + # assembly, which is _not_ loaded by default, which also contains + # types in the System namespace. The desired behavior is for the + # Python runtime to "do the right thing", allowing types from both + # assemblies to be found in the CLR.System module implicitly. + import CLR.System + assert is_clr_class(CLR.System.UriBuilder) + + +def test_import_non_existant_module(): + """Test import failure for a non-existent module.""" + with pytest.raises(ImportError): + import System.SpamSpamSpam + + with pytest.raises(ImportError): + import CLR.System.SpamSpamSpam + + +def test_lookup_no_namespace_type(): + """Test lookup of types without a qualified namespace.""" + import CLR.Python.Test + import CLR + assert is_clr_class(CLR.NoNamespaceType) + + +def test_module_lookup_recursion(): + """Test for recursive lookup handling.""" + with pytest.raises(ImportError): + from CLR import CLR + + with pytest.raises(AttributeError): + import CLR + _ = CLR.CLR + + +def test_module_get_attr(): + """Test module getattr behavior.""" + import CLR.System as System + + int_type = System.Int32 + assert is_clr_class(int_type) + + module = System.Xml + assert is_clr_module(module) + + with pytest.raises(AttributeError): + _ = System.Spam + + with pytest.raises(TypeError): + _ = getattr(System, 1) + + +def test_multiple_imports(): + # import CLR did raise a Seg Fault once + # test if the Exceptions.warn() method still causes it + for _ in range(100): + import CLR + _ = CLR diff --git a/src/tests/test_constructors.py b/src/tests/test_constructors.py index 0039f9bf3..5e5489630 100644 --- a/src/tests/test_constructors.py +++ b/src/tests/test_constructors.py @@ -1,50 +1,46 @@ # -*- coding: utf-8 -*- -import unittest +"""Test CLR class constructor support.""" import System -class ConstructorTests(unittest.TestCase): - """Test CLR class constructor support.""" +def test_enum_constructor(): + """Test enum constructor args""" + from System import TypeCode + from Python.Test import EnumConstructorTest - def test_enum_constructor(self): - """Test enum constructor args""" - from System import TypeCode - from Python.Test import EnumConstructorTest + ob = EnumConstructorTest(TypeCode.Int32) + assert ob.value == TypeCode.Int32 - ob = EnumConstructorTest(TypeCode.Int32) - self.assertTrue(ob.value == TypeCode.Int32) - def test_flags_constructor(self): - """Test flags constructor args""" - from Python.Test import FlagsConstructorTest - from System.IO import FileAccess +def test_flags_constructor(): + """Test flags constructor args""" + from Python.Test import FlagsConstructorTest + from System.IO import FileAccess - flags = FileAccess.Read | FileAccess.Write - ob = FlagsConstructorTest(flags) - self.assertTrue(ob.value == flags) + flags = FileAccess.Read | FileAccess.Write + ob = FlagsConstructorTest(flags) + assert ob.value == flags - def test_struct_constructor(self): - """Test struct constructor args""" - from System import Guid - from Python.Test import StructConstructorTest - guid = Guid.NewGuid() - ob = StructConstructorTest(guid) - self.assertTrue(ob.value == guid) +def test_struct_constructor(): + """Test struct constructor args""" + from System import Guid + from Python.Test import StructConstructorTest - def test_subclass_constructor(self): - """Test subclass constructor args""" - from Python.Test import SubclassConstructorTest + guid = Guid.NewGuid() + ob = StructConstructorTest(guid) + assert ob.value == guid - class Sub(System.Exception): - pass - instance = Sub() - ob = SubclassConstructorTest(instance) - self.assertTrue(isinstance(ob.value, System.Exception)) +def test_subclass_constructor(): + """Test subclass constructor args""" + from Python.Test import SubclassConstructorTest + class Sub(System.Exception): + pass -def test_suite(): - return unittest.makeSuite(ConstructorTests) + instance = Sub() + ob = SubclassConstructorTest(instance) + assert isinstance(ob.value, System.Exception) diff --git a/src/tests/test_conversion.py b/src/tests/test_conversion.py index 0d0cd4008..ac263ef5d 100644 --- a/src/tests/test_conversion.py +++ b/src/tests/test_conversion.py @@ -1,684 +1,699 @@ # -*- coding: utf-8 -*- -import unittest +"""Test CLR <-> Python type conversions.""" import System +import pytest from Python.Test import ConversionTest -from _compat import indexbytes, long, unichr +from ._compat import indexbytes, long, unichr -class ConversionTests(unittest.TestCase): - """Test CLR <-> Python type conversions.""" +def test_bool_conversion(): + """Test bool conversion.""" + ob = ConversionTest() + assert ob.BooleanField is False + assert ob.BooleanField is False + assert ob.BooleanField == 0 - def test_bool_conversion(self): - """Test bool conversion.""" - ob = ConversionTest() - self.assertTrue(ob.BooleanField is False) - self.assertTrue(ob.BooleanField is False) - self.assertTrue(ob.BooleanField == 0) - - ob.BooleanField = True - self.assertTrue(ob.BooleanField is True) - self.assertTrue(ob.BooleanField is True) - self.assertTrue(ob.BooleanField == 1) - - ob.BooleanField = False - self.assertTrue(ob.BooleanField is False) - self.assertTrue(ob.BooleanField is False) - self.assertTrue(ob.BooleanField == 0) - - ob.BooleanField = 1 - self.assertTrue(ob.BooleanField is True) - self.assertTrue(ob.BooleanField is True) - self.assertTrue(ob.BooleanField == 1) - - ob.BooleanField = 0 - self.assertTrue(ob.BooleanField is False) - self.assertTrue(ob.BooleanField is False) - self.assertTrue(ob.BooleanField == 0) - - ob.BooleanField = System.Boolean(None) - self.assertTrue(ob.BooleanField is False) - self.assertTrue(ob.BooleanField is False) - self.assertTrue(ob.BooleanField == 0) - - ob.BooleanField = System.Boolean('') - self.assertTrue(ob.BooleanField is False) - self.assertTrue(ob.BooleanField is False) - self.assertTrue(ob.BooleanField == 0) - - ob.BooleanField = System.Boolean(0) - self.assertTrue(ob.BooleanField is False) - self.assertTrue(ob.BooleanField is False) - self.assertTrue(ob.BooleanField == 0) - - ob.BooleanField = System.Boolean(1) - self.assertTrue(ob.BooleanField is True) - self.assertTrue(ob.BooleanField is True) - self.assertTrue(ob.BooleanField == 1) - - ob.BooleanField = System.Boolean('a') - self.assertTrue(ob.BooleanField is True) - self.assertTrue(ob.BooleanField is True) - self.assertTrue(ob.BooleanField == 1) - - def test_sbyte_conversion(self): - """Test sbyte conversion.""" - self.assertTrue(System.SByte.MaxValue == 127) - self.assertTrue(System.SByte.MinValue == -128) + ob.BooleanField = True + assert ob.BooleanField is True + assert ob.BooleanField is True + assert ob.BooleanField == 1 - ob = ConversionTest() - self.assertTrue(ob.SByteField == 0) + ob.BooleanField = False + assert ob.BooleanField is False + assert ob.BooleanField is False + assert ob.BooleanField == 0 - ob.SByteField = 127 - self.assertTrue(ob.SByteField == 127) + ob.BooleanField = 1 + assert ob.BooleanField is True + assert ob.BooleanField is True + assert ob.BooleanField == 1 - ob.SByteField = -128 - self.assertTrue(ob.SByteField == -128) + ob.BooleanField = 0 + assert ob.BooleanField is False + assert ob.BooleanField is False + assert ob.BooleanField == 0 - ob.SByteField = System.SByte(127) - self.assertTrue(ob.SByteField == 127) + ob.BooleanField = System.Boolean(None) + assert ob.BooleanField is False + assert ob.BooleanField is False + assert ob.BooleanField == 0 - ob.SByteField = System.SByte(-128) - self.assertTrue(ob.SByteField == -128) + ob.BooleanField = System.Boolean('') + assert ob.BooleanField is False + assert ob.BooleanField is False + assert ob.BooleanField == 0 - with self.assertRaises(TypeError): - ConversionTest().SByteField = "spam" + ob.BooleanField = System.Boolean(0) + assert ob.BooleanField is False + assert ob.BooleanField is False + assert ob.BooleanField == 0 - with self.assertRaises(TypeError): - ConversionTest().SByteField = None + ob.BooleanField = System.Boolean(1) + assert ob.BooleanField is True + assert ob.BooleanField is True + assert ob.BooleanField == 1 - with self.assertRaises(OverflowError): - ConversionTest().SByteField = 128 + ob.BooleanField = System.Boolean('a') + assert ob.BooleanField is True + assert ob.BooleanField is True + assert ob.BooleanField == 1 - with self.assertRaises(OverflowError): - ConversionTest().SByteField = -129 - with self.assertRaises(OverflowError): - _ = System.SByte(128) +def test_sbyte_conversion(): + """Test sbyte conversion.""" + assert System.SByte.MaxValue == 127 + assert System.SByte.MinValue == -128 - with self.assertRaises(OverflowError): - _ = System.SByte(-129) + ob = ConversionTest() + assert ob.SByteField == 0 - def test_byte_conversion(self): - """Test byte conversion.""" - self.assertTrue(System.Byte.MaxValue == 255) - self.assertTrue(System.Byte.MinValue == 0) + ob.SByteField = 127 + assert ob.SByteField == 127 - ob = ConversionTest() - self.assertTrue(ob.ByteField == 0) + ob.SByteField = -128 + assert ob.SByteField == -128 - ob.ByteField = 255 - self.assertTrue(ob.ByteField == 255) + ob.SByteField = System.SByte(127) + assert ob.SByteField == 127 - ob.ByteField = 0 - self.assertTrue(ob.ByteField == 0) + ob.SByteField = System.SByte(-128) + assert ob.SByteField == -128 - ob.ByteField = System.Byte(255) - self.assertTrue(ob.ByteField == 255) + with pytest.raises(TypeError): + ConversionTest().SByteField = "spam" - ob.ByteField = System.Byte(0) - self.assertTrue(ob.ByteField == 0) + with pytest.raises(TypeError): + ConversionTest().SByteField = None - with self.assertRaises(TypeError): - ConversionTest().ByteField = "spam" + with pytest.raises(OverflowError): + ConversionTest().SByteField = 128 - with self.assertRaises(TypeError): - ConversionTest().ByteField = None + with pytest.raises(OverflowError): + ConversionTest().SByteField = -129 - with self.assertRaises(OverflowError): - ConversionTest().ByteField = 256 + with pytest.raises(OverflowError): + _ = System.SByte(128) - with self.assertRaises(OverflowError): - ConversionTest().ByteField = -1 + with pytest.raises(OverflowError): + _ = System.SByte(-129) - with self.assertRaises(OverflowError): - _ = System.Byte(256) - with self.assertRaises(OverflowError): - _ = System.Byte(-1) +def test_byte_conversion(): + """Test byte conversion.""" + assert System.Byte.MaxValue == 255 + assert System.Byte.MinValue == 0 - def test_char_conversion(self): - """Test char conversion.""" - self.assertTrue(System.Char.MaxValue == unichr(65535)) - self.assertTrue(System.Char.MinValue == unichr(0)) + ob = ConversionTest() + assert ob.ByteField == 0 - ob = ConversionTest() - self.assertTrue(ob.CharField == u'A') + ob.ByteField = 255 + assert ob.ByteField == 255 - ob.CharField = 'B' - self.assertTrue(ob.CharField == u'B') + ob.ByteField = 0 + assert ob.ByteField == 0 - ob.CharField = u'B' - self.assertTrue(ob.CharField == u'B') + ob.ByteField = System.Byte(255) + assert ob.ByteField == 255 - ob.CharField = 67 - self.assertTrue(ob.CharField == u'C') + ob.ByteField = System.Byte(0) + assert ob.ByteField == 0 - with self.assertRaises(OverflowError): - ConversionTest().CharField = 65536 + with pytest.raises(TypeError): + ConversionTest().ByteField = "spam" - with self.assertRaises(OverflowError): - ConversionTest().CharField = -1 + with pytest.raises(TypeError): + ConversionTest().ByteField = None - with self.assertRaises(TypeError): - ConversionTest().CharField = None + with pytest.raises(OverflowError): + ConversionTest().ByteField = 256 - def test_int16_conversion(self): - """Test int16 conversion.""" - self.assertTrue(System.Int16.MaxValue == 32767) - self.assertTrue(System.Int16.MinValue == -32768) + with pytest.raises(OverflowError): + ConversionTest().ByteField = -1 - ob = ConversionTest() - self.assertTrue(ob.Int16Field == 0) + with pytest.raises(OverflowError): + _ = System.Byte(256) - ob.Int16Field = 32767 - self.assertTrue(ob.Int16Field == 32767) + with pytest.raises(OverflowError): + _ = System.Byte(-1) - ob.Int16Field = -32768 - self.assertTrue(ob.Int16Field == -32768) - ob.Int16Field = System.Int16(32767) - self.assertTrue(ob.Int16Field == 32767) +def test_char_conversion(): + """Test char conversion.""" + assert System.Char.MaxValue == unichr(65535) + assert System.Char.MinValue == unichr(0) - ob.Int16Field = System.Int16(-32768) - self.assertTrue(ob.Int16Field == -32768) + ob = ConversionTest() + assert ob.CharField == u'A' - with self.assertRaises(TypeError): - ConversionTest().Int16Field = "spam" + ob.CharField = 'B' + assert ob.CharField == u'B' - with self.assertRaises(TypeError): - ConversionTest().Int16Field = None + ob.CharField = u'B' + assert ob.CharField == u'B' - with self.assertRaises(OverflowError): - ConversionTest().Int16Field = 32768 + ob.CharField = 67 + assert ob.CharField == u'C' - with self.assertRaises(OverflowError): - ConversionTest().Int16Field = -32769 + with pytest.raises(OverflowError): + ConversionTest().CharField = 65536 - with self.assertRaises(OverflowError): - _ = System.Int16(32768) + with pytest.raises(OverflowError): + ConversionTest().CharField = -1 - with self.assertRaises(OverflowError): - _ = System.Int16(-32769) + with pytest.raises(TypeError): + ConversionTest().CharField = None - def test_int32_conversion(self): - """Test int32 conversion.""" - self.assertTrue(System.Int32.MaxValue == 2147483647) - self.assertTrue(System.Int32.MinValue == -2147483648) - ob = ConversionTest() - self.assertTrue(ob.Int32Field == 0) +def test_int16_conversion(): + """Test int16 conversion.""" + assert System.Int16.MaxValue == 32767 + assert System.Int16.MinValue == -32768 - ob.Int32Field = 2147483647 - self.assertTrue(ob.Int32Field == 2147483647) + ob = ConversionTest() + assert ob.Int16Field == 0 - ob.Int32Field = -2147483648 - self.assertTrue(ob.Int32Field == -2147483648) + ob.Int16Field = 32767 + assert ob.Int16Field == 32767 - ob.Int32Field = System.Int32(2147483647) - self.assertTrue(ob.Int32Field == 2147483647) + ob.Int16Field = -32768 + assert ob.Int16Field == -32768 - ob.Int32Field = System.Int32(-2147483648) - self.assertTrue(ob.Int32Field == -2147483648) + ob.Int16Field = System.Int16(32767) + assert ob.Int16Field == 32767 - with self.assertRaises(TypeError): - ConversionTest().Int32Field = "spam" + ob.Int16Field = System.Int16(-32768) + assert ob.Int16Field == -32768 - with self.assertRaises(TypeError): - ConversionTest().Int32Field = None + with pytest.raises(TypeError): + ConversionTest().Int16Field = "spam" - with self.assertRaises(OverflowError): - ConversionTest().Int32Field = 2147483648 + with pytest.raises(TypeError): + ConversionTest().Int16Field = None - with self.assertRaises(OverflowError): - ConversionTest().Int32Field = -2147483649 + with pytest.raises(OverflowError): + ConversionTest().Int16Field = 32768 - with self.assertRaises(OverflowError): - _ = System.Int32(2147483648) + with pytest.raises(OverflowError): + ConversionTest().Int16Field = -32769 - with self.assertRaises(OverflowError): - _ = System.Int32(-2147483649) + with pytest.raises(OverflowError): + _ = System.Int16(32768) - def test_int64_conversion(self): - """Test int64 conversion.""" - self.assertTrue(System.Int64.MaxValue == long(9223372036854775807)) - self.assertTrue(System.Int64.MinValue == long(-9223372036854775808)) + with pytest.raises(OverflowError): + _ = System.Int16(-32769) - ob = ConversionTest() - self.assertTrue(ob.Int64Field == 0) - ob.Int64Field = long(9223372036854775807) - self.assertTrue(ob.Int64Field == long(9223372036854775807)) +def test_int32_conversion(): + """Test int32 conversion.""" + assert System.Int32.MaxValue == 2147483647 + assert System.Int32.MinValue == -2147483648 - ob.Int64Field = long(-9223372036854775808) - self.assertTrue(ob.Int64Field == long(-9223372036854775808)) + ob = ConversionTest() + assert ob.Int32Field == 0 - ob.Int64Field = System.Int64(long(9223372036854775807)) - self.assertTrue(ob.Int64Field == long(9223372036854775807)) + ob.Int32Field = 2147483647 + assert ob.Int32Field == 2147483647 - ob.Int64Field = System.Int64(long(-9223372036854775808)) - self.assertTrue(ob.Int64Field == long(-9223372036854775808)) + ob.Int32Field = -2147483648 + assert ob.Int32Field == -2147483648 - with self.assertRaises(TypeError): - ConversionTest().Int64Field = "spam" + ob.Int32Field = System.Int32(2147483647) + assert ob.Int32Field == 2147483647 - with self.assertRaises(TypeError): - ConversionTest().Int64Field = None + ob.Int32Field = System.Int32(-2147483648) + assert ob.Int32Field == -2147483648 - with self.assertRaises(OverflowError): - ConversionTest().Int64Field = long(9223372036854775808) + with pytest.raises(TypeError): + ConversionTest().Int32Field = "spam" - with self.assertRaises(OverflowError): - ConversionTest().Int64Field = long(-9223372036854775809) + with pytest.raises(TypeError): + ConversionTest().Int32Field = None - with self.assertRaises(OverflowError): - _ = System.Int64(long(9223372036854775808)) + with pytest.raises(OverflowError): + ConversionTest().Int32Field = 2147483648 - with self.assertRaises(OverflowError): - _ = System.Int64(long(-9223372036854775809)) + with pytest.raises(OverflowError): + ConversionTest().Int32Field = -2147483649 - def test_uint16_conversion(self): - """Test uint16 conversion.""" - self.assertTrue(System.UInt16.MaxValue == 65535) - self.assertTrue(System.UInt16.MinValue == 0) + with pytest.raises(OverflowError): + _ = System.Int32(2147483648) - ob = ConversionTest() - self.assertTrue(ob.UInt16Field == 0) + with pytest.raises(OverflowError): + _ = System.Int32(-2147483649) - ob.UInt16Field = 65535 - self.assertTrue(ob.UInt16Field == 65535) - ob.UInt16Field = -0 - self.assertTrue(ob.UInt16Field == 0) +def test_int64_conversion(): + """Test int64 conversion.""" + assert System.Int64.MaxValue == long(9223372036854775807) + assert System.Int64.MinValue == long(-9223372036854775808) - ob.UInt16Field = System.UInt16(65535) - self.assertTrue(ob.UInt16Field == 65535) + ob = ConversionTest() + assert ob.Int64Field == 0 - ob.UInt16Field = System.UInt16(0) - self.assertTrue(ob.UInt16Field == 0) + ob.Int64Field = long(9223372036854775807) + assert ob.Int64Field == long(9223372036854775807) - with self.assertRaises(TypeError): - ConversionTest().UInt16Field = "spam" + ob.Int64Field = long(-9223372036854775808) + assert ob.Int64Field == long(-9223372036854775808) - with self.assertRaises(TypeError): - ConversionTest().UInt16Field = None + ob.Int64Field = System.Int64(long(9223372036854775807)) + assert ob.Int64Field == long(9223372036854775807) - with self.assertRaises(OverflowError): - ConversionTest().UInt16Field = 65536 + ob.Int64Field = System.Int64(long(-9223372036854775808)) + assert ob.Int64Field == long(-9223372036854775808) - with self.assertRaises(OverflowError): - ConversionTest().UInt16Field = -1 + with pytest.raises(TypeError): + ConversionTest().Int64Field = "spam" - with self.assertRaises(OverflowError): - _ = System.UInt16(65536) + with pytest.raises(TypeError): + ConversionTest().Int64Field = None - with self.assertRaises(OverflowError): - _ = System.UInt16(-1) + with pytest.raises(OverflowError): + ConversionTest().Int64Field = long(9223372036854775808) - def test_uint32_conversion(self): - """Test uint32 conversion.""" - self.assertTrue(System.UInt32.MaxValue == long(4294967295)) - self.assertTrue(System.UInt32.MinValue == 0) + with pytest.raises(OverflowError): + ConversionTest().Int64Field = long(-9223372036854775809) - ob = ConversionTest() - self.assertTrue(ob.UInt32Field == 0) + with pytest.raises(OverflowError): + _ = System.Int64(long(9223372036854775808)) - ob.UInt32Field = long(4294967295) - self.assertTrue(ob.UInt32Field == long(4294967295)) + with pytest.raises(OverflowError): + _ = System.Int64(long(-9223372036854775809)) - ob.UInt32Field = -0 - self.assertTrue(ob.UInt32Field == 0) - ob.UInt32Field = System.UInt32(long(4294967295)) - self.assertTrue(ob.UInt32Field == long(4294967295)) +def test_uint16_conversion(): + """Test uint16 conversion.""" + assert System.UInt16.MaxValue == 65535 + assert System.UInt16.MinValue == 0 - ob.UInt32Field = System.UInt32(0) - self.assertTrue(ob.UInt32Field == 0) + ob = ConversionTest() + assert ob.UInt16Field == 0 - with self.assertRaises(TypeError): - ConversionTest().UInt32Field = "spam" + ob.UInt16Field = 65535 + assert ob.UInt16Field == 65535 - with self.assertRaises(TypeError): - ConversionTest().UInt32Field = None + ob.UInt16Field = -0 + assert ob.UInt16Field == 0 - with self.assertRaises(OverflowError): - ConversionTest().UInt32Field = long(4294967296) + ob.UInt16Field = System.UInt16(65535) + assert ob.UInt16Field == 65535 - with self.assertRaises(OverflowError): - ConversionTest().UInt32Field = -1 + ob.UInt16Field = System.UInt16(0) + assert ob.UInt16Field == 0 - with self.assertRaises(OverflowError): - _ = System.UInt32(long(4294967296)) + with pytest.raises(TypeError): + ConversionTest().UInt16Field = "spam" - with self.assertRaises(OverflowError): - _ = System.UInt32(-1) + with pytest.raises(TypeError): + ConversionTest().UInt16Field = None - def test_uint64_conversion(self): - """Test uint64 conversion.""" - self.assertTrue(System.UInt64.MaxValue == long(18446744073709551615)) - self.assertTrue(System.UInt64.MinValue == 0) + with pytest.raises(OverflowError): + ConversionTest().UInt16Field = 65536 - ob = ConversionTest() - self.assertTrue(ob.UInt64Field == 0) + with pytest.raises(OverflowError): + ConversionTest().UInt16Field = -1 - ob.UInt64Field = long(18446744073709551615) - self.assertTrue(ob.UInt64Field == long(18446744073709551615)) + with pytest.raises(OverflowError): + _ = System.UInt16(65536) - ob.UInt64Field = -0 - self.assertTrue(ob.UInt64Field == 0) + with pytest.raises(OverflowError): + _ = System.UInt16(-1) - ob.UInt64Field = System.UInt64(long(18446744073709551615)) - self.assertTrue(ob.UInt64Field == long(18446744073709551615)) - ob.UInt64Field = System.UInt64(0) - self.assertTrue(ob.UInt64Field == 0) +def test_uint32_conversion(): + """Test uint32 conversion.""" + assert System.UInt32.MaxValue == long(4294967295) + assert System.UInt32.MinValue == 0 - with self.assertRaises(TypeError): - ConversionTest().UInt64Field = "spam" + ob = ConversionTest() + assert ob.UInt32Field == 0 - with self.assertRaises(TypeError): - ConversionTest().UInt64Field = None + ob.UInt32Field = long(4294967295) + assert ob.UInt32Field == long(4294967295) - with self.assertRaises(OverflowError): - ConversionTest().UInt64Field = long(18446744073709551616) + ob.UInt32Field = -0 + assert ob.UInt32Field == 0 - with self.assertRaises(OverflowError): - ConversionTest().UInt64Field = -1 + ob.UInt32Field = System.UInt32(long(4294967295)) + assert ob.UInt32Field == long(4294967295) - with self.assertRaises(OverflowError): - _ = System.UInt64(long(18446744073709551616)) + ob.UInt32Field = System.UInt32(0) + assert ob.UInt32Field == 0 - with self.assertRaises(OverflowError): - _ = System.UInt64(-1) + with pytest.raises(TypeError): + ConversionTest().UInt32Field = "spam" - def test_single_conversion(self): - """Test single conversion.""" - self.assertTrue(System.Single.MaxValue == 3.402823e38) - self.assertTrue(System.Single.MinValue == -3.402823e38) + with pytest.raises(TypeError): + ConversionTest().UInt32Field = None - ob = ConversionTest() - self.assertTrue(ob.SingleField == 0.0) + with pytest.raises(OverflowError): + ConversionTest().UInt32Field = long(4294967296) - ob.SingleField = 3.402823e38 - self.assertTrue(ob.SingleField == 3.402823e38) + with pytest.raises(OverflowError): + ConversionTest().UInt32Field = -1 - ob.SingleField = -3.402823e38 - self.assertTrue(ob.SingleField == -3.402823e38) + with pytest.raises(OverflowError): + _ = System.UInt32(long(4294967296)) - ob.SingleField = System.Single(3.402823e38) - self.assertTrue(ob.SingleField == 3.402823e38) + with pytest.raises(OverflowError): + _ = System.UInt32(-1) - ob.SingleField = System.Single(-3.402823e38) - self.assertTrue(ob.SingleField == -3.402823e38) - with self.assertRaises(TypeError): - ConversionTest().SingleField = "spam" +def test_uint64_conversion(): + """Test uint64 conversion.""" + assert System.UInt64.MaxValue == long(18446744073709551615) + assert System.UInt64.MinValue == 0 - with self.assertRaises(TypeError): - ConversionTest().SingleField = None + ob = ConversionTest() + assert ob.UInt64Field == 0 - with self.assertRaises(OverflowError): - ConversionTest().SingleField = 3.402824e38 + ob.UInt64Field = long(18446744073709551615) + assert ob.UInt64Field == long(18446744073709551615) - with self.assertRaises(OverflowError): - ConversionTest().SingleField = -3.402824e38 + ob.UInt64Field = -0 + assert ob.UInt64Field == 0 - with self.assertRaises(OverflowError): - _ = System.Single(3.402824e38) + ob.UInt64Field = System.UInt64(long(18446744073709551615)) + assert ob.UInt64Field == long(18446744073709551615) - with self.assertRaises(OverflowError): - _ = System.Single(-3.402824e38) + ob.UInt64Field = System.UInt64(0) + assert ob.UInt64Field == 0 - def test_double_conversion(self): - """Test double conversion.""" - self.assertTrue(System.Double.MaxValue == 1.7976931348623157e308) - self.assertTrue(System.Double.MinValue == -1.7976931348623157e308) + with pytest.raises(TypeError): + ConversionTest().UInt64Field = "spam" - ob = ConversionTest() - self.assertTrue(ob.DoubleField == 0.0) + with pytest.raises(TypeError): + ConversionTest().UInt64Field = None - ob.DoubleField = 1.7976931348623157e308 - self.assertTrue(ob.DoubleField == 1.7976931348623157e308) + with pytest.raises(OverflowError): + ConversionTest().UInt64Field = long(18446744073709551616) - ob.DoubleField = -1.7976931348623157e308 - self.assertTrue(ob.DoubleField == -1.7976931348623157e308) + with pytest.raises(OverflowError): + ConversionTest().UInt64Field = -1 - ob.DoubleField = System.Double(1.7976931348623157e308) - self.assertTrue(ob.DoubleField == 1.7976931348623157e308) + with pytest.raises(OverflowError): + _ = System.UInt64(long(18446744073709551616)) - ob.DoubleField = System.Double(-1.7976931348623157e308) - self.assertTrue(ob.DoubleField == -1.7976931348623157e308) + with pytest.raises(OverflowError): + _ = System.UInt64(-1) - with self.assertRaises(TypeError): - ConversionTest().DoubleField = "spam" - with self.assertRaises(TypeError): - ConversionTest().DoubleField = None +def test_single_conversion(): + """Test single conversion.""" + assert System.Single.MaxValue == 3.402823e38 + assert System.Single.MinValue == -3.402823e38 - with self.assertRaises(OverflowError): - ConversionTest().DoubleField = 1.7976931348623159e308 + ob = ConversionTest() + assert ob.SingleField == 0.0 - with self.assertRaises(OverflowError): - ConversionTest().DoubleField = -1.7976931348623159e308 + ob.SingleField = 3.402823e38 + assert ob.SingleField == 3.402823e38 - with self.assertRaises(OverflowError): - _ = System.Double(1.7976931348623159e308) + ob.SingleField = -3.402823e38 + assert ob.SingleField == -3.402823e38 - with self.assertRaises(OverflowError): - _ = System.Double(-1.7976931348623159e308) + ob.SingleField = System.Single(3.402823e38) + assert ob.SingleField == 3.402823e38 - def test_decimal_conversion(self): - """Test decimal conversion.""" - from System import Decimal + ob.SingleField = System.Single(-3.402823e38) + assert ob.SingleField == -3.402823e38 - max_d = Decimal.Parse("79228162514264337593543950335") - min_d = Decimal.Parse("-79228162514264337593543950335") + with pytest.raises(TypeError): + ConversionTest().SingleField = "spam" - self.assertTrue(Decimal.ToInt64(Decimal(10)) == long(10)) + with pytest.raises(TypeError): + ConversionTest().SingleField = None - ob = ConversionTest() - self.assertTrue(ob.DecimalField == Decimal(0)) + with pytest.raises(OverflowError): + ConversionTest().SingleField = 3.402824e38 - ob.DecimalField = Decimal(10) - self.assertTrue(ob.DecimalField == Decimal(10)) + with pytest.raises(OverflowError): + ConversionTest().SingleField = -3.402824e38 - ob.DecimalField = Decimal.One - self.assertTrue(ob.DecimalField == Decimal.One) + with pytest.raises(OverflowError): + _ = System.Single(3.402824e38) - ob.DecimalField = Decimal.Zero - self.assertTrue(ob.DecimalField == Decimal.Zero) + with pytest.raises(OverflowError): + _ = System.Single(-3.402824e38) - ob.DecimalField = max_d - self.assertTrue(ob.DecimalField == max_d) - ob.DecimalField = min_d - self.assertTrue(ob.DecimalField == min_d) +def test_double_conversion(): + """Test double conversion.""" + assert System.Double.MaxValue == 1.7976931348623157e308 + assert System.Double.MinValue == -1.7976931348623157e308 - with self.assertRaises(TypeError): - ConversionTest().DecimalField = None + ob = ConversionTest() + assert ob.DoubleField == 0.0 - with self.assertRaises(TypeError): - ConversionTest().DecimalField = "spam" + ob.DoubleField = 1.7976931348623157e308 + assert ob.DoubleField == 1.7976931348623157e308 - with self.assertRaises(TypeError): - ConversionTest().DecimalField = 1 + ob.DoubleField = -1.7976931348623157e308 + assert ob.DoubleField == -1.7976931348623157e308 - def test_string_conversion(self): - """Test string / unicode conversion.""" - ob = ConversionTest() + ob.DoubleField = System.Double(1.7976931348623157e308) + assert ob.DoubleField == 1.7976931348623157e308 - self.assertTrue(ob.StringField == "spam") - self.assertTrue(ob.StringField == u"spam") + ob.DoubleField = System.Double(-1.7976931348623157e308) + assert ob.DoubleField == -1.7976931348623157e308 - ob.StringField = "eggs" - self.assertTrue(ob.StringField == "eggs") - self.assertTrue(ob.StringField == u"eggs") + with pytest.raises(TypeError): + ConversionTest().DoubleField = "spam" - ob.StringField = u"spam" - self.assertTrue(ob.StringField == "spam") - self.assertTrue(ob.StringField == u"spam") + with pytest.raises(TypeError): + ConversionTest().DoubleField = None - ob.StringField = u'\uffff\uffff' - self.assertTrue(ob.StringField == u'\uffff\uffff') + with pytest.raises(OverflowError): + ConversionTest().DoubleField = 1.7976931348623159e308 - ob.StringField = System.String("spam") - self.assertTrue(ob.StringField == "spam") - self.assertTrue(ob.StringField == u"spam") + with pytest.raises(OverflowError): + ConversionTest().DoubleField = -1.7976931348623159e308 - ob.StringField = System.String(u'\uffff\uffff') - self.assertTrue(ob.StringField == u'\uffff\uffff') + with pytest.raises(OverflowError): + _ = System.Double(1.7976931348623159e308) - ob.StringField = None - self.assertTrue(ob.StringField is None) + with pytest.raises(OverflowError): + _ = System.Double(-1.7976931348623159e308) - with self.assertRaises(TypeError): - ConversionTest().StringField = 1 - def test_interface_conversion(self): - """Test interface conversion.""" - from Python.Test import Spam, ISpam +def test_decimal_conversion(): + """Test decimal conversion.""" + from System import Decimal - ob = ConversionTest() + max_d = Decimal.Parse("79228162514264337593543950335") + min_d = Decimal.Parse("-79228162514264337593543950335") - self.assertTrue(ISpam(ob.SpamField).GetValue() == "spam") - self.assertTrue(ob.SpamField.GetValue() == "spam") + assert Decimal.ToInt64(Decimal(10)) == long(10) - ob.SpamField = Spam("eggs") - self.assertTrue(ISpam(ob.SpamField).GetValue() == "eggs") - self.assertTrue(ob.SpamField.GetValue() == "eggs") + ob = ConversionTest() + assert ob.DecimalField == Decimal(0) - # need to test spam subclass here. + ob.DecimalField = Decimal(10) + assert ob.DecimalField == Decimal(10) - ob.SpamField = None - self.assertTrue(ob.SpamField is None) + ob.DecimalField = Decimal.One + assert ob.DecimalField == Decimal.One - with self.assertRaises(TypeError): - ob = ConversionTest() - ob.SpamField = System.String("bad") + ob.DecimalField = Decimal.Zero + assert ob.DecimalField == Decimal.Zero - with self.assertRaises(TypeError): - ob = ConversionTest() - ob.SpamField = System.Int32(1) + ob.DecimalField = max_d + assert ob.DecimalField == max_d - def test_object_conversion(self): - """Test ob conversion.""" - from Python.Test import Spam + ob.DecimalField = min_d + assert ob.DecimalField == min_d - ob = ConversionTest() - self.assertTrue(ob.ObjectField is None) + with pytest.raises(TypeError): + ConversionTest().DecimalField = None - ob.ObjectField = Spam("eggs") - self.assertTrue(ob.ObjectField.__class__.__name__ == "Spam") - self.assertTrue(ob.ObjectField.GetValue() == "eggs") + with pytest.raises(TypeError): + ConversionTest().DecimalField = "spam" - ob.ObjectField = None - self.assertTrue(ob.ObjectField is None) + with pytest.raises(TypeError): + ConversionTest().DecimalField = 1 - ob.ObjectField = System.String("spam") - self.assertTrue(ob.ObjectField == "spam") - ob.ObjectField = System.Int32(1) - self.assertTrue(ob.ObjectField == 1) +def test_string_conversion(): + """Test string / unicode conversion.""" + ob = ConversionTest() - # need to test subclass here + assert ob.StringField == "spam" + assert ob.StringField == u"spam" - with self.assertRaises(TypeError): - ob = ConversionTest() - ob.ObjectField = self + ob.StringField = "eggs" + assert ob.StringField == "eggs" + assert ob.StringField == u"eggs" - def test_enum_conversion(self): - """Test enum conversion.""" - from Python.Test import ShortEnum + ob.StringField = u"spam" + assert ob.StringField == "spam" + assert ob.StringField == u"spam" - ob = ConversionTest() - self.assertTrue(ob.EnumField == ShortEnum.Zero) + ob.StringField = u'\uffff\uffff' + assert ob.StringField == u'\uffff\uffff' + + ob.StringField = System.String("spam") + assert ob.StringField == "spam" + assert ob.StringField == u"spam" - ob.EnumField = ShortEnum.One - self.assertTrue(ob.EnumField == ShortEnum.One) + ob.StringField = System.String(u'\uffff\uffff') + assert ob.StringField == u'\uffff\uffff' - ob.EnumField = 0 - self.assertTrue(ob.EnumField == ShortEnum.Zero) - self.assertTrue(ob.EnumField == 0) + ob.StringField = None + assert ob.StringField is None - ob.EnumField = 1 - self.assertTrue(ob.EnumField == ShortEnum.One) - self.assertTrue(ob.EnumField == 1) + with pytest.raises(TypeError): + ConversionTest().StringField = 1 - with self.assertRaises(ValueError): - ob = ConversionTest() - ob.EnumField = 10 - with self.assertRaises(ValueError): - ob = ConversionTest() - ob.EnumField = 255 +def test_interface_conversion(): + """Test interface conversion.""" + from Python.Test import Spam, ISpam - with self.assertRaises(OverflowError): - ob = ConversionTest() - ob.EnumField = 1000000 + ob = ConversionTest() - with self.assertRaises(TypeError): - ob = ConversionTest() - ob.EnumField = "spam" + assert ISpam(ob.SpamField).GetValue() == "spam" + assert ob.SpamField.GetValue() == "spam" - def test_null_conversion(self): - """Test null conversion.""" + ob.SpamField = Spam("eggs") + assert ISpam(ob.SpamField).GetValue() == "eggs" + assert ob.SpamField.GetValue() == "eggs" + + # need to test spam subclass here. + + ob.SpamField = None + assert ob.SpamField is None + + with pytest.raises(TypeError): ob = ConversionTest() + ob.SpamField = System.String("bad") + + with pytest.raises(TypeError): + ob = ConversionTest() + ob.SpamField = System.Int32(1) + - ob.StringField = None - self.assertTrue(ob.StringField is None) +def test_object_conversion(): + """Test ob conversion.""" + from Python.Test import Spam - ob.ObjectField = None - self.assertTrue(ob.ObjectField is None) + ob = ConversionTest() + assert ob.ObjectField is None - ob.SpamField = None - self.assertTrue(ob.SpamField is None) + ob.ObjectField = Spam("eggs") + assert ob.ObjectField.__class__.__name__ == "Spam" + assert ob.ObjectField.GetValue() == "eggs" - # Primitive types and enums should not be set to null. + ob.ObjectField = None + assert ob.ObjectField is None - with self.assertRaises(TypeError): - ConversionTest().Int32Field = None + ob.ObjectField = System.String("spam") + assert ob.ObjectField == "spam" - with self.assertRaises(TypeError): - ConversionTest().EnumField = None + ob.ObjectField = System.Int32(1) + assert ob.ObjectField == 1 - def test_byte_array_conversion(self): - """Test byte array conversion.""" + # need to test subclass here + + with pytest.raises(TypeError): + class Foo(object): + pass ob = ConversionTest() + ob.ObjectField = Foo + + +def test_enum_conversion(): + """Test enum conversion.""" + from Python.Test import ShortEnum + + ob = ConversionTest() + assert ob.EnumField == ShortEnum.Zero + + ob.EnumField = ShortEnum.One + assert ob.EnumField == ShortEnum.One + + ob.EnumField = 0 + assert ob.EnumField == ShortEnum.Zero + assert ob.EnumField == 0 - self.assertTrue(ob.ByteArrayField is None) + ob.EnumField = 1 + assert ob.EnumField == ShortEnum.One + assert ob.EnumField == 1 - ob.ByteArrayField = [0, 1, 2, 3, 4] - array = ob.ByteArrayField - self.assertTrue(len(array) == 5) - self.assertTrue(array[0] == 0) - self.assertTrue(array[4] == 4) + with pytest.raises(ValueError): + ob = ConversionTest() + ob.EnumField = 10 + + with pytest.raises(ValueError): + ob = ConversionTest() + ob.EnumField = 255 - value = b"testing" - ob.ByteArrayField = value - array = ob.ByteArrayField - for i, _ in enumerate(value): - self.assertTrue(array[i] == indexbytes(value, i)) + with pytest.raises(OverflowError): + ob = ConversionTest() + ob.EnumField = 1000000 - def test_sbyte_array_conversion(self): - """Test sbyte array conversion.""" + with pytest.raises(TypeError): ob = ConversionTest() + ob.EnumField = "spam" + + +def test_null_conversion(): + """Test null conversion.""" + ob = ConversionTest() + + ob.StringField = None + assert ob.StringField is None + + ob.ObjectField = None + assert ob.ObjectField is None + + ob.SpamField = None + assert ob.SpamField is None + + # Primitive types and enums should not be set to null. + + with pytest.raises(TypeError): + ConversionTest().Int32Field = None + + with pytest.raises(TypeError): + ConversionTest().EnumField = None + + +def test_byte_array_conversion(): + """Test byte array conversion.""" + ob = ConversionTest() + + assert ob.ByteArrayField is None + + ob.ByteArrayField = [0, 1, 2, 3, 4] + array = ob.ByteArrayField + assert len(array) == 5 + assert array[0] == 0 + assert array[4] == 4 + + value = b"testing" + ob.ByteArrayField = value + array = ob.ByteArrayField + for i, _ in enumerate(value): + assert array[i] == indexbytes(value, i) - self.assertTrue(ob.SByteArrayField is None) - ob.SByteArrayField = [0, 1, 2, 3, 4] - array = ob.SByteArrayField - self.assertTrue(len(array) == 5) - self.assertTrue(array[0] == 0) - self.assertTrue(array[4] == 4) +def test_sbyte_array_conversion(): + """Test sbyte array conversion.""" + ob = ConversionTest() - value = b"testing" - ob.SByteArrayField = value - array = ob.SByteArrayField - for i, _ in enumerate(value): - self.assertTrue(array[i] == indexbytes(value, i)) + assert ob.SByteArrayField is None + ob.SByteArrayField = [0, 1, 2, 3, 4] + array = ob.SByteArrayField + assert len(array) == 5 + assert array[0] == 0 + assert array[4] == 4 -def test_suite(): - return unittest.makeSuite(ConversionTests) + value = b"testing" + ob.SByteArrayField = value + array = ob.SByteArrayField + for i, _ in enumerate(value): + assert array[i] == indexbytes(value, i) diff --git a/src/tests/test_delegate.py b/src/tests/test_delegate.py index 4963a09b8..33aca43b3 100644 --- a/src/tests/test_delegate.py +++ b/src/tests/test_delegate.py @@ -1,258 +1,269 @@ # -*- coding: utf-8 -*- # TODO: Add test for ObjectDelegate -import unittest +"""Test CLR delegate support.""" import Python.Test as Test import System +import pytest from Python.Test import DelegateTest, StringDelegate -from _compat import DictProxyType -from utils import HelloClass, hello_func, MultipleHandler +from ._compat import DictProxyType +from .utils import HelloClass, hello_func, MultipleHandler -class DelegateTests(unittest.TestCase): - """Test CLR delegate support.""" +def test_delegate_standard_attrs(): + """Test standard delegate attributes.""" + from Python.Test import PublicDelegate - def test_delegate_standard_attrs(self): - """Test standard delegate attributes.""" - from Python.Test import PublicDelegate + assert PublicDelegate.__name__ == 'PublicDelegate' + assert PublicDelegate.__module__ == 'Python.Test' + assert isinstance(PublicDelegate.__dict__, DictProxyType) + assert PublicDelegate.__doc__ is None - self.assertTrue(PublicDelegate.__name__ == 'PublicDelegate') - self.assertTrue(PublicDelegate.__module__ == 'Python.Test') - self.assertTrue(isinstance(PublicDelegate.__dict__, DictProxyType)) - self.assertTrue(PublicDelegate.__doc__ is None) - def test_global_delegate_visibility(self): - """Test visibility of module-level delegates.""" - from Python.Test import PublicDelegate +def test_global_delegate_visibility(): + """Test visibility of module-level delegates.""" + from Python.Test import PublicDelegate - self.assertTrue(PublicDelegate.__name__ == 'PublicDelegate') - self.assertTrue(Test.PublicDelegate.__name__ == 'PublicDelegate') + assert PublicDelegate.__name__ == 'PublicDelegate' + assert Test.PublicDelegate.__name__ == 'PublicDelegate' - with self.assertRaises(ImportError): - from Python.Test import InternalDelegate - _ = InternalDelegate + with pytest.raises(ImportError): + from Python.Test import InternalDelegate + _ = InternalDelegate - with self.assertRaises(AttributeError): - _ = Test.InternalDelegate + with pytest.raises(AttributeError): + _ = Test.InternalDelegate - def test_nested_delegate_visibility(self): - """Test visibility of nested delegates.""" - ob = DelegateTest.PublicDelegate - self.assertTrue(ob.__name__ == 'PublicDelegate') - ob = DelegateTest.ProtectedDelegate - self.assertTrue(ob.__name__ == 'ProtectedDelegate') +def test_nested_delegate_visibility(): + """Test visibility of nested delegates.""" + ob = DelegateTest.PublicDelegate + assert ob.__name__ == 'PublicDelegate' - with self.assertRaises(AttributeError): - _ = DelegateTest.InternalDelegate + ob = DelegateTest.ProtectedDelegate + assert ob.__name__ == 'ProtectedDelegate' - with self.assertRaises(AttributeError): - _ = DelegateTest.PrivateDelegate + with pytest.raises(AttributeError): + _ = DelegateTest.InternalDelegate - def test_delegate_from_function(self): - """Test delegate implemented with a Python function.""" + with pytest.raises(AttributeError): + _ = DelegateTest.PrivateDelegate - d = StringDelegate(hello_func) - ob = DelegateTest() - self.assertTrue(ob.CallStringDelegate(d) == "hello") - self.assertTrue(d() == "hello") +def test_delegate_from_function(): + """Test delegate implemented with a Python function.""" - ob.stringDelegate = d - self.assertTrue(ob.CallStringDelegate(ob.stringDelegate) == "hello") - self.assertTrue(ob.stringDelegate() == "hello") + d = StringDelegate(hello_func) + ob = DelegateTest() - def test_delegate_from_method(self): - """Test delegate implemented with a Python instance method.""" + assert ob.CallStringDelegate(d) == "hello" + assert d() == "hello" - inst = HelloClass() - d = StringDelegate(inst.hello) - ob = DelegateTest() + ob.stringDelegate = d + assert ob.CallStringDelegate(ob.stringDelegate) == "hello" + assert ob.stringDelegate() == "hello" - self.assertTrue(ob.CallStringDelegate(d) == "hello") - self.assertTrue(d() == "hello") - ob.stringDelegate = d - self.assertTrue(ob.CallStringDelegate(ob.stringDelegate) == "hello") - self.assertTrue(ob.stringDelegate() == "hello") +def test_delegate_from_method(): + """Test delegate implemented with a Python instance method.""" - def test_delegate_from_unbound_method(self): - """Test failure mode for unbound methods.""" + inst = HelloClass() + d = StringDelegate(inst.hello) + ob = DelegateTest() - with self.assertRaises(TypeError): - d = StringDelegate(HelloClass.hello) - d() + assert ob.CallStringDelegate(d) == "hello" + assert d() == "hello" - def test_delegate_from_static_method(self): - """Test delegate implemented with a Python static method.""" + ob.stringDelegate = d + assert ob.CallStringDelegate(ob.stringDelegate) == "hello" + assert ob.stringDelegate() == "hello" - d = StringDelegate(HelloClass.s_hello) - ob = DelegateTest() - self.assertTrue(ob.CallStringDelegate(d) == "hello") - self.assertTrue(d() == "hello") +def test_delegate_from_unbound_method(): + """Test failure mode for unbound methods.""" - ob.stringDelegate = d - self.assertTrue(ob.CallStringDelegate(ob.stringDelegate) == "hello") - self.assertTrue(ob.stringDelegate() == "hello") + with pytest.raises(TypeError): + d = StringDelegate(HelloClass.hello) + d() - inst = HelloClass() - d = StringDelegate(inst.s_hello) - ob = DelegateTest() - self.assertTrue(ob.CallStringDelegate(d) == "hello") - self.assertTrue(d() == "hello") +def test_delegate_from_static_method(): + """Test delegate implemented with a Python static method.""" - ob.stringDelegate = d - self.assertTrue(ob.CallStringDelegate(ob.stringDelegate) == "hello") - self.assertTrue(ob.stringDelegate() == "hello") + d = StringDelegate(HelloClass.s_hello) + ob = DelegateTest() - def test_delegate_from_class_method(self): - """Test delegate implemented with a Python class method.""" + assert ob.CallStringDelegate(d) == "hello" + assert d() == "hello" - d = StringDelegate(HelloClass.c_hello) - ob = DelegateTest() + ob.stringDelegate = d + assert ob.CallStringDelegate(ob.stringDelegate) == "hello" + assert ob.stringDelegate() == "hello" - self.assertTrue(ob.CallStringDelegate(d) == "hello") - self.assertTrue(d() == "hello") + inst = HelloClass() + d = StringDelegate(inst.s_hello) + ob = DelegateTest() - ob.stringDelegate = d - self.assertTrue(ob.CallStringDelegate(ob.stringDelegate) == "hello") - self.assertTrue(ob.stringDelegate() == "hello") + assert ob.CallStringDelegate(d) == "hello" + assert d() == "hello" - inst = HelloClass() - d = StringDelegate(inst.c_hello) - ob = DelegateTest() + ob.stringDelegate = d + assert ob.CallStringDelegate(ob.stringDelegate) == "hello" + assert ob.stringDelegate() == "hello" - self.assertTrue(ob.CallStringDelegate(d) == "hello") - self.assertTrue(d() == "hello") - ob.stringDelegate = d - self.assertTrue(ob.CallStringDelegate(ob.stringDelegate) == "hello") - self.assertTrue(ob.stringDelegate() == "hello") +def test_delegate_from_class_method(): + """Test delegate implemented with a Python class method.""" - def test_delegate_from_callable(self): - """Test delegate implemented with a Python callable object.""" + d = StringDelegate(HelloClass.c_hello) + ob = DelegateTest() - inst = HelloClass() - d = StringDelegate(inst) - ob = DelegateTest() + assert ob.CallStringDelegate(d) == "hello" + assert d() == "hello" - self.assertTrue(ob.CallStringDelegate(d) == "hello") - self.assertTrue(d() == "hello") + ob.stringDelegate = d + assert ob.CallStringDelegate(ob.stringDelegate) == "hello" + assert ob.stringDelegate() == "hello" - ob.stringDelegate = d - self.assertTrue(ob.CallStringDelegate(ob.stringDelegate) == "hello") - self.assertTrue(ob.stringDelegate() == "hello") + inst = HelloClass() + d = StringDelegate(inst.c_hello) + ob = DelegateTest() - def test_delegate_from_managed_instance_method(self): - """Test delegate implemented with a managed instance method.""" - ob = DelegateTest() - d = StringDelegate(ob.SayHello) + assert ob.CallStringDelegate(d) == "hello" + assert d() == "hello" - self.assertTrue(ob.CallStringDelegate(d) == "hello") - self.assertTrue(d() == "hello") + ob.stringDelegate = d + assert ob.CallStringDelegate(ob.stringDelegate) == "hello" + assert ob.stringDelegate() == "hello" - ob.stringDelegate = d - self.assertTrue(ob.CallStringDelegate(ob.stringDelegate) == "hello") - self.assertTrue(ob.stringDelegate() == "hello") - def test_delegate_from_managed_static_method(self): - """Test delegate implemented with a managed static method.""" - d = StringDelegate(DelegateTest.StaticSayHello) - ob = DelegateTest() +def test_delegate_from_callable(): + """Test delegate implemented with a Python callable object.""" - self.assertTrue(ob.CallStringDelegate(d) == "hello") - self.assertTrue(d() == "hello") + inst = HelloClass() + d = StringDelegate(inst) + ob = DelegateTest() - ob.stringDelegate = d - self.assertTrue(ob.CallStringDelegate(ob.stringDelegate) == "hello") - self.assertTrue(ob.stringDelegate() == "hello") + assert ob.CallStringDelegate(d) == "hello" + assert d() == "hello" - def test_delegate_from_delegate(self): - """Test delegate implemented with another delegate.""" - d1 = StringDelegate(hello_func) - d2 = StringDelegate(d1) - ob = DelegateTest() + ob.stringDelegate = d + assert ob.CallStringDelegate(ob.stringDelegate) == "hello" + assert ob.stringDelegate() == "hello" - self.assertTrue(ob.CallStringDelegate(d2) == "hello") - self.assertTrue(d2() == "hello") - ob.stringDelegate = d2 - self.assertTrue(ob.CallStringDelegate(ob.stringDelegate) == "hello") - self.assertTrue(ob.stringDelegate() == "hello") +def test_delegate_from_managed_instance_method(): + """Test delegate implemented with a managed instance method.""" + ob = DelegateTest() + d = StringDelegate(ob.SayHello) - def test_delegate_with_invalid_args(self): - """Test delegate instantiation with invalid (non-callable) args.""" + assert ob.CallStringDelegate(d) == "hello" + assert d() == "hello" - with self.assertRaises(TypeError): - _ = StringDelegate(None) + ob.stringDelegate = d + assert ob.CallStringDelegate(ob.stringDelegate) == "hello" + assert ob.stringDelegate() == "hello" - with self.assertRaises(TypeError): - _ = StringDelegate("spam") - with self.assertRaises(TypeError): - _ = StringDelegate(1) +def test_delegate_from_managed_static_method(): + """Test delegate implemented with a managed static method.""" + d = StringDelegate(DelegateTest.StaticSayHello) + ob = DelegateTest() - def test_multicast_delegate(self): - """Test multicast delegates.""" + assert ob.CallStringDelegate(d) == "hello" + assert d() == "hello" - inst = MultipleHandler() - d1 = StringDelegate(inst.count) - d2 = StringDelegate(inst.count) + ob.stringDelegate = d + assert ob.CallStringDelegate(ob.stringDelegate) == "hello" + assert ob.stringDelegate() == "hello" - md = System.Delegate.Combine(d1, d2) - ob = DelegateTest() - self.assertTrue(ob.CallStringDelegate(md) == "ok") - self.assertTrue(inst.value == 2) +def test_delegate_from_delegate(): + """Test delegate implemented with another delegate.""" + d1 = StringDelegate(hello_func) + d2 = StringDelegate(d1) + ob = DelegateTest() - self.assertTrue(md() == "ok") - self.assertTrue(inst.value == 4) + assert ob.CallStringDelegate(d2) == "hello" + assert d2() == "hello" - def test_subclass_delegate_fails(self): - """Test that subclassing of a delegate type fails.""" - from Python.Test import PublicDelegate + ob.stringDelegate = d2 + assert ob.CallStringDelegate(ob.stringDelegate) == "hello" + assert ob.stringDelegate() == "hello" - with self.assertRaises(TypeError): - class Boom(PublicDelegate): - pass - _ = Boom - def test_delegate_equality(self): - """Test delegate equality.""" +def test_delegate_with_invalid_args(): + """Test delegate instantiation with invalid (non-callable) args.""" - d = StringDelegate(hello_func) - ob = DelegateTest() - ob.stringDelegate = d - self.assertTrue(ob.stringDelegate == d) + with pytest.raises(TypeError): + _ = StringDelegate(None) - def test_bool_delegate(self): - """Test boolean delegate.""" - from Python.Test import BoolDelegate + with pytest.raises(TypeError): + _ = StringDelegate("spam") - def always_so_negative(): - return 0 + with pytest.raises(TypeError): + _ = StringDelegate(1) - d = BoolDelegate(always_so_negative) - ob = DelegateTest() - ob.CallBoolDelegate(d) - self.assertTrue(not d()) - self.assertTrue(not ob.CallBoolDelegate(d)) +def test_multicast_delegate(): + """Test multicast delegates.""" - # test async delegates + inst = MultipleHandler() + d1 = StringDelegate(inst.count) + d2 = StringDelegate(inst.count) - # test multicast delegates + md = System.Delegate.Combine(d1, d2) + ob = DelegateTest() - # test explicit op_ + assert ob.CallStringDelegate(md) == "ok" + assert inst.value == 2 - # test sig mismatch, both on managed and Python side + assert md() == "ok" + assert inst.value == 4 - # test return wrong type +def test_subclass_delegate_fails(): + """Test that subclassing of a delegate type fails.""" + from Python.Test import PublicDelegate -def test_suite(): - return unittest.makeSuite(DelegateTests) + with pytest.raises(TypeError): + class Boom(PublicDelegate): + pass + + _ = Boom + + +def test_delegate_equality(): + """Test delegate equality.""" + + d = StringDelegate(hello_func) + ob = DelegateTest() + ob.stringDelegate = d + assert ob.stringDelegate == d + + +def test_bool_delegate(): + """Test boolean delegate.""" + from Python.Test import BoolDelegate + + def always_so_negative(): + return 0 + + d = BoolDelegate(always_so_negative) + ob = DelegateTest() + ob.CallBoolDelegate(d) + + assert not d() + assert not ob.CallBoolDelegate(d) + + # test async delegates + + # test multicast delegates + + # test explicit op_ + + # test sig mismatch, both on managed and Python side + + # test return wrong type diff --git a/src/tests/test_docstring.py b/src/tests/test_docstring.py index f2bc3302b..640a61915 100644 --- a/src/tests/test_docstring.py +++ b/src/tests/test_docstring.py @@ -1,32 +1,27 @@ # -*- coding: utf-8 -*- -import unittest +"""Test doc strings support.""" -class DocStringTests(unittest.TestCase): - """Test doc strings support.""" +def test_doc_with_ctor(): + from Python.Test import DocWithCtorTest - def test_doc_with_ctor(self): - from Python.Test import DocWithCtorTest + assert DocWithCtorTest.__doc__ == 'DocWithCtorTest Class' + assert DocWithCtorTest.TestMethod.__doc__ == 'DocWithCtorTest TestMethod' + assert DocWithCtorTest.StaticTestMethod.__doc__ == 'DocWithCtorTest StaticTestMethod' - self.assertEqual(DocWithCtorTest.__doc__, 'DocWithCtorTest Class') - self.assertEqual(DocWithCtorTest.TestMethod.__doc__, 'DocWithCtorTest TestMethod') - self.assertEqual(DocWithCtorTest.StaticTestMethod.__doc__, 'DocWithCtorTest StaticTestMethod') - def test_doc_with_ctor_no_doc(self): - from Python.Test import DocWithCtorNoDocTest +def test_doc_with_ctor_no_doc(): + from Python.Test import DocWithCtorNoDocTest - self.assertEqual(DocWithCtorNoDocTest.__doc__, 'Void .ctor(Boolean)') - self.assertEqual(DocWithCtorNoDocTest.TestMethod.__doc__, 'Void TestMethod(Double, Int32)') - self.assertEqual(DocWithCtorNoDocTest.StaticTestMethod.__doc__, 'Void StaticTestMethod(Double, Int32)') + assert DocWithCtorNoDocTest.__doc__ == 'Void .ctor(Boolean)' + assert DocWithCtorNoDocTest.TestMethod.__doc__ == 'Void TestMethod(Double, Int32)' + assert DocWithCtorNoDocTest.StaticTestMethod.__doc__ == 'Void StaticTestMethod(Double, Int32)' - def test_doc_without_ctor(self): - from Python.Test import DocWithoutCtorTest - self.assertEqual(DocWithoutCtorTest.__doc__, 'DocWithoutCtorTest Class') - self.assertEqual(DocWithoutCtorTest.TestMethod.__doc__, 'DocWithoutCtorTest TestMethod') - self.assertEqual(DocWithoutCtorTest.StaticTestMethod.__doc__, 'DocWithoutCtorTest StaticTestMethod') +def test_doc_without_ctor(): + from Python.Test import DocWithoutCtorTest - -def test_suite(): - return unittest.makeSuite(DocStringTests) + assert DocWithoutCtorTest.__doc__ == 'DocWithoutCtorTest Class' + assert DocWithoutCtorTest.TestMethod.__doc__ == 'DocWithoutCtorTest TestMethod' + assert DocWithoutCtorTest.StaticTestMethod.__doc__ == 'DocWithoutCtorTest StaticTestMethod' diff --git a/src/tests/test_engine.py b/src/tests/test_engine.py index b605a3796..60fdbf45d 100644 --- a/src/tests/test_engine.py +++ b/src/tests/test_engine.py @@ -1,46 +1,43 @@ # -*- coding: utf-8 -*- +"""Test PythonEngine embedding APIs.""" + import sys -import unittest import System +import pytest from Python.Runtime import PythonEngine -class EngineTests(unittest.TestCase): - """Test PythonEngine embedding APIs.""" - - def test_multiple_calls_to_initialize(self): - """Test that multiple initialize calls are harmless.""" - try: - PythonEngine.Initialize() - PythonEngine.Initialize() - PythonEngine.Initialize() - except BaseException: - self.fail("Initialize() raise an exception.") +def test_multiple_calls_to_initialize(): + """Test that multiple initialize calls are harmless.""" + try: + PythonEngine.Initialize() + PythonEngine.Initialize() + PythonEngine.Initialize() + except Exception: + assert False # Initialize() raise an exception. - @unittest.skip(reason="FIXME: test crashes") - def test_import_module(self): - """Test module import.""" - m = PythonEngine.ImportModule("sys") - n = m.GetAttr("__name__") - self.assertTrue(n.AsManagedObject(System.String) == "sys") - @unittest.skip(reason="FIXME: test freezes") - def test_run_string(self): - """Test the RunString method.""" - PythonEngine.AcquireLock() +@pytest.mark.skip(reason="FIXME: test crashes") +def test_import_module(): + """Test module import.""" + m = PythonEngine.ImportModule("sys") + n = m.GetAttr("__name__") + assert n.AsManagedObject(System.String) == "sys" - code = "import sys; sys.singleline_worked = 1" - PythonEngine.RunString(code) - self.assertTrue(sys.singleline_worked == 1) - code = "import sys\nsys.multiline_worked = 1" - PythonEngine.RunString(code) - self.assertTrue(sys.multiline_worked == 1) +@pytest.mark.skip(reason="FIXME: test freezes") +def test_run_string(): + """Test the RunString method.""" + PythonEngine.AcquireLock() - PythonEngine.ReleaseLock() + code = "import sys; sys.singleline_worked = 1" + PythonEngine.RunString(code) + assert sys.singleline_worked == 1 + code = "import sys\nsys.multiline_worked = 1" + PythonEngine.RunString(code) + assert sys.multiline_worked == 1 -def test_suite(): - return unittest.makeSuite(EngineTests) + PythonEngine.ReleaseLock() diff --git a/src/tests/test_enum.py b/src/tests/test_enum.py index e7147e69c..b31ce4ec5 100644 --- a/src/tests/test_enum.py +++ b/src/tests/test_enum.py @@ -1,136 +1,145 @@ # -*- coding: utf-8 -*- -import unittest +"""Test clr enum support.""" +import pytest import Python.Test as Test -from _compat import DictProxyType, long - - -class EnumTests(unittest.TestCase): - """Test CLR enum support.""" - - def test_enum_standard_attrs(self): - """Test standard enum attributes.""" - from System import DayOfWeek - - self.assertTrue(DayOfWeek.__name__ == 'DayOfWeek') - self.assertTrue(DayOfWeek.__module__ == 'System') - self.assertTrue(isinstance(DayOfWeek.__dict__, DictProxyType)) - self.assertTrue(DayOfWeek.__doc__ is None) - - def test_enum_get_member(self): - """Test access to enum members.""" - from System import DayOfWeek - - self.assertTrue(DayOfWeek.Sunday == 0) - self.assertTrue(DayOfWeek.Monday == 1) - self.assertTrue(DayOfWeek.Tuesday == 2) - self.assertTrue(DayOfWeek.Wednesday == 3) - self.assertTrue(DayOfWeek.Thursday == 4) - self.assertTrue(DayOfWeek.Friday == 5) - self.assertTrue(DayOfWeek.Saturday == 6) - - def test_byte_enum(self): - """Test byte enum.""" - self.assertTrue(Test.ByteEnum.Zero == 0) - self.assertTrue(Test.ByteEnum.One == 1) - self.assertTrue(Test.ByteEnum.Two == 2) - - def test_sbyte_enum(self): - """Test sbyte enum.""" - self.assertTrue(Test.SByteEnum.Zero == 0) - self.assertTrue(Test.SByteEnum.One == 1) - self.assertTrue(Test.SByteEnum.Two == 2) - - def test_short_enum(self): - """Test short enum.""" - self.assertTrue(Test.ShortEnum.Zero == 0) - self.assertTrue(Test.ShortEnum.One == 1) - self.assertTrue(Test.ShortEnum.Two == 2) - - def test_ushort_enum(self): - """Test ushort enum.""" - self.assertTrue(Test.UShortEnum.Zero == 0) - self.assertTrue(Test.UShortEnum.One == 1) - self.assertTrue(Test.UShortEnum.Two == 2) - - def test_int_enum(self): - """Test int enum.""" - self.assertTrue(Test.IntEnum.Zero == 0) - self.assertTrue(Test.IntEnum.One == 1) - self.assertTrue(Test.IntEnum.Two == 2) - - def test_uint_enum(self): - """Test uint enum.""" - self.assertTrue(Test.UIntEnum.Zero == long(0)) - self.assertTrue(Test.UIntEnum.One == long(1)) - self.assertTrue(Test.UIntEnum.Two == long(2)) - - def test_long_enum(self): - """Test long enum.""" - self.assertTrue(Test.LongEnum.Zero == long(0)) - self.assertTrue(Test.LongEnum.One == long(1)) - self.assertTrue(Test.LongEnum.Two == long(2)) - - def test_ulong_enum(self): - """Test ulong enum.""" - self.assertTrue(Test.ULongEnum.Zero == long(0)) - self.assertTrue(Test.ULongEnum.One == long(1)) - self.assertTrue(Test.ULongEnum.Two == long(2)) - - def test_instantiate_enum_fails(self): - """Test that instantiation of an enum class fails.""" - from System import DayOfWeek - - with self.assertRaises(TypeError): - _ = DayOfWeek() - - def test_subclass_enum_fails(self): - """Test that subclassing of an enumeration fails.""" - from System import DayOfWeek - - with self.assertRaises(TypeError): - class Boom(DayOfWeek): - pass - _ = Boom - - def test_enum_set_member_fails(self): - """Test that setattr operations on enumerations fail.""" - from System import DayOfWeek - - with self.assertRaises(TypeError): - DayOfWeek.Sunday = 13 - - with self.assertRaises(TypeError): - del DayOfWeek.Sunday - - def test_enum_with_flags_attr_conversion(self): - """Test enumeration conversion with FlagsAttribute set.""" - # This works because the FlagsField enum has FlagsAttribute. - Test.FieldTest().FlagsField = 99 - - # This should fail because our test enum doesn't have it. - with self.assertRaises(ValueError): - Test.FieldTest().EnumField = 99 - - def test_enum_conversion(self): - """Test enumeration conversion.""" - ob = Test.FieldTest() - self.assertTrue(ob.EnumField == 0) - - ob.EnumField = Test.ShortEnum.One - self.assertTrue(ob.EnumField == 1) - - with self.assertRaises(ValueError): - Test.FieldTest().EnumField = 20 - - with self.assertRaises(OverflowError): - Test.FieldTest().EnumField = 100000 - - with self.assertRaises(TypeError): - Test.FieldTest().EnumField = "str" - - -def test_suite(): - return unittest.makeSuite(EnumTests) +from ._compat import DictProxyType, long + + +def test_enum_standard_attrs(): + """Test standard enum attributes.""" + from System import DayOfWeek + + assert DayOfWeek.__name__ == 'DayOfWeek' + assert DayOfWeek.__module__ == 'System' + assert isinstance(DayOfWeek.__dict__, DictProxyType) + assert DayOfWeek.__doc__ is None + + +def test_enum_get_member(): + """Test access to enum members.""" + from System import DayOfWeek + + assert DayOfWeek.Sunday == 0 + assert DayOfWeek.Monday == 1 + assert DayOfWeek.Tuesday == 2 + assert DayOfWeek.Wednesday == 3 + assert DayOfWeek.Thursday == 4 + assert DayOfWeek.Friday == 5 + assert DayOfWeek.Saturday == 6 + + +def test_byte_enum(): + """Test byte enum.""" + assert Test.ByteEnum.Zero == 0 + assert Test.ByteEnum.One == 1 + assert Test.ByteEnum.Two == 2 + + +def test_sbyte_enum(): + """Test sbyte enum.""" + assert Test.SByteEnum.Zero == 0 + assert Test.SByteEnum.One == 1 + assert Test.SByteEnum.Two == 2 + + +def test_short_enum(): + """Test short enum.""" + assert Test.ShortEnum.Zero == 0 + assert Test.ShortEnum.One == 1 + assert Test.ShortEnum.Two == 2 + + +def test_ushort_enum(): + """Test ushort enum.""" + assert Test.UShortEnum.Zero == 0 + assert Test.UShortEnum.One == 1 + assert Test.UShortEnum.Two == 2 + + +def test_int_enum(): + """Test int enum.""" + assert Test.IntEnum.Zero == 0 + assert Test.IntEnum.One == 1 + assert Test.IntEnum.Two == 2 + + +def test_uint_enum(): + """Test uint enum.""" + assert Test.UIntEnum.Zero == long(0) + assert Test.UIntEnum.One == long(1) + assert Test.UIntEnum.Two == long(2) + + +def test_long_enum(): + """Test long enum.""" + assert Test.LongEnum.Zero == long(0) + assert Test.LongEnum.One == long(1) + assert Test.LongEnum.Two == long(2) + + +def test_ulong_enum(): + """Test ulong enum.""" + assert Test.ULongEnum.Zero == long(0) + assert Test.ULongEnum.One == long(1) + assert Test.ULongEnum.Two == long(2) + + +def test_instantiate_enum_fails(): + """Test that instantiation of an enum class fails.""" + from System import DayOfWeek + + with pytest.raises(TypeError): + _ = DayOfWeek() + + +def test_subclass_enum_fails(): + """Test that subclassing of an enumeration fails.""" + from System import DayOfWeek + + with pytest.raises(TypeError): + class Boom(DayOfWeek): + pass + + _ = Boom + + +def test_enum_set_member_fails(): + """Test that setattr operations on enumerations fail.""" + from System import DayOfWeek + + with pytest.raises(TypeError): + DayOfWeek.Sunday = 13 + + with pytest.raises(TypeError): + del DayOfWeek.Sunday + + +def test_enum_with_flags_attr_conversion(): + """Test enumeration conversion with FlagsAttribute set.""" + # This works because the FlagsField enum has FlagsAttribute. + Test.FieldTest().FlagsField = 99 + + # This should fail because our test enum doesn't have it. + with pytest.raises(ValueError): + Test.FieldTest().EnumField = 99 + + +def test_enum_conversion(): + """Test enumeration conversion.""" + ob = Test.FieldTest() + assert ob.EnumField == 0 + + ob.EnumField = Test.ShortEnum.One + assert ob.EnumField == 1 + + with pytest.raises(ValueError): + Test.FieldTest().EnumField = 20 + + with pytest.raises(OverflowError): + Test.FieldTest().EnumField = 100000 + + with pytest.raises(TypeError): + Test.FieldTest().EnumField = "str" diff --git a/src/tests/test_event.py b/src/tests/test_event.py index 047af47f3..624b83d44 100644 --- a/src/tests/test_event.py +++ b/src/tests/test_event.py @@ -1,563 +1,584 @@ # -*- coding: utf-8 -*- -import unittest +"""Test CLR event support.""" +import pytest from Python.Test import EventTest, EventArgsTest -from _compat import range -from utils import (CallableHandler, ClassMethodHandler, GenericHandler, - MultipleHandler, StaticMethodHandler, VarCallableHandler, - VariableArgsHandler) +from ._compat import range +from .utils import (CallableHandler, ClassMethodHandler, GenericHandler, + MultipleHandler, StaticMethodHandler, VarCallableHandler, + VariableArgsHandler) -class EventTests(unittest.TestCase): - """Test CLR event support.""" +def test_public_instance_event(): + """Test public instance events.""" + ob = EventTest() - def test_public_instance_event(self): - """Test public instance events.""" - ob = EventTest() + handler = GenericHandler() + assert handler.value is None - handler = GenericHandler() - self.assertTrue(handler.value is None) + ob.PublicEvent += handler.handler - ob.PublicEvent += handler.handler + ob.OnPublicEvent(EventArgsTest(10)) + assert handler.value == 10 - ob.OnPublicEvent(EventArgsTest(10)) - self.assertTrue(handler.value == 10) + ob.PublicEvent -= handler.handler - ob.PublicEvent -= handler.handler - def test_public_static_event(self): - """Test public static events.""" - handler = GenericHandler() - self.assertTrue(handler.value is None) +def test_public_static_event(): + """Test public static events.""" + handler = GenericHandler() + assert handler.value is None - EventTest.PublicStaticEvent += handler.handler + EventTest.PublicStaticEvent += handler.handler - EventTest.OnPublicStaticEvent(EventArgsTest(10)) - self.assertTrue(handler.value == 10) + EventTest.OnPublicStaticEvent(EventArgsTest(10)) + assert handler.value == 10 - def test_protected_instance_event(self): - """Test protected instance events.""" - ob = EventTest() - handler = GenericHandler() - self.assertTrue(handler.value is None) +def test_protected_instance_event(): + """Test protected instance events.""" + ob = EventTest() - ob.ProtectedEvent += handler.handler + handler = GenericHandler() + assert handler.value is None - ob.OnProtectedEvent(EventArgsTest(10)) - self.assertTrue(handler.value == 10) + ob.ProtectedEvent += handler.handler - ob.ProtectedEvent -= handler.handler + ob.OnProtectedEvent(EventArgsTest(10)) + assert handler.value == 10 - def test_protected_static_event(self): - """Test protected static events.""" - handler = GenericHandler() - self.assertTrue(handler.value is None) + ob.ProtectedEvent -= handler.handler - EventTest.ProtectedStaticEvent += handler.handler - EventTest.OnProtectedStaticEvent(EventArgsTest(10)) - self.assertTrue(handler.value == 10) +def test_protected_static_event(): + """Test protected static events.""" + handler = GenericHandler() + assert handler.value is None - EventTest.ProtectedStaticEvent -= handler.handler + EventTest.ProtectedStaticEvent += handler.handler - def test_internal_events(self): - """Test internal events.""" + EventTest.OnProtectedStaticEvent(EventArgsTest(10)) + assert handler.value == 10 - with self.assertRaises(AttributeError): - _ = EventTest().InternalEvent + EventTest.ProtectedStaticEvent -= handler.handler - with self.assertRaises(AttributeError): - _ = EventTest().InternalStaticEvent - with self.assertRaises(AttributeError): - _ = EventTest.InternalStaticEvent +def test_internal_events(): + """Test internal events.""" - def test_private_events(self): - """Test private events.""" + with pytest.raises(AttributeError): + _ = EventTest().InternalEvent - with self.assertRaises(AttributeError): - _ = EventTest().PrivateEvent + with pytest.raises(AttributeError): + _ = EventTest().InternalStaticEvent - with self.assertRaises(AttributeError): - _ = EventTest().PrivateStaticEvent + with pytest.raises(AttributeError): + _ = EventTest.InternalStaticEvent - with self.assertRaises(AttributeError): - _ = EventTest.PrivateStaticEvent - def test_multicast_event(self): - """Test multicast events.""" - ob = EventTest() +def test_private_events(): + """Test private events.""" - handler1 = GenericHandler() - handler2 = GenericHandler() - handler3 = GenericHandler() + with pytest.raises(AttributeError): + _ = EventTest().PrivateEvent - ob.PublicEvent += handler1.handler - ob.PublicEvent += handler2.handler - ob.PublicEvent += handler3.handler + with pytest.raises(AttributeError): + _ = EventTest().PrivateStaticEvent - ob.OnPublicEvent(EventArgsTest(10)) + with pytest.raises(AttributeError): + _ = EventTest.PrivateStaticEvent - self.assertTrue(handler1.value == 10) - self.assertTrue(handler2.value == 10) - self.assertTrue(handler3.value == 10) - ob.OnPublicEvent(EventArgsTest(20)) +def test_multicast_event(): + """Test multicast events.""" + ob = EventTest() - self.assertTrue(handler1.value == 20) - self.assertTrue(handler2.value == 20) - self.assertTrue(handler3.value == 20) + handler1 = GenericHandler() + handler2 = GenericHandler() + handler3 = GenericHandler() - ob.PublicEvent -= handler1.handler - ob.PublicEvent -= handler2.handler - ob.PublicEvent -= handler3.handler + ob.PublicEvent += handler1.handler + ob.PublicEvent += handler2.handler + ob.PublicEvent += handler3.handler - def test_instance_method_handler(self): - """Test instance method handlers.""" - ob = EventTest() - handler = GenericHandler() + ob.OnPublicEvent(EventArgsTest(10)) - ob.PublicEvent += handler.handler - self.assertTrue(handler.value is None) + assert handler1.value == 10 + assert handler2.value == 10 + assert handler3.value == 10 - ob.OnPublicEvent(EventArgsTest(10)) - self.assertTrue(handler.value == 10) + ob.OnPublicEvent(EventArgsTest(20)) - ob.PublicEvent -= handler.handler - self.assertTrue(handler.value == 10) + assert handler1.value == 20 + assert handler2.value == 20 + assert handler3.value == 20 - ob.OnPublicEvent(EventArgsTest(20)) - self.assertTrue(handler.value == 10) + ob.PublicEvent -= handler1.handler + ob.PublicEvent -= handler2.handler + ob.PublicEvent -= handler3.handler - def test_var_args_instance_method_handler(self): - """Test vararg instance method handlers.""" - ob = EventTest() - handler = VariableArgsHandler() - ob.PublicEvent += handler.handler - self.assertTrue(handler.value is None) +def test_instance_method_handler(): + """Test instance method handlers.""" + ob = EventTest() + handler = GenericHandler() - ob.OnPublicEvent(EventArgsTest(10)) - self.assertTrue(handler.value == 10) + ob.PublicEvent += handler.handler + assert handler.value is None - ob.PublicEvent -= handler.handler - self.assertTrue(handler.value == 10) + ob.OnPublicEvent(EventArgsTest(10)) + assert handler.value == 10 - ob.OnPublicEvent(EventArgsTest(20)) - self.assertTrue(handler.value == 10) + ob.PublicEvent -= handler.handler + assert handler.value == 10 - def test_callableob_handler(self): - """Test callable ob handlers.""" - ob = EventTest() - handler = CallableHandler() + ob.OnPublicEvent(EventArgsTest(20)) + assert handler.value == 10 - ob.PublicEvent += handler - self.assertTrue(handler.value is None) - ob.OnPublicEvent(EventArgsTest(10)) - self.assertTrue(handler.value == 10) +def test_var_args_instance_method_handler(): + """Test vararg instance method handlers.""" + ob = EventTest() + handler = VariableArgsHandler() - ob.PublicEvent -= handler - self.assertTrue(handler.value == 10) + ob.PublicEvent += handler.handler + assert handler.value is None - ob.OnPublicEvent(EventArgsTest(20)) - self.assertTrue(handler.value == 10) + ob.OnPublicEvent(EventArgsTest(10)) + assert handler.value == 10 - def test_var_args_callable_handler(self): - """Test varargs callable handlers.""" - ob = EventTest() - handler = VarCallableHandler() + ob.PublicEvent -= handler.handler + assert handler.value == 10 - ob.PublicEvent += handler - self.assertTrue(handler.value is None) + ob.OnPublicEvent(EventArgsTest(20)) + assert handler.value == 10 - ob.OnPublicEvent(EventArgsTest(10)) - self.assertTrue(handler.value == 10) - ob.PublicEvent -= handler - self.assertTrue(handler.value == 10) +def test_callableob_handler(): + """Test callable ob handlers.""" + ob = EventTest() + handler = CallableHandler() - ob.OnPublicEvent(EventArgsTest(20)) - self.assertTrue(handler.value == 10) + ob.PublicEvent += handler + assert handler.value is None - def test_static_method_handler(self): - """Test static method handlers.""" - ob = EventTest() - handler = StaticMethodHandler() - StaticMethodHandler.value = None + ob.OnPublicEvent(EventArgsTest(10)) + assert handler.value == 10 - ob.PublicEvent += handler.handler - self.assertTrue(handler.value is None) + ob.PublicEvent -= handler + assert handler.value == 10 - ob.OnPublicEvent(EventArgsTest(10)) - self.assertTrue(handler.value == 10) + ob.OnPublicEvent(EventArgsTest(20)) + assert handler.value == 10 - ob.PublicEvent -= handler.handler - self.assertTrue(handler.value == 10) - ob.OnPublicEvent(EventArgsTest(20)) - self.assertTrue(handler.value == 10) +def test_var_args_callable_handler(): + """Test varargs callable handlers.""" + ob = EventTest() + handler = VarCallableHandler() - def test_class_method_handler(self): - """Test class method handlers.""" - ob = EventTest() - handler = ClassMethodHandler() - ClassMethodHandler.value = None + ob.PublicEvent += handler + assert handler.value is None - ob.PublicEvent += handler.handler - self.assertTrue(handler.value is None) + ob.OnPublicEvent(EventArgsTest(10)) + assert handler.value == 10 - ob.OnPublicEvent(EventArgsTest(10)) - self.assertTrue(handler.value == 10) + ob.PublicEvent -= handler + assert handler.value == 10 - ob.PublicEvent -= handler.handler - self.assertTrue(handler.value == 10) + ob.OnPublicEvent(EventArgsTest(20)) + assert handler.value == 10 - ob.OnPublicEvent(EventArgsTest(20)) - self.assertTrue(handler.value == 10) - def test_managed_instance_method_handler(self): - """Test managed instance method handlers.""" - ob = EventTest() +def test_static_method_handler(): + """Test static method handlers.""" + ob = EventTest() + handler = StaticMethodHandler() + StaticMethodHandler.value = None - ob.PublicEvent += ob.GenericHandler - self.assertTrue(ob.value == 0) + ob.PublicEvent += handler.handler + assert handler.value is None - ob.OnPublicEvent(EventArgsTest(10)) - self.assertTrue(ob.value == 10) + ob.OnPublicEvent(EventArgsTest(10)) + assert handler.value == 10 - ob.PublicEvent -= ob.GenericHandler - self.assertTrue(ob.value == 10) + ob.PublicEvent -= handler.handler + assert handler.value == 10 - ob.OnPublicEvent(EventArgsTest(20)) - self.assertTrue(ob.value == 10) + ob.OnPublicEvent(EventArgsTest(20)) + assert handler.value == 10 - def test_managed_static_method_handler(self): - """Test managed static method handlers.""" - ob = EventTest() - EventTest.s_value = 0 - ob.PublicEvent += ob.StaticHandler - self.assertTrue(EventTest.s_value == 0) +def test_class_method_handler(): + """Test class method handlers.""" + ob = EventTest() + handler = ClassMethodHandler() + ClassMethodHandler.value = None - ob.OnPublicEvent(EventArgsTest(10)) - self.assertTrue(EventTest.s_value == 10) + ob.PublicEvent += handler.handler + assert handler.value is None - ob.PublicEvent -= ob.StaticHandler - self.assertTrue(EventTest.s_value == 10) + ob.OnPublicEvent(EventArgsTest(10)) + assert handler.value == 10 - ob.OnPublicEvent(EventArgsTest(20)) - self.assertTrue(EventTest.s_value == 10) + ob.PublicEvent -= handler.handler + assert handler.value == 10 - def test_unbound_method_handler(self): - """Test failure mode for unbound method handlers.""" - ob = EventTest() - ob.PublicEvent += GenericHandler.handler + ob.OnPublicEvent(EventArgsTest(20)) + assert handler.value == 10 - with self.assertRaises(TypeError): - ob.OnPublicEvent(EventArgsTest(10)) - ob.PublicEvent -= GenericHandler.handler +def test_managed_instance_method_handler(): + """Test managed instance method handlers.""" + ob = EventTest() - def test_function_handler(self): - """Test function handlers.""" - ob = EventTest() - dict_ = {'value': None} + ob.PublicEvent += ob.GenericHandler + assert ob.value == 0 + + ob.OnPublicEvent(EventArgsTest(10)) + assert ob.value == 10 - def handler(sender, args, dict_=dict_): - dict_['value'] = args.value + ob.PublicEvent -= ob.GenericHandler + assert ob.value == 10 - ob.PublicEvent += handler - self.assertTrue(dict_['value'] is None) + ob.OnPublicEvent(EventArgsTest(20)) + assert ob.value == 10 + +def test_managed_static_method_handler(): + """Test managed static method handlers.""" + ob = EventTest() + EventTest.s_value = 0 + + ob.PublicEvent += ob.StaticHandler + assert EventTest.s_value == 0 + + ob.OnPublicEvent(EventArgsTest(10)) + assert EventTest.s_value == 10 + + ob.PublicEvent -= ob.StaticHandler + assert EventTest.s_value == 10 + + ob.OnPublicEvent(EventArgsTest(20)) + assert EventTest.s_value == 10 + + +def test_unbound_method_handler(): + """Test failure mode for unbound method handlers.""" + ob = EventTest() + ob.PublicEvent += GenericHandler.handler + + with pytest.raises(TypeError): ob.OnPublicEvent(EventArgsTest(10)) - self.assertTrue(dict_['value'] == 10) - ob.PublicEvent -= handler - self.assertTrue(dict_['value'] == 10) + ob.PublicEvent -= GenericHandler.handler + - ob.OnPublicEvent(EventArgsTest(20)) - self.assertTrue(dict_['value'] == 10) +def test_function_handler(): + """Test function handlers.""" + ob = EventTest() + dict_ = {'value': None} - def test_add_non_callable_handler(self): - """Test handling of attempts to add non-callable handlers.""" + def handler(sender, args, dict_=dict_): + dict_['value'] = args.value - with self.assertRaises(TypeError): - ob = EventTest() - ob.PublicEvent += 10 + ob.PublicEvent += handler + assert dict_['value'] is None - with self.assertRaises(TypeError): - ob = EventTest() - ob.PublicEvent += "spam" + ob.OnPublicEvent(EventArgsTest(10)) + assert dict_['value'] == 10 - with self.assertRaises(TypeError): - class Spam(object): - pass + ob.PublicEvent -= handler + assert dict_['value'] == 10 - ob = EventTest() - ob.PublicEvent += Spam() + ob.OnPublicEvent(EventArgsTest(20)) + assert dict_['value'] == 10 - def test_remove_multiple_handlers(self): - """Test removing multiple instances of the same handler.""" + +def test_add_non_callable_handler(): + """Test handling of attempts to add non-callable handlers.""" + + with pytest.raises(TypeError): ob = EventTest() - handler = MultipleHandler() + ob.PublicEvent += 10 - h1 = handler.handler - ob.PublicEvent += h1 + with pytest.raises(TypeError): + ob = EventTest() + ob.PublicEvent += "spam" - h2 = handler.handler - ob.PublicEvent += h2 + with pytest.raises(TypeError): + class Spam(object): + pass - ob.OnPublicEvent(EventArgsTest(10)) - self.assertTrue(handler.value == 20) + ob = EventTest() + ob.PublicEvent += Spam() - ob.PublicEvent -= h1 - ob.OnPublicEvent(EventArgsTest(10)) - self.assertTrue(handler.value == 30) +def test_remove_multiple_handlers(): + """Test removing multiple instances of the same handler.""" + ob = EventTest() + handler = MultipleHandler() - ob.PublicEvent -= h2 + h1 = handler.handler + ob.PublicEvent += h1 - ob.OnPublicEvent(EventArgsTest(10)) - self.assertTrue(handler.value == 30) + h2 = handler.handler + ob.PublicEvent += h2 - # try again, removing in a different order. + ob.OnPublicEvent(EventArgsTest(10)) + assert handler.value == 20 - ob = EventTest() - handler = MultipleHandler() + ob.PublicEvent -= h1 - h1 = handler.handler - ob.PublicEvent += h1 + ob.OnPublicEvent(EventArgsTest(10)) + assert handler.value == 30 - h2 = handler.handler - ob.PublicEvent += h2 + ob.PublicEvent -= h2 - ob.OnPublicEvent(EventArgsTest(10)) - self.assertTrue(handler.value == 20) + ob.OnPublicEvent(EventArgsTest(10)) + assert handler.value == 30 - ob.PublicEvent -= h2 + # try again, removing in a different order. - ob.OnPublicEvent(EventArgsTest(10)) - self.assertTrue(handler.value == 30) + ob = EventTest() + handler = MultipleHandler() - ob.PublicEvent -= h1 + h1 = handler.handler + ob.PublicEvent += h1 - ob.OnPublicEvent(EventArgsTest(10)) - self.assertTrue(handler.value == 30) + h2 = handler.handler + ob.PublicEvent += h2 - def test_remove_multiple_static_handlers(self): - """Test removing multiple instances of a static handler.""" - ob = EventTest() - handler = MultipleHandler() + ob.OnPublicEvent(EventArgsTest(10)) + assert handler.value == 20 - h1 = handler.handler - ob.PublicStaticEvent += h1 + ob.PublicEvent -= h2 - h2 = handler.handler - ob.PublicStaticEvent += h2 + ob.OnPublicEvent(EventArgsTest(10)) + assert handler.value == 30 - ob.OnPublicStaticEvent(EventArgsTest(10)) - self.assertTrue(handler.value == 20) + ob.PublicEvent -= h1 - ob.PublicStaticEvent -= h1 + ob.OnPublicEvent(EventArgsTest(10)) + assert handler.value == 30 - ob.OnPublicStaticEvent(EventArgsTest(10)) - self.assertTrue(handler.value == 30) - ob.PublicStaticEvent -= h2 +def test_remove_multiple_static_handlers(): + """Test removing multiple instances of a static handler.""" + ob = EventTest() + handler = MultipleHandler() - ob.OnPublicStaticEvent(EventArgsTest(10)) - self.assertTrue(handler.value == 30) + h1 = handler.handler + ob.PublicStaticEvent += h1 - # try again, removing in a different order. + h2 = handler.handler + ob.PublicStaticEvent += h2 - ob = EventTest() - handler = MultipleHandler() + ob.OnPublicStaticEvent(EventArgsTest(10)) + assert handler.value == 20 - h1 = handler.handler - ob.PublicStaticEvent += h1 + ob.PublicStaticEvent -= h1 - h2 = handler.handler - ob.PublicStaticEvent += h2 + ob.OnPublicStaticEvent(EventArgsTest(10)) + assert handler.value == 30 - ob.OnPublicStaticEvent(EventArgsTest(10)) - self.assertTrue(handler.value == 20) + ob.PublicStaticEvent -= h2 - ob.PublicStaticEvent -= h2 + ob.OnPublicStaticEvent(EventArgsTest(10)) + assert handler.value == 30 - ob.OnPublicStaticEvent(EventArgsTest(10)) - self.assertTrue(handler.value == 30) + # try again, removing in a different order. - ob.PublicStaticEvent -= h1 + ob = EventTest() + handler = MultipleHandler() - ob.OnPublicStaticEvent(EventArgsTest(10)) - self.assertTrue(handler.value == 30) + h1 = handler.handler + ob.PublicStaticEvent += h1 - def test_random_multiple_handlers(self): - """Test random subscribe / unsubscribe of the same handlers.""" - import random - ob = EventTest() - handler = MultipleHandler() - handler2 = MultipleHandler() + h2 = handler.handler + ob.PublicStaticEvent += h2 - ob.PublicEvent += handler2.handler - ob.PublicEvent += handler2.handler + ob.OnPublicStaticEvent(EventArgsTest(10)) + assert handler.value == 20 - handlers = [] - for _ in range(30): - method = handler.handler - ob.PublicEvent += method - handlers.append(method) + ob.PublicStaticEvent -= h2 - ob.OnPublicEvent(EventArgsTest(10)) - self.assertTrue(handler.value == 300) - self.assertTrue(handler2.value == 20) - handler.value = 0 - handler2.value = 0 - - for i in range(30): - item = random.choice(handlers) - handlers.remove(item) - ob.PublicEvent -= item - handler.value = 0 - ob.OnPublicEvent(EventArgsTest(10)) - self.assertTrue(handler.value == (len(handlers) * 10)) - self.assertTrue(handler2.value == ((i + 1) * 20)) - - handler2.value = 0 - ob.OnPublicEvent(EventArgsTest(10)) - self.assertTrue(handler2.value == 20) + ob.OnPublicStaticEvent(EventArgsTest(10)) + assert handler.value == 30 - ob.PublicEvent -= handler2.handler + ob.PublicStaticEvent -= h1 - handler2.value = 0 - ob.OnPublicEvent(EventArgsTest(10)) - self.assertTrue(handler2.value == 10) + ob.OnPublicStaticEvent(EventArgsTest(10)) + assert handler.value == 30 + + +def test_random_multiple_handlers(): + """Test random subscribe / unsubscribe of the same handlers.""" + import random + ob = EventTest() + handler = MultipleHandler() + handler2 = MultipleHandler() + + ob.PublicEvent += handler2.handler + ob.PublicEvent += handler2.handler - ob.PublicEvent -= handler2.handler + handlers = [] + for _ in range(30): + method = handler.handler + ob.PublicEvent += method + handlers.append(method) - handler2.value = 0 + ob.OnPublicEvent(EventArgsTest(10)) + assert handler.value == 300 + assert handler2.value == 20 + handler.value = 0 + handler2.value = 0 + + for i in range(30): + item = random.choice(handlers) + handlers.remove(item) + ob.PublicEvent -= item + handler.value = 0 ob.OnPublicEvent(EventArgsTest(10)) - self.assertTrue(handler2.value == 0) + assert handler.value == (len(handlers) * 10) + assert handler2.value == ((i + 1) * 20) - def test_remove_internal_call_handler(self): - """Test remove on an event sink implemented w/internalcall.""" - ob = EventTest() + handler2.value = 0 + ob.OnPublicEvent(EventArgsTest(10)) + assert handler2.value == 20 - def h(sender, args): - pass + ob.PublicEvent -= handler2.handler - ob.PublicEvent += h - ob.PublicEvent -= h + handler2.value = 0 + ob.OnPublicEvent(EventArgsTest(10)) + assert handler2.value == 10 - def test_remove_unknown_handler(self): - """Test removing an event handler that was never added.""" + ob.PublicEvent -= handler2.handler - with self.assertRaises(ValueError): - ob = EventTest() - handler = GenericHandler() + handler2.value = 0 + ob.OnPublicEvent(EventArgsTest(10)) + assert handler2.value == 0 - ob.PublicEvent -= handler.handler - def test_handler_callback_failure(self): - """Test failure mode for inappropriate handlers.""" +def test_remove_internal_call_handler(): + """Test remove on an event sink implemented w/internalcall.""" + ob = EventTest() - class BadHandler(object): - def handler(self, one): - return 'too many' + def h(sender, args): + pass + + ob.PublicEvent += h + ob.PublicEvent -= h - ob = EventTest() - handler = BadHandler() - with self.assertRaises(TypeError): - ob.PublicEvent += handler.handler - ob.OnPublicEvent(EventArgsTest(10)) +def test_remove_unknown_handler(): + """Test removing an event handler that was never added.""" + + with pytest.raises(ValueError): + ob = EventTest() + handler = GenericHandler() ob.PublicEvent -= handler.handler - class BadHandler(object): - def handler(self, one, two, three, four, five): - return 'not enough' - ob = EventTest() - handler = BadHandler() +def test_handler_callback_failure(): + """Test failure mode for inappropriate handlers.""" - with self.assertRaises(TypeError): - ob.PublicEvent += handler.handler - ob.OnPublicEvent(EventArgsTest(10)) + class BadHandler(object): + def handler(self, one): + return 'too many' - ob.PublicEvent -= handler.handler + ob = EventTest() + handler = BadHandler() - def test_incorrect_invokation(self): - """Test incorrect invocation of events.""" - ob = EventTest() + with pytest.raises(TypeError): + ob.PublicEvent += handler.handler + ob.OnPublicEvent(EventArgsTest(10)) - handler = GenericHandler() + ob.PublicEvent -= handler.handler + + class BadHandler(object): + def handler(self, one, two, three, four, five): + return 'not enough' + + ob = EventTest() + handler = BadHandler() + + with pytest.raises(TypeError): ob.PublicEvent += handler.handler + ob.OnPublicEvent(EventArgsTest(10)) - with self.assertRaises(TypeError): - ob.OnPublicEvent() + ob.PublicEvent -= handler.handler - with self.assertRaises(TypeError): - ob.OnPublicEvent(32) - ob.PublicEvent -= handler.handler +def test_incorrect_invokation(): + """Test incorrect invocation of events.""" + ob = EventTest() - def test_explicit_cls_event_registration(self): - """Test explicit CLS event registration.""" - from Python.Test import EventHandlerTest + handler = GenericHandler() + ob.PublicEvent += handler.handler - ob = EventTest() - handler = GenericHandler() + with pytest.raises(TypeError): + ob.OnPublicEvent() - delegate = EventHandlerTest(handler.handler) - ob.add_PublicEvent(delegate) - self.assertTrue(handler.value is None) + with pytest.raises(TypeError): + ob.OnPublicEvent(32) - ob.OnPublicEvent(EventArgsTest(10)) - self.assertTrue(handler.value == 10) + ob.PublicEvent -= handler.handler + + +def test_explicit_cls_event_registration(): + """Test explicit CLS event registration.""" + from Python.Test import EventHandlerTest - ob.remove_PublicEvent(delegate) - self.assertTrue(handler.value == 10) + ob = EventTest() + handler = GenericHandler() - ob.OnPublicEvent(EventArgsTest(20)) - self.assertTrue(handler.value == 10) + delegate = EventHandlerTest(handler.handler) + ob.add_PublicEvent(delegate) + assert handler.value is None - def test_implicit_cls_event_registration(self): - """Test implicit CLS event registration.""" + ob.OnPublicEvent(EventArgsTest(10)) + assert handler.value == 10 - with self.assertRaises(TypeError): - ob = EventTest() - handler = GenericHandler() - ob.add_PublicEvent(handler.handler) + ob.remove_PublicEvent(delegate) + assert handler.value == 10 - def test_event_descriptor_abuse(self): - """Test event descriptor abuse.""" + ob.OnPublicEvent(EventArgsTest(20)) + assert handler.value == 10 - with self.assertRaises(TypeError): - del EventTest.PublicEvent - with self.assertRaises(TypeError): - del EventTest.__dict__['PublicEvent'] +def test_implicit_cls_event_registration(): + """Test implicit CLS event registration.""" + + with pytest.raises(TypeError): + ob = EventTest() + handler = GenericHandler() + ob.add_PublicEvent(handler.handler) - desc = EventTest.__dict__['PublicEvent'] - with self.assertRaises(TypeError): - desc.__get__(0, 0) +def test_event_descriptor_abuse(): + """Test event descriptor abuse.""" - with self.assertRaises(TypeError): - desc.__set__(0, 0) + with pytest.raises(TypeError): + del EventTest.PublicEvent - with self.assertRaises(TypeError): - ob = EventTest() - ob.PublicEvent = 0 + with pytest.raises(TypeError): + del EventTest.__dict__['PublicEvent'] - with self.assertRaises(TypeError): - EventTest.PublicStaticEvent = 0 + desc = EventTest.__dict__['PublicEvent'] + with pytest.raises(TypeError): + desc.__get__(0, 0) + + with pytest.raises(TypeError): + desc.__set__(0, 0) + + with pytest.raises(TypeError): + ob = EventTest() + ob.PublicEvent = 0 -def test_suite(): - return unittest.makeSuite(EventTests) + with pytest.raises(TypeError): + EventTest.PublicStaticEvent = 0 diff --git a/src/tests/test_exceptions.py b/src/tests/test_exceptions.py index 2fb55589c..f47209f6d 100644 --- a/src/tests/test_exceptions.py +++ b/src/tests/test_exceptions.py @@ -1,328 +1,347 @@ # -*- coding: utf-8 -*- +"""Test exception support.""" + import sys -import unittest import System +import pytest + +from ._compat import PY2, PY3, pickle, text_type + + +def test_unified_exception_semantics(): + """Test unified exception semantics.""" + e = System.Exception('Something bad happened') + assert isinstance(e, Exception) + assert isinstance(e, System.Exception) + + +def test_standard_exception_attributes(): + """Test accessing standard exception attributes.""" + from System import OverflowException + from Python.Test import ExceptionTest + + e = ExceptionTest.GetExplicitException() + assert isinstance(e, OverflowException) + + assert e.Message == 'error' + + e.Source = 'Test Suite' + assert e.Source == 'Test Suite' + + v = e.ToString() + assert len(v) > 0 + + +def test_extended_exception_attributes(): + """Test accessing extended exception attributes.""" + from Python.Test import ExceptionTest, ExtendedException + from System import OverflowException + + e = ExceptionTest.GetExtendedException() + assert isinstance(e, ExtendedException) + assert isinstance(e, OverflowException) + assert isinstance(e, System.Exception) + + assert e.Message == 'error' + + e.Source = 'Test Suite' + assert e.Source == 'Test Suite' + + v = e.ToString() + assert len(v) > 0 + + assert e.ExtraProperty == 'extra' + e.ExtraProperty = 'changed' + assert e.ExtraProperty == 'changed' + + assert e.GetExtraInfo() == 'changed' + + +def test_raise_class_exception(): + """Test class exception propagation.""" + from System import NullReferenceException + + with pytest.raises(NullReferenceException) as cm: + raise NullReferenceException + + exc = cm.value + assert isinstance(exc, NullReferenceException) + + +def test_exc_info(): + """Test class exception propagation. + Behavior of exc_info changed in Py3. Refactoring its test""" + from System import NullReferenceException + try: + raise NullReferenceException("message") + except Exception as exc: + type_, value, tb = sys.exc_info() + assert type_ is NullReferenceException + assert value.Message == "message" + assert exc.Message == "message" + # FIXME: Lower-case message isn't implemented + # self.assertTrue(exc.message == "message") + assert value is exc + + +def test_raise_class_exception_with_value(): + """Test class exception propagation with associated value.""" + from System import NullReferenceException + + with pytest.raises(NullReferenceException) as cm: + raise NullReferenceException('Aiiieee!') + + exc = cm.value + assert isinstance(exc, NullReferenceException) + assert exc.Message == 'Aiiieee!' + + +def test_raise_instance_exception(): + """Test instance exception propagation.""" + from System import NullReferenceException + + with pytest.raises(NullReferenceException) as cm: + raise NullReferenceException() + + exc = cm.value + assert isinstance(exc, NullReferenceException) + assert len(exc.Message) > 0 + + +def test_raise_instance_exception_with_args(): + """Test instance exception propagation with args.""" + from System import NullReferenceException -from _compat import PY2, PY3, pickle, text_type + with pytest.raises(NullReferenceException) as cm: + raise NullReferenceException("Aiiieee!") + exc = cm.value + assert isinstance(exc, NullReferenceException) + assert exc.Message == 'Aiiieee!' -class ExceptionTests(unittest.TestCase): - """Test exception support.""" - def test_unified_exception_semantics(self): - """Test unified exception semantics.""" - e = System.Exception('Something bad happened') - self.assertTrue(isinstance(e, Exception)) - self.assertTrue(isinstance(e, System.Exception)) +def test_managed_exception_propagation(): + """Test propagation of exceptions raised in managed code.""" + from System import Decimal, OverflowException - def test_standard_exception_attributes(self): - """Test accessing standard exception attributes.""" - from System import OverflowException - from Python.Test import ExceptionTest + with pytest.raises(OverflowException): + Decimal.ToInt64(Decimal.MaxValue) - e = ExceptionTest.GetExplicitException() - self.assertTrue(isinstance(e, OverflowException)) - self.assertTrue(e.Message == 'error') +def test_managed_exception_conversion(): + """Test conversion of managed exceptions.""" + from System import OverflowException + from Python.Test import ExceptionTest - e.Source = 'Test Suite' - self.assertTrue(e.Source == 'Test Suite') + e = ExceptionTest.GetBaseException() + assert isinstance(e, System.Exception) - v = e.ToString() - self.assertTrue(len(v) > 0) + e = ExceptionTest.GetExplicitException() + assert isinstance(e, OverflowException) + assert isinstance(e, System.Exception) - def test_extended_exception_attributes(self): - """Test accessing extended exception attributes.""" - from Python.Test import ExceptionTest, ExtendedException - from System import OverflowException + e = ExceptionTest.GetWidenedException() + assert isinstance(e, OverflowException) + assert isinstance(e, System.Exception) - e = ExceptionTest.GetExtendedException() - self.assertTrue(isinstance(e, ExtendedException)) - self.assertTrue(isinstance(e, OverflowException)) - self.assertTrue(isinstance(e, System.Exception)) + v = ExceptionTest.SetBaseException(System.Exception('error')) + assert v - self.assertTrue(e.Message == 'error') + v = ExceptionTest.SetExplicitException(OverflowException('error')) + assert v - e.Source = 'Test Suite' - self.assertTrue(e.Source == 'Test Suite') + v = ExceptionTest.SetWidenedException(OverflowException('error')) + assert v - v = e.ToString() - self.assertTrue(len(v) > 0) - self.assertTrue(e.ExtraProperty == 'extra') - e.ExtraProperty = 'changed' - self.assertTrue(e.ExtraProperty == 'changed') +def test_catch_exception_from_managed_method(): + """Test catching an exception from a managed method.""" + from Python.Test import ExceptionTest + from System import OverflowException - self.assertTrue(e.GetExtraInfo() == 'changed') + with pytest.raises(OverflowException) as cm: + ExceptionTest().ThrowException() - def test_raise_class_exception(self): - """Test class exception propagation.""" - from System import NullReferenceException + e = cm.value + assert isinstance(e, OverflowException) - with self.assertRaises(NullReferenceException) as cm: - raise NullReferenceException - exc = cm.exception - self.assertTrue(isinstance(exc, NullReferenceException)) +def test_catch_exception_from_managed_property(): + """Test catching an exception from a managed property.""" + from Python.Test import ExceptionTest + from System import OverflowException - def test_exc_info(self): - """Test class exception propagation. - Behavior of exc_info changed in Py3. Refactoring its test""" - from System import NullReferenceException - try: - raise NullReferenceException("message") - except Exception as exc: - type_, value, tb = sys.exc_info() - self.assertTrue(type_ is NullReferenceException) - self.assertTrue(value.Message == "message") - self.assertTrue(exc.Message == "message") - # FIXME: Lower-case message isn't implemented - # self.assertTrue(exc.message == "message") - self.assertTrue(value is exc) + with pytest.raises(OverflowException) as cm: + _ = ExceptionTest().ThrowProperty - def test_raise_class_exception_with_value(self): - """Test class exception propagation with associated value.""" - from System import NullReferenceException + e = cm.value + assert isinstance(e, OverflowException) - with self.assertRaises(NullReferenceException) as cm: - raise NullReferenceException('Aiiieee!') + with pytest.raises(OverflowException) as cm: + ExceptionTest().ThrowProperty = 1 - exc = cm.exception - self.assertTrue(isinstance(exc, NullReferenceException)) - self.assertTrue(exc.Message == 'Aiiieee!') + e = cm.value + assert isinstance(e, OverflowException) - def test_raise_instance_exception(self): - """Test instance exception propagation.""" - from System import NullReferenceException - with self.assertRaises(NullReferenceException) as cm: - raise NullReferenceException() +def test_catch_exception_managed_class(): + """Test catching the managed class of an exception.""" + from System import OverflowException - exc = cm.exception - self.assertTrue(isinstance(exc, NullReferenceException)) - self.assertTrue(len(exc.Message) > 0) + with pytest.raises(OverflowException): + raise OverflowException('overflow') - def test_raise_instance_exception_with_args(self): - """Test instance exception propagation with args.""" - from System import NullReferenceException - with self.assertRaises(NullReferenceException) as cm: - raise NullReferenceException("Aiiieee!") +def test_catch_exception_python_class(): + """Test catching the python class of an exception.""" + from System import OverflowException - exc = cm.exception - self.assertTrue(isinstance(exc, NullReferenceException)) - self.assertTrue(exc.Message == 'Aiiieee!') + with pytest.raises(Exception): + raise OverflowException('overflow') - def test_managed_exception_propagation(self): - """Test propagation of exceptions raised in managed code.""" - from System import Decimal, OverflowException - with self.assertRaises(OverflowException): - Decimal.ToInt64(Decimal.MaxValue) +def test_catch_exception_base_class(): + """Test catching the base of an exception.""" + from System import OverflowException, ArithmeticException - def test_managed_exception_conversion(self): - """Test conversion of managed exceptions.""" - from System import OverflowException - from Python.Test import ExceptionTest + with pytest.raises(ArithmeticException): + raise OverflowException('overflow') - e = ExceptionTest.GetBaseException() - self.assertTrue(isinstance(e, System.Exception)) - e = ExceptionTest.GetExplicitException() - self.assertTrue(isinstance(e, OverflowException)) - self.assertTrue(isinstance(e, System.Exception)) +def test_catch_exception_nested_base_class(): + """Test catching the nested base of an exception.""" + from System import OverflowException, SystemException - e = ExceptionTest.GetWidenedException() - self.assertTrue(isinstance(e, OverflowException)) - self.assertTrue(isinstance(e, System.Exception)) + with pytest.raises(SystemException): + raise OverflowException('overflow') - v = ExceptionTest.SetBaseException(System.Exception('error')) - self.assertTrue(v) - v = ExceptionTest.SetExplicitException(OverflowException('error')) - self.assertTrue(v) +def test_catch_exception_with_assignment(): + """Test catching an exception with assignment.""" + from System import OverflowException - v = ExceptionTest.SetWidenedException(OverflowException('error')) - self.assertTrue(v) + with pytest.raises(OverflowException) as cm: + raise OverflowException('overflow') - def test_catch_exception_from_managed_method(self): - """Test catching an exception from a managed method.""" - from Python.Test import ExceptionTest - from System import OverflowException + e = cm.value + assert isinstance(e, OverflowException) - with self.assertRaises(OverflowException) as cm: - ExceptionTest().ThrowException() - e = cm.exception - self.assertTrue(isinstance(e, OverflowException)) +def test_catch_exception_unqualified(): + """Test catching an unqualified exception.""" + from System import OverflowException - def test_catch_exception_from_managed_property(self): - """Test catching an exception from a managed property.""" - from Python.Test import ExceptionTest - from System import OverflowException + try: + raise OverflowException('overflow') + except: + pass + else: + self.fail("failed to catch unqualified exception") - with self.assertRaises(OverflowException) as cm: - _ = ExceptionTest().ThrowProperty - e = cm.exception - self.assertTrue(isinstance(e, OverflowException)) +def test_catch_baseexception(): + """Test catching an unqualified exception with BaseException.""" + from System import OverflowException - with self.assertRaises(OverflowException) as cm: - ExceptionTest().ThrowProperty = 1 + with pytest.raises(BaseException): + raise OverflowException('overflow') - e = cm.exception - self.assertTrue(isinstance(e, OverflowException)) - def test_catch_exception_managed_class(self): - """Test catching the managed class of an exception.""" - from System import OverflowException +def test_apparent_module_of_exception(): + """Test the apparent module of an exception.""" + from System import OverflowException - with self.assertRaises(OverflowException): - raise OverflowException('overflow') + assert System.Exception.__module__ == 'System' + assert OverflowException.__module__ == 'System' - def test_catch_exception_python_class(self): - """Test catching the python class of an exception.""" - from System import OverflowException - with self.assertRaises(Exception): - raise OverflowException('overflow') +def test_str_of_exception(): + """Test the str() representation of an exception.""" + from System import NullReferenceException, Convert, FormatException - def test_catch_exception_base_class(self): - """Test catching the base of an exception.""" - from System import OverflowException, ArithmeticException + e = NullReferenceException('') + assert str(e) == '' - with self.assertRaises(ArithmeticException): - raise OverflowException('overflow') + e = NullReferenceException('Something bad happened') + assert str(e).startswith('Something bad happened') - def test_catch_exception_nested_base_class(self): - """Test catching the nested base of an exception.""" - from System import OverflowException, SystemException + with pytest.raises(FormatException) as cm: + Convert.ToDateTime('this will fail') - with self.assertRaises(SystemException): - raise OverflowException('overflow') + e = cm.value + # fix for international installation + msg = text_type(e).encode("utf8") + fnd = text_type('System.Convert.ToDateTime').encode("utf8") + assert msg.find(fnd) > -1, msg - def test_catch_exception_with_assignment(self): - """Test catching an exception with assignment.""" - from System import OverflowException - with self.assertRaises(OverflowException) as cm: - raise OverflowException('overflow') +def test_python_compat_of_managed_exceptions(): + """Test managed exceptions compatible with Python's implementation""" + from System import OverflowException + msg = "Simple message" - e = cm.exception - self.assertTrue(isinstance(e, OverflowException)) + e = OverflowException(msg) + assert str(e) == msg + assert text_type(e) == msg - def test_catch_exception_unqualified(self): - """Test catching an unqualified exception.""" - from System import OverflowException + assert e.args == (msg,) + assert isinstance(e.args, tuple) + if PY3: + assert repr(e) == "OverflowException('Simple message',)" + elif PY2: + assert repr(e) == "OverflowException(u'Simple message',)" - try: - raise OverflowException('overflow') - except: - pass - else: - self.fail("failed to catch unqualified exception") - def test_catch_baseexception(self): - """Test catching an unqualified exception with BaseException.""" - from System import OverflowException +def test_exception_is_instance_of_system_object(): + """Test behavior of isinstance(, System.Object).""" + # This is an anti-test, in that this is a caveat of the current + # implementation. Because exceptions are not allowed to be new-style + # classes, we wrap managed exceptions in a general-purpose old-style + # class that delegates to the wrapped object. This makes _almost_ + # everything work as expected, except that an isinstance check against + # CLR.System.Object will fail for a managed exception (because a new + # style class cannot appear in the __bases__ of an old-style class + # without causing a crash in the CPython interpreter). This test is + # here mainly to remind me to update the caveat in the documentation + # one day when when exceptions can be new-style classes. - with self.assertRaises(BaseException): - raise OverflowException('overflow') + # This behavior is now over-shadowed by the implementation of + # __instancecheck__ (i.e., overloading isinstance), so for all Python + # version >= 2.6 we expect isinstance(, Object) to + # be true, even though it does not really subclass Object. + from System import OverflowException, Object - def test_apparent_module_of_exception(self): - """Test the apparent module of an exception.""" - from System import OverflowException + o = OverflowException('error') - self.assertTrue(System.Exception.__module__ == 'System') - self.assertTrue(OverflowException.__module__ == 'System') + if sys.version_info >= (2, 6): + assert isinstance(o, Object) + else: + assert not isinstance(o, Object) - def test_str_of_exception(self): - """Test the str() representation of an exception.""" - from System import NullReferenceException, Convert, FormatException - e = NullReferenceException('') - self.assertEqual(str(e), '') +def test_pickling_exceptions(): + exc = System.Exception("test") + dumped = pickle.dumps(exc) + loaded = pickle.loads(dumped) - e = NullReferenceException('Something bad happened') - self.assertTrue(str(e).startswith('Something bad happened')) + assert exc.args == loaded.args - with self.assertRaises(FormatException) as cm: - Convert.ToDateTime('this will fail') - e = cm.exception - # fix for international installation - msg = text_type(e).encode("utf8") - fnd = text_type('System.Convert.ToDateTime').encode("utf8") - self.assertTrue(msg.find(fnd) > -1, msg) +@pytest.mark.skipif(PY2, reason="__cause__ isn't implemented in PY2") +def test_chained_exceptions(): + from Python.Test import ExceptionTest - def test_python_compat_of_managed_exceptions(self): - """Test managed exceptions compatible with Python's implementation""" - from System import OverflowException - msg = "Simple message" + with pytest.raises(Exception) as cm: + ExceptionTest.ThrowChainedExceptions() - e = OverflowException(msg) - self.assertEqual(str(e), msg) - self.assertEqual(text_type(e), msg) + exc = cm.value - self.assertEqual(e.args, (msg,)) - self.assertTrue(isinstance(e.args, tuple)) - if PY3: - self.assertEqual(repr(e), "OverflowException('Simple message',)") - elif PY2: - self.assertEqual(repr(e), "OverflowException(u'Simple message',)") - - def test_exception_is_instance_of_system_object(self): - """Test behavior of isinstance(, System.Object).""" - # This is an anti-test, in that this is a caveat of the current - # implementation. Because exceptions are not allowed to be new-style - # classes, we wrap managed exceptions in a general-purpose old-style - # class that delegates to the wrapped object. This makes _almost_ - # everything work as expected, except that an isinstance check against - # CLR.System.Object will fail for a managed exception (because a new - # style class cannot appear in the __bases__ of an old-style class - # without causing a crash in the CPython interpreter). This test is - # here mainly to remind me to update the caveat in the documentation - # one day when when exceptions can be new-style classes. - - # This behavior is now over-shadowed by the implementation of - # __instancecheck__ (i.e., overloading isinstance), so for all Python - # version >= 2.6 we expect isinstance(, Object) to - # be true, even though it does not really subclass Object. - from System import OverflowException, Object - - o = OverflowException('error') - - if sys.version_info >= (2, 6): - self.assertTrue(isinstance(o, Object)) - else: - self.assertFalse(isinstance(o, Object)) - - def test_pickling_exceptions(self): - exc = System.Exception("test") - dumped = pickle.dumps(exc) - loaded = pickle.loads(dumped) - - self.assertEqual(exc.args, loaded.args) - - @unittest.skipIf(PY2, "__cause__ isn't implemented in PY2") - def test_chained_exceptions(self): - from Python.Test import ExceptionTest - - with self.assertRaises(Exception) as cm: - ExceptionTest.ThrowChainedExceptions() - - exc = cm.exception - - 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__ - - -def test_suite(): - return unittest.makeSuite(ExceptionTests) + msgs = ("Outer exception", + "Inner exception", + "Innermost exception",) + for msg in msgs: + assert exc.Message == msg + assert exc.__cause__ == exc.InnerException + exc = exc.__cause__ diff --git a/src/tests/test_field.py b/src/tests/test_field.py index b1d596fea..d187de5d2 100644 --- a/src/tests/test_field.py +++ b/src/tests/test_field.py @@ -1,369 +1,392 @@ # -*- coding: utf-8 -*- -import unittest +"""Test CLR field support.""" import System +import pytest from Python.Test import FieldTest -class FieldTests(unittest.TestCase): - """Test CLR field support.""" +def test_public_instance_field(): + """Test public instance fields.""" + ob = FieldTest() + assert ob.PublicField == 0 - def test_public_instance_field(self): - """Test public instance fields.""" - ob = FieldTest() - self.assertTrue(ob.PublicField == 0) + ob.PublicField = 1 + assert ob.PublicField == 1 - ob.PublicField = 1 - self.assertTrue(ob.PublicField == 1) + with pytest.raises(TypeError): + del FieldTest().PublicField - with self.assertRaises(TypeError): - del FieldTest().PublicField - def test_public_static_field(self): - """Test public static fields.""" - ob = FieldTest() - self.assertTrue(FieldTest.PublicStaticField == 0) +def test_public_static_field(): + """Test public static fields.""" + ob = FieldTest() + assert FieldTest.PublicStaticField == 0 - FieldTest.PublicStaticField = 1 - self.assertTrue(FieldTest.PublicStaticField == 1) + FieldTest.PublicStaticField = 1 + assert FieldTest.PublicStaticField == 1 - self.assertTrue(ob.PublicStaticField == 1) - ob.PublicStaticField = 0 - self.assertTrue(ob.PublicStaticField == 0) + assert ob.PublicStaticField == 1 + ob.PublicStaticField = 0 + assert ob.PublicStaticField == 0 - with self.assertRaises(TypeError): - del FieldTest.PublicStaticField + with pytest.raises(TypeError): + del FieldTest.PublicStaticField - with self.assertRaises(TypeError): - del FieldTest().PublicStaticField + with pytest.raises(TypeError): + del FieldTest().PublicStaticField - def test_protected_instance_field(self): - """Test protected instance fields.""" - ob = FieldTest() - self.assertTrue(ob.ProtectedField == 0) - ob.ProtectedField = 1 - self.assertTrue(ob.ProtectedField == 1) +def test_protected_instance_field(): + """Test protected instance fields.""" + ob = FieldTest() + assert ob.ProtectedField == 0 - with self.assertRaises(TypeError): - del FieldTest().ProtectedField + ob.ProtectedField = 1 + assert ob.ProtectedField == 1 - def test_protected_static_field(self): - """Test protected static fields.""" - ob = FieldTest() - self.assertTrue(FieldTest.ProtectedStaticField == 0) + with pytest.raises(TypeError): + del FieldTest().ProtectedField - FieldTest.ProtectedStaticField = 1 - self.assertTrue(FieldTest.ProtectedStaticField == 1) - self.assertTrue(ob.ProtectedStaticField == 1) - ob.ProtectedStaticField = 0 - self.assertTrue(ob.ProtectedStaticField == 0) +def test_protected_static_field(): + """Test protected static fields.""" + ob = FieldTest() + assert FieldTest.ProtectedStaticField == 0 - with self.assertRaises(TypeError): - del FieldTest.ProtectedStaticField + FieldTest.ProtectedStaticField = 1 + assert FieldTest.ProtectedStaticField == 1 - with self.assertRaises(TypeError): - del FieldTest().ProtectedStaticField + assert ob.ProtectedStaticField == 1 + ob.ProtectedStaticField = 0 + assert ob.ProtectedStaticField == 0 - def test_read_only_instance_field(self): - """Test readonly instance fields.""" - self.assertTrue(FieldTest().ReadOnlyField == 0) + with pytest.raises(TypeError): + del FieldTest.ProtectedStaticField - with self.assertRaises(TypeError): - FieldTest().ReadOnlyField = 1 + with pytest.raises(TypeError): + del FieldTest().ProtectedStaticField - with self.assertRaises(TypeError): - del FieldTest().ReadOnlyField - def test_read_only_static_field(self): - """Test readonly static fields.""" - ob = FieldTest() +def test_read_only_instance_field(): + """Test readonly instance fields.""" + assert FieldTest().ReadOnlyField == 0 - self.assertTrue(FieldTest.ReadOnlyStaticField == 0) - self.assertTrue(ob.ReadOnlyStaticField == 0) + with pytest.raises(TypeError): + FieldTest().ReadOnlyField = 1 - with self.assertRaises(TypeError): - FieldTest.ReadOnlyStaticField = 1 + with pytest.raises(TypeError): + del FieldTest().ReadOnlyField - with self.assertRaises(TypeError): - FieldTest().ReadOnlyStaticField = 1 - with self.assertRaises(TypeError): - del FieldTest.ReadOnlyStaticField +def test_read_only_static_field(): + """Test readonly static fields.""" + ob = FieldTest() - with self.assertRaises(TypeError): - del FieldTest().ReadOnlyStaticField + assert FieldTest.ReadOnlyStaticField == 0 + assert ob.ReadOnlyStaticField == 0 - def test_constant_field(self): - """Test const fields.""" - ob = FieldTest() + with pytest.raises(TypeError): + FieldTest.ReadOnlyStaticField = 1 - self.assertTrue(FieldTest.ConstField == 0) - self.assertTrue(ob.ConstField == 0) + with pytest.raises(TypeError): + FieldTest().ReadOnlyStaticField = 1 - with self.assertRaises(TypeError): - FieldTest().ConstField = 1 + with pytest.raises(TypeError): + del FieldTest.ReadOnlyStaticField - with self.assertRaises(TypeError): - FieldTest.ConstField = 1 + with pytest.raises(TypeError): + del FieldTest().ReadOnlyStaticField - with self.assertRaises(TypeError): - del FieldTest().ConstField - with self.assertRaises(TypeError): - del FieldTest.ConstField +def test_constant_field(): + """Test const fields.""" + ob = FieldTest() - def test_internal_field(self): - """Test internal fields.""" + assert FieldTest.ConstField == 0 + assert ob.ConstField == 0 - with self.assertRaises(AttributeError): - _ = FieldTest().InternalField + with pytest.raises(TypeError): + FieldTest().ConstField = 1 - with self.assertRaises(AttributeError): - _ = FieldTest().InternalStaticField + with pytest.raises(TypeError): + FieldTest.ConstField = 1 - with self.assertRaises(AttributeError): - _ = FieldTest.InternalStaticField + with pytest.raises(TypeError): + del FieldTest().ConstField - def test_private_field(self): - """Test private fields.""" + with pytest.raises(TypeError): + del FieldTest.ConstField - with self.assertRaises(AttributeError): - _ = FieldTest().PrivateField - with self.assertRaises(AttributeError): - _ = FieldTest().PrivateStaticField +def test_internal_field(): + """Test internal fields.""" - with self.assertRaises(AttributeError): - _ = FieldTest.PrivateStaticField + with pytest.raises(AttributeError): + _ = FieldTest().InternalField - def test_field_descriptor_get_set(self): - """Test field descriptor get / set.""" + with pytest.raises(AttributeError): + _ = FieldTest().InternalStaticField - # This test ensures that setting an attribute implemented with - # a descriptor actually goes through the descriptor (rather than - # silently replacing the descriptor in the instance or type dict. + with pytest.raises(AttributeError): + _ = FieldTest.InternalStaticField - ob = FieldTest() - self.assertTrue(FieldTest.PublicStaticField == 0) - self.assertTrue(ob.PublicStaticField == 0) +def test_private_field(): + """Test private fields.""" - descriptor = FieldTest.__dict__['PublicStaticField'] - self.assertTrue(type(descriptor) != int) + with pytest.raises(AttributeError): + _ = FieldTest().PrivateField - ob.PublicStaticField = 0 - descriptor = FieldTest.__dict__['PublicStaticField'] - self.assertTrue(type(descriptor) != int) + with pytest.raises(AttributeError): + _ = FieldTest().PrivateStaticField - FieldTest.PublicStaticField = 0 - descriptor = FieldTest.__dict__['PublicStaticField'] - self.assertTrue(type(descriptor) != int) + with pytest.raises(AttributeError): + _ = FieldTest.PrivateStaticField - def test_field_descriptor_wrong_type(self): - """Test setting a field using a value of the wrong type.""" - with self.assertRaises(TypeError): - FieldTest().PublicField = "spam" +def test_field_descriptor_get_set(): + """Test field descriptor get / set.""" - def test_field_descriptor_abuse(self): - """Test field descriptor abuse.""" - desc = FieldTest.__dict__['PublicField'] + # This test ensures that setting an attribute implemented with + # a descriptor actually goes through the descriptor (rather than + # silently replacing the descriptor in the instance or type dict. - with self.assertRaises(TypeError): - desc.__get__(0, 0) + ob = FieldTest() - with self.assertRaises(TypeError): - desc.__set__(0, 0) + assert FieldTest.PublicStaticField == 0 + assert ob.PublicStaticField == 0 - def test_boolean_field(self): - """Test boolean fields.""" - # change this to true / false later for Python 2.3? - ob = FieldTest() - self.assertTrue(ob.BooleanField is False) + descriptor = FieldTest.__dict__['PublicStaticField'] + assert type(descriptor) != int - ob.BooleanField = True - self.assertTrue(ob.BooleanField is True) + ob.PublicStaticField = 0 + descriptor = FieldTest.__dict__['PublicStaticField'] + assert type(descriptor) != int - ob.BooleanField = False - self.assertTrue(ob.BooleanField is False) + FieldTest.PublicStaticField = 0 + descriptor = FieldTest.__dict__['PublicStaticField'] + assert type(descriptor) != int - ob.BooleanField = 1 - self.assertTrue(ob.BooleanField is True) - ob.BooleanField = 0 - self.assertTrue(ob.BooleanField is False) +def test_field_descriptor_wrong_type(): + """Test setting a field using a value of the wrong type.""" - def test_sbyte_field(self): - """Test sbyte fields.""" - ob = FieldTest() - self.assertTrue(ob.SByteField == 0) + with pytest.raises(TypeError): + FieldTest().PublicField = "spam" - ob.SByteField = 1 - self.assertTrue(ob.SByteField == 1) - def test_byte_field(self): - """Test byte fields.""" - ob = FieldTest() - self.assertTrue(ob.ByteField == 0) +def test_field_descriptor_abuse(): + """Test field descriptor abuse.""" + desc = FieldTest.__dict__['PublicField'] - ob.ByteField = 1 - self.assertTrue(ob.ByteField == 1) + with pytest.raises(TypeError): + desc.__get__(0, 0) - def test_char_field(self): - """Test char fields.""" - ob = FieldTest() - self.assertTrue(ob.CharField == u'A') - self.assertTrue(ob.CharField == 'A') + with pytest.raises(TypeError): + desc.__set__(0, 0) - ob.CharField = 'B' - self.assertTrue(ob.CharField == u'B') - self.assertTrue(ob.CharField == 'B') - ob.CharField = u'C' - self.assertTrue(ob.CharField == u'C') - self.assertTrue(ob.CharField == 'C') +def test_boolean_field(): + """Test boolean fields.""" + # change this to true / false later for Python 2.3? + ob = FieldTest() + assert ob.BooleanField is False - def test_int16_field(self): - """Test int16 fields.""" - ob = FieldTest() - self.assertTrue(ob.Int16Field == 0) + ob.BooleanField = True + assert ob.BooleanField is True - ob.Int16Field = 1 - self.assertTrue(ob.Int16Field == 1) + ob.BooleanField = False + assert ob.BooleanField is False - def test_int32_field(self): - """Test int32 fields.""" - ob = FieldTest() - self.assertTrue(ob.Int32Field == 0) + ob.BooleanField = 1 + assert ob.BooleanField is True - ob.Int32Field = 1 - self.assertTrue(ob.Int32Field == 1) + ob.BooleanField = 0 + assert ob.BooleanField is False - def test_int64_field(self): - """Test int64 fields.""" - ob = FieldTest() - self.assertTrue(ob.Int64Field == 0) - ob.Int64Field = 1 - self.assertTrue(ob.Int64Field == 1) +def test_sbyte_field(): + """Test sbyte fields.""" + ob = FieldTest() + assert ob.SByteField == 0 - def test_uint16_field(self): - """Test uint16 fields.""" - ob = FieldTest() - self.assertTrue(ob.UInt16Field == 0) + ob.SByteField = 1 + assert ob.SByteField == 1 - ob.UInt16Field = 1 - self.assertTrue(ob.UInt16Field == 1) - def test_uint32_field(self): - """Test uint32 fields.""" - ob = FieldTest() - self.assertTrue(ob.UInt32Field == 0) +def test_byte_field(): + """Test byte fields.""" + ob = FieldTest() + assert ob.ByteField == 0 - ob.UInt32Field = 1 - self.assertTrue(ob.UInt32Field == 1) + ob.ByteField = 1 + assert ob.ByteField == 1 - def test_uint64_field(self): - """Test uint64 fields.""" - ob = FieldTest() - self.assertTrue(ob.UInt64Field == 0) - ob.UInt64Field = 1 - self.assertTrue(ob.UInt64Field == 1) +def test_char_field(): + """Test char fields.""" + ob = FieldTest() + assert ob.CharField == u'A' + assert ob.CharField == 'A' - def test_single_field(self): - """Test single fields.""" - ob = FieldTest() - self.assertTrue(ob.SingleField == 0.0) + ob.CharField = 'B' + assert ob.CharField == u'B' + assert ob.CharField == 'B' - ob.SingleField = 1.1 - self.assertTrue(ob.SingleField == 1.1) + ob.CharField = u'C' + assert ob.CharField == u'C' + assert ob.CharField == 'C' - def test_double_field(self): - """Test double fields.""" - ob = FieldTest() - self.assertTrue(ob.DoubleField == 0.0) - ob.DoubleField = 1.1 - self.assertTrue(ob.DoubleField == 1.1) +def test_int16_field(): + """Test int16 fields.""" + ob = FieldTest() + assert ob.Int16Field == 0 - def test_decimal_field(self): - """Test decimal fields.""" - ob = FieldTest() - self.assertTrue(ob.DecimalField == System.Decimal(0)) + ob.Int16Field = 1 + assert ob.Int16Field == 1 - ob.DecimalField = System.Decimal(1) - self.assertTrue(ob.DecimalField == System.Decimal(1)) - def test_string_field(self): - """Test string fields.""" - ob = FieldTest() - self.assertTrue(ob.StringField == "spam") +def test_int32_field(): + """Test int32 fields.""" + ob = FieldTest() + assert ob.Int32Field == 0 - ob.StringField = "eggs" - self.assertTrue(ob.StringField == "eggs") + ob.Int32Field = 1 + assert ob.Int32Field == 1 - def test_interface_field(self): - """Test interface fields.""" - from Python.Test import Spam, ISpam - ob = FieldTest() +def test_int64_field(): + """Test int64 fields.""" + ob = FieldTest() + assert ob.Int64Field == 0 - self.assertTrue(ISpam(ob.SpamField).GetValue() == "spam") - self.assertTrue(ob.SpamField.GetValue() == "spam") + ob.Int64Field = 1 + assert ob.Int64Field == 1 - ob.SpamField = Spam("eggs") - self.assertTrue(ISpam(ob.SpamField).GetValue() == "eggs") - self.assertTrue(ob.SpamField.GetValue() == "eggs") - def test_object_field(self): - """Test ob fields.""" - ob = FieldTest() - self.assertTrue(ob.ObjectField is None) +def test_uint16_field(): + """Test uint16 fields.""" + ob = FieldTest() + assert ob.UInt16Field == 0 - ob.ObjectField = System.String("spam") - self.assertTrue(ob.ObjectField == "spam") + ob.UInt16Field = 1 + assert ob.UInt16Field == 1 - ob.ObjectField = System.Int32(1) - self.assertTrue(ob.ObjectField == 1) - ob.ObjectField = None - self.assertTrue(ob.ObjectField is None) +def test_uint32_field(): + """Test uint32 fields.""" + ob = FieldTest() + assert ob.UInt32Field == 0 - def test_enum_field(self): - """Test enum fields.""" - from Python.Test import ShortEnum + ob.UInt32Field = 1 + assert ob.UInt32Field == 1 - ob = FieldTest() - self.assertTrue(ob.EnumField == ShortEnum.Zero) - ob.EnumField = ShortEnum.One - self.assertTrue(ob.EnumField == ShortEnum.One) +def test_uint64_field(): + """Test uint64 fields.""" + ob = FieldTest() + assert ob.UInt64Field == 0 - def test_nullable_field(self): - """Test nullable fields.""" - ob = FieldTest() + ob.UInt64Field = 1 + assert ob.UInt64Field == 1 - ob.StringField = None - self.assertTrue(ob.StringField is None) - ob.ObjectField = None - self.assertTrue(ob.ObjectField is None) +def test_single_field(): + """Test single fields.""" + ob = FieldTest() + assert ob.SingleField == 0.0 - ob.SpamField = None - self.assertTrue(ob.SpamField is None) + ob.SingleField = 1.1 + assert ob.SingleField == 1.1 - # Primitive types and enums should not be set to null. - with self.assertRaises(TypeError): - FieldTest().Int32Field = None +def test_double_field(): + """Test double fields.""" + ob = FieldTest() + assert ob.DoubleField == 0.0 - with self.assertRaises(TypeError): - FieldTest().EnumField = None + ob.DoubleField = 1.1 + assert ob.DoubleField == 1.1 -def test_suite(): - return unittest.makeSuite(FieldTests) +def test_decimal_field(): + """Test decimal fields.""" + ob = FieldTest() + assert ob.DecimalField == System.Decimal(0) + + ob.DecimalField = System.Decimal(1) + assert ob.DecimalField == System.Decimal(1) + + +def test_string_field(): + """Test string fields.""" + ob = FieldTest() + assert ob.StringField == "spam" + + ob.StringField = "eggs" + assert ob.StringField == "eggs" + + +def test_interface_field(): + """Test interface fields.""" + from Python.Test import Spam, ISpam + + ob = FieldTest() + + assert ISpam(ob.SpamField).GetValue() == "spam" + assert ob.SpamField.GetValue() == "spam" + + ob.SpamField = Spam("eggs") + assert ISpam(ob.SpamField).GetValue() == "eggs" + assert ob.SpamField.GetValue() == "eggs" + + +def test_object_field(): + """Test ob fields.""" + ob = FieldTest() + assert ob.ObjectField is None + + ob.ObjectField = System.String("spam") + assert ob.ObjectField == "spam" + + ob.ObjectField = System.Int32(1) + assert ob.ObjectField == 1 + + ob.ObjectField = None + assert ob.ObjectField is None + + +def test_enum_field(): + """Test enum fields.""" + from Python.Test import ShortEnum + + ob = FieldTest() + assert ob.EnumField == ShortEnum.Zero + + ob.EnumField = ShortEnum.One + assert ob.EnumField == ShortEnum.One + + +def test_nullable_field(): + """Test nullable fields.""" + ob = FieldTest() + + ob.StringField = None + assert ob.StringField is None + + ob.ObjectField = None + assert ob.ObjectField is None + + ob.SpamField = None + assert ob.SpamField is None + + # Primitive types and enums should not be set to null. + + with pytest.raises(TypeError): + FieldTest().Int32Field = None + + with pytest.raises(TypeError): + FieldTest().EnumField = None diff --git a/src/tests/test_generic.py b/src/tests/test_generic.py index 8d5ea4c4c..69cd4ee7f 100644 --- a/src/tests/test_generic.py +++ b/src/tests/test_generic.py @@ -1,767 +1,778 @@ # -*- coding: utf-8 -*- +"""Test CLR generics support.""" + import clr -import unittest import System +import pytest + +from ._compat import PY2, long, unicode, unichr, zip + + +def assert_generic_wrapper_by_type(ptype, value): + """Test Helper""" + from Python.Test import GenericWrapper + import System + + inst = GenericWrapper[ptype](value) + assert inst.value == value + + atype = System.Array[ptype] + items = atype([value, value, value]) + inst = GenericWrapper[atype](items) + assert len(inst.value) == 3 + assert inst.value[0] == value + assert inst.value[1] == value + + +def assert_generic_method_by_type(ptype, value, test_type=0): + """Test Helper""" + from Python.Test import GenericMethodTest, GenericStaticMethodTest + import System + + itype = GenericMethodTest[System.Type] + stype = GenericStaticMethodTest[System.Type] + + # Explicit selection (static method) + result = stype.Overloaded[ptype](value) + if test_type: + assert result.__class__ == value.__class__ + else: + assert result == value + + # Type inference (static method) + result = stype.Overloaded(value) + assert result == value + if test_type: + assert result.__class__ == value.__class__ + else: + assert result == value + + # Explicit selection (instance method) + result = itype().Overloaded[ptype](value) + assert result == value + if test_type: + assert result.__class__ == value.__class__ + else: + assert result == value + + # Type inference (instance method) + result = itype().Overloaded(value) + assert result == value + if test_type: + assert result.__class__ == value.__class__ + else: + assert result == value + + atype = System.Array[ptype] + items = atype([value, value, value]) + + # Explicit selection (static method) + result = stype.Overloaded[atype](items) + if test_type: + assert len(result) == 3 + assert result[0].__class__ == value.__class__ + assert result[1].__class__ == value.__class__ + else: + assert len(result) == 3 + assert result[0] == value + assert result[1] == value + + # Type inference (static method) + result = stype.Overloaded(items) + if test_type: + assert len(result) == 3 + assert result[0].__class__ == value.__class__ + assert result[1].__class__ == value.__class__ + else: + assert len(result) == 3 + assert result[0] == value + assert result[1] == value + + # Explicit selection (instance method) + result = itype().Overloaded[atype](items) + if test_type: + assert len(result) == 3 + assert result[0].__class__ == value.__class__ + assert result[1].__class__ == value.__class__ + else: + assert len(result) == 3 + assert result[0] == value + assert result[1] == value + + # Type inference (instance method) + result = itype().Overloaded(items) + if test_type: + assert len(result) == 3 + assert result[0].__class__ == value.__class__ + assert result[1].__class__ == value.__class__ + else: + assert len(result) == 3 + assert result[0] == value + assert result[1] == value + + +def test_python_type_aliasing(): + """Test python type alias support with generics.""" + from System.Collections.Generic import Dictionary + + dict_ = Dictionary[str, str]() + assert dict_.Count == 0 + dict_.Add("one", "one") + assert dict_["one"] == "one" + + dict_ = Dictionary[System.String, System.String]() + assert dict_.Count == 0 + dict_.Add("one", "one") + assert dict_["one"] == "one" + + dict_ = Dictionary[int, int]() + assert dict_.Count == 0 + dict_.Add(1, 1) + assert dict_[1] == 1 + + dict_ = Dictionary[System.Int32, System.Int32]() + assert dict_.Count == 0 + dict_.Add(1, 1) + assert dict_[1] == 1 + + dict_ = Dictionary[long, long]() + assert dict_.Count == 0 + dict_.Add(long(1), long(1)) + assert dict_[long(1)] == long(1) + + dict_ = Dictionary[System.Int64, System.Int64]() + assert dict_.Count == 0 + dict_.Add(long(1), long(1)) + assert dict_[long(1)] == long(1) + + dict_ = Dictionary[float, float]() + assert dict_.Count == 0 + dict_.Add(1.5, 1.5) + assert dict_[1.5] == 1.5 + + dict_ = Dictionary[System.Double, System.Double]() + assert dict_.Count == 0 + dict_.Add(1.5, 1.5) + assert dict_[1.5] == 1.5 + + dict_ = Dictionary[bool, bool]() + assert dict_.Count == 0 + dict_.Add(True, False) + assert dict_[True] is False + + dict_ = Dictionary[System.Boolean, System.Boolean]() + assert dict_.Count == 0 + dict_.Add(True, False) + assert dict_[True] is False + + +def test_generic_reference_type(): + """Test usage of generic reference type definitions.""" + from Python.Test import GenericTypeDefinition + + inst = GenericTypeDefinition[System.String, System.Int32]("one", 2) + assert inst.value1 == "one" + assert inst.value2 == 2 + + +def test_generic_value_type(): + """Test usage of generic value type definitions.""" + inst = System.Nullable[System.Int32](10) + assert inst.HasValue + assert inst.Value == 10 + + +def test_generic_interface(): + # TODO NotImplemented + pass + + +def test_generic_delegate(): + # TODO NotImplemented + pass + + +def test_open_generic_type(): + """Test behavior of reflected open constructed generic types.""" + from Python.Test import DerivedFromOpenGeneric + + open_generic_type = DerivedFromOpenGeneric.__bases__[0] + + with pytest.raises(TypeError): + _ = open_generic_type() + + with pytest.raises(TypeError): + _ = open_generic_type[System.String] + + +def test_derived_from_open_generic_type(): + """Test a generic type derived from an open generic type.""" + from Python.Test import DerivedFromOpenGeneric + + type_ = DerivedFromOpenGeneric[System.String, System.String] + inst = type_(1, 'two', 'three') + + assert inst.value1 == 1 + assert inst.value2 == 'two' + assert inst.value3 == 'three' + + +def test_generic_type_name_resolution(): + """Test the ability to disambiguate generic type names.""" + from Python.Test import GenericNameTest1, GenericNameTest2 + + # If both a non-generic and generic type exist for a name, the + # unadorned name always resolves to the non-generic type. + _class = GenericNameTest1 + assert _class().value == 0 + assert _class.value == 0 + + # If no non-generic type exists for a name, the unadorned name + # cannot be instantiated. It can only be used to bind a generic. + + with pytest.raises(TypeError): + _ = GenericNameTest2() + + _class = GenericNameTest2[int] + assert _class().value == 1 + assert _class.value == 1 + + _class = GenericNameTest2[int, int] + assert _class().value == 2 + assert _class.value == 2 + + +def test_generic_type_binding(): + """Test argument conversion / binding for generic methods.""" + from Python.Test import InterfaceTest, ISayHello1, ShortEnum + import System + + assert_generic_wrapper_by_type(System.Boolean, True) + assert_generic_wrapper_by_type(bool, True) + assert_generic_wrapper_by_type(System.Byte, 255) + assert_generic_wrapper_by_type(System.SByte, 127) + assert_generic_wrapper_by_type(System.Char, u'A') + assert_generic_wrapper_by_type(System.Int16, 32767) + assert_generic_wrapper_by_type(System.Int32, 2147483647) + assert_generic_wrapper_by_type(int, 2147483647) + assert_generic_wrapper_by_type(System.Int64, long(9223372036854775807)) + # Python 3 has no explicit long type, use System.Int64 instead + if PY2: + assert_generic_wrapper_by_type(long, long(9223372036854775807)) + assert_generic_wrapper_by_type(System.UInt16, 65000) + assert_generic_wrapper_by_type(System.UInt32, long(4294967295)) + assert_generic_wrapper_by_type(System.UInt64, long(18446744073709551615)) + assert_generic_wrapper_by_type(System.Single, 3.402823e38) + assert_generic_wrapper_by_type(System.Double, 1.7976931348623157e308) + assert_generic_wrapper_by_type(float, 1.7976931348623157e308) + assert_generic_wrapper_by_type(System.Decimal, System.Decimal.One) + assert_generic_wrapper_by_type(System.String, "test") + assert_generic_wrapper_by_type(unicode, "test") + assert_generic_wrapper_by_type(str, "test") + assert_generic_wrapper_by_type(ShortEnum, ShortEnum.Zero) + assert_generic_wrapper_by_type(System.Object, InterfaceTest()) + assert_generic_wrapper_by_type(InterfaceTest, InterfaceTest()) + assert_generic_wrapper_by_type(ISayHello1, InterfaceTest()) + + +def test_generic_method_binding(): + from Python.Test import GenericMethodTest, GenericStaticMethodTest + from System import InvalidOperationException + + # Can invoke a static member on a closed generic type. + value = GenericStaticMethodTest[str].Overloaded() + assert value == 1 + + with pytest.raises(InvalidOperationException): + # Cannot invoke a static member on an open type. + GenericStaticMethodTest.Overloaded() + + # Can invoke an instance member on a closed generic type. + value = GenericMethodTest[str]().Overloaded() + assert value == 1 + + with pytest.raises(TypeError): + # Cannot invoke an instance member on an open type, + # because the open type cannot be instantiated. + GenericMethodTest().Overloaded() + + +def test_generic_method_type_handling(): + """Test argument conversion / binding for generic methods.""" + from Python.Test import InterfaceTest, ISayHello1, ShortEnum + import System + + # FIXME: The value doesn't fit into Int64 and PythonNet doesn't + # recognize it as UInt64 for unknown reasons. + # assert_generic_method_by_type(System.UInt64, 18446744073709551615L) + assert_generic_method_by_type(System.Boolean, True) + assert_generic_method_by_type(bool, True) + assert_generic_method_by_type(System.Byte, 255) + assert_generic_method_by_type(System.SByte, 127) + assert_generic_method_by_type(System.Char, u'A') + assert_generic_method_by_type(System.Int16, 32767) + assert_generic_method_by_type(System.Int32, 2147483647) + assert_generic_method_by_type(int, 2147483647) + # Python 3 has no explicit long type, use System.Int64 instead + if PY2: + assert_generic_method_by_type(System.Int64, long(9223372036854775807)) + assert_generic_method_by_type(long, long(9223372036854775807)) + assert_generic_method_by_type(System.UInt32, long(4294967295)) + assert_generic_method_by_type(System.Int64, long(1844674407370955161)) + assert_generic_method_by_type(System.UInt16, 65000) + assert_generic_method_by_type(System.Single, 3.402823e38) + assert_generic_method_by_type(System.Double, 1.7976931348623157e308) + assert_generic_method_by_type(float, 1.7976931348623157e308) + assert_generic_method_by_type(System.Decimal, System.Decimal.One) + assert_generic_method_by_type(System.String, "test") + assert_generic_method_by_type(unicode, "test") + assert_generic_method_by_type(str, "test") + assert_generic_method_by_type(ShortEnum, ShortEnum.Zero) + assert_generic_method_by_type(System.Object, InterfaceTest()) + assert_generic_method_by_type(InterfaceTest, InterfaceTest(), 1) + assert_generic_method_by_type(ISayHello1, InterfaceTest(), 1) + + +def test_correct_overload_selection(): + """Test correct overloading selection for common types.""" + from System import (String, Double, Single, + Int16, Int32, Int64) + from System import Math + + substr = String("substring") + assert substr.Substring(2) == substr.Substring.__overloads__[Int32]( + Int32(2)) + assert substr.Substring(2, 3) == substr.Substring.__overloads__[Int32, Int32]( + Int32(2), Int32(3)) + + for atype, value1, value2 in zip([Double, Single, Int16, Int32, Int64], + [1.0, 1.0, 1, 1, 1], + [2.0, 0.5, 2, 0, -1]): + assert Math.Abs(atype(value1)) == Math.Abs.__overloads__[atype](atype(value1)) + assert Math.Abs(value1) == Math.Abs.__overloads__[atype](atype(value1)) + assert Math.Max(atype(value1), + atype(value2)) == Math.Max.__overloads__[atype, atype]( + atype(value1), atype(value2)) + if PY2 and atype is Int64: + value2 = long(value2) + assert Math.Max(atype(value1), + value2) == Math.Max.__overloads__[atype, atype]( + atype(value1), atype(value2)) + + clr.AddReference("System.Runtime.InteropServices") + from System.Runtime.InteropServices import GCHandle, GCHandleType + from System import Array, Byte + cs_array = Array.CreateInstance(Byte, 1000) + handler = GCHandle.Alloc(cs_array, GCHandleType.Pinned) + + +def test_generic_method_overload_selection(): + """Test explicit overload selection with generic methods.""" + from Python.Test import GenericMethodTest, GenericStaticMethodTest + + type = GenericStaticMethodTest[str] + inst = GenericMethodTest[str]() + + # public static int Overloaded() + value = type.Overloaded() + assert value == 1 + + # public int Overloaded() + value = inst.Overloaded() + assert value == 1 + + # public static T Overloaded(T arg) (inferred) + value = type.Overloaded("test") + assert value == "test" + + # public T Overloaded(T arg) (inferred) + value = inst.Overloaded("test") + assert value == "test" + + # public static T Overloaded(T arg) (explicit) + value = type.Overloaded[str]("test") + assert value == "test" + + # public T Overloaded(T arg) (explicit) + value = inst.Overloaded[str]("test") + assert value == "test" + + # public static Q Overloaded(Q arg) + value = type.Overloaded[float](2.2) + assert value == 2.2 + + # public Q Overloaded(Q arg) + value = inst.Overloaded[float](2.2) + assert value == 2.2 + + # public static Q Overloaded(Q arg) + value = type.Overloaded[bool](True) + assert value is True + + # public Q Overloaded(Q arg) + value = inst.Overloaded[bool](True) + assert value is True + + # public static U Overloaded(Q arg1, U arg2) + value = type.Overloaded[bool, str](True, "true") + assert value == "true" + + # public U Overloaded(Q arg1, U arg2) + value = inst.Overloaded[bool, str](True, "true") + assert value == "true" + + # public static U Overloaded(Q arg1, U arg2) + value = type.Overloaded[str, bool]("true", True) + assert value is True + + # public U Overloaded(Q arg1, U arg2) + value = inst.Overloaded[str, bool]("true", True) + assert value is True + + # public static string Overloaded(int arg1, int arg2, string arg3) + value = type.Overloaded[str](123, 456, "success") + assert value == "success" + + # public string Overloaded(int arg1, int arg2, string arg3) + value = inst.Overloaded[str](123, 456, "success") + assert value == "success" + + with pytest.raises(TypeError): + _ = type.Overloaded[str, bool, int]("true", True, 1) + + with pytest.raises(TypeError): + _ = inst.Overloaded[str, bool, int]("true", True, 1) + + +def test_method_overload_selection_with_generic_types(): + """Check method overload selection using generic types.""" + from Python.Test import ISayHello1, InterfaceTest, ShortEnum + from Python.Test import MethodTest, GenericWrapper + + inst = InterfaceTest() + + vtype = GenericWrapper[System.Boolean] + input_ = vtype(True) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value.value is True + + vtype = GenericWrapper[bool] + input_ = vtype(True) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value.value is True + + vtype = GenericWrapper[System.Byte] + input_ = vtype(255) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value.value == 255 -from _compat import PY2, long, unicode, unichr, zip - - -class GenericTests(unittest.TestCase): - """Test CLR generics support.""" - - def _assert_generic_wrapper_by_type(self, ptype, value): - """Test Helper""" - from Python.Test import GenericWrapper - import System - - inst = GenericWrapper[ptype](value) - self.assertTrue(inst.value == value) - - atype = System.Array[ptype] - items = atype([value, value, value]) - inst = GenericWrapper[atype](items) - self.assertTrue(len(inst.value) == 3) - self.assertTrue(inst.value[0] == value) - self.assertTrue(inst.value[1] == value) - - def _assert_generic_method_by_type(self, ptype, value, test_type=0): - """Test Helper""" - from Python.Test import GenericMethodTest, GenericStaticMethodTest - import System - - itype = GenericMethodTest[System.Type] - stype = GenericStaticMethodTest[System.Type] - - # Explicit selection (static method) - result = stype.Overloaded[ptype](value) - if test_type: - self.assertTrue(result.__class__ == value.__class__) - else: - self.assertTrue(result == value) - - # Type inference (static method) - result = stype.Overloaded(value) - self.assertTrue(result == value) - if test_type: - self.assertTrue(result.__class__ == value.__class__) - else: - self.assertTrue(result == value) - - # Explicit selection (instance method) - result = itype().Overloaded[ptype](value) - self.assertTrue(result == value) - if test_type: - self.assertTrue(result.__class__ == value.__class__) - else: - self.assertTrue(result == value) - - # Type inference (instance method) - result = itype().Overloaded(value) - self.assertTrue(result == value) - if test_type: - self.assertTrue(result.__class__ == value.__class__) - else: - self.assertTrue(result == value) - - atype = System.Array[ptype] - items = atype([value, value, value]) - - # Explicit selection (static method) - result = stype.Overloaded[atype](items) - if test_type: - self.assertTrue(len(result) == 3) - self.assertTrue(result[0].__class__ == value.__class__) - self.assertTrue(result[1].__class__ == value.__class__) - else: - self.assertTrue(len(result) == 3) - self.assertTrue(result[0] == value) - self.assertTrue(result[1] == value) - - # Type inference (static method) - result = stype.Overloaded(items) - if test_type: - self.assertTrue(len(result) == 3) - self.assertTrue(result[0].__class__ == value.__class__) - self.assertTrue(result[1].__class__ == value.__class__) - else: - self.assertTrue(len(result) == 3) - self.assertTrue(result[0] == value) - self.assertTrue(result[1] == value) - - # Explicit selection (instance method) - result = itype().Overloaded[atype](items) - if test_type: - self.assertTrue(len(result) == 3) - self.assertTrue(result[0].__class__ == value.__class__) - self.assertTrue(result[1].__class__ == value.__class__) - else: - self.assertTrue(len(result) == 3) - self.assertTrue(result[0] == value) - self.assertTrue(result[1] == value) - - # Type inference (instance method) - result = itype().Overloaded(items) - if test_type: - self.assertTrue(len(result) == 3) - self.assertTrue(result[0].__class__ == value.__class__) - self.assertTrue(result[1].__class__ == value.__class__) - else: - self.assertTrue(len(result) == 3) - self.assertTrue(result[0] == value) - self.assertTrue(result[1] == value) - - def test_python_type_aliasing(self): - """Test python type alias support with generics.""" - from System.Collections.Generic import Dictionary - - dict_ = Dictionary[str, str]() - self.assertEquals(dict_.Count, 0) - dict_.Add("one", "one") - self.assertTrue(dict_["one"] == "one") - - dict_ = Dictionary[System.String, System.String]() - self.assertEquals(dict_.Count, 0) - dict_.Add("one", "one") - self.assertTrue(dict_["one"] == "one") - - dict_ = Dictionary[int, int]() - self.assertEquals(dict_.Count, 0) - dict_.Add(1, 1) - self.assertTrue(dict_[1] == 1) - - dict_ = Dictionary[System.Int32, System.Int32]() - self.assertEquals(dict_.Count, 0) - dict_.Add(1, 1) - self.assertTrue(dict_[1] == 1) - - dict_ = Dictionary[long, long]() - self.assertEquals(dict_.Count, 0) - dict_.Add(long(1), long(1)) - self.assertTrue(dict_[long(1)] == long(1)) - - dict_ = Dictionary[System.Int64, System.Int64]() - self.assertEquals(dict_.Count, 0) - dict_.Add(long(1), long(1)) - self.assertTrue(dict_[long(1)] == long(1)) - - dict_ = Dictionary[float, float]() - self.assertEquals(dict_.Count, 0) - dict_.Add(1.5, 1.5) - self.assertTrue(dict_[1.5] == 1.5) - - dict_ = Dictionary[System.Double, System.Double]() - self.assertEquals(dict_.Count, 0) - dict_.Add(1.5, 1.5) - self.assertTrue(dict_[1.5] == 1.5) - - dict_ = Dictionary[bool, bool]() - self.assertEquals(dict_.Count, 0) - dict_.Add(True, False) - self.assertTrue(dict_[True] is False) - - dict_ = Dictionary[System.Boolean, System.Boolean]() - self.assertEquals(dict_.Count, 0) - dict_.Add(True, False) - self.assertTrue(dict_[True] is False) - - def test_generic_reference_type(self): - """Test usage of generic reference type definitions.""" - from Python.Test import GenericTypeDefinition - - inst = GenericTypeDefinition[System.String, System.Int32]("one", 2) - self.assertTrue(inst.value1 == "one") - self.assertTrue(inst.value2 == 2) - - def test_generic_value_type(self): - """Test usage of generic value type definitions.""" - inst = System.Nullable[System.Int32](10) - self.assertTrue(inst.HasValue) - self.assertTrue(inst.Value == 10) - - def test_generic_interface(self): - # TODO NotImplemented - pass - - def test_generic_delegate(self): - # TODO NotImplemented - pass - - def test_open_generic_type(self): - """Test behavior of reflected open constructed generic types.""" - from Python.Test import DerivedFromOpenGeneric - - open_generic_type = DerivedFromOpenGeneric.__bases__[0] - - with self.assertRaises(TypeError): - _ = open_generic_type() - - with self.assertRaises(TypeError): - _ = open_generic_type[System.String] - - def test_derived_from_open_generic_type(self): - """Test a generic type derived from an open generic type.""" - from Python.Test import DerivedFromOpenGeneric - - type_ = DerivedFromOpenGeneric[System.String, System.String] - inst = type_(1, 'two', 'three') - - self.assertTrue(inst.value1 == 1) - self.assertTrue(inst.value2 == 'two') - self.assertTrue(inst.value3 == 'three') - - def test_generic_type_name_resolution(self): - """Test the ability to disambiguate generic type names.""" - from Python.Test import GenericNameTest1, GenericNameTest2 - - # If both a non-generic and generic type exist for a name, the - # unadorned name always resolves to the non-generic type. - _class = GenericNameTest1 - self.assertTrue(_class().value == 0) - self.assertTrue(_class.value == 0) - - # If no non-generic type exists for a name, the unadorned name - # cannot be instantiated. It can only be used to bind a generic. - - with self.assertRaises(TypeError): - _ = GenericNameTest2() - - _class = GenericNameTest2[int] - self.assertTrue(_class().value == 1) - self.assertTrue(_class.value == 1) - - _class = GenericNameTest2[int, int] - self.assertTrue(_class().value == 2) - self.assertTrue(_class.value == 2) - - def test_generic_type_binding(self): - """Test argument conversion / binding for generic methods.""" - from Python.Test import InterfaceTest, ISayHello1, ShortEnum - import System - - self._assert_generic_wrapper_by_type(System.Boolean, True) - self._assert_generic_wrapper_by_type(bool, True) - self._assert_generic_wrapper_by_type(System.Byte, 255) - self._assert_generic_wrapper_by_type(System.SByte, 127) - self._assert_generic_wrapper_by_type(System.Char, u'A') - self._assert_generic_wrapper_by_type(System.Int16, 32767) - self._assert_generic_wrapper_by_type(System.Int32, 2147483647) - self._assert_generic_wrapper_by_type(int, 2147483647) - self._assert_generic_wrapper_by_type(System.Int64, long(9223372036854775807)) - # Python 3 has no explicit long type, use System.Int64 instead - if PY2: - self._assert_generic_wrapper_by_type(long, long(9223372036854775807)) - self._assert_generic_wrapper_by_type(System.UInt16, 65000) - self._assert_generic_wrapper_by_type(System.UInt32, long(4294967295)) - self._assert_generic_wrapper_by_type(System.UInt64, long(18446744073709551615)) - self._assert_generic_wrapper_by_type(System.Single, 3.402823e38) - self._assert_generic_wrapper_by_type(System.Double, 1.7976931348623157e308) - self._assert_generic_wrapper_by_type(float, 1.7976931348623157e308) - self._assert_generic_wrapper_by_type(System.Decimal, System.Decimal.One) - self._assert_generic_wrapper_by_type(System.String, "test") - self._assert_generic_wrapper_by_type(unicode, "test") - self._assert_generic_wrapper_by_type(str, "test") - self._assert_generic_wrapper_by_type(ShortEnum, ShortEnum.Zero) - self._assert_generic_wrapper_by_type(System.Object, InterfaceTest()) - self._assert_generic_wrapper_by_type(InterfaceTest, InterfaceTest()) - self._assert_generic_wrapper_by_type(ISayHello1, InterfaceTest()) - - def test_generic_method_binding(self): - from Python.Test import GenericMethodTest, GenericStaticMethodTest - from System import InvalidOperationException - - # Can invoke a static member on a closed generic type. - value = GenericStaticMethodTest[str].Overloaded() - self.assertTrue(value == 1) - - with self.assertRaises(InvalidOperationException): - # Cannot invoke a static member on an open type. - GenericStaticMethodTest.Overloaded() - - # Can invoke an instance member on a closed generic type. - value = GenericMethodTest[str]().Overloaded() - self.assertTrue(value == 1) - - with self.assertRaises(TypeError): - # Cannot invoke an instance member on an open type, - # because the open type cannot be instantiated. - GenericMethodTest().Overloaded() - - def test_generic_method_type_handling(self): - """Test argument conversion / binding for generic methods.""" - from Python.Test import InterfaceTest, ISayHello1, ShortEnum - import System - - # FIXME: The value doesn't fit into Int64 and PythonNet doesn't - # recognize it as UInt64 for unknown reasons. - # self._assert_generic_method_by_type(System.UInt64, 18446744073709551615L) - self._assert_generic_method_by_type(System.Boolean, True) - self._assert_generic_method_by_type(bool, True) - self._assert_generic_method_by_type(System.Byte, 255) - self._assert_generic_method_by_type(System.SByte, 127) - self._assert_generic_method_by_type(System.Char, u'A') - self._assert_generic_method_by_type(System.Int16, 32767) - self._assert_generic_method_by_type(System.Int32, 2147483647) - self._assert_generic_method_by_type(int, 2147483647) - # Python 3 has no explicit long type, use System.Int64 instead - if PY2: - self._assert_generic_method_by_type(System.Int64, long(9223372036854775807)) - self._assert_generic_method_by_type(long, long(9223372036854775807)) - self._assert_generic_method_by_type(System.UInt32, long(4294967295)) - self._assert_generic_method_by_type(System.Int64, long(1844674407370955161)) - self._assert_generic_method_by_type(System.UInt16, 65000) - self._assert_generic_method_by_type(System.Single, 3.402823e38) - self._assert_generic_method_by_type(System.Double, 1.7976931348623157e308) - self._assert_generic_method_by_type(float, 1.7976931348623157e308) - self._assert_generic_method_by_type(System.Decimal, System.Decimal.One) - self._assert_generic_method_by_type(System.String, "test") - self._assert_generic_method_by_type(unicode, "test") - self._assert_generic_method_by_type(str, "test") - self._assert_generic_method_by_type(ShortEnum, ShortEnum.Zero) - self._assert_generic_method_by_type(System.Object, InterfaceTest()) - self._assert_generic_method_by_type(InterfaceTest, InterfaceTest(), 1) - self._assert_generic_method_by_type(ISayHello1, InterfaceTest(), 1) - - def test_correct_overload_selection(self): - """Test correct overloading selection for common types.""" - from System import (String, Double, Single, - Int16, Int32, Int64) - from System import Math - - substr = String("substring") - self.assertTrue(substr.Substring(2) == substr.Substring.__overloads__[Int32]( - Int32(2))) - self.assertTrue(substr.Substring(2, 3) == substr.Substring.__overloads__[Int32, Int32]( - Int32(2), Int32(3))) - - for atype, value1, value2 in zip([Double, Single, Int16, Int32, Int64], - [1.0, 1.0, 1, 1, 1], - [2.0, 0.5, 2, 0, -1]): - self.assertTrue(Math.Abs(atype(value1)) == Math.Abs.__overloads__[atype](atype(value1))) - self.assertTrue(Math.Abs(value1) == Math.Abs.__overloads__[atype](atype(value1))) - self.assertTrue( - Math.Max(atype(value1), - atype(value2)) == Math.Max.__overloads__[atype, atype]( - atype(value1), atype(value2))) - if PY2 and atype is Int64: - value2 = long(value2) - self.assertTrue( - Math.Max(atype(value1), - value2) == Math.Max.__overloads__[atype, atype]( - atype(value1), atype(value2))) - - clr.AddReference("System.Runtime.InteropServices") - from System.Runtime.InteropServices import GCHandle, GCHandleType - from System import Array, Byte - cs_array = Array.CreateInstance(Byte, 1000) - handler = GCHandle.Alloc(cs_array, GCHandleType.Pinned) - - def test_generic_method_overload_selection(self): - """Test explicit overload selection with generic methods.""" - from Python.Test import GenericMethodTest, GenericStaticMethodTest - - type = GenericStaticMethodTest[str] - inst = GenericMethodTest[str]() - - # public static int Overloaded() - value = type.Overloaded() - self.assertTrue(value == 1) - - # public int Overloaded() - value = inst.Overloaded() - self.assertTrue(value == 1) - - # public static T Overloaded(T arg) (inferred) - value = type.Overloaded("test") - self.assertTrue(value == "test") - - # public T Overloaded(T arg) (inferred) - value = inst.Overloaded("test") - self.assertTrue(value == "test") - - # public static T Overloaded(T arg) (explicit) - value = type.Overloaded[str]("test") - self.assertTrue(value == "test") - - # public T Overloaded(T arg) (explicit) - value = inst.Overloaded[str]("test") - self.assertTrue(value == "test") - - # public static Q Overloaded(Q arg) - value = type.Overloaded[float](2.2) - self.assertTrue(value == 2.2) - - # public Q Overloaded(Q arg) - value = inst.Overloaded[float](2.2) - self.assertTrue(value == 2.2) - - # public static Q Overloaded(Q arg) - value = type.Overloaded[bool](True) - self.assertTrue(value is True) - - # public Q Overloaded(Q arg) - value = inst.Overloaded[bool](True) - self.assertTrue(value is True) - - # public static U Overloaded(Q arg1, U arg2) - value = type.Overloaded[bool, str](True, "true") - self.assertTrue(value == "true") - - # public U Overloaded(Q arg1, U arg2) - value = inst.Overloaded[bool, str](True, "true") - self.assertTrue(value == "true") - - # public static U Overloaded(Q arg1, U arg2) - value = type.Overloaded[str, bool]("true", True) - self.assertTrue(value is True) - - # public U Overloaded(Q arg1, U arg2) - value = inst.Overloaded[str, bool]("true", True) - self.assertTrue(value is True) - - # public static string Overloaded(int arg1, int arg2, string arg3) - value = type.Overloaded[str](123, 456, "success") - self.assertTrue(value == "success") - - # public string Overloaded(int arg1, int arg2, string arg3) - value = inst.Overloaded[str](123, 456, "success") - self.assertTrue(value == "success") - - with self.assertRaises(TypeError): - _ = type.Overloaded[str, bool, int]("true", True, 1) - - with self.assertRaises(TypeError): - _ = inst.Overloaded[str, bool, int]("true", True, 1) - - def test_method_overload_selection_with_generic_types(self): - """Check method overload selection using generic types.""" - from Python.Test import ISayHello1, InterfaceTest, ShortEnum - from Python.Test import MethodTest, GenericWrapper - - inst = InterfaceTest() - - vtype = GenericWrapper[System.Boolean] - input_ = vtype(True) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value.value is True) - - vtype = GenericWrapper[bool] - input_ = vtype(True) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value.value is True) - - vtype = GenericWrapper[System.Byte] - input_ = vtype(255) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value.value == 255) - - vtype = GenericWrapper[System.SByte] - input_ = vtype(127) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value.value == 127) - - vtype = GenericWrapper[System.Char] - input_ = vtype(u'A') - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value.value == u'A') - - vtype = GenericWrapper[System.Char] - input_ = vtype(65535) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value.value == unichr(65535)) - - vtype = GenericWrapper[System.Int16] - input_ = vtype(32767) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value.value == 32767) - - vtype = GenericWrapper[System.Int32] - input_ = vtype(2147483647) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value.value == 2147483647) - - vtype = GenericWrapper[int] - input_ = vtype(2147483647) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value.value == 2147483647) - - vtype = GenericWrapper[System.Int64] + vtype = GenericWrapper[System.SByte] + input_ = vtype(127) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value.value == 127 + + vtype = GenericWrapper[System.Char] + input_ = vtype(u'A') + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value.value == u'A' + + vtype = GenericWrapper[System.Char] + input_ = vtype(65535) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value.value == unichr(65535) + + vtype = GenericWrapper[System.Int16] + input_ = vtype(32767) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value.value == 32767 + + vtype = GenericWrapper[System.Int32] + input_ = vtype(2147483647) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value.value == 2147483647 + + vtype = GenericWrapper[int] + input_ = vtype(2147483647) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value.value == 2147483647 + + vtype = GenericWrapper[System.Int64] + input_ = vtype(long(9223372036854775807)) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value.value == long(9223372036854775807) + + # Python 3 has no explicit long type, use System.Int64 instead + if PY2: + vtype = GenericWrapper[long] input_ = vtype(long(9223372036854775807)) value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value.value == long(9223372036854775807)) - - # Python 3 has no explicit long type, use System.Int64 instead - if PY2: - vtype = GenericWrapper[long] - input_ = vtype(long(9223372036854775807)) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value.value == long(9223372036854775807)) - - vtype = GenericWrapper[System.UInt16] - input_ = vtype(65000) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value.value == 65000) - - vtype = GenericWrapper[System.UInt32] - input_ = vtype(long(4294967295)) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value.value == long(4294967295)) - - vtype = GenericWrapper[System.UInt64] - input_ = vtype(long(18446744073709551615)) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value.value == long(18446744073709551615)) - - vtype = GenericWrapper[System.Single] - input_ = vtype(3.402823e38) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value.value == 3.402823e38) - - vtype = GenericWrapper[System.Double] - input_ = vtype(1.7976931348623157e308) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value.value == 1.7976931348623157e308) - - vtype = GenericWrapper[float] - input_ = vtype(1.7976931348623157e308) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value.value == 1.7976931348623157e308) - - vtype = GenericWrapper[System.Decimal] - input_ = vtype(System.Decimal.One) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value.value == System.Decimal.One) - - vtype = GenericWrapper[System.String] - input_ = vtype("spam") - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value.value == "spam") - - vtype = GenericWrapper[str] - input_ = vtype("spam") - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value.value == "spam") - - vtype = GenericWrapper[ShortEnum] - input_ = vtype(ShortEnum.Zero) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value.value == ShortEnum.Zero) - - vtype = GenericWrapper[System.Object] - input_ = vtype(inst) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value.value.__class__ == inst.__class__) - - vtype = GenericWrapper[InterfaceTest] - input_ = vtype(inst) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value.value.__class__ == inst.__class__) - - vtype = GenericWrapper[ISayHello1] - input_ = vtype(inst) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value.value.__class__ == inst.__class__) - - vtype = System.Array[GenericWrapper[int]] - input_ = vtype([GenericWrapper[int](0), GenericWrapper[int](1)]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0].value == 0) - self.assertTrue(value[1].value == 1) - - def test_overload_selection_with_arrays_of_generic_types(self): - """Check overload selection using arrays of generic types.""" - from Python.Test import ISayHello1, InterfaceTest, ShortEnum - from Python.Test import MethodTest, GenericWrapper - - inst = InterfaceTest() - - gtype = GenericWrapper[System.Boolean] - vtype = System.Array[gtype] - input_ = vtype([gtype(True), gtype(True)]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0].value is True) - self.assertTrue(value.Length == 2) - - gtype = GenericWrapper[bool] - vtype = System.Array[gtype] - input_ = vtype([gtype(True), gtype(True)]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0].value is True) - self.assertTrue(value.Length == 2) - - gtype = GenericWrapper[System.Byte] - vtype = System.Array[gtype] - input_ = vtype([gtype(255), gtype(255)]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0].value == 255) - self.assertTrue(value.Length == 2) - - gtype = GenericWrapper[System.SByte] - vtype = System.Array[gtype] - input_ = vtype([gtype(127), gtype(127)]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0].value == 127) - self.assertTrue(value.Length == 2) - - gtype = GenericWrapper[System.Char] - vtype = System.Array[gtype] - input_ = vtype([gtype(u'A'), gtype(u'A')]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0].value == u'A') - self.assertTrue(value.Length == 2) - - gtype = GenericWrapper[System.Char] - vtype = System.Array[gtype] - input_ = vtype([gtype(65535), gtype(65535)]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0].value == unichr(65535)) - self.assertTrue(value.Length == 2) - - gtype = GenericWrapper[System.Int16] - vtype = System.Array[gtype] - input_ = vtype([gtype(32767), gtype(32767)]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0].value == 32767) - self.assertTrue(value.Length == 2) - - gtype = GenericWrapper[System.Int32] - vtype = System.Array[gtype] - input_ = vtype([gtype(2147483647), gtype(2147483647)]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0].value == 2147483647) - self.assertTrue(value.Length == 2) - - gtype = GenericWrapper[int] - vtype = System.Array[gtype] - input_ = vtype([gtype(2147483647), gtype(2147483647)]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0].value == 2147483647) - self.assertTrue(value.Length == 2) - - gtype = GenericWrapper[System.Int64] + assert value.value == long(9223372036854775807) + + vtype = GenericWrapper[System.UInt16] + input_ = vtype(65000) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value.value == 65000 + + vtype = GenericWrapper[System.UInt32] + input_ = vtype(long(4294967295)) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value.value == long(4294967295) + + vtype = GenericWrapper[System.UInt64] + input_ = vtype(long(18446744073709551615)) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value.value == long(18446744073709551615) + + vtype = GenericWrapper[System.Single] + input_ = vtype(3.402823e38) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value.value == 3.402823e38 + + vtype = GenericWrapper[System.Double] + input_ = vtype(1.7976931348623157e308) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value.value == 1.7976931348623157e308 + + vtype = GenericWrapper[float] + input_ = vtype(1.7976931348623157e308) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value.value == 1.7976931348623157e308 + + vtype = GenericWrapper[System.Decimal] + input_ = vtype(System.Decimal.One) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value.value == System.Decimal.One + + vtype = GenericWrapper[System.String] + input_ = vtype("spam") + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value.value == "spam" + + vtype = GenericWrapper[str] + input_ = vtype("spam") + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value.value == "spam" + + vtype = GenericWrapper[ShortEnum] + input_ = vtype(ShortEnum.Zero) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value.value == ShortEnum.Zero + + vtype = GenericWrapper[System.Object] + input_ = vtype(inst) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value.value.__class__ == inst.__class__ + + vtype = GenericWrapper[InterfaceTest] + input_ = vtype(inst) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value.value.__class__ == inst.__class__ + + vtype = GenericWrapper[ISayHello1] + input_ = vtype(inst) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value.value.__class__ == inst.__class__ + + vtype = System.Array[GenericWrapper[int]] + input_ = vtype([GenericWrapper[int](0), GenericWrapper[int](1)]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0].value == 0 + assert value[1].value == 1 + + +def test_overload_selection_with_arrays_of_generic_types(): + """Check overload selection using arrays of generic types.""" + from Python.Test import ISayHello1, InterfaceTest, ShortEnum + from Python.Test import MethodTest, GenericWrapper + + inst = InterfaceTest() + + gtype = GenericWrapper[System.Boolean] + vtype = System.Array[gtype] + input_ = vtype([gtype(True), gtype(True)]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0].value is True + assert value.Length == 2 + + gtype = GenericWrapper[bool] + vtype = System.Array[gtype] + input_ = vtype([gtype(True), gtype(True)]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0].value is True + assert value.Length == 2 + + gtype = GenericWrapper[System.Byte] + vtype = System.Array[gtype] + input_ = vtype([gtype(255), gtype(255)]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0].value == 255 + assert value.Length == 2 + + gtype = GenericWrapper[System.SByte] + vtype = System.Array[gtype] + input_ = vtype([gtype(127), gtype(127)]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0].value == 127 + assert value.Length == 2 + + gtype = GenericWrapper[System.Char] + vtype = System.Array[gtype] + input_ = vtype([gtype(u'A'), gtype(u'A')]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0].value == u'A' + assert value.Length == 2 + + gtype = GenericWrapper[System.Char] + vtype = System.Array[gtype] + input_ = vtype([gtype(65535), gtype(65535)]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0].value == unichr(65535) + assert value.Length == 2 + + gtype = GenericWrapper[System.Int16] + vtype = System.Array[gtype] + input_ = vtype([gtype(32767), gtype(32767)]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0].value == 32767 + assert value.Length == 2 + + gtype = GenericWrapper[System.Int32] + vtype = System.Array[gtype] + input_ = vtype([gtype(2147483647), gtype(2147483647)]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0].value == 2147483647 + assert value.Length == 2 + + gtype = GenericWrapper[int] + vtype = System.Array[gtype] + input_ = vtype([gtype(2147483647), gtype(2147483647)]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0].value == 2147483647 + assert value.Length == 2 + + gtype = GenericWrapper[System.Int64] + vtype = System.Array[gtype] + input_ = vtype([gtype(long(9223372036854775807)), + gtype(long(9223372036854775807))]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0].value == long(9223372036854775807) + assert value.Length == 2 + + # Python 3 has no explicit long type, use System.Int64 instead + if PY2: + gtype = GenericWrapper[long] vtype = System.Array[gtype] input_ = vtype([gtype(long(9223372036854775807)), - gtype(long(9223372036854775807))]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0].value == long(9223372036854775807)) - self.assertTrue(value.Length == 2) - - # Python 3 has no explicit long type, use System.Int64 instead - if PY2: - gtype = GenericWrapper[long] - vtype = System.Array[gtype] - input_ = vtype([gtype(long(9223372036854775807)), - gtype(long(9223372036854775807))]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0].value == long(9223372036854775807)) - self.assertTrue(value.Length == 2) - - gtype = GenericWrapper[System.UInt16] - vtype = System.Array[gtype] - input_ = vtype([gtype(65000), gtype(65000)]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0].value == 65000) - self.assertTrue(value.Length == 2) - - gtype = GenericWrapper[System.UInt32] - vtype = System.Array[gtype] - input_ = vtype([gtype(long(4294967295)), gtype(long(4294967295))]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0].value == long(4294967295)) - self.assertTrue(value.Length == 2) - - gtype = GenericWrapper[System.UInt64] - vtype = System.Array[gtype] - input_ = vtype([gtype(long(18446744073709551615)), - gtype(long(18446744073709551615))]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0].value == long(18446744073709551615)) - self.assertTrue(value.Length == 2) - - gtype = GenericWrapper[System.Single] - vtype = System.Array[gtype] - input_ = vtype([gtype(3.402823e38), gtype(3.402823e38)]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0].value == 3.402823e38) - self.assertTrue(value.Length == 2) - - gtype = GenericWrapper[System.Double] - vtype = System.Array[gtype] - input_ = vtype([gtype(1.7976931348623157e308), - gtype(1.7976931348623157e308)]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0].value == 1.7976931348623157e308) - self.assertTrue(value.Length == 2) - - gtype = GenericWrapper[float] - vtype = System.Array[gtype] - input_ = vtype([gtype(1.7976931348623157e308), - gtype(1.7976931348623157e308)]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0].value == 1.7976931348623157e308) - self.assertTrue(value.Length == 2) - - gtype = GenericWrapper[System.Decimal] - vtype = System.Array[gtype] - input_ = vtype([gtype(System.Decimal.One), - gtype(System.Decimal.One)]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0].value == System.Decimal.One) - self.assertTrue(value.Length == 2) - - gtype = GenericWrapper[System.String] - vtype = System.Array[gtype] - input_ = vtype([gtype("spam"), gtype("spam")]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0].value == "spam") - self.assertTrue(value.Length == 2) - - gtype = GenericWrapper[str] - vtype = System.Array[gtype] - input_ = vtype([gtype("spam"), gtype("spam")]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0].value == "spam") - self.assertTrue(value.Length == 2) - - gtype = GenericWrapper[ShortEnum] - vtype = System.Array[gtype] - input_ = vtype([gtype(ShortEnum.Zero), gtype(ShortEnum.Zero)]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0].value == ShortEnum.Zero) - self.assertTrue(value.Length == 2) - - gtype = GenericWrapper[System.Object] - vtype = System.Array[gtype] - input_ = vtype([gtype(inst), gtype(inst)]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0].value.__class__ == inst.__class__) - self.assertTrue(value.Length == 2) - - gtype = GenericWrapper[InterfaceTest] - vtype = System.Array[gtype] - input_ = vtype([gtype(inst), gtype(inst)]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0].value.__class__ == inst.__class__) - self.assertTrue(value.Length == 2) - - gtype = GenericWrapper[ISayHello1] - vtype = System.Array[gtype] - input_ = vtype([gtype(inst), gtype(inst)]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0].value.__class__ == inst.__class__) - self.assertTrue(value.Length == 2) - - def test_generic_overload_selection_magic_name_only(self): - """Test using only __overloads__ to select on type & sig""" - # TODO NotImplemented - pass - - def test_nested_generic_class(self): - """Check nested generic classes.""" - # TODO NotImplemented - pass - - -def test_suite(): - return unittest.makeSuite(GenericTests) + gtype(long(9223372036854775807))]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0].value == long(9223372036854775807) + assert value.Length == 2 + + gtype = GenericWrapper[System.UInt16] + vtype = System.Array[gtype] + input_ = vtype([gtype(65000), gtype(65000)]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0].value == 65000 + assert value.Length == 2 + + gtype = GenericWrapper[System.UInt32] + vtype = System.Array[gtype] + input_ = vtype([gtype(long(4294967295)), gtype(long(4294967295))]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0].value == long(4294967295) + assert value.Length == 2 + + gtype = GenericWrapper[System.UInt64] + vtype = System.Array[gtype] + input_ = vtype([gtype(long(18446744073709551615)), + gtype(long(18446744073709551615))]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0].value == long(18446744073709551615) + assert value.Length == 2 + + gtype = GenericWrapper[System.Single] + vtype = System.Array[gtype] + input_ = vtype([gtype(3.402823e38), gtype(3.402823e38)]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0].value == 3.402823e38 + assert value.Length == 2 + + gtype = GenericWrapper[System.Double] + vtype = System.Array[gtype] + input_ = vtype([gtype(1.7976931348623157e308), + gtype(1.7976931348623157e308)]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0].value == 1.7976931348623157e308 + assert value.Length == 2 + + gtype = GenericWrapper[float] + vtype = System.Array[gtype] + input_ = vtype([gtype(1.7976931348623157e308), + gtype(1.7976931348623157e308)]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0].value == 1.7976931348623157e308 + assert value.Length == 2 + + gtype = GenericWrapper[System.Decimal] + vtype = System.Array[gtype] + input_ = vtype([gtype(System.Decimal.One), + gtype(System.Decimal.One)]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0].value == System.Decimal.One + assert value.Length == 2 + + gtype = GenericWrapper[System.String] + vtype = System.Array[gtype] + input_ = vtype([gtype("spam"), gtype("spam")]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0].value == "spam" + assert value.Length == 2 + + gtype = GenericWrapper[str] + vtype = System.Array[gtype] + input_ = vtype([gtype("spam"), gtype("spam")]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0].value == "spam" + assert value.Length == 2 + + gtype = GenericWrapper[ShortEnum] + vtype = System.Array[gtype] + input_ = vtype([gtype(ShortEnum.Zero), gtype(ShortEnum.Zero)]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0].value == ShortEnum.Zero + assert value.Length == 2 + + gtype = GenericWrapper[System.Object] + vtype = System.Array[gtype] + input_ = vtype([gtype(inst), gtype(inst)]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0].value.__class__ == inst.__class__ + assert value.Length == 2 + + gtype = GenericWrapper[InterfaceTest] + vtype = System.Array[gtype] + input_ = vtype([gtype(inst), gtype(inst)]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0].value.__class__ == inst.__class__ + assert value.Length == 2 + + gtype = GenericWrapper[ISayHello1] + vtype = System.Array[gtype] + input_ = vtype([gtype(inst), gtype(inst)]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0].value.__class__ == inst.__class__ + assert value.Length == 2 + + +def test_generic_overload_selection_magic_name_only(): + """Test using only __overloads__ to select on type & sig""" + # TODO NotImplemented + pass + + +def test_nested_generic_class(): + """Check nested generic classes.""" + # TODO NotImplemented + pass diff --git a/src/tests/test_import.py b/src/tests/test_import.py new file mode 100644 index 000000000..42cafc4df --- /dev/null +++ b/src/tests/test_import.py @@ -0,0 +1,13 @@ +# -*- coding: utf-8 -*- + +"""Test the import statement.""" + +import pytest + + +def test_relative_missing_import(): + """Test that a relative missing import doesn't crash. + Some modules use this to check if a package is installed. + Relative import in the site-packages folder""" + with pytest.raises(ImportError): + from . import _missing_import diff --git a/src/tests/test_indexer.py b/src/tests/test_indexer.py index 422f7282e..6f18550d9 100644 --- a/src/tests/test_indexer.py +++ b/src/tests/test_indexer.py @@ -1,577 +1,599 @@ # -*- coding: utf-8 -*- -import unittest +"""Test support for indexer properties.""" import Python.Test as Test +import pytest -from _compat import long, unichr +from ._compat import long, unichr -class IndexerTests(unittest.TestCase): - """Test support for indexer properties.""" +def test_public_indexer(): + """Test public indexers.""" + ob = Test.PublicIndexerTest() - def test_public_indexer(self): - """Test public indexers.""" - ob = Test.PublicIndexerTest() + ob[0] = "zero" + assert ob[0] == "zero" - ob[0] = "zero" - self.assertTrue(ob[0] == "zero") + ob[1] = "one" + assert ob[1] == "one" + + assert ob[10] is None + + +def test_protected_indexer(): + """Test protected indexers.""" + ob = Test.ProtectedIndexerTest() + + ob[0] = "zero" + assert ob[0] == "zero" + + ob[1] = "one" + assert ob[1] == "one" - ob[1] = "one" - self.assertTrue(ob[1] == "one") + assert ob[10] is None - self.assertTrue(ob[10] is None) - def test_protected_indexer(self): - """Test protected indexers.""" - ob = Test.ProtectedIndexerTest() +def test_internal_indexer(): + """Test internal indexers.""" + ob = Test.InternalIndexerTest() + with pytest.raises(TypeError): ob[0] = "zero" - self.assertTrue(ob[0] == "zero") - ob[1] = "one" - self.assertTrue(ob[1] == "one") + with pytest.raises(TypeError): + Test.InternalIndexerTest.__getitem__(ob, 0) - self.assertTrue(ob[10] is None) + with pytest.raises(TypeError): + ob.__getitem__(0) - def test_internal_indexer(self): - """Test internal indexers.""" - ob = Test.InternalIndexerTest() - with self.assertRaises(TypeError): - ob[0] = "zero" +def test_private_indexer(): + """Test private indexers.""" + ob = Test.PrivateIndexerTest() + + with pytest.raises(TypeError): + ob[0] = "zero" + + with pytest.raises(TypeError): + Test.PrivateIndexerTest.__getitem__(ob, 0) + + with pytest.raises(TypeError): + ob.__getitem__(0) - with self.assertRaises(TypeError): - Test.InternalIndexerTest.__getitem__(ob, 0) - with self.assertRaises(TypeError): - ob.__getitem__(0) +def test_boolean_indexer(): + """Test boolean indexers.""" + ob = Test.BooleanIndexerTest() - def test_private_indexer(self): - """Test private indexers.""" - ob = Test.PrivateIndexerTest() + assert ob[True] is None + assert ob[1] is None - with self.assertRaises(TypeError): - ob[0] = "zero" + ob[0] = "false" + assert ob[0] == "false" - with self.assertRaises(TypeError): - Test.PrivateIndexerTest.__getitem__(ob, 0) + ob[1] = "true" + assert ob[1] == "true" - with self.assertRaises(TypeError): - ob.__getitem__(0) + ob[False] = "false" + assert ob[False] == "false" - def test_boolean_indexer(self): - """Test boolean indexers.""" - ob = Test.BooleanIndexerTest() + ob[True] = "true" + assert ob[True] == "true" - self.assertTrue(ob[True] is None) - self.assertTrue(ob[1] is None) - ob[0] = "false" - self.assertTrue(ob[0] == "false") +def test_byte_indexer(): + """Test byte indexers.""" + ob = Test.ByteIndexerTest() + max_ = 255 + min_ = 0 - ob[1] = "true" - self.assertTrue(ob[1] == "true") + assert ob[max_] is None - ob[False] = "false" - self.assertTrue(ob[False] == "false") + ob[max_] = str(max_) + assert ob[max_] == str(max_) - ob[True] = "true" - self.assertTrue(ob[True] == "true") + ob[min_] = str(min_) + assert ob[min_] == str(min_) - def test_byte_indexer(self): - """Test byte indexers.""" + with pytest.raises(TypeError): ob = Test.ByteIndexerTest() - max_ = 255 - min_ = 0 + ob["wrong"] + + with pytest.raises(TypeError): + ob = Test.ByteIndexerTest() + ob["wrong"] = "wrong" - self.assertTrue(ob[max_] is None) - ob[max_] = str(max_) - self.assertTrue(ob[max_] == str(max_)) +def test_sbyte_indexer(): + """Test sbyte indexers.""" + ob = Test.SByteIndexerTest() + max_ = 127 + min_ = -128 - ob[min_] = str(min_) - self.assertTrue(ob[min_] == str(min_)) + assert ob[max_] is None - with self.assertRaises(TypeError): - ob = Test.ByteIndexerTest() - ob["wrong"] + ob[max_] = str(max_) + assert ob[max_] == str(max_) - with self.assertRaises(TypeError): - ob = Test.ByteIndexerTest() - ob["wrong"] = "wrong" + ob[min_] = str(min_) + assert ob[min_] == str(min_) - def test_sbyte_indexer(self): - """Test sbyte indexers.""" + with pytest.raises(TypeError): ob = Test.SByteIndexerTest() - max_ = 127 - min_ = -128 + ob["wrong"] - self.assertTrue(ob[max_] is None) + with pytest.raises(TypeError): + ob = Test.SByteIndexerTest() + ob["wrong"] = "wrong" - ob[max_] = str(max_) - self.assertTrue(ob[max_] == str(max_)) - ob[min_] = str(min_) - self.assertTrue(ob[min_] == str(min_)) +def test_char_indexer(): + """Test char indexers.""" + ob = Test.CharIndexerTest() + max_ = unichr(65535) + min_ = unichr(0) - with self.assertRaises(TypeError): - ob = Test.SByteIndexerTest() - ob["wrong"] + assert ob[max_] is None - with self.assertRaises(TypeError): - ob = Test.SByteIndexerTest() - ob["wrong"] = "wrong" + ob[max_] = "max_" + assert ob[max_] == "max_" - def test_char_indexer(self): - """Test char indexers.""" + ob[min_] = "min_" + assert ob[min_] == "min_" + + with pytest.raises(TypeError): + ob = Test.CharIndexerTest() + ob["wrong"] + + with pytest.raises(TypeError): ob = Test.CharIndexerTest() - max_ = unichr(65535) - min_ = unichr(0) + ob["wrong"] = "wrong" - self.assertTrue(ob[max_] is None) - ob[max_] = "max_" - self.assertTrue(ob[max_] == "max_") +def test_int16_indexer(): + """Test Int16 indexers.""" + ob = Test.Int16IndexerTest() + max_ = 32767 + min_ = -32768 - ob[min_] = "min_" - self.assertTrue(ob[min_] == "min_") + assert ob[max_] is None - with self.assertRaises(TypeError): - ob = Test.CharIndexerTest() - ob["wrong"] + ob[max_] = str(max_) + assert ob[max_] == str(max_) - with self.assertRaises(TypeError): - ob = Test.CharIndexerTest() - ob["wrong"] = "wrong" + ob[min_] = str(min_) + assert ob[min_] == str(min_) - def test_int16_indexer(self): - """Test Int16 indexers.""" + with pytest.raises(TypeError): ob = Test.Int16IndexerTest() - max_ = 32767 - min_ = -32768 + ob["wrong"] - self.assertTrue(ob[max_] is None) + with pytest.raises(TypeError): + ob = Test.Int16IndexerTest() + ob["wrong"] = "wrong" - ob[max_] = str(max_) - self.assertTrue(ob[max_] == str(max_)) - ob[min_] = str(min_) - self.assertTrue(ob[min_] == str(min_)) +def test_int32_indexer(): + """Test Int32 indexers.""" + ob = Test.Int32IndexerTest() + max_ = 2147483647 + min_ = -2147483648 - with self.assertRaises(TypeError): - ob = Test.Int16IndexerTest() - ob["wrong"] + assert ob[max_] is None - with self.assertRaises(TypeError): - ob = Test.Int16IndexerTest() - ob["wrong"] = "wrong" + ob[max_] = str(max_) + assert ob[max_] == str(max_) + + ob[min_] = str(min_) + assert ob[min_] == str(min_) + + with pytest.raises(TypeError): + ob = Test.Int32IndexerTest() + ob["wrong"] - def test_int32_indexer(self): - """Test Int32 indexers.""" + with pytest.raises(TypeError): ob = Test.Int32IndexerTest() - max_ = 2147483647 - min_ = -2147483648 + ob["wrong"] = "wrong" - self.assertTrue(ob[max_] is None) - ob[max_] = str(max_) - self.assertTrue(ob[max_] == str(max_)) +def test_int64_indexer(): + """Test Int64 indexers.""" + ob = Test.Int64IndexerTest() + max_ = long(9223372036854775807) + min_ = long(-9223372036854775808) - ob[min_] = str(min_) - self.assertTrue(ob[min_] == str(min_)) + assert ob[max_] is None - with self.assertRaises(TypeError): - ob = Test.Int32IndexerTest() - ob["wrong"] + ob[max_] = str(max_) + assert ob[max_] == str(max_) - with self.assertRaises(TypeError): - ob = Test.Int32IndexerTest() - ob["wrong"] = "wrong" + ob[min_] = str(min_) + assert ob[min_] == str(min_) - def test_int64_indexer(self): - """Test Int64 indexers.""" + with pytest.raises(TypeError): ob = Test.Int64IndexerTest() - max_ = long(9223372036854775807) - min_ = long(-9223372036854775808) + ob["wrong"] - self.assertTrue(ob[max_] is None) + with pytest.raises(TypeError): + ob = Test.Int64IndexerTest() + ob["wrong"] = "wrong" + + +def test_uint16_indexer(): + """Test UInt16 indexers.""" + ob = Test.UInt16IndexerTest() + max_ = 65535 + min_ = 0 - ob[max_] = str(max_) - self.assertTrue(ob[max_] == str(max_)) + assert ob[max_] is None - ob[min_] = str(min_) - self.assertTrue(ob[min_] == str(min_)) + ob[max_] = str(max_) + assert ob[max_] == str(max_) - with self.assertRaises(TypeError): - ob = Test.Int64IndexerTest() - ob["wrong"] + ob[min_] = str(min_) + assert ob[min_] == str(min_) - with self.assertRaises(TypeError): - ob = Test.Int64IndexerTest() - ob["wrong"] = "wrong" + with pytest.raises(TypeError): + ob = Test.UInt16IndexerTest() + ob["wrong"] - def test_uint16_indexer(self): - """Test UInt16 indexers.""" + with pytest.raises(TypeError): ob = Test.UInt16IndexerTest() - max_ = 65535 - min_ = 0 + ob["wrong"] = "wrong" + - self.assertTrue(ob[max_] is None) +def test_uint32_indexer(): + """Test UInt32 indexers.""" + ob = Test.UInt32IndexerTest() + max_ = long(4294967295) + min_ = 0 - ob[max_] = str(max_) - self.assertTrue(ob[max_] == str(max_)) + assert ob[max_] is None - ob[min_] = str(min_) - self.assertTrue(ob[min_] == str(min_)) + ob[max_] = str(max_) + assert ob[max_] == str(max_) - with self.assertRaises(TypeError): - ob = Test.UInt16IndexerTest() - ob["wrong"] + ob[min_] = str(min_) + assert ob[min_] == str(min_) - with self.assertRaises(TypeError): - ob = Test.UInt16IndexerTest() - ob["wrong"] = "wrong" + with pytest.raises(TypeError): + ob = Test.UInt32IndexerTest() + ob["wrong"] - def test_uint32_indexer(self): - """Test UInt32 indexers.""" + with pytest.raises(TypeError): ob = Test.UInt32IndexerTest() - max_ = long(4294967295) - min_ = 0 + ob["wrong"] = "wrong" - self.assertTrue(ob[max_] is None) - ob[max_] = str(max_) - self.assertTrue(ob[max_] == str(max_)) +def test_uint64_indexer(): + """Test UInt64 indexers.""" + ob = Test.UInt64IndexerTest() + max_ = long(18446744073709551615) + min_ = 0 - ob[min_] = str(min_) - self.assertTrue(ob[min_] == str(min_)) + assert ob[max_] is None - with self.assertRaises(TypeError): - ob = Test.UInt32IndexerTest() - ob["wrong"] + ob[max_] = str(max_) + assert ob[max_] == str(max_) - with self.assertRaises(TypeError): - ob = Test.UInt32IndexerTest() - ob["wrong"] = "wrong" + ob[min_] = str(min_) + assert ob[min_] == str(min_) - def test_uint64_indexer(self): - """Test UInt64 indexers.""" + with pytest.raises(TypeError): ob = Test.UInt64IndexerTest() - max_ = long(18446744073709551615) - min_ = 0 + ob["wrong"] + + with pytest.raises(TypeError): + ob = Test.UInt64IndexerTest() + ob["wrong"] = "wrong" - self.assertTrue(ob[max_] is None) - ob[max_] = str(max_) - self.assertTrue(ob[max_] == str(max_)) +def test_single_indexer(): + """Test Single indexers.""" + ob = Test.SingleIndexerTest() + max_ = 3.402823e38 + min_ = -3.402823e38 - ob[min_] = str(min_) - self.assertTrue(ob[min_] == str(min_)) + assert ob[max_] is None - with self.assertRaises(TypeError): - ob = Test.UInt64IndexerTest() - ob["wrong"] + ob[max_] = "max_" + assert ob[max_] == "max_" - with self.assertRaises(TypeError): - ob = Test.UInt64IndexerTest() - ob["wrong"] = "wrong" + ob[min_] = "min_" + assert ob[min_] == "min_" + + with pytest.raises(TypeError): + ob = Test.SingleIndexerTest() + ob["wrong"] - def test_single_indexer(self): - """Test Single indexers.""" + with pytest.raises(TypeError): ob = Test.SingleIndexerTest() - max_ = 3.402823e38 - min_ = -3.402823e38 + ob["wrong"] = "wrong" - self.assertTrue(ob[max_] is None) - ob[max_] = "max_" - self.assertTrue(ob[max_] == "max_") +def test_double_indexer(): + """Test Double indexers.""" + ob = Test.DoubleIndexerTest() + max_ = 1.7976931348623157e308 + min_ = -1.7976931348623157e308 - ob[min_] = "min_" - self.assertTrue(ob[min_] == "min_") + assert ob[max_] is None - with self.assertRaises(TypeError): - ob = Test.SingleIndexerTest() - ob["wrong"] + ob[max_] = "max_" + assert ob[max_] == "max_" - with self.assertRaises(TypeError): - ob = Test.SingleIndexerTest() - ob["wrong"] = "wrong" + ob[min_] = "min_" + assert ob[min_] == "min_" - def test_double_indexer(self): - """Test Double indexers.""" + with pytest.raises(TypeError): ob = Test.DoubleIndexerTest() - max_ = 1.7976931348623157e308 - min_ = -1.7976931348623157e308 + ob["wrong"] + + with pytest.raises(TypeError): + ob = Test.DoubleIndexerTest() + ob["wrong"] = "wrong" + - self.assertTrue(ob[max_] is None) +def test_decimal_indexer(): + """Test Decimal indexers.""" + ob = Test.DecimalIndexerTest() - ob[max_] = "max_" - self.assertTrue(ob[max_] == "max_") + from System import Decimal + max_d = Decimal.Parse("79228162514264337593543950335") + min_d = Decimal.Parse("-79228162514264337593543950335") - ob[min_] = "min_" - self.assertTrue(ob[min_] == "min_") + assert ob[max_d] is None - with self.assertRaises(TypeError): - ob = Test.DoubleIndexerTest() - ob["wrong"] + ob[max_d] = "max_" + assert ob[max_d] == "max_" - with self.assertRaises(TypeError): - ob = Test.DoubleIndexerTest() - ob["wrong"] = "wrong" + ob[min_d] = "min_" + assert ob[min_d] == "min_" - def test_decimal_indexer(self): - """Test Decimal indexers.""" + with pytest.raises(TypeError): ob = Test.DecimalIndexerTest() + ob["wrong"] + + with pytest.raises(TypeError): + ob = Test.DecimalIndexerTest() + ob["wrong"] = "wrong" - from System import Decimal - max_d = Decimal.Parse("79228162514264337593543950335") - min_d = Decimal.Parse("-79228162514264337593543950335") - self.assertTrue(ob[max_d] is None) +def test_string_indexer(): + """Test String indexers.""" + ob = Test.StringIndexerTest() - ob[max_d] = "max_" - self.assertTrue(ob[max_d] == "max_") + assert ob["spam"] is None + assert ob[u"spam"] is None - ob[min_d] = "min_" - self.assertTrue(ob[min_d] == "min_") + ob["spam"] = "spam" + assert ob["spam"] == "spam" + assert ob["spam"] == u"spam" + assert ob[u"spam"] == "spam" + assert ob[u"spam"] == u"spam" - with self.assertRaises(TypeError): - ob = Test.DecimalIndexerTest() - ob["wrong"] + ob[u"eggs"] = u"eggs" + assert ob["eggs"] == "eggs" + assert ob["eggs"] == u"eggs" + assert ob[u"eggs"] == "eggs" + assert ob[u"eggs"] == u"eggs" - with self.assertRaises(TypeError): - ob = Test.DecimalIndexerTest() - ob["wrong"] = "wrong" + with pytest.raises(TypeError): + ob = Test.StringIndexerTest() + ob[1] - def test_string_indexer(self): - """Test String indexers.""" + with pytest.raises(TypeError): ob = Test.StringIndexerTest() + ob[1] = "wrong" + + +def test_enum_indexer(): + """Test enum indexers.""" + ob = Test.EnumIndexerTest() + + key = Test.ShortEnum.One - self.assertTrue(ob["spam"] is None) - self.assertTrue(ob[u"spam"] is None) + assert ob[key] is None - ob["spam"] = "spam" - self.assertTrue(ob["spam"] == "spam") - self.assertTrue(ob["spam"] == u"spam") - self.assertTrue(ob[u"spam"] == "spam") - self.assertTrue(ob[u"spam"] == u"spam") + ob[key] = "spam" + assert ob[key] == "spam" - ob[u"eggs"] = u"eggs" - self.assertTrue(ob["eggs"] == "eggs") - self.assertTrue(ob["eggs"] == u"eggs") - self.assertTrue(ob[u"eggs"] == "eggs") - self.assertTrue(ob[u"eggs"] == u"eggs") + ob[key] = "eggs" + assert ob[key] == "eggs" - with self.assertRaises(TypeError): - ob = Test.StringIndexerTest() - ob[1] + ob[1] = "spam" + assert ob[1] == "spam" - with self.assertRaises(TypeError): - ob = Test.StringIndexerTest() - ob[1] = "wrong" + with pytest.raises(TypeError): + ob = Test.EnumIndexerTest() + ob["wrong"] - def test_enum_indexer(self): - """Test enum indexers.""" + with pytest.raises(TypeError): ob = Test.EnumIndexerTest() + ob["wrong"] = "wrong" - key = Test.ShortEnum.One - self.assertTrue(ob[key] is None) +def test_object_indexer(): + """Test ob indexers.""" + ob = Test.ObjectIndexerTest() - ob[key] = "spam" - self.assertTrue(ob[key] == "spam") + from Python.Test import Spam + spam = Spam("spam") - ob[key] = "eggs" - self.assertTrue(ob[key] == "eggs") + assert ob[spam] is None + assert ob["spam"] is None + assert ob[1] is None + assert ob[None] is None - ob[1] = "spam" - self.assertTrue(ob[1] == "spam") + ob[spam] = "spam" + assert ob[spam] == "spam" - with self.assertRaises(TypeError): - ob = Test.EnumIndexerTest() - ob["wrong"] + ob["spam"] = "eggs" + assert ob["spam"] == "eggs" - with self.assertRaises(TypeError): - ob = Test.EnumIndexerTest() - ob["wrong"] = "wrong" + ob[1] = "one" + assert ob[1] == "one" - def test_object_indexer(self): - """Test ob indexers.""" - ob = Test.ObjectIndexerTest() + ob[long(1)] = "long" + assert ob[long(1)] == "long" - from Python.Test import Spam - spam = Spam("spam") + with pytest.raises(TypeError): + class Eggs(object): + pass - self.assertTrue(ob[spam] is None) - self.assertTrue(ob["spam"] is None) - self.assertTrue(ob[1] is None) - self.assertTrue(ob[None] is None) + key = Eggs() + ob = Test.ObjectIndexerTest() + ob[key] = "wrong" - ob[spam] = "spam" - self.assertTrue(ob[spam] == "spam") - ob["spam"] = "eggs" - self.assertTrue(ob["spam"] == "eggs") +def test_interface_indexer(): + """Test interface indexers.""" + ob = Test.InterfaceIndexerTest() - ob[1] = "one" - self.assertTrue(ob[1] == "one") + from Python.Test import Spam + spam = Spam("spam") - ob[long(1)] = "long" - self.assertTrue(ob[long(1)] == "long") + assert ob[spam] is None - with self.assertRaises(TypeError): - class Eggs(object): - pass + ob[spam] = "spam" + assert ob[spam] == "spam" - key = Eggs() - ob = Test.ObjectIndexerTest() - ob[key] = "wrong" + ob[spam] = "eggs" + assert ob[spam] == "eggs" - def test_interface_indexer(self): - """Test interface indexers.""" + with pytest.raises(TypeError): ob = Test.InterfaceIndexerTest() + ob["wrong"] - from Python.Test import Spam - spam = Spam("spam") + with pytest.raises(TypeError): + ob = Test.InterfaceIndexerTest() + ob["wrong"] = "wrong" - self.assertTrue(ob[spam] is None) - ob[spam] = "spam" - self.assertTrue(ob[spam] == "spam") +def test_typed_indexer(): + """Test typed indexers.""" + ob = Test.TypedIndexerTest() - ob[spam] = "eggs" - self.assertTrue(ob[spam] == "eggs") + from Python.Test import Spam + spam = Spam("spam") - with self.assertRaises(TypeError): - ob = Test.InterfaceIndexerTest() - ob["wrong"] + assert ob[spam] is None - with self.assertRaises(TypeError): - ob = Test.InterfaceIndexerTest() - ob["wrong"] = "wrong" + ob[spam] = "spam" + assert ob[spam] == "spam" - def test_typed_indexer(self): - """Test typed indexers.""" + ob[spam] = "eggs" + assert ob[spam] == "eggs" + + with pytest.raises(TypeError): ob = Test.TypedIndexerTest() + ob["wrong"] - from Python.Test import Spam - spam = Spam("spam") + with pytest.raises(TypeError): + ob = Test.TypedIndexerTest() + ob["wrong"] = "wrong" - self.assertTrue(ob[spam] is None) - ob[spam] = "spam" - self.assertTrue(ob[spam] == "spam") +def test_multi_arg_indexer(): + """Test indexers that take multiple index arguments.""" + ob = Test.MultiArgIndexerTest() - ob[spam] = "eggs" - self.assertTrue(ob[spam] == "eggs") + ob[0, 1] = "zero one" + assert ob[0, 1] == "zero one" - with self.assertRaises(TypeError): - ob = Test.TypedIndexerTest() - ob["wrong"] + ob[1, 9] = "one nine" + assert ob[1, 9] == "one nine" - with self.assertRaises(TypeError): - ob = Test.TypedIndexerTest() - ob["wrong"] = "wrong" + assert ob[10, 50] is None - def test_multi_arg_indexer(self): - """Test indexers that take multiple index arguments.""" + with pytest.raises(TypeError): ob = Test.MultiArgIndexerTest() + _ = ob[0, "one"] - ob[0, 1] = "zero one" - self.assertTrue(ob[0, 1] == "zero one") + with pytest.raises(TypeError): + ob = Test.MultiArgIndexerTest() + ob[0, "one"] = "wrong" - ob[1, 9] = "one nine" - self.assertTrue(ob[1, 9] == "one nine") - self.assertTrue(ob[10, 50] is None) +def test_multi_type_indexer(): + """Test indexers that take multiple indices of different types.""" + ob = Test.MultiTypeIndexerTest() + spam = Test.Spam("spam") - with self.assertRaises(TypeError): - ob = Test.MultiArgIndexerTest() - _ = ob[0, "one"] + ob[0, "one", spam] = "zero one spam" + assert ob[0, "one", spam] == "zero one spam" - with self.assertRaises(TypeError): - ob = Test.MultiArgIndexerTest() - ob[0, "one"] = "wrong" + ob[1, "nine", spam] = "one nine spam" + assert ob[1, "nine", spam] == "one nine spam" - def test_multi_type_indexer(self): - """Test indexers that take multiple indices of different types.""" + with pytest.raises(TypeError): ob = Test.MultiTypeIndexerTest() - spam = Test.Spam("spam") + _ = ob[0, 1, spam] - ob[0, "one", spam] = "zero one spam" - self.assertTrue(ob[0, "one", spam] == "zero one spam") - - ob[1, "nine", spam] = "one nine spam" - self.assertTrue(ob[1, "nine", spam] == "one nine spam") + with pytest.raises(TypeError): + ob = Test.MultiTypeIndexerTest() + ob[0, 1, spam] = "wrong" - with self.assertRaises(TypeError): - ob = Test.MultiTypeIndexerTest() - _ = ob[0, 1, spam] - with self.assertRaises(TypeError): - ob = Test.MultiTypeIndexerTest() - ob[0, 1, spam] = "wrong" +def test_multi_default_key_indexer(): + """Test indexers that take multiple indices with a default + key arguments.""" + # default argument is 2 in the MultiDefaultKeyIndexerTest object + ob = Test.MultiDefaultKeyIndexerTest() + ob[0, 2] = "zero one spam" + assert ob[0] == "zero one spam" - def test_multi_default_key_indexer(self): - """Test indexers that take multiple indices with a default - key arguments.""" - # default argument is 2 in the MultiDefaultKeyIndexerTest object - ob = Test.MultiDefaultKeyIndexerTest() - ob[0, 2] = "zero one spam" - self.assertTrue(ob[0] == "zero one spam") + ob[1] = "one nine spam" + assert ob[1, 2] == "one nine spam" - ob[1] = "one nine spam" - self.assertTrue(ob[1, 2] == "one nine spam") - def test_indexer_wrong_key_type(self): - """Test calling an indexer using a key of the wrong type.""" +def test_indexer_wrong_key_type(): + """Test calling an indexer using a key of the wrong type.""" - with self.assertRaises(TypeError): - ob = Test.PublicIndexerTest() - _ = ob["wrong"] + with pytest.raises(TypeError): + ob = Test.PublicIndexerTest() + _ = ob["wrong"] - with self.assertRaises(TypeError): - ob = Test.PublicIndexerTest() - ob["wrong"] = "spam" + with pytest.raises(TypeError): + ob = Test.PublicIndexerTest() + ob["wrong"] = "spam" - def test_indexer_wrong_value_type(self): - """Test calling an indexer using a value of the wrong type.""" - with self.assertRaises(TypeError): - ob = Test.PublicIndexerTest() - ob[1] = 9993.9 +def test_indexer_wrong_value_type(): + """Test calling an indexer using a value of the wrong type.""" - def test_unbound_indexer(self): - """Test calling an unbound indexer.""" + with pytest.raises(TypeError): ob = Test.PublicIndexerTest() + ob[1] = 9993.9 - Test.PublicIndexerTest.__setitem__(ob, 0, "zero") - self.assertTrue(ob[0] == "zero") - Test.PublicIndexerTest.__setitem__(ob, 1, "one") - self.assertTrue(ob[1] == "one") +def test_unbound_indexer(): + """Test calling an unbound indexer.""" + ob = Test.PublicIndexerTest() - self.assertTrue(ob[10] is None) + Test.PublicIndexerTest.__setitem__(ob, 0, "zero") + assert ob[0] == "zero" - def test_indexer_abuse(self): - """Test indexer abuse.""" - _class = Test.PublicIndexerTest - ob = Test.PublicIndexerTest() + Test.PublicIndexerTest.__setitem__(ob, 1, "one") + assert ob[1] == "one" + + assert ob[10] is None - with self.assertRaises(AttributeError): - del _class.__getitem__ - with self.assertRaises(AttributeError): - del ob.__getitem__ +def test_indexer_abuse(): + """Test indexer abuse.""" + _class = Test.PublicIndexerTest + ob = Test.PublicIndexerTest() - with self.assertRaises(AttributeError): - del _class.__setitem__ + with pytest.raises(AttributeError): + del _class.__getitem__ - with self.assertRaises(AttributeError): - del ob.__setitem__ + with pytest.raises(AttributeError): + del ob.__getitem__ + with pytest.raises(AttributeError): + del _class.__setitem__ -def test_suite(): - return unittest.makeSuite(IndexerTests) + with pytest.raises(AttributeError): + del ob.__setitem__ diff --git a/src/tests/test_interface.py b/src/tests/test_interface.py index 1fac36eb8..997f17264 100644 --- a/src/tests/test_interface.py +++ b/src/tests/test_interface.py @@ -1,72 +1,69 @@ # -*- coding: utf-8 -*- -import unittest +"""Test CLR interface support.""" import Python.Test as Test +import pytest -from _compat import DictProxyType +from ._compat import DictProxyType -class InterfaceTests(unittest.TestCase): - """Test CLR interface support.""" +def test_interface_standard_attrs(): + """Test standard class attributes.""" + from Python.Test import IPublicInterface - def test_interface_standard_attrs(self): - """Test standard class attributes.""" - from Python.Test import IPublicInterface + assert IPublicInterface.__name__ == 'IPublicInterface' + assert IPublicInterface.__module__ == 'Python.Test' + assert isinstance(IPublicInterface.__dict__, DictProxyType) - self.assertTrue(IPublicInterface.__name__ == 'IPublicInterface') - self.assertTrue(IPublicInterface.__module__ == 'Python.Test') - self.assertTrue(isinstance(IPublicInterface.__dict__, DictProxyType)) - def test_global_interface_visibility(self): - """Test visibility of module-level interfaces.""" - from Python.Test import IPublicInterface +def test_global_interface_visibility(): + """Test visibility of module-level interfaces.""" + from Python.Test import IPublicInterface - self.assertTrue(IPublicInterface.__name__ == 'IPublicInterface') + assert IPublicInterface.__name__ == 'IPublicInterface' - with self.assertRaises(ImportError): - from Python.Test import IInternalInterface - _ = IInternalInterface + with pytest.raises(ImportError): + from Python.Test import IInternalInterface + _ = IInternalInterface - with self.assertRaises(AttributeError): - _ = Test.IInternalInterface + with pytest.raises(AttributeError): + _ = Test.IInternalInterface - def test_nested_interface_visibility(self): - """Test visibility of nested interfaces.""" - from Python.Test import InterfaceTest - ob = InterfaceTest.IPublic - self.assertTrue(ob.__name__ == 'IPublic') +def test_nested_interface_visibility(): + """Test visibility of nested interfaces.""" + from Python.Test import InterfaceTest - ob = InterfaceTest.IProtected - self.assertTrue(ob.__name__ == 'IProtected') + ob = InterfaceTest.IPublic + assert ob.__name__ == 'IPublic' - with self.assertRaises(AttributeError): - _ = InterfaceTest.IInternal + ob = InterfaceTest.IProtected + assert ob.__name__ == 'IProtected' - with self.assertRaises(AttributeError): - _ = InterfaceTest.IPrivate + with pytest.raises(AttributeError): + _ = InterfaceTest.IInternal - def test_explicit_cast_to_interface(self): - """Test explicit cast to an interface.""" - from Python.Test import InterfaceTest + with pytest.raises(AttributeError): + _ = InterfaceTest.IPrivate - ob = InterfaceTest() - self.assertTrue(type(ob).__name__ == 'InterfaceTest') - self.assertTrue(hasattr(ob, 'HelloProperty')) - i1 = Test.ISayHello1(ob) - self.assertTrue(type(i1).__name__ == 'ISayHello1') - self.assertTrue(hasattr(i1, 'SayHello')) - self.assertTrue(i1.SayHello() == 'hello 1') - self.assertFalse(hasattr(i1, 'HelloProperty')) +def test_explicit_cast_to_interface(): + """Test explicit cast to an interface.""" + from Python.Test import InterfaceTest - i2 = Test.ISayHello2(ob) - self.assertTrue(type(i2).__name__ == 'ISayHello2') - self.assertTrue(i2.SayHello() == 'hello 2') - self.assertTrue(hasattr(i2, 'SayHello')) - self.assertFalse(hasattr(i2, 'HelloProperty')) + ob = InterfaceTest() + assert type(ob).__name__ == 'InterfaceTest' + assert hasattr(ob, 'HelloProperty') + i1 = Test.ISayHello1(ob) + assert type(i1).__name__ == 'ISayHello1' + assert hasattr(i1, 'SayHello') + assert i1.SayHello() == 'hello 1' + assert not hasattr(i1, 'HelloProperty') -def test_suite(): - return unittest.makeSuite(InterfaceTests) + i2 = Test.ISayHello2(ob) + assert type(i2).__name__ == 'ISayHello2' + assert i2.SayHello() == 'hello 2' + assert hasattr(i2, 'SayHello') + assert not hasattr(i2, 'HelloProperty') diff --git a/src/tests/test_method.py b/src/tests/test_method.py index 6c4454004..ad182678d 100644 --- a/src/tests/test_method.py +++ b/src/tests/test_method.py @@ -1,713 +1,834 @@ # -*- coding: utf-8 -*- -import unittest +"""Test CLR method support.""" import System +import pytest from Python.Test import MethodTest -from _compat import PY2, long, unichr +from ._compat import PY2, long, unichr -class MethodTests(unittest.TestCase): - """Test CLR method support.""" +def test_instance_method_descriptor(): + """Test instance method descriptor behavior.""" - def test_instance_method_descriptor(self): - """Test instance method descriptor behavior.""" + with pytest.raises(AttributeError): + MethodTest().PublicMethod = 0 - with self.assertRaises(AttributeError): - MethodTest().PublicMethod = 0 + with pytest.raises(AttributeError): + MethodTest.PublicMethod = 0 - with self.assertRaises(AttributeError): - MethodTest.PublicMethod = 0 + with pytest.raises(AttributeError): + del MethodTest().PublicMethod - with self.assertRaises(AttributeError): - del MethodTest().PublicMethod + with pytest.raises(AttributeError): + del MethodTest.PublicMethod - with self.assertRaises(AttributeError): - del MethodTest.PublicMethod - def test_static_method_descriptor(self): - """Test static method descriptor behavior.""" +def test_static_method_descriptor(): + """Test static method descriptor behavior.""" - with self.assertRaises(AttributeError): - MethodTest().PublicStaticMethod = 0 + with pytest.raises(AttributeError): + MethodTest().PublicStaticMethod = 0 - with self.assertRaises(AttributeError): - MethodTest.PublicStaticMethod = 0 + with pytest.raises(AttributeError): + MethodTest.PublicStaticMethod = 0 - with self.assertRaises(AttributeError): - del MethodTest().PublicStaticMethod + with pytest.raises(AttributeError): + del MethodTest().PublicStaticMethod - with self.assertRaises(AttributeError): - del MethodTest.PublicStaticMethod + with pytest.raises(AttributeError): + del MethodTest.PublicStaticMethod - def test_public_instance_method(self): - """Test public instance method visibility.""" - ob = MethodTest() - self.assertTrue(ob.PublicMethod() == "public") - def test_public_static_method(self): - """Test public static method visibility.""" - ob = MethodTest() - self.assertTrue(MethodTest.PublicStaticMethod() == "public static") - self.assertTrue(ob.PublicStaticMethod() == "public static") +def test_public_instance_method(): + """Test public instance method visibility.""" + ob = MethodTest() + assert ob.PublicMethod() == "public" - def test_protected_instance_method(self): - """Test protected instance method visibility.""" - ob = MethodTest() - self.assertTrue(ob.ProtectedMethod() == "protected") - def test_protected_static_method(self): - """Test protected static method visibility.""" - ob = MethodTest() - result = "protected static" - self.assertTrue(MethodTest.ProtectedStaticMethod() == result) - self.assertTrue(ob.ProtectedStaticMethod() == result) +def test_public_static_method(): + """Test public static method visibility.""" + ob = MethodTest() + assert MethodTest.PublicStaticMethod() == "public static" + assert ob.PublicStaticMethod() == "public static" - def test_internal_method(self): - """Test internal method visibility.""" - with self.assertRaises(AttributeError): - _ = MethodTest().InternalMethod +def test_protected_instance_method(): + """Test protected instance method visibility.""" + ob = MethodTest() + assert ob.ProtectedMethod() == "protected" - with self.assertRaises(AttributeError): - _ = MethodTest.InternalMethod - with self.assertRaises(AttributeError): - _ = MethodTest().InternalStaticMethod +def test_protected_static_method(): + """Test protected static method visibility.""" + ob = MethodTest() + result = "protected static" + assert MethodTest.ProtectedStaticMethod() == result + assert ob.ProtectedStaticMethod() == result - with self.assertRaises(AttributeError): - _ = MethodTest.InternalStaticMethod - def test_private_method(self): - """Test private method visibility.""" +def test_internal_method(): + """Test internal method visibility.""" - with self.assertRaises(AttributeError): - _ = MethodTest().PrivateMethod + with pytest.raises(AttributeError): + _ = MethodTest().InternalMethod - with self.assertRaises(AttributeError): - _ = MethodTest.PrivateMethod + with pytest.raises(AttributeError): + _ = MethodTest.InternalMethod - with self.assertRaises(AttributeError): - _ = MethodTest().PrivateStaticMethod + with pytest.raises(AttributeError): + _ = MethodTest().InternalStaticMethod - with self.assertRaises(AttributeError): - _ = MethodTest.PrivateStaticMethod + with pytest.raises(AttributeError): + _ = MethodTest.InternalStaticMethod - def test_unbound_managed_method_call(self): - """Test calling unbound managed methods.""" - from Python.Test import MethodTestSub - ob = MethodTest() - self.assertTrue(MethodTest.PublicMethod(ob) == "public") +def test_private_method(): + """Test private method visibility.""" + + with pytest.raises(AttributeError): + _ = MethodTest().PrivateMethod + + with pytest.raises(AttributeError): + _ = MethodTest.PrivateMethod + + with pytest.raises(AttributeError): + _ = MethodTest().PrivateStaticMethod + + with pytest.raises(AttributeError): + _ = MethodTest.PrivateStaticMethod + - with self.assertRaises(TypeError): - MethodTest.PublicMethod() +def test_unbound_managed_method_call(): + """Test calling unbound managed methods.""" + from Python.Test import MethodTestSub - ob = MethodTestSub() - self.assertTrue(MethodTestSub.PublicMethod(ob) == "public") - self.assertTrue(MethodTestSub.PublicMethod(ob, "echo") == "echo") + ob = MethodTest() + assert MethodTest.PublicMethod(ob) == "public" - with self.assertRaises(TypeError): - MethodTestSub.PublicMethod("echo") + with pytest.raises(TypeError): + MethodTest.PublicMethod() - def test_overloaded_method_inheritance(self): - """Test that overloads are inherited properly.""" - from Python.Test import MethodTestSub + ob = MethodTestSub() + assert MethodTestSub.PublicMethod(ob) == "public" + assert MethodTestSub.PublicMethod(ob, "echo") == "echo" + with pytest.raises(TypeError): + MethodTestSub.PublicMethod("echo") + + +def test_overloaded_method_inheritance(): + """Test that overloads are inherited properly.""" + from Python.Test import MethodTestSub + + ob = MethodTest() + assert ob.PublicMethod() == "public" + + with pytest.raises(TypeError): ob = MethodTest() - self.assertTrue(ob.PublicMethod() == "public") + ob.PublicMethod("echo") - with self.assertRaises(TypeError): - ob = MethodTest() - ob.PublicMethod("echo") + ob = MethodTestSub() + assert ob.PublicMethod() == "public" - ob = MethodTestSub() - self.assertTrue(ob.PublicMethod() == "public") + assert ob.PublicMethod("echo") == "echo" - self.assertTrue(ob.PublicMethod("echo") == "echo") - def test_method_descriptor_abuse(self): - """Test method descriptor abuse.""" - desc = MethodTest.__dict__['PublicMethod'] +def test_method_descriptor_abuse(): + """Test method descriptor abuse.""" + desc = MethodTest.__dict__['PublicMethod'] - with self.assertRaises(TypeError): - desc.__get__(0, 0) + with pytest.raises(TypeError): + desc.__get__(0, 0) - with self.assertRaises(AttributeError): - desc.__set__(0, 0) + with pytest.raises(AttributeError): + desc.__set__(0, 0) - def test_method_docstrings(self): - """Test standard method docstring generation""" - method = MethodTest.GetType - value = 'System.Type GetType()' - self.assertTrue(method.__doc__ == value) - # ====================================================================== - # Tests of specific argument and result conversion scenarios - # ====================================================================== +def test_method_docstrings(): + """Test standard method docstring generation""" + method = MethodTest.GetType + value = 'System.Type GetType()' + assert method.__doc__ == value - def test_method_call_enum_conversion(self): - """Test enum conversion in method call.""" - from System import TypeCode - ob = MethodTest() - r = ob.TestEnumConversion(TypeCode.Int32) - self.assertTrue(r == TypeCode.Int32) +# ====================================================================== +# Tests of specific argument and result conversion scenarios +# ====================================================================== +def test_method_call_enum_conversion(): + """Test enum conversion in method call.""" + from System import TypeCode - def test_method_call_flags_conversion(self): - """Test flags conversion in method call.""" - from System.IO import FileAccess + ob = MethodTest() + r = ob.TestEnumConversion(TypeCode.Int32) + assert r == TypeCode.Int32 - ob = MethodTest() - flags = FileAccess.Read | FileAccess.Write - r = ob.TestFlagsConversion(flags) - self.assertTrue(r == flags) - def test_method_call_struct_conversion(self): - """Test struct conversion in method call.""" - from System import Guid +def test_method_call_flags_conversion(): + """Test flags conversion in method call.""" + from System.IO import FileAccess - ob = MethodTest() - guid = Guid.NewGuid() - temp = guid.ToString() - r = ob.TestStructConversion(guid) - self.assertTrue(r.ToString() == temp) + ob = MethodTest() + flags = FileAccess.Read | FileAccess.Write + r = ob.TestFlagsConversion(flags) + assert r == flags - def test_subclass_instance_conversion(self): - """Test subclass instance conversion in method call.""" - class TestSubException(System.Exception): - pass +def test_method_call_struct_conversion(): + """Test struct conversion in method call.""" + from System import Guid - ob = MethodTest() - instance = TestSubException() - result = ob.TestSubclassConversion(instance) - self.assertTrue(isinstance(result, System.Exception)) + ob = MethodTest() + guid = Guid.NewGuid() + temp = guid.ToString() + r = ob.TestStructConversion(guid) + assert r.ToString() == temp - def test_null_array_conversion(self): - """Test null array conversion in method call.""" - ob = MethodTest() - r = ob.TestNullArrayConversion(None) - self.assertTrue(r is None) - - def test_string_params_args(self): - """Test use of string params.""" - result = MethodTest.TestStringParamsArg('one', 'two', 'three') - self.assertEqual(result.Length, 3) - self.assertEqual(len(result), 3, result) - self.assertTrue(result[0] == 'one') - self.assertTrue(result[1] == 'two') - self.assertTrue(result[2] == 'three') - - result = MethodTest.TestStringParamsArg(['one', 'two', 'three']) - self.assertTrue(len(result) == 3) - self.assertTrue(result[0] == 'one') - self.assertTrue(result[1] == 'two') - self.assertTrue(result[2] == 'three') - - def test_object_params_args(self): - """Test use of object params.""" - result = MethodTest.TestObjectParamsArg('one', 'two', 'three') - self.assertEqual(len(result), 3, result) - self.assertTrue(result[0] == 'one') - self.assertTrue(result[1] == 'two') - self.assertTrue(result[2] == 'three') - - result = MethodTest.TestObjectParamsArg(['one', 'two', 'three']) - self.assertEqual(len(result), 3, result) - self.assertTrue(result[0] == 'one') - self.assertTrue(result[1] == 'two') - self.assertTrue(result[2] == 'three') - - def test_value_params_args(self): - """Test use of value type params.""" - result = MethodTest.TestValueParamsArg(1, 2, 3) - self.assertEqual(len(result), 3) - self.assertTrue(result[0] == 1) - self.assertTrue(result[1] == 2) - self.assertTrue(result[2] == 3) - - result = MethodTest.TestValueParamsArg([1, 2, 3]) - self.assertEqual(len(result), 3) - self.assertTrue(result[0] == 1) - self.assertTrue(result[1] == 2) - self.assertTrue(result[2] == 3) - - def test_non_params_array_in_last_place(self): - """Test overload resolution with of non-"params" array as - last parameter.""" - result = MethodTest.TestNonParamsArrayInLastPlace(1, 2, 3) - self.assertTrue(result) - - def test_string_out_params(self): - """Test use of string out-parameters.""" - result = MethodTest.TestStringOutParams("hi", "there") - self.assertTrue(isinstance(result, tuple)) - self.assertEqual(len(result), 2) - self.assertTrue(result[0] is True) - self.assertTrue(result[1] == "output string") - - result = MethodTest.TestStringOutParams("hi", None) - self.assertTrue(isinstance(result, tuple)) - self.assertEqual(len(result), 2) - self.assertTrue(result[0] is True) - self.assertTrue(result[1] == "output string") - - def test_string_ref_params(self): - """Test use of string byref parameters.""" - result = MethodTest.TestStringRefParams("hi", "there") - self.assertTrue(isinstance(result, tuple)) - self.assertEqual(len(result), 2) - self.assertTrue(result[0] is True) - self.assertTrue(result[1] == "output string") - - result = MethodTest.TestStringRefParams("hi", None) - self.assertTrue(isinstance(result, tuple)) - self.assertEqual(len(result), 2) - self.assertTrue(result[0] is True) - self.assertTrue(result[1] == "output string") - - def test_value_out_params(self): - """Test use of value type out-parameters.""" - result = MethodTest.TestValueOutParams("hi", 1) - self.assertTrue(isinstance(result, tuple)) - self.assertEqual(len(result), 2) - self.assertTrue(result[0] is True) - self.assertTrue(result[1] == 42) - - # None cannot be converted to a value type like int, long, etc. - with self.assertRaises(TypeError): - MethodTest.TestValueOutParams("hi", None) - - def test_value_ref_params(self): - """Test use of value type byref parameters.""" - result = MethodTest.TestValueRefParams("hi", 1) - self.assertTrue(isinstance(result, tuple)) - self.assertEqual(len(result), 2) - self.assertTrue(result[0] is True) - self.assertTrue(result[1] == 42) - - # None cannot be converted to a value type like int, long, etc. - with self.assertRaises(TypeError): - MethodTest.TestValueRefParams("hi", None) - - def test_object_out_params(self): - """Test use of object out-parameters.""" - result = MethodTest.TestObjectOutParams("hi", MethodTest()) - self.assertTrue(isinstance(result, tuple)) - self.assertTrue(len(result) == 2) - self.assertTrue(result[0] is True) - self.assertTrue(isinstance(result[1], System.Exception)) - - result = MethodTest.TestObjectOutParams("hi", None) - self.assertTrue(isinstance(result, tuple)) - self.assertEqual(len(result), 2) - self.assertTrue(result[0] is True) - self.assertTrue(isinstance(result[1], System.Exception)) - - def test_object_ref_params(self): - """Test use of object byref parameters.""" - result = MethodTest.TestObjectRefParams("hi", MethodTest()) - self.assertTrue(isinstance(result, tuple)) - self.assertEqual(len(result), 2) - self.assertTrue(result[0] is True) - self.assertTrue(isinstance(result[1], System.Exception)) - - result = MethodTest.TestObjectRefParams("hi", None) - self.assertTrue(isinstance(result, tuple)) - self.assertEqual(len(result), 2) - self.assertTrue(result[0] is True) - self.assertTrue(isinstance(result[1], System.Exception)) - - def test_struct_out_params(self): - """Test use of struct out-parameters.""" - result = MethodTest.TestStructOutParams("hi", System.Guid.NewGuid()) - self.assertTrue(isinstance(result, tuple)) - self.assertEqual(len(result), 2) - self.assertTrue(result[0] is True) - self.assertTrue(isinstance(result[1], System.Guid)) - - # None cannot be converted to a value type like a struct - with self.assertRaises(TypeError): - MethodTest.TestValueRefParams("hi", None) - - def test_struct_ref_params(self): - """Test use of struct byref parameters.""" - result = MethodTest.TestStructRefParams("hi", System.Guid.NewGuid()) - self.assertTrue(isinstance(result, tuple)) - self.assertTrue(len(result) == 2) - self.assertTrue(result[0] is True) - self.assertTrue(isinstance(result[1], System.Guid)) - - # None cannot be converted to a value type like a struct - with self.assertRaises(TypeError): - MethodTest.TestValueRefParams("hi", None) - - def test_void_single_out_param(self): - """Test void method with single out-parameter.""" - result = MethodTest.TestVoidSingleOutParam(9) - self.assertTrue(result == 42) - - # None cannot be converted to a value type - with self.assertRaises(TypeError): - MethodTest.TestVoidSingleOutParam(None) - - def test_void_single_ref_param(self): - """Test void method with single ref-parameter.""" - result = MethodTest.TestVoidSingleRefParam(9) - self.assertTrue(result == 42) - - # None cannot be converted to a value type - with self.assertRaises(TypeError): - MethodTest.TestVoidSingleRefParam(None) - - def test_single_default_param(self): - """Test void method with single ref-parameter.""" - result = MethodTest.TestSingleDefaultParam() - self.assertTrue(result == 5) - - def test_one_arg_and_two_default_param(self): - """Test void method with single ref-parameter.""" - result = MethodTest.TestOneArgAndTwoDefaultParam(11) - self.assertTrue(result == 22) - - result = MethodTest.TestOneArgAndTwoDefaultParam(15) - self.assertTrue(result == 26) - - result = MethodTest.TestOneArgAndTwoDefaultParam(20) - self.assertTrue(result == 31) - - def test_two_default_param(self): - """Test void method with single ref-parameter.""" - result = MethodTest.TestTwoDefaultParam() - self.assertTrue(result == 11) - - def test_explicit_selection_with_out_modifier(self): - """Check explicit overload selection with out modifiers.""" - refstr = System.String("").GetType().MakeByRefType() - result = MethodTest.TestStringOutParams.__overloads__[str, refstr]( - "hi", "there") - self.assertTrue(isinstance(result, tuple)) - self.assertTrue(len(result) == 2) - self.assertTrue(result[0] is True) - self.assertTrue(result[1] == "output string") - - result = MethodTest.TestStringOutParams.__overloads__[str, refstr]( - "hi", None) - self.assertTrue(isinstance(result, tuple)) - self.assertTrue(len(result) == 2) - self.assertTrue(result[0] is True) - self.assertTrue(result[1] == "output string") - - def test_explicit_selection_with_ref_modifier(self): - """Check explicit overload selection with ref modifiers.""" - refstr = System.String("").GetType().MakeByRefType() - result = MethodTest.TestStringRefParams.__overloads__[str, refstr]( - "hi", "there") - self.assertTrue(isinstance(result, tuple)) - self.assertTrue(len(result) == 2) - self.assertTrue(result[0] is True) - self.assertTrue(result[1] == "output string") - - result = MethodTest.TestStringRefParams.__overloads__[str, refstr]( - "hi", None) - self.assertTrue(isinstance(result, tuple)) - self.assertTrue(len(result) == 2) - self.assertTrue(result[0] is True) - self.assertTrue(result[1] == "output string") - - def test_explicit_overload_selection(self): - """Check explicit overload selection using [] syntax.""" - from Python.Test import ISayHello1, InterfaceTest, ShortEnum - from System import Array - - inst = InterfaceTest() - - value = MethodTest.Overloaded.__overloads__[System.Boolean](True) - self.assertTrue(value is True) - - value = MethodTest.Overloaded.__overloads__[bool](True) - self.assertTrue(value is True) - - value = MethodTest.Overloaded.__overloads__[System.Byte](255) - self.assertTrue(value == 255) - - value = MethodTest.Overloaded.__overloads__[System.SByte](127) - self.assertTrue(value == 127) - - value = MethodTest.Overloaded.__overloads__[System.Char](u'A') - self.assertTrue(value == u'A') - - value = MethodTest.Overloaded.__overloads__[System.Char](65535) - self.assertTrue(value == unichr(65535)) - - value = MethodTest.Overloaded.__overloads__[System.Int16](32767) - self.assertTrue(value == 32767) - - value = MethodTest.Overloaded.__overloads__[System.Int32](2147483647) - self.assertTrue(value == 2147483647) - - value = MethodTest.Overloaded.__overloads__[int](2147483647) - self.assertTrue(value == 2147483647) - - value = MethodTest.Overloaded.__overloads__[System.Int64]( - long(9223372036854775807)) - self.assertTrue(value == long(9223372036854775807)) - # Python 3 has no explicit long type, use System.Int64 instead - if PY2: - value = MethodTest.Overloaded.__overloads__[long]( - long(9223372036854775807)) - self.assertTrue(value == long(9223372036854775807)) +def test_subclass_instance_conversion(): + """Test subclass instance conversion in method call.""" - value = MethodTest.Overloaded.__overloads__[System.UInt16](65000) - self.assertTrue(value == 65000) + class TestSubException(System.Exception): + pass - value = MethodTest.Overloaded.__overloads__[System.UInt32]( - long(4294967295)) - self.assertTrue(value == long(4294967295)) + ob = MethodTest() + instance = TestSubException() + result = ob.TestSubclassConversion(instance) + assert isinstance(result, System.Exception) - value = MethodTest.Overloaded.__overloads__[System.UInt64]( - long(18446744073709551615)) - self.assertTrue(value == long(18446744073709551615)) - value = MethodTest.Overloaded.__overloads__[System.Single](3.402823e38) - self.assertTrue(value == 3.402823e38) +def test_null_array_conversion(): + """Test null array conversion in method call.""" + ob = MethodTest() + r = ob.TestNullArrayConversion(None) + assert r is None - value = MethodTest.Overloaded.__overloads__[System.Double]( - 1.7976931348623157e308) - self.assertTrue(value == 1.7976931348623157e308) - value = MethodTest.Overloaded.__overloads__[float]( - 1.7976931348623157e308) - self.assertTrue(value == 1.7976931348623157e308) +def test_string_params_args(): + """Test use of string params.""" + result = MethodTest.TestStringParamsArg('one', 'two', 'three') + assert result.Length == 3 + assert len(result) == 3, result + assert result[0] == 'one' + assert result[1] == 'two' + assert result[2] == 'three' - value = MethodTest.Overloaded.__overloads__[System.Decimal]( - System.Decimal.One) - self.assertTrue(value == System.Decimal.One) + result = MethodTest.TestStringParamsArg(['one', 'two', 'three']) + assert len(result) == 3 + assert result[0] == 'one' + assert result[1] == 'two' + assert result[2] == 'three' - value = MethodTest.Overloaded.__overloads__[System.String]("spam") - self.assertTrue(value == "spam") - value = MethodTest.Overloaded.__overloads__[str]("spam") - self.assertTrue(value == "spam") +def test_object_params_args(): + """Test use of object params.""" + result = MethodTest.TestObjectParamsArg('one', 'two', 'three') + assert len(result) == 3, result + assert result[0] == 'one' + assert result[1] == 'two' + assert result[2] == 'three' - value = MethodTest.Overloaded.__overloads__[ShortEnum](ShortEnum.Zero) - self.assertTrue(value == ShortEnum.Zero) + result = MethodTest.TestObjectParamsArg(['one', 'two', 'three']) + assert len(result) == 3, result + assert result[0] == 'one' + assert result[1] == 'two' + assert result[2] == 'three' + + +def test_value_params_args(): + """Test use of value type params.""" + result = MethodTest.TestValueParamsArg(1, 2, 3) + assert len(result) == 3 + assert result[0] == 1 + assert result[1] == 2 + assert result[2] == 3 + + result = MethodTest.TestValueParamsArg([1, 2, 3]) + assert len(result) == 3 + assert result[0] == 1 + assert result[1] == 2 + assert result[2] == 3 + + +def test_non_params_array_in_last_place(): + """Test overload resolution with of non-"params" array as + last parameter.""" + result = MethodTest.TestNonParamsArrayInLastPlace(1, 2, 3) + assert result + + +def test_string_out_params(): + """Test use of string out-parameters.""" + result = MethodTest.TestStringOutParams("hi", "there") + assert isinstance(result, tuple) + assert len(result) == 2 + assert result[0] is True + assert result[1] == "output string" + + result = MethodTest.TestStringOutParams("hi", None) + assert isinstance(result, tuple) + assert len(result) == 2 + assert result[0] is True + assert result[1] == "output string" + + +def test_string_ref_params(): + """Test use of string byref parameters.""" + result = MethodTest.TestStringRefParams("hi", "there") + assert isinstance(result, tuple) + assert len(result) == 2 + assert result[0] is True + assert result[1] == "output string" + + result = MethodTest.TestStringRefParams("hi", None) + assert isinstance(result, tuple) + assert len(result) == 2 + assert result[0] is True + assert result[1] == "output string" + + +def test_value_out_params(): + """Test use of value type out-parameters.""" + result = MethodTest.TestValueOutParams("hi", 1) + assert isinstance(result, tuple) + assert len(result) == 2 + assert result[0] is True + assert result[1] == 42 + + # None cannot be converted to a value type like int, long, etc. + with pytest.raises(TypeError): + MethodTest.TestValueOutParams("hi", None) + + +def test_value_ref_params(): + """Test use of value type byref parameters.""" + result = MethodTest.TestValueRefParams("hi", 1) + assert isinstance(result, tuple) + assert len(result) == 2 + assert result[0] is True + assert result[1] == 42 + + # None cannot be converted to a value type like int, long, etc. + with pytest.raises(TypeError): + MethodTest.TestValueRefParams("hi", None) + + +def test_object_out_params(): + """Test use of object out-parameters.""" + result = MethodTest.TestObjectOutParams("hi", MethodTest()) + assert isinstance(result, tuple) + assert len(result) == 2 + assert result[0] is True + assert isinstance(result[1], System.Exception) + + result = MethodTest.TestObjectOutParams("hi", None) + assert isinstance(result, tuple) + assert len(result) == 2 + assert result[0] is True + assert isinstance(result[1], System.Exception) + + +def test_object_ref_params(): + """Test use of object byref parameters.""" + result = MethodTest.TestObjectRefParams("hi", MethodTest()) + assert isinstance(result, tuple) + assert len(result) == 2 + assert result[0] is True + assert isinstance(result[1], System.Exception) + + result = MethodTest.TestObjectRefParams("hi", None) + assert isinstance(result, tuple) + assert len(result) == 2 + assert result[0] is True + assert isinstance(result[1], System.Exception) + + +def test_struct_out_params(): + """Test use of struct out-parameters.""" + result = MethodTest.TestStructOutParams("hi", System.Guid.NewGuid()) + assert isinstance(result, tuple) + assert len(result) == 2 + assert result[0] is True + assert isinstance(result[1], System.Guid) + + # None cannot be converted to a value type like a struct + with pytest.raises(TypeError): + MethodTest.TestValueRefParams("hi", None) + + +def test_struct_ref_params(): + """Test use of struct byref parameters.""" + result = MethodTest.TestStructRefParams("hi", System.Guid.NewGuid()) + assert isinstance(result, tuple) + assert len(result) == 2 + assert result[0] is True + assert isinstance(result[1], System.Guid) + + # None cannot be converted to a value type like a struct + with pytest.raises(TypeError): + MethodTest.TestValueRefParams("hi", None) + + +def test_void_single_out_param(): + """Test void method with single out-parameter.""" + result = MethodTest.TestVoidSingleOutParam(9) + assert result == 42 + + # None cannot be converted to a value type + with pytest.raises(TypeError): + MethodTest.TestVoidSingleOutParam(None) - value = MethodTest.Overloaded.__overloads__[System.Object](inst) - self.assertTrue(value.__class__ == inst.__class__) - value = MethodTest.Overloaded.__overloads__[InterfaceTest](inst) - self.assertTrue(value.__class__ == inst.__class__) +def test_void_single_ref_param(): + """Test void method with single ref-parameter.""" + result = MethodTest.TestVoidSingleRefParam(9) + assert result == 42 - value = MethodTest.Overloaded.__overloads__[ISayHello1](inst) - self.assertTrue(value.__class__ == inst.__class__) + # None cannot be converted to a value type + with pytest.raises(TypeError): + MethodTest.TestVoidSingleRefParam(None) - atype = Array[System.Object] - value = MethodTest.Overloaded.__overloads__[str, int, atype]( - "one", 1, atype([1, 2, 3])) - self.assertTrue(value == 3) - value = MethodTest.Overloaded.__overloads__[str, int]("one", 1) - self.assertTrue(value == 1) +def test_single_default_param(): + """Test void method with single ref-parameter.""" + result = MethodTest.TestSingleDefaultParam() + assert result == 5 - value = MethodTest.Overloaded.__overloads__[int, str](1, "one") - self.assertTrue(value == 1) - def test_overload_selection_with_array_types(self): - """Check overload selection using array types.""" - from Python.Test import ISayHello1, InterfaceTest, ShortEnum - from System import Array +def test_one_arg_and_two_default_param(): + """Test void method with single ref-parameter.""" + result = MethodTest.TestOneArgAndTwoDefaultParam(11) + assert result == 22 - inst = InterfaceTest() + result = MethodTest.TestOneArgAndTwoDefaultParam(15) + assert result == 26 - vtype = Array[System.Boolean] - input_ = vtype([True, True]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0] is True) - self.assertTrue(value[1] is True) + result = MethodTest.TestOneArgAndTwoDefaultParam(20) + assert result == 31 - vtype = Array[bool] - input_ = vtype([True, True]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0] is True) - self.assertTrue(value[1] is True) - vtype = Array[System.Byte] - input_ = vtype([0, 255]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0] == 0) - self.assertTrue(value[1] == 255) +def test_two_default_param(): + """Test void method with single ref-parameter.""" + result = MethodTest.TestTwoDefaultParam() + assert result == 11 - vtype = Array[System.SByte] - input_ = vtype([0, 127]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0] == 0) - self.assertTrue(value[1] == 127) - vtype = Array[System.Char] - input_ = vtype([u'A', u'Z']) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0] == u'A') - self.assertTrue(value[1] == u'Z') +def test_explicit_selection_with_out_modifier(): + """Check explicit overload selection with out modifiers.""" + refstr = System.String("").GetType().MakeByRefType() + result = MethodTest.TestStringOutParams.__overloads__[str, refstr]( + "hi", "there") + assert isinstance(result, tuple) + assert len(result) == 2 + assert result[0] is True + assert result[1] == "output string" - vtype = Array[System.Char] - input_ = vtype([0, 65535]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0] == unichr(0)) - self.assertTrue(value[1] == unichr(65535)) + result = MethodTest.TestStringOutParams.__overloads__[str, refstr]( + "hi", None) + assert isinstance(result, tuple) + assert len(result) == 2 + assert result[0] is True + assert result[1] == "output string" - vtype = Array[System.Int16] - input_ = vtype([0, 32767]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0] == 0) - self.assertTrue(value[1] == 32767) - vtype = Array[System.Int32] - input_ = vtype([0, 2147483647]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0] == 0) - self.assertTrue(value[1] == 2147483647) +def test_explicit_selection_with_ref_modifier(): + """Check explicit overload selection with ref modifiers.""" + refstr = System.String("").GetType().MakeByRefType() + result = MethodTest.TestStringRefParams.__overloads__[str, refstr]( + "hi", "there") + assert isinstance(result, tuple) + assert len(result) == 2 + assert result[0] is True + assert result[1] == "output string" - vtype = Array[int] - input_ = vtype([0, 2147483647]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0] == 0) - self.assertTrue(value[1] == 2147483647) + result = MethodTest.TestStringRefParams.__overloads__[str, refstr]( + "hi", None) + assert isinstance(result, tuple) + assert len(result) == 2 + assert result[0] is True + assert result[1] == "output string" + + +def test_explicit_overload_selection(): + """Check explicit overload selection using [] syntax.""" + from Python.Test import ISayHello1, InterfaceTest, ShortEnum + from System import Array + + inst = InterfaceTest() + + value = MethodTest.Overloaded.__overloads__[System.Boolean](True) + assert value is True + + value = MethodTest.Overloaded.__overloads__[bool](True) + assert value is True + + value = MethodTest.Overloaded.__overloads__[System.Byte](255) + assert value == 255 + + value = MethodTest.Overloaded.__overloads__[System.SByte](127) + assert value == 127 + + value = MethodTest.Overloaded.__overloads__[System.Char](u'A') + assert value == u'A' + + value = MethodTest.Overloaded.__overloads__[System.Char](65535) + assert value == unichr(65535) + + value = MethodTest.Overloaded.__overloads__[System.Int16](32767) + assert value == 32767 + + value = MethodTest.Overloaded.__overloads__[System.Int32](2147483647) + assert value == 2147483647 - vtype = Array[System.Int64] + value = MethodTest.Overloaded.__overloads__[int](2147483647) + assert value == 2147483647 + + value = MethodTest.Overloaded.__overloads__[System.Int64]( + long(9223372036854775807)) + assert value == long(9223372036854775807) + + # Python 3 has no explicit long type, use System.Int64 instead + if PY2: + value = MethodTest.Overloaded.__overloads__[long]( + long(9223372036854775807)) + assert value == long(9223372036854775807) + + value = MethodTest.Overloaded.__overloads__[System.UInt16](65000) + assert value == 65000 + + value = MethodTest.Overloaded.__overloads__[System.UInt32]( + long(4294967295)) + assert value == long(4294967295) + + value = MethodTest.Overloaded.__overloads__[System.UInt64]( + long(18446744073709551615)) + assert value == long(18446744073709551615) + + value = MethodTest.Overloaded.__overloads__[System.Single](3.402823e38) + assert value == 3.402823e38 + + value = MethodTest.Overloaded.__overloads__[System.Double]( + 1.7976931348623157e308) + assert value == 1.7976931348623157e308 + + value = MethodTest.Overloaded.__overloads__[float]( + 1.7976931348623157e308) + assert value == 1.7976931348623157e308 + + value = MethodTest.Overloaded.__overloads__[System.Decimal]( + System.Decimal.One) + assert value == System.Decimal.One + + value = MethodTest.Overloaded.__overloads__[System.String]("spam") + assert value == "spam" + + value = MethodTest.Overloaded.__overloads__[str]("spam") + assert value == "spam" + + value = MethodTest.Overloaded.__overloads__[ShortEnum](ShortEnum.Zero) + assert value == ShortEnum.Zero + + value = MethodTest.Overloaded.__overloads__[System.Object](inst) + assert value.__class__ == inst.__class__ + + value = MethodTest.Overloaded.__overloads__[InterfaceTest](inst) + assert value.__class__ == inst.__class__ + + value = MethodTest.Overloaded.__overloads__[ISayHello1](inst) + assert value.__class__ == inst.__class__ + + atype = Array[System.Object] + value = MethodTest.Overloaded.__overloads__[str, int, atype]( + "one", 1, atype([1, 2, 3])) + assert value == 3 + + value = MethodTest.Overloaded.__overloads__[str, int]("one", 1) + assert value == 1 + + value = MethodTest.Overloaded.__overloads__[int, str](1, "one") + assert value == 1 + + +def test_overload_selection_with_array_types(): + """Check overload selection using array types.""" + from Python.Test import ISayHello1, InterfaceTest, ShortEnum + from System import Array + + inst = InterfaceTest() + + vtype = Array[System.Boolean] + input_ = vtype([True, True]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0] is True + assert value[1] is True + + vtype = Array[bool] + input_ = vtype([True, True]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0] is True + assert value[1] is True + + vtype = Array[System.Byte] + input_ = vtype([0, 255]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0] == 0 + assert value[1] == 255 + + vtype = Array[System.SByte] + input_ = vtype([0, 127]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0] == 0 + assert value[1] == 127 + + vtype = Array[System.Char] + input_ = vtype([u'A', u'Z']) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0] == u'A' + assert value[1] == u'Z' + + vtype = Array[System.Char] + input_ = vtype([0, 65535]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0] == unichr(0) + assert value[1] == unichr(65535) + + vtype = Array[System.Int16] + input_ = vtype([0, 32767]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0] == 0 + assert value[1] == 32767 + + vtype = Array[System.Int32] + input_ = vtype([0, 2147483647]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0] == 0 + assert value[1] == 2147483647 + + vtype = Array[int] + input_ = vtype([0, 2147483647]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0] == 0 + assert value[1] == 2147483647 + + vtype = Array[System.Int64] + input_ = vtype([0, long(9223372036854775807)]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0] == 0 + assert value[1] == long(9223372036854775807) + + # Python 3 has no explicit long type, use System.Int64 instead + if PY2: + vtype = Array[long] input_ = vtype([0, long(9223372036854775807)]) value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0] == 0) - self.assertTrue(value[1] == long(9223372036854775807)) - - # Python 3 has no explicit long type, use System.Int64 instead - if PY2: - vtype = Array[long] - input_ = vtype([0, long(9223372036854775807)]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0] == 0) - self.assertTrue(value[1] == long(9223372036854775807)) - - vtype = Array[System.UInt16] - input_ = vtype([0, 65000]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0] == 0) - self.assertTrue(value[1] == 65000) + assert value[0] == 0 + assert value[1] == long(9223372036854775807) + + vtype = Array[System.UInt16] + input_ = vtype([0, 65000]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0] == 0 + assert value[1] == 65000 + + vtype = Array[System.UInt32] + input_ = vtype([0, long(4294967295)]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0] == 0 + assert value[1] == long(4294967295) + + vtype = Array[System.UInt64] + input_ = vtype([0, long(18446744073709551615)]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0] == 0 + assert value[1] == long(18446744073709551615) + + vtype = Array[System.Single] + input_ = vtype([0.0, 3.402823e38]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0] == 0.0 + assert value[1] == 3.402823e38 + + vtype = Array[System.Double] + input_ = vtype([0.0, 1.7976931348623157e308]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0] == 0.0 + assert value[1] == 1.7976931348623157e308 + + vtype = Array[float] + input_ = vtype([0.0, 1.7976931348623157e308]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0] == 0.0 + assert value[1] == 1.7976931348623157e308 + + vtype = Array[System.Decimal] + input_ = vtype([System.Decimal.Zero, System.Decimal.One]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0] == System.Decimal.Zero + assert value[1] == System.Decimal.One + + vtype = Array[System.String] + input_ = vtype(["one", "two"]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0] == "one" + assert value[1] == "two" + + vtype = Array[str] + input_ = vtype(["one", "two"]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0] == "one" + assert value[1] == "two" + + vtype = Array[ShortEnum] + input_ = vtype([ShortEnum.Zero, ShortEnum.One]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0] == ShortEnum.Zero + assert value[1] == ShortEnum.One + + vtype = Array[System.Object] + input_ = vtype([inst, inst]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0].__class__ == inst.__class__ + assert value[1].__class__ == inst.__class__ + + vtype = Array[InterfaceTest] + input_ = vtype([inst, inst]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0].__class__ == inst.__class__ + assert value[1].__class__ == inst.__class__ - vtype = Array[System.UInt32] - input_ = vtype([0, long(4294967295)]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0] == 0) - self.assertTrue(value[1] == long(4294967295)) + vtype = Array[ISayHello1] + input_ = vtype([inst, inst]) + value = MethodTest.Overloaded.__overloads__[vtype](input_) + assert value[0].__class__ == inst.__class__ + assert value[1].__class__ == inst.__class__ - vtype = Array[System.UInt64] - input_ = vtype([0, long(18446744073709551615)]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0] == 0) - self.assertTrue(value[1] == long(18446744073709551615)) - vtype = Array[System.Single] - input_ = vtype([0.0, 3.402823e38]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0] == 0.0) - self.assertTrue(value[1] == 3.402823e38) +def test_explicit_overload_selection_failure(): + """Check that overload selection fails correctly.""" - vtype = Array[System.Double] - input_ = vtype([0.0, 1.7976931348623157e308]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0] == 0.0) - self.assertTrue(value[1] == 1.7976931348623157e308) + with pytest.raises(TypeError): + _ = MethodTest.Overloaded.__overloads__[System.Type](True) - vtype = Array[float] - input_ = vtype([0.0, 1.7976931348623157e308]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0] == 0.0) - self.assertTrue(value[1] == 1.7976931348623157e308) + with pytest.raises(TypeError): + _ = MethodTest.Overloaded.__overloads__[int, int](1, 1) - vtype = Array[System.Decimal] - input_ = vtype([System.Decimal.Zero, System.Decimal.One]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0] == System.Decimal.Zero) - self.assertTrue(value[1] == System.Decimal.One) + with pytest.raises(TypeError): + _ = MethodTest.Overloaded.__overloads__[str, int, int]("", 1, 1) - vtype = Array[System.String] - input_ = vtype(["one", "two"]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0] == "one") - self.assertTrue(value[1] == "two") + with pytest.raises(TypeError): + _ = MethodTest.Overloaded.__overloads__[int, long](1) - vtype = Array[str] - input_ = vtype(["one", "two"]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0] == "one") - self.assertTrue(value[1] == "two") - vtype = Array[ShortEnum] - input_ = vtype([ShortEnum.Zero, ShortEnum.One]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0] == ShortEnum.Zero) - self.assertTrue(value[1] == ShortEnum.One) +def test_we_can_bind_to_encoding_get_string(): + """Check that we can bind to the Encoding.GetString method + with variables.""" + from System.Text import Encoding + from System.IO import MemoryStream - vtype = Array[System.Object] - input_ = vtype([inst, inst]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0].__class__ == inst.__class__) - self.assertTrue(value[1].__class__ == inst.__class__) + my_bytes = Encoding.UTF8.GetBytes('Some testing string') + stream = MemoryStream() + stream.Write(my_bytes, 0, my_bytes.Length) + stream.Position = 0 - vtype = Array[InterfaceTest] - input_ = vtype([inst, inst]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0].__class__ == inst.__class__) - self.assertTrue(value[1].__class__ == inst.__class__) + buff = System.Array.CreateInstance(System.Byte, 3) + buff.Initialize() + data = [] + read = 1 - vtype = Array[ISayHello1] - input_ = vtype([inst, inst]) - value = MethodTest.Overloaded.__overloads__[vtype](input_) - self.assertTrue(value[0].__class__ == inst.__class__) - self.assertTrue(value[1].__class__ == inst.__class__) + while read > 0: + read, _ = stream.Read(buff, 0, buff.Length) + temp = Encoding.UTF8.GetString(buff, 0, read) + data.append(temp) + + data = ''.join(data) + assert data == 'Some testing string' + + +def test_wrong_overload(): + """Test regression in which implicit conversion caused the wrong types + to be used. See #131 for issue. Fixed by #137, #151""" + + # Used to return `50L` + res = System.Math.Abs(50.5) + assert res == 50.5 + assert type(res) == float + + res = System.Math.Abs(-50.5) + assert res == 50.5 + assert type(res) == float + + res = System.Math.Max(50.5, 50.1) + assert res == 50.5 + assert type(res) == float + + res = System.Math.Max(System.Double(10.5), System.Double(50.5)) + assert res == 50.5 + assert type(res) == float # Should it return a System.Double? + + res = System.Math.Max(System.Double(50.5), 50.1) + assert res == 50.5 + assert type(res) == float + + +def test_no_object_in_param(): + """Test that fix for #203 doesn't break behavior w/ no object overload""" + + res = MethodTest.TestOverloadedNoObject(5) + assert res == "Got int" + + with pytest.raises(TypeError): + MethodTest.TestOverloadedNoObject("test") + + +def test_object_in_param(): + """Test regression introduced by #151 in which Object method overloads + aren't being used. See #203 for issue.""" + + res = MethodTest.TestOverloadedObject(5) + assert res == "Got int" + + res = MethodTest.TestOverloadedObject("test") + assert res == "Got object" + + +def test_object_in_multiparam(): + """Test method with object multiparams behaves""" + + res = MethodTest.TestOverloadedObjectTwo(5, 5) + assert res == "Got int-int" + + res = MethodTest.TestOverloadedObjectTwo(5, "foo") + assert res == "Got int-string" - def test_explicit_overload_selection_failure(self): - """Check that overload selection fails correctly.""" + res = MethodTest.TestOverloadedObjectTwo("foo", 7.24) + assert res == "Got string-object" - with self.assertRaises(TypeError): - _ = MethodTest.Overloaded.__overloads__[System.Type](True) + res = MethodTest.TestOverloadedObjectTwo("foo", "bar") + assert res == "Got string-string" - with self.assertRaises(TypeError): - _ = MethodTest.Overloaded.__overloads__[int, int](1, 1) + res = MethodTest.TestOverloadedObjectTwo("foo", 5) + assert res == "Got string-int" - with self.assertRaises(TypeError): - _ = MethodTest.Overloaded.__overloads__[str, int, int]("", 1, 1) + res = MethodTest.TestOverloadedObjectTwo(7.24, 7.24) + assert res == "Got object-object" - with self.assertRaises(TypeError): - _ = MethodTest.Overloaded.__overloads__[int, long](1) - def test_we_can_bind_to_encoding_get_string(self): - """Check that we can bind to the Encoding.GetString method - with variables.""" - from System.Text import Encoding - from System.IO import MemoryStream +def test_object_in_multiparam_exception(): + """Test method with object multiparams behaves""" - my_bytes = Encoding.UTF8.GetBytes('Some testing string') - stream = MemoryStream() - stream.Write(my_bytes, 0, my_bytes.Length) - stream.Position = 0 + with pytest.raises(TypeError): + MethodTest.TestOverloadedObjectThree("foo", "bar") - buff = System.Array.CreateInstance(System.Byte, 3) - buff.Initialize() - data = [] - read = 1 - while read > 0: - read, _ = stream.Read(buff, 0, buff.Length) - temp = Encoding.UTF8.GetString(buff, 0, read) - data.append(temp) +def test_case_sensitive(): + """Test that case-sensitivity is respected. GH#81""" - data = ''.join(data) - self.assertEqual(data, 'Some testing string') + res = MethodTest.CaseSensitive() + assert res == "CaseSensitive" + res = MethodTest.Casesensitive() + assert res == "Casesensitive" -def test_suite(): - return unittest.makeSuite(MethodTests) + with pytest.raises(AttributeError): + MethodTest.casesensitive() diff --git a/src/tests/test_module.py b/src/tests/test_module.py index 5ee8e6fc2..2255ea411 100644 --- a/src/tests/test_module.py +++ b/src/tests/test_module.py @@ -1,348 +1,369 @@ # -*- coding: utf-8 -*- +"""Test CLR modules and the CLR import hook.""" + import clr import time import types -import unittest import warnings from fnmatch import fnmatch -from _compat import ClassType, PY2, PY3, range -from utils import is_clr_class, is_clr_module, is_clr_root_module +import pytest + +from ._compat import ClassType, PY2, PY3, range +from .utils import is_clr_class, is_clr_module, is_clr_root_module # testImplicitAssemblyLoad() passes on deprecation warning; perfect! # # clr.AddReference('System.Windows.Forms') -class ModuleTests(unittest.TestCase): - """Test CLR modules and the CLR import hook.""" +def test_import_hook_works(): + """Test that the import hook works correctly both using the + included runtime and an external runtime. This must be + the first test run in the unit tests!""" + from System import String - def test_import_hook_works(self): - """Test that the import hook works correctly both using the - included runtime and an external runtime. This must be - the first test run in the unit tests!""" - from System import String - def test_import_clr(self): - import clr - self.assertTrue(is_clr_root_module(clr)) +def test_import_clr(): + import clr + assert is_clr_root_module(clr) - def test_version_clr(self): - import clr - self.assertTrue(clr.__version__ >= "2.2.0") - def test_preload_var(self): - import clr - self.assertTrue(clr.getPreload() is False, clr.getPreload()) +def test_version_clr(): + import clr + assert clr.__version__ >= "2.2.0" + + +def test_preload_var(): + import clr + assert clr.getPreload() is False, clr.getPreload() + clr.setPreload(False) + assert clr.getPreload() is False, clr.getPreload() + try: + clr.setPreload(True) + assert clr.getPreload() is True, clr.getPreload() + clr.setPreload(0) + assert clr.getPreload() is False, clr.getPreload() + clr.setPreload(1) + assert clr.getPreload() is True, clr.getPreload() + + import System.Configuration + content = dir(System.Configuration) + assert len(content) > 10, content + finally: clr.setPreload(False) - self.assertTrue(clr.getPreload() is False, clr.getPreload()) - try: - clr.setPreload(True) - self.assertTrue(clr.getPreload() is True, clr.getPreload()) - clr.setPreload(0) - self.assertTrue(clr.getPreload() is False, clr.getPreload()) - clr.setPreload(1) - self.assertTrue(clr.getPreload() is True, clr.getPreload()) - - import System.Configuration - content = dir(System.Configuration) - self.assertTrue(len(content) > 10, content) - finally: - clr.setPreload(False) - - def test_module_interface(self): - """Test the interface exposed by CLR module objects.""" - 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, 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(is_clr_class(System.String)) - self.assertTrue(is_clr_class(System.Int32)) - - def test_simple_import(self): - """Test simple import.""" - import System - self.assertTrue(is_clr_module(System)) - self.assertTrue(System.__name__ == 'System') - - import sys - self.assertTrue(isinstance(sys, types.ModuleType)) - self.assertTrue(sys.__name__ == 'sys') - - if PY3: - import http.client as httplib - self.assertTrue(isinstance(httplib, types.ModuleType)) - self.assertTrue(httplib.__name__ == 'http.client') - elif PY2: - import httplib - self.assertTrue(isinstance(httplib, types.ModuleType)) - self.assertTrue(httplib.__name__ == 'httplib') - - def test_simple_import_with_alias(self): - """Test simple import with aliasing.""" - import System as mySystem - self.assertTrue(is_clr_module(mySystem)) - self.assertTrue(mySystem.__name__ == 'System') - - import sys as mySys - self.assertTrue(isinstance(mySys, types.ModuleType)) - self.assertTrue(mySys.__name__ == 'sys') - - if PY3: - import http.client as myHttplib - self.assertTrue(isinstance(myHttplib, types.ModuleType)) - self.assertTrue(myHttplib.__name__ == 'http.client') - elif PY2: - import httplib as myHttplib - self.assertTrue(isinstance(myHttplib, types.ModuleType)) - self.assertTrue(myHttplib.__name__ == 'httplib') - - def test_dotted_name_import(self): - """Test dotted-name import.""" - import System.Reflection - self.assertTrue(is_clr_module(System.Reflection)) - self.assertTrue(System.Reflection.__name__ == 'System.Reflection') - - import xml.dom - self.assertTrue(isinstance(xml.dom, types.ModuleType)) - self.assertTrue(xml.dom.__name__ == 'xml.dom') - - def test_multiple_dotted_name_import(self): - """Test an import bug with multiple dotted imports.""" - import System.Data - self.assertTrue(is_clr_module(System.Data)) - self.assertTrue(System.Data.__name__ == 'System.Data') - import System.Data - self.assertTrue(is_clr_module(System.Data)) - self.assertTrue(System.Data.__name__ == 'System.Data') - - def test_dotted_name_import_with_alias(self): - """Test dotted-name import with aliasing.""" - import System.Reflection as SysRef - self.assertTrue(is_clr_module(SysRef)) - self.assertTrue(SysRef.__name__ == 'System.Reflection') - - import xml.dom as myDom - self.assertTrue(isinstance(myDom, types.ModuleType)) - self.assertTrue(myDom.__name__ == 'xml.dom') - - def test_simple_import_from(self): - """Test simple 'import from'.""" - from System import Reflection - self.assertTrue(is_clr_module(Reflection)) - self.assertTrue(Reflection.__name__ == 'System.Reflection') - - from xml import dom - self.assertTrue(isinstance(dom, types.ModuleType)) - self.assertTrue(dom.__name__ == 'xml.dom') - - def test_simple_import_from_with_alias(self): - """Test simple 'import from' with aliasing.""" - from System import Collections as Coll - self.assertTrue(is_clr_module(Coll)) - self.assertTrue(Coll.__name__ == 'System.Collections') - - from xml import dom as myDom - self.assertTrue(isinstance(myDom, types.ModuleType)) - self.assertTrue(myDom.__name__ == 'xml.dom') - - def test_dotted_name_import_from(self): - """Test dotted-name 'import from'.""" - from System.Collections import Specialized - self.assertTrue(is_clr_module(Specialized)) - self.assertTrue( - Specialized.__name__ == 'System.Collections.Specialized') - - from System.Collections.Specialized import StringCollection - self.assertTrue(is_clr_class(StringCollection)) - self.assertTrue(StringCollection.__name__ == 'StringCollection') - - from xml.dom import pulldom - self.assertTrue(isinstance(pulldom, types.ModuleType)) - self.assertTrue(pulldom.__name__ == 'xml.dom.pulldom') - - from xml.dom.pulldom import PullDOM - self.assertTrue(isinstance(PullDOM, ClassType)) - self.assertTrue(PullDOM.__name__ == 'PullDOM') - - def test_dotted_name_import_from_with_alias(self): - """Test dotted-name 'import from' with aliasing.""" - from System.Collections import Specialized as Spec - self.assertTrue(is_clr_module(Spec)) - self.assertTrue(Spec.__name__ == 'System.Collections.Specialized') - - from System.Collections.Specialized import StringCollection as SC - self.assertTrue(is_clr_class(SC)) - self.assertTrue(SC.__name__ == 'StringCollection') - - from xml.dom import pulldom as myPulldom - self.assertTrue(isinstance(myPulldom, types.ModuleType)) - self.assertTrue(myPulldom.__name__ == 'xml.dom.pulldom') - - from xml.dom.pulldom import PullDOM as myPullDOM - self.assertTrue(isinstance(myPullDOM, ClassType)) - self.assertTrue(myPullDOM.__name__ == 'PullDOM') - - def test_from_module_import_star(self): - """Test from module import * behavior.""" - count = len(locals().keys()) - m = __import__('System.Xml', globals(), locals(), ['*']) - self.assertTrue(m.__name__ == 'System.Xml') - self.assertTrue(is_clr_module(m)) - self.assertTrue(len(locals().keys()) > count + 1) - - def test_implicit_assembly_load(self): - """Test implicit assembly loading via import.""" - with warnings.catch_warnings(record=True) as w: - warnings.simplefilter("always") - - # should trigger a DeprecationWarning as Microsoft.Build hasn't - # been added as a reference yet (and should exist for mono) - import Microsoft.Build - - self.assertEqual(len(w), 1) - self.assertTrue(isinstance(w[0].message, DeprecationWarning)) - - with warnings.catch_warnings(record=True) as w: - clr.AddReference("System.Windows.Forms") - import System.Windows.Forms as Forms - self.assertTrue(is_clr_module(Forms)) - self.assertTrue(Forms.__name__ == 'System.Windows.Forms') - from System.Windows.Forms import Form - self.assertTrue(is_clr_class(Form)) - self.assertTrue(Form.__name__ == 'Form') - self.assertEqual(len(w), 0) - - def test_explicit_assembly_load(self): - """Test explicit assembly loading using standard CLR tools.""" - from System.Reflection import Assembly - import System, sys - - assembly = Assembly.LoadWithPartialName('System.Data') - self.assertTrue(assembly is not None) - - import System.Data - self.assertTrue('System.Data' in sys.modules) - - assembly = Assembly.LoadWithPartialName('SpamSpamSpamSpamEggsAndSpam') - self.assertTrue(assembly is None) - - def test_implicit_load_already_valid_namespace(self): - """Test implicit assembly load over an already valid namespace.""" - # In this case, the mscorlib assembly (loaded by default) defines - # a number of types in the System namespace. There is also a System - # assembly, which is _not_ loaded by default, which also contains - # types in the System namespace. The desired behavior is for the - # Python runtime to "do the right thing", allowing types from both - # assemblies to be found in the System module implicitly. - import System - self.assertTrue(is_clr_class(System.UriBuilder)) - def test_import_non_existant_module(self): - """Test import failure for a non-existent module.""" - with self.assertRaises(ImportError): - import System.SpamSpamSpam - def test_lookup_no_namespace_type(self): - """Test lookup of types without a qualified namespace.""" - import Python.Test - import clr - self.assertTrue(is_clr_class(clr.NoNamespaceType)) +def test_module_interface(): + """Test the interface exposed by CLR module objects.""" + import System + assert type(System.__dict__) == type({}) + assert System.__name__ == 'System' + # 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__ + assert fnmatch(system_file, "*System*.dll") or fnmatch(system_file, "*mscorlib.dll"), \ + "unexpected System.__file__: " + system_file + assert System.__doc__.startswith("Namespace containing types from the following assemblies:") + assert is_clr_class(System.String) + assert is_clr_class(System.Int32) + + +def test_simple_import(): + """Test simple import.""" + import System + assert is_clr_module(System) + assert System.__name__ == 'System' + + import sys + assert isinstance(sys, types.ModuleType) + assert sys.__name__ == 'sys' + + if PY3: + import http.client as httplib + assert isinstance(httplib, types.ModuleType) + assert httplib.__name__ == 'http.client' + elif PY2: + import httplib + assert isinstance(httplib, types.ModuleType) + assert httplib.__name__ == 'httplib' + + +def test_simple_import_with_alias(): + """Test simple import with aliasing.""" + import System as mySystem + assert is_clr_module(mySystem) + assert mySystem.__name__ == 'System' + + import sys as mySys + assert isinstance(mySys, types.ModuleType) + assert mySys.__name__ == 'sys' + + if PY3: + import http.client as myHttplib + assert isinstance(myHttplib, types.ModuleType) + assert myHttplib.__name__ == 'http.client' + elif PY2: + import httplib as myHttplib + assert isinstance(myHttplib, types.ModuleType) + assert myHttplib.__name__ == 'httplib' + + +def test_dotted_name_import(): + """Test dotted-name import.""" + import System.Reflection + assert is_clr_module(System.Reflection) + assert System.Reflection.__name__ == 'System.Reflection' + + import xml.dom + assert isinstance(xml.dom, types.ModuleType) + assert xml.dom.__name__ == 'xml.dom' + + +def test_multiple_dotted_name_import(): + """Test an import bug with multiple dotted imports.""" + import System.Data + assert is_clr_module(System.Data) + assert System.Data.__name__ == 'System.Data' + import System.Data + assert is_clr_module(System.Data) + assert System.Data.__name__ == 'System.Data' + + +def test_dotted_name_import_with_alias(): + """Test dotted-name import with aliasing.""" + import System.Reflection as SysRef + assert is_clr_module(SysRef) + assert SysRef.__name__ == 'System.Reflection' + + import xml.dom as myDom + assert isinstance(myDom, types.ModuleType) + assert myDom.__name__ == 'xml.dom' + + +def test_simple_import_from(): + """Test simple 'import from'.""" + from System import Reflection + assert is_clr_module(Reflection) + assert Reflection.__name__ == 'System.Reflection' + + from xml import dom + assert isinstance(dom, types.ModuleType) + assert dom.__name__ == 'xml.dom' + + +def test_simple_import_from_with_alias(): + """Test simple 'import from' with aliasing.""" + from System import Collections as Coll + assert is_clr_module(Coll) + assert Coll.__name__ == 'System.Collections' + + from xml import dom as myDom + assert isinstance(myDom, types.ModuleType) + assert myDom.__name__ == 'xml.dom' + + +def test_dotted_name_import_from(): + """Test dotted-name 'import from'.""" + from System.Collections import Specialized + assert is_clr_module(Specialized) + assert Specialized.__name__ == 'System.Collections.Specialized' + + from System.Collections.Specialized import StringCollection + assert is_clr_class(StringCollection) + assert StringCollection.__name__ == 'StringCollection' + + from xml.dom import pulldom + assert isinstance(pulldom, types.ModuleType) + assert pulldom.__name__ == 'xml.dom.pulldom' + + from xml.dom.pulldom import PullDOM + assert isinstance(PullDOM, ClassType) + assert PullDOM.__name__ == 'PullDOM' + + +def test_dotted_name_import_from_with_alias(): + """Test dotted-name 'import from' with aliasing.""" + from System.Collections import Specialized as Spec + assert is_clr_module(Spec) + assert Spec.__name__ == 'System.Collections.Specialized' + + from System.Collections.Specialized import StringCollection as SC + assert is_clr_class(SC) + assert SC.__name__ == 'StringCollection' + + from xml.dom import pulldom as myPulldom + assert isinstance(myPulldom, types.ModuleType) + assert myPulldom.__name__ == 'xml.dom.pulldom' + + from xml.dom.pulldom import PullDOM as myPullDOM + assert isinstance(myPullDOM, ClassType) + assert myPullDOM.__name__ == 'PullDOM' + + +def test_from_module_import_star(): + """Test from module import * behavior.""" + count = len(locals().keys()) + m = __import__('System.Xml', globals(), locals(), ['*']) + assert m.__name__ == 'System.Xml' + assert is_clr_module(m) + assert len(locals().keys()) > count + 1 + + +def test_implicit_assembly_load(): + """Test implicit assembly loading via import.""" + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + + # should trigger a DeprecationWarning as Microsoft.Build hasn't + # been added as a reference yet (and should exist for mono) + import Microsoft.Build + + assert len(w) == 1 + assert isinstance(w[0].message, DeprecationWarning) + + with warnings.catch_warnings(record=True) as w: + clr.AddReference("System.Windows.Forms") + import System.Windows.Forms as Forms + assert is_clr_module(Forms) + assert Forms.__name__ == 'System.Windows.Forms' + from System.Windows.Forms import Form + assert is_clr_class(Form) + assert Form.__name__ == 'Form' + assert len(w) == 0 - def test_module_lookup_recursion(self): - """Test for recursive lookup handling.""" - with self.assertRaises(ImportError): - from System import System +def test_explicit_assembly_load(): + """Test explicit assembly loading using standard CLR tools.""" + from System.Reflection import Assembly + import System, sys - with self.assertRaises(AttributeError): - import System - _ = System.System + assembly = Assembly.LoadWithPartialName('System.Data') + assert assembly is not None - def test_module_get_attr(self): - """Test module getattr behavior.""" + import System.Data + assert 'System.Data' in sys.modules + + assembly = Assembly.LoadWithPartialName('SpamSpamSpamSpamEggsAndSpam') + assert assembly is None + + +def test_implicit_load_already_valid_namespace(): + """Test implicit assembly load over an already valid namespace.""" + # In this case, the mscorlib assembly (loaded by default) defines + # a number of types in the System namespace. There is also a System + # assembly, which is _not_ loaded by default, which also contains + # types in the System namespace. The desired behavior is for the + # Python runtime to "do the right thing", allowing types from both + # assemblies to be found in the System module implicitly. + import System + assert is_clr_class(System.UriBuilder) + + +def test_import_non_existant_module(): + """Test import failure for a non-existent module.""" + with pytest.raises(ImportError): + import System.SpamSpamSpam + + +def test_lookup_no_namespace_type(): + """Test lookup of types without a qualified namespace.""" + import Python.Test + import clr + assert is_clr_class(clr.NoNamespaceType) + + +def test_module_lookup_recursion(): + """Test for recursive lookup handling.""" + + with pytest.raises(ImportError): + from System import System + + with pytest.raises(AttributeError): import System + _ = System.System + - int_type = System.Int32 - self.assertTrue(is_clr_class(int_type)) +def test_module_get_attr(): + """Test module getattr behavior.""" + import System - module = System.Xml - self.assertTrue(is_clr_module(module)) + int_type = System.Int32 + assert is_clr_class(int_type) - with self.assertRaises(AttributeError): - _ = System.Spam + module = System.Xml + assert is_clr_module(module) - with self.assertRaises(TypeError): - _ = getattr(System, 1) + with pytest.raises(AttributeError): + _ = System.Spam - def test_module_attr_abuse(self): - """Test handling of attempts to set module attributes.""" + with pytest.raises(TypeError): + _ = getattr(System, 1) - # It would be safer to use a dict-proxy as the __dict__ for CLR - # modules, but as of Python 2.3 some parts of the CPython runtime - # like dir() will fail if a module dict is not a real dictionary. - def test(): - import System - System.__dict__['foo'] = 0 - return 1 +def test_module_attr_abuse(): + """Test handling of attempts to set module attributes.""" - self.assertTrue(test()) + # It would be safer to use a dict-proxy as the __dict__ for CLR + # modules, but as of Python 2.3 some parts of the CPython runtime + # like dir() will fail if a module dict is not a real dictionary. - def test_module_type_abuse(self): - """Test handling of attempts to break the module type.""" + def test(): import System - mtype = type(System) - - with self.assertRaises(TypeError): - mtype.__getattribute__(0, 'spam') - - with self.assertRaises(TypeError): - mtype.__setattr__(0, 'spam', 1) - - with self.assertRaises(TypeError): - mtype.__repr__(0) - - def test_clr_list_assemblies(self): - from clr import ListAssemblies - verbose = list(ListAssemblies(True)) - short = list(ListAssemblies(False)) - self.assertTrue(u'mscorlib' in short) - self.assertTrue(u'System' in short) - self.assertTrue(u'Culture=' in verbose[0]) - self.assertTrue(u'Version=' in verbose[0]) - - def test_clr_add_reference(self): - from clr import AddReference - from System.IO import FileNotFoundException - for name in ("System", "Python.Runtime"): - assy = AddReference(name) - assy_name = assy.GetName().Name - self.assertEqual(assy_name, name) - - with self.assertRaises(FileNotFoundException): - AddReference("somethingtotallysilly") - - def test_assembly_load_thread_safety(self): - from Python.Test import ModuleTest - # spin up .NET thread which loads assemblies and triggers AppDomain.AssemblyLoad event - ModuleTest.RunThreads() - time.sleep(1e-5) - for _ 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 - _ = Dictionary[Guid, DateTime]() - ModuleTest.JoinThreads() - - -def test_suite(): - return unittest.makeSuite(ModuleTests) + System.__dict__['foo'] = 0 + return 1 + + assert test() + + +def test_module_type_abuse(): + """Test handling of attempts to break the module type.""" + import System + mtype = type(System) + + with pytest.raises(TypeError): + mtype.__getattribute__(0, 'spam') + + with pytest.raises(TypeError): + mtype.__setattr__(0, 'spam', 1) + + with pytest.raises(TypeError): + mtype.__repr__(0) + + +def test_clr_list_assemblies(): + from clr import ListAssemblies + verbose = list(ListAssemblies(True)) + short = list(ListAssemblies(False)) + assert u'mscorlib' in short + assert u'System' in short + assert u'Culture=' in verbose[0] + assert u'Version=' in verbose[0] + + +def test_clr_add_reference(): + from clr import AddReference + from System.IO import FileNotFoundException + for name in ("System", "Python.Runtime"): + assy = AddReference(name) + assy_name = assy.GetName().Name + assert assy_name == name + + with pytest.raises(FileNotFoundException): + AddReference("somethingtotallysilly") + + +def test_assembly_load_thread_safety(): + from Python.Test import ModuleTest + # spin up .NET thread which loads assemblies and triggers AppDomain.AssemblyLoad event + ModuleTest.RunThreads() + time.sleep(1e-5) + for _ 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 + _ = Dictionary[Guid, DateTime]() + ModuleTest.JoinThreads() diff --git a/src/tests/test_property.py b/src/tests/test_property.py index 8fb37768a..4dc8ea111 100644 --- a/src/tests/test_property.py +++ b/src/tests/test_property.py @@ -1,145 +1,148 @@ # -*- coding: utf-8 -*- -import unittest +"""Test CLR property support.""" +import pytest from Python.Test import PropertyTest -class PropertyTests(unittest.TestCase): - """Test CLR property support.""" +def test_public_instance_property(): + """Test public instance properties.""" + ob = PropertyTest() - def test_public_instance_property(self): - """Test public instance properties.""" - ob = PropertyTest() + assert ob.PublicProperty == 0 + ob.PublicProperty = 1 + assert ob.PublicProperty == 1 - self.assertTrue(ob.PublicProperty == 0) - ob.PublicProperty = 1 - self.assertTrue(ob.PublicProperty == 1) + with pytest.raises(TypeError): + del PropertyTest().PublicProperty - with self.assertRaises(TypeError): - del PropertyTest().PublicProperty - def test_public_static_property(self): - """Test public static properties.""" - ob = PropertyTest() +def test_public_static_property(): + """Test public static properties.""" + ob = PropertyTest() - self.assertTrue(PropertyTest.PublicStaticProperty == 0) - PropertyTest.PublicStaticProperty = 1 - self.assertTrue(PropertyTest.PublicStaticProperty == 1) + assert PropertyTest.PublicStaticProperty == 0 + PropertyTest.PublicStaticProperty = 1 + assert PropertyTest.PublicStaticProperty == 1 - self.assertTrue(ob.PublicStaticProperty == 1) - ob.PublicStaticProperty = 0 - self.assertTrue(ob.PublicStaticProperty == 0) + assert ob.PublicStaticProperty == 1 + ob.PublicStaticProperty = 0 + assert ob.PublicStaticProperty == 0 - with self.assertRaises(TypeError): - del PropertyTest.PublicStaticProperty + with pytest.raises(TypeError): + del PropertyTest.PublicStaticProperty - with self.assertRaises(TypeError): - del PropertyTest().PublicStaticProperty + with pytest.raises(TypeError): + del PropertyTest().PublicStaticProperty - def test_protected_instance_property(self): - """Test protected instance properties.""" - ob = PropertyTest() - self.assertTrue(ob.ProtectedProperty == 0) - ob.ProtectedProperty = 1 - self.assertTrue(ob.ProtectedProperty == 1) +def test_protected_instance_property(): + """Test protected instance properties.""" + ob = PropertyTest() - with self.assertRaises(TypeError): - del PropertyTest().ProtectedProperty + assert ob.ProtectedProperty == 0 + ob.ProtectedProperty = 1 + assert ob.ProtectedProperty == 1 - def test_protected_static_property(self): - """Test protected static properties.""" - ob = PropertyTest() + with pytest.raises(TypeError): + del PropertyTest().ProtectedProperty - self.assertTrue(PropertyTest.ProtectedStaticProperty == 0) - PropertyTest.ProtectedStaticProperty = 1 - self.assertTrue(PropertyTest.ProtectedStaticProperty == 1) - self.assertTrue(ob.ProtectedStaticProperty == 1) - ob.ProtectedStaticProperty = 0 - self.assertTrue(ob.ProtectedStaticProperty == 0) +def test_protected_static_property(): + """Test protected static properties.""" + ob = PropertyTest() - with self.assertRaises(TypeError): - del PropertyTest.ProtectedStaticProperty + assert PropertyTest.ProtectedStaticProperty == 0 + PropertyTest.ProtectedStaticProperty = 1 + assert PropertyTest.ProtectedStaticProperty == 1 - with self.assertRaises(TypeError): - del PropertyTest().ProtectedStaticProperty + assert ob.ProtectedStaticProperty == 1 + ob.ProtectedStaticProperty = 0 + assert ob.ProtectedStaticProperty == 0 - def test_internal_property(self): - """Test internal properties.""" + with pytest.raises(TypeError): + del PropertyTest.ProtectedStaticProperty - with self.assertRaises(AttributeError): - _ = PropertyTest().InternalProperty + with pytest.raises(TypeError): + del PropertyTest().ProtectedStaticProperty - with self.assertRaises(AttributeError): - _ = PropertyTest().InternalStaticProperty - with self.assertRaises(AttributeError): - _ = PropertyTest.InternalStaticProperty +def test_internal_property(): + """Test internal properties.""" - def test_private_property(self): - """Test private properties.""" + with pytest.raises(AttributeError): + _ = PropertyTest().InternalProperty - with self.assertRaises(AttributeError): - _ = PropertyTest().PrivateProperty + with pytest.raises(AttributeError): + _ = PropertyTest().InternalStaticProperty - with self.assertRaises(AttributeError): - _ = PropertyTest().PrivateStaticProperty + with pytest.raises(AttributeError): + _ = PropertyTest.InternalStaticProperty - with self.assertRaises(AttributeError): - _ = PropertyTest.PrivateStaticProperty - def test_property_descriptor_get_set(self): - """Test property descriptor get / set.""" +def test_private_property(): + """Test private properties.""" - # This test ensures that setting an attribute implemented with - # a descriptor actually goes through the descriptor (rather than - # silently replacing the descriptor in the instance or type dict. + with pytest.raises(AttributeError): + _ = PropertyTest().PrivateProperty - ob = PropertyTest() + with pytest.raises(AttributeError): + _ = PropertyTest().PrivateStaticProperty + + with pytest.raises(AttributeError): + _ = PropertyTest.PrivateStaticProperty - self.assertTrue(PropertyTest.PublicStaticProperty == 0) - self.assertTrue(ob.PublicStaticProperty == 0) - descriptor = PropertyTest.__dict__['PublicStaticProperty'] - self.assertTrue(type(descriptor) != int) +def test_property_descriptor_get_set(): + """Test property descriptor get / set.""" - ob.PublicStaticProperty = 0 - descriptor = PropertyTest.__dict__['PublicStaticProperty'] - self.assertTrue(type(descriptor) != int) + # This test ensures that setting an attribute implemented with + # a descriptor actually goes through the descriptor (rather than + # silently replacing the descriptor in the instance or type dict. - PropertyTest.PublicStaticProperty = 0 - descriptor = PropertyTest.__dict__['PublicStaticProperty'] - self.assertTrue(type(descriptor) != int) + ob = PropertyTest() - def test_property_descriptor_wrong_type(self): - """Test setting a property using a value of the wrong type.""" + assert PropertyTest.PublicStaticProperty == 0 + assert ob.PublicStaticProperty == 0 - with self.assertRaises(TypeError): - ob = PropertyTest() - ob.PublicProperty = "spam" + descriptor = PropertyTest.__dict__['PublicStaticProperty'] + assert type(descriptor) != int + + ob.PublicStaticProperty = 0 + descriptor = PropertyTest.__dict__['PublicStaticProperty'] + assert type(descriptor) != int + + PropertyTest.PublicStaticProperty = 0 + descriptor = PropertyTest.__dict__['PublicStaticProperty'] + assert type(descriptor) != int + + +def test_property_descriptor_wrong_type(): + """Test setting a property using a value of the wrong type.""" + + with pytest.raises(TypeError): + ob = PropertyTest() + ob.PublicProperty = "spam" - def test_property_descriptor_abuse(self): - """Test property descriptor abuse.""" - desc = PropertyTest.__dict__['PublicProperty'] - with self.assertRaises(TypeError): - desc.__get__(0, 0) +def test_property_descriptor_abuse(): + """Test property descriptor abuse.""" + desc = PropertyTest.__dict__['PublicProperty'] - with self.assertRaises(TypeError): - desc.__set__(0, 0) + with pytest.raises(TypeError): + desc.__get__(0, 0) - def test_interface_property(self): - """Test properties of interfaces. Added after a bug report - that an IsAbstract check was inappropriate and prevented - use of properties when only the interface is known.""" - from System.Collections import Hashtable, ICollection + with pytest.raises(TypeError): + desc.__set__(0, 0) - mapping = Hashtable() - coll = ICollection(mapping) - self.assertTrue(coll.Count == 0) +def test_interface_property(): + """Test properties of interfaces. Added after a bug report + that an IsAbstract check was inappropriate and prevented + use of properties when only the interface is known.""" + from System.Collections import Hashtable, ICollection -def test_suite(): - return unittest.makeSuite(PropertyTests) + mapping = Hashtable() + coll = ICollection(mapping) + assert coll.Count == 0 diff --git a/src/tests/test_recursive_types.py b/src/tests/test_recursive_types.py new file mode 100644 index 000000000..ca4b871cf --- /dev/null +++ b/src/tests/test_recursive_types.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- + +"""Test if interop with recursive type inheritance works.""" + + +def test_recursive_type_creation(): + """Test that a recursive types don't crash with a + StackOverflowException""" + from Python.Test import RecursiveInheritance + + test_instance = RecursiveInheritance.SubClass() + test_instance.SomeMethod() diff --git a/src/tests/test_subclass.py b/src/tests/test_subclass.py index 34ec86d9a..8e862a56d 100644 --- a/src/tests/test_subclass.py +++ b/src/tests/test_subclass.py @@ -4,14 +4,15 @@ # both Linux and Windows # TODO: Remove delay of class creations. Adding SetUp/TearDown may help -import unittest +"""Test sub-classing managed types""" import System +import pytest from Python.Test import (IInterfaceTest, SubClassTest, EventArgsTest, FunctionsTest) from System.Collections.Generic import List -from _compat import range +from ._compat import range def interface_test_class_fixture(): @@ -84,113 +85,111 @@ def OnTestEvent(self, value): return DerivedEventTest -class SubClassTests(unittest.TestCase): - """Test sub-classing managed types""" - - @unittest.skip(reason="FIXME: test randomly pass/fails") - def test_base_class(self): - """Test base class managed type""" - ob = SubClassTest() - self.assertEqual(ob.foo(), "foo") - self.assertEqual(FunctionsTest.test_foo(ob), "foo") - self.assertEqual(ob.bar("bar", 2), "bar") - self.assertEqual(FunctionsTest.test_bar(ob, "bar", 2), "bar") - self.assertEqual(ob.not_overriden(), "not_overriden") - self.assertEqual(list(ob.return_list()), ["a", "b", "c"]) - self.assertEqual(list(SubClassTest.test_list(ob)), ["a", "b", "c"]) - - @unittest.skip(reason="FIXME: test randomly pass/fails") - def test_interface(self): - """Test python classes can derive from C# interfaces""" - InterfaceTestClass = interface_test_class_fixture() - ob = InterfaceTestClass() - self.assertEqual(ob.foo(), "InterfaceTestClass") - self.assertEqual(FunctionsTest.test_foo(ob), "InterfaceTestClass") - self.assertEqual(ob.bar("bar", 2), "bar/bar") - self.assertEqual(FunctionsTest.test_bar(ob, "bar", 2), "bar/bar") - - x = FunctionsTest.pass_through(ob) - self.assertEqual(id(x), id(ob)) - - @unittest.skip(reason="FIXME: test randomly pass/fails") - def test_derived_class(self): - """Test python class derived from managed type""" - DerivedClass = derived_class_fixture() - ob = DerivedClass() - self.assertEqual(ob.foo(), "DerivedClass") - self.assertEqual(ob.base_foo(), "foo") - self.assertEqual(ob.super_foo(), "foo") - self.assertEqual(FunctionsTest.test_foo(ob), "DerivedClass") - self.assertEqual(ob.bar("bar", 2), "bar_bar") - self.assertEqual(FunctionsTest.test_bar(ob, "bar", 2), "bar_bar") - self.assertEqual(ob.not_overriden(), "not_overriden") - self.assertEqual(list(ob.return_list()), ["A", "B", "C"]) - self.assertEqual(list(SubClassTest.test_list(ob)), ["A", "B", "C"]) - - x = FunctionsTest.pass_through(ob) - self.assertEqual(id(x), id(ob)) - - @unittest.skip(reason="FIXME: test randomly pass/fails") - def test_create_instance(self): - """Test derived instances can be created from managed code""" - DerivedClass = derived_class_fixture() - ob = FunctionsTest.create_instance(DerivedClass) - self.assertEqual(ob.foo(), "DerivedClass") - self.assertEqual(FunctionsTest.test_foo(ob), "DerivedClass") - self.assertEqual(ob.bar("bar", 2), "bar_bar") - self.assertEqual(FunctionsTest.test_bar(ob, "bar", 2), "bar_bar") - self.assertEqual(ob.not_overriden(), "not_overriden") - - x = FunctionsTest.pass_through(ob) - self.assertEqual(id(x), id(ob)) - - InterfaceTestClass = interface_test_class_fixture() - ob2 = FunctionsTest.create_instance(InterfaceTestClass) - self.assertEqual(ob2.foo(), "InterfaceTestClass") - self.assertEqual(FunctionsTest.test_foo(ob2), "InterfaceTestClass") - self.assertEqual(ob2.bar("bar", 2), "bar/bar") - self.assertEqual(FunctionsTest.test_bar(ob2, "bar", 2), "bar/bar") - - y = FunctionsTest.pass_through(ob2) - self.assertEqual(id(y), id(ob2)) - - @unittest.skip(reason="FIXME: test randomly pass/fails") - def test_events(self): - class EventHandler(object): - def handler(self, x, args): - self.value = args.value - - event_handler = EventHandler() - - x = SubClassTest() - x.TestEvent += event_handler.handler - self.assertEqual(FunctionsTest.test_event(x, 1), 1) - self.assertEqual(event_handler.value, 1) - - InterfaceTestClass = interface_test_class_fixture() - i = InterfaceTestClass() - with self.assertRaises(System.NotImplementedException): - FunctionsTest.test_event(i, 2) - - DerivedEventTest = derived_event_test_class_fixture() - d = DerivedEventTest() - d.add_TestEvent(event_handler.handler) - self.assertEqual(FunctionsTest.test_event(d, 3), 3) - self.assertEqual(event_handler.value, 3) - self.assertEqual(len(d.event_handlers), 1) - - def test_isinstance(self): - a = [str(x) for x in range(0, 1000)] - b = [System.String(x) for x in a] - - for x in a: - self.assertFalse(isinstance(x, System.Object)) - self.assertFalse(isinstance(x, System.String)) - - for x in b: - self.assertTrue(isinstance(x, System.Object)) - self.assertTrue(isinstance(x, System.String)) - - -def test_suite(): - return unittest.makeSuite(SubClassTests) +@pytest.mark.skip(reason="FIXME: test randomly pass/fails") +def test_base_class(): + """Test base class managed type""" + ob = SubClassTest() + assert ob.foo() == "foo" + assert FunctionsTest.test_foo(ob) == "foo" + assert ob.bar("bar", 2) == "bar" + assert FunctionsTest.test_bar(ob, "bar", 2) == "bar" + assert ob.not_overriden() == "not_overriden" + assert list(ob.return_list()) == ["a", "b", "c"] + assert list(SubClassTest.test_list(ob)) == ["a", "b", "c"] + + +@pytest.mark.skip(reason="FIXME: test randomly pass/fails") +def test_interface(): + """Test python classes can derive from C# interfaces""" + InterfaceTestClass = interface_test_class_fixture() + ob = InterfaceTestClass() + assert ob.foo() == "InterfaceTestClass" + assert FunctionsTest.test_foo(ob) == "InterfaceTestClass" + assert ob.bar("bar", 2) == "bar/bar" + assert FunctionsTest.test_bar(ob, "bar", 2) == "bar/bar" + + x = FunctionsTest.pass_through(ob) + assert id(x) == id(ob) + + +@pytest.mark.skip(reason="FIXME: test randomly pass/fails") +def test_derived_class(): + """Test python class derived from managed type""" + DerivedClass = derived_class_fixture() + ob = DerivedClass() + assert ob.foo() == "DerivedClass" + assert ob.base_foo() == "foo" + assert ob.super_foo() == "foo" + assert FunctionsTest.test_foo(ob) == "DerivedClass" + assert ob.bar("bar", 2) == "bar_bar" + assert FunctionsTest.test_bar(ob, "bar", 2) == "bar_bar" + assert ob.not_overriden() == "not_overriden" + assert list(ob.return_list()) == ["A", "B", "C"] + assert list(SubClassTest.test_list(ob)) == ["A", "B", "C"] + + x = FunctionsTest.pass_through(ob) + assert id(x) == id(ob) + + +@pytest.mark.skip(reason="FIXME: test randomly pass/fails") +def test_create_instance(): + """Test derived instances can be created from managed code""" + DerivedClass = derived_class_fixture() + ob = FunctionsTest.create_instance(DerivedClass) + assert ob.foo() == "DerivedClass" + assert FunctionsTest.test_foo(ob) == "DerivedClass" + assert ob.bar("bar", 2) == "bar_bar" + assert FunctionsTest.test_bar(ob, "bar", 2) == "bar_bar" + assert ob.not_overriden() == "not_overriden" + + x = FunctionsTest.pass_through(ob) + assert id(x) == id(ob) + + InterfaceTestClass = interface_test_class_fixture() + ob2 = FunctionsTest.create_instance(InterfaceTestClass) + assert ob2.foo() == "InterfaceTestClass" + assert FunctionsTest.test_foo(ob2) == "InterfaceTestClass" + assert ob2.bar("bar", 2) == "bar/bar" + assert FunctionsTest.test_bar(ob2, "bar", 2) == "bar/bar" + + y = FunctionsTest.pass_through(ob2) + assert id(y) == id(ob2) + + +@pytest.mark.skip(reason="FIXME: test randomly pass/fails") +def test_events(): + class EventHandler(object): + def handler(self, x, args): + self.value = args.value + + event_handler = EventHandler() + + x = SubClassTest() + x.TestEvent += event_handler.handler + assert FunctionsTest.test_event(x, 1) == 1 + assert event_handler.value == 1 + + InterfaceTestClass = interface_test_class_fixture() + i = InterfaceTestClass() + with pytest.raises(System.NotImplementedException): + FunctionsTest.test_event(i, 2) + + DerivedEventTest = derived_event_test_class_fixture() + d = DerivedEventTest() + d.add_TestEvent(event_handler.handler) + assert FunctionsTest.test_event(d, 3) == 3 + assert event_handler.value == 3 + assert len(d.event_handlers) == 1 + + +def test_isinstance_check(): + a = [str(x) for x in range(0, 1000)] + b = [System.String(x) for x in a] + + for x in a: + assert not isinstance(x, System.Object) + assert not isinstance(x, System.String) + + for x in b: + assert isinstance(x, System.Object) + assert isinstance(x, System.String) diff --git a/src/tests/test_suite/__init__.py b/src/tests/test_suite/__init__.py deleted file mode 100644 index ecc1c858f..000000000 --- a/src/tests/test_suite/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -# -*- coding: utf-8 -*- - -import unittest - -from .test_callback import test_suite as callback_tests -from .test_import import test_suite as import_tests -from .test_recursive_types import test_suite as recursive_types_tests - - -def test_suite(): - suite = unittest.TestSuite() - suite.addTests((import_tests(),)) - suite.addTests((callback_tests(),)) - suite.addTests((recursive_types_tests(),)) - return suite diff --git a/src/tests/test_suite/test_callback.py b/src/tests/test_suite/test_callback.py deleted file mode 100644 index 2cb234442..000000000 --- a/src/tests/test_suite/test_callback.py +++ /dev/null @@ -1,33 +0,0 @@ -# -*- coding: utf-8 -*- - -import unittest - - -def simpleDefaultArg(arg='test'): - return arg - - -class CallbackTests(unittest.TestCase): - """Test that callbacks from C# into python work.""" - - def test_default_for_null(self): - """Test that C# can use null for an optional python argument""" - from Python.Test import CallbackTest - - test_instance = CallbackTest() - ret_val = test_instance.Call_simpleDefaultArg_WithNull(__name__) - python_ret_val = simpleDefaultArg(None) - self.assertEquals(ret_val, python_ret_val) - - def test_default_for_none(self): - """Test that C# can use no argument for an optional python argument""" - from Python.Test import CallbackTest - - test_instance = CallbackTest() - ret_val = test_instance.Call_simpleDefaultArg_WithEmptyArgs(__name__) - python_ret_val = simpleDefaultArg() - self.assertEquals(ret_val, python_ret_val) - - -def test_suite(): - return unittest.makeSuite(CallbackTests) diff --git a/src/tests/test_suite/test_import.py b/src/tests/test_suite/test_import.py deleted file mode 100644 index 9bae9ca5f..000000000 --- a/src/tests/test_suite/test_import.py +++ /dev/null @@ -1,18 +0,0 @@ -# -*- coding: utf-8 -*- - -import unittest - - -class ImportTests(unittest.TestCase): - """Test the import statement.""" - - def test_relative_missing_import(self): - """Test that a relative missing import doesn't crash. - Some modules use this to check if a package is installed. - Relative import in the site-packages folder""" - with self.assertRaises(ImportError): - from . import _missing_import - - -def test_suite(): - return unittest.makeSuite(ImportTests) diff --git a/src/tests/test_suite/test_recursive_types.py b/src/tests/test_suite/test_recursive_types.py deleted file mode 100644 index a213937a5..000000000 --- a/src/tests/test_suite/test_recursive_types.py +++ /dev/null @@ -1,19 +0,0 @@ -# -*- coding: utf-8 -*- - -import unittest - - -class RecursiveTypesTests(unittest.TestCase): - """Test if interop with recursive type inheritance works.""" - - def test_recursive_type_creation(self): - """Test that a recursive types don't crash with a - StackOverflowException""" - from Python.Test import RecursiveInheritance - - test_instance = RecursiveInheritance.SubClass() - test_instance.SomeMethod() - - -def test_suite(): - return unittest.makeSuite(RecursiveTypesTests) diff --git a/src/tests/test_sysargv.py b/src/tests/test_sysargv.py index eefb4d341..d86aa1c1d 100644 --- a/src/tests/test_sysargv.py +++ b/src/tests/test_sysargv.py @@ -1,17 +1,18 @@ # -*- coding: utf-8 -*- -import unittest +"""Test sys.argv state.""" + import sys -class SysArgvTests(unittest.TestCase): - """Test sys.argv state.""" +from ._compat import check_output - def test_sys_argv_state(self): - """Test sys.argv state doesn't change after clr import.""" - argv = sys.argv - import clr - self.assertTrue(argv == sys.argv) +def test_sys_argv_state(filepath): + """Test sys.argv state doesn't change after clr import. + To better control the arguments being passed, test on a fresh python + instance with specific arguments""" -def test_suite(): - return unittest.makeSuite(SysArgvTests) + script = filepath("argv-fixture.py") + out = check_output([sys.executable, script, "foo", "bar"]) + assert "foo" in out + assert "bar" in out diff --git a/src/tests/test_thread.py b/src/tests/test_thread.py index 623be60a0..c62c15939 100644 --- a/src/tests/test_thread.py +++ b/src/tests/test_thread.py @@ -1,62 +1,58 @@ # -*- coding: utf-8 -*- +"""Test CLR bridge threading and GIL handling.""" + import threading import time -import unittest - -from _compat import range, thread -from utils import dprint - -class ThreadTests(unittest.TestCase): - """Test CLR bridge threading and GIL handling.""" +from ._compat import range, thread +from .utils import dprint - def test_simple_callback_to_python(self): - """Test a call to managed code that then calls back into Python.""" - from Python.Test import ThreadTest - dprint("thread %s SimpleCallBack" % thread.get_ident()) - result = ThreadTest.CallEchoString("spam") - self.assertTrue(result == "spam") - dprint("thread %s SimpleCallBack ret" % thread.get_ident()) +def test_simple_callback_to_python(): + """Test a call to managed code that then calls back into Python.""" + from Python.Test import ThreadTest - def test_double_callback_to_python(self): - """Test a call to managed code that then calls back into Python - that then calls managed code that then calls Python again.""" - from Python.Test import ThreadTest + dprint("thread %s SimpleCallBack" % thread.get_ident()) + result = ThreadTest.CallEchoString("spam") + assert result == "spam" + dprint("thread %s SimpleCallBack ret" % thread.get_ident()) - dprint("thread %s DoubleCallBack" % thread.get_ident()) - result = ThreadTest.CallEchoString2("spam") - self.assertTrue(result == "spam") - dprint("thread %s DoubleCallBack ret" % thread.get_ident()) - def test_python_thread_calls_to_clr(self): - """Test calls by Python-spawned threads into managed code.""" - # This test is very likely to hang if something is wrong ;) - import System +def test_double_callback_to_python(): + """Test a call to managed code that then calls back into Python + that then calls managed code that then calls Python again.""" + from Python.Test import ThreadTest - done = [] + dprint("thread %s DoubleCallBack" % thread.get_ident()) + result = ThreadTest.CallEchoString2("spam") + assert result == "spam" + dprint("thread %s DoubleCallBack ret" % thread.get_ident()) - def run_thread(): - for i in range(10): - time.sleep(0.1) - dprint("thread %s %d" % (thread.get_ident(), i)) - mstr = System.String("thread %s %d" % (thread.get_ident(), i)) - dprint(mstr.ToString()) - done.append(None) - dprint("thread %s %d done" % (thread.get_ident(), i)) - def start_threads(count): - for _ in range(count): - thread_ = threading.Thread(target=run_thread) - thread_.start() +def test_python_thread_calls_to_clr(): + """Test calls by Python-spawned threads into managed code.""" + # This test is very likely to hang if something is wrong ;) + import System - start_threads(5) + done = [] - while len(done) < 50: - dprint(len(done)) + def run_thread(): + for i in range(10): time.sleep(0.1) - - -def test_suite(): - return unittest.makeSuite(ThreadTests) + dprint("thread %s %d" % (thread.get_ident(), i)) + mstr = System.String("thread %s %d" % (thread.get_ident(), i)) + dprint(mstr.ToString()) + done.append(None) + dprint("thread %s %d done" % (thread.get_ident(), i)) + + def start_threads(count): + for _ in range(count): + thread_ = threading.Thread(target=run_thread) + thread_.start() + + start_threads(5) + + while len(done) < 50: + dprint(len(done)) + time.sleep(0.1) diff --git a/src/tests/tests.pyproj b/src/tests/tests.pyproj index 5d042249e..cefa0d05e 100644 --- a/src/tests/tests.pyproj +++ b/src/tests/tests.pyproj @@ -6,7 +6,7 @@ {250c535c-c060-4f0c-bd80-41f2bf373565} runtests.py - + ..\..\ . . {888888a0-9f3d-457c-b088-3a5042f75d52} @@ -27,17 +27,17 @@ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Python Tools\Microsoft.PythonTools.targets + + + - - - - + @@ -50,23 +50,20 @@ + + - - - - - + + - - - + diff --git a/src/tests/utils.py b/src/tests/utils.py index 6729d7b30..cacb015ec 100644 --- a/src/tests/utils.py +++ b/src/tests/utils.py @@ -7,7 +7,7 @@ from __future__ import print_function -from _compat import PY2, PY3 +from ._compat import PY2, PY3 def dprint(msg): diff --git a/tox.ini b/tox.ini index 1cc666ae3..3c9be5c63 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,4 @@ [tox] -skipsdist=True skip_missing_interpreters=True envlist = py27 @@ -7,36 +6,22 @@ envlist = py34 py35 py36 + py37 check [testenv] -recreate=True -basepython = - py27: {env:TOXPYTHON:python2.7} - py33: {env:TOXPYTHON:python3.3} - py34: {env:TOXPYTHON:python3.4} - py35: {env:TOXPYTHON:python3.5} - py36: {env:TOXPYTHON:python3.6} - check: python3.5 -setenv = - PYTHONUNBUFFERED=True - DISTUTILS_DEBUG= -passenv = - * +deps = + pytest commands = - python --version - python -c "import struct; print('ARCH: %d' % (struct.calcsize('P') * 8))" - python -c "import ctypes; print('UCS%d' % ctypes.sizeof(ctypes.c_wchar))" - python setup.py bdist_wheel - pip install --no-index --find-links=dist/ pythonnet - {posargs:python src\tests\runtests.py} + {posargs:py.test} [testenv:check] ignore_errors=True +skip_install=True +basepython=python3.5 deps = check-manifest flake8 commands = - check-manifest {toxinidir} flake8 src setup.py python setup.py check --strict --metadata