From d8b4e69f5990c6606d537d4ace8d4ca6aa581472 Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Sat, 29 Apr 2023 13:44:44 +0200 Subject: [PATCH 01/55] try to use a strategy in test snippet to include more jdk versions during testing. --- .azure/scripts/test.yml | 96 ++++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 45 deletions(-) diff --git a/.azure/scripts/test.yml b/.azure/scripts/test.yml index 3177c59ab..8d48c2b08 100644 --- a/.azure/scripts/test.yml +++ b/.azure/scripts/test.yml @@ -1,48 +1,54 @@ # This task tests individual platforms and versions +strategy: + matrix: + jdk_version: + - '8' + - '11' + steps: -- task: UsePythonVersion@0 - inputs: - versionSpec: '$(python.version)' - -- template: jdk.yml - parameters: - version: 11 - -- script: | - python setup.py build_ext --inplace - displayName: 'Build module' - -- script: | - pip install numpy jedi typing_extensions - python -c "import jpype" - displayName: 'Check module' - -- script: | - python setup.py test_java - pip install -r test-requirements.txt - displayName: 'Install test' - -- script: | - python -m pytest -v --junit-xml=build/test/test.xml test/jpypetest --checkjni - displayName: 'Test JDK 11' - condition: eq(variables['jpypetest.fast'], 'false') - -- script: | - python -m pytest -v --junit-xml=build/test/test.xml test/jpypetest --checkjni --fast - displayName: 'Test JDK 11 (fast)' - condition: eq(variables['jpypetest.fast'], 'true') - -# presence of jpype/ seems to confuse entry_points so `cd` elsewhere -- script: | - pip install . - mkdir empty - cd empty - python -m PyInstaller.utils.run_tests --include_only jpype._pyinstaller. - displayName: 'Test PyInstaller result' - -- task: PublishTestResults@2 - condition: succeededOrFailed() - inputs: - testResultsFiles: 'build/test/test.xml' - testRunTitle: 'Publish test results for Python $(python.version) with JDK 11' + - task: UsePythonVersion@0 + inputs: + versionSpec: '$(python.version)' + + - template: jdk.yml + parameters: + version: ${{ matrix.jdk_version }} + + - script: | + python setup.py build_ext --inplace + displayName: 'Build module' + + - script: | + pip install numpy jedi typing_extensions + python -c "import jpype" + displayName: 'Check module' + + - script: | + python setup.py test_java + pip install -r test-requirements.txt + displayName: 'Install test' + + - script: | + python -m pytest -v --junit-xml=build/test/test.xml test/jpypetest --checkjni + displayName: 'Test JDK ${{ matrix.jdk_version }}' + condition: eq(variables['jpypetest.fast'], 'false') + + - script: | + python -m pytest -v --junit-xml=build/test/test.xml test/jpypetest --checkjni --fast + displayName: 'Test JDK ${{ matrix.jdk_version }} (fast)' + condition: eq(variables['jpypetest.fast'], 'true') + + # presence of jpype/ seems to confuse entry_points so `cd` elsewhere + - script: | + pip install . + mkdir empty + cd empty + python -m PyInstaller.utils.run_tests --include_only jpype._pyinstaller. + displayName: 'Test PyInstaller result' + + - task: PublishTestResults@2 + condition: succeededOrFailed() + inputs: + testResultsFiles: 'build/test/test.xml' + testRunTitle: 'Publish test results for Python $(python.version) with JDK ${{ matrix.jdk_version }}' From b7b3b8eec20c670a2fa2c6a7cdf3685944850dbe Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Sat, 29 Apr 2023 14:15:15 +0200 Subject: [PATCH 02/55] try a mixture of jdk and python versions --- .azure/build.yml | 9 ++++ .azure/scripts/test.yml | 95 +++++++++++++++++++---------------------- 2 files changed, 53 insertions(+), 51 deletions(-) diff --git a/.azure/build.yml b/.azure/build.yml index 4b16e8e04..e4378b613 100644 --- a/.azure/build.yml +++ b/.azure/build.yml @@ -56,24 +56,31 @@ jobs: linux-3.8: imageName: "ubuntu-latest" python.version: '3.8' + jdk.version: '8' linux-3.9: imageName: "ubuntu-latest" python.version: '3.9' + jdk.version: '11' linux-3.10: imageName: "ubuntu-latest" python.version: '3.10' + jdk.version: '17' linux-3.11: imageName: "ubuntu-latest" python.version: '3.11' + jdk.version: '17' windows-3.7: imageName: "windows-2019" python.version: '3.7' + jdk.version: '8' windows-3.8: imageName: "windows-2019" python.version: '3.8' + jdk.version: '11' windows-3.9: imageName: "windows-2019" python.version: '3.9' + jdk.version: '17' #jpypetest.fast: 'true' windows-3.10: imageName: "windows-2019" @@ -81,9 +88,11 @@ jobs: windows-3.11: imageName: "windows-2019" python.version: '3.11' + jdk.version: '17' mac-3.9: imageName: "macos-11" python.version: '3.9' + jdk.version: '11' jpypetest.fast: 'true' pool: diff --git a/.azure/scripts/test.yml b/.azure/scripts/test.yml index 8d48c2b08..ed9af0c39 100644 --- a/.azure/scripts/test.yml +++ b/.azure/scripts/test.yml @@ -1,54 +1,47 @@ # This task tests individual platforms and versions -strategy: - matrix: - jdk_version: - - '8' - - '11' - steps: - - task: UsePythonVersion@0 - inputs: - versionSpec: '$(python.version)' - - - template: jdk.yml - parameters: - version: ${{ matrix.jdk_version }} - - - script: | - python setup.py build_ext --inplace - displayName: 'Build module' - - - script: | - pip install numpy jedi typing_extensions - python -c "import jpype" - displayName: 'Check module' - - - script: | - python setup.py test_java - pip install -r test-requirements.txt - displayName: 'Install test' - - - script: | - python -m pytest -v --junit-xml=build/test/test.xml test/jpypetest --checkjni - displayName: 'Test JDK ${{ matrix.jdk_version }}' - condition: eq(variables['jpypetest.fast'], 'false') - - - script: | - python -m pytest -v --junit-xml=build/test/test.xml test/jpypetest --checkjni --fast - displayName: 'Test JDK ${{ matrix.jdk_version }} (fast)' - condition: eq(variables['jpypetest.fast'], 'true') - - # presence of jpype/ seems to confuse entry_points so `cd` elsewhere - - script: | - pip install . - mkdir empty - cd empty - python -m PyInstaller.utils.run_tests --include_only jpype._pyinstaller. - displayName: 'Test PyInstaller result' - - - task: PublishTestResults@2 - condition: succeededOrFailed() - inputs: - testResultsFiles: 'build/test/test.xml' - testRunTitle: 'Publish test results for Python $(python.version) with JDK ${{ matrix.jdk_version }}' +- task: UsePythonVersion@0 + inputs: + versionSpec: '$(python.version)' +- task: UseJavaVersion@1 + inputs: + versionSpec: '$(jdk.version)' + +- script: | + python setup.py build_ext --inplace + displayName: 'Build module' + +- script: | + pip install numpy jedi typing_extensions + python -c "import jpype" + displayName: 'Check module' + +- script: | + python setup.py test_java + pip install -r test-requirements.txt + displayName: 'Install test' + +- script: | + python -m pytest -v --junit-xml=build/test/test.xml test/jpypetest --checkjni + displayName: 'Test JDK 11' + condition: eq(variables['jpypetest.fast'], 'false') + +- script: | + python -m pytest -v --junit-xml=build/test/test.xml test/jpypetest --checkjni --fast + displayName: 'Test JDK 11 (fast)' + condition: eq(variables['jpypetest.fast'], 'true') + +# presence of jpype/ seems to confuse entry_points so `cd` elsewhere +- script: | + pip install . + mkdir empty + cd empty + python -m PyInstaller.utils.run_tests --include_only jpype._pyinstaller. + displayName: 'Test PyInstaller result' + +- task: PublishTestResults@2 + condition: succeededOrFailed() + inputs: + testResultsFiles: 'build/test/test.xml' + testRunTitle: 'Publish test results for Python $(python.version) with JDK 11' From c86d99a35f2983c4c34140c4bb251e08420d5c49 Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Sat, 29 Apr 2023 14:27:40 +0200 Subject: [PATCH 03/55] try tool installer --- .azure/scripts/test.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.azure/scripts/test.yml b/.azure/scripts/test.yml index ed9af0c39..f534b81c3 100644 --- a/.azure/scripts/test.yml +++ b/.azure/scripts/test.yml @@ -3,10 +3,10 @@ steps: - task: UsePythonVersion@0 inputs: versionSpec: '$(python.version)' -- task: UseJavaVersion@1 +- task: ToolInstaller@1 inputs: - versionSpec: '$(jdk.version)' - + toolName: 'jdk' + version: '$(jdk.version)' - script: | python setup.py build_ext --inplace displayName: 'Build module' From 2b68c2a44214715e271b2f0e7cd3b159020b7a00 Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Sat, 29 Apr 2023 17:50:53 +0200 Subject: [PATCH 04/55] try JavaToolInstaller --- .azure/scripts/test.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.azure/scripts/test.yml b/.azure/scripts/test.yml index f534b81c3..0d55e1bb9 100644 --- a/.azure/scripts/test.yml +++ b/.azure/scripts/test.yml @@ -3,10 +3,13 @@ steps: - task: UsePythonVersion@0 inputs: versionSpec: '$(python.version)' -- task: ToolInstaller@1 + +- task: JavaToolInstaller@0 inputs: - toolName: 'jdk' - version: '$(jdk.version)' + versionSpec: '$(jdk.version)' + jdkArchitectureOption: 'x64' + jdkSourceOption: 'PreInstalled' + - script: | python setup.py build_ext --inplace displayName: 'Build module' From 62093dca14e51b98bfa55fd6800f205d260a2b37 Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Sat, 29 Apr 2023 18:04:55 +0200 Subject: [PATCH 05/55] use JavaToolInstaller in jdk.yml --- .azure/scripts/jdk.yml | 14 +++++--------- .azure/scripts/test.yml | 8 +++----- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/.azure/scripts/jdk.yml b/.azure/scripts/jdk.yml index d37fd5808..e8362b8aa 100644 --- a/.azure/scripts/jdk.yml +++ b/.azure/scripts/jdk.yml @@ -3,12 +3,8 @@ parameters: type: string default: 8 -steps: -- script: | - set v="##vso[task.setvariable variable=JAVA_HOME]%JAVA_HOME_${{parameters.version}}_X64%" - echo %v:"=% - condition: eq(variables['Agent.OS'], 'Windows_NT') - -- script: | - echo "##vso[task.setvariable variable=JAVA_HOME]$(JAVA_HOME_${{parameters.version}}_X64)" - condition: ne(variables['Agent.OS'], 'Windows_NT') +- task: JavaToolInstaller@0 + inputs: + versionSpec: '$(parameters.version)' + jdkArchitectureOption: 'x64' + jdkSourceOption: 'PreInstalled' diff --git a/.azure/scripts/test.yml b/.azure/scripts/test.yml index 0d55e1bb9..1820a34df 100644 --- a/.azure/scripts/test.yml +++ b/.azure/scripts/test.yml @@ -4,11 +4,9 @@ steps: inputs: versionSpec: '$(python.version)' -- task: JavaToolInstaller@0 - inputs: - versionSpec: '$(jdk.version)' - jdkArchitectureOption: 'x64' - jdkSourceOption: 'PreInstalled' +- template: jdk.yml + parameters: + version: '$(jdk.version)' - script: | python setup.py build_ext --inplace From 0ac018b14666f0a53b0a1efd14abdf1f79736f10 Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Sat, 29 Apr 2023 18:09:13 +0200 Subject: [PATCH 06/55] steps --- .azure/scripts/jdk.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.azure/scripts/jdk.yml b/.azure/scripts/jdk.yml index e8362b8aa..02581c40a 100644 --- a/.azure/scripts/jdk.yml +++ b/.azure/scripts/jdk.yml @@ -3,8 +3,9 @@ parameters: type: string default: 8 -- task: JavaToolInstaller@0 - inputs: - versionSpec: '$(parameters.version)' - jdkArchitectureOption: 'x64' - jdkSourceOption: 'PreInstalled' +steps: + - task: JavaToolInstaller@0 + inputs: + versionSpec: '$(parameters.version)' + jdkArchitectureOption: 'x64' + jdkSourceOption: 'PreInstalled' From c9025abda6ded82830446ee03a222f62fd402176 Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Sat, 29 Apr 2023 18:18:40 +0200 Subject: [PATCH 07/55] use another variable expansion technique --- .azure/scripts/jdk.yml | 2 +- .azure/scripts/test.yml | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.azure/scripts/jdk.yml b/.azure/scripts/jdk.yml index 02581c40a..7ffbe4d84 100644 --- a/.azure/scripts/jdk.yml +++ b/.azure/scripts/jdk.yml @@ -6,6 +6,6 @@ parameters: steps: - task: JavaToolInstaller@0 inputs: - versionSpec: '$(parameters.version)' + versionSpec: ${{ parameters.version }} jdkArchitectureOption: 'x64' jdkSourceOption: 'PreInstalled' diff --git a/.azure/scripts/test.yml b/.azure/scripts/test.yml index 1820a34df..d8f528f31 100644 --- a/.azure/scripts/test.yml +++ b/.azure/scripts/test.yml @@ -24,12 +24,12 @@ steps: - script: | python -m pytest -v --junit-xml=build/test/test.xml test/jpypetest --checkjni - displayName: 'Test JDK 11' + displayName: 'Test JDK $(jdk.version)' condition: eq(variables['jpypetest.fast'], 'false') - script: | python -m pytest -v --junit-xml=build/test/test.xml test/jpypetest --checkjni --fast - displayName: 'Test JDK 11 (fast)' + displayName: 'Test JDK $(jdk.version) (fast)' condition: eq(variables['jpypetest.fast'], 'true') # presence of jpype/ seems to confuse entry_points so `cd` elsewhere @@ -44,5 +44,4 @@ steps: condition: succeededOrFailed() inputs: testResultsFiles: 'build/test/test.xml' - testRunTitle: 'Publish test results for Python $(python.version) with JDK 11' - + testRunTitle: 'Publish test results for Python $(python.version) with JDK $(jdk.version)' From 8384638f1332533a9f9158d77a29791c49851580 Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Sat, 29 Apr 2023 18:33:06 +0200 Subject: [PATCH 08/55] add missing version --- .azure/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.azure/build.yml b/.azure/build.yml index e4378b613..93ff30401 100644 --- a/.azure/build.yml +++ b/.azure/build.yml @@ -53,6 +53,7 @@ jobs: linux-3.7: imageName: "ubuntu-latest" python.version: '3.7' + jdk.version: '8' linux-3.8: imageName: "ubuntu-latest" python.version: '3.8' From e5480b09fb9ee4a9a34cf493addef6fbcbeb6047 Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Sat, 29 Apr 2023 18:33:22 +0200 Subject: [PATCH 09/55] fix type --- .azure/scripts/jdk.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.azure/scripts/jdk.yml b/.azure/scripts/jdk.yml index 7ffbe4d84..614ae6b47 100644 --- a/.azure/scripts/jdk.yml +++ b/.azure/scripts/jdk.yml @@ -1,7 +1,7 @@ parameters: - name: version type: string - default: 8 + default: '8' steps: - task: JavaToolInstaller@0 From b711ae12312776ad8ba8cd760ccfc6314c8345f8 Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Sat, 29 Apr 2023 19:11:54 +0200 Subject: [PATCH 10/55] generate sane displayName --- .azure/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.azure/build.yml b/.azure/build.yml index 93ff30401..69998495c 100644 --- a/.azure/build.yml +++ b/.azure/build.yml @@ -54,6 +54,7 @@ jobs: imageName: "ubuntu-latest" python.version: '3.7' jdk.version: '8' + displayName: '${{ matrix.imageName }}-py-${{ matrix.python.version }}-JDK${{ matrix.jdk.version }}' linux-3.8: imageName: "ubuntu-latest" python.version: '3.8' From 12779374e0c0df2e528a2c49c7268ebf5bf7e42f Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Sat, 29 Apr 2023 19:17:19 +0200 Subject: [PATCH 11/55] revert --- .azure/build.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.azure/build.yml b/.azure/build.yml index 69998495c..93ff30401 100644 --- a/.azure/build.yml +++ b/.azure/build.yml @@ -54,7 +54,6 @@ jobs: imageName: "ubuntu-latest" python.version: '3.7' jdk.version: '8' - displayName: '${{ matrix.imageName }}-py-${{ matrix.python.version }}-JDK${{ matrix.jdk.version }}' linux-3.8: imageName: "ubuntu-latest" python.version: '3.8' From f6922035c9cd19b66b9d11dd8fe33aab024ac7eb Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Sat, 29 Apr 2023 19:18:50 +0200 Subject: [PATCH 12/55] missing vars. --- .azure/build.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.azure/build.yml b/.azure/build.yml index 93ff30401..518804206 100644 --- a/.azure/build.yml +++ b/.azure/build.yml @@ -86,6 +86,7 @@ jobs: windows-3.10: imageName: "windows-2019" python.version: '3.10' + jdk.version: '11' windows-3.11: imageName: "windows-2019" python.version: '3.11' @@ -93,7 +94,7 @@ jobs: mac-3.9: imageName: "macos-11" python.version: '3.9' - jdk.version: '11' + jdk.version: '17' jpypetest.fast: 'true' pool: From 283b39f608bed7a06e5ddce74693c7ed8c3b1272 Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Sat, 29 Apr 2023 13:34:44 +0200 Subject: [PATCH 13/55] added new jni versions ranged from 9 to 21 (from openjdk) --- native/jni_include/jni.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/native/jni_include/jni.h b/native/jni_include/jni.h index a380acf71..04e7dbfc6 100644 --- a/native/jni_include/jni.h +++ b/native/jni_include/jni.h @@ -1179,6 +1179,11 @@ JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* reserved); #define JNI_VERSION_1_6 0x00010006 #define JNI_VERSION_1_7 0x00010007 #define JNI_VERSION_1_8 0x00010008 +#define JNI_VERSION_9 0x00090000 +#define JNI_VERSION_10 0x000a0000 +#define JNI_VERSION_19 0x00130000 +#define JNI_VERSION_20 0x00140000 +#define JNI_VERSION_21 0x00150000 #define JNI_OK (0) /* no error */ #define JNI_ERR (-1) /* generic error */ From dcba813681a34584f567821f6d240af6fc9eaf45 Mon Sep 17 00:00:00 2001 From: Ken Dombeck Date: Mon, 3 Jun 2024 10:07:02 -0500 Subject: [PATCH 14/55] Fix misspelling in documentation --- doc/userguide.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/userguide.rst b/doc/userguide.rst index 3ab818d4c..abd9b17b8 100644 --- a/doc/userguide.rst +++ b/doc/userguide.rst @@ -8,7 +8,7 @@ JPype User Guide JPype Introduction ****************** JPype is a Python module to provide full access to Java from within Python. -Unlike Jython, JPype does not achive this by re-implementing Python, but +Unlike Jython, JPype does not achieve this by re-implementing Python, but instead by interfacing both virtual machines at the native level. This shared memory based approach achieves good computing performance, while providing the access to the entirety of CPython and Java libraries. From d487b32774805d14249a15fc030aeac148025b67 Mon Sep 17 00:00:00 2001 From: Karl Nelson Date: Sun, 16 Jun 2024 21:47:03 -0700 Subject: [PATCH 15/55] Changes for numpy 2.0 to fix test matrix. --- doc/CHANGELOG.rst | 5 ++ native/common/jp_convert.cpp | 76 ++++++++++++++++++++++++++ test/jpypetest/test_conversionInt.py | 4 +- test/jpypetest/test_conversionLong.py | 4 +- test/jpypetest/test_conversionShort.py | 4 +- test/jpypetest/test_jboolean.py | 4 +- test/jpypetest/test_jbyte.py | 4 +- test/jpypetest/test_jdouble.py | 16 +++++- test/jpypetest/test_jfloat.py | 16 +++++- 9 files changed, 119 insertions(+), 14 deletions(-) diff --git a/doc/CHANGELOG.rst b/doc/CHANGELOG.rst index 5848e7d66..217dd8320 100644 --- a/doc/CHANGELOG.rst +++ b/doc/CHANGELOG.rst @@ -19,6 +19,11 @@ Latest Changes: For editable installs, ``python setup.py --enable-tracing develop`` must now be done with ``python setup.py develop --enable-tracing``. + - Update for tests for numpy 2.0. + + - Support of np.float16 conversion with arrays. + + - **1.5.0 - 2023-04-03** - Support for Python 3.12 diff --git a/native/common/jp_convert.cpp b/native/common/jp_convert.cpp index 919417461..5d288e044 100644 --- a/native/common/jp_convert.cpp +++ b/native/common/jp_convert.cpp @@ -14,10 +14,61 @@ See NOTICE file for details. *****************************************************************************/ #include "jpype.h" +#include +#include namespace { +template +class Half +{ +public: + static jvalue convert(void* c) + { + uint16_t i = *(uint16_t*) c; + uint32_t sign = (i&0x8000)>>15; + uint32_t man = (i&0x7C00)>>10; + uint32_t frac = (i&0x03ff); + uint32_t k = sign<<31; + + if (man == 0) + { + // subnormal numbers + if (frac != 0) + { + frac = frac | (frac >> 1); + frac = frac | (frac >> 2); + frac = frac | (frac >> 4); + frac = frac | (frac >> 8); + int zeros = std::bitset<32>(~frac).count(); + man = 127-zeros+7; + man <<= 23; + frac <<= zeros-8; + frac &= 0x7fffff; + k |= man | frac; + } + } + else if (man < 31) + { + // normal numbers + man = man-15+127; + man <<= 23; + frac <<= 13; + k |= man | frac; + } + else + { + // to infinity and beyond! + if (frac == 0) + k |= 0x7f800000; + else + k |= 0x7f800001 | ((frac&0x200)<<12); + } + return func(&k); + } +}; + template class Convert { @@ -385,6 +436,31 @@ jconverter getConverter(const char* from, int itemsize, const char* to) case 'd': return &Convert::toD; } break; + case 'e': + if (reverse) switch (to[0]) + { + case 'z': return &Reverse::toZ>::convert>::call4; + case 'b': return &Reverse::toB>::convert>::call4; + case 'c': return &Reverse::toC>::convert>::call4; + case 's': return &Reverse::toS>::convert>::call4; + case 'i': return &Reverse::toI>::convert>::call4; + case 'j': return &Reverse::toJ>::convert>::call4; + case 'f': return &Reverse::toF>::convert>::call4; + case 'd': return &Reverse::toD>::convert>::call4; + } + else switch (to[0]) + { + case 'z': return &Half::toZ>::convert; + case 'b': return &Half::toB>::convert; + case 'c': return &Half::toC>::convert; + case 's': return &Half::toS>::convert; + case 'i': return &Half::toI>::convert; + case 'j': return &Half::toJ>::convert; + case 'f': return &Half::toF>::convert; + case 'd': return &Half::toD>::convert; + } + break; + case 'n': if (reverse) switch (to[0]) { diff --git a/test/jpypetest/test_conversionInt.py b/test/jpypetest/test_conversionInt.py index bb94ca025..8c9721c51 100644 --- a/test/jpypetest/test_conversionInt.py +++ b/test/jpypetest/test_conversionInt.py @@ -73,10 +73,10 @@ def testIntFromFloat(self): self.Test.callInt(float(2)) @common.unittest.skipUnless(haveNumpy(), "numpy not available") - def testIntFromNPFloat(self): + def testIntFromNPFloat16(self): import numpy as np with self.assertRaises(TypeError): - self.Test.callInt(np.float_(2)) + self.Test.callInt(np.float16(2)) @common.unittest.skipUnless(haveNumpy(), "numpy not available") def testIntFromNPFloat32(self): diff --git a/test/jpypetest/test_conversionLong.py b/test/jpypetest/test_conversionLong.py index ae3f31313..256b4ed0c 100644 --- a/test/jpypetest/test_conversionLong.py +++ b/test/jpypetest/test_conversionLong.py @@ -73,10 +73,10 @@ def testLongFromFloat(self): self.Test.callLong(float(2)) @common.unittest.skipUnless(haveNumpy(), "numpy not available") - def testLongFromNPFloat(self): + def testLongFromNPFloat16(self): import numpy as np with self.assertRaises(TypeError): - self.Test.callLong(np.float_(2)) + self.Test.callLong(np.float16(2)) @common.unittest.skipUnless(haveNumpy(), "numpy not available") def testLongFromNPFloat32(self): diff --git a/test/jpypetest/test_conversionShort.py b/test/jpypetest/test_conversionShort.py index d3fd81ffa..0c3d072c8 100644 --- a/test/jpypetest/test_conversionShort.py +++ b/test/jpypetest/test_conversionShort.py @@ -73,10 +73,10 @@ def testShortFromFloat(self): self.Test.callShort(float(2)) @common.unittest.skipUnless(haveNumpy(), "numpy not available") - def testShortFromNPFloat(self): + def testShortFromNPFloat16(self): import numpy as np with self.assertRaises(TypeError): - self.Test.callShort(np.float_(2)) + self.Test.callShort(np.float16(2)) @common.unittest.skipUnless(haveNumpy(), "numpy not available") def testShortFromNPFloat32(self): diff --git a/test/jpypetest/test_jboolean.py b/test/jpypetest/test_jboolean.py index ed0f6bd99..b27c63fd0 100644 --- a/test/jpypetest/test_jboolean.py +++ b/test/jpypetest/test_jboolean.py @@ -100,10 +100,10 @@ def testBooleanFromFloat(self): self.Test.callBoolean(float(2)) @common.requireNumpy - def testBooleanFromNPFloat(self): + def testBooleanFromNPFloat16(self): import numpy as np with self.assertRaises(TypeError): - self.Test.callBoolean(np.float_(2)) + self.Test.callBoolean(np.float16(2)) @common.requireNumpy def testBooleanFromNPFloat32(self): diff --git a/test/jpypetest/test_jbyte.py b/test/jpypetest/test_jbyte.py index 55bfd4ec8..a4b995c9b 100644 --- a/test/jpypetest/test_jbyte.py +++ b/test/jpypetest/test_jbyte.py @@ -108,10 +108,10 @@ def testByteFromFloat(self): self.fixture.callByte(float(2)) @common.requireNumpy - def testByteFromNPFloat(self): + def testByteFromNPFloat16(self): import numpy as np with self.assertRaises(TypeError): - self.fixture.callByte(np.float_(2)) + self.fixture.callByte(np.float16(2)) @common.requireNumpy def testByteFromNPFloat32(self): diff --git a/test/jpypetest/test_jdouble.py b/test/jpypetest/test_jdouble.py index 09c03351b..cf3b89799 100644 --- a/test/jpypetest/test_jdouble.py +++ b/test/jpypetest/test_jdouble.py @@ -374,8 +374,8 @@ def testArraySetFromNPDouble(self): self.assertElementsAlmostEqual(a, jarr) @common.requireNumpy - def testArrayInitFromNPFloat(self): - a = np.random.random(100).astype(np.float_) + def testArrayInitFromNPFloat16(self): + a = np.random.random(100).astype(np.float16) jarr = JArray(JDouble)(a) self.assertElementsAlmostEqual(a, jarr) @@ -436,3 +436,15 @@ def __len__(self): def testCastBoolean(self): self.assertEqual(JDouble._canConvertToJava(JBoolean(True)), "none") + + @common.requireNumpy + def testNPFloat16(self): + v= [0.000000e+00, 5.960464e-08, 1.788139e-07, 1.788139e-07, 4.172325e-07, 8.940697e-07, 1.847744e-06, 3.755093e-06, 7.569790e-06, 1.519918e-05, 3.045797e-05, 6.097555e-05, 6.103516e-05, 3.332520e-01, 1.000000e+00, 6.550400e+04, np.inf, -np.inf] + a = np.array(v, dtype=np.float16) + jarr = JArray(JDouble)(a) + for v1,v2 in zip(a, jarr): + self.assertEqual(v1,v2) + a = np.array([np.nan], dtype=np.float16) + jarr = JArray(JDouble)(a) + self.assertTrue(np.isnan(jarr[0])) + diff --git a/test/jpypetest/test_jfloat.py b/test/jpypetest/test_jfloat.py index 4fbce3591..eb63fe168 100644 --- a/test/jpypetest/test_jfloat.py +++ b/test/jpypetest/test_jfloat.py @@ -382,8 +382,8 @@ def testArraySetFromNPDouble(self): self.assertElementsAlmostEqual(a, jarr) @common.requireNumpy - def testArrayInitFromNPFloat(self): - a = np.random.random(100).astype(np.float_) + def testArrayInitFromNPFloat16(self): + a = np.random.random(100).astype(np.float16) jarr = JArray(JFloat)(a) self.assertElementsAlmostEqual(a, jarr) @@ -441,3 +441,15 @@ def __len__(self): ja[:] = [1, 2, 3] with self.assertRaisesRegex(ValueError, "mismatch"): ja[:] = a + + @common.requireNumpy + def testNPFloat16(self): + v= [0.000000e+00, 5.960464e-08, 1.788139e-07, 1.788139e-07, 4.172325e-07, 8.940697e-07, 1.847744e-06, 3.755093e-06, 7.569790e-06, 1.519918e-05, 3.045797e-05, 6.097555e-05, 6.103516e-05, 3.332520e-01, 1.000000e+00, 6.550400e+04, np.inf, -np.inf] + a = np.array(v, dtype=np.float16) + jarr = JArray(JFloat)(a) + for v1,v2 in zip(a, jarr): + self.assertEqual(v1,v2) + a = np.array([np.nan], dtype=np.float16) + jarr = JArray(JFloat)(a) + self.assertTrue(np.isnan(jarr[0])) + From f6849c5412d506e10a89e49aad42d13cc70f350c Mon Sep 17 00:00:00 2001 From: Karl Nelson Date: Sun, 23 Jun 2024 09:21:59 -0700 Subject: [PATCH 16/55] Trying to test tests working --- test/jpypetest/test_buffer.py | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/test/jpypetest/test_buffer.py b/test/jpypetest/test_buffer.py index 0da865232..3882511df 100644 --- a/test/jpypetest/test_buffer.py +++ b/test/jpypetest/test_buffer.py @@ -315,11 +315,11 @@ def testMemoryByte(self): jtype = jpype.JByte[:] # Simple checks - for dtype in ("c", "?", "b", "B", "h", "H", "i", "I", "l", "L", "q", "Q", "f", "d", "n", "N"): + for dtype in "c?bBhHiIlLqQfdnN": jtype(mv.cast(dtype)) jtype(mv.cast("@" + dtype)) - for dtype in ("s", "p", "P", "e"): + for dtype in "spP": with self.assertRaises(Exception): jtype(mv.cast(dtype)) @@ -328,11 +328,12 @@ def testMemoryInt(self): jtype = jpype.JInt[:] # Simple checks - for dtype in ("c", "?", "b", "B", "h", "H", "i", "I", "l", "L", "q", "Q", "f", "d", "n", "N"): + for dtype in "c?bBhHiIlLqQfdnN": + print(dtype) jtype(mv.cast(dtype)) jtype(mv.cast("@" + dtype)) - for dtype in ("s", "p", "P", "e"): + for dtype in "spP": with self.assertRaises(Exception): jtype(mv.cast(dtype)) @@ -341,11 +342,11 @@ def testMemoryShort(self): jtype = jpype.JShort[:] # Simple checks - for dtype in ("c", "?", "b", "B", "h", "H", "i", "I", "l", "L", "q", "Q", "f", "d", "n", "N"): + for dtype in "c?bBhHiIlLqQfdnN": jtype(mv.cast(dtype)) jtype(mv.cast("@" + dtype)) - for dtype in ("s", "p", "P", "e"): + for dtype in "spP": with self.assertRaises(Exception): jtype(mv.cast(dtype)) @@ -354,11 +355,11 @@ def testMemoryLong(self): jtype = jpype.JLong[:] # Simple checks - for dtype in ("c", "?", "b", "B", "h", "H", "i", "I", "l", "L", "q", "Q", "f", "d", "n", "N"): + for dtype in "c?bBhHiIlLqQfdnN": jtype(mv.cast(dtype)) jtype(mv.cast("@" + dtype)) - for dtype in ("s", "p", "P", "e"): + for dtype in "spP": with self.assertRaises(Exception): jtype(mv.cast(dtype)) @@ -367,11 +368,11 @@ def testMemoryFloat(self): jtype = jpype.JFloat[:] # Simple checks - for dtype in ("c", "?", "b", "B", "h", "H", "i", "I", "l", "L", "q", "Q", "f", "d", "n", "N"): + for dtype in "c?bBhHiIlLqQfdnN": jtype(mv.cast(dtype)) jtype(mv.cast("@" + dtype)) - for dtype in ("s", "p", "P", "e"): + for dtype in "spP": with self.assertRaises(Exception): jtype(mv.cast(dtype)) @@ -380,11 +381,11 @@ def testMemoryDouble(self): jtype = jpype.JDouble[:] # Simple checks - for dtype in ("c", "?", "b", "B", "h", "H", "i", "I", "l", "L", "q", "Q", "f", "d", "n", "N"): + for dtype in "c?bBhHiIlLqQfdnN": jtype(mv.cast(dtype)) jtype(mv.cast("@" + dtype)) - for dtype in ("s", "p", "P", "e"): + for dtype in "spP": with self.assertRaises(Exception): jtype(mv.cast(dtype)) @@ -393,11 +394,11 @@ def testMemoryBoolean(self): jtype = jpype.JBoolean[:] # Simple checks - for dtype in ("c", "?", "b", "B", "h", "H", "i", "I", "l", "L", "q", "Q", "f", "d", "n", "N"): + for dtype in "c?bBhHiIlLqQfdnN": jtype(mv.cast(dtype)) jtype(mv.cast("@" + dtype)) - for dtype in ("s", "p", "P", "e"): + for dtype in "spP": with self.assertRaises(Exception): jtype(mv.cast(dtype)) @@ -406,7 +407,7 @@ def testMemoryChar(self): jtype = jpype.JChar[:] # Simple checks - for dtype in ("c", "?", "b", "B", "h", "H", "i", "I", "l", "L", "q", "Q", "n", "N"): + for dtype in "c?bBhHiIlLqQnN": jtype(mv.cast(dtype)) jtype(mv.cast("@" + dtype)) From 2ef11689f233d366b86d6df7c0393fe42937525f Mon Sep 17 00:00:00 2001 From: Karl Nelson Date: Thu, 27 Jun 2024 14:50:11 -0700 Subject: [PATCH 17/55] Fixes #1198 --- native/python/include/pyjp.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/native/python/include/pyjp.h b/native/python/include/pyjp.h index c9645843d..df6983af3 100755 --- a/native/python/include/pyjp.h +++ b/native/python/include/pyjp.h @@ -178,13 +178,14 @@ JPValue *PyJPValue_getJavaSlot(PyObject* obj); PyObject *PyJPModule_getClass(PyObject* module, PyObject *obj); PyObject *PyJPValue_getattro(PyObject *obj, PyObject *name); int PyJPValue_setattro(PyObject *self, PyObject *name, PyObject *value); -void PyJPClass_hook(JPJavaFrame &frame, JPClass* cls); PyObject *PyJPChar_Create(PyTypeObject *type, Py_UCS2 p); #ifdef __cplusplus } #endif +void PyJPClass_hook(JPJavaFrame &frame, JPClass* cls); + // C++ methods JPPyObject PyJPArray_create(JPJavaFrame &frame, PyTypeObject* wrapper, const JPValue& value); JPPyObject PyJPBuffer_create(JPJavaFrame &frame, PyTypeObject *type, const JPValue & value); From 31339e37e61a6a4df224cae98a806cebf948ec4d Mon Sep 17 00:00:00 2001 From: Alexander Rashed Date: Mon, 29 Jul 2024 11:47:35 +0200 Subject: [PATCH 18/55] remove usage of setuptools.command.test --- doc/install.rst | 2 +- setup.cfg | 3 --- setup.py | 1 - setupext/__init__.py | 1 - setupext/pytester.py | 39 --------------------------------------- 5 files changed, 1 insertion(+), 45 deletions(-) delete mode 100644 setupext/pytester.py diff --git a/doc/install.rst b/doc/install.rst index 6e1ef71b1..4e1ae14e8 100644 --- a/doc/install.rst +++ b/doc/install.rst @@ -107,7 +107,7 @@ bench requires JDK to build. **4. Test JPype with (optional):** :: - python setup.py test + python -m pytest diff --git a/setup.cfg b/setup.cfg index 44c5ddbe5..acc5cf1af 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,3 @@ -[alias] -test=pytest - [tool:pytest] addopts = --verbose testpaths = diff --git a/setup.py b/setup.py index 06f8c2064..83c263f39 100644 --- a/setup.py +++ b/setup.py @@ -70,7 +70,6 @@ 'develop': setupext.develop.Develop, 'test_java': setupext.test_java.TestJavaCommand, 'sdist': setupext.sdist.BuildSourceDistribution, - 'test': setupext.pytester.PyTest, }, zip_safe=False, ext_modules=[jpypeJar, jpypeLib, ], diff --git a/setupext/__init__.py b/setupext/__init__.py index d4f70098f..f47d0bc5a 100644 --- a/setupext/__init__.py +++ b/setupext/__init__.py @@ -21,4 +21,3 @@ from . import develop from . import test_java from . import sdist -from . import pytester diff --git a/setupext/pytester.py b/setupext/pytester.py deleted file mode 100644 index a19a3fa7d..000000000 --- a/setupext/pytester.py +++ /dev/null @@ -1,39 +0,0 @@ -# ***************************************************************************** -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# See NOTICE file for details. -# -# ***************************************************************************** -import sys - -from setuptools.command.test import test as TestCommand - - -class PyTest(TestCommand): - user_options = [("pytest-args=", "a", "Arguments to pass to pytest")] - - def initialize_options(self): - TestCommand.initialize_options(self) - self.pytest_args = "" - - def run_tests(self): - self.run_command("test_java") - - import shlex - - # import here, cause outside the eggs aren't loaded - import pytest - - errno = pytest.main(shlex.split(self.pytest_args)) - sys.exit(errno) From eb8fe61c691148d575526a8f5436874099847f23 Mon Sep 17 00:00:00 2001 From: John D Clark Date: Fri, 16 Aug 2024 17:14:06 -0400 Subject: [PATCH 19/55] Update LICENSE The current LICENSE file does not support the GitHub License badge detecting the correct license of the project. Replacing the current license file with a copy of the license file from the Apache License 2.0 website will cause the GitHub License badge to correctly identify the license of jpype. --- LICENSE | 388 +++++++++++++++++++++++++++++--------------------------- 1 file changed, 201 insertions(+), 187 deletions(-) diff --git a/LICENSE b/LICENSE index 4a1737519..261eeb9e9 100644 --- a/LICENSE +++ b/LICENSE @@ -1,187 +1,201 @@ -============== -Apache License -============== - -:Version: 2.0 -:Date: January 2004 -:URL: http://www.apache.org/licenses/ - ------------------------------------------------------------- -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION ------------------------------------------------------------- - -1. Definitions. ---------------- - -**"License"** shall mean the terms and conditions for use, reproduction, and -distribution as defined by Sections 1 through 9 of this document. - -**"Licensor"** shall mean the copyright owner or entity authorized by the -copyright owner that is granting the License. - -**"Legal Entity"** shall mean the union of the acting entity and all other -entities that control, are controlled by, or are under common control with that -entity. For the purposes of this definition, "control" means *(i)* the power, -direct or indirect, to cause the direction or management of such entity, -whether by contract or otherwise, or *(ii)* ownership of fifty percent (50%) or -more of the outstanding shares, or *(iii)* beneficial ownership of such entity. - -**"You"** (or **"Your"**) shall mean an individual or Legal Entity exercising -permissions granted by this License. - -**"Source"** form shall mean the preferred form for making modifications, -including but not limited to software source code, documentation source, and -configuration files. - -**"Object"** form shall mean any form resulting from mechanical transformation -or translation of a Source form, including but not limited to compiled object -code, generated documentation, and conversions to other media types. - -**"Work"** shall mean the work of authorship, whether in Source or Object form, -made available under the License, as indicated by a copyright notice that is -included in or attached to the work (an example is provided in the Appendix -below). - -**"Derivative Works"** shall mean any work, whether in Source or Object form, -that is based on (or derived from) the Work and for which the editorial -revisions, annotations, elaborations, or other modifications represent, as a -whole, an original work of authorship. For the purposes of this License, -Derivative Works shall not include works that remain separable from, or merely -link (or bind by name) to the interfaces of, the Work and Derivative Works -thereof. - -**"Contribution"** shall mean any work of authorship, including the original -version of the Work and any modifications or additions to that Work or -Derivative Works thereof, that is intentionally submitted to Licensor for -inclusion in the Work by the copyright owner or by an individual or Legal -Entity authorized to submit on behalf of the copyright owner. For the purposes -of this definition, "submitted" means any form of electronic, verbal, or -written communication sent to the Licensor or its representatives, including -but not limited to communication on electronic mailing lists, source code -control systems, and issue tracking systems that are managed by, or on behalf -of, the Licensor for the purpose of discussing and improving the Work, but -excluding communication that is conspicuously marked or otherwise designated in -writing by the copyright owner as "Not a Contribution." - -**"Contributor"** shall mean Licensor and any individual or Legal Entity on -behalf of whom a Contribution has been received by Licensor and subsequently -incorporated within the Work. - -2. Grant of Copyright License. ------------------------------- - -Subject to the terms and conditions of this License, each Contributor hereby -grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, -irrevocable copyright license to reproduce, prepare Derivative Works of, -publicly display, publicly perform, sublicense, and distribute the Work and -such Derivative Works in Source or Object form. - -3. Grant of Patent License. ---------------------------- - -Subject to the terms and conditions of this License, each Contributor hereby -grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, -irrevocable (except as stated in this section) patent license to make, have -made, use, offer to sell, sell, import, and otherwise transfer the Work, where -such license applies only to those patent claims licensable by such Contributor -that are necessarily infringed by their Contribution(s) alone or by combination -of their Contribution(s) with the Work to which such Contribution(s) was -submitted. If You institute patent litigation against any entity (including a -cross-claim or counterclaim in a lawsuit) alleging that the Work or a -Contribution incorporated within the Work constitutes direct or contributory -patent infringement, then any patent licenses granted to You under this License -for that Work shall terminate as of the date such litigation is filed. - -4. Redistribution. ------------------- - -You may reproduce and distribute copies of the Work or Derivative Works thereof -in any medium, with or without modifications, and in Source or Object form, -provided that You meet the following conditions: - -- You must give any other recipients of the Work or Derivative Works a copy of - this License; and - -- You must cause any modified files to carry prominent notices stating that You - changed the files; and - -- You must retain, in the Source form of any Derivative Works that You - distribute, all copyright, patent, trademark, and attribution notices from - the Source form of the Work, excluding those notices that do not pertain to - any part of the Derivative Works; and - -- If the Work includes a ``"NOTICE"`` text file as part of its distribution, - then any Derivative Works that You distribute must include a readable copy of - the attribution notices contained within such ``NOTICE`` file, excluding - those notices that do not pertain to any part of the Derivative Works, in at - least one of the following places: within a ``NOTICE`` text file distributed - as part of the Derivative Works; within the Source form or documentation, if - provided along with the Derivative Works; or, within a display generated by - the Derivative Works, if and wherever such third-party notices normally - appear. The contents of the ``NOTICE`` file are for informational purposes - only and do not modify the License. You may add Your own attribution notices - within Derivative Works that You distribute, alongside or as an addendum to - the ``NOTICE`` text from the Work, provided that such additional attribution - notices cannot be construed as modifying the License. You may add Your own - copyright statement to Your modifications and may provide additional or - different license terms and conditions for use, reproduction, or distribution - of Your modifications, or for any such Derivative Works as a whole, provided - Your use, reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. -------------------------------- - -Unless You explicitly state otherwise, any Contribution intentionally submitted -for inclusion in the Work by You to the Licensor shall be under the terms and -conditions of this License, without any additional terms or conditions. -Notwithstanding the above, nothing herein shall supersede or modify the terms -of any separate license agreement you may have executed with Licensor regarding -such Contributions. - -6. Trademarks. --------------- - -This License does not grant permission to use the trade names, trademarks, -service marks, or product names of the Licensor, except as required for -reasonable and customary use in describing the origin of the Work and -reproducing the content of the ``NOTICE`` file. - -7. Disclaimer of Warranty. --------------------------- - -Unless required by applicable law or agreed to in writing, Licensor provides -the Work (and each Contributor provides its Contributions) on an **"AS IS" -BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND**, either express or -implied, including, without limitation, any warranties or conditions of -**TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR -PURPOSE**. You are solely responsible for determining the appropriateness of -using or redistributing the Work and assume any risks associated with Your -exercise of permissions under this License. - -8. Limitation of Liability. ---------------------------- - -In no event and under no legal theory, whether in tort (including negligence), -contract, or otherwise, unless required by applicable law (such as deliberate -and grossly negligent acts) or agreed to in writing, shall any Contributor be -liable to You for damages, including any direct, indirect, special, incidental, -or consequential damages of any character arising as a result of this License -or out of the use or inability to use the Work (including but not limited to -damages for loss of goodwill, work stoppage, computer failure or malfunction, -or any and all other commercial damages or losses), even if such Contributor -has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. ----------------------------------------------- - -While redistributing the Work or Derivative Works thereof, You may choose to -offer, and charge a fee for, acceptance of support, warranty, indemnity, or -other liability obligations and/or rights consistent with this License. -However, in accepting such obligations, You may act only on Your own behalf and -on Your sole responsibility, not on behalf of any other Contributor, and only -if You agree to indemnify, defend, and hold each Contributor harmless for any -liability incurred by, or claims asserted against, such Contributor by reason -of your accepting any such warranty or additional liability. - -**END OF TERMS AND CONDITIONS** + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. From 76b9cd344724c1fcf7d362fa9fa3ee342df4209a Mon Sep 17 00:00:00 2001 From: John D Clark Date: Sat, 17 Aug 2024 09:07:56 -0400 Subject: [PATCH 20/55] JPype-#1210: Update Readme to refer locally for the license badge. --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 0e2ddab1c..c69fcbd13 100644 --- a/README.rst +++ b/README.rst @@ -61,7 +61,7 @@ LLNL-CODE- 812311 .. |javaversions| image:: https://img.shields.io/badge/java-8%20%7C%209%20%7C%2011-purple.svg .. |jvm| image:: https://img.shields.io/badge/jvm-Open%20%7C%20Oracle%20%7C%20Corretto-purple.svg .. |platform| image:: https://img.shields.io/conda/pn/conda-forge/jpype1.svg -.. |license| image:: https://img.shields.io/github/license/jpype-project/jpype.svg +.. |license| image:: https://img.shields.io/github/license/clajo04/jpype.svg .. _Apache 2 License: https://github.com/jpype-project/jpype/blob/master/LICENSE .. _Python Docs: http://jpype.readthedocs.org/en/latest/ From 98331a639547bc419a3e6fdac6d618c2da57c5ca Mon Sep 17 00:00:00 2001 From: John D Clark Date: Sat, 17 Aug 2024 14:59:38 -0400 Subject: [PATCH 21/55] Update README.rst Reversing out changes to the readme as I didn't realize my change on a local branch would submit to my PR on jpype-project. --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index c69fcbd13..0e2ddab1c 100644 --- a/README.rst +++ b/README.rst @@ -61,7 +61,7 @@ LLNL-CODE- 812311 .. |javaversions| image:: https://img.shields.io/badge/java-8%20%7C%209%20%7C%2011-purple.svg .. |jvm| image:: https://img.shields.io/badge/jvm-Open%20%7C%20Oracle%20%7C%20Corretto-purple.svg .. |platform| image:: https://img.shields.io/conda/pn/conda-forge/jpype1.svg -.. |license| image:: https://img.shields.io/github/license/clajo04/jpype.svg +.. |license| image:: https://img.shields.io/github/license/jpype-project/jpype.svg .. _Apache 2 License: https://github.com/jpype-project/jpype/blob/master/LICENSE .. _Python Docs: http://jpype.readthedocs.org/en/latest/ From 21166bad014ad9a27a50c7da4883f65ff245630b Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Mon, 19 Aug 2024 23:58:05 +0200 Subject: [PATCH 22/55] wip --- jpype/_jvmfinder.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/jpype/_jvmfinder.py b/jpype/_jvmfinder.py index 64b656c2b..0202aae45 100644 --- a/jpype/_jvmfinder.py +++ b/jpype/_jvmfinder.py @@ -37,7 +37,6 @@ class JVMNotFoundException(ValueError): To avoid this exception specify the JAVA_HOME environment variable as a valid jre or jdk root directory. """ - pass class JVMNotSupportedException(ValueError): @@ -49,7 +48,6 @@ class JVMNotSupportedException(ValueError): 32 vs 64 bit, or the JVM is older than the version used to compile JPype. """ - pass def getDefaultJVMPath(): @@ -74,6 +72,9 @@ def getDefaultJVMPath(): return finder.get_jvm_path() +get_default_jvm_path = getDefaultJVMPath + + class JVMFinder(object): """ JVM library finder base class From 3ad084a6a4d5ef450e5e7ca51fe26801db7039ad Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Tue, 20 Aug 2024 00:04:39 +0200 Subject: [PATCH 23/55] remove py 3.7 --- .azure/build.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.azure/build.yml b/.azure/build.yml index 5226e47b1..a07ee84b6 100644 --- a/.azure/build.yml +++ b/.azure/build.yml @@ -50,10 +50,7 @@ jobs: dependsOn: Deps strategy: matrix: - linux-3.7: - imageName: "ubuntu-latest" - python.version: '3.7' - linux-3.8: + linux-3.8: # todo: 3.8 will be EOL on October 31, 2024 imageName: "ubuntu-latest" python.version: '3.8' jdk.version: '8' From 3e7a75b85f192ab5508c22cadcfc66b77ed314de Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Tue, 20 Aug 2024 00:27:50 +0200 Subject: [PATCH 24/55] add win-py312-jdk-17 to matrix --- .azure/build.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.azure/build.yml b/.azure/build.yml index a07ee84b6..efef78da9 100644 --- a/.azure/build.yml +++ b/.azure/build.yml @@ -50,6 +50,7 @@ jobs: dependsOn: Deps strategy: matrix: + # Linux linux-3.8: # todo: 3.8 will be EOL on October 31, 2024 imageName: "ubuntu-latest" python.version: '3.8' @@ -69,11 +70,11 @@ jobs: linux-3.12: imageName: "ubuntu-latest" python.version: '3.12' + # Windows windows-3.8: imageName: "windows-2019" python.version: '3.8' jdk.version: '8' - windows-3.9: imageName: "windows-2019" python.version: '3.9' @@ -85,6 +86,11 @@ jobs: imageName: "windows-2019" python.version: '3.11' jdk.version: '17' + windows-3.12: + imageName: "windows-2019" + python.version: '3.12' + jdk.version: '21' + # OSX mac-3.9: imageName: "macos-11" python.version: '3.9' @@ -104,7 +110,7 @@ jobs: matrix: linux-3.8: imageName: "ubuntu-16.04" - jdk_version: "1.11" + jdk_version: "1.11" # fixme: this version is simply ignored. python.version: '3.8' pool: vmImage: $(imageName) From 89f905d3a54cc4e53009618cdaa5a1b95ab6252e Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Tue, 20 Aug 2024 00:37:18 +0200 Subject: [PATCH 25/55] use macos-12 image --- .azure/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.azure/build.yml b/.azure/build.yml index efef78da9..7b5b3efef 100644 --- a/.azure/build.yml +++ b/.azure/build.yml @@ -92,8 +92,8 @@ jobs: jdk.version: '21' # OSX mac-3.9: - imageName: "macos-11" - python.version: '3.9' + imageName: "macos-12" + python.version: '3.12' jpypetest.fast: 'true' jdk.version: '17' From 986c61c460e40ebefcbe37056ed5b7c1f75a0b40 Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Tue, 20 Aug 2024 00:40:44 +0200 Subject: [PATCH 26/55] test old py and j for osx --- .azure/build.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.azure/build.yml b/.azure/build.yml index 7b5b3efef..82d410425 100644 --- a/.azure/build.yml +++ b/.azure/build.yml @@ -91,7 +91,12 @@ jobs: python.version: '3.12' jdk.version: '21' # OSX - mac-3.9: + mac-3.8: + imageName: "macos-12" + python.version: '3.8' + jpypetest.fast: 'true' + jdk.version: '8' + mac-3.12: imageName: "macos-12" python.version: '3.12' jpypetest.fast: 'true' From e23f1de3770da43c3a0e8cfae6a08ed57c1fb960 Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Tue, 20 Aug 2024 00:43:13 +0200 Subject: [PATCH 27/55] try to fix debug job (how to trigger it?) --- .azure/build.yml | 7 ++++--- .azure/scripts/debug.yml | 4 ++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.azure/build.yml b/.azure/build.yml index 82d410425..a68a77328 100644 --- a/.azure/build.yml +++ b/.azure/build.yml @@ -73,7 +73,7 @@ jobs: # Windows windows-3.8: imageName: "windows-2019" - python.version: '3.8' + python.version: '3.8' # todo: 3.8 will be EOL on October 31, 2024 jdk.version: '8' windows-3.9: imageName: "windows-2019" @@ -93,7 +93,7 @@ jobs: # OSX mac-3.8: imageName: "macos-12" - python.version: '3.8' + python.version: '3.8' # todo: 3.8 will be EOL on October 31, 2024 jpypetest.fast: 'true' jdk.version: '8' mac-3.12: @@ -115,11 +115,12 @@ jobs: matrix: linux-3.8: imageName: "ubuntu-16.04" - jdk_version: "1.11" # fixme: this version is simply ignored. + jdk.version: "11" python.version: '3.8' pool: vmImage: $(imageName) steps: + - template: - template: scripts/deps.yml - template: scripts/debug.yml diff --git a/.azure/scripts/debug.yml b/.azure/scripts/debug.yml index 4f8d9ca08..7341ed53c 100644 --- a/.azure/scripts/debug.yml +++ b/.azure/scripts/debug.yml @@ -5,6 +5,10 @@ steps: inputs: versionSpec: '$(python.version)' +- template: jdk.yml + parameters: + version: '$(jdk.version)' + - script: | sudo apt install gdb pip install ./ From 6722c6dfee58c960d75ab24a6603714bbc79d87c Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Tue, 20 Aug 2024 10:43:29 +0200 Subject: [PATCH 28/55] test sqlite only for jvm versions > 8 --- test/jpypetest/test_sql_sqlite.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/test/jpypetest/test_sql_sqlite.py b/test/jpypetest/test_sql_sqlite.py index a63b4e02c..0b6156b64 100644 --- a/test/jpypetest/test_sql_sqlite.py +++ b/test/jpypetest/test_sql_sqlite.py @@ -1,15 +1,15 @@ # This file is Public Domain and may be used without restrictions, # because nobody should have to waste their lives typing this again. -import jpype -from jpype.types import * -from jpype import java -import jpype.dbapi2 as dbapi2 -import common import datetime import decimal +import sys import threading -java = jpype.java +import common +import jpype +import jpype.dbapi2 as dbapi2 +from jpype import java, isJVMStarted +from jpype.types import * try: import zlib @@ -20,12 +20,22 @@ db_name = "jdbc:sqlite::memory:" +if isJVMStarted(): + java_version = str(jpype.java.lang.System.getProperty("java.version")) + java_version = java_version.split(".") + + if java_version[0] == "8":# and sys.platform == "win": + raise common.unittest.SkipTest("sqlite unsupported on this config.") + + class ConnectTestCase(common.JPypeTestCase): def setUp(self): common.JPypeTestCase.setUp(self) if common.fast: raise common.unittest.SkipTest("fast") + + def testConnect(self): cx = dbapi2.connect(db_name) self.assertIsInstance(cx, dbapi2.Connection) From 3a7f44e488a25a8d5af9c251cacbdb263375e161 Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Tue, 20 Aug 2024 10:44:53 +0200 Subject: [PATCH 29/55] shut up mypy --- test/jpypetest/test_sql_sqlite.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/jpypetest/test_sql_sqlite.py b/test/jpypetest/test_sql_sqlite.py index 0b6156b64..e296e5c0a 100644 --- a/test/jpypetest/test_sql_sqlite.py +++ b/test/jpypetest/test_sql_sqlite.py @@ -21,8 +21,7 @@ if isJVMStarted(): - java_version = str(jpype.java.lang.System.getProperty("java.version")) - java_version = java_version.split(".") + java_version = str(jpype.java.lang.System.getProperty("java.version")).split(".") if java_version[0] == "8":# and sys.platform == "win": raise common.unittest.SkipTest("sqlite unsupported on this config.") From dc75df26c31682e05f370357ee0035dae1a26da5 Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Tue, 20 Aug 2024 10:49:34 +0200 Subject: [PATCH 30/55] f --- .azure/build.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.azure/build.yml b/.azure/build.yml index a68a77328..a3a33e43e 100644 --- a/.azure/build.yml +++ b/.azure/build.yml @@ -120,7 +120,5 @@ jobs: pool: vmImage: $(imageName) steps: - - template: - template: scripts/deps.yml - template: scripts/debug.yml - From 43d40057440d4e70d4ffeaece85119cd9633de78 Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Tue, 20 Aug 2024 10:53:14 +0200 Subject: [PATCH 31/55] imports --- test/jpypetest/test_sql_generic.py | 1 - test/jpypetest/test_sql_sqlite.py | 1 - 2 files changed, 2 deletions(-) diff --git a/test/jpypetest/test_sql_generic.py b/test/jpypetest/test_sql_generic.py index d2381a2ec..69e1128c9 100644 --- a/test/jpypetest/test_sql_generic.py +++ b/test/jpypetest/test_sql_generic.py @@ -1,5 +1,4 @@ # This file is Public Domain and may be used without restrictions. -from jpype.types import * import jpype.dbapi2 as dbapi2 import common import time diff --git a/test/jpypetest/test_sql_sqlite.py b/test/jpypetest/test_sql_sqlite.py index e296e5c0a..530987037 100644 --- a/test/jpypetest/test_sql_sqlite.py +++ b/test/jpypetest/test_sql_sqlite.py @@ -2,7 +2,6 @@ # because nobody should have to waste their lives typing this again. import datetime import decimal -import sys import threading import common From 1e18114dbb892bc1a585f486456920ad2b8ee021 Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Tue, 20 Aug 2024 10:55:16 +0200 Subject: [PATCH 32/55] update AUTHORS.rst --- AUTHORS.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AUTHORS.rst b/AUTHORS.rst index 45b48bf96..029f3e03a 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -2,8 +2,8 @@ Authors ------- The original author: Steve Menard - -Current Maintainer: Luis Nell +Current Lead Developer: Karl Einar Nelson +Current Maintainer: Martin K. Scherer Huge thanks to these CONTRIBUTORS: From d7352b4492ddbbaabc346cfb54c7d78881d4325a Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Tue, 20 Aug 2024 10:55:41 +0200 Subject: [PATCH 33/55] imports --- test/jpypetest/conftest.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/jpypetest/conftest.py b/test/jpypetest/conftest.py index ecdf6ee03..2661b9062 100755 --- a/test/jpypetest/conftest.py +++ b/test/jpypetest/conftest.py @@ -16,8 +16,6 @@ # # ***************************************************************************** import pytest -import _jpype -import jpype import common From 335809d8d83db0f6b48b7fc37e1450f069c0c431 Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Tue, 20 Aug 2024 10:56:08 +0200 Subject: [PATCH 34/55] imports (locally in WinJVMFinder) --- jpype/_jvmfinder.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/jpype/_jvmfinder.py b/jpype/_jvmfinder.py index 70d7abb0a..f19c1aa36 100644 --- a/jpype/_jvmfinder.py +++ b/jpype/_jvmfinder.py @@ -23,10 +23,7 @@ __all__ = ['getDefaultJVMPath', 'JVMNotFoundException', 'JVMNotSupportedException'] -try: - import winreg -except ImportError: - winreg = None # type: ignore[assignment] + class JVMNotFoundException(ValueError): @@ -392,8 +389,11 @@ def _get_from_registry(self): :return: The path found in the registry, or None """ - if not winreg: + try: + import winreg + except ImportError: return None + for location in reg_keys: try: jreKey = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, location) From f9e2b7887f68fc80e774ac3e1fd8a30f936a286d Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Tue, 20 Aug 2024 11:05:49 +0200 Subject: [PATCH 35/55] [ci] name jobs with python and jdk suffix --- .azure/build.yml | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/.azure/build.yml b/.azure/build.yml index a3a33e43e..c5f8473c7 100644 --- a/.azure/build.yml +++ b/.azure/build.yml @@ -51,52 +51,54 @@ jobs: strategy: matrix: # Linux - linux-3.8: # todo: 3.8 will be EOL on October 31, 2024 + linux-py3.8-jdk8: # todo: 3.8 will be EOL on October 31, 2024 imageName: "ubuntu-latest" python.version: '3.8' jdk.version: '8' - linux-3.9: + linux-py3.9-jdk11: imageName: "ubuntu-latest" python.version: '3.9' jdk.version: '11' - linux-3.10: + linux-py3.10-jdk17: imageName: "ubuntu-latest" python.version: '3.10' jdk.version: '17' - linux-3.11: + linux-py3.11-jdk17: imageName: "ubuntu-latest" python.version: '3.11' jdk.version: '17' - linux-3.12: + linux-py3.12-jdk17: imageName: "ubuntu-latest" python.version: '3.12' + jdk.version: '17' # Windows - windows-3.8: + windows-py3.8-jdk8: imageName: "windows-2019" python.version: '3.8' # todo: 3.8 will be EOL on October 31, 2024 jdk.version: '8' - windows-3.9: + windows-py3.9-jdk11: imageName: "windows-2019" python.version: '3.9' jdk.version: '11' - windows-3.10: + windows-py3.10-jdk8: imageName: "windows-2019" python.version: '3.10' - windows-3.11: + jdk.version: '8' + windows-py3.11-jdk17: imageName: "windows-2019" python.version: '3.11' jdk.version: '17' - windows-3.12: + windows-py3.12-jdk21: imageName: "windows-2019" python.version: '3.12' jdk.version: '21' - # OSX - mac-3.8: + # OSX, we only test an old Python version with JDK8 and recent Py with recent JDK. + mac-py3.8-jdk8: imageName: "macos-12" python.version: '3.8' # todo: 3.8 will be EOL on October 31, 2024 jpypetest.fast: 'true' jdk.version: '8' - mac-3.12: + mac-py3.12-jdk17: imageName: "macos-12" python.version: '3.12' jpypetest.fast: 'true' @@ -113,7 +115,7 @@ jobs: dependsOn: Deps strategy: matrix: - linux-3.8: + linux-py3.8-jdk11: imageName: "ubuntu-16.04" jdk.version: "11" python.version: '3.8' From 56e17eea4e9f444251d7d665c52820133d35a3f5 Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Tue, 20 Aug 2024 11:09:22 +0200 Subject: [PATCH 36/55] [ci] fail if jdk could not be set --- .azure/scripts/jdk.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.azure/scripts/jdk.yml b/.azure/scripts/jdk.yml index 614ae6b47..39f3e329e 100644 --- a/.azure/scripts/jdk.yml +++ b/.azure/scripts/jdk.yml @@ -9,3 +9,6 @@ steps: versionSpec: ${{ parameters.version }} jdkArchitectureOption: 'x64' jdkSourceOption: 'PreInstalled' + - bash: exit 1 + displayName: JDK ${{ parameters.version }} could not be set. + condition: eq(variables['Agent.JobStatus'], 'SucceededWithIssues') From 674312c98a3cf094271f369568f25adb75e23b2b Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Tue, 20 Aug 2024 11:09:32 +0200 Subject: [PATCH 37/55] minor --- .azure/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.azure/build.yml b/.azure/build.yml index c5f8473c7..1ebe24559 100644 --- a/.azure/build.yml +++ b/.azure/build.yml @@ -15,7 +15,7 @@ trigger: - test/* variables: -# indicate whether the testsuite should skip long running tests or not. +# indicate whether the testsuite should skip long-running tests or not. - name: jpypetest.fast value: 'false' From ce75eea668b848f7e514e753c4cfd73cf96ef04d Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Tue, 20 Aug 2024 11:19:20 +0200 Subject: [PATCH 38/55] replace impl test for windows jvmfinder --- jpype/_jvmfinder.py | 3 ++- test/jpypetest/test_jvmfinder.py | 14 ++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/jpype/_jvmfinder.py b/jpype/_jvmfinder.py index f19c1aa36..071fb6365 100644 --- a/jpype/_jvmfinder.py +++ b/jpype/_jvmfinder.py @@ -382,7 +382,8 @@ def __init__(self): def check(self, jvm): _checkJVMArch(jvm) - def _get_from_registry(self): + @staticmethod + def _get_from_registry(): """ Retrieves the path to the default Java installation stored in the Windows registry diff --git a/test/jpypetest/test_jvmfinder.py b/test/jpypetest/test_jvmfinder.py index 4e16a7b2e..d833b4582 100644 --- a/test/jpypetest/test_jvmfinder.py +++ b/test/jpypetest/test_jvmfinder.py @@ -16,8 +16,8 @@ # # ***************************************************************************** # part of JPype1; author Martin K. Scherer; 2014 - - +import pathlib +import sys import unittest from unittest import mock import common @@ -175,14 +175,12 @@ def testCheckArch(self): self.assertRaises(JVMNotSupportedException): jpype._jvmfinder._checkJVMArch('path', 2**32) + @unittest.skipIf(sys.platform != "win", "only on windows") def testWindowsRegistry(self): finder = jpype._jvmfinder.WindowsJVMFinder() - with mock.patch("jpype._jvmfinder.winreg") as winregmock: - winregmock.QueryValueEx.return_value = ('success', '') - self.assertEqual(finder._get_from_registry(), 'success') - winregmock.OpenKey.side_effect = OSError() - self.assertEqual(finder._get_from_registry(), None) - + jvm_home = pathlib.Path(finder.get_jvm_path()) + assert jvm_home.exists() + assert jvm_home.is_dir() if __name__ == '__main__': unittest.main() From 155abab3dcd12833df2a8f7b43f1abdbb7cf40bc Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Tue, 20 Aug 2024 11:27:00 +0200 Subject: [PATCH 39/55] modernize jvmfinder a bit --- jpype/_jvmfinder.py | 84 ++++++++++++++++++--------------------------- 1 file changed, 34 insertions(+), 50 deletions(-) diff --git a/jpype/_jvmfinder.py b/jpype/_jvmfinder.py index 071fb6365..eda6af74c 100644 --- a/jpype/_jvmfinder.py +++ b/jpype/_jvmfinder.py @@ -21,9 +21,9 @@ import sys __all__ = ['getDefaultJVMPath', - 'JVMNotFoundException', 'JVMNotSupportedException'] - - + 'get_default_jvm_path', + 'JVMNotFoundException', + 'JVMNotSupportedException'] class JVMNotFoundException(ValueError): @@ -47,7 +47,7 @@ class JVMNotSupportedException(ValueError): """ -def getDefaultJVMPath(): +def getDefaultJVMPath() -> str: """ Retrieves the path to the default or first found JVM library @@ -72,21 +72,17 @@ def getDefaultJVMPath(): get_default_jvm_path = getDefaultJVMPath -class JVMFinder(object): +class JVMFinder: """ JVM library finder base class """ + # Library file name + _libfile = "libjvm.so" - def __init__(self): - """ - Sets up members - """ - # Library file name - self._libfile = "libjvm.so" - - # Predefined locations - self._locations = ("/usr/lib/jvm", "/usr/java") + # Predefined locations + _locations = ("/usr/lib/jvm", "/usr/java") + def __init__(self): # Search methods self._methods = (self._get_from_java_home, self._get_from_known_locations) @@ -128,7 +124,8 @@ def find_libjvm(self, java_home): "environment variable is pointing " "to correct installation.") - def find_possible_homes(self, parents): + @staticmethod + def find_possible_homes(parents): """ Generator that looks for the first-level children folders that could be Java installations, according to their name @@ -251,21 +248,17 @@ class LinuxJVMFinder(JVMFinder): Linux JVM library finder class """ - def __init__(self): - """ - Sets up members - """ - # Call the parent constructor - JVMFinder.__init__(self) + # Java bin file + _java = "/usr/bin/java" - # Java bin file - self._java = "/usr/bin/java" + # Library file name + _libfile = "libjvm.so" - # Library file name - self._libfile = "libjvm.so" + # Predefined locations + _locations = ("/usr/lib/jvm", "/usr/java", "/opt/sun") - # Predefined locations - self._locations = ("/usr/lib/jvm", "/usr/java", "/opt/sun") + def __init__(self): + super().__init__() # Search methods self._methods = (self._get_from_java_home, @@ -294,23 +287,20 @@ class DarwinJVMFinder(LinuxJVMFinder): """ Mac OS X JVM library finder class """ + # Library file name + _libfile = "libjli.dylib" + # Predefined locations + _locations = ('/Library/Java/JavaVirtualMachines',) def __init__(self): """ Sets up members """ - # Call the parent constructor - LinuxJVMFinder.__init__(self) - - # Library file name - self._libfile = "libjli.dylib" + super().__init__() self._methods = list(self._methods) self._methods.append(self._javahome_binary) - # Predefined locations - self._locations = ('/Library/Java/JavaVirtualMachines',) - def _javahome_binary(self): """ for osx > 10.5 we have the nice util /usr/libexec/java_home available. Invoke it and @@ -321,7 +311,8 @@ def _javahome_binary(self): from packaging.version import Version current = Version(platform.mac_ver()[0][:4]) - if current >= Version('10.6') and current < Version('10.9'): + # TODO: check if the java_home tool is still available and fix the version boundaries. + if Version('10.6') <= current: #< Version('10.9'): return subprocess.check_output( ['/usr/libexec/java_home']).strip() @@ -356,25 +347,18 @@ def _checkJVMArch(jvmPath, maxsize=sys.maxsize): raise JVMNotSupportedException("Unable to determine JVM Type") -reg_keys = [r"SOFTWARE\JavaSoft\Java Runtime Environment", - r"SOFTWARE\JavaSoft\JRE", - ] - - class WindowsJVMFinder(JVMFinder): """ Windows JVM library finder class """ + reg_keys = [r"SOFTWARE\JavaSoft\Java Runtime Environment", + r"SOFTWARE\JavaSoft\JRE", + ] + # Library file name + _libfile = "jvm.dll" def __init__(self): - """ - Sets up members - """ - # Call the parent constructor - JVMFinder.__init__(self) - - # Library file name - self._libfile = "jvm.dll" + super().__init__() # Search methods self._methods = (self._get_from_java_home, self._get_from_registry) @@ -395,7 +379,7 @@ def _get_from_registry(): except ImportError: return None - for location in reg_keys: + for location in WindowsJVMFinder.reg_keys: try: jreKey = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, location) cv = winreg.QueryValueEx(jreKey, "CurrentVersion") From 27557f305c282eadac0ea6d0e03d7cb326531ab7 Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Tue, 20 Aug 2024 11:49:48 +0200 Subject: [PATCH 40/55] [ci] condition does not work... another shot --- .azure/scripts/jdk.yml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.azure/scripts/jdk.yml b/.azure/scripts/jdk.yml index 39f3e329e..fcdaa327d 100644 --- a/.azure/scripts/jdk.yml +++ b/.azure/scripts/jdk.yml @@ -9,6 +9,11 @@ steps: versionSpec: ${{ parameters.version }} jdkArchitectureOption: 'x64' jdkSourceOption: 'PreInstalled' - - bash: exit 1 +# FIXME: we'd want to stop the execution of the whole pipeline, if the JDK could not be set. +# - bash: exit 1 +# displayName: JDK ${{ parameters.version }} could not be set. +# condition: eq(variables['Agent.JobStatus'], 'SucceededWithIssues') + - bash: | + echo AGENT_JOBSTATUS = $AGENT_JOBSTATUS + if [[ "$AGENT_JOBSTATUS" == "SucceededWithIssues" ]]; then exit 1; fi displayName: JDK ${{ parameters.version }} could not be set. - condition: eq(variables['Agent.JobStatus'], 'SucceededWithIssues') From 529c5df490553fd97a526711e2739c57b7d84e22 Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Tue, 20 Aug 2024 11:55:48 +0200 Subject: [PATCH 41/55] try to switch to PublishCodeCoverageResults version 2 --- .azure/scripts/coverage.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.azure/scripts/coverage.yml b/.azure/scripts/coverage.yml index 77c8ae1d8..2f68c2b35 100644 --- a/.azure/scripts/coverage.yml +++ b/.azure/scripts/coverage.yml @@ -28,18 +28,18 @@ steps: bash <(curl -s https://codecov.io/bash) -f coverage.xml -f coverage_py.xml -f coverage_java.xml -X gcov displayName: 'Report' -- task: PublishCodeCoverageResults@1 +- task: PublishCodeCoverageResults@2 inputs: codeCoverageTool: 'JaCoCo' summaryFileLocation: coverage_java.xml pathToSources: native/java -- task: PublishCodeCoverageResults@1 +- task: PublishCodeCoverageResults@2 inputs: codeCoverageTool: 'cobertura' summaryFileLocation: coverage.xml -- task: PublishCodeCoverageResults@1 +- task: PublishCodeCoverageResults@2 inputs: codeCoverageTool: 'cobertura' summaryFileLocation: coverage_py.xml From 640c65f20b144d7189309d1be91ce06d67ceb17e Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Tue, 20 Aug 2024 12:10:43 +0200 Subject: [PATCH 42/55] proper display name --- .azure/scripts/jdk.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.azure/scripts/jdk.yml b/.azure/scripts/jdk.yml index fcdaa327d..25121dfc2 100644 --- a/.azure/scripts/jdk.yml +++ b/.azure/scripts/jdk.yml @@ -9,11 +9,7 @@ steps: versionSpec: ${{ parameters.version }} jdkArchitectureOption: 'x64' jdkSourceOption: 'PreInstalled' -# FIXME: we'd want to stop the execution of the whole pipeline, if the JDK could not be set. -# - bash: exit 1 -# displayName: JDK ${{ parameters.version }} could not be set. -# condition: eq(variables['Agent.JobStatus'], 'SucceededWithIssues') - bash: | echo AGENT_JOBSTATUS = $AGENT_JOBSTATUS if [[ "$AGENT_JOBSTATUS" == "SucceededWithIssues" ]]; then exit 1; fi - displayName: JDK ${{ parameters.version }} could not be set. + displayName: JDK ${{ parameters.version }} set as JAVA_HOME. From 5b3d65bbdabf99c84dda8da49c30cdb96d36e05e Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Wed, 21 Aug 2024 01:36:27 +0200 Subject: [PATCH 43/55] minor --- jpype/_jvmfinder.py | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/jpype/_jvmfinder.py b/jpype/_jvmfinder.py index eda6af74c..1217b9b55 100644 --- a/jpype/_jvmfinder.py +++ b/jpype/_jvmfinder.py @@ -25,9 +25,11 @@ 'JVMNotFoundException', 'JVMNotSupportedException'] +from typing import Sequence + class JVMNotFoundException(ValueError): - """ Exception raised when no JVM was found in the search path. + """Exception raised when no JVM was found in the search path. This exception is raised when the all of the places searched did not contain a JVM. The locations searched depend on the machine architecture. @@ -37,7 +39,7 @@ class JVMNotFoundException(ValueError): class JVMNotSupportedException(ValueError): - """ Exception raised when the JVM is not supported. + """Exception raised when the JVM is not supported. This exception is raised after a search found a valid Java home directory was found, but the JVM shared library found is not supported. Typically @@ -48,8 +50,7 @@ class JVMNotSupportedException(ValueError): def getDefaultJVMPath() -> str: - """ - Retrieves the path to the default or first found JVM library + """Retrieves the path to the default or first found JVM library. Returns: The path to the JVM shared library file @@ -73,14 +74,12 @@ def getDefaultJVMPath() -> str: class JVMFinder: - """ - JVM library finder base class - """ + """JVM library finder base class.""" # Library file name - _libfile = "libjvm.so" + _libfile: str = "libjvm.so" # Predefined locations - _locations = ("/usr/lib/jvm", "/usr/java") + _locations: Sequence = ("/usr/lib/jvm", "/usr/java") def __init__(self): # Search methods @@ -88,12 +87,10 @@ def __init__(self): self._get_from_known_locations) def find_libjvm(self, java_home): - """ - Recursively looks for the given file + """Recursively looks for the given file. Parameters: java_home(str): A Java home folder - filename(str): filename: Name of the file to find Returns: The first found file path, or None @@ -244,9 +241,7 @@ def _get_from_known_locations(self): class LinuxJVMFinder(JVMFinder): - """ - Linux JVM library finder class - """ + """Linux JVM library finder class.""" # Java bin file _java = "/usr/bin/java" From 20f82271bbe57e692a64e6f97cfcecba29413b63 Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Wed, 21 Aug 2024 01:36:36 +0200 Subject: [PATCH 44/55] minor2 --- test/jpypetest/common.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/jpypetest/common.py b/test/jpypetest/common.py index 05e00e1e2..9531c615f 100644 --- a/test/jpypetest/common.py +++ b/test/jpypetest/common.py @@ -21,7 +21,6 @@ import jpype import logging from os import path -import sys import unittest # Extensively used as common.unittest. CLASSPATH = None @@ -143,7 +142,3 @@ def assertElementsAlmostEqual(self, a, b): def useEqualityFunc(self, func): return UseFunc(self, func, 'assertEqual') - - -if __name__ == '__main__': - unittest.main() From 146509d8566ae8c8db4048329a117df9ab03461e Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Wed, 21 Aug 2024 01:37:14 +0200 Subject: [PATCH 45/55] removed obsolete tests (nobody is going to fix or rewrite) --- test/jpypetest/test_jvmfinder.py | 72 +++++--------------------------- 1 file changed, 10 insertions(+), 62 deletions(-) diff --git a/test/jpypetest/test_jvmfinder.py b/test/jpypetest/test_jvmfinder.py index d833b4582..8c1b3c34d 100644 --- a/test/jpypetest/test_jvmfinder.py +++ b/test/jpypetest/test_jvmfinder.py @@ -16,15 +16,15 @@ # # ***************************************************************************** # part of JPype1; author Martin K. Scherer; 2014 +# from unittest import mock +import os import pathlib import sys import unittest from unittest import mock -import common -import os -import jpype._jvmfinder -from jpype._jvmfinder import * +from jpype._jvmfinder import (LinuxJVMFinder, JVMNotSupportedException, DarwinJVMFinder, + WindowsJVMFinder) class JVMFinderTest(unittest.TestCase): @@ -52,7 +52,7 @@ def test_find_libjvm(self): # contains broken and working jvms mockwalk.return_value = walk_fake - finder = jpype._jvmfinder.LinuxJVMFinder() + finder = LinuxJVMFinder() p = finder.find_libjvm('arbitrary java home') self.assertEqual( p, os.path.join('jre/lib/amd64/server', 'libjvm.so'), 'wrong jvm returned') @@ -62,7 +62,7 @@ def test_find_libjvm(self): walk_fake[-1] = ((), (), (),) mockwalk.return_value = walk_fake - finder = jpype._jvmfinder.LinuxJVMFinder() + finder = LinuxJVMFinder() with self.assertRaises(JVMNotSupportedException) as context: finder.find_libjvm('arbitrary java home') @@ -81,7 +81,7 @@ def test_get_from_bin(self, mock_real_path, mock_path_exists, mock_os_walk): mock_path_exists.return_value = True mock_real_path.return_value = '/usr/lib/jvm/java-6-openjdk-amd64/bin/java' - finder = jpype._jvmfinder.LinuxJVMFinder() + finder = LinuxJVMFinder() p = finder._get_from_bin() self.assertEqual( @@ -94,7 +94,7 @@ def testDarwinBinary(self, mock_mac_ver): expected = '/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home\n' - finder = jpype._jvmfinder.DarwinJVMFinder() + finder = DarwinJVMFinder() # fake check_output with mock.patch('subprocess.check_output') as mock_checkoutput: @@ -107,29 +107,8 @@ def testDarwinBinary(self, mock_mac_ver): p = finder._javahome_binary() self.assertEqual(p, None) - # FIXME this is testing the details of the implementation rather than the results. - # it is included only for coverage purposes. Revise this to be a more meaningful test - # next time it breaks. - # FIXME this test does passes locally but not in the CI. Disabling for now. - @common.unittest.skip # type: ignore - def testPlatform(self): - with mock.patch('jpype._jvmfinder.sys') as mocksys, mock.patch('jpype._jvmfinder.WindowsJVMFinder') as finder: - mocksys.platform = 'win32' - jpype._jvmfinder.getDefaultJVMPath() - self.assertIn(finder().get_jvm_path, finder.mock_calls) - - with mock.patch('jpype._jvmfinder.sys') as mocksys, mock.patch('jpype._jvmfinder.LinuxJVMFinder') as finder: - mocksys.platform = 'linux' - getDefaultJVMPath() - self.assertIn(finder().get_jvm_path, finder.mock_calls) - - with mock.patch('jpype._jvmfinder.sys') as mocksys, mock.patch('jpype._jvmfinder.DarwinJVMFinder') as finder: - mocksys.platform = 'darwin' - getDefaultJVMPath() - self.assertIn(finder().get_jvm_path, finder.mock_calls) - def testLinuxGetFromBin(self): - finder = jpype._jvmfinder.LinuxJVMFinder() + finder = LinuxJVMFinder() def f(s): return s @@ -144,40 +123,9 @@ def f(s): self.assertEqual( pathmock.dirname.mock_calls[0][1], (finder._java,)) - # FIXME this test is faking files using the mock system. Replace it with stub - # files so that we have a more accurate test rather than just testing the implementation. - # FIXME this fails in the CI but works locally. Disabling this for now. - @common.unittest.skip # type: ignore - def testCheckArch(self): - import struct - with mock.patch("builtins.open", mock.mock_open(read_data="data")) as mock_file, \ - self.assertRaises(JVMNotSupportedException): - jpype._jvmfinder._checkJVMArch('path', 2**32) - - data = struct.pack(' Date: Wed, 21 Aug 2024 01:37:32 +0200 Subject: [PATCH 46/55] added java version fixture --- test/jpypetest/conftest.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/jpypetest/conftest.py b/test/jpypetest/conftest.py index 2661b9062..b77f02072 100755 --- a/test/jpypetest/conftest.py +++ b/test/jpypetest/conftest.py @@ -16,6 +16,7 @@ # # ***************************************************************************** import pytest + import common @@ -43,3 +44,13 @@ def common_opts(request): request.cls._convertStrings = request.config.getoption("--convertStrings") request.cls._jacoco = request.config.getoption("--jacoco") request.cls._checkjni = request.config.getoption("--checkjni") + + +@pytest.fixture(scope="session", autouse=True) +def java_version(request): + import subprocess, sys + java_version = subprocess.check_output([sys.executable, "-c", + "import jpype; jpype.startJVM(); print(jpype.java.lang.System.getProperty('java.version'))"]) + print("java_version", java_version) + request._java_version = java_version[0] + yield java_version \ No newline at end of file From b3a480238833cbea2fd62ac7f7f2c0b05ed31169 Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Wed, 21 Aug 2024 12:57:25 +0200 Subject: [PATCH 47/55] skip --- test/jpypetest/conftest.py | 16 +++++++++------- test/jpypetest/test_sql_sqlite.py | 20 +++++++++++++------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/test/jpypetest/conftest.py b/test/jpypetest/conftest.py index b77f02072..051cff752 100755 --- a/test/jpypetest/conftest.py +++ b/test/jpypetest/conftest.py @@ -15,6 +15,8 @@ # See NOTICE file for details. # # ***************************************************************************** +from functools import cache + import pytest import common @@ -46,11 +48,11 @@ def common_opts(request): request.cls._checkjni = request.config.getoption("--checkjni") -@pytest.fixture(scope="session", autouse=True) -def java_version(request): +#@pytest.fixture(scope="session", autouse=True) +@cache +def java_version(): + print("hi from java_version()") import subprocess, sys - java_version = subprocess.check_output([sys.executable, "-c", - "import jpype; jpype.startJVM(); print(jpype.java.lang.System.getProperty('java.version'))"]) - print("java_version", java_version) - request._java_version = java_version[0] - yield java_version \ No newline at end of file + java_version = str(subprocess.check_output([sys.executable, "-c", + "import jpype; jpype.startJVM(); print(jpype.java.lang.System.getProperty('java.version'))"])) + return java_version.split(".") diff --git a/test/jpypetest/test_sql_sqlite.py b/test/jpypetest/test_sql_sqlite.py index 530987037..f845f75c9 100644 --- a/test/jpypetest/test_sql_sqlite.py +++ b/test/jpypetest/test_sql_sqlite.py @@ -3,11 +3,14 @@ import datetime import decimal import threading +from unittest import SkipTest + +import pytest import common import jpype import jpype.dbapi2 as dbapi2 -from jpype import java, isJVMStarted +from jpype import java from jpype.types import * try: @@ -18,12 +21,17 @@ db_name = "jdbc:sqlite::memory:" +def setUpModule(module): + from conftest import java_version + version = java_version() + print("setup module: jdk version", version) + if version[0] == "8": + pytest.skip("jdk8 unsupported", allow_module_level=True) -if isJVMStarted(): - java_version = str(jpype.java.lang.System.getProperty("java.version")).split(".") + # raise common.unittest.SkipTest("SQLite unsupported for JDK 8.") - if java_version[0] == "8":# and sys.platform == "win": - raise common.unittest.SkipTest("sqlite unsupported on this config.") +#def setUpModule(java_version): +# print("setuppppp", setUpModule.__name__) class ConnectTestCase(common.JPypeTestCase): @@ -32,8 +40,6 @@ def setUp(self): if common.fast: raise common.unittest.SkipTest("fast") - - def testConnect(self): cx = dbapi2.connect(db_name) self.assertIsInstance(cx, dbapi2.Connection) From d171b5008720a32b268be4d8402cabc5aa83abbc Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Thu, 22 Aug 2024 03:54:11 +0200 Subject: [PATCH 48/55] refactor --- test/jpypetest/common.py | 13 +++++++++++++ test/jpypetest/conftest.py | 11 ----------- test/jpypetest/test_sql_sqlite.py | 4 ++-- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/test/jpypetest/common.py b/test/jpypetest/common.py index 9531c615f..6b987c6f9 100644 --- a/test/jpypetest/common.py +++ b/test/jpypetest/common.py @@ -15,6 +15,7 @@ # See NOTICE file for details. # # ***************************************************************************** +from functools import lru_cache import pytest import _jpype @@ -142,3 +143,15 @@ def assertElementsAlmostEqual(self, a, b): def useEqualityFunc(self, func): return UseFunc(self, func, 'assertEqual') + + +@lru_cache(1) +def java_version(): + import subprocess + import sys + java_version = str(subprocess.check_output([sys.executable, "-c", + "import jpype; jpype.startJVM(); " + "print(jpype.java.lang.System.getProperty('java.version'))"]), + encoding='ascii') + print("java_version:", java_version) + return tuple(map(int, java_version.split("."))) diff --git a/test/jpypetest/conftest.py b/test/jpypetest/conftest.py index 051cff752..e613f87d9 100755 --- a/test/jpypetest/conftest.py +++ b/test/jpypetest/conftest.py @@ -15,7 +15,6 @@ # See NOTICE file for details. # # ***************************************************************************** -from functools import cache import pytest @@ -46,13 +45,3 @@ def common_opts(request): request.cls._convertStrings = request.config.getoption("--convertStrings") request.cls._jacoco = request.config.getoption("--jacoco") request.cls._checkjni = request.config.getoption("--checkjni") - - -#@pytest.fixture(scope="session", autouse=True) -@cache -def java_version(): - print("hi from java_version()") - import subprocess, sys - java_version = str(subprocess.check_output([sys.executable, "-c", - "import jpype; jpype.startJVM(); print(jpype.java.lang.System.getProperty('java.version'))"])) - return java_version.split(".") diff --git a/test/jpypetest/test_sql_sqlite.py b/test/jpypetest/test_sql_sqlite.py index f845f75c9..c485f680e 100644 --- a/test/jpypetest/test_sql_sqlite.py +++ b/test/jpypetest/test_sql_sqlite.py @@ -22,10 +22,10 @@ db_name = "jdbc:sqlite::memory:" def setUpModule(module): - from conftest import java_version + from common import java_version version = java_version() print("setup module: jdk version", version) - if version[0] == "8": + if version[0] == 8: pytest.skip("jdk8 unsupported", allow_module_level=True) # raise common.unittest.SkipTest("SQLite unsupported for JDK 8.") From 5f474f0ca2ed919c081844ce733f0b35c3d986e8 Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Thu, 22 Aug 2024 04:05:55 +0200 Subject: [PATCH 49/55] fix version check --- test/jpypetest/test_sql_sqlite.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/test/jpypetest/test_sql_sqlite.py b/test/jpypetest/test_sql_sqlite.py index c485f680e..663028d44 100644 --- a/test/jpypetest/test_sql_sqlite.py +++ b/test/jpypetest/test_sql_sqlite.py @@ -24,15 +24,9 @@ def setUpModule(module): from common import java_version version = java_version() - print("setup module: jdk version", version) - if version[0] == 8: + if version[0] == 1 and version[1] == 8: pytest.skip("jdk8 unsupported", allow_module_level=True) - # raise common.unittest.SkipTest("SQLite unsupported for JDK 8.") - -#def setUpModule(java_version): -# print("setuppppp", setUpModule.__name__) - class ConnectTestCase(common.JPypeTestCase): def setUp(self): From 29838e8c7bff34d974bf5cb7edca154342eb344e Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Thu, 22 Aug 2024 04:11:37 +0200 Subject: [PATCH 50/55] cleanup --- test/jpypetest/common.py | 1 - test/jpypetest/test_sql_h2.py | 9 +++++++++ test/jpypetest/test_sql_hsqldb.py | 8 ++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/test/jpypetest/common.py b/test/jpypetest/common.py index 6b987c6f9..8f7d45b2d 100644 --- a/test/jpypetest/common.py +++ b/test/jpypetest/common.py @@ -153,5 +153,4 @@ def java_version(): "import jpype; jpype.startJVM(); " "print(jpype.java.lang.System.getProperty('java.version'))"]), encoding='ascii') - print("java_version:", java_version) return tuple(map(int, java_version.split("."))) diff --git a/test/jpypetest/test_sql_h2.py b/test/jpypetest/test_sql_h2.py index e8471ca73..9c984cdb8 100644 --- a/test/jpypetest/test_sql_h2.py +++ b/test/jpypetest/test_sql_h2.py @@ -1,5 +1,7 @@ # This file is Public Domain and may be used without restrictions, # because nobody should have to waste their lives typing this again. +import pytest + import jpype from jpype.types import * from jpype import java @@ -19,6 +21,13 @@ db_name = "jdbc:h2:mem:testdb" +def setUpModule(module): + from common import java_version + version = java_version() + if version[0] == 1 and version[1] == 8: + pytest.skip("jdk8 unsupported", allow_module_level=True) + + class ConnectTestCase(common.JPypeTestCase): def setUp(self): diff --git a/test/jpypetest/test_sql_hsqldb.py b/test/jpypetest/test_sql_hsqldb.py index 231a3a8a0..c51950785 100644 --- a/test/jpypetest/test_sql_hsqldb.py +++ b/test/jpypetest/test_sql_hsqldb.py @@ -24,6 +24,14 @@ #first = "jdbc:derby:memory:myDb;create=True" +def setUpModule(module): + from common import java_version + import pytest + version = java_version() + if version[0] == 1 and version[1] == 8: + pytest.skip("jdk8 unsupported", allow_module_level=True) + + @common.unittest.skipUnless(zlib, "requires zlib") class ConnectTestCase(common.JPypeTestCase): def setUp(self): From 0e18bce46431725503fd728457149e206879c3dd Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Thu, 22 Aug 2024 04:16:11 +0200 Subject: [PATCH 51/55] minor --- .azure/scripts/test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.azure/scripts/test.yml b/.azure/scripts/test.yml index 3535cf022..4a2e3df39 100644 --- a/.azure/scripts/test.yml +++ b/.azure/scripts/test.yml @@ -25,12 +25,12 @@ steps: - script: | python -m pytest -v --junit-xml=build/test/test.xml test/jpypetest --checkjni - displayName: 'Test JDK $(jdk.version)' + displayName: 'Test JDK $(jdk.version) and Python $(python.version)' condition: eq(variables['jpypetest.fast'], 'false') - script: | python -m pytest -v --junit-xml=build/test/test.xml test/jpypetest --checkjni --fast - displayName: 'Test JDK $(jdk.version) (fast)' + displayName: 'Test JDK $(jdk.version) and Python $(python.version) (fast)' condition: eq(variables['jpypetest.fast'], 'true') # presence of jpype/ seems to confuse entry_points so `cd` elsewhere From 80769f6746cbaab3ece789bfcc4e1ab68b6a482f Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Thu, 22 Aug 2024 04:21:55 +0200 Subject: [PATCH 52/55] minor2 --- test/jpypetest/test_sql_sqlite.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/jpypetest/test_sql_sqlite.py b/test/jpypetest/test_sql_sqlite.py index 663028d44..2de96715c 100644 --- a/test/jpypetest/test_sql_sqlite.py +++ b/test/jpypetest/test_sql_sqlite.py @@ -3,7 +3,6 @@ import datetime import decimal import threading -from unittest import SkipTest import pytest @@ -11,7 +10,7 @@ import jpype import jpype.dbapi2 as dbapi2 from jpype import java -from jpype.types import * +from jpype.types import JArray, JByte try: import zlib From 69bbe2e4bee8670c3005f6646820344ee0aed4dd Mon Sep 17 00:00:00 2001 From: "Martin K. Scherer" Date: Thu, 22 Aug 2024 04:48:11 +0200 Subject: [PATCH 53/55] fix mypy --- jpype/_jvmfinder.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/jpype/_jvmfinder.py b/jpype/_jvmfinder.py index 1217b9b55..dcf423345 100644 --- a/jpype/_jvmfinder.py +++ b/jpype/_jvmfinder.py @@ -25,7 +25,7 @@ 'JVMNotFoundException', 'JVMNotSupportedException'] -from typing import Sequence +from typing import Sequence, Tuple class JVMNotFoundException(ValueError): @@ -79,7 +79,7 @@ class JVMFinder: _libfile: str = "libjvm.so" # Predefined locations - _locations: Sequence = ("/usr/lib/jvm", "/usr/java") + _locations: Tuple[str, ...] = ("/usr/lib/jvm", "/usr/java") def __init__(self): # Search methods @@ -285,7 +285,7 @@ class DarwinJVMFinder(LinuxJVMFinder): # Library file name _libfile = "libjli.dylib" # Predefined locations - _locations = ('/Library/Java/JavaVirtualMachines',) + _locations = ('/Library/Java/JavaVirtualMachines',) # type: ignore def __init__(self): """ From 507c42f67801db847bd3c95df7b2c901dbfbd877 Mon Sep 17 00:00:00 2001 From: Andrew Strelsky <46897303+astrelsky@users.noreply.github.com> Date: Mon, 16 Sep 2024 08:22:55 -0400 Subject: [PATCH 54/55] prevent misuse of PyTuple_Pack --- native/common/include/jpype.h | 7 ++++++- native/common/jp_class.cpp | 6 +++--- native/common/jp_classhints.cpp | 2 +- native/common/jp_exception.cpp | 2 +- native/python/jp_pythontypes.cpp | 2 +- native/python/pyjp_array.cpp | 4 ++-- native/python/pyjp_buffer.cpp | 2 +- native/python/pyjp_char.cpp | 14 +++++++------- native/python/pyjp_class.cpp | 10 +++++----- native/python/pyjp_method.cpp | 8 ++++---- native/python/pyjp_number.cpp | 14 +++++++------- native/python/pyjp_object.cpp | 4 ++-- native/python/pyjp_package.cpp | 8 ++++---- native/python/pyjp_proxy.cpp | 2 +- 14 files changed, 45 insertions(+), 40 deletions(-) diff --git a/native/common/include/jpype.h b/native/common/include/jpype.h index 406e4b67f..179efa201 100644 --- a/native/common/include/jpype.h +++ b/native/common/include/jpype.h @@ -176,6 +176,11 @@ struct _object; using PyObject = _object; #endif +template +static inline constexpr PyObject *JPPyTuple_Pack(T... args) { + return PyTuple_Pack(sizeof...(T), args...); +} + // Base utility headers #include "jp_javaframe.h" #include "jp_context.h" @@ -196,4 +201,4 @@ using PyObject = _object; // Primitives classes #include "jp_primitivetype.h" -#endif // _JPYPE_H_ \ No newline at end of file +#endif // _JPYPE_H_ diff --git a/native/common/jp_class.cpp b/native/common/jp_class.cpp index 265ee2757..4b540572b 100644 --- a/native/common/jp_class.cpp +++ b/native/common/jp_class.cpp @@ -372,15 +372,15 @@ JPPyObject JPClass::convertToPythonObject(JPJavaFrame& frame, jvalue value, bool jstring m = frame.getMessage((jthrowable) value.l); if (m != nullptr) { - tuple0 = JPPyObject::call(PyTuple_Pack(1, + tuple0 = JPPyObject::call(JPPyTuple_Pack( JPPyString::fromStringUTF8(frame.toStringUTF8(m)).get())); } else { - tuple0 = JPPyObject::call(PyTuple_Pack(1, + tuple0 = JPPyObject::call(JPPyTuple_Pack( JPPyString::fromStringUTF8(frame.toString(value.l)).get())); } } - JPPyObject tuple1 = JPPyObject::call(PyTuple_Pack(2, + JPPyObject tuple1 = JPPyObject::call(JPPyTuple_Pack( _JObjectKey, tuple0.get())); // Exceptions need new and init obj = JPPyObject::call(PyObject_Call(wrapper.get(), tuple1.get(), nullptr)); diff --git a/native/common/jp_classhints.cpp b/native/common/jp_classhints.cpp index c719e6b9e..8548723c9 100644 --- a/native/common/jp_classhints.cpp +++ b/native/common/jp_classhints.cpp @@ -146,7 +146,7 @@ class JPPythonConversion : public JPConversion { JP_TRACE_IN("JPPythonConversion::convert"); JPClass *cls = ((JPClass*) match.closure); - JPPyObject args = JPPyObject::call(PyTuple_Pack(2, + JPPyObject args = JPPyObject::call(JPPyTuple_Pack( cls->getHost(), match.object)); JPPyObject ret = JPPyObject::call(PyObject_Call(method_.get(), args.get(), nullptr)); JPValue *value = PyJPValue_getJavaSlot(ret.get()); diff --git a/native/common/jp_exception.cpp b/native/common/jp_exception.cpp index a99964c69..a6032faef 100644 --- a/native/common/jp_exception.cpp +++ b/native/common/jp_exception.cpp @@ -512,7 +512,7 @@ PyObject *tb_create( JPPyObject lasti = JPPyObject::claim(PyLong_FromLong(PyFrame_GetLasti(pframe))); #endif JPPyObject linenuma = JPPyObject::claim(PyLong_FromLong(linenum)); - JPPyObject tuple = JPPyObject::call(PyTuple_Pack(4, Py_None, frame.get(), lasti.get(), linenuma.get())); + JPPyObject tuple = JPPyObject::call(JPPyTuple_Pack(Py_None, frame.get(), lasti.get(), linenuma.get())); JPPyObject traceback = JPPyObject::accept(PyObject_Call((PyObject*) &PyTraceBack_Type, tuple.get(), NULL)); // We could fail in process diff --git a/native/python/jp_pythontypes.cpp b/native/python/jp_pythontypes.cpp index 01178cb93..ee9c8971b 100644 --- a/native/python/jp_pythontypes.cpp +++ b/native/python/jp_pythontypes.cpp @@ -483,7 +483,7 @@ void JPPyErrFrame::normalize() // we have forced it to realize the exception. if (!PyExceptionInstance_Check(m_ExceptionValue.get())) { - JPPyObject args = JPPyObject::call(PyTuple_Pack(1, m_ExceptionValue.get())); + JPPyObject args = JPPyObject::call(JPPyTuple_Pack(m_ExceptionValue.get())); m_ExceptionValue = JPPyObject::call(PyObject_Call(m_ExceptionClass.get(), args.get(), nullptr)); PyException_SetTraceback(m_ExceptionValue.get(), m_ExceptionTrace.get()); JPPyErr::restore(m_ExceptionClass, m_ExceptionValue, m_ExceptionTrace); diff --git a/native/python/pyjp_array.cpp b/native/python/pyjp_array.cpp index 17066531c..c190066bb 100644 --- a/native/python/pyjp_array.cpp +++ b/native/python/pyjp_array.cpp @@ -484,7 +484,7 @@ static PyType_Spec arrayPrimSpec = { void PyJPArray_initType(PyObject * module) { - JPPyObject tuple = JPPyObject::call(PyTuple_Pack(1, PyJPObject_Type)); + JPPyObject tuple = JPPyObject::call(JPPyTuple_Pack(PyJPObject_Type)); PyJPArray_Type = (PyTypeObject*) PyJPClass_FromSpecWithBases(&arraySpec, tuple.get()); JP_PY_CHECK(); #if PY_VERSION_HEX < 0x03090000 @@ -493,7 +493,7 @@ void PyJPArray_initType(PyObject * module) PyModule_AddObject(module, "_JArray", (PyObject*) PyJPArray_Type); JP_PY_CHECK(); - tuple = JPPyObject::call(PyTuple_Pack(1, PyJPArray_Type)); + tuple = JPPyObject::call(JPPyTuple_Pack(PyJPArray_Type)); PyJPArrayPrimitive_Type = (PyTypeObject*) PyJPClass_FromSpecWithBases(&arrayPrimSpec, tuple.get()); #if PY_VERSION_HEX < 0x03090000 diff --git a/native/python/pyjp_buffer.cpp b/native/python/pyjp_buffer.cpp index fdf6dc56b..a69daa24e 100644 --- a/native/python/pyjp_buffer.cpp +++ b/native/python/pyjp_buffer.cpp @@ -143,7 +143,7 @@ static PyType_Spec bufferSpec = { void PyJPBuffer_initType(PyObject * module) { - JPPyObject tuple = JPPyObject::call(PyTuple_Pack(1, PyJPObject_Type)); + JPPyObject tuple = JPPyObject::call(JPPyTuple_Pack(PyJPObject_Type)); PyJPBuffer_Type = (PyTypeObject*) PyJPClass_FromSpecWithBases(&bufferSpec, tuple.get()); #if PY_VERSION_HEX < 0x03090000 PyJPBuffer_Type->tp_as_buffer = &directBuffer; diff --git a/native/python/pyjp_char.cpp b/native/python/pyjp_char.cpp index d6d21dcf0..2790879cf 100644 --- a/native/python/pyjp_char.cpp +++ b/native/python/pyjp_char.cpp @@ -91,7 +91,7 @@ PyObject *PyJPChar_Create(PyTypeObject *type, Py_UCS2 p) self->m_Data[3] = 0; // Values taken from internal/cpython/unicode.h - + // Mark the type in unicode _PyUnicode_LENGTH(self) = 1; _PyUnicode_HASH(self) = -1; @@ -120,7 +120,7 @@ PyObject *PyJPChar_Create(PyTypeObject *type, Py_UCS2 p) char *data = (char*) ( ((PyCompactUnicodeObject*) self) + 1); data[0] = (char) p; data[1] = 0; - + #if PY_VERSION_HEX < 0x030c0000 _PyUnicode_WSTR_LENGTH(self) = 0; _PyUnicode_WSTR(self) = nullptr; @@ -212,7 +212,7 @@ static PyObject * PyJPChar_new(PyTypeObject *type, PyObject *pyargs, PyObject * if (cv != (Py_UCS4) - 1) { JPPyObject v = JPPyObject::call(PyLong_FromLong(cv)); - JPPyObject args0 = JPPyObject::call(PyTuple_Pack(1, v.get())); + JPPyObject args0 = JPPyObject::call(JPPyTuple_Pack(v.get())); JPPyObjectVector args(args0.get()); jv = cls->newInstance(frame, args); } else if (PyIndex_Check(in)) @@ -222,7 +222,7 @@ static PyObject * PyJPChar_new(PyTypeObject *type, PyObject *pyargs, PyObject * } else if (PyFloat_Check(in)) { JPPyObject v = JPPyObject::call(PyNumber_Long(in)); - JPPyObject args0 = JPPyObject::call(PyTuple_Pack(1, v.get())); + JPPyObject args0 = JPPyObject::call(JPPyTuple_Pack(v.get())); JPPyObjectVector args(args0.get()); jv = cls->newInstance(frame, args); } else @@ -325,7 +325,7 @@ static PyObject *apply(PyObject *first, PyObject *second, PyObject* (*func)(PyOb JPValue *slot0 = PyJPValue_getJavaSlot(first); JPValue *slot1 = PyJPValue_getJavaSlot(second); if (slot0 != nullptr && slot1 != nullptr) - { + { if (assertNotNull(slot0)) return nullptr; if (assertNotNull(slot1)) @@ -385,7 +385,7 @@ static PyObject *PyJPChar_add(PyObject *first, PyObject *second) JPValue *slot0 = PyJPValue_getJavaSlot(first); JPValue *slot1 = PyJPValue_getJavaSlot(second); if (slot1 != nullptr && slot0 != nullptr) - { + { if (assertNotNull(slot0)) return nullptr; if (assertNotNull(slot1)) @@ -655,7 +655,7 @@ static PyType_Spec charSpec = { void PyJPChar_initType(PyObject* module) { // We will inherit from str and JObject - PyObject *bases = PyTuple_Pack(2, &PyUnicode_Type, PyJPObject_Type); + PyObject *bases = JPPyTuple_Pack(&PyUnicode_Type, PyJPObject_Type); PyJPChar_Type = (PyTypeObject*) PyJPClass_FromSpecWithBases(&charSpec, bases); Py_DECREF(bases); JP_PY_CHECK(); // GCOVR_EXCL_LINE diff --git a/native/python/pyjp_class.cpp b/native/python/pyjp_class.cpp index fc633e11c..cdd7f8e0e 100644 --- a/native/python/pyjp_class.cpp +++ b/native/python/pyjp_class.cpp @@ -148,7 +148,7 @@ PyObject* PyJPClass_FromSpecWithBases(PyType_Spec *spec, PyObject *bases) heap->ht_name = heap->ht_qualname; Py_INCREF(heap->ht_name); if (bases == nullptr) - type->tp_bases = PyTuple_Pack(1, (PyObject*) & PyBaseObject_Type); + type->tp_bases = JPPyTuple_Pack((PyObject*) & PyBaseObject_Type); else { type->tp_bases = bases; @@ -935,7 +935,7 @@ static PyObject *PyJPClass_getDoc(PyJPClass *self, void *ctxt) // Pack the arguments { JP_TRACE("Pack arguments"); - JPPyObject args = JPPyObject::call(PyTuple_Pack(1, self)); + JPPyObject args = JPPyObject::call(JPPyTuple_Pack(self)); JP_TRACE("Call Python"); self->m_Doc = PyObject_Call(_JClassDoc, args.get(), nullptr); Py_XINCREF(self->m_Doc); @@ -1021,7 +1021,7 @@ static PyType_Spec classSpec = { void PyJPClass_initType(PyObject* module) { - PyObject *bases = PyTuple_Pack(1, &PyType_Type); + PyObject *bases = JPPyTuple_Pack(&PyType_Type); PyJPClass_Type = (PyTypeObject*) PyType_FromSpecWithBases(&classSpec, bases); Py_DECREF(bases); JP_PY_CHECK(); @@ -1160,7 +1160,7 @@ void PyJPClass_hook(JPJavaFrame &frame, JPClass* cls) JPPyObject members = JPPyObject::call(PyDict_New()); - JPPyObject args = JPPyObject::call(PyTuple_Pack(3, + JPPyObject args = JPPyObject::call(JPPyTuple_Pack( JPPyString::fromStringUTF8(cls->getCanonicalName()).get(), PyJPClass_getBases(frame, cls).get(), members.get())); @@ -1216,6 +1216,6 @@ void PyJPClass_hook(JPJavaFrame &frame, JPClass* cls) // Call the post load routine to attach inner classes JP_TRACE("call post"); - args = JPPyObject::call(PyTuple_Pack(1, self)); + args = JPPyObject::call(JPPyTuple_Pack(self)); JPPyObject rc2 = JPPyObject::call(PyObject_Call(_JClassPost, args.get(), nullptr)); } diff --git a/native/python/pyjp_method.cpp b/native/python/pyjp_method.cpp index 9edc7e835..6af47040f 100644 --- a/native/python/pyjp_method.cpp +++ b/native/python/pyjp_method.cpp @@ -216,7 +216,7 @@ static PyObject *PyJPMethod_getDoc(PyJPMethod *self, void *ctxt) jvalue v; v.l = (jobject) self->m_Method->getClass()->getJavaClass(); JPPyObject obj(context->_java_lang_Class->convertToPythonObject(frame, v, true)); - JPPyObject args = JPPyObject::call(PyTuple_Pack(3, + JPPyObject args = JPPyObject::call(JPPyTuple_Pack( self, obj.get(), ov.get())); JP_TRACE("Call Python"); self->m_Doc = PyObject_Call(_JMethodDoc, args.get(), nullptr); @@ -268,7 +268,7 @@ PyObject *PyJPMethod_getAnnotations(PyJPMethod *self, void *ctxt) jvalue v; v.l = (jobject) self->m_Method->getClass()->getJavaClass(); JPPyObject obj(context->_java_lang_Class->convertToPythonObject(frame, v, true)); - JPPyObject args = JPPyObject::call(PyTuple_Pack(3, + JPPyObject args = JPPyObject::call(JPPyTuple_Pack( self, obj.get(), ov.get())); JP_TRACE("Call Python"); self->m_Annotations = PyObject_Call(_JMethodAnnotations, args.get(), nullptr); @@ -293,7 +293,7 @@ PyObject *PyJPMethod_getCodeAttr(PyJPMethod *self, void *ctx, const char *attr) PyJPModule_getContext(); if (self->m_CodeRep == nullptr) { - JPPyObject args = JPPyObject::call(PyTuple_Pack(1, self)); + JPPyObject args = JPPyObject::call(JPPyTuple_Pack(self)); JP_TRACE("Call Python"); self->m_CodeRep = PyObject_Call(_JMethodCode, args.get(), nullptr); } @@ -396,7 +396,7 @@ void PyJPMethod_initType(PyObject* module) // We inherit from PyFunction_Type just so we are an instance // for purposes of inspect and tab completion tools. But // we will just ignore their memory layout as we have our own. - JPPyObject tuple = JPPyObject::call(PyTuple_Pack(1, &PyFunction_Type)); + JPPyObject tuple = JPPyObject::call(JPPyTuple_Pack(&PyFunction_Type)); unsigned long flags = PyFunction_Type.tp_flags; PyFunction_Type.tp_flags |= Py_TPFLAGS_BASETYPE; PyJPMethod_Type = (PyTypeObject*) PyType_FromSpecWithBases(&methodSpec, tuple.get()); diff --git a/native/python/pyjp_number.cpp b/native/python/pyjp_number.cpp index 5f342b83c..17fb7da85 100644 --- a/native/python/pyjp_number.cpp +++ b/native/python/pyjp_number.cpp @@ -270,7 +270,7 @@ static PyObject *PyJPBoolean_new(PyTypeObject *type, PyObject *args, PyObject *k return nullptr; } int i = PyObject_IsTrue(PyTuple_GetItem(args, 0)); - PyObject *args2 = PyTuple_Pack(1, PyLong_FromLong(i)); + PyObject *args2 = JPPyTuple_Pack(PyLong_FromLong(i)); self = JPPyObject::call(PyLong_Type.tp_new(type, args2, kwargs)); Py_DECREF(args2); JPClass *cls = PyJPClass_getJPClass((PyObject*) type); @@ -373,21 +373,21 @@ void PyJPNumber_initType(PyObject* module) { PyObject *bases; - bases = PyTuple_Pack(2, &PyLong_Type, PyJPObject_Type); + bases = JPPyTuple_Pack(&PyLong_Type, PyJPObject_Type); PyJPNumberLong_Type = (PyTypeObject*) PyJPClass_FromSpecWithBases(&numberLongSpec, bases); Py_DECREF(bases); JP_PY_CHECK(); // GCOVR_EXCL_LINE PyModule_AddObject(module, "_JNumberLong", (PyObject*) PyJPNumberLong_Type); JP_PY_CHECK(); // GCOVR_EXCL_LINE - bases = PyTuple_Pack(2, &PyFloat_Type, PyJPObject_Type); + bases = JPPyTuple_Pack(&PyFloat_Type, PyJPObject_Type); PyJPNumberFloat_Type = (PyTypeObject*) PyJPClass_FromSpecWithBases(&numberFloatSpec, bases); Py_DECREF(bases); JP_PY_CHECK(); // GCOVR_EXCL_LINE PyModule_AddObject(module, "_JNumberFloat", (PyObject*) PyJPNumberFloat_Type); JP_PY_CHECK(); // GCOVR_EXCL_LINE - bases = PyTuple_Pack(1, &PyLong_Type, PyJPObject_Type); + bases = JPPyTuple_Pack(&PyLong_Type, PyJPObject_Type); PyJPNumberBool_Type = (PyTypeObject*) PyJPClass_FromSpecWithBases(&numberBooleanSpec, bases); Py_DECREF(bases); JP_PY_CHECK(); // GCOVR_EXCL_LINE @@ -404,7 +404,7 @@ JPPyObject PyJPNumber_create(JPJavaFrame &frame, JPPyObject& wrapper, const JPVa jlong l = 0; if (value.getValue().l != nullptr) l = frame.CallBooleanMethodA(value.getJavaObject(), context->_java_lang_Boolean->m_BooleanValueID, nullptr); - PyObject *args = PyTuple_Pack(1, PyLong_FromLongLong(l)); + PyObject *args = JPPyTuple_Pack(PyLong_FromLongLong(l)); return JPPyObject::call(PyLong_Type.tp_new((PyTypeObject*) wrapper.get(), args, nullptr)); } if (PyObject_IsSubclass(wrapper.get(), (PyObject*) & PyLong_Type)) @@ -415,7 +415,7 @@ JPPyObject PyJPNumber_create(JPJavaFrame &frame, JPPyObject& wrapper, const JPVa auto* jb = dynamic_cast( value.getClass()); l = frame.CallLongMethodA(value.getJavaObject(), jb->m_LongValueID, nullptr); } - PyObject *args = PyTuple_Pack(1, PyLong_FromLongLong(l)); + PyObject *args = JPPyTuple_Pack(PyLong_FromLongLong(l)); return JPPyObject::call(PyLong_Type.tp_new((PyTypeObject*) wrapper.get(), args, nullptr)); } if (PyObject_IsSubclass(wrapper.get(), (PyObject*) & PyFloat_Type)) @@ -426,7 +426,7 @@ JPPyObject PyJPNumber_create(JPJavaFrame &frame, JPPyObject& wrapper, const JPVa auto* jb = dynamic_cast( value.getClass()); l = frame.CallDoubleMethodA(value.getJavaObject(), jb->m_DoubleValueID, nullptr); } - PyObject *args = PyTuple_Pack(1, PyFloat_FromDouble(l)); + PyObject *args = JPPyTuple_Pack(PyFloat_FromDouble(l)); return JPPyObject::call(PyFloat_Type.tp_new((PyTypeObject*) wrapper.get(), args, nullptr)); } JP_RAISE(PyExc_TypeError, "unable to convert"); //GCOVR_EXCL_LINE diff --git a/native/python/pyjp_object.cpp b/native/python/pyjp_object.cpp index ae2ffbe0d..220bf2fa6 100644 --- a/native/python/pyjp_object.cpp +++ b/native/python/pyjp_object.cpp @@ -366,13 +366,13 @@ void PyJPObject_initType(PyObject* module) PyModule_AddObject(module, "_JObject", (PyObject*) PyJPObject_Type); JP_PY_CHECK(); // GCOVR_EXCL_LINE - JPPyObject bases = JPPyObject::call(PyTuple_Pack(2, PyExc_Exception, PyJPObject_Type)); + JPPyObject bases = JPPyObject::call(JPPyTuple_Pack(PyExc_Exception, PyJPObject_Type)); PyJPException_Type = (PyTypeObject*) PyJPClass_FromSpecWithBases(&excSpec, bases.get()); JP_PY_CHECK(); // GCOVR_EXCL_LINE PyModule_AddObject(module, "_JException", (PyObject*) PyJPException_Type); JP_PY_CHECK(); // GCOVR_EXCL_LINE - bases = JPPyObject::call(PyTuple_Pack(1, PyJPObject_Type)); + bases = JPPyObject::call(JPPyTuple_Pack(PyJPObject_Type)); PyJPComparable_Type = (PyTypeObject*) PyJPClass_FromSpecWithBases(&comparableSpec, bases.get()); JP_PY_CHECK(); // GCOVR_EXCL_LINE PyModule_AddObject(module, "_JComparable", (PyObject*) PyJPComparable_Type); diff --git a/native/python/pyjp_package.cpp b/native/python/pyjp_package.cpp index 67cd17e3a..443173932 100644 --- a/native/python/pyjp_package.cpp +++ b/native/python/pyjp_package.cpp @@ -163,7 +163,7 @@ static PyObject *PyJPPackage_getattro(PyObject *self, PyObject *attr) JPPyErrFrame err; err.normalize(); err.clear(); - JPPyObject tuple0 = JPPyObject::call(PyTuple_Pack(3, self, attr, err.m_ExceptionValue.get())); + JPPyObject tuple0 = JPPyObject::call(JPPyTuple_Pack(self, attr, err.m_ExceptionValue.get())); PyObject *rc = PyObject_Call(h.get(), tuple0.get(), nullptr); if (rc == nullptr) return nullptr; @@ -182,7 +182,7 @@ static PyObject *PyJPPackage_getattro(PyObject *self, PyObject *attr) { JPPyObject u = JPPyObject::call(PyUnicode_FromFormat("%s.%U", PyModule_GetName(self), attr)); - JPPyObject args = JPPyObject::call(PyTuple_Pack(1, u.get())); + JPPyObject args = JPPyObject::call(JPPyTuple_Pack(u.get())); out = JPPyObject::call(PyObject_Call((PyObject*) PyJPPackage_Type, args.get(), nullptr)); } else { @@ -284,7 +284,7 @@ static PyObject *PyJPPackage_cast(PyObject *self, PyObject *other) PyObject* matmul = PyDict_GetItemString(dict, "__matmul__"); if (matmul == nullptr) Py_RETURN_NOTIMPLEMENTED; - JPPyObject args = JPPyObject::call(PyTuple_Pack(2, self, other)); + JPPyObject args = JPPyObject::call(JPPyTuple_Pack(self, other)); return PyObject_Call(matmul, args.get(), nullptr); JP_PY_CATCH(nullptr); } @@ -338,7 +338,7 @@ static PyType_Spec packageSpec = { void PyJPPackage_initType(PyObject* module) { // Inherit from module. - JPPyObject bases = JPPyObject::call(PyTuple_Pack(1, &PyModule_Type)); + JPPyObject bases = JPPyObject::call(JPPyTuple_Pack(&PyModule_Type)); packageSpec.basicsize = PyModule_Type.tp_basicsize; PyJPPackage_Type = (PyTypeObject*) PyType_FromSpecWithBases(&packageSpec, bases.get()); JP_PY_CHECK(); diff --git a/native/python/pyjp_proxy.cpp b/native/python/pyjp_proxy.cpp index 48603bbc5..fc79be213 100644 --- a/native/python/pyjp_proxy.cpp +++ b/native/python/pyjp_proxy.cpp @@ -173,7 +173,7 @@ PyType_Spec PyJPProxySpec = { void PyJPProxy_initType(PyObject* module) { - JPPyObject bases = JPPyObject::call(PyTuple_Pack(1, &PyBaseObject_Type)); + JPPyObject bases = JPPyObject::call(JPPyTuple_Pack(&PyBaseObject_Type)); PyJPProxy_Type = (PyTypeObject*) PyType_FromSpecWithBases(&PyJPProxySpec, bases.get()); JP_PY_CHECK(); PyModule_AddObject(module, "_JProxy", (PyObject*) PyJPProxy_Type); From 1b76a403dfa2a60f4e1ed1d0ef5f8bc85a5efba9 Mon Sep 17 00:00:00 2001 From: Andrew Strelsky <46897303+astrelsky@users.noreply.github.com> Date: Mon, 16 Sep 2024 18:15:38 -0400 Subject: [PATCH 55/55] return JPPyObject from JPPyTuple_Pack --- native/common/include/jpype.h | 7 ++++--- native/common/jp_class.cpp | 11 +++++------ native/common/jp_classhints.cpp | 3 +-- native/common/jp_exception.cpp | 2 +- native/python/jp_pythontypes.cpp | 2 +- native/python/pyjp_array.cpp | 4 ++-- native/python/pyjp_buffer.cpp | 2 +- native/python/pyjp_char.cpp | 9 ++++----- native/python/pyjp_class.cpp | 18 ++++++++++-------- native/python/pyjp_method.cpp | 10 ++++------ native/python/pyjp_number.cpp | 29 ++++++++++++----------------- native/python/pyjp_object.cpp | 4 ++-- native/python/pyjp_package.cpp | 8 ++++---- native/python/pyjp_proxy.cpp | 2 +- 14 files changed, 52 insertions(+), 59 deletions(-) diff --git a/native/common/include/jpype.h b/native/common/include/jpype.h index 179efa201..861831040 100644 --- a/native/common/include/jpype.h +++ b/native/common/include/jpype.h @@ -176,9 +176,11 @@ struct _object; using PyObject = _object; #endif +#include "jp_pythontypes.h" + template -static inline constexpr PyObject *JPPyTuple_Pack(T... args) { - return PyTuple_Pack(sizeof...(T), args...); +static inline JPPyObject JPPyTuple_Pack(T... args) { + return JPPyObject::call(PyTuple_Pack(sizeof...(T), args...)); } // Base utility headers @@ -186,7 +188,6 @@ static inline constexpr PyObject *JPPyTuple_Pack(T... args) { #include "jp_context.h" #include "jp_exception.h" #include "jp_tracer.h" -#include "jp_pythontypes.h" #include "jp_typemanager.h" #include "jp_encoding.h" #include "jp_modifier.h" diff --git a/native/common/jp_class.cpp b/native/common/jp_class.cpp index 4b540572b..fb8ab324e 100644 --- a/native/common/jp_class.cpp +++ b/native/common/jp_class.cpp @@ -372,16 +372,15 @@ JPPyObject JPClass::convertToPythonObject(JPJavaFrame& frame, jvalue value, bool jstring m = frame.getMessage((jthrowable) value.l); if (m != nullptr) { - tuple0 = JPPyObject::call(JPPyTuple_Pack( - JPPyString::fromStringUTF8(frame.toStringUTF8(m)).get())); + tuple0 = JPPyTuple_Pack( + JPPyString::fromStringUTF8(frame.toStringUTF8(m)).get()); } else { - tuple0 = JPPyObject::call(JPPyTuple_Pack( - JPPyString::fromStringUTF8(frame.toString(value.l)).get())); + tuple0 = JPPyTuple_Pack( + JPPyString::fromStringUTF8(frame.toString(value.l)).get()); } } - JPPyObject tuple1 = JPPyObject::call(JPPyTuple_Pack( - _JObjectKey, tuple0.get())); + JPPyObject tuple1 = JPPyTuple_Pack(_JObjectKey, tuple0.get()); // Exceptions need new and init obj = JPPyObject::call(PyObject_Call(wrapper.get(), tuple1.get(), nullptr)); } else diff --git a/native/common/jp_classhints.cpp b/native/common/jp_classhints.cpp index 8548723c9..7435f8b76 100644 --- a/native/common/jp_classhints.cpp +++ b/native/common/jp_classhints.cpp @@ -146,8 +146,7 @@ class JPPythonConversion : public JPConversion { JP_TRACE_IN("JPPythonConversion::convert"); JPClass *cls = ((JPClass*) match.closure); - JPPyObject args = JPPyObject::call(JPPyTuple_Pack( - cls->getHost(), match.object)); + JPPyObject args = JPPyTuple_Pack(cls->getHost(), match.object); JPPyObject ret = JPPyObject::call(PyObject_Call(method_.get(), args.get(), nullptr)); JPValue *value = PyJPValue_getJavaSlot(ret.get()); if (value != nullptr) diff --git a/native/common/jp_exception.cpp b/native/common/jp_exception.cpp index a6032faef..339df1a9c 100644 --- a/native/common/jp_exception.cpp +++ b/native/common/jp_exception.cpp @@ -512,7 +512,7 @@ PyObject *tb_create( JPPyObject lasti = JPPyObject::claim(PyLong_FromLong(PyFrame_GetLasti(pframe))); #endif JPPyObject linenuma = JPPyObject::claim(PyLong_FromLong(linenum)); - JPPyObject tuple = JPPyObject::call(JPPyTuple_Pack(Py_None, frame.get(), lasti.get(), linenuma.get())); + JPPyObject tuple = JPPyTuple_Pack(Py_None, frame.get(), lasti.get(), linenuma.get()); JPPyObject traceback = JPPyObject::accept(PyObject_Call((PyObject*) &PyTraceBack_Type, tuple.get(), NULL)); // We could fail in process diff --git a/native/python/jp_pythontypes.cpp b/native/python/jp_pythontypes.cpp index ee9c8971b..3dfba7808 100644 --- a/native/python/jp_pythontypes.cpp +++ b/native/python/jp_pythontypes.cpp @@ -483,7 +483,7 @@ void JPPyErrFrame::normalize() // we have forced it to realize the exception. if (!PyExceptionInstance_Check(m_ExceptionValue.get())) { - JPPyObject args = JPPyObject::call(JPPyTuple_Pack(m_ExceptionValue.get())); + JPPyObject args = JPPyTuple_Pack(m_ExceptionValue.get()); m_ExceptionValue = JPPyObject::call(PyObject_Call(m_ExceptionClass.get(), args.get(), nullptr)); PyException_SetTraceback(m_ExceptionValue.get(), m_ExceptionTrace.get()); JPPyErr::restore(m_ExceptionClass, m_ExceptionValue, m_ExceptionTrace); diff --git a/native/python/pyjp_array.cpp b/native/python/pyjp_array.cpp index c190066bb..88387a45f 100644 --- a/native/python/pyjp_array.cpp +++ b/native/python/pyjp_array.cpp @@ -484,7 +484,7 @@ static PyType_Spec arrayPrimSpec = { void PyJPArray_initType(PyObject * module) { - JPPyObject tuple = JPPyObject::call(JPPyTuple_Pack(PyJPObject_Type)); + JPPyObject tuple = JPPyTuple_Pack(PyJPObject_Type); PyJPArray_Type = (PyTypeObject*) PyJPClass_FromSpecWithBases(&arraySpec, tuple.get()); JP_PY_CHECK(); #if PY_VERSION_HEX < 0x03090000 @@ -493,7 +493,7 @@ void PyJPArray_initType(PyObject * module) PyModule_AddObject(module, "_JArray", (PyObject*) PyJPArray_Type); JP_PY_CHECK(); - tuple = JPPyObject::call(JPPyTuple_Pack(PyJPArray_Type)); + tuple = JPPyTuple_Pack(PyJPArray_Type); PyJPArrayPrimitive_Type = (PyTypeObject*) PyJPClass_FromSpecWithBases(&arrayPrimSpec, tuple.get()); #if PY_VERSION_HEX < 0x03090000 diff --git a/native/python/pyjp_buffer.cpp b/native/python/pyjp_buffer.cpp index a69daa24e..561754de5 100644 --- a/native/python/pyjp_buffer.cpp +++ b/native/python/pyjp_buffer.cpp @@ -143,7 +143,7 @@ static PyType_Spec bufferSpec = { void PyJPBuffer_initType(PyObject * module) { - JPPyObject tuple = JPPyObject::call(JPPyTuple_Pack(PyJPObject_Type)); + JPPyObject tuple = JPPyTuple_Pack(PyJPObject_Type); PyJPBuffer_Type = (PyTypeObject*) PyJPClass_FromSpecWithBases(&bufferSpec, tuple.get()); #if PY_VERSION_HEX < 0x03090000 PyJPBuffer_Type->tp_as_buffer = &directBuffer; diff --git a/native/python/pyjp_char.cpp b/native/python/pyjp_char.cpp index 2790879cf..eb37e62aa 100644 --- a/native/python/pyjp_char.cpp +++ b/native/python/pyjp_char.cpp @@ -212,7 +212,7 @@ static PyObject * PyJPChar_new(PyTypeObject *type, PyObject *pyargs, PyObject * if (cv != (Py_UCS4) - 1) { JPPyObject v = JPPyObject::call(PyLong_FromLong(cv)); - JPPyObject args0 = JPPyObject::call(JPPyTuple_Pack(v.get())); + JPPyObject args0 = JPPyTuple_Pack(v.get()); JPPyObjectVector args(args0.get()); jv = cls->newInstance(frame, args); } else if (PyIndex_Check(in)) @@ -222,7 +222,7 @@ static PyObject * PyJPChar_new(PyTypeObject *type, PyObject *pyargs, PyObject * } else if (PyFloat_Check(in)) { JPPyObject v = JPPyObject::call(PyNumber_Long(in)); - JPPyObject args0 = JPPyObject::call(JPPyTuple_Pack(v.get())); + JPPyObject args0 = JPPyTuple_Pack(v.get()); JPPyObjectVector args(args0.get()); jv = cls->newInstance(frame, args); } else @@ -655,9 +655,8 @@ static PyType_Spec charSpec = { void PyJPChar_initType(PyObject* module) { // We will inherit from str and JObject - PyObject *bases = JPPyTuple_Pack(&PyUnicode_Type, PyJPObject_Type); - PyJPChar_Type = (PyTypeObject*) PyJPClass_FromSpecWithBases(&charSpec, bases); - Py_DECREF(bases); + JPPyObject bases = JPPyTuple_Pack(&PyUnicode_Type, PyJPObject_Type); + PyJPChar_Type = (PyTypeObject*) PyJPClass_FromSpecWithBases(&charSpec, bases.get()); JP_PY_CHECK(); // GCOVR_EXCL_LINE PyModule_AddObject(module, "_JChar", (PyObject*) PyJPChar_Type); JP_PY_CHECK(); // GCOVR_EXCL_LINE diff --git a/native/python/pyjp_class.cpp b/native/python/pyjp_class.cpp index cdd7f8e0e..72a1ead45 100644 --- a/native/python/pyjp_class.cpp +++ b/native/python/pyjp_class.cpp @@ -148,7 +148,10 @@ PyObject* PyJPClass_FromSpecWithBases(PyType_Spec *spec, PyObject *bases) heap->ht_name = heap->ht_qualname; Py_INCREF(heap->ht_name); if (bases == nullptr) - type->tp_bases = JPPyTuple_Pack((PyObject*) & PyBaseObject_Type); + { + // do NOT use JPPyTuple_Pack here + type->tp_bases = PyTuple_Pack(1, (PyObject*) & PyBaseObject_Type); + } else { type->tp_bases = bases; @@ -935,7 +938,7 @@ static PyObject *PyJPClass_getDoc(PyJPClass *self, void *ctxt) // Pack the arguments { JP_TRACE("Pack arguments"); - JPPyObject args = JPPyObject::call(JPPyTuple_Pack(self)); + JPPyObject args = JPPyTuple_Pack(self); JP_TRACE("Call Python"); self->m_Doc = PyObject_Call(_JClassDoc, args.get(), nullptr); Py_XINCREF(self->m_Doc); @@ -1021,9 +1024,8 @@ static PyType_Spec classSpec = { void PyJPClass_initType(PyObject* module) { - PyObject *bases = JPPyTuple_Pack(&PyType_Type); - PyJPClass_Type = (PyTypeObject*) PyType_FromSpecWithBases(&classSpec, bases); - Py_DECREF(bases); + JPPyObject bases = JPPyTuple_Pack(&PyType_Type); + PyJPClass_Type = (PyTypeObject*) PyType_FromSpecWithBases(&classSpec, bases.get()); JP_PY_CHECK(); PyModule_AddObject(module, "_JClass", (PyObject*) PyJPClass_Type); JP_PY_CHECK(); @@ -1160,10 +1162,10 @@ void PyJPClass_hook(JPJavaFrame &frame, JPClass* cls) JPPyObject members = JPPyObject::call(PyDict_New()); - JPPyObject args = JPPyObject::call(JPPyTuple_Pack( + JPPyObject args = JPPyTuple_Pack( JPPyString::fromStringUTF8(cls->getCanonicalName()).get(), PyJPClass_getBases(frame, cls).get(), - members.get())); + members.get()); // Catch creation loop, the process of creating our parent host = (PyObject*) cls->getHost(); @@ -1216,6 +1218,6 @@ void PyJPClass_hook(JPJavaFrame &frame, JPClass* cls) // Call the post load routine to attach inner classes JP_TRACE("call post"); - args = JPPyObject::call(JPPyTuple_Pack(self)); + args = JPPyTuple_Pack(self); JPPyObject rc2 = JPPyObject::call(PyObject_Call(_JClassPost, args.get(), nullptr)); } diff --git a/native/python/pyjp_method.cpp b/native/python/pyjp_method.cpp index 6af47040f..facf2a994 100644 --- a/native/python/pyjp_method.cpp +++ b/native/python/pyjp_method.cpp @@ -216,8 +216,7 @@ static PyObject *PyJPMethod_getDoc(PyJPMethod *self, void *ctxt) jvalue v; v.l = (jobject) self->m_Method->getClass()->getJavaClass(); JPPyObject obj(context->_java_lang_Class->convertToPythonObject(frame, v, true)); - JPPyObject args = JPPyObject::call(JPPyTuple_Pack( - self, obj.get(), ov.get())); + JPPyObject args = JPPyTuple_Pack(self, obj.get(), ov.get()); JP_TRACE("Call Python"); self->m_Doc = PyObject_Call(_JMethodDoc, args.get(), nullptr); Py_XINCREF(self->m_Doc); @@ -268,8 +267,7 @@ PyObject *PyJPMethod_getAnnotations(PyJPMethod *self, void *ctxt) jvalue v; v.l = (jobject) self->m_Method->getClass()->getJavaClass(); JPPyObject obj(context->_java_lang_Class->convertToPythonObject(frame, v, true)); - JPPyObject args = JPPyObject::call(JPPyTuple_Pack( - self, obj.get(), ov.get())); + JPPyObject args = JPPyTuple_Pack(self, obj.get(), ov.get()); JP_TRACE("Call Python"); self->m_Annotations = PyObject_Call(_JMethodAnnotations, args.get(), nullptr); } @@ -293,7 +291,7 @@ PyObject *PyJPMethod_getCodeAttr(PyJPMethod *self, void *ctx, const char *attr) PyJPModule_getContext(); if (self->m_CodeRep == nullptr) { - JPPyObject args = JPPyObject::call(JPPyTuple_Pack(self)); + JPPyObject args = JPPyTuple_Pack(self); JP_TRACE("Call Python"); self->m_CodeRep = PyObject_Call(_JMethodCode, args.get(), nullptr); } @@ -396,7 +394,7 @@ void PyJPMethod_initType(PyObject* module) // We inherit from PyFunction_Type just so we are an instance // for purposes of inspect and tab completion tools. But // we will just ignore their memory layout as we have our own. - JPPyObject tuple = JPPyObject::call(JPPyTuple_Pack(&PyFunction_Type)); + JPPyObject tuple = JPPyTuple_Pack(&PyFunction_Type); unsigned long flags = PyFunction_Type.tp_flags; PyFunction_Type.tp_flags |= Py_TPFLAGS_BASETYPE; PyJPMethod_Type = (PyTypeObject*) PyType_FromSpecWithBases(&methodSpec, tuple.get()); diff --git a/native/python/pyjp_number.cpp b/native/python/pyjp_number.cpp index 17fb7da85..9f55af4a1 100644 --- a/native/python/pyjp_number.cpp +++ b/native/python/pyjp_number.cpp @@ -270,9 +270,8 @@ static PyObject *PyJPBoolean_new(PyTypeObject *type, PyObject *args, PyObject *k return nullptr; } int i = PyObject_IsTrue(PyTuple_GetItem(args, 0)); - PyObject *args2 = JPPyTuple_Pack(PyLong_FromLong(i)); - self = JPPyObject::call(PyLong_Type.tp_new(type, args2, kwargs)); - Py_DECREF(args2); + JPPyObject args2 = JPPyTuple_Pack(PyLong_FromLong(i)); + self = JPPyObject::call(PyLong_Type.tp_new(type, args2.get(), kwargs)); JPClass *cls = PyJPClass_getJPClass((PyObject*) type); if (cls == nullptr) { @@ -371,25 +370,21 @@ PyType_Spec numberBooleanSpec = { void PyJPNumber_initType(PyObject* module) { - PyObject *bases; - bases = JPPyTuple_Pack(&PyLong_Type, PyJPObject_Type); - PyJPNumberLong_Type = (PyTypeObject*) PyJPClass_FromSpecWithBases(&numberLongSpec, bases); - Py_DECREF(bases); + JPPyObject bases = JPPyTuple_Pack(&PyLong_Type, PyJPObject_Type); + PyJPNumberLong_Type = (PyTypeObject*) PyJPClass_FromSpecWithBases(&numberLongSpec, bases.get()); JP_PY_CHECK(); // GCOVR_EXCL_LINE PyModule_AddObject(module, "_JNumberLong", (PyObject*) PyJPNumberLong_Type); JP_PY_CHECK(); // GCOVR_EXCL_LINE bases = JPPyTuple_Pack(&PyFloat_Type, PyJPObject_Type); - PyJPNumberFloat_Type = (PyTypeObject*) PyJPClass_FromSpecWithBases(&numberFloatSpec, bases); - Py_DECREF(bases); + PyJPNumberFloat_Type = (PyTypeObject*) PyJPClass_FromSpecWithBases(&numberFloatSpec, bases.get()); JP_PY_CHECK(); // GCOVR_EXCL_LINE PyModule_AddObject(module, "_JNumberFloat", (PyObject*) PyJPNumberFloat_Type); JP_PY_CHECK(); // GCOVR_EXCL_LINE bases = JPPyTuple_Pack(&PyLong_Type, PyJPObject_Type); - PyJPNumberBool_Type = (PyTypeObject*) PyJPClass_FromSpecWithBases(&numberBooleanSpec, bases); - Py_DECREF(bases); + PyJPNumberBool_Type = (PyTypeObject*) PyJPClass_FromSpecWithBases(&numberBooleanSpec, bases.get()); JP_PY_CHECK(); // GCOVR_EXCL_LINE PyModule_AddObject(module, "_JBoolean", (PyObject*) PyJPNumberBool_Type); JP_PY_CHECK(); // GCOVR_EXCL_LINE @@ -404,8 +399,8 @@ JPPyObject PyJPNumber_create(JPJavaFrame &frame, JPPyObject& wrapper, const JPVa jlong l = 0; if (value.getValue().l != nullptr) l = frame.CallBooleanMethodA(value.getJavaObject(), context->_java_lang_Boolean->m_BooleanValueID, nullptr); - PyObject *args = JPPyTuple_Pack(PyLong_FromLongLong(l)); - return JPPyObject::call(PyLong_Type.tp_new((PyTypeObject*) wrapper.get(), args, nullptr)); + JPPyObject args = JPPyTuple_Pack(PyLong_FromLongLong(l)); + return JPPyObject::call(PyLong_Type.tp_new((PyTypeObject*) wrapper.get(), args.get(), nullptr)); } if (PyObject_IsSubclass(wrapper.get(), (PyObject*) & PyLong_Type)) { @@ -415,8 +410,8 @@ JPPyObject PyJPNumber_create(JPJavaFrame &frame, JPPyObject& wrapper, const JPVa auto* jb = dynamic_cast( value.getClass()); l = frame.CallLongMethodA(value.getJavaObject(), jb->m_LongValueID, nullptr); } - PyObject *args = JPPyTuple_Pack(PyLong_FromLongLong(l)); - return JPPyObject::call(PyLong_Type.tp_new((PyTypeObject*) wrapper.get(), args, nullptr)); + JPPyObject args = JPPyTuple_Pack(PyLong_FromLongLong(l)); + return JPPyObject::call(PyLong_Type.tp_new((PyTypeObject*) wrapper.get(), args.get(), nullptr)); } if (PyObject_IsSubclass(wrapper.get(), (PyObject*) & PyFloat_Type)) { @@ -426,8 +421,8 @@ JPPyObject PyJPNumber_create(JPJavaFrame &frame, JPPyObject& wrapper, const JPVa auto* jb = dynamic_cast( value.getClass()); l = frame.CallDoubleMethodA(value.getJavaObject(), jb->m_DoubleValueID, nullptr); } - PyObject *args = JPPyTuple_Pack(PyFloat_FromDouble(l)); - return JPPyObject::call(PyFloat_Type.tp_new((PyTypeObject*) wrapper.get(), args, nullptr)); + JPPyObject args = JPPyTuple_Pack(PyFloat_FromDouble(l)); + return JPPyObject::call(PyFloat_Type.tp_new((PyTypeObject*) wrapper.get(), args.get(), nullptr)); } JP_RAISE(PyExc_TypeError, "unable to convert"); //GCOVR_EXCL_LINE } diff --git a/native/python/pyjp_object.cpp b/native/python/pyjp_object.cpp index 220bf2fa6..46fe6d892 100644 --- a/native/python/pyjp_object.cpp +++ b/native/python/pyjp_object.cpp @@ -366,13 +366,13 @@ void PyJPObject_initType(PyObject* module) PyModule_AddObject(module, "_JObject", (PyObject*) PyJPObject_Type); JP_PY_CHECK(); // GCOVR_EXCL_LINE - JPPyObject bases = JPPyObject::call(JPPyTuple_Pack(PyExc_Exception, PyJPObject_Type)); + JPPyObject bases = JPPyTuple_Pack(PyExc_Exception, PyJPObject_Type); PyJPException_Type = (PyTypeObject*) PyJPClass_FromSpecWithBases(&excSpec, bases.get()); JP_PY_CHECK(); // GCOVR_EXCL_LINE PyModule_AddObject(module, "_JException", (PyObject*) PyJPException_Type); JP_PY_CHECK(); // GCOVR_EXCL_LINE - bases = JPPyObject::call(JPPyTuple_Pack(PyJPObject_Type)); + bases = JPPyTuple_Pack(PyJPObject_Type); PyJPComparable_Type = (PyTypeObject*) PyJPClass_FromSpecWithBases(&comparableSpec, bases.get()); JP_PY_CHECK(); // GCOVR_EXCL_LINE PyModule_AddObject(module, "_JComparable", (PyObject*) PyJPComparable_Type); diff --git a/native/python/pyjp_package.cpp b/native/python/pyjp_package.cpp index 443173932..1583510a6 100644 --- a/native/python/pyjp_package.cpp +++ b/native/python/pyjp_package.cpp @@ -163,7 +163,7 @@ static PyObject *PyJPPackage_getattro(PyObject *self, PyObject *attr) JPPyErrFrame err; err.normalize(); err.clear(); - JPPyObject tuple0 = JPPyObject::call(JPPyTuple_Pack(self, attr, err.m_ExceptionValue.get())); + JPPyObject tuple0 = JPPyTuple_Pack(self, attr, err.m_ExceptionValue.get()); PyObject *rc = PyObject_Call(h.get(), tuple0.get(), nullptr); if (rc == nullptr) return nullptr; @@ -182,7 +182,7 @@ static PyObject *PyJPPackage_getattro(PyObject *self, PyObject *attr) { JPPyObject u = JPPyObject::call(PyUnicode_FromFormat("%s.%U", PyModule_GetName(self), attr)); - JPPyObject args = JPPyObject::call(JPPyTuple_Pack(u.get())); + JPPyObject args = JPPyTuple_Pack(u.get()); out = JPPyObject::call(PyObject_Call((PyObject*) PyJPPackage_Type, args.get(), nullptr)); } else { @@ -284,7 +284,7 @@ static PyObject *PyJPPackage_cast(PyObject *self, PyObject *other) PyObject* matmul = PyDict_GetItemString(dict, "__matmul__"); if (matmul == nullptr) Py_RETURN_NOTIMPLEMENTED; - JPPyObject args = JPPyObject::call(JPPyTuple_Pack(self, other)); + JPPyObject args = JPPyTuple_Pack(self, other); return PyObject_Call(matmul, args.get(), nullptr); JP_PY_CATCH(nullptr); } @@ -338,7 +338,7 @@ static PyType_Spec packageSpec = { void PyJPPackage_initType(PyObject* module) { // Inherit from module. - JPPyObject bases = JPPyObject::call(JPPyTuple_Pack(&PyModule_Type)); + JPPyObject bases = JPPyTuple_Pack(&PyModule_Type); packageSpec.basicsize = PyModule_Type.tp_basicsize; PyJPPackage_Type = (PyTypeObject*) PyType_FromSpecWithBases(&packageSpec, bases.get()); JP_PY_CHECK(); diff --git a/native/python/pyjp_proxy.cpp b/native/python/pyjp_proxy.cpp index fc79be213..aeb14802e 100644 --- a/native/python/pyjp_proxy.cpp +++ b/native/python/pyjp_proxy.cpp @@ -173,7 +173,7 @@ PyType_Spec PyJPProxySpec = { void PyJPProxy_initType(PyObject* module) { - JPPyObject bases = JPPyObject::call(JPPyTuple_Pack(&PyBaseObject_Type)); + JPPyObject bases = JPPyTuple_Pack(&PyBaseObject_Type); PyJPProxy_Type = (PyTypeObject*) PyType_FromSpecWithBases(&PyJPProxySpec, bases.get()); JP_PY_CHECK(); PyModule_AddObject(module, "_JProxy", (PyObject*) PyJPProxy_Type);