├── .gitignore ├── CHANGES.md ├── LICENSE.txt ├── MANIFEST.in ├── README.md ├── appveyor.yml ├── ci ├── appveyor │ └── dump-dlls.py └── travis │ ├── before_script.sh │ ├── run.sh │ └── upload-to-ftp.sh ├── doc ├── .gitignore ├── Makefile ├── _static │ ├── figures │ │ ├── deployment.png │ │ └── deployment.puml │ └── java-apidocs │ │ ├── allclasses-frame.html │ │ ├── allclasses-noframe.html │ │ ├── constant-values.html │ │ ├── deprecated-list.html │ │ ├── help-doc.html │ │ ├── index-all.html │ │ ├── index.html │ │ ├── org │ │ └── jpy │ │ │ ├── DL.html │ │ │ ├── KeyError.html │ │ │ ├── PyDictWrapper.html │ │ │ ├── PyInputMode.html │ │ │ ├── PyLib.CallableKind.html │ │ │ ├── PyLib.Diag.html │ │ │ ├── PyLib.html │ │ │ ├── PyModule.html │ │ │ ├── PyObject.html │ │ │ ├── StopIteration.html │ │ │ ├── class-use │ │ │ ├── DL.html │ │ │ ├── KeyError.html │ │ │ ├── PyDictWrapper.html │ │ │ ├── PyInputMode.html │ │ │ ├── PyLib.CallableKind.html │ │ │ ├── PyLib.Diag.html │ │ │ ├── PyLib.html │ │ │ ├── PyModule.html │ │ │ ├── PyObject.html │ │ │ └── StopIteration.html │ │ │ ├── package-frame.html │ │ │ ├── package-summary.html │ │ │ ├── package-tree.html │ │ │ └── package-use.html │ │ ├── overview-tree.html │ │ ├── package-list │ │ ├── script.js │ │ ├── serialized-form.html │ │ └── stylesheet.css ├── conf.py ├── index.rst ├── install.rst ├── intro.rst ├── make.bat ├── modify.rst ├── reference.rst └── tutorial.rst ├── ez_setup.py ├── jpyutil.py ├── pom.xml ├── pysobug ├── .gitignore ├── README.txt ├── make.sh ├── mypy.c ├── mypydl.c ├── mypymod.c └── setup.py ├── setup.cfg ├── setup.py ├── src ├── main │ ├── c │ │ ├── jni │ │ │ ├── org_jpy_DL.c │ │ │ ├── org_jpy_DL.h │ │ │ ├── org_jpy_PyLib.c │ │ │ ├── org_jpy_PyLib.h │ │ │ ├── org_jpy_PyLib_CallableKind.h │ │ │ └── org_jpy_PyLib_Diag.h │ │ ├── jpy_compat.c │ │ ├── jpy_compat.h │ │ ├── jpy_conv.c │ │ ├── jpy_conv.h │ │ ├── jpy_diag.c │ │ ├── jpy_diag.h │ │ ├── jpy_jarray.c │ │ ├── jpy_jarray.h │ │ ├── jpy_jfield.c │ │ ├── jpy_jfield.h │ │ ├── jpy_jmethod.c │ │ ├── jpy_jmethod.h │ │ ├── jpy_jobj.c │ │ ├── jpy_jobj.h │ │ ├── jpy_jtype.c │ │ ├── jpy_jtype.h │ │ ├── jpy_module.c │ │ ├── jpy_module.h │ │ ├── jpy_verboseexcept.c │ │ └── jpy_verboseexcept.h │ └── java │ │ └── org │ │ └── jpy │ │ ├── DL.java │ │ ├── KeyError.java │ │ ├── PyDictWrapper.java │ │ ├── PyInputMode.java │ │ ├── PyLib.java │ │ ├── PyLibConfig.java │ │ ├── PyListWrapper.java │ │ ├── PyModule.java │ │ ├── PyObject.java │ │ ├── PyProxyHandler.java │ │ ├── StopIteration.java │ │ ├── annotations │ │ ├── Mutable.java │ │ ├── Output.java │ │ └── Return.java │ │ ├── jsr223 │ │ ├── ScriptEngineFactoryImpl.java │ │ └── ScriptEngineImpl.java │ │ └── package-info.java └── test │ ├── java │ └── org │ │ └── jpy │ │ ├── JavaReflectionTest.java │ │ ├── LifeCycleTest.java │ │ ├── PyLibTest.java │ │ ├── PyLibWithSysPathTest.java │ │ ├── PyModuleTest.java │ │ ├── PyObjectTest.java │ │ ├── UseCases.java │ │ ├── fixtures │ │ ├── ConstructorOverloadTestFixture.java │ │ ├── CovariantOverloadExtendTestFixture.java │ │ ├── CovariantOverloadTestFixture.java │ │ ├── DefaultInterfaceImplTestFixture.java │ │ ├── DefaultInterfaceTestFixture.java │ │ ├── ExceptionTestFixture.java │ │ ├── FieldTestFixture.java │ │ ├── MethodOverloadTestFixture.java │ │ ├── MethodReturnValueTestFixture.java │ │ ├── ModifyAndReturnParametersTestFixture.java │ │ ├── Processor.java │ │ ├── Thing.java │ │ ├── TypeConversionTestFixture.java │ │ ├── TypeResolutionTestFixture.java │ │ ├── TypeTranslationTestFixture.java │ │ └── VarArgsTestFixture.java │ │ └── jsr223 │ │ └── Jsr223Test.java │ ├── python │ ├── fixtures │ │ ├── hasheqstr.py │ │ ├── proc_class.py │ │ ├── proc_module.py │ │ └── raise_errors.py │ ├── imp │ │ ├── import_ex1.py │ │ ├── import_ex2.py │ │ ├── packages-jre6.txt │ │ └── packages-jre7.txt │ ├── jpy_array_test.py │ ├── jpy_diag_test.py │ ├── jpy_exception_test.py │ ├── jpy_field_test.py │ ├── jpy_gettype_test.py │ ├── jpy_modretparam_test.py │ ├── jpy_mt_test.py │ ├── jpy_overload_test.py │ ├── jpy_perf_test.py │ ├── jpy_retval_test.py │ ├── jpy_rt_test.py │ ├── jpy_translation_test.py │ ├── jpy_typeconv_test.py │ └── jpy_typeres_test.py │ └── resources │ ├── META-INF │ └── services │ │ └── javax.script.ScriptEngineFactory │ └── pymodules │ └── mod_1.py └── winbuild.cmd /.gitignore: -------------------------------------------------------------------------------- 1 | venv 2 | target 3 | build 4 | dist 5 | MANIFEST 6 | .idea 7 | *.iml 8 | *.jar 9 | *.war 10 | *.ear 11 | __pycache__/ 12 | hs_err_pid* 13 | winbuild.log 14 | local.dat 15 | setup.out 16 | *.pyc 17 | jpy.egg-info 18 | lib/ 19 | .vagrant 20 | Vagrantfile 21 | *.so 22 | *.dll 23 | 24 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include *.txt 2 | include *.xml 3 | include doc/make.bat 4 | include doc/Makefile 5 | include lib/*.jar 6 | recursive-include doc *.py 7 | recursive-include doc *.rst 8 | recursive-include src/main/c *.h 9 | recursive-include src/main/c *.c 10 | recursive-include src/main/java *.java 11 | recursive-include src/test/java *.java 12 | recursive-include src/test/python *.py 13 | 14 | -------------------------------------------------------------------------------- /ci/appveyor/dump-dlls.py: -------------------------------------------------------------------------------- 1 | import psutil, os 2 | 3 | p = psutil.Process(os.getpid()) 4 | for dll in p.memory_maps(): 5 | print(dll.path) 6 | 7 | -------------------------------------------------------------------------------- /ci/travis/before_script.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [[ $TRAVIS_OS_NAME == 'osx' ]]; then 4 | 5 | # Install some custom requirements on OS X 6 | # e.g. brew install pyenv-virtualenv 7 | # See https://gist.github.com/Bouke/11261620 8 | # and https://github.com/bincrafters/conan-bazel_installer 9 | 10 | brew update || brew update 11 | brew outdated pyenv || brew upgrade pyenv 12 | brew install pyenv-virtualenv 13 | eval "$(pyenv init -)" 14 | eval "$(pyenv virtualenv-init -)" 15 | 16 | pyenv install --list 17 | pyenv install --skip-existing $PYTHON_VERSION 18 | pyenv virtualenv $PYTHON_VERSION jpy-venv 19 | 20 | else 21 | # Install pyenv 22 | # See https://github.com/pyenv/pyenv 23 | git clone https://github.com/pyenv/pyenv.git $HOME/.pyenv 24 | export PYENV_ROOT="$HOME/.pyenv" 25 | export PATH="$PYENV_ROOT/bin:$PATH" 26 | eval "$(pyenv init -)" 27 | 28 | # Install pyenv virtualenv plugin 29 | # See https://github.com/pyenv/pyenv-virtualenv 30 | git clone https://github.com/pyenv/pyenv-virtualenv.git $(pyenv root)/plugins/pyenv-virtualenv 31 | eval "$(pyenv virtualenv-init -)" 32 | 33 | # Create virtualenv from current Python 34 | pyenv virtualenv jpy-venv 35 | fi 36 | 37 | pyenv rehash 38 | pyenv activate jpy-venv 39 | pip install wheel 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /ci/travis/run.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | 4 | if [[ $TRAVIS_OS_NAME != 'osx' ]]; then 5 | export PYENV_ROOT="$HOME/.pyenv" 6 | export PATH="$PYENV_ROOT/bin:$PATH" 7 | fi 8 | 9 | eval "$(pyenv init -)" 10 | eval "$(pyenv virtualenv-init -)" 11 | pyenv activate jpy-venv 12 | python --version 13 | 14 | # oracle-java8-set-default seems to modify PATH but not JAVA_HOME :( 15 | java -version 16 | if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then 17 | export JAVA_HOME=$(/usr/libexec/java_home -v 1.8); 18 | else 19 | export JAVA_HOME=/usr/lib/jvm/java-8-oracle 20 | fi 21 | echo $JAVA_HOME 22 | 23 | python setup.py --maven bdist_wheel 24 | -------------------------------------------------------------------------------- /ci/travis/upload-to-ftp.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | function upload_ftp { 4 | echo Uploading ${1}: ${2} 5 | curl --ftp-create-dirs -T $2 -u "$FTP_USER:$FTP_PASSWORD" "ftp://$FTP_HOST/software/$TRAVIS_OS_NAME/" 6 | } 7 | 8 | echo "success pushing artifacts to FTP..." 9 | upload_ftp "wheel" "dist/*.whl" 10 | -------------------------------------------------------------------------------- /doc/.gitignore: -------------------------------------------------------------------------------- 1 | _build 2 | _templates 3 | -------------------------------------------------------------------------------- /doc/_static/figures/deployment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcdev/jpy/76548cb6f3b9ba795ed6b3a42327607234eaba3c/doc/_static/figures/deployment.png -------------------------------------------------------------------------------- /doc/_static/figures/deployment.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | 3 | component JVM 4 | component Python 5 | 6 | artifact jdl.so 7 | artifact jpy.so 8 | artifact jpy.jar 9 | artifact jpyutil.py 10 | file jpyconfig.properties 11 | file jpyconfig.py 12 | 13 | jpy.jar ..> jpy.so 14 | jpy.jar ..> jdl.so 15 | jpy.jar ..> jpyconfig.properties 16 | 17 | jpyutil.py ..> jpyconfig.py 18 | 19 | Python ..> jpy.so 20 | Python ..> jpyutil.py 21 | JVM ..> jpy.jar 22 | 23 | @enduml -------------------------------------------------------------------------------- /doc/_static/java-apidocs/allclasses-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | All Classes (Java-Python Bridge 0.10.0 Java API) 8 | 9 | 10 | 11 | 12 | 13 |

All Classes

14 |
15 | 27 |
28 | 29 | 30 | -------------------------------------------------------------------------------- /doc/_static/java-apidocs/allclasses-noframe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | All Classes (Java-Python Bridge 0.10.0 Java API) 8 | 9 | 10 | 11 | 12 | 13 |

All Classes

14 |
15 | 27 |
28 | 29 | 30 | -------------------------------------------------------------------------------- /doc/_static/java-apidocs/deprecated-list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Deprecated List (Java-Python Bridge 0.10.0 Java API) 8 | 9 | 10 | 11 | 12 | 13 | 23 | 26 | 27 |
28 | 29 | 30 |
Skip navigation links
31 | 32 | 33 | 34 | 43 |
44 | 71 | 72 |
73 |

Deprecated API

74 |

Contents

75 | 78 |
79 |
80 | 81 | 82 | 97 |
98 | 99 |
100 | 101 | 102 |
Skip navigation links
103 | 104 | 105 | 106 | 115 |
116 | 143 | 144 |

Copyright © 2014–2020 Brockmann Consult GmbH. All rights reserved.

145 | 146 | 147 | -------------------------------------------------------------------------------- /doc/_static/java-apidocs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Java-Python Bridge 0.10.0 Java API 8 | 61 | 62 | 63 | 64 | 65 | 66 | <noscript> 67 | <div>JavaScript is disabled on your browser.</div> 68 | </noscript> 69 | <h2>Frame Alert</h2> 70 | <p>This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. Link to <a href="org/jpy/package-summary.html">Non-frame version</a>.</p> 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /doc/_static/java-apidocs/org/jpy/class-use/DL.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Uses of Class org.jpy.DL (Java-Python Bridge 0.10.0 Java API) 8 | 9 | 10 | 11 | 12 | 13 | 23 | 26 | 27 |
28 | 29 | 30 |
Skip navigation links
31 | 32 | 33 | 34 | 43 |
44 | 71 | 72 |
73 |

Uses of Class
org.jpy.DL

74 |
75 |
No usage of org.jpy.DL
76 | 77 |
78 | 79 | 80 |
Skip navigation links
81 | 82 | 83 | 84 | 93 |
94 | 121 | 122 |

Copyright © 2014–2020 Brockmann Consult GmbH. All rights reserved.

123 | 124 | 125 | -------------------------------------------------------------------------------- /doc/_static/java-apidocs/org/jpy/class-use/KeyError.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Uses of Class org.jpy.KeyError (Java-Python Bridge 0.10.0 Java API) 8 | 9 | 10 | 11 | 12 | 13 | 23 | 26 | 27 |
28 | 29 | 30 |
Skip navigation links
31 | 32 | 33 | 34 | 43 |
44 | 71 | 72 |
73 |

Uses of Class
org.jpy.KeyError

74 |
75 |
No usage of org.jpy.KeyError
76 | 77 |
78 | 79 | 80 |
Skip navigation links
81 | 82 | 83 | 84 | 93 |
94 | 121 | 122 |

Copyright © 2014–2020 Brockmann Consult GmbH. All rights reserved.

123 | 124 | 125 | -------------------------------------------------------------------------------- /doc/_static/java-apidocs/org/jpy/class-use/PyLib.Diag.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Uses of Class org.jpy.PyLib.Diag (Java-Python Bridge 0.10.0 Java API) 8 | 9 | 10 | 11 | 12 | 13 | 23 | 26 | 27 |
28 | 29 | 30 |
Skip navigation links
31 | 32 | 33 | 34 | 43 |
44 | 71 | 72 |
73 |

Uses of Class
org.jpy.PyLib.Diag

74 |
75 |
No usage of org.jpy.PyLib.Diag
76 | 77 |
78 | 79 | 80 |
Skip navigation links
81 | 82 | 83 | 84 | 93 |
94 | 121 | 122 |

Copyright © 2014–2020 Brockmann Consult GmbH. All rights reserved.

123 | 124 | 125 | -------------------------------------------------------------------------------- /doc/_static/java-apidocs/org/jpy/class-use/PyLib.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Uses of Class org.jpy.PyLib (Java-Python Bridge 0.10.0 Java API) 8 | 9 | 10 | 11 | 12 | 13 | 23 | 26 | 27 |
28 | 29 | 30 |
Skip navigation links
31 | 32 | 33 | 34 | 43 |
44 | 71 | 72 |
73 |

Uses of Class
org.jpy.PyLib

74 |
75 |
No usage of org.jpy.PyLib
76 | 77 |
78 | 79 | 80 |
Skip navigation links
81 | 82 | 83 | 84 | 93 |
94 | 121 | 122 |

Copyright © 2014–2020 Brockmann Consult GmbH. All rights reserved.

123 | 124 | 125 | -------------------------------------------------------------------------------- /doc/_static/java-apidocs/org/jpy/class-use/StopIteration.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Uses of Class org.jpy.StopIteration (Java-Python Bridge 0.10.0 Java API) 8 | 9 | 10 | 11 | 12 | 13 | 23 | 26 | 27 |
28 | 29 | 30 |
Skip navigation links
31 | 32 | 33 | 34 | 43 |
44 | 71 | 72 |
73 |

Uses of Class
org.jpy.StopIteration

74 |
75 |
No usage of org.jpy.StopIteration
76 | 77 |
78 | 79 | 80 |
Skip navigation links
81 | 82 | 83 | 84 | 93 |
94 | 121 | 122 |

Copyright © 2014–2020 Brockmann Consult GmbH. All rights reserved.

123 | 124 | 125 | -------------------------------------------------------------------------------- /doc/_static/java-apidocs/org/jpy/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | org.jpy (Java-Python Bridge 0.10.0 Java API) 8 | 9 | 10 | 11 | 12 | 13 |

org.jpy

14 |
15 |

Classes

16 | 24 |

Enums

25 | 29 |

Exceptions

30 | 34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /doc/_static/java-apidocs/package-list: -------------------------------------------------------------------------------- 1 | org.jpy 2 | -------------------------------------------------------------------------------- /doc/_static/java-apidocs/script.js: -------------------------------------------------------------------------------- 1 | function show(type) 2 | { 3 | count = 0; 4 | for (var key in methods) { 5 | var row = document.getElementById(key); 6 | if ((methods[key] & type) != 0) { 7 | row.style.display = ''; 8 | row.className = (count++ % 2) ? rowColor : altColor; 9 | } 10 | else 11 | row.style.display = 'none'; 12 | } 13 | updateTabs(type); 14 | } 15 | 16 | function updateTabs(type) 17 | { 18 | for (var value in tabs) { 19 | var sNode = document.getElementById(tabs[value][0]); 20 | var spanNode = sNode.firstChild; 21 | if (value == type) { 22 | sNode.className = activeTableTab; 23 | spanNode.innerHTML = tabs[value][1]; 24 | } 25 | else { 26 | sNode.className = tableTab; 27 | spanNode.innerHTML = "" + tabs[value][1] + ""; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /doc/_static/java-apidocs/serialized-form.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Serialized Form (Java-Python Bridge 0.10.0 Java API) 8 | 9 | 10 | 11 | 12 | 13 | 23 | 26 | 27 |
28 | 29 | 30 |
Skip navigation links
31 | 32 | 33 | 34 | 43 |
44 | 71 | 72 |
73 |

Serialized Form

74 |
75 |
76 | 93 |
94 | 95 |
96 | 97 | 98 |
Skip navigation links
99 | 100 | 101 | 102 | 111 |
112 | 139 | 140 |

Copyright © 2014–2020 Brockmann Consult GmbH. All rights reserved.

141 | 142 | 143 | -------------------------------------------------------------------------------- /doc/index.rst: -------------------------------------------------------------------------------- 1 | .. jpy documentation master file, created by 2 | sphinx-quickstart on Mon Jan 20 21:26:19 2014. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to jpy's documentation! 7 | =============================== 8 | 9 | jpy is a *bi-directional* Java-Python bridge allowing you to call Java from Python and Python from Java. 10 | 11 | Contents: 12 | 13 | .. toctree:: 14 | :maxdepth: 2 15 | 16 | intro 17 | install 18 | tutorial 19 | reference 20 | modify 21 | 22 | 23 | Indices and tables 24 | ================== 25 | 26 | * :ref:`genindex` 27 | * :ref:`modindex` 28 | * :ref:`search` 29 | 30 | -------------------------------------------------------------------------------- /doc/modify.rst: -------------------------------------------------------------------------------- 1 | ############# 2 | How to Modify 3 | ############# 4 | 5 | =============== 6 | Rebuild Process 7 | =============== 8 | 9 | jpy's source distribution directory layout uses the `Maven common directory structure `_. 10 | 11 | * ``setup.py`` - Python build/installation script, will compile Python and Java sources, install the libraries and run all unit-level tests. 12 | * ``pom.xml`` - Maven project file to build the Java sources. Called by ``setup.py``. 13 | * ``src/main/c`` - C source files for the jpy Python API 14 | * ``src/test/python`` - Python API test cases 15 | * ``src/main/java`` - Java source files for the jpy Java API 16 | * ``src/test/java`` - Java API test cases 17 | 18 | 19 | After changing any source code just run setup again as indicated in the :ref:`build` process. 20 | 21 | 22 | After changing signatures of native methods in ``src/main/java/org/jpy/PyLib.java``, you need to compile the Java classes 23 | and regenerate the C headers for the ``PyLib`` class using Maven:: 24 | 25 | mvn compile 26 | javah -d src/main/c/jni -v -classpath target/classes org.jpy.PyLib 27 | 28 | Then always adapt changes ``org_jpy_PyLib.c`` according to newly generated ``org_jpy_PyLib.h`` and ``org_jpy_PyLib_Diag.h``. 29 | Files are found in ``src/main/c/jni/``. Then run setup again as indicated above. 30 | 31 | ======================= 32 | C Programming Guideline 33 | ======================= 34 | 35 | * Follow style used in Python itself 36 | * Python type global variable names: `J_Type` 37 | * Python type instance structs: `JPy_J` 38 | * Python function decl for a type: `J_(JNIEnv* jenv, JPy_J* , ...)` 39 | * The pointer is always the first parameter, only type slots obtain their `jenv` from `JPy_GetJEnv()` 40 | * Python slots function for a type: `J_(JNIEnv* jenv, JPy_J* self, ...)` 41 | * Usually functions shall indicate errors by returning NULL or -1 on error. 42 | Callers can expect that the PyErr_SetError has been set correctly and thus simply 43 | return NULL or -1 again. 44 | Exception: very simple functions, e.g. `JObj_Check()`, can go without error status indication. 45 | * Naming conventions: 46 | 47 | * jpy_jtype.h/c - The Java Meta-Type 48 | * JPy_JType type 49 | * JType_xxx() functions 50 | * jpy_jobj.h/c - The Java Object Wrapper 51 | * JPy_JObj type 52 | * JObj_xxx() functions 53 | * jpy_jmethod.h/c - The Java Method Wrapper 54 | * JPy_JMethod type 55 | * JPy_JOverloadedMethod type 56 | * JMethod_xxx() functions 57 | * JOverloadedMethod_xxx() functions 58 | * jpy_jfield.h/c - The Java Field Wrapper 59 | * JPy_JField type 60 | * JField_xxx() functions 61 | * jpy_conv.h/c - Conversion of Python objects from/to Java values 62 | * JPy_From functions / JPy_FROM_ macros create Python objects (new references!) from Java types 63 | * JPy_As functions / JPy_AS_ macros convert from Python objects to Java types 64 | * jpy_diag.h/c - Control of outputting diagnostic info 65 | * JPy_Diag type 66 | * JPy_DIAG_F_ macros 67 | * JPy_DIAG_PRINT(flags, format, ...) macros 68 | * jpy_module.h/c - The 'jpy' module definition 69 | * JPy_xxx() functions 70 | * jni/org_jpy_PyLib.h - generated by javah from PyLib.java 71 | * jni/org_jpy_PyLib_Diag.h - generated by javah from PyLib.java 72 | * jni/org_jpy_PyLib.c - native implementations from PyLib.java 73 | 74 | -------------------------------------------------------------------------------- /doc/tutorial.rst: -------------------------------------------------------------------------------- 1 | ######## 2 | Tutorial 3 | ######## 4 | 5 | 6 | Sorry, the jpy tutorial is not yet written. Meanwhile please refer to jpy's Python and Java unit-level tests 7 | in order to learn how to use jpy. They are located at 8 | 9 | * `src/test/python `_ 10 | * `src/test/java `_ 11 | 12 | 13 | ********************* 14 | Using jpy with Python 15 | ********************* 16 | 17 | Using the Java Standard Library 18 | =============================== 19 | 20 | 21 | Calling your Java Classes from Python 22 | ===================================== 23 | 24 | 25 | Primitive array parameters that are mutable 26 | ------------------------------------------- 27 | 28 | 29 | Primitive array parameters that are return value 30 | ------------------------------------------------ 31 | 32 | 33 | 34 | ******************* 35 | Using jpy with Java 36 | ******************* 37 | 38 | 39 | Getting Started 40 | =============== 41 | 42 | 43 | Using the Python Standard Library 44 | ================================= 45 | 46 | 47 | Calling your Python functions from Java 48 | ======================================= 49 | 50 | 51 | Extending Java with Python 52 | ========================== 53 | -------------------------------------------------------------------------------- /pysobug/.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | *.o 3 | *.so 4 | mypy 5 | 6 | 7 | -------------------------------------------------------------------------------- /pysobug/README.txt: -------------------------------------------------------------------------------- 1 | 2 | ############################# 3 | Python shared library problem 4 | ############################# 5 | 6 | Problem: Native Python C-extensions can't find Python symbols if Python interpreter is embedded into a shared library. 7 | This problem does not occur on Windows systems. 8 | 9 | * mypydl.c - Source for a shared libary (mypydl.so) that embeds a Python interpreter 10 | * mypy.c - Source for a main program (mypy) that dynamically loads the shared library mypydl.so 11 | * mypymod.c - Native Python extension module (mypymod) that uses the Python C-API 12 | 13 | make.sh - builds mypydl.so, mypy and the mypymod Python extension module. 14 | 15 | The main program mypy interprets all given arguments as Python code and executes it:: 16 | 17 | $ bash ./make.sh 18 | $ ./mypy "print('Hello')" 19 | mypy: executing [print('Hello')] 20 | Hello 21 | mypy: status 0 22 | 23 | Here is how to reproduce the problem:: 24 | 25 | $ ./mypy "import mypymod" 26 | mypy: executing [import mypymod] 27 | Traceback (most recent call last): 28 | File "", line 1, in 29 | ImportError: /home/norman/.local/lib/python3.4/site-packages/mypymod.cpython-34m.so: undefined symbol: Py_BuildValue 30 | ... 31 | mypy: status -1 32 | 33 | Or with numpy:: 34 | 35 | $ ./mypy "import numpy" 36 | mypy: executing [import numpy] 37 | ... 38 | ImportError: /home/norman/.local/lib/python3.4/site-packages/numpy/core/multiarray.cpython-34m.so: undefined symbol: PyExc_SystemError 39 | mypy: status -1 40 | 41 | 42 | If the Python shared library is explicitly pre-loaded, then these errors don't occur:: 43 | 44 | $ LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libpython3.4m.so ./mypy "import mypymod" 45 | mypy: executing [import mypymod] 46 | PyInit_mypymod: enter 47 | PyInit_mypymod: exit: module=0x7f72d34a4188 48 | mypy: status 0 49 | 50 | The error also doesn't occur, if I link my Python extension module explicitly against the Python shared library:: 51 | 52 | extension = Extension('mypymod', sources=['mypymod.c'], libraries=['python3.4m']) 53 | setup(name='mypymod', ext_modules=[extension]) 54 | 55 | Understandably but unfortunately, most Python extensions don't declare the dependency to a specific Python version explicitly. -------------------------------------------------------------------------------- /pysobug/make.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -x #echo on 3 | 4 | # These are more or less the compiler and linker flags used by Python's distutils.core.setup() 5 | 6 | CC_FLAGS="-pthread -g -fwrapv -O2 -Wall -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2" 7 | LD_FLAGS="-shared -fPIC -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-O1" 8 | 9 | gcc $CC_FLAGS mypy.c -ldl -o mypy 10 | gcc $CC_FLAGS mypydl.c -I/usr/include/python3.4m -lpython3.4m $LD_FLAGS -o mypydl.so 11 | 12 | python3 setup.py install --user 13 | 14 | -------------------------------------------------------------------------------- /pysobug/mypy.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | typedef int (*mypy_run_fn)(int argc, const char** argv); 6 | 7 | int main(int argc, const char** argv) 8 | { 9 | void* handle; 10 | mypy_run_fn mypy_run; 11 | 12 | // This one works 13 | handle = dlopen("./mypydl.so", RTLD_LAZY | RTLD_GLOBAL); 14 | // This one not 15 | //handle = dlopen("./mypydl.so", RTLD_LAZY); 16 | if (handle == NULL) { 17 | fprintf(stderr, "mypy: error: %s\n", dlerror()); 18 | return 1; 19 | } 20 | 21 | mypy_run = (mypy_run_fn) dlsym(handle, "mypy_run"); 22 | if (mypy_run == NULL) { 23 | fprintf(stderr, "mypy: error: %s\n", dlerror()); 24 | return 2; 25 | } 26 | 27 | mypy_run(argc - 1, argv + 1); 28 | 29 | dlclose(handle); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /pysobug/mypydl.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int mypy_run(int argc, const char** argv) 4 | { 5 | const char* script; 6 | int i, status; 7 | 8 | Py_Initialize(); 9 | 10 | for (i = 0; i < argc; i++) { 11 | script = argv[i]; 12 | printf("mypy: executing [%s]\n", script); 13 | status = PyRun_SimpleString(script); 14 | printf("mypy: status %d\n", status); 15 | } 16 | 17 | Py_Finalize(); 18 | 19 | return 0; 20 | } 21 | 22 | -------------------------------------------------------------------------------- /pysobug/mypymod.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | PyObject* id(PyObject* self, PyObject* args); 5 | 6 | 7 | static PyMethodDef functions[] = 8 | { 9 | {"id", id, METH_VARARGS, "id()"}, 10 | {NULL, NULL, 0, NULL} /*Sentinel*/ 11 | }; 12 | 13 | 14 | static struct PyModuleDef module_def = 15 | { 16 | PyModuleDef_HEAD_INIT, 17 | "mypymod", /* Name */ 18 | "My Python Module", /* Module documentation */ 19 | -1, /* Size of per-interpreter state */ 20 | functions, 21 | NULL, // m_reload 22 | NULL, // m_traverse 23 | NULL, // m_clear 24 | NULL // m_free 25 | }; 26 | 27 | 28 | PyMODINIT_FUNC PyInit_mypymod(void) 29 | { 30 | PyObject* module = NULL; 31 | 32 | printf("PyInit_mypymod: enter\n"); 33 | 34 | module = PyModule_Create(&module_def); 35 | if (module == NULL) { 36 | return NULL; 37 | } 38 | 39 | printf("PyInit_mypymod: exit: module=%p\n", module); 40 | 41 | return module; 42 | } 43 | 44 | 45 | PyObject* id(PyObject* self, PyObject* args) 46 | { 47 | static int idval = 0; 48 | idval++; 49 | return Py_BuildValue("i", idval); 50 | } 51 | 52 | 53 | -------------------------------------------------------------------------------- /pysobug/setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from distutils.core import setup 4 | from distutils.extension import Extension 5 | 6 | # This one works 7 | #extension = Extension('mypymod', sources=['mypymod.c'], libraries=['python3.4m']) 8 | # This one not 9 | extension = Extension('mypymod', sources=['mypymod.c']) 10 | setup(name='mypymod', ext_modules=[extension]) 11 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [global] 2 | verbose = 1 3 | 4 | [build] 5 | force = 1 6 | 7 | [install] 8 | record = setup.out 9 | 10 | [metadata] 11 | description-file = README.md -------------------------------------------------------------------------------- /src/main/c/jni/org_jpy_DL.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "org_jpy_DL.h" 18 | 19 | #if !defined(_WIN32) && !defined(__CYGWIN__) 20 | 21 | #include 22 | 23 | /* 24 | * Class: org_jpy_DL 25 | * Method: dlopen 26 | * Signature: (Ljava/lang/String;I)J 27 | */ 28 | JNIEXPORT jlong JNICALL Java_org_jpy_DL_dlopen 29 | (JNIEnv *jenv, jclass dlClass, jstring jPath, jint mode) 30 | { 31 | const char* path; 32 | int flags; 33 | 34 | if (jPath == NULL) { 35 | return 0; 36 | } 37 | 38 | path = (*jenv)->GetStringUTFChars(jenv, jPath, NULL); 39 | if (path == NULL) { 40 | return 0; 41 | } 42 | 43 | flags = 0; 44 | if ((mode & org_jpy_DL_RTLD_LAZY) != 0) { 45 | flags |= RTLD_LAZY; 46 | } 47 | if ((mode & org_jpy_DL_RTLD_NOW) != 0) { 48 | flags |= RTLD_NOW; 49 | } 50 | if ((mode & org_jpy_DL_RTLD_LOCAL) != 0) { 51 | flags |= RTLD_LOCAL; 52 | } 53 | if ((mode & org_jpy_DL_RTLD_GLOBAL) != 0) { 54 | flags |= RTLD_GLOBAL; 55 | } 56 | 57 | return (jlong) dlopen(path, flags); 58 | } 59 | 60 | /* 61 | * Class: org_jpy_DL 62 | * Method: dlclose 63 | * Signature: (J)I 64 | */ 65 | JNIEXPORT jint JNICALL Java_org_jpy_DL_dlclose 66 | (JNIEnv *jenv, jclass dlClass, jlong handle) 67 | { 68 | return dlclose((void*) handle); 69 | } 70 | 71 | /* 72 | * Class: org_jpy_DL 73 | * Method: dlerror 74 | * Signature: ()Ljava/lang/String; 75 | */ 76 | JNIEXPORT jstring JNICALL Java_org_jpy_DL_dlerror 77 | (JNIEnv *jenv, jclass dlClass) 78 | { 79 | const char* message; 80 | 81 | message = dlerror(); 82 | if (message != NULL) { 83 | return (*jenv)->NewStringUTF(jenv, message); 84 | } else { 85 | return NULL; 86 | } 87 | } 88 | 89 | #else /* !defined(_WIN32) && !defined(__CYGWIN__) */ 90 | 91 | // Dummy DLL entry point for Python 2.7 (Windows requires it) 92 | __declspec(dllexport) void initjdl(void) { } 93 | 94 | // Dummy DLL entry point for Python 3.3+ (Windows requires it) 95 | __declspec(dllexport) void* PyInit_jdl(void) { return NULL; } 96 | 97 | /* 98 | * Class: org_jpy_DL 99 | * Method: dlopen 100 | * Signature: (Ljava/lang/String;I)J 101 | */ 102 | JNIEXPORT jlong JNICALL Java_org_jpy_DL_dlopen 103 | (JNIEnv *jenv, jclass dlClass, jstring jPath, jint mode) 104 | { 105 | return 0; 106 | } 107 | 108 | /* 109 | * Class: org_jpy_DL 110 | * Method: dlclose 111 | * Signature: (J)I 112 | */ 113 | JNIEXPORT jint JNICALL Java_org_jpy_DL_dlclose 114 | (JNIEnv *jenv, jclass dlClass, jlong handle) 115 | { 116 | return 0; 117 | } 118 | 119 | /* 120 | * Class: org_jpy_DL 121 | * Method: dlerror 122 | * Signature: ()Ljava/lang/String; 123 | */ 124 | JNIEXPORT jstring JNICALL Java_org_jpy_DL_dlerror 125 | (JNIEnv *jenv, jclass dlClass) 126 | { 127 | return NULL; 128 | } 129 | 130 | #endif /* !defined(_WIN32) && !defined(__CYGWIN__) */ 131 | 132 | -------------------------------------------------------------------------------- /src/main/c/jni/org_jpy_DL.h: -------------------------------------------------------------------------------- 1 | /* DO NOT EDIT THIS FILE - it is machine generated */ 2 | #include 3 | /* Header for class org_jpy_DL */ 4 | 5 | #ifndef _Included_org_jpy_DL 6 | #define _Included_org_jpy_DL 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | #undef org_jpy_DL_RTLD_LAZY 11 | #define org_jpy_DL_RTLD_LAZY 1L 12 | #undef org_jpy_DL_RTLD_NOW 13 | #define org_jpy_DL_RTLD_NOW 2L 14 | #undef org_jpy_DL_RTLD_LOCAL 15 | #define org_jpy_DL_RTLD_LOCAL 4L 16 | #undef org_jpy_DL_RTLD_GLOBAL 17 | #define org_jpy_DL_RTLD_GLOBAL 8L 18 | /* 19 | * Class: org_jpy_DL 20 | * Method: dlopen 21 | * Signature: (Ljava/lang/String;I)J 22 | */ 23 | JNIEXPORT jlong JNICALL Java_org_jpy_DL_dlopen 24 | (JNIEnv *, jclass, jstring, jint); 25 | 26 | /* 27 | * Class: org_jpy_DL 28 | * Method: dlclose 29 | * Signature: (J)I 30 | */ 31 | JNIEXPORT jint JNICALL Java_org_jpy_DL_dlclose 32 | (JNIEnv *, jclass, jlong); 33 | 34 | /* 35 | * Class: org_jpy_DL 36 | * Method: dlerror 37 | * Signature: ()Ljava/lang/String; 38 | */ 39 | JNIEXPORT jstring JNICALL Java_org_jpy_DL_dlerror 40 | (JNIEnv *, jclass); 41 | 42 | #ifdef __cplusplus 43 | } 44 | #endif 45 | #endif 46 | -------------------------------------------------------------------------------- /src/main/c/jni/org_jpy_PyLib_CallableKind.h: -------------------------------------------------------------------------------- 1 | /* DO NOT EDIT THIS FILE - it is machine generated */ 2 | #include 3 | /* Header for class org_jpy_PyLib_CallableKind */ 4 | 5 | #ifndef _Included_org_jpy_PyLib_CallableKind 6 | #define _Included_org_jpy_PyLib_CallableKind 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | #endif 14 | -------------------------------------------------------------------------------- /src/main/c/jni/org_jpy_PyLib_Diag.h: -------------------------------------------------------------------------------- 1 | /* DO NOT EDIT THIS FILE - it is machine generated */ 2 | #include 3 | /* Header for class org_jpy_PyLib_Diag */ 4 | 5 | #ifndef _Included_org_jpy_PyLib_Diag 6 | #define _Included_org_jpy_PyLib_Diag 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | #undef org_jpy_PyLib_Diag_F_OFF 11 | #define org_jpy_PyLib_Diag_F_OFF 0L 12 | #undef org_jpy_PyLib_Diag_F_TYPE 13 | #define org_jpy_PyLib_Diag_F_TYPE 1L 14 | #undef org_jpy_PyLib_Diag_F_METH 15 | #define org_jpy_PyLib_Diag_F_METH 2L 16 | #undef org_jpy_PyLib_Diag_F_EXEC 17 | #define org_jpy_PyLib_Diag_F_EXEC 4L 18 | #undef org_jpy_PyLib_Diag_F_MEM 19 | #define org_jpy_PyLib_Diag_F_MEM 8L 20 | #undef org_jpy_PyLib_Diag_F_JVM 21 | #define org_jpy_PyLib_Diag_F_JVM 16L 22 | #undef org_jpy_PyLib_Diag_F_ERR 23 | #define org_jpy_PyLib_Diag_F_ERR 32L 24 | #undef org_jpy_PyLib_Diag_F_ALL 25 | #define org_jpy_PyLib_Diag_F_ALL 255L 26 | /* 27 | * Class: org_jpy_PyLib_Diag 28 | * Method: getFlags 29 | * Signature: ()I 30 | */ 31 | JNIEXPORT jint JNICALL Java_org_jpy_PyLib_00024Diag_getFlags 32 | (JNIEnv *, jclass); 33 | 34 | /* 35 | * Class: org_jpy_PyLib_Diag 36 | * Method: setFlags 37 | * Signature: (I)V 38 | */ 39 | JNIEXPORT void JNICALL Java_org_jpy_PyLib_00024Diag_setFlags 40 | (JNIEnv *, jclass, jint); 41 | 42 | #ifdef __cplusplus 43 | } 44 | #endif 45 | #endif 46 | -------------------------------------------------------------------------------- /src/main/c/jpy_compat.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "jpy_compat.h" 18 | 19 | 20 | #ifdef JPY_COMPAT_27 21 | 22 | const char* JPy_AsUTF8_PriorToPy33(PyObject* pyStr) 23 | { 24 | if (PyUnicode_Check(pyStr)) { 25 | pyStr = PyUnicode_AsUTF8String(pyStr); 26 | if (pyStr == NULL) { 27 | return NULL; 28 | } 29 | } 30 | return PyString_AsString(pyStr); 31 | } 32 | 33 | wchar_t* JPy_AsWideCharString_PriorToPy33(PyObject* pyUnicode, Py_ssize_t* size) 34 | { 35 | wchar_t* buffer = NULL; 36 | PyObject* pyNewRef = NULL; 37 | 38 | if (!PyUnicode_Check(pyUnicode)) { 39 | pyNewRef = PyUnicode_FromObject(pyUnicode); 40 | if (pyNewRef == NULL) { 41 | goto error; 42 | } 43 | pyUnicode = pyNewRef; 44 | } 45 | 46 | *size = PyUnicode_GET_SIZE(pyUnicode); 47 | if (*size < 0) { 48 | goto error; 49 | } 50 | 51 | buffer = PyMem_New(wchar_t, *size); 52 | if (buffer == NULL) { 53 | goto error; 54 | } 55 | 56 | *size = PyUnicode_AsWideChar((PyUnicodeObject*) pyUnicode, buffer, *size); 57 | if (*size < 0) { 58 | PyMem_Free(buffer); 59 | buffer = NULL; 60 | } 61 | 62 | error: 63 | 64 | Py_XDECREF(pyNewRef); 65 | 66 | return buffer; 67 | } 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /src/main/c/jpy_compat.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef JPY_COMPAT_H 18 | #define JPY_COMPAT_H 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | #include 25 | 26 | #define JPY_VERSION_ERROR "jpy requires either Python 2.7 or Python 3.3+" 27 | 28 | #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION == 7 29 | #define JPY_COMPAT_27 1 30 | #undef JPY_COMPAT_33P 31 | #elif PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION >= 3 32 | #define JPY_COMPAT_33P 1 33 | #if PY_MINOR_VERSION >= 5 34 | #define JPY_COMPAT_35P 1 35 | #endif 36 | #undef JPY_COMPAT_27 37 | #else 38 | #error JPY_VERSION_ERROR 39 | #endif 40 | 41 | 42 | #if defined(JPY_COMPAT_33P) 43 | 44 | #define JPy_IS_CLONG(pyArg) PyLong_Check(pyArg) 45 | #define JPy_AS_CLONG(pyArg) PyLong_AsLong(pyArg) 46 | #define JPy_AS_CLONGLONG(pyArg) PyLong_AsLongLong(pyArg) 47 | #define JPy_FROM_CLONG(cl) PyLong_FromLong(cl) 48 | 49 | #define JPy_IS_STR(pyArg) PyUnicode_Check(pyArg) 50 | #define JPy_FROM_CSTR(cstr) PyUnicode_FromString(cstr) 51 | #define JPy_FROM_FORMAT PyUnicode_FromFormat 52 | 53 | #define JPy_AS_UTF8(unicode) PyUnicode_AsUTF8(unicode) 54 | #define JPy_AS_WIDE_CHAR_STR(unicode, size) PyUnicode_AsWideCharString(unicode, size) 55 | #define JPy_FROM_WIDE_CHAR_STR(wc, size) PyUnicode_FromKindAndData(PyUnicode_2BYTE_KIND, wc, size) 56 | 57 | #elif defined(JPY_COMPAT_27) 58 | 59 | #define JPy_IS_CLONG(pyArg) (PyInt_Check(pyArg) || PyLong_Check(pyArg)) 60 | #define JPy_AS_CLONG(pyArg) (PyInt_Check(pyArg) ? PyInt_AsLong(pyArg) : PyLong_AsLong(pyArg)) 61 | #define JPy_AS_CLONGLONG(pyArg) (PyInt_Check(pyArg) ? PyInt_AsLong(pyArg) : PyLong_AsLongLong(pyArg)) 62 | #define JPy_FROM_CLONG(cl) PyInt_FromLong(cl) 63 | 64 | #define JPy_IS_STR(pyArg) (PyString_Check(pyArg) || PyUnicode_Check(pyArg)) 65 | #define JPy_FROM_CSTR(cstr) PyString_FromString(cstr) 66 | #define JPy_FROM_FORMAT PyString_FromFormat 67 | 68 | // Implement conversion rules from Python 2 to 3 as given here: 69 | // https://docs.python.org/3.3/howto/cporting.html 70 | // http://lucumr.pocoo.org/2011/1/22/forwards-compatible-python/ 71 | 72 | const char* JPy_AsUTF8_PriorToPy33(PyObject* unicode); 73 | wchar_t* JPy_AsWideCharString_PriorToPy33(PyObject *unicode, Py_ssize_t *size); 74 | 75 | #define JPy_AS_UTF8(unicode) JPy_AsUTF8_PriorToPy33(unicode) 76 | #define JPy_AS_WIDE_CHAR_STR(unicode, size) JPy_AsWideCharString_PriorToPy33(unicode, size) 77 | #define JPy_FROM_WIDE_CHAR_STR(wc, size) PyUnicode_FromWideChar(wc, size) 78 | 79 | #endif 80 | 81 | 82 | #ifdef __cplusplus 83 | } /* extern "C" */ 84 | #endif 85 | #endif /* !JPY_COMPAT_H */ 86 | -------------------------------------------------------------------------------- /src/main/c/jpy_conv.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef JPY_CONV_H 18 | #define JPY_CONV_H 19 | 20 | #include "jpy_compat.h" 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | #define JPy_AS_JBOOLEAN(pyArg) (jboolean) (pyArg == Py_True ? 1 : (pyArg == Py_False || pyArg == Py_None) ? 0 : (JPy_AS_CLONG(pyArg)) != 0) 27 | #define JPy_AS_JCHAR(pyArg) (jchar) (pyArg == Py_None ? 0 : JPy_AS_CLONG(pyArg)) 28 | #define JPy_AS_JBYTE(pyArg) (jbyte) (pyArg == Py_None ? 0 : JPy_AS_CLONG(pyArg)) 29 | #define JPy_AS_JSHORT(pyArg) (jshort) (pyArg == Py_None ? 0 : JPy_AS_CLONG(pyArg)) 30 | #define JPy_AS_JINT(pyArg) (jint) (pyArg == Py_None ? 0 : JPy_AS_CLONG(pyArg)) 31 | #define JPy_AS_JLONG(pyArg) (jlong) (pyArg == Py_None ? 0 : JPy_AS_CLONGLONG(pyArg)) 32 | #define JPy_AS_JFLOAT(pyArg) (jfloat) (pyArg == Py_None ? 0 : PyFloat_AsDouble(pyArg)) 33 | #define JPy_AS_JDOUBLE(pyArg) (jdouble) (pyArg == Py_None ? 0 : PyFloat_AsDouble(pyArg)) 34 | 35 | #if defined(JPY_COMPAT_33P) 36 | 37 | #define JPy_FROM_JBOOLEAN(jArg) PyBool_FromLong(jArg) 38 | #define JPy_FROM_JCHAR(jArg) PyLong_FromLong(jArg) 39 | #define JPy_FROM_JBYTE(jArg) PyLong_FromLong(jArg) 40 | #define JPy_FROM_JSHORT(jArg) PyLong_FromLong(jArg) 41 | #define JPy_FROM_JINT(jArg) PyLong_FromLong(jArg) 42 | #define JPy_FROM_JLONG(jArg) PyLong_FromLongLong(jArg) 43 | #define JPy_FROM_JFLOAT(jArg) PyFloat_FromDouble(jArg) 44 | #define JPy_FROM_JDOUBLE(jArg) PyFloat_FromDouble(jArg) 45 | 46 | #elif defined(JPY_COMPAT_27) 47 | 48 | #define JPy_FROM_JBOOLEAN(jArg) PyBool_FromLong(jArg) 49 | #define JPy_FROM_JCHAR(jArg) PyInt_FromLong(jArg) 50 | #define JPy_FROM_JBYTE(jArg) PyInt_FromLong(jArg) 51 | #define JPy_FROM_JSHORT(jArg) PyInt_FromLong(jArg) 52 | #define JPy_FROM_JINT(jArg) PyLong_FromLong(jArg) 53 | #define JPy_FROM_JLONG(jArg) PyLong_FromLongLong(jArg) 54 | #define JPy_FROM_JFLOAT(jArg) PyFloat_FromDouble(jArg) 55 | #define JPy_FROM_JDOUBLE(jArg) PyFloat_FromDouble(jArg) 56 | 57 | #else 58 | 59 | #error JPY_VERSION_ERROR 60 | 61 | #endif 62 | 63 | #define JPy_FROM_JVOID() Py_BuildValue("") 64 | #define JPy_FROM_JNULL() Py_BuildValue("") 65 | 66 | 67 | /** 68 | * Convert Java string to Python string/unicode object. 69 | */ 70 | PyObject* JPy_FromJString(JNIEnv* jenv, jstring stringRef); 71 | 72 | /** 73 | * Convert any Java Object to Python Object. 74 | */ 75 | PyObject* JPy_FromJObject(JNIEnv* jenv, jobject objectRef); 76 | 77 | /** 78 | * Convert any Java Object of known type to Python Object. 79 | */ 80 | PyObject* JPy_FromJObjectWithType(JNIEnv* jenv, jobject objectRef, JPy_JType* type); 81 | 82 | /** 83 | * Convert Python unicode object to Java String. 84 | */ 85 | int JPy_AsJString(JNIEnv* jenv, PyObject* pyObj, jstring* stringRef); 86 | 87 | /** 88 | * Convert any Python objects to Java object. 89 | * 90 | * @param allowObjectWrapping if true, may return a PyObject for unrecognized object types 91 | */ 92 | int JPy_AsJObject(JNIEnv* jenv, PyObject* pyObj, jobject* objectRef, jboolean allowObjectWrapping); 93 | 94 | /** 95 | * Convert Python objects to Java object with known type. 96 | */ 97 | int JPy_AsJObjectWithType(JNIEnv* jenv, PyObject* pyObj, jobject* objectRef, JPy_JType* type); 98 | 99 | /** 100 | * Convert Python objects to Java object with known type. 101 | */ 102 | int JPy_AsJObjectWithClass(JNIEnv* jenv, PyObject* pyObj, jobject* objectRef, jclass classRef); 103 | 104 | 105 | /** 106 | * Creates a Python unicode object representing the name of the given class. 107 | * Returns a new reference. 108 | */ 109 | PyObject* JPy_FromTypeName(JNIEnv* jenv, jclass classRef); 110 | 111 | /** 112 | * Gets the UTF8-encoded name of the given Java type. 113 | * Caller is responsible for freeing the returned string using PyMem_Del(). 114 | */ 115 | char* JPy_GetTypeName(JNIEnv* jenv, jclass classRef); 116 | 117 | 118 | #ifdef __cplusplus 119 | } /* extern "C" */ 120 | #endif 121 | 122 | #endif /* !JPY_CONV_H */ -------------------------------------------------------------------------------- /src/main/c/jpy_diag.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef JPY_DIAG_H 18 | #define JPY_DIAG_H 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | #include "jpy_compat.h" 25 | 26 | typedef struct JPy_Diag 27 | { 28 | PyObject_HEAD 29 | int flags; 30 | int F_OFF; 31 | int F_TYPE; 32 | int F_METH; 33 | int F_EXEC; 34 | int F_MEM; 35 | int F_JVM; 36 | int F_ERR; 37 | int F_ALL; 38 | } 39 | JPy_Diag; 40 | 41 | 42 | #define JPy_DIAG_F_OFF 0x00 43 | #define JPy_DIAG_F_TYPE 0x01 44 | #define JPy_DIAG_F_METH 0x02 45 | #define JPy_DIAG_F_EXEC 0x04 46 | #define JPy_DIAG_F_MEM 0x08 47 | #define JPy_DIAG_F_JVM 0x10 48 | #define JPy_DIAG_F_ERR 0x20 49 | #define JPy_DIAG_F_ALL 0xff 50 | 51 | extern PyTypeObject Diag_Type; 52 | extern int JPy_DiagFlags; 53 | 54 | PyObject* Diag_New(void); 55 | 56 | void JPy_DiagPrint(int diagFlags, const char * format, ...); 57 | 58 | #define JPy_DIAG_PRINT if (JPy_DiagFlags != 0) JPy_DiagPrint 59 | 60 | 61 | #ifdef __cplusplus 62 | } /* extern "C" */ 63 | #endif 64 | #endif /* !JPY_DIAG_H */ -------------------------------------------------------------------------------- /src/main/c/jpy_jarray.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef JPY_JARRAY_H 18 | #define JPY_JARRAY_H 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | #include "jpy_compat.h" 25 | 26 | /** 27 | * The Java primitive array representation in Python. 28 | * 29 | * IMPORTANT: JPy_JArray must only differ from the JPy_JObj structure by the 'bufferExportCount' member 30 | * since we use the same basic type, name JPy_JType for it. DON'T ever change member positions! 31 | * @see JPy_JObj 32 | */ 33 | typedef struct JPy_JArray 34 | { 35 | PyObject_HEAD 36 | jobject objectRef; 37 | jint bufferExportCount; 38 | } 39 | JPy_JArray; 40 | 41 | extern PyBufferProcs JArray_as_buffer_boolean; 42 | extern PyBufferProcs JArray_as_buffer_char; 43 | extern PyBufferProcs JArray_as_buffer_byte; 44 | extern PyBufferProcs JArray_as_buffer_short; 45 | extern PyBufferProcs JArray_as_buffer_int; 46 | extern PyBufferProcs JArray_as_buffer_long; 47 | extern PyBufferProcs JArray_as_buffer_float; 48 | extern PyBufferProcs JArray_as_buffer_double; 49 | 50 | #ifdef __cplusplus 51 | } /* extern "C" */ 52 | #endif 53 | #endif /* !JPY_JARRAY_H */ 54 | -------------------------------------------------------------------------------- /src/main/c/jpy_jfield.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "jpy_module.h" 18 | #include "jpy_diag.h" 19 | #include "jpy_jtype.h" 20 | #include "jpy_jobj.h" 21 | #include "jpy_jfield.h" 22 | #include "jpy_conv.h" 23 | #include "jpy_compat.h" 24 | 25 | 26 | JPy_JField* JField_New(JPy_JType* declaringClass, PyObject* fieldName, JPy_JType* fieldType, jboolean isStatic, jboolean isFinal, jfieldID fid) 27 | { 28 | PyTypeObject* type = &JField_Type; 29 | JPy_JField* field; 30 | 31 | field = (JPy_JField*) type->tp_alloc(type, 0); 32 | field->declaringClass = declaringClass; 33 | field->name = fieldName; 34 | field->type = fieldType; 35 | field->isStatic = isStatic; 36 | field->isFinal = isFinal; 37 | field->fid = fid; 38 | 39 | Py_INCREF(field->name); 40 | Py_INCREF(field->type); 41 | 42 | return field; 43 | } 44 | 45 | /** 46 | * The JField type's tp_dealloc slot. 47 | */ 48 | void JField_dealloc(JPy_JField* self) 49 | { 50 | Py_DECREF(self->name); 51 | Py_DECREF(self->type); 52 | Py_TYPE(self)->tp_free((PyObject*) self); 53 | } 54 | 55 | void JField_Del(JPy_JField* field) 56 | { 57 | JField_dealloc(field); 58 | } 59 | 60 | 61 | /** 62 | * The JField type's tp_repr slot. 63 | */ 64 | PyObject* JField_repr(JPy_JField* self) 65 | { 66 | const char* name = JPy_AS_UTF8(self->name); 67 | return JPy_FROM_FORMAT("%s(name='%s', is_static=%d, is_final=%d, fid=%p)", 68 | ((PyObject*)self)->ob_type->tp_name, 69 | name, 70 | self->isStatic, 71 | self->isFinal, 72 | self->fid); 73 | } 74 | 75 | /** 76 | * The JField type's tp_str slot. 77 | */ 78 | PyObject* JField_str(JPy_JField* self) 79 | { 80 | Py_INCREF(self->name); 81 | return self->name; 82 | } 83 | 84 | 85 | static PyMemberDef JField_members[] = 86 | { 87 | {"name", T_OBJECT_EX, offsetof(JPy_JField, name), READONLY, "Field name"}, 88 | {"is_static", T_BOOL, offsetof(JPy_JField, isStatic), READONLY, "Tests if this is a static field"}, 89 | {"is_final", T_BOOL, offsetof(JPy_JField, isFinal), READONLY, "Tests if this is a final field"}, 90 | {NULL} /* Sentinel */ 91 | }; 92 | 93 | 94 | /** 95 | * Implements the BeamPy_JObjectType class singleton. 96 | */ 97 | PyTypeObject JField_Type = { 98 | PyVarObject_HEAD_INIT(NULL, 0) 99 | "jpy.JField", /* tp_name */ 100 | sizeof (JPy_JField), /* tp_basicsize */ 101 | 0, /* tp_itemsize */ 102 | (destructor)JField_dealloc, /* tp_dealloc */ 103 | NULL, /* tp_print */ 104 | NULL, /* tp_getattr */ 105 | NULL, /* tp_setattr */ 106 | NULL, /* tp_reserved */ 107 | (reprfunc)JField_repr, /* tp_repr */ 108 | NULL, /* tp_as_number */ 109 | NULL, /* tp_as_sequence */ 110 | NULL, /* tp_as_mapping */ 111 | NULL, /* tp_hash */ 112 | NULL, /* tp_call */ 113 | (reprfunc)JField_str, /* tp_str */ 114 | NULL, /* tp_getattro */ 115 | NULL, /* tp_setattro */ 116 | NULL, /* tp_as_buffer */ 117 | Py_TPFLAGS_DEFAULT, /* tp_flags */ 118 | "Java Field Wrapper", /* tp_doc */ 119 | NULL, /* tp_traverse */ 120 | NULL, /* tp_clear */ 121 | NULL, /* tp_richcompare */ 122 | 0, /* tp_weaklistoffset */ 123 | NULL, /* tp_iter */ 124 | NULL, /* tp_iternext */ 125 | NULL, /* tp_methods */ 126 | JField_members, /* tp_members */ 127 | NULL, /* tp_getset */ 128 | NULL, /* tp_base */ 129 | NULL, /* tp_dict */ 130 | NULL, /* tp_descr_get */ 131 | NULL, /* tp_descr_set */ 132 | 0, /* tp_dictoffset */ 133 | NULL, /* tp_init */ 134 | NULL, /* tp_alloc */ 135 | NULL, /* tp_new */ 136 | }; -------------------------------------------------------------------------------- /src/main/c/jpy_jfield.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef JPY_JFIELD_H 18 | #define JPY_JFIELD_H 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | #include "jpy_compat.h" 25 | 26 | /** 27 | * Python object representing a Java method. It's type is 'JMethod'. 28 | */ 29 | typedef struct 30 | { 31 | PyObject_HEAD 32 | 33 | // The declaring class. 34 | JPy_JType* declaringClass; 35 | // Field name. 36 | PyObject* name; 37 | // Field type. 38 | JPy_JType* type; 39 | // Method is static? 40 | char isStatic; 41 | // Method is final? 42 | char isFinal; 43 | // Field ID retrieved from JNI. 44 | jfieldID fid; 45 | } 46 | JPy_JField; 47 | 48 | /** 49 | * The Python 'JMethod' type singleton. 50 | */ 51 | extern PyTypeObject JField_Type; 52 | 53 | JPy_JField* JField_New(JPy_JType* declaringType, PyObject* fieldKey, JPy_JType* fieldType, jboolean isStatic, jboolean isFinal, jfieldID fid); 54 | void JField_Del(JPy_JField* field); 55 | 56 | #ifdef __cplusplus 57 | } /* extern "C" */ 58 | #endif 59 | 60 | #endif /* !JPY_JFIELD_H */ -------------------------------------------------------------------------------- /src/main/c/jpy_jmethod.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * This file was modified by Illumon. 17 | */ 18 | 19 | #ifndef JPY_JMETHOD_H 20 | #define JPY_JMETHOD_H 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | #include "jpy_compat.h" 27 | 28 | /** 29 | * Python object representing a Java method. It's type is 'JMethod'. 30 | */ 31 | typedef struct 32 | { 33 | PyObject_HEAD 34 | 35 | // The declaring class. 36 | JPy_JType* declaringClass; 37 | // Method name. 38 | PyObject* name; 39 | // Method parameter count. 40 | int paramCount; 41 | // Method is static? 42 | char isStatic; 43 | // Method is varargs? 44 | char isVarArgs; 45 | // Method parameter types. Will be NULL, if parameter_count == 0. 46 | JPy_ParamDescriptor* paramDescriptors; 47 | // Method return type. Will be NULL for constructors. 48 | JPy_ReturnDescriptor* returnDescriptor; 49 | // The JNI method ID obtained from the declaring class. 50 | jmethodID mid; 51 | } 52 | JPy_JMethod; 53 | 54 | /** 55 | * The Python 'JMethod' type singleton. 56 | */ 57 | extern PyTypeObject JMethod_Type; 58 | 59 | /** 60 | * Python object representing an overloaded Java method. It's type is 'JOverloadedMethod'. 61 | */ 62 | typedef struct 63 | { 64 | PyObject_HEAD 65 | 66 | // The declaring class. 67 | JPy_JType* declaringClass; 68 | // Method name. 69 | PyObject* name; 70 | // List of method overloads (a PyList with items of type JPy_JMethod). 71 | PyObject* methodList; 72 | } 73 | JPy_JOverloadedMethod; 74 | 75 | /** 76 | * The Python 'JOverloadedMethod' type singleton. 77 | */ 78 | extern PyTypeObject JOverloadedMethod_Type; 79 | 80 | JPy_JMethod* JOverloadedMethod_FindMethod(JNIEnv* jenv, JPy_JOverloadedMethod* overloadedMethod, PyObject* argTuple, jboolean visitSuperClass, int *isVarArgsArray); 81 | JPy_JMethod* JOverloadedMethod_FindStaticMethod(JPy_JOverloadedMethod* overloadedMethod, PyObject* argTuple); 82 | JPy_JOverloadedMethod* JOverloadedMethod_New(JPy_JType* declaringClass, PyObject* name, JPy_JMethod* method); 83 | int JOverloadedMethod_AddMethod(JPy_JOverloadedMethod* overloadedMethod, JPy_JMethod* method); 84 | 85 | JPy_JMethod* JMethod_New(JPy_JType* declaringClass, 86 | PyObject* name, 87 | int paramCount, 88 | JPy_ParamDescriptor* paramDescriptors, 89 | JPy_ReturnDescriptor* returnDescriptor, 90 | jboolean isStatic, 91 | jboolean isVarArgs, 92 | jmethodID mid); 93 | 94 | void JMethod_Del(JPy_JMethod* method); 95 | 96 | int JMethod_ConvertToJavaValues(JNIEnv* jenv, JPy_JMethod* jMethod, int argCount, PyObject* argTuple, jvalue* jArgs); 97 | 98 | int JMethod_CreateJArgs(JNIEnv* jenv, JPy_JMethod* jMethod, PyObject* argTuple, jvalue** jValues, JPy_ArgDisposer** jDisposers, int isVarArgsArray); 99 | void JMethod_DisposeJArgs(JNIEnv* jenv, int paramCount, jvalue* jValues, JPy_ArgDisposer* jDisposers); 100 | 101 | #ifdef __cplusplus 102 | } /* extern "C" */ 103 | #endif 104 | 105 | #endif /* !JPY_JMETHOD_H */ -------------------------------------------------------------------------------- /src/main/c/jpy_jobj.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * This file was modified by Illumon. 17 | * 18 | */ 19 | 20 | #ifndef JPY_JOBJ_H 21 | #define JPY_JOBJ_H 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | #include "jpy_compat.h" 28 | 29 | /** 30 | * The Java Object representation in Python. 31 | * @see JPy_JArray 32 | */ 33 | typedef struct JPy_JObj 34 | { 35 | PyObject_HEAD 36 | jobject objectRef; 37 | } 38 | JPy_JObj; 39 | 40 | 41 | int JObj_Check(PyObject* arg); 42 | 43 | PyObject* JObj_New(JNIEnv* jenv, jobject objectRef); 44 | PyObject* JObj_FromType(JNIEnv* jenv, JPy_JType* type, jobject objectRef); 45 | 46 | int JObj_InitTypeSlots(PyTypeObject* type, const char* typeName, PyTypeObject* superType); 47 | 48 | 49 | #ifdef __cplusplus 50 | } /* extern "C" */ 51 | #endif 52 | #endif /* !JPY_JOBJ_H */ -------------------------------------------------------------------------------- /src/main/c/jpy_jtype.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * 17 | * This file was modified by Illumon. 18 | * 19 | */ 20 | 21 | #ifndef JPY_JTYPE_H 22 | #define JPY_JTYPE_H 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | #include "jpy_compat.h" 29 | 30 | /** 31 | * The Python type 'JType' representing a Java type. 32 | */ 33 | typedef struct JPy_JType 34 | { 35 | // Since this is a type object, inherit everything from from PyTypeObject. 36 | // It is absolutely essential that this is the first struct member! 37 | // typeObj.tp_name is this type's fully qualified Java name (same as 'javaName' field). 38 | PyTypeObject typeObj; 39 | // The Java type name. 40 | char* javaName; 41 | // The JNI class reference (global reference). 42 | jclass classRef; 43 | // The super type of this type. This will be NULL for primitive types, 'void', and 'java.lang.Object'. 44 | struct JPy_JType* superType; 45 | // If component type of this type if this type is an array, NULL otherwise. 46 | struct JPy_JType* componentType; 47 | // If TRUE, 'classRef' refers to a Java primitive type or 'void'. 48 | char isPrimitive; 49 | // If TRUE, 'classRef' refers to a Java interface type. 50 | char isInterface; 51 | // If TRUE, the type is currently being resolved. 52 | char isResolving; 53 | // If TRUE, all the class constructors and methods have already been resolved. 54 | char isResolved; 55 | } 56 | JPy_JType; 57 | 58 | /** 59 | * The 'JType' singleton. 60 | */ 61 | extern PyTypeObject JType_Type; 62 | 63 | typedef void (*JPy_DisposeArg)(JNIEnv*, jvalue* value, void* data); 64 | 65 | /** 66 | * ArgDisposers are used to dispose arguments after invocation of Java methods. 67 | * We need to dispose those arguments which have been created as local references, 68 | * e.g. jenv->NewString(), jenv->NewObjectArray(), jenv->NewArray(). 69 | */ 70 | typedef struct JPy_ArgDisposer 71 | { 72 | void* data; 73 | JPy_DisposeArg DisposeArg; 74 | } 75 | JPy_ArgDisposer; 76 | 77 | 78 | struct JPy_ParamDescriptor; 79 | 80 | typedef int (*JPy_MatchPyArg)(JNIEnv*, struct JPy_ParamDescriptor*, PyObject*); 81 | typedef int (*JPy_MatchVarArgPyArg)(JNIEnv*, struct JPy_ParamDescriptor*, PyObject*, int); 82 | typedef int (*JPy_ConvertPyArg)(JNIEnv*, struct JPy_ParamDescriptor*, PyObject*, jvalue*, JPy_ArgDisposer*); 83 | typedef int (*JPy_ConvertVarArgPyArg)(JNIEnv*, struct JPy_ParamDescriptor*, PyObject*, int, jvalue*, JPy_ArgDisposer*); 84 | 85 | /** 86 | * Method return value descriptor. 87 | */ 88 | typedef struct JPy_ReturnDescriptor 89 | { 90 | /** 91 | * The return type. 92 | */ 93 | JPy_JType* type; 94 | /** 95 | * If JPy_ParamDescriptor.isReturnIndex == TRUE the index of the parameter, whose argument will serve as return value. 96 | * If JPy_ParamDescriptor.isReturnIndex == FALSE it will be -1. 97 | */ 98 | jint paramIndex; 99 | } 100 | JPy_ReturnDescriptor; 101 | 102 | /** 103 | * Method parameter descriptor. 104 | */ 105 | typedef struct JPy_ParamDescriptor 106 | { 107 | JPy_JType* type; 108 | jboolean isMutable; 109 | jboolean isOutput; 110 | jboolean isReturn; 111 | JPy_MatchPyArg MatchPyArg; 112 | JPy_MatchVarArgPyArg MatchVarArgPyArg; 113 | JPy_ConvertPyArg ConvertPyArg; 114 | JPy_ConvertVarArgPyArg ConvertVarArgPyArg; 115 | } 116 | JPy_ParamDescriptor; 117 | 118 | 119 | int JType_Check(PyObject* obj); 120 | 121 | JPy_JType* JType_GetTypeForObject(JNIEnv* jenv, jobject objectRef); 122 | JPy_JType* JType_GetTypeForName(JNIEnv* jenv, const char* typeName, jboolean resolve); 123 | JPy_JType* JType_GetType(JNIEnv* jenv, jclass classRef, jboolean resolve); 124 | 125 | PyObject* JType_ConvertJavaToPythonObject(JNIEnv* jenv, JPy_JType* type, jobject objectRef); 126 | int JType_ConvertPythonToJavaObject(JNIEnv* jenv, JPy_JType* type, PyObject* arg, jobject* objectRef, jboolean allowObjectWrapping); 127 | 128 | PyObject* JType_GetOverloadedMethod(JNIEnv* jenv, JPy_JType* type, PyObject* methodName, jboolean useSuperClass); 129 | 130 | int JType_MatchPyArgAsJObject(JNIEnv* jenv, JPy_JType* type, PyObject* pyArg); 131 | 132 | int JType_CreateJavaArray(JNIEnv* jenv, JPy_JType* componentType, PyObject* pyArg, jobject* objectRef, jboolean allowObjectWrapping); 133 | 134 | // Non-API. Defined in jpy_jobj.c 135 | int JType_InitSlots(JPy_JType* type); 136 | // Non-API. Defined in jpy_jtype.c 137 | int JType_ResolveType(JNIEnv* jenv, JPy_JType* type); 138 | 139 | int JType_AddClassAttribute(JNIEnv* jenv, JPy_JType* type); 140 | 141 | #ifdef __cplusplus 142 | } /* extern "C" */ 143 | #endif 144 | #endif /* !JPY_JTYPE_H */ -------------------------------------------------------------------------------- /src/main/c/jpy_verboseexcept.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * This file was modified by Illumon. 17 | * 18 | */ 19 | 20 | #include 21 | #include "jpy_verboseexcept.h" 22 | 23 | int JPy_VerboseExceptions = 0; 24 | 25 | PyObject* VerboseExceptions_New(void) 26 | { 27 | return PyObject_New(PyObject, &VerboseExceptions_Type); 28 | } 29 | 30 | 31 | PyObject* VerboseExceptions_getattro(PyObject* self, PyObject *attr_name) 32 | { 33 | if (strcmp(JPy_AS_UTF8(attr_name), "enabled") == 0) { 34 | return PyBool_FromLong(JPy_VerboseExceptions); 35 | } else { 36 | return PyObject_GenericGetAttr(self, attr_name); 37 | } 38 | } 39 | 40 | 41 | int VerboseExceptions_setattro(PyObject* self, PyObject *attr_name, PyObject *v) 42 | { 43 | if (strcmp(JPy_AS_UTF8(attr_name), "enabled") == 0) { 44 | if (PyBool_Check(v)) { 45 | JPy_VerboseExceptions = v == Py_True; 46 | } else { 47 | PyErr_SetString(PyExc_ValueError, "value for 'flags' must be a boolean"); 48 | return -1; 49 | } 50 | return 0; 51 | } else { 52 | return PyObject_GenericSetAttr(self, attr_name, v); 53 | } 54 | } 55 | 56 | 57 | PyTypeObject VerboseExceptions_Type = 58 | { 59 | PyVarObject_HEAD_INIT(NULL, 0) 60 | "jpy.VerboseExceptions", /* tp_name */ 61 | sizeof (VerboseExceptions_Type), /* tp_basicsize */ 62 | 0, /* tp_itemsize */ 63 | NULL, /* tp_dealloc */ 64 | NULL, /* tp_print */ 65 | NULL, /* tp_getattr */ 66 | NULL, /* tp_setattr */ 67 | NULL, /* tp_reserved */ 68 | NULL, /* tp_repr */ 69 | NULL, /* tp_as_number */ 70 | NULL, /* tp_as_sequence */ 71 | NULL, /* tp_as_mapping */ 72 | NULL, /* tp_hash */ 73 | NULL, /* tp_call */ 74 | NULL, /* tp_str */ 75 | (getattrofunc) VerboseExceptions_getattro, /* tp_getattro */ 76 | (setattrofunc) VerboseExceptions_setattro, /* tp_setattro */ 77 | NULL, /* tp_as_buffer */ 78 | Py_TPFLAGS_DEFAULT, /* tp_flags */ 79 | "Controls python exception verbosity", /* tp_doc */ 80 | NULL, /* tp_traverse */ 81 | NULL, /* tp_clear */ 82 | NULL, /* tp_richcompare */ 83 | 0, /* tp_weaklistoffset */ 84 | NULL, /* tp_iter */ 85 | NULL, /* tp_iternext */ 86 | NULL, /* tp_methods */ 87 | NULL, /* tp_members */ 88 | NULL, /* tp_getset */ 89 | NULL, /* tp_base */ 90 | NULL, /* tp_dict */ 91 | NULL, /* tp_descr_get */ 92 | NULL, /* tp_descr_set */ 93 | 0, /* tp_dictoffset */ 94 | (initproc) NULL, /* tp_init */ 95 | NULL, /* tp_alloc */ 96 | NULL, /* tp_new */ 97 | }; 98 | -------------------------------------------------------------------------------- /src/main/c/jpy_verboseexcept.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * This file was modified by Illumon. 17 | * 18 | */ 19 | 20 | #ifndef JPY_VERBOSEEXCEPT_H 21 | #define JPY_VERBOSEEXCEPT_H 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | #include "jpy_compat.h" 28 | 29 | extern PyTypeObject VerboseExceptions_Type; 30 | extern int JPy_VerboseExceptions; 31 | 32 | PyObject* VerboseExceptions_New(void); 33 | 34 | #ifdef __cplusplus 35 | } /* extern "C" */ 36 | #endif 37 | #endif /* !JPY_DIAG_H */ -------------------------------------------------------------------------------- /src/main/java/org/jpy/DL.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.jpy; 18 | 19 | /** 20 | * A replacement for {@link System#load(String)} with support for POSIX {@code dlopen} flags. 21 | *

22 | * Important note: This class is useful on POSIX (Unix/Linux) systems only. On Windows OSes, all methods 23 | * are no-ops. 24 | * 25 | * @author Norman Fomferra 26 | * @see dlopen(3) - Linux manual page 27 | * @since 0.7 28 | */ 29 | public class DL { 30 | /** 31 | * Resolve undefined symbols as code from the dynamic library is executed. 32 | */ 33 | public static final int RTLD_LAZY = 0x0001; 34 | /** 35 | * Resolve all undefined symbols before {@link #dlopen} returns and fail if this cannot be done. 36 | */ 37 | public static final int RTLD_NOW = 0x0002; 38 | /** 39 | * This is the converse of RTLD_GLOBAL, and the default if neither flag is specified. 40 | */ 41 | public static final int RTLD_LOCAL = 0x0004; 42 | /** 43 | * External symbols defined in the library will be made available to subsequently loaded libraries. 44 | */ 45 | public static final int RTLD_GLOBAL = 0x0008; 46 | 47 | /** 48 | * loads the dynamic library file named by the null-terminated string filename and returns 49 | * an opaque "handle" for the dynamic library. If filename is {@code null}, then the returned handle 50 | * is for the main program. If filename contains a slash ("/"), then it is interpreted as a 51 | * (relative or absolute) pathname. 52 | * 53 | * @param filename dynamic library filename or {@code null} 54 | * @param flag combination of {@link #RTLD_GLOBAL} or {@link #RTLD_LOCAL} with {@link #RTLD_LAZY}, 55 | * {@link #RTLD_NOW}. 56 | * @return opaque "handle" for the dynamic library. 57 | */ 58 | public static native long dlopen(String filename, int flag); 59 | 60 | public static native int dlclose(long handle); 61 | 62 | public static native String dlerror(); 63 | 64 | static { 65 | try { 66 | System.loadLibrary("jdl"); 67 | } catch (Throwable t) { 68 | String jdlLibPath = System.getProperty("jpy.jdlLib"); 69 | if (jdlLibPath != null) { 70 | System.load(jdlLibPath); 71 | } else { 72 | throw new RuntimeException("Failed to load 'jdl' shared library. You can use system property 'jpy.jdlLib' to specify it.", t); 73 | } 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/org/jpy/KeyError.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * This file was modified by Illumon. 17 | * 18 | */ 19 | package org.jpy; 20 | 21 | /** 22 | * Translation of Python KeyErrors so that they can be programmatically detected from Java. 23 | */ 24 | public class KeyError extends RuntimeException { 25 | KeyError(String message) { 26 | super(message); 27 | } 28 | } -------------------------------------------------------------------------------- /src/main/java/org/jpy/PyInputMode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.jpy; 18 | 19 | import java.util.Map; 20 | 21 | /** 22 | * Source code input modes for compiling/executing Python source code. 23 | * 24 | * @author Norman Fomferra 25 | * @since 0.8 26 | * @see PyObject#executeCode(String, PyInputMode) 27 | * @see PyObject#executeCode(String, PyInputMode, Map, Map) 28 | */ 29 | public enum PyInputMode { 30 | /** 31 | * Compile/execute single statement code. 32 | *

33 | * The start symbol from the Python grammar for a 34 | * single statement ({@code Py_single_input} in Python PyRun API). 35 | * This is the symbol used for the interactive interpreter loop. 36 | */ 37 | STATEMENT(256), 38 | /** 39 | * Compile/execute multi-statement script code. 40 | *

41 | * The start symbol from the Python grammar for sequences of 42 | * statements as read from a file or other source ({@code Py_file_input} in Python PyRun API). 43 | * This is the symbol to use when compiling arbitrarily long Python source code. 44 | */ 45 | SCRIPT(257), 46 | /** 47 | * Compile/execute single expression. 48 | *

49 | * The start symbol from the Python grammar for sequences of 50 | * statements as read from a file or other source ({@code Py_eval_input} in Python PyRun API). 51 | */ 52 | EXPRESSION(258); 53 | 54 | public int value() { 55 | return value; 56 | } 57 | 58 | private final int value; 59 | 60 | PyInputMode(int value) { 61 | this.value = value; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/org/jpy/PyLibConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.jpy; 18 | 19 | import java.io.File; 20 | import java.io.FileReader; 21 | import java.io.IOException; 22 | import java.io.InputStream; 23 | import java.io.InputStreamReader; 24 | import java.io.Reader; 25 | import java.util.Properties; 26 | import java.util.Set; 27 | 28 | /** 29 | * Provides configuration for {@link org.jpy.PyLib}. 30 | * 31 | * @author Norman Fomferra 32 | * @since 0.7 33 | */ 34 | class PyLibConfig { 35 | 36 | private static final boolean DEBUG = Boolean.getBoolean("jpy.debug"); 37 | public static final String PYTHON_LIB_KEY = "jpy.pythonLib"; 38 | public static final String JPY_LIB_KEY = "jpy.jpyLib"; 39 | public static final String JPY_CONFIG_KEY = "jpy.config"; 40 | public static final String JPY_CONFIG_RESOURCE = "jpyconfig.properties"; 41 | 42 | public enum OS { 43 | WINDOWS, 44 | UNIX, 45 | MAC_OS, 46 | SUNOS, 47 | } 48 | 49 | private static final Properties properties = new Properties(); 50 | 51 | 52 | static { 53 | if (DEBUG) System.out.println("org.jpy.PyLibConfig: entered static initializer"); 54 | InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream(JPY_CONFIG_RESOURCE); 55 | if (stream != null) { 56 | loadConfig(stream, JPY_CONFIG_RESOURCE); 57 | } 58 | String path = System.getProperty(JPY_CONFIG_KEY); 59 | if (path != null) { 60 | File file = new File(path); 61 | if (file.isFile()) { 62 | loadConfig(file); 63 | } 64 | } 65 | File file = new File(JPY_CONFIG_RESOURCE).getAbsoluteFile(); 66 | if (file.isFile()) { 67 | loadConfig(file); 68 | } 69 | if (DEBUG) System.out.println("org.jpy.PyLibConfig: exited static initializer"); 70 | } 71 | 72 | private static void loadConfig(InputStream stream, String name) { 73 | try { 74 | if (DEBUG) 75 | System.out.printf(String.format("org.jpy.PyLibConfig: loading configuration resource %s\n", name)); 76 | try (Reader reader = new InputStreamReader(stream)) { 77 | loadConfig(reader); 78 | } 79 | } catch (IOException e) { 80 | if (DEBUG) e.printStackTrace(System.err); 81 | } 82 | } 83 | 84 | private static void loadConfig(File file) { 85 | try { 86 | if (DEBUG) 87 | System.out.printf(String.format("%s: loading configuration file %s\n", PyLibConfig.class.getName(), file)); 88 | try (Reader reader = new FileReader(file)) { 89 | loadConfig(reader); 90 | } 91 | } catch (IOException e) { 92 | System.err.printf("org.jpy.PyLibConfig: %s: %s\n", file, e.getMessage()); 93 | if (DEBUG) e.printStackTrace(System.err); 94 | } 95 | } 96 | 97 | private static void loadConfig(Reader reader) throws IOException { 98 | properties.load(reader); 99 | Set propertyNames = properties.stringPropertyNames(); 100 | for (String propertyName : propertyNames) { 101 | String propertyValue = properties.getProperty(propertyName); 102 | if (propertyValue != null) { 103 | System.setProperty(propertyName, propertyValue); 104 | } 105 | } 106 | } 107 | 108 | public static Properties getProperties() { 109 | return new Properties(properties); 110 | } 111 | 112 | public static String getProperty(String key, boolean mustHave) { 113 | // System properties overwrite .jpy properties 114 | String property = System.getProperty(key); 115 | if (property != null) { 116 | return property; 117 | } 118 | property = properties.getProperty(key); 119 | if (property == null && mustHave) { 120 | throw new RuntimeException("missing configuration property '" + key + "'"); 121 | } 122 | return property; 123 | } 124 | 125 | public static OS getOS() { 126 | String os = System.getProperty("os.name").toLowerCase(); 127 | if (os.contains("win")) { 128 | return OS.WINDOWS; 129 | } else if (os.contains("nix") || os.contains("nux") || os.contains("aix")) { 130 | return OS.UNIX; 131 | } else if (os.contains("mac")) { 132 | return OS.MAC_OS; 133 | } else if (os.contains("sunos")) { 134 | return OS.SUNOS; 135 | } 136 | return null; 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/main/java/org/jpy/PyModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.jpy; 18 | 19 | import java.util.Objects; 20 | import static org.jpy.PyLib.assertPythonRuns; 21 | 22 | /** 23 | * Represents a Python module. 24 | * 25 | * @author Norman Fomferra 26 | * @since 0.7 27 | */ 28 | public class PyModule extends PyObject { 29 | 30 | /** 31 | * The Python module's name. 32 | */ 33 | private final String name; 34 | 35 | PyModule(String name, long pointer) { 36 | super(pointer); 37 | this.name = name; 38 | } 39 | 40 | /** 41 | * @return The Python module's name. 42 | */ 43 | public String getName() { 44 | return name; 45 | } 46 | 47 | /** 48 | * Get the Python interpreter's main module and return its Java representation. 49 | * It can be used to access global scope variables and functions. For example: 50 | *

 51 |      *      PyLib.execScript("def incByOne(x): return x + 1");
 52 |      *      PyModule mainModule = PyModule.getMain();
 53 |      *      PyObject eleven = mainModule.call("incByOne", 10);
 54 |      * 
55 | * 56 | * @return The Python main module's Java representation. 57 | * @since 0.8 58 | */ 59 | public static PyModule getMain() { 60 | return importModule("__main__"); 61 | } 62 | 63 | /** 64 | * Get the Python interpreter's buildins module and returns its Java representation. 65 | * It can be used to call functions such as {@code len()}, {@code type()}, {@code list()}, etc. For example: 66 | *
 67 |      *      builtins = PyModule.getBuiltins();
 68 |      *      PyObject size = builtins.call("len", pyList);
 69 |      * 
70 | * 71 | * @return Java representation of Python's builtin module. 72 | * @see org.jpy.PyObject#call(String, Object...) 73 | * @since 0.8 74 | */ 75 | public static PyModule getBuiltins() { 76 | try { 77 | //Python 3.3+ 78 | return importModule("builtins"); 79 | } catch (Exception e) { 80 | //Python 2.7 81 | return importModule("__builtin__"); 82 | } 83 | } 84 | 85 | /** 86 | * Import a Python module into the Python interpreter and return its Java representation. 87 | * 88 | * @param name The Python module's name. 89 | * @return The Python module's Java representation. 90 | */ 91 | public static PyModule importModule(String name) { 92 | assertPythonRuns(); 93 | Objects.requireNonNull(name, "name must not be null"); 94 | long pointer = PyLib.importModule(name); 95 | return pointer != 0 ? new PyModule(name, pointer) : null; 96 | } 97 | 98 | /** 99 | * Extends Python's 'sys.path' variable by the given module path. 100 | * 101 | * @param modulePath The new module path. Should be an absolute pathname. 102 | * @param prepend If true, the new path will be the new first element of 'sys.path', otherwise it will be the last. 103 | * @return The altered 'sys.path' list. 104 | * @since 0.8 105 | */ 106 | public static PyObject extendSysPath(String modulePath, boolean prepend) { 107 | Objects.requireNonNull(modulePath, "path must not be null"); 108 | PyModule sys = importModule("sys"); 109 | PyObject sysPath = sys.getAttribute("path"); 110 | if (prepend) { 111 | sysPath.call("insert", 0, modulePath); 112 | } else { 113 | sysPath.call("append", modulePath); 114 | } 115 | return sysPath; 116 | } 117 | 118 | 119 | /** 120 | * Create a Java proxy instance of this Python module which contains compatible functions to the ones provided in the 121 | * interface given by the {@code type} parameter. 122 | * 123 | * @param type The interface's type. 124 | * @param The interface name. 125 | * @return A (proxy) instance implementing the given interface. 126 | */ 127 | @Override 128 | public T createProxy(Class type) { 129 | assertPythonRuns(); 130 | Objects.requireNonNull(type, "type must not be null"); 131 | return (T) createProxy(PyLib.CallableKind.FUNCTION, type); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/main/java/org/jpy/StopIteration.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * This file was modified by Illumon. 17 | * 18 | */ 19 | package org.jpy; 20 | 21 | /** 22 | * Translation of Python StopIteration so that they can be programmatically detected from Java. 23 | */ 24 | public class StopIteration extends RuntimeException { 25 | StopIteration(String message) { 26 | super(message); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/jpy/annotations/Mutable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.jpy.annotations; 18 | 19 | import java.lang.annotation.ElementType; 20 | import java.lang.annotation.Retention; 21 | import java.lang.annotation.RetentionPolicy; 22 | import java.lang.annotation.Target; 23 | 24 | /** 25 | * Used to mark method parameters as mutable, that is, an argument's state is expected to be modified by the method. 26 | *

27 | * Note: this class is not used yet. 28 | * 29 | * @author Norman Fomferra 30 | */ 31 | @Target(value = ElementType.PARAMETER) 32 | @Retention(value = RetentionPolicy.RUNTIME) 33 | public @interface Mutable { 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/jpy/annotations/Output.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.jpy.annotations; 18 | 19 | import java.lang.annotation.ElementType; 20 | import java.lang.annotation.Retention; 21 | import java.lang.annotation.RetentionPolicy; 22 | import java.lang.annotation.Target; 23 | 24 | /** 25 | * Used to mark method parameters as mere output, that is, an argument is expected to be written to by the method but not read from. 26 | *

27 | * Note: this class is not used yet. 28 | * 29 | * @author Norman Fomferra 30 | */ 31 | @Target(value = ElementType.PARAMETER) 32 | @Retention(value = RetentionPolicy.RUNTIME) 33 | public @interface Output { 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/jpy/annotations/Return.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.jpy.annotations; 18 | 19 | import java.lang.annotation.ElementType; 20 | import java.lang.annotation.Retention; 21 | import java.lang.annotation.RetentionPolicy; 22 | import java.lang.annotation.Target; 23 | 24 | /** 25 | * Used to mark method parameters as return values, that is, an argument may be returned as-is by the method. 26 | *

27 | * Note: this class is not used yet. 28 | * 29 | * @author Norman Fomferra 30 | */ 31 | @Target(value = ElementType.PARAMETER) 32 | @Retention(value = RetentionPolicy.RUNTIME) 33 | public @interface Return { 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/jpy/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * Provides the classes necessary to 19 | *

    20 | *
  1. create an embedded Python VM,
  2. 21 | *
  3. to execute Python code,
  4. 22 | *
  5. to import Python modules,
  6. 23 | *
  7. to access Python variables, and finally
  8. 24 | *
  9. to call Python functions and class methods.
  10. 25 | *
26 | * 27 | *

28 | * The entry point to the jpy Java API is the {@link org.jpy.PyLib} class which is used to either 29 | * detect an already running Python interpreter or to start a new one: 30 | * 31 | *

32 |  *     if (!PyLib.isPythonRunning()) {
33 |  *         PyLib.startPython(opt1, opt2, ...);
34 |  *     }
35 |  * 
36 | * 37 | * jpy API clients should first call {@link org.jpy.PyLib#isPythonRunning()} in order to check if a Python interpreter is already available. 38 | * If not, {@link org.jpy.PyLib#startPython(String...)} must be called before any other jpy API is used. 39 | *

40 | * Once the Python interpreter in running clients can either execute Python code directly using the {@link org.jpy.PyLib#execScript(String)} method or 41 | * load a Python module using {@link org.jpy.PyModule#importModule(String)}. The returned {@link org.jpy.PyModule} object 42 | * then is the entry point to access Python variables and invoke functions. 43 | *

44 | * Some {@link org.jpy.PyModule} methods return {@link org.jpy.PyObject} instances. These can be used to 45 | * create instances of Python classes, and to access Python class members, attributes and to invoke Python object methods.. 46 | * 47 | * @since 0.7 48 | */ 49 | package org.jpy; -------------------------------------------------------------------------------- /src/test/java/org/jpy/LifeCycleTest.java: -------------------------------------------------------------------------------- 1 | package org.jpy; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | public class LifeCycleTest { 7 | private static final boolean ON_WINDOWS = System.getProperty("os.name").toLowerCase().contains("windows"); 8 | 9 | @Test 10 | public void testCanStartAndStopWithoutException() { 11 | PyLib.startPython(); 12 | Assert.assertTrue(PyLib.isPythonRunning()); 13 | PyModule sys1 = PyModule.importModule("sys"); 14 | Assert.assertNotNull(sys1); 15 | final long sys1Pointer = sys1.getPointer(); 16 | 17 | PyLib.stopPython(); 18 | if (!ON_WINDOWS) { 19 | Assert.assertFalse(PyLib.isPythonRunning()); 20 | } 21 | 22 | PyLib.startPython(); 23 | Assert.assertTrue(PyLib.isPythonRunning()); 24 | 25 | PyModule sys2 = PyModule.importModule("sys"); 26 | Assert.assertNotNull(sys2); 27 | final long sys2Pointer = sys2.getPointer(); 28 | 29 | if (!ON_WINDOWS) { 30 | Assert.assertNotEquals(sys1Pointer, sys2Pointer); 31 | } 32 | 33 | PyLib.stopPython(); 34 | if (!ON_WINDOWS) { 35 | Assert.assertFalse(PyLib.isPythonRunning()); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/org/jpy/PyLibWithSysPathTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.jpy; 18 | 19 | import org.junit.*; 20 | 21 | import java.io.File; 22 | import java.net.URI; 23 | import java.security.CodeSource; 24 | 25 | import static org.junit.Assert.*; 26 | 27 | 28 | public class PyLibWithSysPathTest { 29 | 30 | @Before 31 | public void setUp() throws Exception { 32 | 33 | CodeSource codeSource = PyLibWithSysPathTest.class.getProtectionDomain().getCodeSource(); 34 | if (codeSource == null) { 35 | System.out.println(PyLibWithSysPathTest.class + " not run: no code source found"); 36 | return; 37 | } 38 | URI codeSourceLocation = codeSource.getLocation().toURI(); 39 | System.out.println(PyLibWithSysPathTest.class + ": code source: " + codeSourceLocation); 40 | File codeSourceDir = new File(codeSourceLocation); 41 | if (!codeSourceDir.isDirectory()) { 42 | System.out.println(PyLibWithSysPathTest.class + " not run: code source is not a directory: " + codeSourceLocation); 43 | return; 44 | } 45 | 46 | File pymodulesDir = new File(codeSourceDir, "pymodules"); 47 | //assertFalse(PyLib.isPythonRunning()); 48 | System.out.println("PyLibWithSysPathTest: starting Python with 'sys.path' extension: " + pymodulesDir); 49 | PyLib.startPython(pymodulesDir.getPath()); 50 | //PyLib.startPython("x"); 51 | assertTrue(PyLib.isPythonRunning()); 52 | } 53 | 54 | @After 55 | public void tearDown() throws Exception { 56 | PyLib.stopPython(); 57 | } 58 | 59 | @Test 60 | public void testLoadModule() throws Exception { 61 | PyModule pyModule = PyModule.importModule("mod_1"); 62 | assertNotNull(pyModule); 63 | PyObject pyAnswer = pyModule.getAttribute("answer"); 64 | assertNotNull(pyAnswer); 65 | assertEquals(42, pyAnswer.getIntValue()); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/test/java/org/jpy/PyModuleTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.jpy; 18 | 19 | import org.junit.*; 20 | 21 | import java.io.File; 22 | 23 | import static org.junit.Assert.assertEquals; 24 | import static org.junit.Assert.assertNotNull; 25 | import static org.junit.Assert.assertTrue; 26 | 27 | /** 28 | * @author Norman Fomferra 29 | */ 30 | public class PyModuleTest { 31 | 32 | @Before 33 | public void setUp() throws Exception { 34 | //System.out.println("PyModuleTest: Current thread: " + Thread.currentThread()); 35 | 36 | String importPath = new File("src/test/python/fixtures").getCanonicalPath(); 37 | PyLib.startPython(importPath); 38 | assertEquals(true, PyLib.isPythonRunning()); 39 | 40 | //PyLib.Diag.setFlags(PyLib.Diag.F_METH); 41 | } 42 | 43 | @After 44 | public void tearDown() throws Exception { 45 | PyLib.Diag.setFlags(PyLib.Diag.F_OFF); 46 | PyLib.stopPython(); 47 | } 48 | 49 | @Test 50 | public void testCreateAndCallProxySingleThreaded() throws Exception { 51 | //PyObjectTest.addTestDirToPythonSysPath(); 52 | PyModule procModule = PyModule.importModule("proc_module"); 53 | PyObjectTest.testCallProxySingleThreaded(procModule); 54 | } 55 | 56 | // see https://github.com/bcdev/jpy/issues/26 57 | @Test 58 | public void testCreateAndCallProxyMultiThreaded() throws Exception { 59 | //PyObjectTest.addTestDirToPythonSysPath(); 60 | PyModule procModule = PyModule.importModule("proc_module"); 61 | PyObjectTest.testCallProxyMultiThreaded(procModule); 62 | } 63 | 64 | // see: https://github.com/bcdev/jpy/issues/39: Improve Java exception messages on Python errors #39 65 | @Test 66 | public void testPythonErrorMessages() throws Exception { 67 | //PyObjectTest.addTestDirToPythonSysPath(); 68 | PyModule raiserModule = PyModule.importModule("raise_errors"); 69 | for (int i=0;i < 10;i++) { 70 | try { 71 | raiserModule.call("raise_if_zero", 0); 72 | Assert.fail(); 73 | } catch (RuntimeException e) { 74 | //e.printStackTrace(); 75 | String message = e.getMessage(); 76 | //System.out.println("message = " + message); 77 | assertNotNull(message); 78 | assertTrue(message.startsWith("Error in Python interpreter")); 79 | assertTrue(message.contains("Type: <")); 80 | assertTrue(message.contains("IndexError'>\n")); 81 | assertTrue(message.contains("Value: arg wasn't there\n")); 82 | assertTrue(message.contains("Line: 3\n")); 83 | assertTrue(message.contains("Namespace: raise_if_zero\n")); 84 | assertTrue(message.contains("File: ")); 85 | } 86 | // ok 87 | raiserModule.call("raise_if_zero", 1); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/test/java/org/jpy/UseCases.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.jpy; 18 | 19 | import org.junit.After; 20 | import org.junit.Before; 21 | import org.junit.Assert; 22 | import org.junit.Test; 23 | 24 | import java.util.Locale; 25 | 26 | import static org.junit.Assert.assertEquals; 27 | import static org.junit.Assert.assertTrue; 28 | 29 | /** 30 | * Some (more complex) tests that represent possible API use cases. 31 | * 32 | * @author Norman Fomferra 33 | */ 34 | public class UseCases { 35 | 36 | @Before 37 | public void setUp() { 38 | PyLib.startPython(); 39 | } 40 | 41 | @After 42 | public void tearDown() { 43 | PyLib.stopPython(); 44 | } 45 | 46 | @Test 47 | public void modifyPythonSysPath() { 48 | 49 | PyModule builtinsMod = PyModule.getBuiltins(); 50 | 51 | PyModule sysMod = PyModule.importModule("sys"); 52 | PyObject pathObj = sysMod.getAttribute("path"); 53 | 54 | PyObject lenObj1 = builtinsMod.call("len", pathObj); 55 | pathObj.call("append", "/usr/home/norman/"); 56 | PyObject lenObj2 = builtinsMod.call("len", pathObj); 57 | 58 | int lenVal1 = lenObj1.getIntValue(); 59 | int lenVal2 = lenObj2.getIntValue(); 60 | String[] pathEntries = pathObj.getObjectArrayValue(String.class); 61 | 62 | ///////////////////////////////////////////////// 63 | 64 | assertEquals(lenVal1 + 1, lenVal2); 65 | assertEquals(pathEntries.length, lenVal2); 66 | //for (int i = 0; i < pathEntries.length; i++) { 67 | // System.out.printf("pathEntries[%d] = %s%n", i, pathEntries[i]); 68 | //} 69 | 70 | ///////////////////////////////////////////////// 71 | } 72 | 73 | @Test 74 | public void setAndGetGlobalPythonVariables() throws Exception { 75 | 76 | PyLib.startPython(); 77 | PyLib.execScript("paramInt = 123"); 78 | PyLib.execScript("paramStr = 'abc'"); 79 | PyModule mainModule = PyModule.getMain(); 80 | PyObject paramIntObj = mainModule.getAttribute("paramInt"); 81 | PyObject paramStrObj = mainModule.getAttribute("paramStr"); 82 | int paramIntValue = paramIntObj.getIntValue(); 83 | String paramStrValue = paramStrObj.getStringValue(); 84 | 85 | ///////////////////////////////////////////////// 86 | 87 | assertEquals(123, paramIntValue); 88 | assertEquals("abc", paramStrValue); 89 | 90 | ///////////////////////////////////////////////// 91 | } 92 | 93 | @Test 94 | public void defAndUseGlobalPythonFunction() throws Exception { 95 | 96 | PyLib.startPython(); 97 | PyLib.execScript("def incByOne(x): return x + 1"); 98 | PyModule mainModule = PyModule.getMain(); 99 | PyObject eleven = mainModule.call("incByOne", 10); 100 | 101 | ///////////////////////////////////////////////// 102 | 103 | assertEquals(11, eleven.getIntValue()); 104 | 105 | ///////////////////////////////////////////////// 106 | // Performance test for TheMegaTB: 107 | 108 | long t0 = System.nanoTime(); 109 | long numCalls = 100000; 110 | PyObject num = eleven; 111 | for (long i = 0; i < numCalls; i++) { 112 | num = mainModule.call("incByOne", num); 113 | } 114 | long t1 = System.nanoTime(); 115 | 116 | assertEquals(11 + numCalls, num.getIntValue()); 117 | 118 | double millis = (t1 - t0) / 1000. / 1000.; 119 | double callsPerMilli = numCalls / millis; 120 | double millisPerCall = millis / numCalls; 121 | 122 | System.out.printf("Performance: %10.1f Python-calls/ms, %2.10f ms/Python-call%n", callsPerMilli, millisPerCall); 123 | assertTrue(callsPerMilli > 1.0); 124 | 125 | ///////////////////////////////////////////////// 126 | } 127 | 128 | static { 129 | Locale.setDefault(Locale.ENGLISH); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /src/test/java/org/jpy/fixtures/ConstructorOverloadTestFixture.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.jpy.fixtures; 18 | 19 | /** 20 | * @author Norman Fomferra 21 | */ 22 | @SuppressWarnings("UnusedDeclaration") 23 | public class ConstructorOverloadTestFixture { 24 | String state; 25 | 26 | public ConstructorOverloadTestFixture() { 27 | initState(); 28 | } 29 | 30 | public ConstructorOverloadTestFixture(int a) { 31 | initState(a); 32 | } 33 | 34 | public ConstructorOverloadTestFixture(int a, int b) { 35 | initState(a, b); 36 | } 37 | 38 | public ConstructorOverloadTestFixture(float a) { 39 | initState(a); 40 | } 41 | 42 | public ConstructorOverloadTestFixture(float a, float b) { 43 | initState(a, b); 44 | } 45 | 46 | public ConstructorOverloadTestFixture(int a, float b) { 47 | initState(a, b); 48 | } 49 | 50 | public ConstructorOverloadTestFixture(float a, int b) { 51 | initState(a, b); 52 | } 53 | 54 | public String getState() { 55 | return state; 56 | } 57 | 58 | private void initState(Object... args) { 59 | state = MethodOverloadTestFixture.stringifyArgs(args); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/test/java/org/jpy/fixtures/CovariantOverloadExtendTestFixture.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * This file was modified by Illumon. 17 | */ 18 | 19 | package org.jpy.fixtures; 20 | 21 | import java.lang.reflect.Array; 22 | import java.lang.reflect.Method; 23 | 24 | /** 25 | * Used as a test class for the test cases in jpy_overload_test.py 26 | * 27 | * @author Charles P. Wright 28 | */ 29 | @SuppressWarnings("UnusedDeclaration") 30 | public class CovariantOverloadExtendTestFixture extends CovariantOverloadTestFixture { 31 | public CovariantOverloadExtendTestFixture(int x) { 32 | super(x * 2); 33 | } 34 | 35 | public CovariantOverloadExtendTestFixture foo(Number a, int b) { 36 | return new CovariantOverloadExtendTestFixture(a.intValue() - b); 37 | } 38 | } -------------------------------------------------------------------------------- /src/test/java/org/jpy/fixtures/CovariantOverloadTestFixture.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * This file was modified by Illumon. 17 | */ 18 | 19 | package org.jpy.fixtures; 20 | 21 | import java.lang.reflect.Array; 22 | import java.lang.reflect.Method; 23 | 24 | /** 25 | * Used as a test class for the test cases in jpy_overload_test.py 26 | * 27 | * @author Charles P. Wright 28 | */ 29 | @SuppressWarnings("UnusedDeclaration") 30 | public class CovariantOverloadTestFixture { 31 | int x; 32 | 33 | public CovariantOverloadTestFixture(int x) { 34 | this.x = x; 35 | } 36 | 37 | public CovariantOverloadTestFixture foo(Number a, int b) { 38 | return new CovariantOverloadTestFixture(a.intValue() + b); 39 | } 40 | 41 | public int getX() { 42 | return x; 43 | } 44 | } -------------------------------------------------------------------------------- /src/test/java/org/jpy/fixtures/DefaultInterfaceImplTestFixture.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.jpy.fixtures; 18 | 19 | import static org.jpy.fixtures.MethodOverloadTestFixture.stringifyArgs; 20 | 21 | /** 22 | * Used as a test class for the test cases in jpy_overload_test.py 23 | * 24 | * @author Charles Wright 25 | */ 26 | @SuppressWarnings("UnusedDeclaration") 27 | public class DefaultInterfaceImplTestFixture implements DefaultInterfaceTestFixture { 28 | public int doIt() { 29 | return 2; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/org/jpy/fixtures/DefaultInterfaceTestFixture.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.jpy.fixtures; 18 | 19 | import static org.jpy.fixtures.MethodOverloadTestFixture.stringifyArgs; 20 | 21 | /** 22 | * Used as a test class for the test cases in jpy_overload_test.py 23 | * 24 | * @author Charles Wright 25 | */ 26 | @SuppressWarnings("UnusedDeclaration") 27 | public interface DefaultInterfaceTestFixture { 28 | int doIt(); 29 | 30 | default public int doItPlusOne() { 31 | return 1 + doIt(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/org/jpy/fixtures/ExceptionTestFixture.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * This file was modified by Illumon. 17 | * 18 | */ 19 | 20 | package org.jpy.fixtures; 21 | 22 | import java.io.IOException; 23 | 24 | /** 25 | * Used as a test class for the test cases in jpy_exception_test.py 26 | * 27 | * @author Norman Fomferra 28 | */ 29 | @SuppressWarnings("UnusedDeclaration") 30 | public class ExceptionTestFixture { 31 | public int throwNpeIfArgIsNull(String arg) { 32 | return arg.length(); 33 | } 34 | 35 | public int throwNpeIfArgIsNull2(String arg) { 36 | return throwNpeIfArgIsNull(arg); 37 | } 38 | 39 | public int throwNpeIfArgIsNullNested(String arg) { 40 | try { 41 | return throwNpeIfArgIsNull(arg); 42 | } catch (Exception e) { 43 | throw new RuntimeException("Nested exception", e); 44 | } 45 | } 46 | 47 | public int throwNpeIfArgIsNullNested2(String arg) { 48 | return throwNpeIfArgIsNullNested(arg); 49 | } 50 | 51 | public int throwNpeIfArgIsNullNested3(String arg) { 52 | try { 53 | return throwNpeIfArgIsNullNested2(arg); 54 | } catch (Exception e) { 55 | throw new RuntimeException("Nested exception 3", e); 56 | } 57 | } 58 | 59 | public int throwAioobeIfIndexIsNotZero(int index) { 60 | int[] ints = new int[]{101}; 61 | return ints[index]; 62 | } 63 | 64 | 65 | public void throwRteIfMessageIsNotNull(String message) { 66 | if (message != null) { 67 | throw new RuntimeException(message); 68 | } 69 | } 70 | 71 | public void throwIoeIfMessageIsNotNull(String message) throws IOException { 72 | if (message != null) { 73 | throw new IOException(message); 74 | } 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /src/test/java/org/jpy/fixtures/FieldTestFixture.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.jpy.fixtures; 18 | 19 | /** 20 | * Used as a test class for the test cases in jpy_field_test.py 21 | * 22 | * @author Norman Fomferra 23 | */ 24 | @SuppressWarnings("UnusedDeclaration") 25 | public class FieldTestFixture { 26 | 27 | public static final boolean z_STATIC_FIELD = true; 28 | public static final char c_STATIC_FIELD = 'A'; 29 | public static final byte b_STATIC_FIELD = (byte) 123; 30 | public static final short s_STATIC_FIELD = (short) 12345; 31 | public static final int i_STATIC_FIELD = 123456789; 32 | public static final long j_STATIC_FIELD = 1234567890123456789L; 33 | public static final float f_STATIC_FIELD = 0.12345F; 34 | public static final double d_STATIC_FIELD = 0.123456789; 35 | 36 | public static final String S_OBJ_STATIC_FIELD = "ABC"; 37 | public static final Thing l_OBJ_STATIC_FIELD = new Thing(123); 38 | 39 | public boolean zInstField; 40 | public char cInstField; 41 | public byte bInstField; 42 | public short sInstField; 43 | public int iInstField; 44 | public long jInstField; 45 | public float fInstField; 46 | public double dInstField; 47 | 48 | public Boolean zObjInstField; 49 | public Character cObjInstField; 50 | public Byte bObjInstField; 51 | public Short sObjInstField; 52 | public Integer iObjInstField; 53 | public Long jObjInstField; 54 | public Float fObjInstField; 55 | public Double dObjInstField; 56 | 57 | public String SObjInstField; 58 | public Thing lObjInstField; 59 | } 60 | -------------------------------------------------------------------------------- /src/test/java/org/jpy/fixtures/MethodOverloadTestFixture.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.jpy.fixtures; 18 | 19 | import java.lang.reflect.Array; 20 | 21 | /** 22 | * Used as a test class for the test cases in jpy_overload_test.py 23 | * 24 | * @author Norman Fomferra 25 | */ 26 | @SuppressWarnings("UnusedDeclaration") 27 | public class MethodOverloadTestFixture { 28 | 29 | public String join(int a, int b) { 30 | return stringifyArgs(a, b); 31 | } 32 | 33 | public String join(int a, double b) { 34 | return stringifyArgs(a, b); 35 | } 36 | 37 | public String join(int a, String b) { 38 | return stringifyArgs(a, b); 39 | } 40 | 41 | public String join(double a, int b) { 42 | return stringifyArgs(a, b); 43 | } 44 | 45 | public String join(double a, double b) { 46 | return stringifyArgs(a, b); 47 | } 48 | 49 | public String join(double a, String b) { 50 | return stringifyArgs(a, b); 51 | } 52 | 53 | public String join(String a, int b) { 54 | return stringifyArgs(a, b); 55 | } 56 | 57 | public String join(String a, double b) { 58 | return stringifyArgs(a, b); 59 | } 60 | 61 | public String join(String a, String b) { 62 | return stringifyArgs(a, b); 63 | } 64 | 65 | ////////////////////////////////////////////// 66 | 67 | public String join(String a) { 68 | return stringifyArgs(a); 69 | } 70 | 71 | public String join(String a, String b, String c) { 72 | return stringifyArgs(a, b, c); 73 | } 74 | 75 | ////////////////////////////////////////////// 76 | public String join2(Comparable a, int b, String c, String d) { 77 | return stringifyArgs(a, b, c, d); 78 | } 79 | 80 | ////////////////////////////////////////////// 81 | public String join3(Number a, int b) { 82 | return stringifyArgs(a, b); 83 | } 84 | 85 | /** 86 | * Used to test that we also find overloaded methods in class hierarchies 87 | */ 88 | public static class MethodOverloadTestFixture2 extends MethodOverloadTestFixture { 89 | 90 | public String join(String a, String b, String c, String d) { 91 | return stringifyArgs(a, b, c, d); 92 | } 93 | } 94 | 95 | ////////////////////////////////////////////// 96 | 97 | // Should never been found, since 'float' is not present in Python 98 | public String join(int a, float b) { 99 | return stringifyArgs(a, b); 100 | } 101 | 102 | static String stringifyArgs(Object... args) { 103 | StringBuilder argString = new StringBuilder(); 104 | for (int i = 0; i < args.length; i++) { 105 | if (i > 0) { 106 | argString.append(","); 107 | } 108 | Object arg = args[i]; 109 | if (arg != null) { 110 | Class argClass = arg.getClass(); 111 | argString.append(argClass.getSimpleName()); 112 | argString.append('('); 113 | if (argClass.isArray()) { 114 | stringifyArray(arg, argString); 115 | } else { 116 | stringifyObject(arg, argString); 117 | } 118 | argString.append(')'); 119 | } else { 120 | argString.append("null"); 121 | } 122 | } 123 | return argString.toString(); 124 | } 125 | 126 | private static void stringifyObject(Object arg, StringBuilder argString) { 127 | argString.append(String.valueOf(arg)); 128 | } 129 | 130 | private static void stringifyArray(Object arg, StringBuilder argString) { 131 | boolean primitive = arg.getClass().getComponentType().isPrimitive(); 132 | int length = Array.getLength(arg); 133 | for (int i = 0; i < length; i++) { 134 | Object item = Array.get(arg, i); 135 | if (i > 0) { 136 | argString.append(","); 137 | } 138 | if (primitive) { 139 | argString.append(String.valueOf(item)); 140 | } else { 141 | argString.append(stringifyArgs(item)); 142 | } 143 | } 144 | } 145 | 146 | 147 | } 148 | -------------------------------------------------------------------------------- /src/test/java/org/jpy/fixtures/MethodReturnValueTestFixture.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.jpy.fixtures; 18 | 19 | /** 20 | * Used as a test class for the test cases in jpy_retval_test.py 21 | * Note: Please make sure to not add any method overloads to this class. 22 | * This is done in {@link MethodOverloadTestFixture}. 23 | * 24 | * @author Norman Fomferra 25 | */ 26 | @SuppressWarnings("UnusedDeclaration") 27 | public class MethodReturnValueTestFixture { 28 | 29 | public void getVoid() { 30 | } 31 | 32 | public boolean getValue_boolean(boolean value) { 33 | return value; 34 | } 35 | 36 | public byte getValue_byte(byte value) { 37 | return value; 38 | } 39 | 40 | public short getValue_short(short value) { 41 | return value; 42 | } 43 | 44 | public int getValue_int(int value) { 45 | return value; 46 | } 47 | 48 | public long getValue_long(long value) { 49 | return value; 50 | } 51 | 52 | public float getValue_float(float value) { 53 | return value; 54 | } 55 | 56 | public double getValue_double(double value) { 57 | return value; 58 | } 59 | 60 | public String getString(String string) { 61 | return string; 62 | } 63 | 64 | public Thing getObject(Thing object) { 65 | return object; 66 | } 67 | 68 | /////////////////////////////////////////////////////////////////////////////////// 69 | // 1D-Array Return Values 70 | 71 | public boolean[] getArray1D_boolean(boolean item0, boolean item1, boolean item2) { 72 | return new boolean[]{item0, item1, item2}; 73 | } 74 | 75 | public byte[] getArray1D_byte(byte item0, byte item1, byte item2) { 76 | return new byte[]{item0, item1, item2}; 77 | } 78 | 79 | public short[] getArray1D_short(short item0, short item1, short item2) { 80 | return new short[]{item0, item1, item2}; 81 | } 82 | 83 | public int[] getArray1D_int(int item0, int item1, int item2) { 84 | return new int[]{item0, item1, item2}; 85 | } 86 | 87 | public long[] getArray1D_long(long item0, long item1, long item2) { 88 | return new long[]{item0, item1, item2}; 89 | } 90 | 91 | public float[] getArray1D_float(float item0, float item1, float item2) { 92 | return new float[]{item0, item1, item2}; 93 | } 94 | 95 | public double[] getArray1D_double(double item0, double item1, double item2) { 96 | return new double[]{item0, item1, item2}; 97 | } 98 | 99 | public String[] getArray1D_String(String item0, String item1, String item2) { 100 | return new String[]{item0, item1, item2}; 101 | } 102 | 103 | public Thing[] getArray1D_Object(Thing item0, Thing item1, Thing item2) { 104 | return new Thing[]{item0, item1, item2}; 105 | } 106 | 107 | // add other variants 108 | 109 | /////////////////////////////////////////////////////////////////////////////////// 110 | // 2D-Array Return Values 111 | 112 | public boolean[][] getArray2D_boolean(boolean item00, boolean item01, boolean item10, boolean item11) { 113 | return new boolean[][]{{item00, item01}, {item10, item11}}; 114 | } 115 | 116 | public byte[][] getArray2D_byte(byte item00, byte item01, byte item10, byte item11) { 117 | return new byte[][]{{item00, item01}, {item10, item11}}; 118 | } 119 | 120 | public int[][] getArray2D_byte(int item00, int item01, int item10, int item11) { 121 | return new int[][]{{item00, item01}, {item10, item11}}; 122 | } 123 | 124 | // add other variants 125 | } 126 | -------------------------------------------------------------------------------- /src/test/java/org/jpy/fixtures/ModifyAndReturnParametersTestFixture.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.jpy.fixtures; 18 | 19 | import org.jpy.annotations.Mutable; 20 | import org.jpy.annotations.Output; 21 | import org.jpy.annotations.Return; 22 | 23 | /** 24 | * Used as a test class for the test cases in jpy_modretparam_test.py 25 | * 26 | * @author Norman Fomferra 27 | */ 28 | @SuppressWarnings("UnusedDeclaration") 29 | public class ModifyAndReturnParametersTestFixture { 30 | 31 | public void modifyThing(@Mutable Thing thing, int value) { 32 | thing.setValue(value); 33 | } 34 | 35 | public Thing returnThing(@Return Thing thing) { 36 | if (thing == null) { 37 | thing = new Thing(); 38 | } 39 | return thing; 40 | } 41 | 42 | public Thing modifyAndReturnThing(@Mutable @Return Thing thing, int value) { 43 | if (thing == null) { 44 | thing = new Thing(); 45 | } 46 | thing.setValue(value); 47 | return thing; 48 | } 49 | 50 | public void modifyIntArray(@Mutable int[] array, int item0, int item1, int item2) { 51 | array[0] = item0; 52 | array[1] = item1; 53 | array[2] = item2; 54 | } 55 | 56 | public int[] returnIntArray(@Return int[] array) { 57 | if (array == null) { 58 | array = new int[3]; 59 | } 60 | return array; 61 | } 62 | 63 | public int[] modifyAndReturnIntArray(@Mutable @Return int[] array, int item0, int item1, int item2) { 64 | if (array == null) { 65 | array = new int[3]; 66 | } 67 | array[0] = item0; 68 | array[1] = item1; 69 | array[2] = item2; 70 | return array; 71 | } 72 | 73 | public void modifyAndOutputIntArray(@Mutable @Output int[] array, int item0, int item1, int item2) { 74 | if (array == null) { 75 | return; 76 | } 77 | array[0] = item0; 78 | array[1] = item1; 79 | array[2] = item2; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/test/java/org/jpy/fixtures/Processor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.jpy.fixtures; 18 | 19 | /** 20 | * Stands for an image data processor. 21 | * 22 | * Created by Norman on 19.12.13. 23 | */ 24 | public interface Processor { 25 | String initialize(); 26 | 27 | String computeTile(int w, int h, float[] data); 28 | 29 | String dispose(); 30 | 31 | void setVal(int n); 32 | 33 | int getVal(); 34 | 35 | boolean check1234(); 36 | } 37 | -------------------------------------------------------------------------------- /src/test/java/org/jpy/fixtures/Thing.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.jpy.fixtures; 18 | 19 | /** 20 | * Stands for any Java object. 21 | * 22 | * @author Norman Fomferra 23 | */ 24 | @SuppressWarnings("UnusedDeclaration") 25 | public class Thing { 26 | private int value; 27 | 28 | public Thing() { 29 | } 30 | 31 | public Thing(int value) { 32 | this.value = value; 33 | } 34 | 35 | public int getValue() { 36 | return value; 37 | } 38 | 39 | public void setValue(int value) { 40 | this.value = value; 41 | } 42 | 43 | @Override 44 | public boolean equals(Object o) { 45 | if (this == o) return true; 46 | if (o == null || getClass() != o.getClass()) return false; 47 | Thing thing = (Thing) o; 48 | return value == thing.value; 49 | } 50 | 51 | @Override 52 | public int hashCode() { 53 | return value; 54 | } 55 | 56 | @Override 57 | public String toString() { 58 | return "Thing[value=" + value + "]"; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/test/java/org/jpy/fixtures/TypeConversionTestFixture.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.jpy.fixtures; 18 | 19 | import static org.jpy.fixtures.MethodOverloadTestFixture.stringifyArgs; 20 | 21 | /** 22 | * Used as a test class for the test cases in jpy_typeconv_test.py 23 | * 24 | * @author Norman Fomferra 25 | */ 26 | @SuppressWarnings("UnusedDeclaration") 27 | public class TypeConversionTestFixture { 28 | 29 | public String stringifyObjectArg(Object arg) { 30 | return stringifyArgs(arg); 31 | } 32 | 33 | public String stringifyIntArrayArg(int[] arg) { 34 | return stringifyArgs((Object) arg); 35 | } 36 | 37 | public String stringifyObjectArrayArg(Object[] arg) { 38 | return stringifyArgs((Object) arg); 39 | } 40 | 41 | public String stringifyStringArrayArg(String[] arg) { 42 | return stringifyArgs((Object) arg); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/org/jpy/fixtures/TypeResolutionTestFixture.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.jpy.fixtures; 18 | 19 | /** 20 | * Used as a test class for the test cases in jpy_typeres_test.py 21 | * 22 | * @author Norman Fomferra 23 | */ 24 | @SuppressWarnings("UnusedDeclaration") 25 | public class TypeResolutionTestFixture { 26 | 27 | public SuperThing createSuperThing(int value) { 28 | return new SuperThing(value); 29 | } 30 | 31 | 32 | public static class SuperThing extends Thing { 33 | public SuperThing(int value) { 34 | super(value); 35 | } 36 | 37 | public void add(int val) { 38 | setValue(getValue() + val); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/test/java/org/jpy/fixtures/TypeTranslationTestFixture.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * This file was modified by Illumon. 17 | * 18 | */ 19 | 20 | package org.jpy.fixtures; 21 | 22 | /** 23 | * Used as a test class for the test cases in jpy_retval_test.py 24 | * Note: Please make sure to not add any method overloads to this class. 25 | * This is done in {@link MethodOverloadTestFixture}. 26 | * 27 | * @author Norman Fomferra 28 | */ 29 | @SuppressWarnings("UnusedDeclaration") 30 | public class TypeTranslationTestFixture { 31 | public Thing makeThing(int value) { 32 | return new Thing(value); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/org/jpy/fixtures/VarArgsTestFixture.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * This file was modified by Illumon. 17 | * 18 | */ 19 | 20 | package org.jpy.fixtures; 21 | 22 | import java.lang.reflect.Array; 23 | 24 | /** 25 | * Used as a test class for the test cases in jpy_overload_test.py 26 | * 27 | * @author Norman Fomferra 28 | */ 29 | @SuppressWarnings("UnusedDeclaration") 30 | public class VarArgsTestFixture { 31 | 32 | public String join(String prefix, int ... a) { 33 | return stringifyArgs(prefix, a); 34 | } 35 | 36 | public String join(String prefix, double ... a) { 37 | return stringifyArgs(prefix, a); 38 | } 39 | public String join(String prefix, float ... a) { 40 | return stringifyArgs(prefix, a); 41 | } 42 | public String join(String prefix, String ... a) { 43 | return stringifyArgs(prefix, a); 44 | } 45 | 46 | public String joinFloat(String prefix, float ... a) { 47 | return stringifyArgs(prefix, a); 48 | } 49 | 50 | public String joinLong(String prefix, long ... a) { 51 | return stringifyArgs(prefix, a); 52 | } 53 | public String joinShort(String prefix, short ... a) { 54 | return stringifyArgs(prefix, a); 55 | } 56 | public String joinByte(String prefix, byte ... a) { 57 | return stringifyArgs(prefix, a); 58 | } 59 | public String joinChar(String prefix, char ... a) { 60 | return stringifyArgs(prefix, a); 61 | } 62 | public String joinBoolean(String prefix, boolean ... a) { 63 | return stringifyArgs(prefix, a); 64 | } 65 | public String joinObjects(String prefix, Object ... a) { 66 | return stringifyArgs(prefix, a); 67 | } 68 | 69 | public int chooseFixedArity(int... a) { 70 | return 2; 71 | } 72 | 73 | public int chooseFixedArity() { 74 | return 1; 75 | } 76 | 77 | public int stringOrObjectVarArgs(String ... a) { 78 | return 1 + a.length; 79 | } 80 | public int stringOrObjectVarArgs(Object ... a) { 81 | return 2 + a.length; 82 | } 83 | 84 | static String stringifyArgs(Object... args) { 85 | StringBuilder argString = new StringBuilder(); 86 | for (int i = 0; i < args.length; i++) { 87 | if (i > 0) { 88 | argString.append(","); 89 | } 90 | Object arg = args[i]; 91 | if (arg != null) { 92 | Class argClass = arg.getClass(); 93 | argString.append(argClass.getSimpleName()); 94 | argString.append('('); 95 | if (argClass.isArray()) { 96 | stringifyArray(arg, argString); 97 | } else { 98 | stringifyObject(arg, argString); 99 | } 100 | argString.append(')'); 101 | } else { 102 | argString.append("null"); 103 | } 104 | } 105 | return argString.toString(); 106 | } 107 | 108 | private static void stringifyObject(Object arg, StringBuilder argString) { 109 | argString.append(String.valueOf(arg)); 110 | } 111 | 112 | private static void stringifyArray(Object arg, StringBuilder argString) { 113 | boolean primitive = arg.getClass().getComponentType().isPrimitive(); 114 | int length = Array.getLength(arg); 115 | for (int i = 0; i < length; i++) { 116 | Object item = Array.get(arg, i); 117 | if (i > 0) { 118 | argString.append(","); 119 | } 120 | if (primitive) { 121 | argString.append(String.valueOf(item)); 122 | } else { 123 | argString.append(stringifyArgs(item)); 124 | } 125 | } 126 | } 127 | 128 | 129 | } 130 | -------------------------------------------------------------------------------- /src/test/java/org/jpy/jsr223/Jsr223Test.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015 Brockmann Consult GmbH 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.jpy.jsr223; 18 | 19 | import org.junit.Assert; 20 | import org.junit.Test; 21 | 22 | import javax.script.ScriptEngine; 23 | import javax.script.ScriptEngineFactory; 24 | import javax.script.ScriptEngineManager; 25 | import java.util.List; 26 | 27 | import static org.junit.Assert.assertEquals; 28 | import static org.junit.Assert.assertNotNull; 29 | 30 | public class Jsr223Test { 31 | 32 | @Test 33 | public void testThatScriptEngineFactoryIsRegistered() throws Exception { 34 | assertNotNull(getScriptEngineFactory()); 35 | } 36 | 37 | @Test 38 | public void testThatScriptEngineFactorySupportsMinimumParameterKeys() throws Exception { 39 | ScriptEngineFactoryImpl scriptEngineFactory = getScriptEngineFactory(); 40 | assertEquals("cpython", scriptEngineFactory.getParameter(ScriptEngine.NAME)); 41 | assertEquals("jpy Python Engine", scriptEngineFactory.getParameter(ScriptEngine.ENGINE)); 42 | assertEquals("0.1-alpha", scriptEngineFactory.getParameter(ScriptEngine.ENGINE_VERSION)); 43 | assertEquals("python", scriptEngineFactory.getParameter(ScriptEngine.LANGUAGE)); 44 | assertEquals("3.x", scriptEngineFactory.getParameter(ScriptEngine.LANGUAGE_VERSION)); 45 | } 46 | 47 | private ScriptEngineFactoryImpl getScriptEngineFactory() { 48 | ScriptEngineManager engineManager = new ScriptEngineManager(); 49 | List engineFactories = engineManager.getEngineFactories(); 50 | ScriptEngineFactoryImpl engineFactoryImpl = null; 51 | for (ScriptEngineFactory engineFactory : engineFactories) { 52 | if (engineFactory instanceof ScriptEngineFactoryImpl) { 53 | engineFactoryImpl = (ScriptEngineFactoryImpl) engineFactory; 54 | } 55 | } 56 | return engineFactoryImpl; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/test/python/fixtures/hasheqstr.py: -------------------------------------------------------------------------------- 1 | class Simple(object): 2 | def __init__(self, v): 3 | self._v = v 4 | 5 | def __str__(self): 6 | return "Simple: " + str(self._v) 7 | 8 | def getValue(self): 9 | return self._v 10 | 11 | class HashSimple(object): 12 | def __init__(self, v): 13 | self._v = v 14 | 15 | def __str__(self): 16 | return "HashSimple: " + str(self._v) 17 | 18 | def getValue(self): 19 | return self._v 20 | 21 | def __hash__(self): 22 | return hash(self._v) 23 | 24 | def __eq__(self, other): 25 | if isinstance(other, self.__class__): 26 | return self._v == other._v 27 | else: 28 | return False # Java can't support NotImplemented 29 | 30 | -------------------------------------------------------------------------------- /src/test/python/fixtures/proc_class.py: -------------------------------------------------------------------------------- 1 | class Processor: 2 | def __init__(self): 3 | pass 4 | 5 | 6 | def initialize(self): 7 | return 'initialize' 8 | 9 | def computeTile(self, x, y, array): 10 | self.spend_some_time() 11 | return 'computeTile-' + str(x) + ',' + str(y) 12 | 13 | def dispose(self): 14 | return 'dispose' 15 | 16 | 17 | def spend_some_time(self): 18 | l = list(range(10000)) 19 | for i in range(10000): 20 | l.reverse() 21 | 22 | def setVal(self, val): 23 | self._val = val 24 | 25 | def getVal(self): 26 | return self._val 27 | 28 | def check1234(self): 29 | return self._val == 1234 30 | -------------------------------------------------------------------------------- /src/test/python/fixtures/proc_module.py: -------------------------------------------------------------------------------- 1 | 2 | def initialize(): 3 | return 'initialize' 4 | 5 | def computeTile(x, y, array): 6 | spend_some_time() 7 | return 'computeTile-' + str(x) + ',' + str(y) 8 | 9 | def dispose(): 10 | return 'dispose' 11 | 12 | 13 | def spend_some_time(): 14 | l = list(range(10000)) 15 | for i in range(10000): 16 | l.reverse() 17 | 18 | _module_val = None 19 | def setVal(val): 20 | global _module_val 21 | _module_val = val 22 | 23 | def getVal(): 24 | global _module_val 25 | return _module_val 26 | 27 | def check1234(): 28 | global _module_val 29 | return _module_val == 1234 30 | -------------------------------------------------------------------------------- /src/test/python/fixtures/raise_errors.py: -------------------------------------------------------------------------------- 1 | def raise_if_zero(arg): 2 | if not arg: 3 | raise IndexError("arg wasn't there") -------------------------------------------------------------------------------- /src/test/python/imp/import_ex1.py: -------------------------------------------------------------------------------- 1 | """ 2 | Testing Python import machinery with the goal to let users import Java class like this: 3 | from jpy.java.io import File 4 | or 5 | from jpy import java.io.File as File 6 | """ 7 | 8 | __author__ = 'Norman' 9 | 10 | import sys 11 | import importlib.abc 12 | 13 | 14 | class JavaClass: 15 | def __init__(self, fullname): 16 | self.fullname = fullname 17 | 18 | def __repr__(self): 19 | return "JavaClass('" + self.fullname + "')" 20 | 21 | def __str__(self): 22 | return self.fullname 23 | 24 | 25 | class JavaPackageImporter(importlib.abc.MetaPathFinder): 26 | 27 | def __init__(self, file): 28 | self.packages = set() 29 | #with open(file, "r") as f: 30 | # for line in f: 31 | # package = line.strip() 32 | # self.register_package(package) 33 | #print(self.packages) 34 | 35 | 36 | def register_package(self, fullname): 37 | package = fullname 38 | while package: 39 | self.packages.add(package) 40 | dot_pos = package.rfind('.') 41 | if dot_pos > 0: 42 | package = package[:dot_pos] 43 | else: 44 | package = None 45 | 46 | 47 | def get_package(self, fullname): 48 | dot_pos = fullname.rfind('.') 49 | if dot_pos > 0: 50 | package = fullname[:dot_pos] 51 | name = fullname[dot_pos + 1:] 52 | else: 53 | package = '' 54 | name = fullname 55 | return (package, name) 56 | 57 | 58 | def load_java_class(self, module, fullname): 59 | print('try loading java class "' + fullname + '"...') 60 | package, name = self.get_package(fullname) 61 | #module.__dict__[name] = JavaClass(fullname) 62 | #return JavaClass(fullname) 63 | return None 64 | 65 | def new_module(self, fullname): 66 | package, name = self.get_package(fullname) 67 | 68 | print('creating module "' + fullname + '"') 69 | module = type(sys)(fullname) 70 | module.__loader__ = self 71 | module.__path__ = None 72 | module.__package__ = package 73 | return module 74 | 75 | 76 | def find_module(self, fullname, path): 77 | print('find_module(fullname="' + str(fullname) + '", path="' + str(path) + '")') 78 | if fullname in self.packages: 79 | return self 80 | 81 | package, name = self.get_package(fullname) 82 | if package in self.packages: 83 | return self 84 | 85 | return None 86 | 87 | 88 | def load_module(self, fullname): 89 | print('load_module(fullname="' + str(fullname) + '")') 90 | is_reload = fullname in sys.modules 91 | if is_reload: 92 | module = sys.modules[fullname] 93 | print('module found!') 94 | # Now, check what to do next...? 95 | else: 96 | if fullname in self.packages: 97 | print('known package: ' + fullname) 98 | module = self.new_module(fullname) 99 | sys.modules[fullname] = module 100 | else: 101 | print('not a known package: ' + fullname) 102 | package, class_name = self.get_package(fullname) 103 | module = sys.modules[package] 104 | if module is None: 105 | return None 106 | module = self.load_java_class(module, fullname) 107 | return module 108 | 109 | 110 | 111 | jpi = JavaPackageImporter('packages-jre7.txt') 112 | #jpi.register_package('org.esa.beam.framework.datamodel') 113 | #jpi.register_package('org.esa.beam.framework.dataio') 114 | #jpi.register_package('org.esa.beam.framework.gpf') 115 | 116 | sys.meta_path += [jpi] 117 | 118 | #import jpy 119 | import bibo 120 | import riser 121 | #from jpy import Riser as Riser 122 | 123 | 124 | import numpy 125 | from numpy import array 126 | 127 | 128 | #import java.io 129 | #import java.lang 130 | #import java.util 131 | #import numpy 132 | #import java.wraaaw 133 | #from java.util import String 134 | #from java.io import File 135 | 136 | #s = String('Hello') 137 | #print(f) 138 | 139 | #f = File('x') 140 | #print(f) 141 | 142 | 143 | #import os.path 144 | # 145 | #print(os.__name__) 146 | #print(os.__package__) 147 | #print(os.__file__) 148 | # 149 | #print(dir(java.io)) 150 | # 151 | # 152 | #print(os.__name__) 153 | #print(os.__package__) 154 | #print(os.__file__) 155 | #print(list(os.__path__)) 156 | #print(os.path.__name__) 157 | #print(os.path.__package__) 158 | #print(os.path.__file__) 159 | #print(list(os.path.__path__)) 160 | # 161 | #print('java.io:', dir(java.io)) 162 | 163 | -------------------------------------------------------------------------------- /src/test/python/imp/import_ex2.py: -------------------------------------------------------------------------------- 1 | """ 2 | Testing Python import machinery with the goal to let users import Java class like this: 3 | from jpy.java.io import File 4 | or 5 | from jpy import java.io.File as File 6 | """ 7 | 8 | __author__ = 'Norman' 9 | 10 | import sys 11 | import importlib.abc 12 | 13 | ModuleType = type(sys) 14 | yyyy = ModuleType('yyyy') 15 | 16 | 17 | class JavaClass: 18 | def __init__(self, fullname): 19 | self.fullname = fullname 20 | 21 | def __repr__(self): 22 | return "JavaClass('" + self.fullname + "')" 23 | 24 | def __str__(self): 25 | return self.fullname 26 | 27 | 28 | class JavaPackageImporter(importlib.abc.MetaPathFinder): 29 | 30 | def get_package(self, fullname): 31 | dot_pos = fullname.rfind('.') 32 | if dot_pos > 0: 33 | package = fullname[:dot_pos] 34 | name = fullname[dot_pos + 1:] 35 | else: 36 | package = '' 37 | name = fullname 38 | return (package, name) 39 | 40 | def load_java_class(self, module, fullname): 41 | print('try loading java class "' + fullname + '"...') 42 | package, name = self.get_package(fullname) 43 | #module.__dict__[name] = JavaClass(fullname) 44 | #return JavaClass(fullname) 45 | return None 46 | 47 | def new_module(self, fullname): 48 | #package, name = self.get_package(fullname) 49 | 50 | print('creating module "' + fullname + '"') 51 | module = type(sys)(fullname) 52 | module.__loader__ = self 53 | module.__path__ = None 54 | #module.__package__ = package 55 | return module 56 | 57 | 58 | def find_module(self, fullname, path): 59 | print('find_module(fullname="' + str(fullname) + '", path="' + str(path) + '")') 60 | 61 | if fullname == 'yyyy' or fullname.startswith('yyyy.'): 62 | return self 63 | 64 | return None 65 | 66 | 67 | def load_module(self, fullname): 68 | print('load_module(fullname="' + str(fullname) + '")') 69 | is_reload = fullname in sys.modules 70 | if is_reload: 71 | module = sys.modules[fullname] 72 | print('module found!') 73 | # Now, check what to do next...? 74 | else: 75 | print('new module: ' + fullname) 76 | module = self.new_module(fullname) 77 | sys.modules[fullname] = module 78 | return module 79 | 80 | 81 | jpi = JavaPackageImporter() 82 | sys.meta_path += [jpi] 83 | 84 | import yyyy.bibo 85 | import yyyy.riser.bibo 86 | import yyyy.bibo.riser 87 | from yyyy.bibo import Riser as Riser 88 | 89 | 90 | import numpy 91 | from numpy import array 92 | -------------------------------------------------------------------------------- /src/test/python/imp/packages-jre6.txt: -------------------------------------------------------------------------------- 1 | java.applet 2 | java.awt 3 | java.awt.color 4 | java.awt.datatransfer 5 | java.awt.dnd 6 | java.awt.event 7 | java.awt.font 8 | java.awt.geom 9 | java.awt.im 10 | java.awt.im.spi 11 | java.awt.image 12 | java.awt.image.renderable 13 | java.awt.print 14 | java.beans 15 | java.beans.beancontext 16 | java.io 17 | java.lang 18 | java.lang.annotation 19 | java.lang.instrument 20 | java.lang.management 21 | java.lang.ref 22 | java.lang.reflect 23 | java.math 24 | java.net 25 | java.nio 26 | java.nio.channels 27 | java.nio.channels.spi 28 | java.nio.charset 29 | java.nio.charset.spi 30 | java.rmi 31 | java.rmi.activation 32 | java.rmi.dgc 33 | java.rmi.registry 34 | java.rmi.server 35 | java.security 36 | java.security.acl 37 | java.security.cert 38 | java.security.interfaces 39 | java.security.spec 40 | java.sql 41 | java.text 42 | java.text.spi 43 | java.util 44 | java.util.concurrent 45 | java.util.concurrent.atomic 46 | java.util.concurrent.locks 47 | java.util.jar 48 | java.util.logging 49 | java.util.prefs 50 | java.util.regex 51 | java.util.spi 52 | java.util.zip 53 | javax.accessibility 54 | javax.activation 55 | javax.activity 56 | javax.annotation 57 | javax.annotation.processing 58 | javax.crypto 59 | javax.crypto.interfaces 60 | javax.crypto.spec 61 | javax.imageio 62 | javax.imageio.event 63 | javax.imageio.metadata 64 | javax.imageio.plugins.bmp 65 | javax.imageio.plugins.jpeg 66 | javax.imageio.spi 67 | javax.imageio.stream 68 | javax.jws 69 | javax.jws.soap 70 | javax.lang.model 71 | javax.lang.model.element 72 | javax.lang.model.type 73 | javax.lang.model.util 74 | javax.management 75 | javax.management.loading 76 | javax.management.modelmbean 77 | javax.management.monitor 78 | javax.management.openmbean 79 | javax.management.relation 80 | javax.management.remote 81 | javax.management.remote.rmi 82 | javax.management.timer 83 | javax.naming 84 | javax.naming.directory 85 | javax.naming.event 86 | javax.naming.ldap 87 | javax.naming.spi 88 | javax.net 89 | javax.net.ssl 90 | javax.print 91 | javax.print.attribute 92 | javax.print.attribute.standard 93 | javax.print.event 94 | javax.rmi 95 | javax.rmi.CORBA 96 | javax.rmi.ssl 97 | javax.script 98 | javax.security.auth 99 | javax.security.auth.callback 100 | javax.security.auth.kerberos 101 | javax.security.auth.login 102 | javax.security.auth.spi 103 | javax.security.auth.x500 104 | javax.security.cert 105 | javax.security.sasl 106 | javax.sound.midi 107 | javax.sound.midi.spi 108 | javax.sound.sampled 109 | javax.sound.sampled.spi 110 | javax.sql 111 | javax.sql.rowset 112 | javax.sql.rowset.serial 113 | javax.sql.rowset.spi 114 | javax.swing 115 | javax.swing.border 116 | javax.swing.colorchooser 117 | javax.swing.event 118 | javax.swing.filechooser 119 | javax.swing.plaf 120 | javax.swing.plaf.basic 121 | javax.swing.plaf.metal 122 | javax.swing.plaf.multi 123 | javax.swing.plaf.synth 124 | javax.swing.table 125 | javax.swing.text 126 | javax.swing.text.html 127 | javax.swing.text.html.parser 128 | javax.swing.text.rtf 129 | javax.swing.tree 130 | javax.swing.undo 131 | javax.tools 132 | javax.transaction 133 | javax.transaction.xa 134 | javax.xml 135 | javax.xml.bind 136 | javax.xml.bind.annotation 137 | javax.xml.bind.annotation.adapters 138 | javax.xml.bind.attachment 139 | javax.xml.bind.helpers 140 | javax.xml.bind.util 141 | javax.xml.crypto 142 | javax.xml.crypto.dom 143 | javax.xml.crypto.dsig 144 | javax.xml.crypto.dsig.dom 145 | javax.xml.crypto.dsig.keyinfo 146 | javax.xml.crypto.dsig.spec 147 | javax.xml.datatype 148 | javax.xml.namespace 149 | javax.xml.parsers 150 | javax.xml.soap 151 | javax.xml.stream 152 | javax.xml.stream.events 153 | javax.xml.stream.util 154 | javax.xml.transform 155 | javax.xml.transform.dom 156 | javax.xml.transform.sax 157 | javax.xml.transform.stax 158 | javax.xml.transform.stream 159 | javax.xml.validation 160 | javax.xml.ws 161 | javax.xml.ws.handler 162 | javax.xml.ws.handler.soap 163 | javax.xml.ws.http 164 | javax.xml.ws.soap 165 | javax.xml.ws.spi 166 | javax.xml.ws.wsaddressing 167 | javax.xml.xpath 168 | org.ietf.jgss 169 | org.omg.CORBA 170 | org.omg.CORBA_2_3 171 | org.omg.CORBA_2_3.portable 172 | org.omg.CORBA.DynAnyPackage 173 | org.omg.CORBA.ORBPackage 174 | org.omg.CORBA.portable 175 | org.omg.CORBA.TypeCodePackage 176 | org.omg.CosNaming 177 | org.omg.CosNaming.NamingContextExtPackage 178 | org.omg.CosNaming.NamingContextPackage 179 | org.omg.Dynamic 180 | org.omg.DynamicAny 181 | org.omg.DynamicAny.DynAnyFactoryPackage 182 | org.omg.DynamicAny.DynAnyPackage 183 | org.omg.IOP 184 | org.omg.IOP.CodecFactoryPackage 185 | org.omg.IOP.CodecPackage 186 | org.omg.Messaging 187 | org.omg.PortableInterceptor 188 | org.omg.PortableInterceptor.ORBInitInfoPackage 189 | org.omg.PortableServer 190 | org.omg.PortableServer.CurrentPackage 191 | org.omg.PortableServer.POAManagerPackage 192 | org.omg.PortableServer.POAPackage 193 | org.omg.PortableServer.portable 194 | org.omg.PortableServer.ServantLocatorPackage 195 | org.omg.SendingContext 196 | org.omg.stub.java.rmi 197 | org.w3c.dom 198 | org.w3c.dom.bootstrap 199 | org.w3c.dom.events 200 | org.w3c.dom.ls 201 | org.xml.sax 202 | org.xml.sax.ext 203 | org.xml.sax.helpers 204 | 205 | -------------------------------------------------------------------------------- /src/test/python/imp/packages-jre7.txt: -------------------------------------------------------------------------------- 1 | java.applet 2 | java.awt 3 | java.awt.color 4 | java.awt.datatransfer 5 | java.awt.dnd 6 | java.awt.event 7 | java.awt.font 8 | java.awt.geom 9 | java.awt.im 10 | java.awt.im.spi 11 | java.awt.image 12 | java.awt.image.renderable 13 | java.awt.print 14 | java.beans 15 | java.beans.beancontext 16 | java.io 17 | java.lang 18 | java.lang.annotation 19 | java.lang.instrument 20 | java.lang.invoke 21 | java.lang.management 22 | java.lang.ref 23 | java.lang.reflect 24 | java.math 25 | java.net 26 | java.nio 27 | java.nio.channels 28 | java.nio.channels.spi 29 | java.nio.charset 30 | java.nio.charset.spi 31 | java.nio.file 32 | java.nio.file.attribute 33 | java.nio.file.spi 34 | java.rmi 35 | java.rmi.activation 36 | java.rmi.dgc 37 | java.rmi.registry 38 | java.rmi.server 39 | java.security 40 | java.security.acl 41 | java.security.cert 42 | java.security.interfaces 43 | java.security.spec 44 | java.sql 45 | java.text 46 | java.text.spi 47 | java.util 48 | java.util.concurrent 49 | java.util.concurrent.atomic 50 | java.util.concurrent.locks 51 | java.util.jar 52 | java.util.logging 53 | java.util.prefs 54 | java.util.regex 55 | java.util.spi 56 | java.util.zip 57 | javax.accessibility 58 | javax.activation 59 | javax.activity 60 | javax.annotation 61 | javax.annotation.processing 62 | javax.crypto 63 | javax.crypto.interfaces 64 | javax.crypto.spec 65 | javax.imageio 66 | javax.imageio.event 67 | javax.imageio.metadata 68 | javax.imageio.plugins.bmp 69 | javax.imageio.plugins.jpeg 70 | javax.imageio.spi 71 | javax.imageio.stream 72 | javax.jws 73 | javax.jws.soap 74 | javax.lang.model 75 | javax.lang.model.element 76 | javax.lang.model.type 77 | javax.lang.model.util 78 | javax.management 79 | javax.management.loading 80 | javax.management.modelmbean 81 | javax.management.monitor 82 | javax.management.openmbean 83 | javax.management.relation 84 | javax.management.remote 85 | javax.management.remote.rmi 86 | javax.management.timer 87 | javax.naming 88 | javax.naming.directory 89 | javax.naming.event 90 | javax.naming.ldap 91 | javax.naming.spi 92 | javax.net 93 | javax.net.ssl 94 | javax.print 95 | javax.print.attribute 96 | javax.print.attribute.standard 97 | javax.print.event 98 | javax.rmi 99 | javax.rmi.CORBA 100 | javax.rmi.ssl 101 | javax.script 102 | javax.security.auth 103 | javax.security.auth.callback 104 | javax.security.auth.kerberos 105 | javax.security.auth.login 106 | javax.security.auth.spi 107 | javax.security.auth.x500 108 | javax.security.cert 109 | javax.security.sasl 110 | javax.sound.midi 111 | javax.sound.midi.spi 112 | javax.sound.sampled 113 | javax.sound.sampled.spi 114 | javax.sql 115 | javax.sql.rowset 116 | javax.sql.rowset.serial 117 | javax.sql.rowset.spi 118 | javax.swing 119 | javax.swing.border 120 | javax.swing.colorchooser 121 | javax.swing.event 122 | javax.swing.filechooser 123 | javax.swing.plaf 124 | javax.swing.plaf.basic 125 | javax.swing.plaf.metal 126 | javax.swing.plaf.multi 127 | javax.swing.plaf.nimbus 128 | javax.swing.plaf.synth 129 | javax.swing.table 130 | javax.swing.text 131 | javax.swing.text.html 132 | javax.swing.text.html.parser 133 | javax.swing.text.rtf 134 | javax.swing.tree 135 | javax.swing.undo 136 | javax.tools 137 | javax.transaction 138 | javax.transaction.xa 139 | javax.xml 140 | javax.xml.bind 141 | javax.xml.bind.annotation 142 | javax.xml.bind.annotation.adapters 143 | javax.xml.bind.attachment 144 | javax.xml.bind.helpers 145 | javax.xml.bind.util 146 | javax.xml.crypto 147 | javax.xml.crypto.dom 148 | javax.xml.crypto.dsig 149 | javax.xml.crypto.dsig.dom 150 | javax.xml.crypto.dsig.keyinfo 151 | javax.xml.crypto.dsig.spec 152 | javax.xml.datatype 153 | javax.xml.namespace 154 | javax.xml.parsers 155 | javax.xml.soap 156 | javax.xml.stream 157 | javax.xml.stream.events 158 | javax.xml.stream.util 159 | javax.xml.transform 160 | javax.xml.transform.dom 161 | javax.xml.transform.sax 162 | javax.xml.transform.stax 163 | javax.xml.transform.stream 164 | javax.xml.validation 165 | javax.xml.ws 166 | javax.xml.ws.handler 167 | javax.xml.ws.handler.soap 168 | javax.xml.ws.http 169 | javax.xml.ws.soap 170 | javax.xml.ws.spi 171 | javax.xml.ws.spi.http 172 | javax.xml.ws.wsaddressing 173 | javax.xml.xpath 174 | org.ietf.jgss 175 | org.omg.CORBA 176 | org.omg.CORBA_2_3 177 | org.omg.CORBA_2_3.portable 178 | org.omg.CORBA.DynAnyPackage 179 | org.omg.CORBA.ORBPackage 180 | org.omg.CORBA.portable 181 | org.omg.CORBA.TypeCodePackage 182 | org.omg.CosNaming 183 | org.omg.CosNaming.NamingContextExtPackage 184 | org.omg.CosNaming.NamingContextPackage 185 | org.omg.Dynamic 186 | org.omg.DynamicAny 187 | org.omg.DynamicAny.DynAnyFactoryPackage 188 | org.omg.DynamicAny.DynAnyPackage 189 | org.omg.IOP 190 | org.omg.IOP.CodecFactoryPackage 191 | org.omg.IOP.CodecPackage 192 | org.omg.Messaging 193 | org.omg.PortableInterceptor 194 | org.omg.PortableInterceptor.ORBInitInfoPackage 195 | org.omg.PortableServer 196 | org.omg.PortableServer.CurrentPackage 197 | org.omg.PortableServer.POAManagerPackage 198 | org.omg.PortableServer.POAPackage 199 | org.omg.PortableServer.portable 200 | org.omg.PortableServer.ServantLocatorPackage 201 | org.omg.SendingContext 202 | org.omg.stub.java.rmi 203 | org.w3c.dom 204 | org.w3c.dom.bootstrap 205 | org.w3c.dom.events 206 | org.w3c.dom.ls 207 | org.xml.sax 208 | org.xml.sax.ext 209 | org.xml.sax.helpers 210 | -------------------------------------------------------------------------------- /src/test/python/jpy_diag_test.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | import jpyutil 4 | 5 | 6 | jpyutil.init_jvm(jvm_maxmem='512M') 7 | import jpy 8 | 9 | 10 | class TestJavaArrays(unittest.TestCase): 11 | def test_diag_flags_constants(self): 12 | self.assertIsNotNone(jpy.diag) 13 | self.assertIsNotNone(jpy.diag.flags) 14 | self.assertEqual(jpy.diag.F_OFF, 0x00) 15 | self.assertEqual(jpy.diag.F_TYPE, 0x01) 16 | self.assertEqual(jpy.diag.F_METH, 0x02) 17 | self.assertEqual(jpy.diag.F_EXEC, 0x04) 18 | self.assertEqual(jpy.diag.F_MEM, 0x08) 19 | self.assertEqual(jpy.diag.F_JVM, 0x10) 20 | self.assertEqual(jpy.diag.F_ERR, 0x20) 21 | self.assertEqual(jpy.diag.F_ALL, 0xff) 22 | 23 | 24 | def test_diag_flags_value(self): 25 | self.assertIsNotNone(jpy.diag) 26 | self.assertEqual(jpy.diag.flags, 0) 27 | jpy.diag.flags = 1 28 | self.assertEqual(jpy.diag.flags, 1) 29 | jpy.diag.flags = 0 30 | self.assertEqual(jpy.diag.flags, 0) 31 | jpy.diag.flags = jpy.diag.F_EXEC + jpy.diag.F_MEM 32 | self.assertEqual(jpy.diag.flags, 12) 33 | jpy.diag.flags = 0 34 | self.assertEqual(jpy.diag.flags, 0) 35 | jpy.diag.flags += jpy.diag.F_EXEC 36 | jpy.diag.flags += jpy.diag.F_MEM 37 | self.assertEqual(jpy.diag.flags, 12) 38 | 39 | 40 | if __name__ == '__main__': 41 | print('\nRunning ' + __file__) 42 | unittest.main() 43 | -------------------------------------------------------------------------------- /src/test/python/jpy_field_test.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | import jpyutil 4 | 5 | 6 | jpyutil.init_jvm(jvm_maxmem='512M', jvm_classpath=['target/test-classes']) 7 | import jpy 8 | 9 | 10 | class TestFields(unittest.TestCase): 11 | def setUp(self): 12 | self.Fixture = jpy.get_type('org.jpy.fixtures.FieldTestFixture') 13 | self.assertIsNotNone(self.Fixture) 14 | 15 | self.Thing = jpy.get_type('org.jpy.fixtures.Thing') 16 | self.assertIsNotNone(self.Thing) 17 | 18 | self.String = jpy.get_type('java.lang.String') 19 | self.assertIsNotNone(self.String) 20 | 21 | 22 | def test_static_fields(self): 23 | self.assertEqual(self.Fixture.z_STATIC_FIELD, True) 24 | self.assertEqual(self.Fixture.c_STATIC_FIELD, 65) 25 | self.assertEqual(self.Fixture.b_STATIC_FIELD, 123) 26 | self.assertEqual(self.Fixture.s_STATIC_FIELD, 12345) 27 | self.assertEqual(self.Fixture.i_STATIC_FIELD, 123456789) 28 | self.assertEqual(self.Fixture.j_STATIC_FIELD, 1234567890123456789) 29 | self.assertAlmostEqual(self.Fixture.f_STATIC_FIELD, 0.12345, places=5) 30 | self.assertAlmostEqual(self.Fixture.d_STATIC_FIELD, 0.123456789) 31 | 32 | self.assertEqual(self.Fixture.S_OBJ_STATIC_FIELD, 'ABC') 33 | self.assertEqual(self.Fixture.l_OBJ_STATIC_FIELD, self.Thing(123)) 34 | 35 | 36 | def test_primitive_instance_fields(self): 37 | fixture = self.Fixture() 38 | self.assertEqual(fixture.zInstField, False) 39 | self.assertEqual(fixture.cInstField, 0) 40 | self.assertEqual(fixture.bInstField, 0) 41 | self.assertEqual(fixture.sInstField, 0) 42 | self.assertEqual(fixture.iInstField, 0) 43 | self.assertEqual(fixture.jInstField, 0) 44 | self.assertEqual(fixture.fInstField, 0) 45 | self.assertEqual(fixture.dInstField, 0) 46 | 47 | fixture.zInstField = True 48 | fixture.cInstField = 65 49 | fixture.bInstField = 123 50 | fixture.sInstField = 12345 51 | fixture.iInstField = 123456789 52 | fixture.jInstField = 1234567890123456789 53 | fixture.fInstField = 0.12345 54 | fixture.dInstField = 0.123456789 55 | 56 | self.assertEqual(fixture.zInstField, True) 57 | self.assertEqual(fixture.cInstField, 65) 58 | self.assertEqual(fixture.bInstField, 123) 59 | self.assertEqual(fixture.sInstField, 12345) 60 | self.assertEqual(fixture.iInstField, 123456789) 61 | self.assertEqual(fixture.jInstField, 1234567890123456789) 62 | self.assertAlmostEqual(fixture.fInstField, 0.12345, places=5) 63 | self.assertAlmostEqual(fixture.dInstField, 0.123456789) 64 | 65 | 66 | def test_object_instance_fields(self): 67 | fixture = self.Fixture() 68 | self.assertEqual(fixture.zObjInstField, None) 69 | self.assertEqual(fixture.cObjInstField, None) 70 | self.assertEqual(fixture.bObjInstField, None) 71 | self.assertEqual(fixture.sObjInstField, None) 72 | self.assertEqual(fixture.iObjInstField, None) 73 | self.assertEqual(fixture.jObjInstField, None) 74 | self.assertEqual(fixture.fObjInstField, None) 75 | self.assertEqual(fixture.dObjInstField, None) 76 | self.assertEqual(fixture.SObjInstField, None) 77 | self.assertEqual(fixture.lObjInstField, None) 78 | 79 | fixture.zObjInstField = True 80 | fixture.cObjInstField = 65 81 | fixture.bObjInstField = 123 82 | fixture.sObjInstField = 12345 83 | fixture.iObjInstField = 123456789 84 | fixture.jObjInstField = 1234567890123456789 85 | fixture.fObjInstField = 0.12345 86 | fixture.dObjInstField = 0.123456789 87 | fixture.SObjInstField = 'ABC' 88 | fixture.lObjInstField = self.Thing(123) 89 | 90 | self.assertEqual(fixture.zObjInstField, True) 91 | self.assertEqual(fixture.cObjInstField, 65) 92 | self.assertEqual(fixture.bObjInstField, 123) 93 | self.assertEqual(fixture.sObjInstField, 12345) 94 | self.assertEqual(fixture.iObjInstField, 123456789) 95 | self.assertEqual(fixture.jObjInstField, 1234567890123456789) 96 | self.assertAlmostEqual(fixture.fObjInstField, 0.12345, places=5) 97 | self.assertAlmostEqual(fixture.dObjInstField, 0.123456789) 98 | self.assertEqual(fixture.SObjInstField, 'ABC') 99 | self.assertEqual(fixture.lObjInstField, self.Thing(123)) 100 | 101 | 102 | if __name__ == '__main__': 103 | print('\nRunning ' + __file__) 104 | unittest.main() 105 | -------------------------------------------------------------------------------- /src/test/python/jpy_gettype_test.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import sys 3 | 4 | import jpyutil 5 | 6 | 7 | jpyutil.init_jvm(jvm_maxmem='512M', jvm_classpath=['target/test-classes']) 8 | import jpy 9 | 10 | 11 | if sys.version_info >= (3, 0, 0): 12 | TYPE_STR_PREFIX = '") 21 | 22 | IntArray2D = jpy.get_type('[[I') 23 | self.assertEqual(str(IntArray2D), TYPE_STR_PREFIX + "'[[I'>") 24 | 25 | IntArray3D = jpy.get_type('[[[I') 26 | self.assertEqual(str(IntArray3D), TYPE_STR_PREFIX + "'[[[I'>") 27 | 28 | with self.assertRaises(RuntimeError) as e: 29 | IntArray1D() 30 | self.assertEqual(str(e.exception), "no constructor found (missing JType attribute '__jinit__')") 31 | 32 | 33 | def test_get_class_of_object_array(self): 34 | StringArray1D = jpy.get_type('[Ljava.lang.String;') 35 | self.assertEqual(str(StringArray1D), TYPE_STR_PREFIX + "'[Ljava.lang.String;'>") 36 | 37 | StringArray2D = jpy.get_type('[[Ljava.lang.String;') 38 | self.assertEqual(str(StringArray2D), TYPE_STR_PREFIX + "'[[Ljava.lang.String;'>") 39 | 40 | StringArray3D = jpy.get_type('[[[Ljava.lang.String;') 41 | self.assertEqual(str(StringArray3D), TYPE_STR_PREFIX + "'[[[Ljava.lang.String;'>") 42 | 43 | with self.assertRaises(RuntimeError) as e: 44 | StringArray1D() 45 | self.assertEqual(str(e.exception), "no constructor found (missing JType attribute '__jinit__')") 46 | 47 | def test_get_class_fromm_inner_class(self): 48 | Point2D = jpy.get_type('java.awt.geom.Point2D') 49 | self.assertEqual(str(Point2D), TYPE_STR_PREFIX + "'java.awt.geom.Point2D'>") 50 | DoublePoint = jpy.get_type('java.awt.geom.Point2D$Double') 51 | self.assertEqual(str(DoublePoint), TYPE_STR_PREFIX + "'java.awt.geom.Point2D$Double'>") 52 | 53 | 54 | def test_get_class_of_unknown_type(self): 55 | with self.assertRaises(ValueError) as e: 56 | String = jpy.get_type('java.lang.Spring') 57 | self.assertEqual(str(e.exception), "Java class 'java.lang.Spring' not found") 58 | 59 | with self.assertRaises(ValueError) as e: 60 | IntArray = jpy.get_type('int[]') 61 | self.assertEqual(str(e.exception), "Java class 'int[]' not found") 62 | 63 | def test_issue_74(self): 64 | """ 65 | Try to create enough references to trigger collection by Python. 66 | """ 67 | java_types = ['boolean', 'char', 'byte', 'short', 'int', 'long', 68 | 'float', 'double', 'void', 'java.lang.String'] 69 | 70 | for java_type in java_types: 71 | for i in range(200): 72 | jpy.get_type(java_type) 73 | 74 | 75 | 76 | if __name__ == '__main__': 77 | print('\nRunning ' + __file__) 78 | unittest.main() 79 | -------------------------------------------------------------------------------- /src/test/python/jpy_mt_test.py: -------------------------------------------------------------------------------- 1 | import threading 2 | import unittest 3 | import jpyutil 4 | 5 | jpyutil.init_jvm(jvm_maxmem='512M') 6 | import jpy 7 | 8 | 9 | class MyThread(threading.Thread): 10 | 11 | def __init__(self, value): 12 | threading.Thread.__init__(self) 13 | Integer = jpy.get_type('java.lang.Integer') 14 | self.intObj = Integer(value) 15 | 16 | def run(self): 17 | # perform some operation on the local object using a new thread 18 | self.intValue = self.intObj.intValue() 19 | 20 | 21 | class TestMultipleThreads(unittest.TestCase): 22 | 23 | 24 | def test_multi_thread_access(self): 25 | 26 | t1 = MyThread(123) 27 | t2 = MyThread(234) 28 | t3 = MyThread(345) 29 | t4 = MyThread(456) 30 | 31 | t1.start() 32 | t2.start() 33 | t3.start() 34 | t4.start() 35 | 36 | t1.join() 37 | t2.join() 38 | t3.join() 39 | t4.join() 40 | 41 | self.assertEqual(123, t1.intValue) 42 | self.assertEqual(234, t2.intValue) 43 | self.assertEqual(345, t3.intValue) 44 | self.assertEqual(456, t4.intValue) 45 | 46 | 47 | if __name__ == '__main__': 48 | print('\nRunning ' + __file__) 49 | unittest.main() 50 | -------------------------------------------------------------------------------- /src/test/python/jpy_perf_test.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import time 3 | import random 4 | import jpyutil 5 | jpyutil.init_jvm(jvm_maxmem='512M') 6 | import jpy 7 | 8 | 9 | class TestPerformance(unittest.TestCase): 10 | 11 | def test_general_rt_perf(self): 12 | 13 | Integer = jpy.get_type('java.lang.Integer') 14 | String = jpy.get_type('java.lang.String') 15 | File = jpy.get_type('java.io.File') 16 | HashMap = jpy.get_type('java.util.HashMap') 17 | 18 | # 1 million 19 | N = 1000000 20 | 21 | indexes = list(range(N)) 22 | random.shuffle(indexes) 23 | 24 | t0 = time.time() 25 | pairs = [(Integer(index), File('path')) for index in indexes] 26 | t1 = time.time() 27 | print('Integer + File object instantiation took', t1-t0, 's for', N, 'calls, this is', 1000*(t1-t0)/N, 'ms per call') 28 | 29 | map = HashMap() 30 | 31 | t0 = time.time() 32 | for pair in pairs: 33 | i, f = pair 34 | map.put(i, f) 35 | t1 = time.time() 36 | print('HashMap.put() took', t1-t0, 's for', N, 'calls, this is', 1000*(t1-t0)/N, 'ms per call') 37 | 38 | t0 = time.time() 39 | for pair in pairs: 40 | i, f = pair 41 | f = map.get(i) 42 | t1 = time.time() 43 | print('HashMap.get() took', t1-t0, 's for', N, 'calls, this is', 1000*(t1-t0)/N, 'ms per call') 44 | 45 | 46 | 47 | if __name__ == '__main__': 48 | print('\nRunning ' + __file__) 49 | unittest.main() 50 | -------------------------------------------------------------------------------- /src/test/python/jpy_retval_test.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | import jpyutil 4 | 5 | 6 | jpyutil.init_jvm(jvm_maxmem='512M', jvm_classpath=['target/test-classes']) 7 | import jpy 8 | 9 | 10 | class TestMethodReturnValues(unittest.TestCase): 11 | def setUp(self): 12 | self.Fixture = jpy.get_type('org.jpy.fixtures.MethodReturnValueTestFixture') 13 | self.assertIsNotNone(self.Fixture) 14 | self.Thing = jpy.get_type('org.jpy.fixtures.Thing') 15 | self.assertIsNotNone(self.Thing) 16 | 17 | def test_void(self): 18 | fixture = self.Fixture() 19 | self.assertEqual(fixture.getVoid(), None) 20 | 21 | def test_primitive_values(self): 22 | fixture = self.Fixture() 23 | self.assertEqual(fixture.getValue_boolean(True), True) 24 | self.assertEqual(fixture.getValue_byte(11), 11) 25 | self.assertEqual(fixture.getValue_short(12), 12) 26 | self.assertEqual(fixture.getValue_int(13), 13) 27 | self.assertEqual(fixture.getValue_long(14), 14) 28 | self.assertAlmostEqual(fixture.getValue_float(15.1), 15.1, places=5) 29 | self.assertEqual(fixture.getValue_double(16.2), 16.2) 30 | 31 | def test_objects(self): 32 | fixture = self.Fixture() 33 | obj = self.Thing() 34 | self.assertEqual(fixture.getString('Hi!'), 'Hi!') 35 | self.assertEqual(fixture.getObject(obj), obj) 36 | 37 | def test_array1d_boolean(self): 38 | fixture = self.Fixture() 39 | array = fixture.getArray1D_boolean(True, False, True) 40 | self.assertEqual(len(array), 3) 41 | self.assertEqual(array[0], True) 42 | self.assertEqual(array[1], False) 43 | self.assertEqual(array[2], True) 44 | 45 | def test_array1d_byte(self): 46 | fixture = self.Fixture() 47 | array = fixture.getArray1D_byte(-10, 20, 30) 48 | self.assertEqual(len(array), 3) 49 | self.assertEqual(array[0], -10) 50 | self.assertEqual(array[1], 20) 51 | self.assertEqual(array[2], 30) 52 | 53 | def test_array1d_short(self): 54 | fixture = self.Fixture() 55 | array = fixture.getArray1D_short(-10001, 20001, 30001) 56 | self.assertEqual(len(array), 3) 57 | self.assertEqual(array[0], -10001) 58 | self.assertEqual(array[1], 20001) 59 | self.assertEqual(array[2], 30001) 60 | 61 | def test_array1d_int(self): 62 | fixture = self.Fixture() 63 | array = fixture.getArray1D_int(-100001, 200001, 300001) 64 | self.assertEqual(len(array), 3) 65 | self.assertEqual(array[0], -100001) 66 | self.assertEqual(array[1], 200001) 67 | self.assertEqual(array[2], 300001) 68 | 69 | def test_array1d_long(self): 70 | fixture = self.Fixture() 71 | array = fixture.getArray1D_long(-10000000001, 20000000001, 30000000001) 72 | self.assertEqual(len(array), 3) 73 | self.assertEqual(array[0], -10000000001) 74 | self.assertEqual(array[1], 20000000001) 75 | self.assertEqual(array[2], 30000000001) 76 | 77 | def test_array1d_float(self): 78 | fixture = self.Fixture() 79 | array = fixture.getArray1D_float(-1.01, 2.01, 3.01) 80 | self.assertEqual(len(array), 3) 81 | self.assertAlmostEqual(array[0], -1.01, places=5) 82 | self.assertAlmostEqual(array[1], 2.01, places=5) 83 | self.assertAlmostEqual(array[2], 3.01, places=5) 84 | 85 | def test_array1d_double(self): 86 | fixture = self.Fixture() 87 | array = fixture.getArray1D_double(-1.01, 2.01, 3.01) 88 | self.assertEqual(len(array), 3) 89 | self.assertEqual(array[0], -1.01) 90 | self.assertEqual(array[1], 2.01) 91 | self.assertEqual(array[2], 3.01) 92 | 93 | def test_array1d_String(self): 94 | fixture = self.Fixture() 95 | array = fixture.getArray1D_String('A', 'B', 'C') 96 | self.assertEqual(len(array), 3) 97 | self.assertEqual(array[0], 'A') 98 | self.assertEqual(array[1], 'B') 99 | self.assertEqual(array[2], 'C') 100 | 101 | def test_array1d_Object(self): 102 | fixture = self.Fixture() 103 | array = fixture.getArray1D_Object(self.Thing(7), self.Thing(8), self.Thing(9)) 104 | self.assertEqual(len(array), 3) 105 | self.assertEqual(array[0], self.Thing(7)) 106 | self.assertEqual(array[1], self.Thing(8)) 107 | self.assertEqual(array[2], self.Thing(9)) 108 | 109 | 110 | if __name__ == '__main__': 111 | print('\nRunning ' + __file__) 112 | unittest.main() 113 | -------------------------------------------------------------------------------- /src/test/python/jpy_translation_test.py: -------------------------------------------------------------------------------- 1 | # This file was modified by Illumon. 2 | import unittest 3 | 4 | import jpyutil 5 | 6 | jpyutil.init_jvm(jvm_maxmem='512M', jvm_classpath=['target/test-classes']) 7 | import jpy 8 | 9 | 10 | class DummyWrapper: 11 | def __init__(self, theThing): 12 | self.theThing = theThing 13 | 14 | def getValue(self): 15 | return 2 * self.theThing.getValue() 16 | 17 | 18 | def make_wrapper(type, thing): 19 | return DummyWrapper(thing) 20 | 21 | 22 | class TestTypeTranslation(unittest.TestCase): 23 | def setUp(self): 24 | self.Fixture = jpy.get_type('org.jpy.fixtures.TypeTranslationTestFixture') 25 | self.assertIsNotNone(self.Fixture) 26 | 27 | def test_Translation(self): 28 | fixture = self.Fixture() 29 | thing = fixture.makeThing(7) 30 | self.assertEqual(thing.getValue(), 7) 31 | self.assertEquals(repr(type(thing)), "") 32 | 33 | jpy.type_translations['org.jpy.fixtures.Thing'] = make_wrapper 34 | thing = fixture.makeThing(8) 35 | self.assertEqual(thing.getValue(), 16) 36 | self.assertEqual(type(thing), type(DummyWrapper(None))) 37 | 38 | jpy.type_translations['org.jpy.fixtures.Thing'] = None 39 | self.assertEqual(fixture.makeThing(9).getValue(), 9) 40 | 41 | 42 | if __name__ == '__main__': 43 | print('\nRunning ' + __file__) 44 | unittest.main() 45 | -------------------------------------------------------------------------------- /src/test/python/jpy_typeconv_test.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import array 3 | 4 | import jpyutil 5 | 6 | 7 | jpyutil.init_jvm(jvm_maxmem='512M', jvm_classpath=['target/test-classes']) 8 | import jpy 9 | 10 | 11 | class TestTypeConversions(unittest.TestCase): 12 | def setUp(self): 13 | self.Fixture = jpy.get_type('org.jpy.fixtures.TypeConversionTestFixture') 14 | self.assertTrue('org.jpy.fixtures.TypeConversionTestFixture' in jpy.types) 15 | 16 | 17 | def test_ToObjectConversion(self): 18 | fixture = self.Fixture() 19 | self.assertEqual(fixture.stringifyObjectArg(12), 'Integer(12)') 20 | self.assertEqual(fixture.stringifyObjectArg(0.34), 'Double(0.34)') 21 | self.assertEqual(fixture.stringifyObjectArg('abc'), 'String(abc)') 22 | 23 | with self.assertRaises(ValueError) as e: 24 | fixture.stringifyObjectArg(1 + 2j) 25 | self.assertEqual(str(e.exception), 'cannot convert a Python \'complex\' to a Java \'java.lang.Object\'') 26 | 27 | 28 | def test_ToPrimitiveArrayConversion(self): 29 | fixture = self.Fixture() 30 | 31 | # Python int array to Java int array 32 | a = array.array('i', [1, 2, 3]) 33 | self.assertEqual(fixture.stringifyIntArrayArg(a), 'int[](1,2,3)') 34 | 35 | # integer list 36 | a = [4, 5, 6] 37 | self.assertEqual(fixture.stringifyIntArrayArg(a), 'int[](4,5,6)') 38 | 39 | # integer tuple 40 | a = (7, 8, 9) 41 | self.assertEqual(fixture.stringifyIntArrayArg(a), 'int[](7,8,9)') 42 | 43 | with self.assertRaises(RuntimeError) as e: 44 | fixture.stringifyIntArrayArg(1 + 2j) 45 | self.assertEqual(str(e.exception), 'no matching Java method overloads found') 46 | 47 | 48 | def test_ToObjectArrayConversion(self): 49 | fixture = self.Fixture() 50 | 51 | self.assertEqual(fixture.stringifyObjectArrayArg(('A', 12, 3.4)), 'Object[](String(A),Integer(12),Double(3.4))') 52 | self.assertEqual(fixture.stringifyObjectArrayArg(['A', 12, 3.4]), 'Object[](String(A),Integer(12),Double(3.4))') 53 | 54 | self.assertEqual(fixture.stringifyStringArrayArg(('A', 'B', 'C')), 'String[](String(A),String(B),String(C))') 55 | self.assertEqual(fixture.stringifyStringArrayArg(['A', 'B', 'C']), 'String[](String(A),String(B),String(C))') 56 | 57 | 58 | if __name__ == '__main__': 59 | print('\nRunning ' + __file__) 60 | unittest.main() 61 | -------------------------------------------------------------------------------- /src/test/python/jpy_typeres_test.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | import jpyutil 4 | 5 | 6 | jpyutil.init_jvm(jvm_maxmem='512M', jvm_classpath=['target/test-classes']) 7 | import jpy 8 | 9 | 10 | class TestTypeResolution(unittest.TestCase): 11 | def setUp(self): 12 | self.Fixture = jpy.get_type('org.jpy.fixtures.TypeResolutionTestFixture') 13 | self.assertIsNotNone(self.Fixture) 14 | 15 | 16 | def test_ThatTypeIsResolvedLate(self): 17 | self.assertTrue('org.jpy.fixtures.TypeResolutionTestFixture' in jpy.types) 18 | self.assertTrue('org.jpy.fixtures.TypeResolutionTestFixture$SuperThing' in jpy.types) 19 | self.assertTrue('org.jpy.fixtures.Thing' in jpy.types) 20 | 21 | fixture = self.Fixture() 22 | 23 | # Create a thing instance, the type 'org.jpy.fixtures.Thing' is not resolved yet 24 | thing = fixture.createSuperThing(2001) 25 | 26 | # Assert that 'org.jpy.fixtures.Thing' is not resolved yet 27 | SuperThing = jpy.types['org.jpy.fixtures.TypeResolutionTestFixture$SuperThing'] 28 | self.assertFalse('add' in SuperThing.__dict__) 29 | 30 | # Assert that 'org.jpy.fixtures.Thing' is not resolved yet 31 | Thing = jpy.types['org.jpy.fixtures.Thing'] 32 | self.assertFalse('getValue' in Thing.__dict__) 33 | 34 | # Calling 'add()' on SuperThing will resolve 'org.jpy.fixtures.Thing' 35 | thing.add(10) 36 | self.assertTrue('add' in SuperThing.__dict__) 37 | self.assertTrue('getValue' in Thing.__dict__) 38 | 39 | value = thing.getValue() 40 | self.assertEqual(value, 2011) 41 | 42 | # see https://github.com/bcdev/jpy/issues/63 43 | def test_ThatJavaTypesHaveAValidClassAttribute(self): 44 | Long = jpy.get_type('java.lang.Long') 45 | self.assertIsNotNone(Long.jclass) 46 | Class = jpy.get_type('java.lang.Class') 47 | self.assertIsNotNone(Class.jclass) 48 | Object = jpy.get_type('java.lang.Object') 49 | self.assertIsNotNone(Object.jclass) 50 | 51 | # see https://github.com/bcdev/jpy/issues/64 52 | def test_ThatInterfaceTypesIncludeMethodsOfExtendedTypes(self): 53 | ObjectInput = jpy.get_type('java.io.ObjectInput', resolve=True) 54 | # assert that a method declared of java.io.ObjectInput is in __dict__ 55 | self.assertTrue('readObject' in ObjectInput.__dict__) 56 | # assert that a method declared of java.io.DataInput is in __dict__ 57 | self.assertTrue('readLine' in ObjectInput.__dict__) 58 | 59 | 60 | 61 | if __name__ == '__main__': 62 | print('\nRunning ' + __file__) 63 | unittest.main() 64 | -------------------------------------------------------------------------------- /src/test/resources/META-INF/services/javax.script.ScriptEngineFactory: -------------------------------------------------------------------------------- 1 | org.jpy.jsr223.ScriptEngineFactoryImpl -------------------------------------------------------------------------------- /src/test/resources/pymodules/mod_1.py: -------------------------------------------------------------------------------- 1 | answer = 42 -------------------------------------------------------------------------------- /winbuild.cmd: -------------------------------------------------------------------------------- 1 | :: Windows SDK 7.1 settings 2 | SET SDK_SETENV=C:\Program Files\Microsoft SDKs\Windows\v7.1\bin\setenv 3 | SET VS90COMNTOOLS=%VS100COMNTOOLS% 4 | SET DISTUTILS_USE_SDK=1 5 | 6 | :: VS 14 settings (with Windows 10) 7 | ::SET SDK_SETENV=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC 8 | ::SET VS100COMNTOOLS=C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools\ 9 | 10 | 11 | SET JDK32_HOME=C:\Program Files (x86)\Java\jdk1.8.0_112 12 | SET JDK64_HOME=C:\Program Files\Java\jdk1.8.0_112 13 | 14 | SET PY27_64=D:\jpy\Python27-amd64 15 | SET PY33_64=D:\jpy\Python33-amd64 16 | SET PY34_64=D:\jpy\Python34-amd64 17 | SET PY35_64=D:\jpy\Python35-amd64 18 | SET PY27_32=D:\jpy\Python27 19 | SET PY33_32=D:\jpy\Python33 20 | SET PY34_32=D:\jpy\Python34 21 | SET PY35_32=D:\jpy\Python35 22 | 23 | SET OLD_PYTHONHOME=%PYTHONHOME% 24 | SET PYTHONHOME= 25 | 26 | IF NOT EXIST "%JDK64_HOME%" GOTO Build_32 27 | SET JAVA_HOME=%JDK64_HOME% 28 | CALL "%SDK_SETENV%" /x64 /release 29 | 30 | SET PYTHONHOME=%PY27_64% 31 | IF NOT EXIST "%PYTHONHOME%" GOTO Build_PY33_64 32 | ECHO Starting build using "%PYTHONHOME%" and "%JAVA_HOME%" 33 | "%PYTHONHOME%\python.exe" setup.py --maven bdist_wheel 34 | 35 | 36 | :Build_PY33_64 37 | SET PYTHONHOME=%PY33_64% 38 | IF NOT EXIST "%PYTHONHOME%" GOTO Build_PY34_64 39 | ECHO Starting build using "%PYTHONHOME%" and "%JAVA_HOME%" 40 | "%PYTHONHOME%\python.exe" setup.py --maven bdist_wheel 41 | 42 | :Build_PY34_64 43 | SET PYTHONHOME=%PY34_64% 44 | IF NOT EXIST "%PYTHONHOME%" GOTO Build_32 45 | ECHO Starting build using "%PYTHONHOME%" and "%JAVA_HOME%" 46 | "%PYTHONHOME%\python.exe" setup.py --maven bdist_wheel 47 | 48 | :Build_PY35_64 49 | SET PYTHONHOME=%PY35_64% 50 | IF NOT EXIST "%PYTHONHOME%" GOTO Build_32 51 | ECHO Starting build using "%PYTHONHOME%" and "%JAVA_HOME%" 52 | "%PYTHONHOME%\python.exe" setup.py --maven bdist_wheel 53 | 54 | :Build_32 55 | 56 | IF NOT EXIST "%JDK32_HOME%" GOTO Build_End 57 | SET JAVA_HOME=%JDK32_HOME% 58 | CALL "%SDK_SETENV%" /x86 /release 59 | 60 | SET PYTHONHOME=%PY27_32% 61 | IF NOT EXIST "%PYTHONHOME%" GOTO Build_PY33_32 62 | ECHO Starting build using "%PYTHONHOME%" and "%JAVA_HOME%" 63 | "%PYTHONHOME%\python.exe" setup.py --maven bdist_wheel 64 | 65 | :Build_PY33_32 66 | SET PYTHONHOME=%PY33_32% 67 | IF NOT EXIST "%PYTHONHOME%" GOTO Build_PY34_32 68 | ECHO Starting build using "%PYTHONHOME%" and "%JAVA_HOME%" 69 | "%PYTHONHOME%\python.exe" setup.py --maven bdist_wheel 70 | 71 | :Build_PY34_32 72 | SET PYTHONHOME=%PY34_32% 73 | IF NOT EXIST "%PYTHONHOME%" GOTO Build_End 74 | ECHO Starting build using "%PYTHONHOME%" and "%JAVA_HOME%" 75 | "%PYTHONHOME%\python.exe" setup.py --maven bdist_wheel 76 | 77 | :Build_PY35_32 78 | SET PYTHONHOME=%PY35_32% 79 | IF NOT EXIST "%PYTHONHOME%" GOTO Build_End 80 | ECHO Starting build using "%PYTHONHOME%" and "%JAVA_HOME%" 81 | "%PYTHONHOME%\python.exe" setup.py --maven bdist_wheel 82 | 83 | :Build_End 84 | IF EXIST "%PYTHONHOME%" "%PYTHONHOME%\python.exe" setup.py sdist 85 | SET PYTHONHOME=%OLD_PYTHONHOME% 86 | --------------------------------------------------------------------------------