├── .github └── workflows │ ├── create.yml │ ├── no-response.yml │ ├── push-x86.yml │ ├── push.yml │ └── support.yml ├── .gitignore ├── .readthedocs.yaml ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── CONTACT.md ├── CONTRIBUTING.md ├── FAQ.md ├── LICENSE ├── MANIFEST.in ├── Makefile ├── README.md ├── build.xml ├── docs ├── Makefile ├── make.bat ├── requirements.txt └── source │ ├── android.rst │ ├── api.rst │ ├── building.rst │ ├── conf.py │ ├── contact.rst │ ├── contribute.rst │ ├── faq.rst │ ├── index.rst │ ├── installation.rst │ ├── packaging.rst │ └── quickstart.rst ├── examples └── arraylists │ ├── arraylist.java │ └── arraylist.py ├── jnius ├── __init__.py ├── env.py ├── jni.pxi ├── jnius.pyx ├── jnius_compat.pxi ├── jnius_conversion.pxi ├── jnius_env.pxi ├── jnius_export_class.pxi ├── jnius_export_func.pxi ├── jnius_jvm_android.pxi ├── jnius_jvm_desktop.pxi ├── jnius_jvm_dlopen.pxi ├── jnius_localref.pxi ├── jnius_nativetypes3.pxi ├── jnius_proxy.pxi ├── jnius_utils.pxi ├── reflect.py ├── signatures.py └── src │ └── org │ └── jnius │ └── NativeInvocationHandler.java ├── jnius_config.py ├── main.workflow ├── pyproject.toml ├── renovate.json ├── setup.cfg ├── setup.py ├── setup_sdist.py └── tests ├── android └── testhardware │ └── main.py ├── java-src └── org │ ├── jnius │ ├── BasicsTest.java │ ├── CharsAndStrings.java │ ├── Child.java │ ├── ChildVisibilityTest.java │ ├── ClassArgument.java │ ├── CloseableClass.java │ ├── ConstructorTest.java │ ├── HelloWorld.java │ ├── InterfaceWithPublicEnum.java │ ├── MultipleDimensions.java │ ├── MultipleMethods.java │ ├── ObjectArgument.java │ ├── Parent.java │ ├── SimpleEnum.java │ ├── VariableArgConstructors.java │ ├── VariablePassing.java │ └── VisibilityTest.java │ └── jnius2 │ └── ChildVisibilityTest.java ├── test_arraylist.py ├── test_assignable.py ├── test_bad_declaration.py ├── test_basics.py ├── test_bytearray.py ├── test_cast.py ├── test_chars_and_strings.py ├── test_class_argument.py ├── test_closeable.py ├── test_collections.py ├── test_comparable.py ├── test_constructor.py ├── test_dir.py ├── test_enum.py ├── test_export_class.py ├── test_implementation.py ├── test_inheritance.py ├── test_int_vs_long.py ├── test_interface.py ├── test_jnitable_overflow.py ├── test_jnius_config.py ├── test_jvm_options.py ├── test_lambdas.py ├── test_method_multiple_signatures.py ├── test_multidimension.py ├── test_object_args.py ├── test_output_args.py ├── test_pass_by_reference_or_value.py ├── test_proxy.py ├── test_reflect.py ├── test_signature.py ├── test_simple.py ├── test_static.py ├── test_visibility_all.py ├── test_visibility_package_protected.py ├── test_visibility_public_only.py └── test_visibility_public_protected.py /.github/workflows/no-response.yml: -------------------------------------------------------------------------------- 1 | name: No Response 2 | 3 | # Both `issue_comment` and `scheduled` event types are required for this Action 4 | # to work properly. 5 | on: 6 | issue_comment: 7 | types: [created] 8 | schedule: 9 | # Schedule for an arbitrary time (4am) once every day 10 | - cron: '* 4 * * *' 11 | 12 | jobs: 13 | noResponse: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: lee-dohm/no-response@9bb0a4b5e6a45046f00353d5de7d90fb8bd773bb 17 | # This commit hash targets release v0.5.0 of lee-dohm/no-response. 18 | # Targeting a commit hash instead of a tag has been done for security reasons. 19 | # Please be aware that the commit hash specifically targets the "Automatic compilation" 20 | # done by `github-actions[bot]` as the `no-response` Action needs to be compiled. 21 | with: 22 | token: ${{ github.token }} 23 | daysUntilClose: 42 24 | responseRequiredLabel: 'awaiting-reply' 25 | closeComment: > 26 | This issue has been automatically closed because there has been no response 27 | to our request for more information from the original author. With only the 28 | information that is currently in the issue, we don't have the means 29 | to take action. Please reach out if you have or find the answers we need so 30 | that we can investigate further. 31 | -------------------------------------------------------------------------------- /.github/workflows/push-x86.yml: -------------------------------------------------------------------------------- 1 | on: [push, pull_request] 2 | name: Continuous Integration (x86) 3 | jobs: 4 | Tests: 5 | name: base 6 | runs-on: ubuntu-latest 7 | strategy: 8 | matrix: 9 | python: 10 | - '3.8' 11 | - '3.9' 12 | - '3.10' 13 | - '3.11' 14 | container: 15 | image: i386/python:${{ matrix.python }}-buster 16 | steps: 17 | - name: info 18 | run: | 19 | linux32 sh -ec ' 20 | cat /etc/*release || true 21 | uname -a 22 | git version 23 | python --version 24 | ' 25 | 26 | - name: checkout 27 | run: | 28 | linux32 sh -ec ' 29 | git config --global --add safe.directory '*' 30 | git init . 31 | git remote add origin https://github.com/$GITHUB_REPOSITORY 32 | git config --local gc.auto 0 33 | git fetch --no-tags --prune --progress --no-recurse-submodules \ 34 | --depth=1 origin +$GITHUB_SHA:refs/remotes/origin/${GITHUB_REF##*/} 35 | git checkout --progress --force -B ${GITHUB_REF##*/} \ 36 | refs/remotes/origin/${GITHUB_REF##*/} 37 | git log -1 --format=%H 38 | ' 39 | 40 | - name: setup java 41 | run: | 42 | linux32 sh -ec ' 43 | apt update 44 | apt install -y openjdk-11-jdk-headless ant 45 | java -version 46 | ' 47 | env: 48 | DEBIAN_FRONTEND: noninteractive 49 | 50 | - name: install 51 | run: | 52 | linux32 sh -ec ' 53 | pip install --timeout=120 .[dev,ci] 54 | ' 55 | 56 | - name: test 57 | run: | 58 | linux32 sh -ec ' 59 | ant all 60 | cd tests 61 | CLASSPATH=../build/test-classes:../build/classes pytest -v 62 | ' 63 | -------------------------------------------------------------------------------- /.github/workflows/push.yml: -------------------------------------------------------------------------------- 1 | on: [push, pull_request] 2 | name: Continuous Integration 3 | jobs: 4 | Tests: 5 | name: base 6 | continue-on-error: true 7 | strategy: 8 | matrix: 9 | python: 10 | - '3.8' 11 | - '3.9' 12 | - '3.10' 13 | - '3.11' 14 | - '3.12' 15 | - 'pypy-3.8' 16 | - 'pypy-3.9' 17 | java: 18 | - '8' 19 | - '11' 20 | - '23' 21 | os: 22 | # macos-latest (ATM macos-14) runs on Apple Silicon, 23 | # macos-13 runs on Intel 24 | - 'ubuntu-latest' 25 | - 'windows-latest' 26 | - 'macos-latest' 27 | - 'macos-13' 28 | cython: 29 | - '<3' 30 | - '>=3' 31 | architecture: 32 | - 'x64' 33 | - 'x86' 34 | - 'aarch64' 35 | exclude: 36 | - os: windows-latest 37 | architecture: aarch64 38 | - os: ubuntu-latest 39 | architecture: aarch64 40 | - os: ubuntu-latest 41 | architecture: x86 42 | - os: macos-13 43 | architecture: aarch64 44 | - os: macos-13 45 | architecture: x86 46 | - os: macos-latest 47 | architecture: aarch64 48 | java: '8' 49 | - os: macos-latest 50 | architecture: x64 51 | - os: macos-latest 52 | architecture: x86 53 | - os: windows-latest 54 | architecture: x86 55 | python: 'pypy-3.8' 56 | - os: windows-latest 57 | architecture: x86 58 | python: 'pypy-3.9' 59 | - os: windows-latest 60 | architecture: x86 61 | java: '20' 62 | - os: windows-latest 63 | architecture: x86 64 | java: '21' 65 | - os: windows-latest 66 | architecture: x86 67 | java: '22' 68 | - os: windows-latest 69 | architecture: x86 70 | java: '23' 71 | 72 | runs-on: ${{ matrix.os }} 73 | steps: 74 | - uses: actions/checkout@master 75 | 76 | - name: Setup python 77 | uses: actions/setup-python@v5 78 | with: 79 | python-version: ${{ matrix.python }} 80 | architecture: ${{ matrix.architecture == 'aarch64' && 'arm64' || matrix.architecture }} 81 | 82 | - name: Setup java 83 | uses: actions/setup-java@v4 84 | with: 85 | java-version: ${{ matrix.java }} 86 | distribution: 'temurin' 87 | architecture: ${{ matrix.architecture }} 88 | 89 | - name: (macOS) Setup test dependencies 90 | if: matrix.os == 'macos-latest' || matrix.os == 'macos-13' 91 | run: brew install ant 92 | 93 | - name: Build test classes via ant 94 | run: ant all 95 | 96 | - name: (Windows) Force Cython version 97 | # Windows sed doesnt accept .bak filename extensions 98 | if: matrix.os == 'windows-latest' 99 | run: sed -i 's/"Cython"/"Cython${{matrix.cython}}"/' pyproject.toml 100 | 101 | - name: (Linux, macOS) Force Cython version 102 | # macOS sed requires .bak filename extensions 103 | if: (matrix.os == 'ubuntu-latest') || (matrix.os == 'macos-latest') || (matrix.os == 'macos-13') 104 | run: sed -i.bak 's/"Cython"/"Cython${{matrix.cython}}"/' pyproject.toml 105 | 106 | - name: Install pyjnius with [dev, ci] extras 107 | run: | 108 | pip install --timeout=120 .[dev,ci] 109 | 110 | - name: (Windows) Test pyjnius via pytest 111 | if: matrix.os == 'windows-latest' 112 | run: | 113 | $env:PATH +=";$env:JAVA_HOME\jre\bin\server\;$env:JAVA_HOME\jre\bin\client\;$env:JAVA_HOME\bin\server\" 114 | $env:CLASSPATH ="../build/test-classes;../build/classes" 115 | cd tests 116 | pytest -v 117 | 118 | - name: (Linux, macOS) Test pyjnius via pytest 119 | if: (matrix.os == 'ubuntu-latest') || (matrix.os == 'macos-latest') || (matrix.os == 'macos-13') 120 | run: | 121 | cd tests 122 | CLASSPATH=../build/test-classes:../build/classes python -m pytest -v 123 | 124 | # - name: coveralls 125 | # run: python -m coveralls 126 | # env: 127 | # COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_REPO_TOKEN }} 128 | -------------------------------------------------------------------------------- /.github/workflows/support.yml: -------------------------------------------------------------------------------- 1 | name: 'Support Requests' 2 | 3 | on: 4 | issues: 5 | types: [labeled, unlabeled, reopened] 6 | 7 | permissions: 8 | issues: write 9 | 10 | jobs: 11 | action: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: dessant/support-requests@v4 15 | with: 16 | github-token: ${{ github.token }} 17 | support-label: 'support' 18 | issue-comment: > 19 | 👋 We use the issue tracker exclusively for bug reports and feature requests. 20 | However, this issue appears to be a support request. Please use our 21 | [support channels](https://github.com/kivy/pyjnius/blob/master/CONTACT.md) 22 | to get help with the project. 23 | 24 | Let us know if this comment was made in error, and we'll be happy 25 | to reopen the issue. 26 | close-issue: true 27 | lock-issue: false 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyo 2 | *.pyc 3 | jnius/jnius.c 4 | jnius/config.pxi 5 | jnius/jnius.so 6 | build 7 | .*.swp 8 | *.class 9 | .idea 10 | *~ 11 | *.so 12 | *.iml 13 | dist 14 | pyjnius.egg-info 15 | jnius.egg-info 16 | *.pyd 17 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # Read the Docs configuration file for Sphinx projects 2 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 3 | 4 | version: 2 5 | 6 | build: 7 | os: ubuntu-22.04 8 | tools: 9 | python: "3" 10 | 11 | python: 12 | install: 13 | - requirements: docs/requirements.txt 14 | 15 | sphinx: 16 | configuration: docs/source/conf.py 17 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | In the interest of fostering an open and welcoming community, we as 2 | contributors and maintainers need to ensure participation in our project and 3 | our sister projects is a harassment-free and positive experience for everyone. 4 | It is vital that all interaction is conducted in a manner conveying respect, 5 | open-mindedness and gratitude. 6 | 7 | Please consult the [latest Kivy Code of Conduct](https://github.com/kivy/kivy/blob/master/CODE_OF_CONDUCT.md). 8 | 9 | -------------------------------------------------------------------------------- /CONTACT.md: -------------------------------------------------------------------------------- 1 | # Contacting the Kivy Team 2 | 3 | If you are looking to contact the Kivy Team (who are responsible for managing 4 | the PyJNIus project), including looking for support, please see our 5 | latest [Contact Us](https://github.com/kivy/kivy/blob/master/CONTACT.md) 6 | document. 7 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution Guidelines 2 | 3 | PyJNIus is part of the [Kivy](https://kivy.org) ecosystem - a large group of 4 | products used by many thousands of developers for free, but it 5 | is built entirely by the contributions of volunteers. We welcome (and rely on) 6 | users who want to give back to the community by contributing to the project. 7 | 8 | Contributions can come in many forms. See the latest 9 | [Contribution Guidelines](https://github.com/kivy/kivy/blob/master/CONTRIBUTING.md) 10 | for how you can help us. 11 | -------------------------------------------------------------------------------- /FAQ.md: -------------------------------------------------------------------------------- 1 | # FAQ for PyJNIus 2 | 3 | ## Introduction 4 | 5 | PyJNIus is a [Python](https://www.python.org/) library for accessing 6 | [Java](https://www.java.com/) classes using the 7 | [Java Native Interface](https://docs.oracle.com/javase/8/docs/technotes/guides/jni/) 8 | (JNI). 9 | 10 | Warning: the [PyPI](https://pypi.org/) package name is now 11 | [pyjnius](https://pypi.org/project/pyjnius/) instead of `jnius`. 12 | 13 | ## No questions yet 14 | 15 | No Frequently Asked Questions have been identified yet. Please contribute some. 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2010-2023 Kivy Team and other contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include *LICENSE 2 | recursive-include jnius *.pyx *.pxi 3 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: build_ext 2 | 3 | .PHONY: build_ext tests 4 | 5 | PYTHON=python 6 | PYTEST=pytest 7 | 8 | JAVA_TARGET ?= $(shell $(PYTHON) -c "import re; print('1.6' if int(re.findall(r'\d+', '$(shell javac -version 2>&1)')[0]) < 12 else '1.7')" ) 9 | JAVAC_OPTS=-target $(JAVA_TARGET) -source $(JAVA_TARGET) 10 | JAVAC=javac $(JAVAC_OPTS) 11 | 12 | ANT=ant -Dant.build.javac.source=$(JAVA_TARGET) -Dant.build.javac.target=$(JAVA_TARGET) 13 | 14 | build_ext: 15 | $(ANT) all 16 | $(PYTHON) setup.py build_ext --inplace -g 17 | 18 | clean: 19 | $(ANT) clean 20 | rm -rf build jnius/config.pxi 21 | 22 | html: 23 | $(MAKE) -C docs html 24 | 25 | # for use in travis; tests whatever you got. 26 | # use PYTHON3=1 to force python3 in other environments. 27 | tests: 28 | (cd tests; env CLASSPATH=../build/test-classes:../build/classes PYTHONPATH=..:$(PYTHONPATH) $(PYTEST) -v) 29 | -------------------------------------------------------------------------------- /build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 15 | 16 | 17 | 18 | 19 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = build 9 | 10 | # Internal variables. 11 | PAPEROPT_a4 = -D latex_paper_size=a4 12 | PAPEROPT_letter = -D latex_paper_size=letter 13 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source 14 | # the i18n builder cannot share the environment and doctrees with the others 15 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source 16 | 17 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext 18 | 19 | help: 20 | @echo "Please use \`make ' where is one of" 21 | @echo " html to make standalone HTML files" 22 | @echo " dirhtml to make HTML files named index.html in directories" 23 | @echo " singlehtml to make a single large HTML file" 24 | @echo " pickle to make pickle files" 25 | @echo " json to make JSON files" 26 | @echo " htmlhelp to make HTML files and a HTML help project" 27 | @echo " qthelp to make HTML files and a qthelp project" 28 | @echo " devhelp to make HTML files and a Devhelp project" 29 | @echo " epub to make an epub" 30 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 31 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 32 | @echo " text to make text files" 33 | @echo " man to make manual pages" 34 | @echo " texinfo to make Texinfo files" 35 | @echo " info to make Texinfo files and run them through makeinfo" 36 | @echo " gettext to make PO message catalogs" 37 | @echo " changes to make an overview of all changed/added/deprecated items" 38 | @echo " linkcheck to check all external links for integrity" 39 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 40 | 41 | clean: 42 | -rm -rf $(BUILDDIR)/* 43 | 44 | html: 45 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 46 | @echo 47 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 48 | 49 | dirhtml: 50 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 51 | @echo 52 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 53 | 54 | singlehtml: 55 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 56 | @echo 57 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 58 | 59 | pickle: 60 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 61 | @echo 62 | @echo "Build finished; now you can process the pickle files." 63 | 64 | json: 65 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 66 | @echo 67 | @echo "Build finished; now you can process the JSON files." 68 | 69 | htmlhelp: 70 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 71 | @echo 72 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 73 | ".hhp project file in $(BUILDDIR)/htmlhelp." 74 | 75 | qthelp: 76 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 77 | @echo 78 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 79 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 80 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Pyjnius.qhcp" 81 | @echo "To view the help file:" 82 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Pyjnius.qhc" 83 | 84 | devhelp: 85 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 86 | @echo 87 | @echo "Build finished." 88 | @echo "To view the help file:" 89 | @echo "# mkdir -p $$HOME/.local/share/devhelp/Pyjnius" 90 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Pyjnius" 91 | @echo "# devhelp" 92 | 93 | epub: 94 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 95 | @echo 96 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 97 | 98 | latex: 99 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 100 | @echo 101 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 102 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 103 | "(use \`make latexpdf' here to do that automatically)." 104 | 105 | latexpdf: 106 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 107 | @echo "Running LaTeX files through pdflatex..." 108 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 109 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 110 | 111 | text: 112 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 113 | @echo 114 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 115 | 116 | man: 117 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 118 | @echo 119 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 120 | 121 | texinfo: 122 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 123 | @echo 124 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 125 | @echo "Run \`make' in that directory to run these through makeinfo" \ 126 | "(use \`make info' here to do that automatically)." 127 | 128 | info: 129 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 130 | @echo "Running Texinfo files through makeinfo..." 131 | make -C $(BUILDDIR)/texinfo info 132 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 133 | 134 | gettext: 135 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 136 | @echo 137 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 138 | 139 | changes: 140 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 141 | @echo 142 | @echo "The overview file is in $(BUILDDIR)/changes." 143 | 144 | linkcheck: 145 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 146 | @echo 147 | @echo "Link check complete; look for any errors in the above output " \ 148 | "or in $(BUILDDIR)/linkcheck/output.txt." 149 | 150 | doctest: 151 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 152 | @echo "Testing of doctests in the sources finished, look at the " \ 153 | "results in $(BUILDDIR)/doctest/output.txt." 154 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM Command file for Sphinx documentation 4 | 5 | if "%SPHINXBUILD%" == "" ( 6 | set SPHINXBUILD=sphinx-build 7 | ) 8 | set BUILDDIR=build 9 | set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source 10 | set I18NSPHINXOPTS=%SPHINXOPTS% source 11 | if NOT "%PAPER%" == "" ( 12 | set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% 13 | set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% 14 | ) 15 | 16 | if "%1" == "" goto help 17 | 18 | if "%1" == "help" ( 19 | :help 20 | echo.Please use `make ^` where ^ is one of 21 | echo. html to make standalone HTML files 22 | echo. dirhtml to make HTML files named index.html in directories 23 | echo. singlehtml to make a single large HTML file 24 | echo. pickle to make pickle files 25 | echo. json to make JSON files 26 | echo. htmlhelp to make HTML files and a HTML help project 27 | echo. qthelp to make HTML files and a qthelp project 28 | echo. devhelp to make HTML files and a Devhelp project 29 | echo. epub to make an epub 30 | echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter 31 | echo. text to make text files 32 | echo. man to make manual pages 33 | echo. texinfo to make Texinfo files 34 | echo. gettext to make PO message catalogs 35 | echo. changes to make an overview over all changed/added/deprecated items 36 | echo. linkcheck to check all external links for integrity 37 | echo. doctest to run all doctests embedded in the documentation if enabled 38 | goto end 39 | ) 40 | 41 | if "%1" == "clean" ( 42 | for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i 43 | del /q /s %BUILDDIR%\* 44 | goto end 45 | ) 46 | 47 | if "%1" == "html" ( 48 | %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html 49 | if errorlevel 1 exit /b 1 50 | echo. 51 | echo.Build finished. The HTML pages are in %BUILDDIR%/html. 52 | goto end 53 | ) 54 | 55 | if "%1" == "dirhtml" ( 56 | %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml 57 | if errorlevel 1 exit /b 1 58 | echo. 59 | echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. 60 | goto end 61 | ) 62 | 63 | if "%1" == "singlehtml" ( 64 | %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml 65 | if errorlevel 1 exit /b 1 66 | echo. 67 | echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. 68 | goto end 69 | ) 70 | 71 | if "%1" == "pickle" ( 72 | %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle 73 | if errorlevel 1 exit /b 1 74 | echo. 75 | echo.Build finished; now you can process the pickle files. 76 | goto end 77 | ) 78 | 79 | if "%1" == "json" ( 80 | %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json 81 | if errorlevel 1 exit /b 1 82 | echo. 83 | echo.Build finished; now you can process the JSON files. 84 | goto end 85 | ) 86 | 87 | if "%1" == "htmlhelp" ( 88 | %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp 89 | if errorlevel 1 exit /b 1 90 | echo. 91 | echo.Build finished; now you can run HTML Help Workshop with the ^ 92 | .hhp project file in %BUILDDIR%/htmlhelp. 93 | goto end 94 | ) 95 | 96 | if "%1" == "qthelp" ( 97 | %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp 98 | if errorlevel 1 exit /b 1 99 | echo. 100 | echo.Build finished; now you can run "qcollectiongenerator" with the ^ 101 | .qhcp project file in %BUILDDIR%/qthelp, like this: 102 | echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Pyjnius.qhcp 103 | echo.To view the help file: 104 | echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Pyjnius.ghc 105 | goto end 106 | ) 107 | 108 | if "%1" == "devhelp" ( 109 | %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp 110 | if errorlevel 1 exit /b 1 111 | echo. 112 | echo.Build finished. 113 | goto end 114 | ) 115 | 116 | if "%1" == "epub" ( 117 | %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub 118 | if errorlevel 1 exit /b 1 119 | echo. 120 | echo.Build finished. The epub file is in %BUILDDIR%/epub. 121 | goto end 122 | ) 123 | 124 | if "%1" == "latex" ( 125 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 126 | if errorlevel 1 exit /b 1 127 | echo. 128 | echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. 129 | goto end 130 | ) 131 | 132 | if "%1" == "text" ( 133 | %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text 134 | if errorlevel 1 exit /b 1 135 | echo. 136 | echo.Build finished. The text files are in %BUILDDIR%/text. 137 | goto end 138 | ) 139 | 140 | if "%1" == "man" ( 141 | %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man 142 | if errorlevel 1 exit /b 1 143 | echo. 144 | echo.Build finished. The manual pages are in %BUILDDIR%/man. 145 | goto end 146 | ) 147 | 148 | if "%1" == "texinfo" ( 149 | %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo 150 | if errorlevel 1 exit /b 1 151 | echo. 152 | echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. 153 | goto end 154 | ) 155 | 156 | if "%1" == "gettext" ( 157 | %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale 158 | if errorlevel 1 exit /b 1 159 | echo. 160 | echo.Build finished. The message catalogs are in %BUILDDIR%/locale. 161 | goto end 162 | ) 163 | 164 | if "%1" == "changes" ( 165 | %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes 166 | if errorlevel 1 exit /b 1 167 | echo. 168 | echo.The overview file is in %BUILDDIR%/changes. 169 | goto end 170 | ) 171 | 172 | if "%1" == "linkcheck" ( 173 | %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck 174 | if errorlevel 1 exit /b 1 175 | echo. 176 | echo.Link check complete; look for any errors in the above output ^ 177 | or in %BUILDDIR%/linkcheck/output.txt. 178 | goto end 179 | ) 180 | 181 | if "%1" == "doctest" ( 182 | %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest 183 | if errorlevel 1 exit /b 1 184 | echo. 185 | echo.Testing of doctests in the sources finished, look at the ^ 186 | results in %BUILDDIR%/doctest/output.txt. 187 | goto end 188 | ) 189 | 190 | :end 191 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | Sphinx~=7.2.6 2 | furo==2024.8.6 -------------------------------------------------------------------------------- /docs/source/android.rst: -------------------------------------------------------------------------------- 1 | .. _android: 2 | 3 | Android 4 | ======= 5 | 6 | Android has a great and extensive API to control devices, your application 7 | etc. Some parts of the Android API are directly accessible with PyJNIus but 8 | some of them require you to code in Java. 9 | 10 | .. note:: 11 | Since Android 8.0 (Oreo) the maximum limit for the local references 12 | previously known as "local reference table overflow" after 512 refs 13 | has been lifted, therefore PyJNIus can create proper Java applications 14 | with a lot of local references. `Android JNI tips 15 | `_ 16 | 17 | Get the DPI 18 | ----------- 19 | 20 | The `DisplayMetrics 21 | `_ 22 | contains multiple fields that can return a lot of information about the device's 23 | screen:: 24 | 25 | from jnius import autoclass 26 | DisplayMetrics = autoclass('android.util.DisplayMetrics') 27 | metrics = DisplayMetrics() 28 | print('DPI', metrics.getDeviceDensity()) 29 | 30 | .. Note :: 31 | To access nested classes, use `$` e.g. 32 | `autoclass('android.provider.MediaStore$Images$Media')`. 33 | 34 | Recording an audio file 35 | ----------------------- 36 | 37 | By looking at the `Audio Capture 38 | `_ guide 39 | for Android, you can see the simple steps for recording an audio file. 40 | Let's do it with PyJNIus:: 41 | 42 | from jnius import autoclass 43 | from time import sleep 44 | 45 | # get the needed Java classes 46 | MediaRecorder = autoclass('android.media.MediaRecorder') 47 | AudioSource = autoclass('android.media.MediaRecorder$AudioSource') 48 | OutputFormat = autoclass('android.media.MediaRecorder$OutputFormat') 49 | AudioEncoder = autoclass('android.media.MediaRecorder$AudioEncoder') 50 | 51 | # create out recorder 52 | mRecorder = MediaRecorder() 53 | mRecorder.setAudioSource(AudioSource.MIC) 54 | mRecorder.setOutputFormat(OutputFormat.THREE_GPP) 55 | mRecorder.setOutputFile('/sdcard/testrecorder.3gp') 56 | mRecorder.setAudioEncoder(AudioEncoder.AMR_NB) 57 | mRecorder.prepare() 58 | 59 | # record 5 seconds 60 | mRecorder.start() 61 | sleep(5) 62 | mRecorder.stop() 63 | mRecorder.release() 64 | 65 | And tada, you'll have a `/sdcard/testrecorder.3gp` file! 66 | 67 | 68 | Playing an audio file 69 | --------------------- 70 | 71 | Following the previous section on how to record an audio file, you can read it 72 | using the Android Media Player too:: 73 | 74 | from jnius import autoclass 75 | from time import sleep 76 | 77 | # get the MediaPlayer java class 78 | MediaPlayer = autoclass('android.media.MediaPlayer') 79 | 80 | # create our player 81 | mPlayer = MediaPlayer() 82 | mPlayer.setDataSource('/sdcard/testrecorder.3gp') 83 | mPlayer.prepare() 84 | 85 | # play 86 | print('duration:', mPlayer.getDuration()) 87 | mPlayer.start() 88 | print('current position:', mPlayer.getCurrentPosition()) 89 | sleep(5) 90 | 91 | # then after the play: 92 | mPlayer.release() 93 | 94 | 95 | Accessing the Activity 96 | ---------------------- 97 | 98 | This example will show how to start a new Intent. Be careful: some Intents 99 | require you to setup parts in the `AndroidManifest.xml` and have some 100 | actions performed within your Activity. This is out of the scope of PyJNIus but 101 | we'll show you what the best approach is for playing with it. 102 | 103 | Using the Python-for-android project, you can access the default 104 | `PythonActivity`. Let's look at an example that demonstrates the 105 | `Intent.ACTION_VIEW`:: 106 | 107 | from jnius import cast 108 | from jnius import autoclass 109 | 110 | # import the needed Java class 111 | PythonActivity = autoclass('org.kivy.android.PythonActivity') 112 | Intent = autoclass('android.content.Intent') 113 | Uri = autoclass('android.net.Uri') 114 | 115 | # create the intent 116 | intent = Intent() 117 | intent.setAction(Intent.ACTION_VIEW) 118 | intent.setData(Uri.parse('http://kivy.org')) 119 | 120 | # PythonActivity.mActivity is the instance of the current Activity 121 | # BUT, startActivity is a method from the Activity class, not from our 122 | # PythonActivity. 123 | # We need to cast our class into an activity and use it 124 | currentActivity = cast('android.app.Activity', PythonActivity.mActivity) 125 | currentActivity.startActivity(intent) 126 | 127 | # The website will open. 128 | 129 | 130 | Accelerometer access 131 | -------------------- 132 | 133 | The accelerometer is a good example that shows how to write a little 134 | Java code that you can access later with PyJNIus. 135 | 136 | The `SensorManager 137 | `_ 138 | lets you access the device's sensors. To use it, you need to register a 139 | `SensorEventListener 140 | `_ 141 | and overload 2 abstract methods: `onAccuracyChanged` and `onSensorChanged`. 142 | 143 | Open your python-for-android distribution, go in the `src` directory, and 144 | create a file `org/myapp/Hardware.java`. In this file, you will create 145 | everything needed for accessing the accelerometer:: 146 | 147 | package org.myapp; 148 | 149 | import org.kivy.android.PythonActivity; 150 | import android.content.Context; 151 | import android.hardware.Sensor; 152 | import android.hardware.SensorEvent; 153 | import android.hardware.SensorEventListener; 154 | import android.hardware.SensorManager; 155 | 156 | public class Hardware { 157 | 158 | // Contain the last event we got from the listener 159 | static public SensorEvent lastEvent = null; 160 | 161 | // Define a new listener 162 | static class AccelListener implements SensorEventListener { 163 | public void onSensorChanged(SensorEvent ev) { 164 | lastEvent = ev; 165 | } 166 | public void onAccuracyChanged(Sensor sensor , int accuracy) { 167 | } 168 | } 169 | 170 | // Create our listener 171 | static AccelListener accelListener = new AccelListener(); 172 | 173 | // Method to activate/deactivate the accelerometer service and listener 174 | static void accelerometerEnable(boolean enable) { 175 | Context context = (Context) PythonActivity.mActivity; 176 | SensorManager sm = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); 177 | Sensor accel = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); 178 | 179 | if (accel == null) 180 | return; 181 | 182 | if (enable) 183 | sm.registerListener(accelListener, accel, SensorManager.SENSOR_DELAY_GAME); 184 | else 185 | sm.unregisterListener(accelListener, accel); 186 | } 187 | } 188 | 189 | So we created one method named `accelerometerEnable` to activate/deactivate the 190 | listener. And we saved the last event received in `Hardware.lastEvent`. 191 | Now you can use it in PyJNIus:: 192 | 193 | from time import sleep 194 | from jnius import autoclass 195 | 196 | Hardware = autoclass('org.myapp.Hardware') 197 | 198 | # activate the accelerometer 199 | Hardware.accelerometerEnable(True) 200 | 201 | # read it 202 | for i in xrange(20): 203 | 204 | # read the last event 205 | lastEvent = Hardware.lastEvent 206 | 207 | # we might not get any events. 208 | if not lastEvent: 209 | continue 210 | 211 | # show the current values! 212 | print(lastEvent.values) 213 | 214 | sleep(.1) 215 | 216 | # don't forget to deactivate it 217 | Hardware.accelerometerEnable(False) 218 | 219 | You'll obtain something like this:: 220 | 221 | [-0.0095768067985773087, 9.4235782623291016, 2.2122423648834229] 222 | ... 223 | 224 | 225 | Using TextToSpeech 226 | ------------------ 227 | 228 | Same as the audio capture, by looking at the `An introduction to Text-To-Speech in Android 229 | `_ blog post, it's easy to do it 230 | with PyJNIus:: 231 | 232 | from jnius import autoclass 233 | Locale = autoclass('java.util.Locale') 234 | PythonActivity = autoclass('org.kivy.android.PythonActivity') 235 | TextToSpeech = autoclass('android.speech.tts.TextToSpeech') 236 | tts = TextToSpeech(PythonActivity.mActivity, None) 237 | 238 | # Play something in english 239 | tts.setLanguage(Locale.US) 240 | tts.speak('Hello World.', TextToSpeech.QUEUE_FLUSH, None) 241 | 242 | # Queue something in french 243 | tts.setLanguage(Locale.FRANCE) 244 | tts.speak('Bonjour tout le monde.', TextToSpeech.QUEUE_ADD, None) 245 | 246 | -------------------------------------------------------------------------------- /docs/source/building.rst: -------------------------------------------------------------------------------- 1 | .. _building: 2 | 3 | Building PyJNIus 4 | ================ 5 | 6 | Building PyJNIus is necessary for development purposes, or if there is no 7 | pre-built binary for your particular platform. 8 | 9 | Like installation of PyJNIus, building PyJNIus requires a `Java Development Kit 10 | `_ (JDK) 11 | to be installed. 12 | 13 | Apart from the JDK, the build requirements for each platform are as follows: 14 | 15 | - Linux: the `GNU Compiler Collection `_ (GCC), e.g. using 16 | `apt-get install build-essentials` on Debian-based distributions. 17 | - Windows: `Microsoft Visual C++ Build Tools `_ 18 | (the command-line tools subset of Visual Studio). 19 | For more information or options, see Python's `Windows Compilers wiki 20 | `_. 21 | - macOS: `Xcode command-line tools `_. 22 | 23 | In all cases, after checking out PyJNIus from GitHub, it can be *built* and installed using:: 24 | 25 | pip install . 26 | 27 | This installs `Cython `_ (as specified in the 28 | `pyproject.toml `_) 29 | in a Python build environment. On all platforms, if PyJNIus cannot find your JDK, you can set 30 | the `JAVA_HOME` environment variable (this is often needed on Windows). 31 | 32 | If you want to compile the PyJNIus extension within the directory for any development, 33 | just type:: 34 | 35 | make 36 | 37 | You can run the tests suite to make sure everything is running right:: 38 | 39 | make tests 40 | 41 | In these cases, you may need to have `Cython `_ 42 | and `pytest `_ installed in the current Python environment. -------------------------------------------------------------------------------- /docs/source/contact.rst: -------------------------------------------------------------------------------- 1 | .. _contact: 2 | 3 | Contact Us 4 | ========== 5 | 6 | If you are looking to contact the Kivy Team (who are responsible for managing the 7 | PyJNIus project), including looking for support, please see our 8 | `latest contact details `_. -------------------------------------------------------------------------------- /docs/source/contribute.rst: -------------------------------------------------------------------------------- 1 | .. _contribute: 2 | 3 | Contribution Guidelines 4 | ======================= 5 | 6 | Kivy is a large product used by many thousands of developers for free, but it 7 | is built entirely by the contributions of volunteers. We welcome (and rely on) 8 | users who want to give back to the community by contributing to the project. 9 | 10 | Contributions can come in many forms. To learn more, see our 11 | `latest Contribution Guidelines `_. -------------------------------------------------------------------------------- /docs/source/faq.rst: -------------------------------------------------------------------------------- 1 | .. _faq: 2 | 3 | FAQ 4 | === 5 | 6 | PyJNIus has an `online FAQ `_. It contains the answers to 7 | questions that repeatedly come up. 8 | -------------------------------------------------------------------------------- /docs/source/index.rst: -------------------------------------------------------------------------------- 1 | Welcome to PyJNIus 2 | ================== 3 | 4 | PyJNIus is a `Python `_ library for accessing 5 | `Java `_ classes using the 6 | `Java Native Interface ` 7 | (JNI). 8 | 9 | It either starts a new `Java Virtual machine `_ 10 | (JVM) inside the process, or retrieves the already surrounding JVM (for example on Android). 11 | 12 | PyJNIus is managed by the `Kivy Team `_ and can be 13 | used with `python-for-android `_. 14 | 15 | PyJNIus is released and distributed under the terms of the MIT license. You should have received a 16 | copy of the MIT license alongside your Kivy distribution. Our 17 | `latest license `_ 18 | is also available. 19 | 20 | 21 | This documentation is divided into differents parts. We recommend you to start 22 | with :ref:`installation`, and then head over to the :ref:`quickstart`. You can 23 | also check :ref:`android` for specific example for the Android platform. If 24 | you'd rather dive into the internals of PyJNIus, check out the :ref:`api` 25 | documentation. 26 | 27 | .. toctree:: 28 | :maxdepth: 2 29 | 30 | installation 31 | quickstart 32 | android 33 | api 34 | packaging 35 | contact 36 | contribute 37 | faq 38 | 39 | Indices and tables 40 | ================== 41 | 42 | * :ref:`genindex` 43 | * :ref:`modindex` 44 | * :ref:`search` 45 | 46 | -------------------------------------------------------------------------------- /docs/source/installation.rst: -------------------------------------------------------------------------------- 1 | .. _installation: 2 | 3 | Installation 4 | ============ 5 | 6 | PyJNIus has pre-compiled binaries on PyPi for recent Python versions on Linux, 7 | macOS and Windows. 8 | 9 | On each platform:: 10 | 11 | pip install pyjnius 12 | 13 | should successfully install the package. 14 | 15 | If there is no pre-compiled binary available, pip install will aim to compile 16 | a binary on your operating system. For more information see the :ref:`building` 17 | documentation. 18 | 19 | You will need the Java JDK installed (`OpenJDK `_ is fine). 20 | PyJNIus searches for Java in the usual places on each operating system. If PyJNIus 21 | cannot find Java, set the `JAVA_HOME` environment variable (this is often needed 22 | `on Windows `_). 23 | 24 | Installation for Android 25 | ------------------------ 26 | 27 | To use pyjnius in an Android app, you must include it in your compiled 28 | Python distribution. This is done automatically if you build a `Kivy 29 | `__ app, but you can also add it to your 30 | requirements explicitly as follows. 31 | 32 | If you use `buildozer 33 | `__, add pyjnius to your 34 | requirements in buildozer.spec:: 35 | 36 | requirements = pyjnius 37 | 38 | If you use `python-for-android 39 | `__ directly, add 40 | pyjnius to the requirements argument when creating a dist or apk:: 41 | 42 | p4a apk --requirements=pyjnius 43 | 44 | 45 | Installation for Conda 46 | ---------------------- 47 | 48 | Similar to PIP there is a package manager for 49 | `Anaconda ` called Conda. 50 | An unofficial compiled distributions of PyJNIus for Conda supported 51 | platforms you can find at https://anaconda.org/conda-forge/pyjnius. 52 | 53 | You can install ``pyjnius`` with this command:: 54 | 55 | conda install -c conda-forge pyjnius 56 | 57 | Or if you want a specific package label e.g. ``gcc7``:: 58 | 59 | conda install -c conda-forge/label/gcc7 pyjnius 60 | -------------------------------------------------------------------------------- /docs/source/packaging.rst: -------------------------------------------------------------------------------- 1 | .. _packaging: 2 | 3 | Packaging 4 | ========= 5 | 6 | For Packaging, we suggest use of `PyInstaller `_. 7 | With these simple steps we will create a simple executable containing PyJNIus 8 | that prints the path of currently used Java. These steps assume you have 9 | a supported version of Python for PyJNIus and PyInstaller available together 10 | with Java installed (necessary for running the application). 11 | 12 | main.py 13 | ------- 14 | 15 | .. code:: python 16 | 17 | from jnius import autoclass 18 | 19 | if __name__ == '__main__': 20 | print(autoclass('java.lang.System').getProperty('java.home')) 21 | 22 | This will be our ``main.py`` file. You can now call PyInstaller to create 23 | a basic ``.spec`` file which contains basic instructions for PyInstaller with:: 24 | 25 | pyinstaller main.py 26 | 27 | main.spec 28 | --------- 29 | 30 | The created ``.spec`` file might look like this:: 31 | 32 | # -*- mode: python -*- 33 | 34 | block_cipher = None 35 | 36 | 37 | a = Analysis( 38 | ['main.py'], 39 | pathex=[''], 40 | binaries=None, 41 | datas=None, 42 | hiddenimports=[], 43 | hookspath=[], 44 | runtime_hooks=[], 45 | excludes=[], 46 | win_no_prefer_redirects=False, 47 | win_private_assemblies=False, 48 | cipher=block_cipher 49 | ) 50 | 51 | pyz = PYZ( 52 | a.pure, 53 | a.zipped_data, 54 | cipher=block_cipher 55 | ) 56 | 57 | exe = EXE( 58 | pyz, 59 | a.scripts, 60 | exclude_binaries=True, 61 | name='main', 62 | debug=False, 63 | strip=False, 64 | upx=True, 65 | console=True 66 | ) 67 | 68 | coll = COLLECT( 69 | exe, 70 | a.binaries, 71 | a.zipfiles, 72 | a.datas, 73 | strip=False, 74 | upx=True, 75 | name='main' 76 | ) 77 | 78 | Notice the ``Analysis`` section, it contains details for what Python related 79 | files to collect e.g. the ``main.py`` file. For PyJNIus to work you need to 80 | include the ``jnius_config`` module to the ``hiddenimports`` list, otherwise 81 | you will get a ``ImportError: No module named jnius_config``:: 82 | 83 | ... 84 | 85 | a = Analysis( 86 | ['main.py'], 87 | pathex=[''], 88 | binaries=None, 89 | datas=None, 90 | hiddenimports=['jnius_config'], 91 | hookspath=[], 92 | runtime_hooks=[], 93 | excludes=[], 94 | win_no_prefer_redirects=False, 95 | win_private_assemblies=False, 96 | cipher=block_cipher 97 | ) 98 | 99 | ... 100 | 101 | After the ``.spec`` file is ready, in our case it's by default called by the 102 | name of the ``.py`` file, we need to direct PyInstaller to use that file:: 103 | 104 | pyinstaller main.spec 105 | 106 | This will create a folder with all required ``.dll`` and ``.pyd`` or ``.so`` 107 | shared libraries and other necessary files for our application and for Python 108 | itself. 109 | 110 | Running 111 | ------- 112 | 113 | We have the application ready, but the "problem" is PyJNIus doesn't detect 114 | any installed Java on your computer (yet). Therefore if you try to run the 115 | application, it'll crash with a ``ImportError: DLL load failed: ...``. 116 | For this simple example if you can see ``jnius.jnius.pyd`` or 117 | ``jnius.jnius.so`` in the final folder with ``main.exe`` (or just ``main``), 118 | the error indicates that the application could not find Java Virtual Machine. 119 | 120 | The Java Virtual Machine is in simple terms said another necessary shared 121 | library your application needs to load (``jvm.dll`` or ``libjvm.so``). 122 | 123 | On Windows this file might be in a folder similar to this:: 124 | 125 | C:\Program Files\Java\jdk1.7.0_79\jre\bin\server 126 | 127 | and you need to include the folder to the system ``PATH`` environment variable 128 | with this command:: 129 | 130 | set PATH=%PATH%;C:\\Program Files\\Java\\jdk1.7.0_79\\jre\\bin\\server 131 | 132 | After the ``jvm.dll`` or ``libjvm.so`` becomes available, you can safely 133 | try to run your application:: 134 | 135 | main.exe 136 | 137 | and you should get an output similar to this:: 138 | 139 | C:\Program Files\Java\jdk1.7.0_79\jre 140 | -------------------------------------------------------------------------------- /docs/source/quickstart.rst: -------------------------------------------------------------------------------- 1 | .. _quickstart: 2 | 3 | Quickstart 4 | ========== 5 | 6 | Eager to get started? This page will give you a good introduction to Pyjnius. It assumes 7 | you have already PyJNIus installed. If you do not, ensure you have a Java JDK installed, 8 | then try `pip install pyjnius` - you can head over to the :ref:`installation` section 9 | for more information. 10 | 11 | A minimal example 12 | ----------------- 13 | 14 | A minimal PyJNIus example looks something like this:: 15 | 16 | from jnius import autoclass 17 | 18 | Stack = autoclass('java.util.Stack') 19 | stack = Stack() 20 | stack.push('hello') 21 | stack.push('world') 22 | 23 | print(stack.pop()) # --> 'world' 24 | print(stack.pop()) # --> 'hello' 25 | 26 | Just save it as `test.py` (or something similar) and run it with your Python 27 | interpreter. Make sure not to call your application `jnius.py` because it would 28 | conflict with PyJNIus itself:: 29 | 30 | $ python test.py 31 | world 32 | hello 33 | 34 | To load nested java classes, use the "$" separator as so:: 35 | 36 | version = autoclass("android.os.Build$VERSION") 37 | base_os = version.BASE_OS 38 | 39 | 40 | Automatic recursive inspection 41 | ------------------------------ 42 | 43 | PyJNIus uses Java reflection to give you a new autoclass() if the return type is 44 | not a native type. Let's see this example:: 45 | 46 | System = autoclass('java.lang.System') 47 | System.out.println('Hello World') 48 | 49 | We only declared the first System class, but we are able to use all the static 50 | fields and methods naturally. Let's go deeper:: 51 | 52 | >>> System = autoclass('java.lang.System') 53 | >>> System 54 | 55 | >>> System.out 56 | 57 | >>> System.out.println 58 | 59 | 60 | The recursive reflection always gives you an appropriate object that reflects the 61 | returned Java object. 62 | -------------------------------------------------------------------------------- /examples/arraylists/arraylist.java: -------------------------------------------------------------------------------- 1 | // javac arraylist.java 2 | // java arraylist 3 | 4 | import java.lang.String; 5 | import java.util.List; 6 | import java.util.Arrays; 7 | import java.util.ArrayList; 8 | 9 | 10 | public class arraylist { 11 | public static void main(String[] args) { 12 | // Object based empty ArrayList 13 | ArrayList jlist = new ArrayList(); 14 | System.out.println(jlist); 15 | System.out.println(jlist.size()); 16 | 17 | // String array 18 | String[] str_array = {"a", "b", "c"}; 19 | System.out.println(str_array.toString()); 20 | System.out.println(str_array.length); 21 | 22 | // add the array of strings to the list 23 | jlist.add(str_array); 24 | System.out.println(jlist.toString()); 25 | System.out.println(jlist.size()); 26 | 27 | // create a new ArrayList from String array 28 | ArrayList str_list = new ArrayList( 29 | Arrays.asList(str_array.toString()) 30 | ); 31 | jlist.add(str_list); 32 | System.out.println(jlist.toString()); 33 | System.out.println(jlist.size()); 34 | 35 | // add an empty Object to ArrayList 36 | jlist.add(new Object()); 37 | System.out.println(jlist.toString()); 38 | System.out.println(jlist.size()); 39 | 40 | // new ArrayList to wrap everything up 41 | ArrayList plain_list = new ArrayList(); 42 | plain_list.add(str_array); 43 | plain_list.add(str_list); 44 | plain_list.add(jlist); 45 | System.out.println(plain_list.toString()); 46 | System.out.println(plain_list.size()); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /examples/arraylists/arraylist.py: -------------------------------------------------------------------------------- 1 | # pylint: disable=invalid-name 2 | ''' 3 | Example of nested ArrayList and passing empty tuple/list to Java functions. 4 | ''' 5 | 6 | from __future__ import unicode_literals, print_function 7 | from jnius import autoclass, cast # pylint: disable=import-error 8 | 9 | String = autoclass('java.lang.String') 10 | List = autoclass('java.util.List') 11 | Arrays = autoclass('java.util.Arrays') 12 | ArrayList = autoclass('java.util.ArrayList') 13 | JavaArray = autoclass('java.lang.reflect.Array') 14 | Object = autoclass('java.lang.Object') 15 | 16 | 17 | def sep_print(*args): 18 | ''' 19 | Separate args because in <80char console (e.g. Windows) 20 | is the output barely readable with [[, @, ;, ,, ... 21 | ''' 22 | print(*args) 23 | print('-' * 10) 24 | 25 | 26 | # Object based empty ArrayList 27 | jlist = ArrayList() 28 | sep_print(jlist, jlist.toString(), len(jlist)) 29 | 30 | # String array 31 | str_array = JavaArray.newInstance(String, 3) 32 | for i, item in enumerate(('a', 'b', 'c')): 33 | str_array[i] = String(item) 34 | sep_print(str_array, len(str_array)) 35 | 36 | # add the array of strings to the list 37 | jlist.add(str_array) 38 | sep_print(jlist, jlist.toString(), len(jlist)) 39 | 40 | # create a new ArrayList from String array 41 | str_list = ArrayList(Arrays.asList(str_array)) 42 | jlist.add(str_list) 43 | sep_print(jlist, jlist.toString(), len(jlist)) 44 | 45 | # add an empty Object to ArrayList 46 | jlist.add(Object()) 47 | sep_print(jlist, jlist.toString(), len(jlist)) 48 | 49 | # new ArrayList to wrap everything up 50 | plain_list = ArrayList() 51 | plain_list.add(str_array) 52 | plain_list.add(str_list) 53 | plain_list.add(jlist) 54 | sep_print(plain_list, plain_list.toString(), len(plain_list)) 55 | -------------------------------------------------------------------------------- /jnius/__init__.py: -------------------------------------------------------------------------------- 1 | ''' 2 | PyJNIus 3 | ======= 4 | 5 | Accessing Java classes from Python. 6 | 7 | All the documentation is available at: http://pyjnius.readthedocs.org 8 | ''' 9 | 10 | __version__ = '1.6.1' 11 | 12 | from .env import get_java_setup 13 | 14 | import os 15 | import sys 16 | if sys.platform == 'win32' and sys.version_info >= (3, 8): 17 | path = os.path.dirname(__file__) 18 | java = get_java_setup(sys.platform) 19 | jdk_home = java.get_javahome() 20 | with os.add_dll_directory(path): 21 | for suffix in ( 22 | ('bin', 'client'), 23 | ('bin', 'server'), 24 | ('bin', 'default'), 25 | ('jre', 'bin', 'client'), 26 | ('jre', 'bin', 'server'), 27 | ('jre', 'bin', 'default'), 28 | ): 29 | path = os.path.join(jdk_home, *suffix) 30 | if not os.path.isdir(path): 31 | continue 32 | 33 | with os.add_dll_directory(path): 34 | try: 35 | from .jnius import * # noqa 36 | from .reflect import * # noqa 37 | except Exception as e: 38 | pass 39 | else: 40 | break 41 | else: 42 | raise Exception("Unable to create jni env, no jvm dll found.") 43 | else: 44 | from .jnius import * # noqa 45 | from .reflect import * # noqa 46 | 47 | # XXX monkey patch methods that cannot be in cython. 48 | # Cython doesn't allow to set new attribute on methods it compiled 49 | 50 | HASHCODE_MAX = 2 ** 31 - 1 51 | 52 | 53 | class PythonJavaClass_(PythonJavaClass, metaclass=MetaJavaBase): 54 | 55 | @java_method('()I', name='hashCode') 56 | def hashCode(self): 57 | return id(self) % HASHCODE_MAX 58 | 59 | @java_method('()Ljava/lang/String;', name='hashCode') 60 | def hashCode_(self): 61 | return '{}'.format(self.hashCode()) 62 | 63 | @java_method('()Ljava/lang/String;', name='toString') 64 | def toString(self): 65 | return repr(self) 66 | 67 | @java_method('(Ljava/lang/Object;)Z', name='equals') 68 | def equals(self, other): 69 | return self.hashCode() == other.hashCode() 70 | 71 | 72 | PythonJavaClass = PythonJavaClass_ 73 | 74 | 75 | # from https://gist.github.com/tito/09c42fb4767721dc323d 76 | import os 77 | if "ANDROID_ARGUMENT" in os.environ: 78 | # on android, catch all exception to ensure about a jnius.detach 79 | import threading 80 | import jnius 81 | orig_thread_run = threading.Thread.run 82 | 83 | def jnius_thread_hook(*args, **kwargs): 84 | try: 85 | return orig_thread_run(*args, **kwargs) 86 | finally: 87 | jnius.detach() 88 | 89 | threading.Thread.run = jnius_thread_hook 90 | -------------------------------------------------------------------------------- /jnius/jnius.pyx: -------------------------------------------------------------------------------- 1 | 2 | ''' 3 | Java wrapper 4 | ============ 5 | 6 | With this module, you can create Python class that reflects a Java class, and use 7 | it directly in Python. 8 | 9 | Example with static method 10 | -------------------------- 11 | 12 | Java:: 13 | 14 | package org.test; 15 | public class Hardware { 16 | static int getDPI() { 17 | return metrics.densityDpi; 18 | } 19 | } 20 | 21 | Python:: 22 | 23 | class Hardware(JavaClass): 24 | __metaclass__ = MetaJavaClass 25 | __javaclass__ = 'org/test/Hardware' 26 | getDPI = JavaStaticMethod('()I') 27 | 28 | Hardware.getDPI() 29 | 30 | 31 | Example with instance method 32 | ---------------------------- 33 | 34 | Java:: 35 | 36 | package org.test; 37 | public class Action { 38 | public String getName() { 39 | return new String("Hello world") 40 | } 41 | } 42 | 43 | Python:: 44 | 45 | class Action(JavaClass): 46 | __metaclass__ = MetaJavaClass 47 | __javaclass__ = 'org/test/Action' 48 | getName = JavaMethod('()Ljava/lang/String;') 49 | 50 | action = Action() 51 | print action.getName() 52 | # will output Hello World 53 | 54 | 55 | Example with static/instance field 56 | ---------------------------------- 57 | 58 | Java:: 59 | 60 | package org.test; 61 | public class Test { 62 | public static String field1 = new String("hello"); 63 | public String field2; 64 | 65 | public Test() { 66 | this.field2 = new String("world"); 67 | } 68 | } 69 | 70 | Python:: 71 | 72 | class Test(JavaClass): 73 | __metaclass__ = MetaJavaClass 74 | __javaclass__ = 'org/test/Test' 75 | 76 | field1 = JavaStaticField('Ljava/lang/String;') 77 | field2 = JavaField('Ljava/lang/String;') 78 | 79 | # access directly to the static field 80 | print Test.field1 81 | 82 | # create the instance, and access to the instance field 83 | test = Test() 84 | print test.field2 85 | 86 | ''' 87 | 88 | __all__ = ('JavaObject', 'JavaClass', 'JavaMethod', 'JavaField', 89 | 'JavaStaticMethod', 'JavaStaticField', 'JavaMultipleMethod', 90 | 'MetaJavaBase', 'MetaJavaClass', 'JavaException', 'cast', 91 | 'find_javaclass', 'PythonJavaClass', 'java_method', 'detach') 92 | 93 | from libc.stdlib cimport malloc, free 94 | from functools import partial 95 | import sys 96 | import traceback 97 | 98 | include "jnius_compat.pxi" 99 | include "jni.pxi" 100 | include "config.pxi" 101 | 102 | IF JNIUS_PLATFORM == "android": 103 | include "jnius_jvm_android.pxi" 104 | ELIF JNIUS_PLATFORM == "win32": 105 | include "jnius_jvm_desktop.pxi" 106 | ELSE: 107 | include "jnius_jvm_dlopen.pxi" 108 | 109 | # from Cython 3.0, in the MetaJavaClass, this is accessed as _JavaClass__cls_storage 110 | # see https://cython.readthedocs.io/en/latest/src/userguide/migrating_to_cy30.html#class-private-name-mangling 111 | cdef CLS_STORAGE_NAME = '_JavaClass__cls_storage' if JNIUS_CYTHON_3 else '__cls_storage' 112 | 113 | include "jnius_env.pxi" 114 | include "jnius_utils.pxi" 115 | include "jnius_conversion.pxi" 116 | include "jnius_localref.pxi" 117 | 118 | include "jnius_nativetypes3.pxi" 119 | 120 | include "jnius_export_func.pxi" 121 | include "jnius_export_class.pxi" 122 | 123 | include "jnius_proxy.pxi" 124 | -------------------------------------------------------------------------------- /jnius/jnius_compat.pxi: -------------------------------------------------------------------------------- 1 | ''' 2 | Handle Python 2 vs 3 differences here. 3 | ''' 4 | 5 | # because Cython's basestring doesn't work with isinstance() properly 6 | # and has differences between Python 2 and Python 3 runtime behavior 7 | # so it's not really usable unless some bug in the upstream is fixed 8 | # (tested with Cython==0.29.2) 9 | cdef tuple base_string = (bytes, str) 10 | 11 | 12 | cdef unicode to_unicode(object arg): 13 | ''' 14 | Accept full object as a type to prevent py2/py3 differences 15 | and throw an exception in case of misusing this function. 16 | ''' 17 | 18 | if not isinstance(arg, base_string): 19 | raise JavaException( 20 | 'Argument {!r} is not of a text type.'.format(arg) 21 | ) 22 | 23 | cdef unicode result 24 | if isinstance(arg, bytes): 25 | result = (arg).decode('utf-8') 26 | else: 27 | result = arg 28 | return result 29 | -------------------------------------------------------------------------------- /jnius/jnius_env.pxi: -------------------------------------------------------------------------------- 1 | 2 | cdef JNIEnv *default_env = NULL 3 | 4 | cdef extern int gettid() 5 | cdef JavaVM *jvm = NULL 6 | 7 | cdef JNIEnv *get_jnienv() except NULL: 8 | global default_env 9 | # first call, init. 10 | if default_env == NULL: 11 | default_env = get_platform_jnienv() 12 | if default_env == NULL: 13 | return NULL 14 | default_env[0].GetJavaVM(default_env, &jvm) 15 | 16 | # return the current env attached to the thread 17 | # XXX it threads are created from C (not java), we'll leak here. 18 | cdef JNIEnv *env = NULL 19 | jvm[0].AttachCurrentThread(jvm, &env, NULL) 20 | return env 21 | 22 | 23 | def detach(): 24 | jvm[0].DetachCurrentThread(jvm) 25 | 26 | -------------------------------------------------------------------------------- /jnius/jnius_export_func.pxi: -------------------------------------------------------------------------------- 1 | def cast(destclass, obj): 2 | cdef JavaClass jc 3 | cdef JavaClass jobj = obj 4 | from .reflect import autoclass 5 | if isinstance(destclass, str): 6 | jc = autoclass(destclass)(noinstance=True) 7 | else: 8 | jc = destclass(noinstance=True) 9 | jc.instanciate_from(jobj.j_self) 10 | return jc 11 | 12 | 13 | def find_javaclass(namestr): 14 | namestr = namestr.replace('.', '/') 15 | cdef bytes name = str_for_c(namestr) 16 | from .reflect import Class 17 | cdef JavaClass cls 18 | cdef jclass jc 19 | cdef JNIEnv *j_env = get_jnienv() 20 | 21 | jc = j_env[0].FindClass(j_env, name) 22 | check_exception(j_env) 23 | 24 | cls = Class(noinstance=True) 25 | cls.instanciate_from(create_local_ref(j_env, jc)) 26 | j_env[0].DeleteLocalRef(j_env, jc) 27 | return cls 28 | 29 | -------------------------------------------------------------------------------- /jnius/jnius_jvm_android.pxi: -------------------------------------------------------------------------------- 1 | # on android, rely on SDL to get the JNI env 2 | cdef extern JNIEnv *SDL_AndroidGetJNIEnv() 3 | 4 | 5 | cdef JNIEnv *get_platform_jnienv() except NULL: 6 | return SDL_AndroidGetJNIEnv() 7 | -------------------------------------------------------------------------------- /jnius/jnius_jvm_desktop.pxi: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | from os.path import join 4 | from jnius.env import get_java_setup 5 | 6 | # on desktop, we need to create an env :) 7 | # example taken from http://www.inonit.com/cygwin/jni/invocationApi/c.html 8 | 9 | cdef extern jint __stdcall JNI_CreateJavaVM(JavaVM **pvm, void **penv, void *args) 10 | cdef extern from "jni.h": 11 | int JNI_VERSION_1_4 12 | int JNI_OK 13 | jboolean JNI_FALSE 14 | ctypedef struct JavaVMInitArgs: 15 | jint version 16 | jint nOptions 17 | jboolean ignoreUnrecognized 18 | JavaVMOption *options 19 | ctypedef struct JavaVMOption: 20 | char *optionString 21 | void *extraInfo 22 | 23 | cdef JNIEnv *_platform_default_env = NULL 24 | 25 | cdef void create_jnienv() except *: 26 | cdef JavaVM* jvm 27 | cdef JavaVMInitArgs args 28 | cdef JavaVMOption *options 29 | cdef int ret 30 | cdef bytes py_bytes 31 | import jnius_config 32 | 33 | optarr = jnius_config.options 34 | cp = jnius_config.expand_classpath() 35 | optarr.append("-Djava.class.path={0}".format(cp)) 36 | 37 | optarr = [str_for_c(x) for x in optarr] 38 | options = malloc(sizeof(JavaVMOption) * len(optarr)) 39 | for i, opt in enumerate(optarr): 40 | options[i].optionString = (opt) 41 | options[i].extraInfo = NULL 42 | 43 | args.version = JNI_VERSION_1_4 44 | args.options = options 45 | args.nOptions = len(optarr) 46 | args.ignoreUnrecognized = JNI_FALSE 47 | 48 | attempted = [] 49 | if sys.version_info >= (3, 8): 50 | # uh, let's see if this works and cleanup later 51 | java = get_java_setup('win32') 52 | jdk_home = java.get_javahome() 53 | for suffix in ( 54 | ('bin', 'client'), 55 | ('bin', 'server'), 56 | ('bin', 'default'), 57 | ('jre', 'bin', 'client'), 58 | ('jre', 'bin', 'server'), 59 | ('jre', 'bin', 'default'), 60 | ): 61 | path = join(jdk_home, *suffix) 62 | if not os.path.isdir(path): 63 | continue 64 | with os.add_dll_directory(path): 65 | attempted.append(path) 66 | try: 67 | ret = JNI_CreateJavaVM(&jvm, &_platform_default_env, &args) 68 | except Exception as e: 69 | pass 70 | else: 71 | break 72 | else: 73 | if len(attempted) > 0: 74 | raise Exception("Unable to create jni env, no jvm dll found in %s" % str(attempted)) 75 | else: 76 | raise Exception("Unable to create jni env, no valid java library paths were found in %s, perhaps you need to update JAVA_HOME" % jdk_home) 77 | else: 78 | ret = JNI_CreateJavaVM(&jvm, &_platform_default_env, &args) 79 | 80 | free(options) 81 | 82 | if ret != JNI_OK: 83 | raise SystemError("JVM failed to start") 84 | 85 | jnius_config.vm_running = True 86 | import traceback 87 | jnius_config.vm_started_at = ''.join(traceback.format_stack()) 88 | 89 | cdef JNIEnv *get_platform_jnienv() except NULL: 90 | if _platform_default_env == NULL: 91 | create_jnienv() 92 | return _platform_default_env 93 | -------------------------------------------------------------------------------- /jnius/jnius_jvm_dlopen.pxi: -------------------------------------------------------------------------------- 1 | include "config.pxi" 2 | import os 3 | from shlex import split 4 | from subprocess import check_output, CalledProcessError 5 | from os.path import dirname, join, exists 6 | from os import readlink 7 | from sys import platform 8 | from .env import get_java_setup 9 | 10 | 11 | cdef extern from 'dlfcn.h' nogil: 12 | void* dlopen(const char *filename, int flag) 13 | char *dlerror() 14 | void *dlsym(void *handle, const char *symbol) 15 | int dlclose(void *handle) 16 | 17 | unsigned int RTLD_LAZY 18 | unsigned int RTLD_NOW 19 | unsigned int RTLD_GLOBAL 20 | unsigned int RTLD_LOCAL 21 | unsigned int RTLD_NODELETE 22 | unsigned int RTLD_NOLOAD 23 | unsigned int RTLD_DEEPBIND 24 | 25 | unsigned int RTLD_DEFAULT 26 | long unsigned int RTLD_NEXT 27 | 28 | 29 | cdef extern from "jni.h": 30 | int JNI_VERSION_1_6 31 | int JNI_OK 32 | jboolean JNI_FALSE 33 | ctypedef struct JavaVMInitArgs: 34 | jint version 35 | jint nOptions 36 | jboolean ignoreUnrecognized 37 | JavaVMOption *options 38 | ctypedef struct JavaVMOption: 39 | char *optionString 40 | void *extraInfo 41 | 42 | cdef JNIEnv *_platform_default_env = NULL 43 | 44 | 45 | cdef void create_jnienv() except *: 46 | cdef JavaVM* jvm 47 | cdef JavaVMInitArgs args 48 | cdef JavaVMOption *options 49 | cdef int ret 50 | cdef bytes py_bytes 51 | cdef void *handle 52 | import jnius_config 53 | 54 | JAVA_LOCATION = get_java_setup() 55 | cdef str java_lib = JAVA_LOCATION.get_jnius_lib_location() 56 | 57 | lib_path = str_for_c(java_lib) 58 | 59 | handle = dlopen(lib_path, RTLD_NOW | RTLD_GLOBAL) 60 | 61 | if handle == NULL: 62 | raise SystemError("Error calling dlopen({0}): {1}".format(lib_path, dlerror())) 63 | 64 | cdef void *jniCreateJVM = dlsym(handle, b"JNI_CreateJavaVM") 65 | 66 | if jniCreateJVM == NULL: 67 | raise SystemError("Error calling dlfcn for JNI_CreateJavaVM: {0}".format(dlerror())) 68 | 69 | optarr = jnius_config.options 70 | optarr.append("-Djava.class.path=" + jnius_config.expand_classpath()) 71 | 72 | optarr = [str_for_c(x) for x in optarr] 73 | options = malloc(sizeof(JavaVMOption) * len(optarr)) 74 | for i, opt in enumerate(optarr): 75 | options[i].optionString = (opt) 76 | options[i].extraInfo = NULL 77 | 78 | args.version = JNI_VERSION_1_6 79 | args.options = options 80 | args.nOptions = len(optarr) 81 | args.ignoreUnrecognized = JNI_FALSE 82 | 83 | ret = ( jniCreateJVM)(&jvm, &_platform_default_env, &args) 84 | free(options) 85 | 86 | if ret != JNI_OK: 87 | raise SystemError("JVM failed to start: {0}".format(ret)) 88 | 89 | jnius_config.vm_running = True 90 | import traceback 91 | jnius_config.vm_started_at = ''.join(traceback.format_stack()) 92 | 93 | cdef JNIEnv *get_platform_jnienv() except NULL: 94 | if _platform_default_env == NULL: 95 | create_jnienv() 96 | return _platform_default_env 97 | -------------------------------------------------------------------------------- /jnius/jnius_localref.pxi: -------------------------------------------------------------------------------- 1 | cdef class LocalRef: 2 | cdef jobject obj 3 | 4 | def __cinit__(self): 5 | self.obj = NULL 6 | 7 | def __dealloc__(self): 8 | cdef JNIEnv *j_env 9 | if self.obj != NULL: 10 | j_env = get_jnienv() 11 | j_env[0].DeleteGlobalRef(j_env, self.obj) 12 | self.obj = NULL 13 | 14 | cdef void create(self, JNIEnv *env, jobject obj) except *: 15 | self.obj = env[0].NewGlobalRef(env, obj) 16 | 17 | def __repr__(self): 18 | return ''.format( 19 | self.obj, id(self)) 20 | 21 | 22 | cdef LocalRef create_local_ref(JNIEnv *env, jobject obj): 23 | cdef LocalRef ret = LocalRef() 24 | ret.create(env, obj) 25 | return ret 26 | 27 | -------------------------------------------------------------------------------- /jnius/jnius_nativetypes3.pxi: -------------------------------------------------------------------------------- 1 | 2 | cdef python_op(int op, object a, object b): 3 | if op == 0: 4 | return a < b 5 | elif op == 1: 6 | return a <= b 7 | elif op == 2: 8 | return a == b 9 | elif op == 3: 10 | return a >= b 11 | elif op == 4: 12 | return a > b 13 | elif op == 5: 14 | return a != b 15 | 16 | cdef class ByteArray: 17 | cdef LocalRef _jobject 18 | cdef long _size 19 | cdef unsigned char *_buf 20 | cdef unsigned char[:] _arr 21 | 22 | def __cinit__(self): 23 | self._size = 0 24 | self._buf = NULL 25 | self._arr = None 26 | 27 | def __dealloc__(self): 28 | cdef JNIEnv *j_env 29 | if self._buf != NULL: 30 | j_env = get_jnienv() 31 | j_env[0].ReleaseByteArrayElements( 32 | j_env, self._jobject.obj, self._buf, 0) 33 | self._buf = NULL 34 | self._jobject = None 35 | 36 | cdef void set_buffer(self, JNIEnv *env, jobject obj, long size, jbyte *buf) except *: 37 | if self._buf != NULL: 38 | raise Exception('Cannot call set_buffer() twice.') 39 | self._jobject = LocalRef() 40 | self._jobject.create(env, obj) 41 | self._size = size 42 | self._buf = buf 43 | if size: 44 | self._arr = self._buf 45 | 46 | def __str__(self): 47 | return ''.format( 48 | self._size, id(self)) 49 | 50 | def __len__(self): 51 | return self._size 52 | 53 | def __getitem__(self, index): 54 | cdef long xx 55 | if isinstance(index, slice): 56 | val = [] 57 | if self._size: 58 | (start, stop, step) = index.indices(len(self._arr)) 59 | for x in range(start, stop, step): 60 | xx = x 61 | val.append(self._arr[xx]) 62 | return val 63 | else: 64 | xx = index 65 | return self._arr[xx] 66 | 67 | def __richcmp__(self, other, op): 68 | cdef ByteArray b_other 69 | if isinstance(other, (list, tuple)): 70 | return python_op(op, self.tolist(), other) 71 | elif isinstance(other, ByteArray): 72 | b_other = other 73 | return python_op(op, self.tostring(), other.tostring()) 74 | else: 75 | return False 76 | 77 | def tolist(self): 78 | return list(self[:]) 79 | 80 | def tostring(self): 81 | return self._buf[:self._size] 82 | -------------------------------------------------------------------------------- /jnius/jnius_proxy.pxi: -------------------------------------------------------------------------------- 1 | class java_method(object): 2 | def __init__(self, signature, name=None): 3 | super(java_method, self).__init__() 4 | self.signature = signature 5 | self.name = name 6 | 7 | def __get__(self, instance, instancetype): 8 | return partial(self.__call__, instance) 9 | 10 | def __call__(self, f): 11 | f.__javasignature__ = self.signature 12 | f.__javaname__ = self.name 13 | return f 14 | 15 | 16 | cdef class PythonJavaClass(object): 17 | ''' 18 | Base class to create a java class from python 19 | ''' 20 | cdef jclass j_cls 21 | cdef public object j_self 22 | 23 | def __cinit__(self, *args): 24 | self.j_cls = NULL 25 | self.j_self = None 26 | 27 | def __init__(self, *args, **kwargs): 28 | self._init_j_self_ptr() 29 | 30 | def _init_j_self_ptr(self): 31 | javacontext = 'system' 32 | if hasattr(self, '__javacontext__'): 33 | javacontext = self.__javacontext__ 34 | self.j_self = create_proxy_instance(get_jnienv(), self, 35 | self.__javainterfaces__, javacontext) 36 | 37 | # discover all the java method implemented 38 | self.__javamethods__ = {} 39 | for x in dir(self): 40 | attr = getattr(self, x) 41 | if not callable(attr): 42 | continue 43 | if not hasattr(attr, '__javasignature__'): 44 | continue 45 | signature = parse_definition(attr.__javasignature__) 46 | self.__javamethods__[(attr.__javaname__ or x, signature)] = attr 47 | 48 | def invoke(self, method, *args): 49 | try: 50 | ret = self._invoke(method, *args) 51 | return ret 52 | except Exception: 53 | traceback.print_exc() 54 | return None 55 | 56 | def _invoke(self, method, *args): 57 | from .reflect import get_signature 58 | # search the java method 59 | 60 | ret_signature = get_signature(method.getReturnType()) 61 | args_signature = tuple([get_signature(x) for x in method.getParameterTypes()]) 62 | method_name = method.getName() 63 | 64 | key = (method_name, (ret_signature, args_signature)) 65 | 66 | py_method = self.__javamethods__.get(key, None) 67 | if not py_method: 68 | print(''.join([ 69 | '\n===== Python/java method missing ======', 70 | '\nPython class:', repr(self), 71 | '\nJava method name:', method_name, 72 | '\nSignature: ({}){}'.format(''.join(args_signature), ret_signature), 73 | '\n=======================================\n'])) 74 | raise NotImplementedError('The method {} is not implemented'.format(key)) 75 | 76 | return py_method(*args) 77 | 78 | 79 | cdef jobject py_invoke0(JNIEnv *j_env, jobject j_this, jobject j_proxy, jobject 80 | j_method, jobjectArray args) except * with gil: 81 | 82 | from .reflect import get_signature, Method 83 | cdef jfieldID ptrField 84 | cdef jlong jptr 85 | cdef object py_obj 86 | cdef JavaClass method 87 | cdef jobject j_arg 88 | 89 | # get the python object 90 | ptrField = j_env[0].GetFieldID(j_env, 91 | j_env[0].GetObjectClass(j_env, j_this), "ptr", "J") 92 | jptr = j_env[0].GetLongField(j_env, j_this, ptrField) 93 | py_obj = jptr 94 | 95 | # extract the method information 96 | method = Method(noinstance=True) 97 | method.instanciate_from(create_local_ref(j_env, j_method)) 98 | ret_signature = get_signature(method.getReturnType()) 99 | args_signature = [get_signature(x) for x in method.getParameterTypes()] 100 | 101 | # convert java argument to python object 102 | # native java type are given with java.lang.*, even if the signature say 103 | # it's a native type. 104 | py_args = [] 105 | convert_signature = { 106 | 'Z': 'Ljava/lang/Boolean;', 107 | 'B': 'Ljava/lang/Byte;', 108 | 'C': 'Ljava/lang/Character;', 109 | 'S': 'Ljava/lang/Short;', 110 | 'I': 'Ljava/lang/Integer;', 111 | 'J': 'Ljava/lang/Long;', 112 | 'F': 'Ljava/lang/Float;', 113 | 'D': 'Ljava/lang/Double;'} 114 | 115 | for index, arg_signature in enumerate(args_signature): 116 | arg_signature = convert_signature.get(arg_signature, arg_signature) 117 | j_arg = j_env[0].GetObjectArrayElement(j_env, args, index) 118 | py_arg = convert_jobject_to_python(j_env, arg_signature, j_arg) 119 | j_env[0].DeleteLocalRef(j_env, j_arg) 120 | py_args.append(py_arg) 121 | 122 | # really invoke the python method 123 | name = method.getName() 124 | ret = py_obj.invoke(method, *py_args) 125 | 126 | # convert back to the return type 127 | # use the populate_args(), but in the reverse way :) 128 | t = ret_signature[:1] 129 | 130 | # did python returned a "native" type ? 131 | jtype = None 132 | 133 | if ret_signature == 'Ljava/lang/Object;': 134 | # generic object, try to manually convert it 135 | tp = type(ret) 136 | if tp == int: 137 | jtype = 'J' 138 | elif tp == float: 139 | jtype = 'D' 140 | elif tp == bool: 141 | jtype = 'Z' 142 | elif len(ret_signature) == 1: 143 | jtype = ret_signature 144 | 145 | try: 146 | return convert_python_to_jobject(j_env, jtype or ret_signature, ret) 147 | except Exception: 148 | traceback.print_exc() 149 | 150 | 151 | cdef jobject invoke0(JNIEnv *j_env, jobject j_this, jobject j_proxy, jobject 152 | j_method, jobjectArray args) with gil: 153 | try: 154 | return py_invoke0(j_env, j_this, j_proxy, j_method, args) 155 | except Exception: 156 | traceback.print_exc() 157 | return NULL 158 | 159 | # now we need to create a proxy and pass it an invocation handler 160 | cdef create_proxy_instance(JNIEnv *j_env, py_obj, j_interfaces, javacontext): 161 | from .reflect import autoclass 162 | Proxy = autoclass('java.lang.reflect.Proxy') 163 | NativeInvocationHandler = autoclass('org.jnius.NativeInvocationHandler') 164 | 165 | # convert strings to Class 166 | j_interfaces = [find_javaclass(x) for x in j_interfaces] 167 | 168 | cdef JavaClass nih = NativeInvocationHandler(py_obj) 169 | cdef JNINativeMethod invoke_methods[1] 170 | invoke_methods[0].name = 'invoke0' 171 | invoke_methods[0].signature = '(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;' 172 | invoke_methods[0].fnPtr = &invoke0 173 | j_env[0].RegisterNatives(j_env, nih.j_cls, invoke_methods, 1) 174 | 175 | # create the proxy and pass it the invocation handler 176 | cdef JavaClass j_obj 177 | if javacontext == 'app': 178 | Thread = autoclass('java.lang.Thread') 179 | classLoader = Thread.currentThread().getContextClassLoader() 180 | j_obj = Proxy.newProxyInstance( 181 | classLoader, j_interfaces, nih) 182 | 183 | elif javacontext == 'system': 184 | ClassLoader = autoclass('java.lang.ClassLoader') 185 | classLoader = ClassLoader.getSystemClassLoader() 186 | j_obj = Proxy.newProxyInstance( 187 | classLoader, j_interfaces, nih) 188 | 189 | else: 190 | raise Exception( 191 | 'Invalid __javacontext__ {}, must be app or system.'.format( 192 | javacontext)) 193 | 194 | return j_obj 195 | -------------------------------------------------------------------------------- /jnius/signatures.py: -------------------------------------------------------------------------------- 1 | ''' 2 | signatures.py 3 | ============= 4 | 5 | A handy API for writing JNI signatures easily 6 | 7 | Author: chrisjrn 8 | 9 | This module aims to provide a more human-friendly API for 10 | wiring up Java proxy methods in PyJnius. 11 | 12 | You can use the signature function to produce JNI method 13 | signautures for methods; passing PyJnius JavaClass classes 14 | as return or argument types; provided here are annotations 15 | representing Java's primitive and array times. 16 | 17 | Methods can return just a standard primitive type: 18 | 19 | >>> signature(jint, ()) 20 | '()I' 21 | 22 | >>> s.signature(jvoid, [jint]) 23 | '(I)V' 24 | 25 | Or you can use autoclass proxies to specify Java classes 26 | for return types. 27 | 28 | >>> from jnius import autoclass 29 | >>> String = autoclass("java.lang.String") 30 | >>> signature(String, ()) 31 | '()Ljava/lang/String;' 32 | 33 | ''' 34 | 35 | __version__ = '0.0.1' 36 | 37 | from . import JavaClass 38 | from . import java_method 39 | 40 | 41 | ''' Type specifiers for primitives ''' 42 | 43 | 44 | class _JavaSignaturePrimitive(object): 45 | _spec = "" 46 | 47 | 48 | def _MakeSignaturePrimitive(name, spec): 49 | class __Primitive(_JavaSignaturePrimitive): 50 | ''' PyJnius signature for Java %s type ''' % name 51 | _name = name 52 | _spec = spec 53 | __Primitive.__name__ = "j" + name 54 | 55 | return __Primitive 56 | 57 | 58 | jboolean = _MakeSignaturePrimitive("boolean", "Z") 59 | jbyte = _MakeSignaturePrimitive("byte", "B") 60 | jchar = _MakeSignaturePrimitive("char", "C") 61 | jdouble = _MakeSignaturePrimitive("double", "D") 62 | jfloat = _MakeSignaturePrimitive("float", "F") 63 | jint = _MakeSignaturePrimitive("int", "I") 64 | jlong = _MakeSignaturePrimitive("long", "J") 65 | jshort = _MakeSignaturePrimitive("short", "S") 66 | jvoid = _MakeSignaturePrimitive("void", "V") 67 | 68 | 69 | def JArray(of_type): 70 | ''' Signature helper for identifying arrays of a given object or 71 | primitive type. ''' 72 | 73 | spec = "[" + _jni_type_spec(of_type) 74 | return _MakeSignaturePrimitive("array", spec) 75 | 76 | 77 | def with_signature(returns, takes): 78 | ''' Alternative version of @java_method that takes JavaClass 79 | objects to produce the method signature. ''' 80 | 81 | sig = signature(returns, takes) 82 | return java_method(sig) 83 | 84 | 85 | def signature(returns, takes): 86 | ''' Produces a JNI method signature, taking the provided arguments 87 | and returning the given return type. ''' 88 | 89 | out_takes = [] 90 | for arg in takes: 91 | out_takes.append(_jni_type_spec(arg)) 92 | 93 | return "(" + "".join(out_takes) + ")" + _jni_type_spec(returns) 94 | 95 | 96 | def _jni_type_spec(jclass): 97 | ''' Produces a JNI type specification string for the given argument. 98 | If the argument is a jnius.JavaClass, it produces the JNI type spec 99 | for the class. Signature primitives return their stored type spec. 100 | ''' 101 | 102 | if issubclass(jclass, JavaClass): 103 | return "L" + jclass.__javaclass__ + ";" 104 | elif issubclass(jclass, _JavaSignaturePrimitive): 105 | return jclass._spec 106 | -------------------------------------------------------------------------------- /jnius/src/org/jnius/NativeInvocationHandler.java: -------------------------------------------------------------------------------- 1 | package org.jnius; 2 | import java.lang.reflect.InvocationHandler; 3 | import java.lang.reflect.Method; 4 | 5 | public class NativeInvocationHandler implements InvocationHandler { 6 | static boolean DEBUG = false; 7 | private long ptr; 8 | 9 | public NativeInvocationHandler(long ptr) { 10 | this.ptr = ptr; 11 | } 12 | 13 | public Object invoke(Object proxy, Method method, Object[] args) { 14 | if ( DEBUG ) { 15 | // don't call it, or recursive lookup/proxy will go! 16 | //System.out.print(proxy); 17 | //System.out.print(", "); 18 | String message = "+ java:invoke(, " + method + ", " + args; 19 | System.out.print(message); 20 | System.out.println(")"); 21 | System.out.flush(); 22 | } 23 | 24 | Object ret = invoke0(proxy, method, args); 25 | 26 | if ( DEBUG ) { 27 | System.out.print("+ java:invoke returned: "); 28 | System.out.println(ret); 29 | } 30 | 31 | return ret; 32 | } 33 | 34 | public long getPythonObjectPointer() { 35 | return ptr; 36 | } 37 | 38 | native Object invoke0(Object proxy, Method method, Object[] args); 39 | } 40 | -------------------------------------------------------------------------------- /jnius_config.py: -------------------------------------------------------------------------------- 1 | __all__ = ('set_options', 'add_options', 'get_options', 2 | 'set_classpath', 'add_classpath', 'get_classpath', 3 | 'expand_classpath') 4 | 5 | import platform 6 | if platform.system() == 'Windows': 7 | split_char = ';' 8 | else: 9 | split_char = ':' 10 | 11 | vm_running = False 12 | vm_started_at = None 13 | options = [] 14 | classpath = None 15 | 16 | 17 | def check_vm_running(): 18 | """Raises a ValueError if the VM is already running.""" 19 | if vm_running: 20 | raise ValueError("VM is already running, can't set classpath/options; VM started at" + vm_started_at) 21 | 22 | 23 | def set_options(*opts): 24 | """Sets the list of options to the JVM. Removes any previously set options.""" 25 | check_vm_running() 26 | global options 27 | options = list(opts) 28 | 29 | 30 | def add_options(*opts): 31 | """Appends options to the list of VM options.""" 32 | check_vm_running() 33 | global options 34 | options.extend(opts) 35 | 36 | 37 | def get_options(): 38 | """Retrieves the current list of VM options.""" 39 | global options 40 | return list(options) 41 | 42 | 43 | def set_classpath(*path): 44 | """ 45 | Sets the classpath for the JVM to use. Replaces any existing classpath, overriding the CLASSPATH environment variable. 46 | """ 47 | check_vm_running() 48 | global classpath 49 | classpath = list(path) 50 | 51 | 52 | def add_classpath(*path): 53 | """ 54 | Appends items to the classpath for the JVM to use. 55 | Replaces any existing classpath, overriding the CLASSPATH environment variable. 56 | """ 57 | check_vm_running() 58 | global classpath 59 | if classpath is None: 60 | classpath = list(path) 61 | else: 62 | classpath.extend(path) 63 | 64 | 65 | def get_classpath(): 66 | "Retrieves the classpath the JVM will use." 67 | from os import environ 68 | from os.path import realpath 69 | import sys 70 | global classpath 71 | 72 | # add a path to java classes packaged with jnius 73 | if sys.version_info >= (3, 9): 74 | from contextlib import ExitStack 75 | import importlib.resources 76 | import atexit 77 | 78 | # see https://importlib-resources.readthedocs.io/en/latest/migration.html#pkg-resources-resource-filename 79 | file_manager = ExitStack() 80 | atexit.register(file_manager.close) 81 | # importlib.resources.files is only available from Python 3.9 82 | # use https://github.com/python/importlib_resources/issues/60 not __name__ as jnius_config.py is not a package 83 | resource_path = importlib.resources.files('jnius') / 'src' 84 | return_classpath = [ str(resource_path) ] 85 | file_manager.enter_context(importlib.resources.as_file(resource_path)) 86 | else: 87 | from pkg_resources import resource_filename 88 | return_classpath = [realpath(resource_filename(__name__, 'jnius/src'))] 89 | 90 | 91 | if classpath is not None: 92 | return_classpath = classpath + return_classpath 93 | 94 | elif 'CLASSPATH' in environ: 95 | return_classpath = environ['CLASSPATH'].split(split_char) + return_classpath 96 | 97 | else: 98 | return_classpath = [realpath('.')] + return_classpath 99 | 100 | return return_classpath 101 | 102 | 103 | def expand_classpath(): 104 | from glob import glob 105 | paths = [] 106 | # deal with wildcards 107 | for path in get_classpath(): 108 | if not path.endswith('*'): 109 | paths.append(path) 110 | else: 111 | paths.extend(glob(path + '.[Jj][Aa][Rr]')) 112 | return split_char.join(paths) 113 | -------------------------------------------------------------------------------- /main.workflow: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = [ 3 | "setuptools>=58.0.0", 4 | "wheel", 5 | "Cython" 6 | ] 7 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:recommended" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [options.extras_require] 2 | dev = 3 | pytest 4 | pytest-cov 5 | pycodestyle 6 | ci = 7 | coveralls 8 | pytest-rerunfailures 9 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Setup.py for creating a binary distribution. 3 | ''' 4 | 5 | from os import environ 6 | from os.path import dirname, join 7 | import subprocess 8 | import sys 9 | 10 | from setup_sdist import SETUP_KWARGS 11 | from setuptools import setup, Extension 12 | from setuptools.command.build_ext import build_ext 13 | 14 | 15 | # XXX hack to be able to import jnius.env withough having build 16 | # jnius.jnius yet, better solution welcome 17 | syspath = sys.path[:] 18 | sys.path.insert(0, 'jnius') 19 | from env import get_java_setup 20 | sys.path = syspath 21 | 22 | def getenv(key): 23 | '''Get value from environment and decode it.''' 24 | val = environ.get(key) 25 | if val is not None: 26 | try: 27 | return val.decode() 28 | except AttributeError: 29 | return val 30 | return val 31 | 32 | 33 | PYX_FILES = [ 34 | 'jnius.pyx', 35 | ] 36 | PXI_FILES = [ 37 | 'jnius_compat.pxi', 38 | 'jnius_conversion.pxi', 39 | 'jnius_export_class.pxi', 40 | 'jnius_export_func.pxi', 41 | 'jnius_jvm_android.pxi', 42 | 'jnius_jvm_desktop.pxi', 43 | 'jnius_jvm_dlopen.pxi', 44 | 'jnius_localref.pxi', 45 | 'jnius_nativetypes3.pxi', 46 | 'jnius_proxy.pxi', 47 | 'jnius.pyx', 48 | 'jnius_utils.pxi' 49 | ] 50 | 51 | EXTRA_LINK_ARGS = [] 52 | 53 | # detect Python for android 54 | PLATFORM = sys.platform 55 | NDKPLATFORM = getenv('NDKPLATFORM') 56 | if NDKPLATFORM is not None and getenv('LIBLINK'): 57 | PLATFORM = 'android' 58 | 59 | # detect platform 60 | if PLATFORM == 'android': 61 | PYX_FILES = [fn[:-3] + 'c' for fn in PYX_FILES] 62 | 63 | JAVA=get_java_setup(PLATFORM) 64 | 65 | assert JAVA.is_jdk(), "You need a JDK, we only found a JRE. Try setting JAVA_HOME" 66 | 67 | 68 | def compile_native_invocation_handler(java): 69 | '''Find javac and compile NativeInvocationHandler.java.''' 70 | javac = java.get_javac() 71 | source_level = '8' 72 | try: 73 | subprocess.check_call([ 74 | javac, '-target', source_level, '-source', source_level, 75 | join('jnius', 'src', 'org', 'jnius', 'NativeInvocationHandler.java') 76 | ]) 77 | except FileNotFoundError: 78 | subprocess.check_call([ 79 | javac.replace('"', ''), '-target', source_level, '-source', source_level, 80 | join('jnius', 'src', 'org', 'jnius', 'NativeInvocationHandler.java') 81 | ]) 82 | 83 | 84 | compile_native_invocation_handler(JAVA) 85 | 86 | 87 | # generate the config.pxi 88 | with open(join(dirname(__file__), 'jnius', 'config.pxi'), 'w') as fd: 89 | if PLATFORM == 'android': 90 | cython3 = environ.get('ANDROID_PYJNIUS_CYTHON_3', '0') == '1' 91 | else: 92 | import Cython 93 | cython3 = Cython.__version__.startswith('3.') 94 | fd.write('DEF JNIUS_PLATFORM = {0!r}\n\n'.format(PLATFORM)) 95 | # record the Cython version, to address #669 96 | fd.write(f'DEF JNIUS_CYTHON_3 = {cython3}') 97 | 98 | # pop setup.py from included files in the installed package 99 | SETUP_KWARGS['py_modules'].remove('setup') 100 | 101 | ext_modules = [ 102 | Extension( 103 | 'jnius', 104 | [join('jnius', x) for x in PYX_FILES], 105 | depends=[join('jnius', x) for x in PXI_FILES], 106 | libraries=JAVA.get_libraries(), 107 | library_dirs=JAVA.get_library_dirs(), 108 | include_dirs=JAVA.get_include_dirs(), 109 | extra_link_args=EXTRA_LINK_ARGS, 110 | ) 111 | ] 112 | 113 | for ext_mod in ext_modules: 114 | ext_mod.cython_directives = {'language_level': 3} 115 | 116 | 117 | # create the extension 118 | setup( 119 | cmdclass={'build_ext': build_ext}, 120 | ext_modules=ext_modules, 121 | **SETUP_KWARGS 122 | ) 123 | -------------------------------------------------------------------------------- /setup_sdist.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Setup.py only for creating a source distributions. 3 | 4 | This file holds all the common setup.py keyword arguments between the source 5 | distribution and the ordinary setup.py for binary distribution. Running this 6 | instead of the default setup.py will create a GitHub-like archive with setup.py 7 | meant for installing via pip. 8 | ''' 9 | from io import open 10 | 11 | # pylint: disable=import-error,no-name-in-module 12 | from setuptools import setup 13 | from os.path import join 14 | 15 | with open("README.md", encoding='utf8') as f: 16 | README = f.read() 17 | 18 | 19 | with open(join('jnius', '__init__.py')) as fd: 20 | VERSION = [ 21 | x for x in fd.readlines() 22 | if x.startswith('__version__') 23 | ][0].split("'")[-2] 24 | 25 | 26 | SETUP_KWARGS = { 27 | 'name': 'pyjnius', 28 | 'version': VERSION, 29 | 'url': "https://github.com/kivy/pyjnius", 30 | 'project_urls': { 31 | 'Website': "https://kivy.org", 32 | 'Documentation': "https://pyjnius.readthedocs.io", 33 | 'Source': "https://github.com/kivy/pyjnius", 34 | 'Bug Reports': "https://github.com/kivy/pyjnius/issues", 35 | }, 36 | 'packages': ['jnius'], 37 | 'py_modules': ['jnius_config', 'setup', 'setup_sdist', 'jnius.env'], 38 | 'ext_package': 'jnius', 39 | 'package_data': { 40 | 'jnius': ['src/org/jnius/*'], 41 | }, 42 | 'long_description_content_type': 'text/markdown', 43 | 'long_description': README, 44 | 'author': 'Kivy Team and other contributors', 45 | 'author_email': 'kivy-dev@googlegroups.com', 46 | 'description': 47 | "A Python library for accessing access Java classes as using the " 48 | "Java Native Interface (JNI).", 49 | 'keywords': 'Java JNI Android', 50 | 'classifiers': [ 51 | 'Development Status :: 5 - Production/Stable', 52 | 'Intended Audience :: Developers', 53 | 'License :: OSI Approved :: MIT License', 54 | 'Natural Language :: English', 55 | 'Operating System :: MacOS', 56 | 'Operating System :: Microsoft :: Windows', 57 | 'Operating System :: POSIX :: Linux', 58 | 'Operating System :: Android', 59 | 'Programming Language :: Python :: 3.8', 60 | 'Programming Language :: Python :: 3.9', 61 | 'Programming Language :: Python :: 3.10', 62 | 'Programming Language :: Python :: 3.11', 63 | 'Programming Language :: Python :: 3.12', 64 | 'Topic :: Software Development :: Libraries :: Application Frameworks' 65 | ] 66 | } 67 | 68 | if __name__ == '__main__': 69 | setup(**SETUP_KWARGS) 70 | -------------------------------------------------------------------------------- /tests/android/testhardware/main.py: -------------------------------------------------------------------------------- 1 | from time import sleep 2 | from jnius import autoclass 3 | 4 | print '-- test hardware start!' 5 | 6 | Hardware = autoclass('org.renpy.android.Hardware') 7 | print 'DPI is', Hardware.getDPI() 8 | 9 | Hardware.accelerometerEnable(True) 10 | for x in xrange(20): 11 | print Hardware.accelerometerReading() 12 | sleep(.1) 13 | 14 | print '-- test hardware done!' 15 | -------------------------------------------------------------------------------- /tests/java-src/org/jnius/BasicsTest.java: -------------------------------------------------------------------------------- 1 | package org.jnius; 2 | 3 | import java.lang.String; 4 | 5 | public class BasicsTest { 6 | static public boolean methodStaticZ() { return true; }; 7 | static public byte methodStaticB() { return 127; }; 8 | static public char methodStaticC() { return 'k'; }; 9 | static public short methodStaticS() { return 32767; }; 10 | static public int methodStaticI() { return 2147483467; }; 11 | static public long methodStaticJ() { return 9223372036854775807L; }; 12 | static public float methodStaticF() { return 1.23456789f; }; 13 | static public double methodStaticD() { return 1.23456789; }; 14 | static public String methodStaticString() { return new String("hello \uD83C\uDF0E!"); } 15 | 16 | public boolean methodZ() { return true; }; 17 | public byte methodB() { return 127; }; 18 | public char methodC() { return 'k'; }; 19 | public short methodS() { return 32767; }; 20 | public int methodI() { return 2147483467; }; 21 | public long methodJ() { return 9223372036854775807L; }; 22 | public float methodF() { return 1.23456789f; }; 23 | public double methodD() { return 1.23456789; }; 24 | public String methodString() { return new String("hello \uD83C\uDF0E!"); } 25 | public void methodException(int depth) throws IllegalArgumentException { 26 | if (depth == 0) throw new IllegalArgumentException("hello \uD83C\uDF0E!"); 27 | else methodException(depth -1); 28 | } 29 | public void methodExceptionChained() throws IllegalArgumentException { 30 | try { 31 | methodException(5); 32 | } catch (IllegalArgumentException e) { 33 | throw new IllegalArgumentException("helloworld2", e); 34 | } 35 | } 36 | public boolean getDisabled() { return true; }; 37 | public boolean isEnabled() { return !this.getDisabled(); }; 38 | 39 | static public boolean fieldStaticZ = true; 40 | static public byte fieldStaticB = 127; 41 | static public char fieldStaticC = 'k'; 42 | static public short fieldStaticS = 32767; 43 | static public int fieldStaticI = 2147483467; 44 | static public long fieldStaticJ = 9223372036854775807L; 45 | static public float fieldStaticF = 1.23456789f; 46 | static public double fieldStaticD = 1.23456789; 47 | static public String fieldStaticString = new String("hello \uD83C\uDF0E!"); 48 | 49 | public boolean fieldZ = true; 50 | public byte fieldB = 127; 51 | public char fieldC = 'k'; 52 | public short fieldS = 32767; 53 | public int fieldI = 2147483467; 54 | public long fieldJ = 9223372036854775807L; 55 | public float fieldF = 1.23456789f; 56 | public double fieldD = 1.23456789; 57 | public String fieldString = new String("hello \uD83C\uDF0E!"); 58 | 59 | public boolean fieldSetZ; 60 | public byte fieldSetB; 61 | public char fieldSetC; 62 | public short fieldSetS; 63 | public int fieldSetI; 64 | public long fieldSetJ; 65 | public float fieldSetF; 66 | public double fieldSetD; 67 | public String fieldSetString; 68 | 69 | // Floating-point comparison epsilon 70 | private final static double EPSILON = 1E-6; 71 | 72 | public BasicsTest() {} 73 | public BasicsTest(byte fieldBVal) { 74 | fieldB = fieldBVal; 75 | } 76 | 77 | public boolean[] methodArrayZ() { 78 | boolean[] x = new boolean[3]; 79 | x[0] = x[1] = x[2] = true; 80 | return x; 81 | }; 82 | public byte[] methodArrayB() { 83 | byte[] x = new byte[3]; 84 | x[0] = x[1] = x[2] = 127; 85 | return x; 86 | }; 87 | public char[] methodArrayC() { 88 | char[] x = new char[3]; 89 | x[0] = x[1] = x[2] = 'k'; 90 | return x; 91 | }; 92 | public short[] methodArrayS() { 93 | short[] x = new short[3]; 94 | x[0] = x[1] = x[2] = 32767; 95 | return x; 96 | }; 97 | public int[] methodArrayI() { 98 | int[] x = new int[3]; 99 | x[0] = x[1] = x[2] = 2147483467; 100 | return x; 101 | }; 102 | public long[] methodArrayJ() { 103 | long[] x = new long[3]; 104 | x[0] = x[1] = x[2] = 9223372036854775807L; 105 | return x; 106 | }; 107 | public float[] methodArrayF() { 108 | float[] x = new float[3]; 109 | x[0] = x[1] = x[2] = 1.23456789f; 110 | return x; 111 | }; 112 | public double[] methodArrayD() { 113 | double[] x = new double[3]; 114 | x[0] = x[1] = x[2] = 1.23456789; 115 | return x; 116 | }; 117 | public String[] methodArrayString() { 118 | String[] x = new String[3]; 119 | x[0] = x[1] = x[2] = new String("hello \uD83C\uDF0E!"); 120 | return x; 121 | }; 122 | 123 | 124 | public boolean methodParamsZBCSIJFD(boolean x1, byte x2, char x3, short x4, 125 | int x5, long x6, float x7, double x8) { 126 | return (x1 == true && x2 == 127 && x3 == 'k' && x4 == 32767 && 127 | x5 == 2147483467 && x6 == 9223372036854775807L && 128 | (Math.abs(x7 - 1.23456789f) < EPSILON) && 129 | (Math.abs(x8 - 1.23456789) < EPSILON)); 130 | } 131 | 132 | public boolean methodParamsString(String s) { 133 | return (s.equals("hello \uD83C\uDF0E!")); 134 | } 135 | 136 | public boolean methodParamsArrayI(int[] x) { 137 | if (x.length != 3) 138 | return false; 139 | return (x[0] == 1 && x[1] == 2 && x[2] == 3); 140 | } 141 | 142 | public boolean methodParamsArrayString(String[] x) { 143 | if (x.length != 2) 144 | return false; 145 | return (x[0].equals("hello") && x[1].equals("\uD83C\uDF0E")); 146 | } 147 | 148 | public boolean methodParamsObject(Object x) { 149 | return true; 150 | } 151 | 152 | public Object methodReturnStrings() { 153 | String[] hello_world = new String[2]; 154 | hello_world[0] = "Hello"; 155 | hello_world[1] = "\uD83C\uDF0E"; 156 | return hello_world; 157 | } 158 | 159 | public Object methodReturnIntegers() { 160 | int[] integers = new int[2]; 161 | integers[0] = 1; 162 | integers[1] = 2; 163 | return integers; 164 | } 165 | 166 | public boolean methodParamsArrayByte(byte[] x) { 167 | if (x.length != 3) 168 | return false; 169 | return (x[0] == 127 && x[1] == 127 && x[2] == 127); 170 | } 171 | 172 | public void fillByteArray(byte[] x) { 173 | if (x.length != 3) 174 | return; 175 | x[0] = 127; 176 | x[1] = 1; 177 | x[2] = -127; 178 | } 179 | 180 | public byte[] methodReturnEmptyByteArray() { 181 | return new byte[0]; 182 | } 183 | 184 | public boolean testFieldSetZ() { 185 | return (fieldSetZ == true); 186 | } 187 | 188 | public boolean testFieldSetB() { 189 | return (fieldSetB == 127); 190 | } 191 | 192 | public boolean testFieldSetC() { 193 | return (fieldSetC == 'k'); 194 | } 195 | 196 | public boolean testFieldSetS() { 197 | return (fieldSetS == 32767); 198 | } 199 | 200 | public boolean testFieldSetI() { 201 | return (fieldSetI == 2147483467); 202 | } 203 | 204 | public boolean testFieldSetJ() { 205 | return (fieldSetJ == 9223372036854775807L); 206 | } 207 | 208 | public boolean testFieldSetF() { 209 | return (Math.abs(fieldSetF - 1.23456789f) < EPSILON); 210 | } 211 | 212 | public boolean testFieldSetD() { 213 | return (Math.abs(fieldSetD - 1.23456789) < EPSILON); 214 | } 215 | } 216 | -------------------------------------------------------------------------------- /tests/java-src/org/jnius/CharsAndStrings.java: -------------------------------------------------------------------------------- 1 | package org.jnius; 2 | 3 | import java.lang.String; 4 | 5 | public class CharsAndStrings { 6 | 7 | public char testChar1; 8 | public char testChar2; 9 | public char testChar3; 10 | public String testString1; 11 | public String testString2; 12 | public String testString3; 13 | 14 | static public char testStaticChar1 = 'a'; 15 | static public char testStaticChar2 = 'ä'; 16 | static public char testStaticChar3 = '☺'; 17 | static public String testStaticString1 = "hello world"; 18 | static public String testStaticString2 = "umlauts: äöü"; 19 | static public String testStaticString3 = "happy face: ☺"; 20 | 21 | public char[] testCharArray1; 22 | public char[] testCharArray2; 23 | static public char[] testStaticCharArray1 = new char[]{'a', 'b', 'c'}; 24 | static public char[] testStaticCharArray2 = new char[]{'a', 'ä', '☺'}; 25 | static public String testStringDefNull = null; 26 | static public int testInt = 0; 27 | 28 | public CharsAndStrings() { 29 | this.testChar1 = 'a'; 30 | this.testChar2 = 'ä'; 31 | this.testChar3 = '☺'; 32 | 33 | this.testString1 = "hello world"; 34 | this.testString2 = "umlauts: äöü"; 35 | this.testString3 = "happy face: ☺"; 36 | 37 | testCharArray1 = new char[]{'a', 'b', 'c'}; 38 | testCharArray2 = new char[]{'a', 'ä', '☺'}; 39 | } 40 | 41 | public char testChar(int i, char testChar) { 42 | if (i == 1) { 43 | assert this.testChar1 == testChar; 44 | return this.testChar1; 45 | } else if (i == 2) { 46 | assert this.testChar2 == testChar; 47 | return this.testChar2; 48 | } else { 49 | assert this.testChar3 == testChar; 50 | return this.testChar3; 51 | } 52 | } 53 | 54 | static public char testStaticChar(int i, char testChar) { 55 | if (i == 1) { 56 | assert CharsAndStrings.testStaticChar1 == testChar; 57 | return CharsAndStrings.testStaticChar1; 58 | } else if (i == 2) { 59 | assert CharsAndStrings.testStaticChar2 == testChar; 60 | return CharsAndStrings.testStaticChar2; 61 | } else { 62 | assert CharsAndStrings.testStaticChar3 == testChar; 63 | return CharsAndStrings.testStaticChar3; 64 | } 65 | } 66 | 67 | public String testString(int i, String testString) { 68 | if (i == 1) { 69 | assert this.testString1.equals(testString); 70 | return this.testString1; 71 | } else if (i == 2) { 72 | assert this.testString2.equals(testString); 73 | return this.testString2; 74 | } else { 75 | assert this.testString3.equals(testString); 76 | return this.testString3; 77 | } 78 | } 79 | 80 | static public String testStaticString(int i, String testString) { 81 | if (i == 1) { 82 | assert CharsAndStrings.testStaticString1.equals(testString); 83 | return CharsAndStrings.testStaticString1; 84 | } else if (i == 2) { 85 | assert CharsAndStrings.testStaticString2.equals(testString); 86 | return CharsAndStrings.testStaticString2; 87 | } else { 88 | assert CharsAndStrings.testStaticString3.equals(testString); 89 | return CharsAndStrings.testStaticString3; 90 | } 91 | } 92 | 93 | public char[] testCharArray(int i) { 94 | if (i == 1) { 95 | return testCharArray1; 96 | } else { 97 | return testCharArray2; 98 | } 99 | } 100 | 101 | static public char[] testStaticCharArray(int i) { 102 | if (i == 1) { 103 | return testStaticCharArray1; 104 | } else { 105 | return testStaticCharArray2; 106 | } 107 | } 108 | 109 | static public void setString(String ignore, String value) { 110 | testStringDefNull = value; 111 | } 112 | 113 | static public void setInt(String ignore, int value) { 114 | testInt = value; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /tests/java-src/org/jnius/Child.java: -------------------------------------------------------------------------------- 1 | package org.jnius; 2 | 3 | import org.jnius.Parent; 4 | 5 | public class Child extends Parent { 6 | 7 | public int CHILD_FIELD = 1; 8 | 9 | public int doCall(int child) { 10 | return 1; 11 | } 12 | 13 | static public Child newInstance(){ 14 | return new Child(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests/java-src/org/jnius/ChildVisibilityTest.java: -------------------------------------------------------------------------------- 1 | package org.jnius; 2 | 3 | import java.lang.String; 4 | 5 | public class ChildVisibilityTest extends VisibilityTest { 6 | public String fieldChildPublic = "ChildPublic"; 7 | String fieldChildPackageProtected = "ChildPackageProtected"; 8 | protected String fieldChildProtected = "ChildProtected"; 9 | private String fieldChildPrivate = "ChildPrivate"; 10 | 11 | static public String fieldChildStaticPublic = "ChildStaticPublic"; 12 | static String fieldChildStaticPackageProtected = "ChildStaticPackageProtected"; 13 | static protected String fieldChildStaticProtected = "ChildStaticProtected"; 14 | static private String fieldChildStaticPrivate = "ChildStaticPrivate"; 15 | 16 | public String methodChildPublic() { 17 | return fieldChildPublic; 18 | } 19 | 20 | String methodChildPackageProtected() { 21 | return fieldChildPackageProtected; 22 | } 23 | 24 | protected String methodChildProtected() { 25 | return fieldChildProtected; 26 | } 27 | 28 | private String methodChildPrivate() { 29 | return fieldChildPrivate; 30 | } 31 | 32 | protected boolean methodMultiArgs(boolean a, boolean b) { 33 | return a & !b; 34 | } 35 | 36 | private boolean methodMultiArgs(boolean a, boolean b, boolean c) { 37 | return a & !b & c; 38 | } 39 | 40 | // dummy method to avoid warning about unused methods 41 | public String methodChildDummy() { 42 | this.methodMultiArgs(true, true, false); 43 | return this.methodChildPrivate(); 44 | } 45 | 46 | static public String methodChildStaticPublic() { 47 | return fieldChildStaticPublic; 48 | } 49 | 50 | static String methodChildStaticPackageProtected() { 51 | return fieldChildStaticPackageProtected; 52 | } 53 | 54 | static protected String methodChildStaticProtected() { 55 | return fieldChildStaticProtected; 56 | } 57 | 58 | static private String methodChildStaticPrivate() { 59 | return fieldChildStaticPrivate; 60 | } 61 | 62 | static protected boolean methodStaticMultiArgs(boolean a, boolean b) { 63 | return a & !b; 64 | } 65 | 66 | static private boolean methodStaticMultiArgs(boolean a, boolean b, boolean c) { 67 | return a & !b & c; 68 | } 69 | 70 | // dummy method to avoid warning about unused methods 71 | static public String methodChildStaticDummy() { 72 | ChildVisibilityTest.methodStaticMultiArgs(true, true, true); 73 | return ChildVisibilityTest.methodChildStaticPrivate(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /tests/java-src/org/jnius/ClassArgument.java: -------------------------------------------------------------------------------- 1 | package org.jnius; 2 | 3 | 4 | public class ClassArgument { 5 | public static String getName(Class klass) { 6 | return klass.toString(); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/java-src/org/jnius/CloseableClass.java: -------------------------------------------------------------------------------- 1 | package org.jnius; 2 | 3 | import java.io.Closeable; 4 | 5 | public class CloseableClass implements Closeable{ 6 | public static boolean open = true; 7 | 8 | public CloseableClass() { 9 | open = true; 10 | } 11 | 12 | public void close() { 13 | open = false; 14 | } 15 | } -------------------------------------------------------------------------------- /tests/java-src/org/jnius/ConstructorTest.java: -------------------------------------------------------------------------------- 1 | package org.jnius; 2 | import java.lang.Character; 3 | 4 | 5 | public class ConstructorTest { 6 | public int ret; 7 | 8 | public ConstructorTest() { 9 | ret = 753; 10 | } 11 | 12 | public ConstructorTest(int cret) { 13 | ret = cret; 14 | } 15 | 16 | public ConstructorTest(char charet) { 17 | ret = (int) charet; 18 | } 19 | 20 | public ConstructorTest(int cret, char charet) { 21 | ret = cret + (int) charet; 22 | } 23 | 24 | public ConstructorTest(Object DO_NOT_CALL) { 25 | throw new Error(); 26 | } 27 | 28 | public ConstructorTest(java.io.OutputStream os) { 29 | ret = 42; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/java-src/org/jnius/HelloWorld.java: -------------------------------------------------------------------------------- 1 | package org.jnius; 2 | 3 | public class HelloWorld { 4 | public String hello() { 5 | return new String("world"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tests/java-src/org/jnius/InterfaceWithPublicEnum.java: -------------------------------------------------------------------------------- 1 | package org.jnius; 2 | 3 | 4 | public interface InterfaceWithPublicEnum { 5 | 6 | public enum ATTITUDE { 7 | GOOD, BAD, UGLY, 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/java-src/org/jnius/MultipleDimensions.java: -------------------------------------------------------------------------------- 1 | package org.jnius; 2 | 3 | public class MultipleDimensions { 4 | public static boolean methodParamsMatrixI(int[][] x) { 5 | if (x.length != 3 || x[0].length != 3) 6 | return false; 7 | return (x[0][0] == 1 && x[0][1] == 2 && x[1][2] == 6); 8 | } 9 | public static int[][] methodReturnMatrixI() { 10 | int[][] matrix = {{1,2,3}, 11 | {4,5,6}, 12 | {7,8,9}}; 13 | return matrix; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /tests/java-src/org/jnius/MultipleMethods.java: -------------------------------------------------------------------------------- 1 | package org.jnius; 2 | 3 | public class MultipleMethods { 4 | 5 | public static String resolve() { 6 | return "resolved no args"; 7 | } 8 | 9 | public static String resolve(String i) { 10 | return "resolved one arg"; 11 | } 12 | 13 | public static String resolve(String i, String j) { 14 | return "resolved two args"; 15 | } 16 | 17 | public static String resolve(String i, String j, int k) { 18 | return "resolved two string and an integer"; 19 | } 20 | 21 | public static String resolve(String i, String j, int k, int l) { 22 | return "resolved two string and two integers"; 23 | } 24 | 25 | public static String resolve(String i, String j, int... integers) { 26 | return "resolved two args and varargs"; 27 | } 28 | 29 | public static String resolve(int... integers) { 30 | return "resolved varargs"; 31 | } 32 | 33 | public static String resolve(int i, long j, String k) { 34 | return "resolved one int, one long and a string"; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /tests/java-src/org/jnius/ObjectArgument.java: -------------------------------------------------------------------------------- 1 | package org.jnius; 2 | 3 | 4 | public class ObjectArgument { 5 | public static int checkObject(Object obj) { 6 | if (obj == null) { 7 | return -1; 8 | } else { 9 | return 0; 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/java-src/org/jnius/Parent.java: -------------------------------------------------------------------------------- 1 | package org.jnius; 2 | 3 | public class Parent { 4 | 5 | public static int STATIC_PARENT_FIELD = 1; 6 | 7 | public int doCall(Object o) { 8 | return 0; 9 | } 10 | 11 | public int getParentStaticField() { 12 | return STATIC_PARENT_FIELD; 13 | } 14 | 15 | public static int StaticGetParentStaticField() { 16 | return STATIC_PARENT_FIELD; 17 | } 18 | 19 | public int getParentField() { 20 | return PARENT_FIELD; 21 | } 22 | 23 | static public Parent newInstance(){ 24 | return new Parent(); 25 | } 26 | 27 | public int PARENT_FIELD = 0; 28 | } 29 | -------------------------------------------------------------------------------- /tests/java-src/org/jnius/SimpleEnum.java: -------------------------------------------------------------------------------- 1 | package org.jnius; 2 | 3 | 4 | public enum SimpleEnum { 5 | GOOD, BAD, UGLY, 6 | } 7 | -------------------------------------------------------------------------------- /tests/java-src/org/jnius/VariableArgConstructors.java: -------------------------------------------------------------------------------- 1 | package org.jnius; 2 | 3 | public class VariableArgConstructors { 4 | public int constructorUsed; 5 | 6 | public VariableArgConstructors(int arg1, String arg2, int arg3, Object arg4, int... arg5) { 7 | constructorUsed = 1; 8 | } 9 | 10 | public VariableArgConstructors(int arg1, String arg2, Object arg3, int... arg4) { 11 | constructorUsed = 2; 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /tests/java-src/org/jnius/VariablePassing.java: -------------------------------------------------------------------------------- 1 | package org.jnius; 2 | 3 | public class VariablePassing { 4 | 5 | public VariablePassing() { 6 | 7 | } 8 | 9 | public VariablePassing(int[] numbers) { 10 | squareNumbers(numbers); 11 | } 12 | 13 | public VariablePassing(int[] numbers1, int[] numbers2, int[] numbers3, int[] numbers4) { 14 | squareNumbers(numbers1); 15 | squareNumbers(numbers2); 16 | squareNumbers(numbers3); 17 | squareNumbers(numbers4); 18 | } 19 | 20 | private static void squareNumbers(int[] numbers) { 21 | for (int i = 0; i < numbers.length; i++) { 22 | numbers[i] = i * i; 23 | } 24 | } 25 | 26 | public static void singleParamStatic(int[] numbers) { 27 | squareNumbers(numbers); 28 | } 29 | 30 | public static void multipleParamsStatic(int[] numbers1, int[] numbers2, int[] numbers3, int[] numbers4) { 31 | squareNumbers(numbers1); 32 | squareNumbers(numbers2); 33 | squareNumbers(numbers3); 34 | squareNumbers(numbers4); 35 | } 36 | 37 | public void singleParam(int[] numbers) { 38 | squareNumbers(numbers); 39 | } 40 | 41 | public void multipleParams(int[] numbers1, int[] numbers2, int[] numbers3, int[] numbers4) { 42 | squareNumbers(numbers1); 43 | squareNumbers(numbers2); 44 | squareNumbers(numbers3); 45 | squareNumbers(numbers4); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /tests/java-src/org/jnius/VisibilityTest.java: -------------------------------------------------------------------------------- 1 | package org.jnius; 2 | 3 | import java.lang.String; 4 | 5 | public class VisibilityTest { 6 | public String fieldPublic = "Public"; 7 | String fieldPackageProtected = "PackageProtected"; 8 | protected String fieldProtected = "Protected"; 9 | private String fieldPrivate = "Private"; 10 | 11 | static public String fieldStaticPublic = "StaticPublic"; 12 | static String fieldStaticPackageProtected = "StaticPackageProtected"; 13 | static protected String fieldStaticProtected = "StaticProtected"; 14 | static private String fieldStaticPrivate = "StaticPrivate"; 15 | 16 | public String methodPublic() { 17 | return fieldPublic; 18 | } 19 | 20 | String methodPackageProtected() { 21 | return fieldPackageProtected; 22 | } 23 | 24 | protected String methodProtected() { 25 | return fieldProtected; 26 | } 27 | 28 | private String methodPrivate() { 29 | return fieldPrivate; 30 | } 31 | 32 | public boolean methodMultiArgs(boolean a) { 33 | return a; 34 | } 35 | 36 | // dummy method to avoid warning methodPrivate() isn't used 37 | public String methodDummy() { 38 | return this.methodPrivate(); 39 | } 40 | 41 | static public String methodStaticPublic() { 42 | return fieldStaticPublic; 43 | } 44 | 45 | static String methodStaticPackageProtected() { 46 | return fieldStaticPackageProtected; 47 | } 48 | 49 | static protected String methodStaticProtected() { 50 | return fieldStaticProtected; 51 | } 52 | 53 | static private String methodStaticPrivate() { 54 | return fieldStaticPrivate; 55 | } 56 | 57 | static public boolean methodStaticMultiArgs(boolean a) { 58 | return a; 59 | } 60 | 61 | // dummy method to avoid warning methodStaticPrivate() isn't used 62 | static public String methodStaticDummy() { 63 | return VisibilityTest.methodStaticPrivate(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /tests/java-src/org/jnius2/ChildVisibilityTest.java: -------------------------------------------------------------------------------- 1 | package org.jnius2; 2 | 3 | import java.lang.String; 4 | 5 | import org.jnius.VisibilityTest; 6 | 7 | public class ChildVisibilityTest extends VisibilityTest { 8 | public String fieldChildPublic = "ChildPublic"; 9 | String fieldChildPackageProtected = "ChildPackageProtected"; 10 | protected String fieldChildProtected = "ChildProtected"; 11 | private String fieldChildPrivate = "ChildPrivate"; 12 | 13 | static public String fieldChildStaticPublic = "ChildStaticPublic"; 14 | static String fieldChildStaticPackageProtected = "ChildStaticPackageProtected"; 15 | static protected String fieldChildStaticProtected = "ChildStaticProtected"; 16 | static private String fieldChildStaticPrivate = "ChildStaticPrivate"; 17 | 18 | public String methodChildPublic() { 19 | return fieldChildPublic; 20 | } 21 | 22 | String methodChildPackageProtected() { 23 | return fieldChildPackageProtected; 24 | } 25 | 26 | protected String methodChildProtected() { 27 | return fieldChildProtected; 28 | } 29 | 30 | private String methodChildPrivate() { 31 | return fieldChildPrivate; 32 | } 33 | 34 | protected boolean methodMultiArgs(boolean a, boolean b) { 35 | return a & !b; 36 | } 37 | 38 | private boolean methodMultiArgs(boolean a, boolean b, boolean c) { 39 | return a & !b & c; 40 | } 41 | 42 | // dummy method to avoid warning about unused methods 43 | public String methodChildDummy() { 44 | this.methodMultiArgs(true, true, false); 45 | return this.methodChildPrivate(); 46 | } 47 | 48 | static public String methodChildStaticPublic() { 49 | return fieldChildStaticPublic; 50 | } 51 | 52 | static String methodChildStaticPackageProtected() { 53 | return fieldChildStaticPackageProtected; 54 | } 55 | 56 | static protected String methodChildStaticProtected() { 57 | return fieldChildStaticProtected; 58 | } 59 | 60 | static private String methodChildStaticPrivate() { 61 | return fieldChildStaticPrivate; 62 | } 63 | 64 | static protected boolean methodStaticMultiArgs(boolean a, boolean b) { 65 | return a & !b; 66 | } 67 | 68 | static private boolean methodStaticMultiArgs(boolean a, boolean b, boolean c) { 69 | return a & !b & c; 70 | } 71 | 72 | // dummy method to avoid warning about unused methods 73 | static public String methodChildStaticDummy() { 74 | ChildVisibilityTest.methodStaticMultiArgs(true, true, true); 75 | return ChildVisibilityTest.methodChildStaticPrivate(); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /tests/test_arraylist.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | import unittest 3 | from jnius import autoclass 4 | 5 | 6 | class ArrayListTest(unittest.TestCase): 7 | 8 | def test_other_dunders(self): 9 | alist = autoclass('java.util.ArrayList')() 10 | args = [1,2] 11 | for arg in args: 12 | alist.add(arg) 13 | self.assertEqual(len(args), len(alist)) 14 | for idx, arg in enumerate(args): 15 | self.assertTrue(arg in alist) 16 | del(alist[1]) 17 | del(alist[0]) 18 | self.assertEqual(0, len(alist)) 19 | 20 | def test_output(self): 21 | alist = autoclass('java.util.ArrayList')() 22 | args = [0, 1, 5, -1, -5, 0.0, 1.0, 5.0, -1.0, -5.0, True, False] 23 | 24 | for arg in args: 25 | alist.add(arg) 26 | for idx, arg in enumerate(args): 27 | if isinstance(arg, bool): 28 | self.assertEqual(str(alist[idx]), str(int(arg))) 29 | else: 30 | self.assertEqual(str(alist[idx]), str(arg)) 31 | self.assertEqual(len(args), len(alist)) 32 | 33 | 34 | if __name__ == '__main__': 35 | unittest.main() 36 | -------------------------------------------------------------------------------- /tests/test_assignable.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from __future__ import division 3 | from __future__ import absolute_import 4 | import unittest 5 | from jnius import autoclass, JavaException 6 | 7 | 8 | class AssignableFrom(unittest.TestCase): 9 | 10 | def test_assignable(self): 11 | ArrayList = autoclass('java.util.ArrayList') 12 | Object = autoclass('java.lang.Object') 13 | 14 | a = ArrayList() 15 | # addAll accept Collection, Object must failed 16 | with self.assertRaisesRegex(TypeError, "Invalid instance of 'java/lang/Object' passed for a 'java/util/Collection'"): 17 | a.addAll(Object()) 18 | 19 | # while adding another ArrayList must be ok. 20 | a.addAll(ArrayList()) 21 | -------------------------------------------------------------------------------- /tests/test_bad_declaration.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from __future__ import division 3 | from __future__ import absolute_import 4 | import unittest 5 | from jnius import JavaException, JavaClass 6 | from jnius.reflect import autoclass 7 | 8 | class BadDeclarationTest(unittest.TestCase): 9 | 10 | def test_class_not_found(self): 11 | #self.assertRaises(JavaException, autoclass, 'org.unknow.class') 12 | #self.assertRaises(JavaException, autoclass, 'java/lang/String') 13 | pass 14 | 15 | def test_invalid_attribute(self): 16 | Stack = autoclass('java.util.Stack') 17 | self.assertRaises(AttributeError, getattr, Stack, 'helloworld') 18 | 19 | def test_invalid_static_call(self): 20 | Stack = autoclass('java.util.Stack') 21 | self.assertRaises(JavaException, Stack.push, 'hello') 22 | 23 | def test_with_too_much_arguments(self): 24 | Stack = autoclass('java.util.Stack') 25 | stack = Stack() 26 | self.assertRaises(JavaException, stack.push, 'hello', 'world', 123) 27 | 28 | def test_java_exception_handling(self): 29 | Stack = autoclass('java.util.Stack') 30 | stack = Stack() 31 | try: 32 | stack.pop() 33 | self.fail("Expected exception to be thrown") 34 | except JavaException as je: 35 | # print "Got JavaException: " + str(je) 36 | # print "Got Exception Class: " + je.classname 37 | # print "Got stacktrace: \n" + '\n'.join(je.stacktrace) 38 | self.assertEqual("java.util.EmptyStackException", je.classname) 39 | 40 | def test_java_exception_chaining(self): 41 | BasicsTest = autoclass('org.jnius.BasicsTest') 42 | basics = BasicsTest() 43 | try: 44 | basics.methodExceptionChained() 45 | self.fail("Expected exception to be thrown") 46 | except JavaException as je: 47 | # print "Got JavaException: " + str(je) 48 | # print "Got Exception Class: " + je.classname 49 | # print "Got Exception Message: " + je.innermessage 50 | # print "Got stacktrace: \n" + '\n'.join(je.stacktrace) 51 | self.assertEqual("java.lang.IllegalArgumentException", je.classname) 52 | self.assertEqual("helloworld2", je.innermessage) 53 | self.assertIn("Caused by:", je.stacktrace) 54 | self.assertEqual(11, len(je.stacktrace)) 55 | -------------------------------------------------------------------------------- /tests/test_basics.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from __future__ import division 3 | from __future__ import absolute_import 4 | import unittest 5 | from jnius.reflect import autoclass 6 | 7 | 8 | class BasicsTest(unittest.TestCase): 9 | 10 | def test_static_methods(self): 11 | Test = autoclass('org.jnius.BasicsTest') 12 | self.assertEqual(Test.methodStaticZ(), True) 13 | self.assertEqual(Test.methodStaticB(), 127) 14 | self.assertEqual(Test.methodStaticC(), 'k') 15 | self.assertEqual(Test.methodStaticS(), 32767) 16 | self.assertEqual(Test.methodStaticI(), 2147483467) 17 | self.assertEqual(Test.methodStaticJ(), 9223372036854775807) 18 | self.assertAlmostEqual(Test.methodStaticF(), 1.23456789) 19 | self.assertEqual(Test.methodStaticD(), 1.23456789) 20 | self.assertEqual(Test.methodStaticString(), 'hello \U0001F30E!') 21 | 22 | def test_static_fields(self): 23 | Test = autoclass('org.jnius.BasicsTest') 24 | self.assertEqual(Test.fieldStaticZ, True) 25 | self.assertEqual(Test.fieldStaticB, 127) 26 | self.assertEqual(Test.fieldStaticC, 'k') 27 | self.assertEqual(Test.fieldStaticS, 32767) 28 | self.assertEqual(Test.fieldStaticI, 2147483467) 29 | self.assertEqual(Test.fieldStaticJ, 9223372036854775807) 30 | self.assertAlmostEqual(Test.fieldStaticF, 1.23456789) 31 | self.assertEqual(Test.fieldStaticD, 1.23456789) 32 | self.assertEqual(Test.fieldStaticString, 'hello \U0001F30E!') 33 | 34 | def test_instance_methods(self): 35 | test = autoclass('org.jnius.BasicsTest')() 36 | self.assertEqual(test.methodZ(), True) 37 | self.assertEqual(test.methodB(), 127) 38 | self.assertEqual(test.methodC(), 'k') 39 | self.assertEqual(test.methodS(), 32767) 40 | self.assertEqual(test.methodI(), 2147483467) 41 | self.assertEqual(test.methodJ(), 9223372036854775807) 42 | self.assertAlmostEqual(test.methodF(), 1.23456789) 43 | self.assertEqual(test.methodD(), 1.23456789) 44 | self.assertEqual(test.methodString(), 'hello \U0001F30E!') 45 | 46 | def test_instance_fields(self): 47 | test = autoclass('org.jnius.BasicsTest')() 48 | self.assertEqual(test.fieldZ, True) 49 | self.assertEqual(test.fieldB, 127) 50 | self.assertEqual(test.fieldC, 'k') 51 | self.assertEqual(test.fieldS, 32767) 52 | self.assertEqual(test.fieldI, 2147483467) 53 | self.assertEqual(test.fieldJ, 9223372036854775807) 54 | self.assertAlmostEqual(test.fieldF, 1.23456789) 55 | self.assertEqual(test.fieldD, 1.23456789) 56 | self.assertEqual(test.fieldString, 'hello \U0001F30E!') 57 | test2 = autoclass('org.jnius.BasicsTest')(10) 58 | self.assertEqual(test2.fieldB, 10) 59 | self.assertEqual(test.fieldB, 127) 60 | self.assertEqual(test2.fieldB, 10) 61 | 62 | def test_instance_getter_naming(self): 63 | test = autoclass('org.jnius.BasicsTest')() 64 | self.assertEqual(test.disabled, True) 65 | self.assertEqual(test.enabled, False) 66 | 67 | def test_instance_set_fields(self): 68 | test = autoclass('org.jnius.BasicsTest')() 69 | test.fieldSetZ = True 70 | test.fieldSetB = 127 71 | test.fieldSetC = ord('k') 72 | test.fieldSetS = 32767 73 | test.fieldSetI = 2147483467 74 | test.fieldSetJ = 9223372036854775807 75 | test.fieldSetF = 1.23456789 76 | test.fieldSetD = 1.23456789 77 | 78 | self.assertTrue(test.testFieldSetZ()) 79 | self.assertTrue(test.testFieldSetB()) 80 | self.assertTrue(test.testFieldSetC()) 81 | self.assertTrue(test.testFieldSetS()) 82 | self.assertTrue(test.testFieldSetI()) 83 | self.assertTrue(test.testFieldSetJ()) 84 | self.assertTrue(test.testFieldSetF()) 85 | self.assertTrue(test.testFieldSetD()) 86 | 87 | def test_instances_methods_array(self): 88 | test = autoclass('org.jnius.BasicsTest')() 89 | self.assertEqual(test.methodArrayZ(), [True] * 3) 90 | self.assertEqual(test.methodArrayB()[0], 127) 91 | self.assertEqual(test.methodArrayB(), [127] * 3) 92 | self.assertEqual(test.methodArrayC(), ['k'] * 3) 93 | self.assertEqual(test.methodArrayS(), [32767] * 3) 94 | self.assertEqual(test.methodArrayI(), [2147483467] * 3) 95 | self.assertEqual(test.methodArrayJ(), [9223372036854775807] * 3) 96 | 97 | ret = test.methodArrayF() 98 | ref = [1.23456789] * 3 99 | self.assertAlmostEqual(ret[0], ref[0]) 100 | self.assertAlmostEqual(ret[1], ref[1]) 101 | self.assertAlmostEqual(ret[2], ref[2]) 102 | 103 | self.assertEqual(test.methodArrayD(), [1.23456789] * 3) 104 | self.assertEqual(test.methodArrayString(), ['hello \U0001F30E!'] * 3) 105 | 106 | def test_instances_methods_params(self): 107 | test = autoclass('org.jnius.BasicsTest')() 108 | self.assertEqual(test.methodParamsZBCSIJFD( 109 | True, 127, 'k', 32767, 2147483467, 9223372036854775807, 1.23456789, 1.23456789), True) 110 | self.assertEqual(test.methodParamsString('hello \U0001F30E!'), True) 111 | self.assertEqual(test.methodParamsArrayI([1, 2, 3]), True) 112 | self.assertEqual(test.methodParamsArrayString([ 113 | 'hello', '\U0001F30E']), True) 114 | 115 | def test_instances_methods_params_object_list_str(self): 116 | test = autoclass('org.jnius.BasicsTest')() 117 | self.assertEqual(test.methodParamsObject([ 118 | 'hello', 'world']), True) 119 | 120 | def test_instances_methods_params_object_list_int(self): 121 | test = autoclass('org.jnius.BasicsTest')() 122 | self.assertEqual(test.methodParamsObject([1, 2]), True) 123 | 124 | def test_instances_methods_params_object_list_float(self): 125 | test = autoclass('org.jnius.BasicsTest')() 126 | self.assertEqual(test.methodParamsObject([3.14, 1.61]), True) 127 | 128 | def test_instances_methods_params_array_byte(self): 129 | test = autoclass('org.jnius.BasicsTest')() 130 | self.assertEqual(test.methodParamsArrayByte([127, 127, 127]), True) 131 | ret = test.methodArrayB() 132 | self.assertEqual(test.methodParamsArrayByte(ret), True) 133 | 134 | def test_return_array_as_object_array_of_strings(self): 135 | test = autoclass('org.jnius.BasicsTest')() 136 | self.assertEqual(test.methodReturnStrings(), ['Hello', 137 | '\U0001F30E']) 138 | 139 | def test_return_array_as_object_of_integers(self): 140 | test = autoclass('org.jnius.BasicsTest')() 141 | self.assertEqual(test.methodReturnIntegers(), [1, 2]) 142 | -------------------------------------------------------------------------------- /tests/test_bytearray.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from __future__ import division 3 | from __future__ import absolute_import 4 | import unittest 5 | from jnius import autoclass 6 | 7 | class StringArgumentForByteArrayTest(unittest.TestCase): 8 | 9 | def test_string_arg_for_byte_array(self): 10 | # the ByteBuffer.wrap() accept only byte[]. 11 | ByteBuffer = autoclass('java.nio.ByteBuffer') 12 | self.assertIsNotNone(ByteBuffer.wrap(b'hello world')) 13 | 14 | def test_string_arg_with_signed_char(self): 15 | ByteBuffer = autoclass('java.nio.ByteBuffer') 16 | self.assertIsNotNone(ByteBuffer.wrap(b'\x00\xffHello World\x7f')) 17 | 18 | def test_fill_byte_array(self): 19 | arr = [0, 0, 0] 20 | Test = autoclass('org.jnius.BasicsTest')() 21 | Test.fillByteArray(arr) 22 | # we don't received signed byte, but unsigned in python. 23 | self.assertEqual( 24 | arr, 25 | [127, 1, 129]) 26 | 27 | def test_create_bytearray(self): 28 | StringBufferInputStream = autoclass('java.io.StringBufferInputStream') 29 | nis = StringBufferInputStream("Hello world") 30 | barr = bytearray("\x00" * 5, encoding="utf8") 31 | self.assertEqual(nis.read(barr, 0, 5), 5) 32 | self.assertEqual(barr, b"Hello") 33 | 34 | def test_bytearray_ascii(self): 35 | ByteArrayInputStream = autoclass('java.io.ByteArrayInputStream') 36 | s = b"".join(bytes(x) for x in range(256)) 37 | nis = ByteArrayInputStream(s) 38 | barr = bytearray("\x00" * 256, encoding="ascii") 39 | self.assertEqual(nis.read(barr, 0, 256), 256) 40 | self.assertEqual(barr[:256], s[:256]) 41 | 42 | def test_empty_bytearray(self): 43 | Test = autoclass('org.jnius.BasicsTest')() 44 | arr = Test.methodReturnEmptyByteArray() 45 | self.assertEqual(len(arr), 0) 46 | with self.assertRaises(IndexError): 47 | arr[0] 48 | self.assertEqual(arr, []) 49 | self.assertEqual(arr[:1], []) 50 | self.assertEqual(arr.tostring(), b'') 51 | -------------------------------------------------------------------------------- /tests/test_cast.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from __future__ import division 3 | from __future__ import absolute_import 4 | import unittest 5 | from jnius.reflect import autoclass 6 | from jnius import cast 7 | 8 | 9 | class MultipleSignatureTest(unittest.TestCase): 10 | def test_multiple_constructors(self): 11 | String = autoclass('java.lang.String') 12 | s = String('hello world') 13 | self.assertEqual(s.__javaclass__, 'java/lang/String') 14 | o = cast('java.lang.Object', s) 15 | self.assertEqual(o.__javaclass__, 'java/lang/Object') 16 | 17 | def test_mmap_toString(self): 18 | mapClass = autoclass('java.util.HashMap') 19 | hmap = mapClass() 20 | hmap.put("a", "1") 21 | hmap.toString() 22 | mmap = cast('java.util.Map', hmap) 23 | mmap.toString() 24 | mmap.getClass() 25 | -------------------------------------------------------------------------------- /tests/test_chars_and_strings.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # from __future__ import print_function 3 | from __future__ import division 4 | from __future__ import absolute_import 5 | import unittest 6 | from jnius.reflect import autoclass, JavaException 7 | 8 | 9 | class CharsAndStringsTest(unittest.TestCase): 10 | 11 | def test_char_fields(self): 12 | Test = autoclass('org.jnius.CharsAndStrings', 13 | include_protected=False, include_private=False) 14 | test = Test() 15 | 16 | self.assertEqual(test.testChar1, 'a') 17 | self.assertEqual(test.testChar2, 'ä') 18 | self.assertEqual(test.testChar3, '☺') 19 | 20 | self.assertEqual(Test.testStaticChar1, 'a') 21 | self.assertEqual(Test.testStaticChar2, 'ä') 22 | self.assertEqual(Test.testStaticChar3, '☺') 23 | 24 | def test_string_fields(self): 25 | Test = autoclass('org.jnius.CharsAndStrings', 26 | include_protected=False, include_private=False) 27 | test = Test() 28 | 29 | self.assertEqual(test.testString1, "hello world") 30 | self.assertEqual(test.testString2, "umlauts: äöü") 31 | self.assertEqual(test.testString3, "happy face: ☺") 32 | 33 | self.assertEqual(Test.testStaticString1, "hello world") 34 | self.assertEqual(Test.testStaticString2, "umlauts: äöü") 35 | self.assertEqual(Test.testStaticString3, "happy face: ☺") 36 | 37 | def test_char_methods(self): 38 | Test = autoclass('org.jnius.CharsAndStrings', 39 | include_protected=False, include_private=False) 40 | test = Test() 41 | 42 | self.assertEqual(test.testChar(1, 'a'), 'a') 43 | self.assertEqual(test.testChar(2, 'ä'), 'ä') 44 | self.assertEqual(test.testChar(3, '☺'), '☺') 45 | 46 | self.assertEqual(Test.testStaticChar(1, 'a'), 'a') 47 | self.assertEqual(Test.testStaticChar(2, 'ä'), 'ä') 48 | self.assertEqual(Test.testStaticChar(3, '☺'), '☺') 49 | 50 | def test_string_methods(self): 51 | Test = autoclass('org.jnius.CharsAndStrings', 52 | include_protected=False, include_private=False) 53 | test = Test() 54 | 55 | self.assertEqual(test.testString(1, "hello world"), "hello world") 56 | self.assertEqual(test.testString(2, "umlauts: äöü"), "umlauts: äöü") 57 | self.assertEqual(test.testString(3, "happy face: ☺"), "happy face: ☺") 58 | 59 | self.assertEqual(Test.testStaticString(1, "hello world"), "hello world") 60 | self.assertEqual(Test.testStaticString(2, "umlauts: äöü"), "umlauts: äöü") 61 | self.assertEqual(Test.testStaticString(3, "happy face: ☺"), "happy face: ☺") 62 | 63 | def test_char_array(self): 64 | Test = autoclass('org.jnius.CharsAndStrings', 65 | include_protected=False, include_private=False) 66 | test = Test() 67 | 68 | charArray1 = ['a', 'b', 'c'] 69 | charArray2 = ['a', 'ä', '☺'] 70 | 71 | for c1, c2 in zip(charArray1, test.testCharArray1): 72 | self.assertEqual(c1, c2) 73 | for c1, c2 in zip(charArray1, test.testCharArray(1)): 74 | self.assertEqual(c1, c2) 75 | for c1, c2 in zip(charArray2, test.testCharArray2): 76 | self.assertEqual(c1, c2) 77 | for c1, c2 in zip(charArray2, test.testCharArray(2)): 78 | self.assertEqual(c1, c2) 79 | 80 | def test_static_char_array(self): 81 | Test = autoclass('org.jnius.CharsAndStrings', 82 | include_protected=False, include_private=False) 83 | 84 | charArray1 = ['a', 'b', 'c'] 85 | charArray2 = ['a', 'ä', '☺'] 86 | 87 | for c1, c2 in zip(charArray1, Test.testStaticCharArray1): 88 | self.assertEqual(c1, c2) 89 | for c1, c2 in zip(charArray1, Test.testStaticCharArray(1)): 90 | self.assertEqual(c1, c2) 91 | for c1, c2 in zip(charArray2, Test.testStaticCharArray2): 92 | self.assertEqual(c1, c2) 93 | for c1, c2 in zip(charArray2, Test.testStaticCharArray(2)): 94 | self.assertEqual(c1, c2) 95 | 96 | 97 | def test_java_string(self): 98 | JString = autoclass('java.lang.String') 99 | 100 | testString1 = JString('hello world') 101 | self.assertTrue(testString1.equals('hello world')) 102 | testString2 = JString('umlauts: äöü') 103 | self.assertTrue(testString2.equals('umlauts: äöü')) 104 | testString3 = JString('happy face: ☺') 105 | self.assertTrue(testString3.equals('happy face: ☺')) 106 | 107 | # two methods below are concerned with type-checking of arguments 108 | 109 | def test_pass_intfloat_as_string(self): 110 | CharsAndStrings = autoclass("org.jnius.CharsAndStrings") 111 | self.assertIsNone(CharsAndStrings.testStringDefNull) 112 | with self.assertRaisesRegex(TypeError, "Invalid instance of 'java/lang/Integer' passed for a 'java/lang/String'"): 113 | # we cannot provide an int to a String 114 | CharsAndStrings.setString("a", 2) 115 | with self.assertRaisesRegex(TypeError, "Invalid instance of 'java/lang/Float' passed for a 'java/lang/String'"): 116 | # we cannot provide an float to a String 117 | CharsAndStrings.setString("a", 2.2) 118 | alist = autoclass("java.util.ArrayList")() 119 | with self.assertRaisesRegex(TypeError, "Invalid instance of 'java/util/ArrayList' passed for a 'java/lang/String'"): 120 | # we cannot provide a list to a String 121 | CharsAndStrings.setString("a", alist) 122 | system = autoclass("java.lang.System") 123 | with self.assertRaises(JavaException): 124 | system.setErr("a string") 125 | 126 | def test_pass_string_as_int(self): 127 | CharsAndStrings = autoclass("org.jnius.CharsAndStrings") 128 | self.assertEqual(0, CharsAndStrings.testInt) 129 | with self.assertRaisesRegex(TypeError, "an integer is required"): 130 | # we cannot provide a String to an int 131 | CharsAndStrings.setInt("a", "2") 132 | -------------------------------------------------------------------------------- /tests/test_class_argument.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from __future__ import division 3 | from __future__ import absolute_import 4 | import unittest 5 | from jnius.reflect import autoclass 6 | 7 | class BasicsTest(unittest.TestCase): 8 | 9 | def test_static_methods(self): 10 | ClassArgument = autoclass('org.jnius.ClassArgument') 11 | self.assertEqual(ClassArgument.getName(ClassArgument), 'class org.jnius.ClassArgument') 12 | -------------------------------------------------------------------------------- /tests/test_closeable.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Test creating for java.io.Closeable dunder 3 | ''' 4 | 5 | from __future__ import absolute_import 6 | import unittest 7 | from jnius import autoclass, JavaException, protocol_map 8 | 9 | 10 | class TestCloseable(unittest.TestCase): 11 | ''' 12 | TestCase for using java.io.Closeable dunder 13 | ''' 14 | 15 | def test_stringreader_closeable(self): 16 | ''' 17 | this checkes that java.lang.AutoCloseable instances gain 18 | the correct dunder methods 19 | ''' 20 | swCheck = autoclass("java.io.StringWriter")() 21 | self.assertTrue("__enter__" in dir(swCheck)) 22 | self.assertTrue("__exit__" in dir(swCheck)) 23 | 24 | with autoclass("java.io.StringWriter")() as sw: 25 | sw.write("Hello") 26 | 27 | def test_our_closeable(self): 28 | ''' 29 | this checkes that closeable dunder methods are actually called 30 | org.jnius.CloseableClass has java.io.Closeable, to differ from 31 | java.lang.AutoCloseable (which is what is in interface_map) 32 | ''' 33 | ourcloseableClz = autoclass("org.jnius.CloseableClass") 34 | self.assertTrue("__enter__" in dir(ourcloseableClz())) 35 | self.assertTrue("__exit__" in dir(ourcloseableClz())) 36 | 37 | self.assertTrue(ourcloseableClz.open) 38 | with ourcloseableClz() as ourcloseable2: 39 | self.assertTrue(ourcloseableClz.open) 40 | self.assertFalse(ourcloseableClz.open) 41 | 42 | def test_protocol_map(self): 43 | self.assertTrue("java.util.List" in protocol_map) 44 | -------------------------------------------------------------------------------- /tests/test_collections.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | import unittest 3 | from jnius import autoclass, protocol_map 4 | 5 | 6 | class TestCollections(unittest.TestCase): 7 | 8 | def test_hashset(self): 9 | hset = autoclass('java.util.HashSet')() 10 | data = {1,2} 11 | # add is in both Python and Java 12 | for k in data: 13 | hset.add(k) 14 | # __len__ 15 | print(dir(hset)) 16 | self.assertEqual(len(data), len(hset)) 17 | # __contains__ 18 | for k in data: 19 | self.assertTrue(k in hset) 20 | self.assertFalse(0 in hset) 21 | # __iter__ 22 | for k in hset: 23 | self.assertTrue(k in data) 24 | # __delitem__ 25 | for k in data: 26 | del(hset[k]) 27 | self.assertFalse(k in hset) 28 | 29 | def test_hashmap(self): 30 | hmap = autoclass('java.util.HashMap')() 31 | data = {1 : 'hello', 2 : 'world'} 32 | # __setitem__ 33 | for k,v in data.items(): 34 | hmap[k] = v 35 | # __len__ 36 | self.assertEqual(len(data), len(hmap)) 37 | # __contains__ 38 | for k,v in data.items(): 39 | self.assertTrue(k in hmap) 40 | self.assertEqual(data[k], hmap[k]) 41 | # __iter__ 42 | for k in hmap: 43 | self.assertTrue(k in data) 44 | # __map_entry__ 45 | for k,v in hmap.entrySet(): 46 | self.assertEqual(data[k], v) 47 | # __contains__ 48 | self.assertFalse(0 in hmap) 49 | # __delitem__ 50 | for k in data: 51 | del(hmap[k]) 52 | self.assertFalse(k in hmap) 53 | 54 | if __name__ == '__main__': 55 | unittest.main() 56 | -------------------------------------------------------------------------------- /tests/test_comparable.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | import unittest 3 | from jnius import autoclass, protocol_map 4 | 5 | class ComparableTest(unittest.TestCase): 6 | def __init__(self, *args, **kwargs): 7 | super(ComparableTest, self).__init__(*args, **kwargs) 8 | 9 | def test_compare_integer(self): 10 | five = autoclass('java.lang.Integer')(5) 11 | six = autoclass('java.lang.Integer')(6) 12 | six_two = autoclass('java.lang.Integer')(6) 13 | self.assertTrue(five < six) 14 | self.assertTrue(six > five) 15 | self.assertTrue(six == six_two) 16 | self.assertTrue(five <= six) 17 | self.assertTrue(six >= five) 18 | self.assertTrue(six >= six_two) 19 | self.assertTrue(six <= six_two) 20 | 21 | if __name__ == '__main__': 22 | unittest.main() -------------------------------------------------------------------------------- /tests/test_constructor.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Test creating an instance of a Java class and fetching its values. 3 | ''' 4 | 5 | from __future__ import absolute_import 6 | import unittest 7 | from jnius import autoclass, JavaException 8 | 9 | 10 | class TestConstructor(unittest.TestCase): 11 | ''' 12 | TestCase for using constructors with PyJNIus. 13 | ''' 14 | 15 | def test_constructor_none(self): 16 | ''' 17 | Empty constructor, baked value in the .java file. 18 | ''' 19 | 20 | ConstructorTest = autoclass('org.jnius.ConstructorTest') 21 | inst = ConstructorTest() 22 | self.assertEqual(inst.ret, 753) 23 | self.assertTrue(ConstructorTest._class.isInstance(inst)) 24 | self.assertTrue(inst.getClass().isInstance(inst)) 25 | 26 | def test_constructor_int(self): 27 | ''' 28 | Constructor expecting int and setting it as public 'ret' property. 29 | ''' 30 | 31 | ConstructorTest = autoclass('org.jnius.ConstructorTest') 32 | inst = ConstructorTest(123) 33 | self.assertEqual(inst.ret, 123) 34 | self.assertTrue(ConstructorTest._class.isInstance(inst)) 35 | self.assertTrue(inst.getClass().isInstance(inst)) 36 | 37 | def test_constructor_string(self): 38 | ''' 39 | Constructor expecting char, casting it to int and setting it 40 | as public 'ret' property. 41 | ''' 42 | 43 | ConstructorTest = autoclass('org.jnius.ConstructorTest') 44 | inst = ConstructorTest('a') 45 | self.assertEqual(inst.ret, ord('a')) 46 | self.assertTrue(ConstructorTest._class.isInstance(inst)) 47 | self.assertTrue(inst.getClass().isInstance(inst)) 48 | 49 | def test_constructor_multiobj(self): 50 | ''' 51 | Constructor expecting String. 52 | ''' 53 | 54 | outputStream = autoclass('java.lang.System').out 55 | ConstructorTest = autoclass('org.jnius.ConstructorTest') 56 | inst = ConstructorTest(outputStream, signature="(Ljava/io/OutputStream;)V") 57 | self.assertEqual(inst.ret, 42) 58 | self.assertTrue(ConstructorTest._class.isInstance(inst)) 59 | self.assertTrue(inst.getClass().isInstance(inst)) 60 | 61 | def test_constructor_int_string(self): 62 | ''' 63 | Constructor expecting int and char, casting char to int and summing it 64 | as public 'ret' property. 65 | ''' 66 | 67 | ConstructorTest = autoclass('org.jnius.ConstructorTest') 68 | inst = ConstructorTest(3, 'a') 69 | self.assertEqual(inst.ret, 3 + ord('a')) 70 | self.assertTrue(ConstructorTest._class.isInstance(inst)) 71 | self.assertTrue(inst.getClass().isInstance(inst)) 72 | 73 | def test_constructor_exception(self): 74 | ''' 75 | No such constructor found (no such signature), 76 | should raise JavaException. 77 | ''' 78 | 79 | ConstructorTest = autoclass('org.jnius.ConstructorTest') 80 | with self.assertRaises(JavaException): 81 | ConstructorTest('1.', 2.0, False) 82 | 83 | 84 | if __name__ == '__main__': 85 | unittest.main() 86 | -------------------------------------------------------------------------------- /tests/test_dir.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from __future__ import division 3 | from __future__ import absolute_import 4 | import unittest 5 | from jnius.reflect import autoclass 6 | 7 | class DirTest(unittest.TestCase): 8 | 9 | def test_varargs_signatures(self): 10 | # >>> from jnius import autoclass 11 | # >>> cls = autoclass('java.lang.System') 12 | # >>> cls.out.printf.signatures() 13 | # [(['java/lang/String', 'java/lang/Object...'], 'java/io/PrintStream'), 14 | # (['java/util/Locale', 'java/lang/String', 'java/lang/Object...'], 'java/io/PrintStream')] 15 | 16 | cls = autoclass("java.lang.System") 17 | result = cls.out.printf.signatures() 18 | 19 | assert isinstance(result, list) 20 | assert all(isinstance(f, tuple) for f in result) 21 | 22 | assert (['java/lang/String', 'java/lang/Object...'], 'java/io/PrintStream') in result 23 | assert (['java/util/Locale', 'java/lang/String', 'java/lang/Object...'], 'java/io/PrintStream') in result 24 | 25 | def test_array_signatures(self): 26 | # >>> from jnius import autoclass 27 | # >>> cls = autoclass('java.util.List') 28 | # >>> cls.toArray.signatures() 29 | # [([], 'java/lang/Object[]'), 30 | # (['java/lang/Object[]'], 'java/lang/Object[]')] 31 | 32 | cls = autoclass("java.util.List") 33 | result = cls.toArray.signatures() 34 | 35 | assert isinstance(result, list) 36 | assert all(isinstance(f, tuple) for f in result) 37 | 38 | assert ([], 'java/lang/Object[]') in result 39 | assert (['java/lang/Object[]'], 'java/lang/Object[]') in result 40 | 41 | def test_signatures(self): 42 | # >>> from jnius import autoclass 43 | # >>> cls = autoclass('java.lang.String') 44 | # >>> cls.valueOf.signatures() 45 | # [(['boolean'], 'java/lang/String'), 46 | # (['char'], 'java/lang/String'), 47 | # (['char[]'], 'java/lang/String'), 48 | # (['char[]', 'int', 'int'], 'java/lang/String'), 49 | # (['double'], 'java/lang/String'), 50 | # (['float'], 'java/lang/String'), 51 | # (['int'], 'java/lang/String'), 52 | # (['java/lang/Object'], 'java/lang/String'), 53 | # (['long'], 'java/lang/String')] 54 | 55 | cls = autoclass("java.lang.String") 56 | result = cls.valueOf.signatures() 57 | 58 | assert isinstance(result, list) 59 | assert all(isinstance(f, tuple) for f in result) 60 | 61 | assert sorted(result) == sorted([ 62 | (['boolean'], 'java/lang/String'), 63 | (['char'], 'java/lang/String'), 64 | (['char[]'], 'java/lang/String'), 65 | (['char[]', 'int', 'int'], 'java/lang/String'), 66 | (['double'], 'java/lang/String'), 67 | (['float'], 'java/lang/String'), 68 | (['int'], 'java/lang/String'), 69 | (['java/lang/Object'], 'java/lang/String'), 70 | (['long'], 'java/lang/String') 71 | ]) 72 | -------------------------------------------------------------------------------- /tests/test_enum.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Enum in Java returns itself when trying to get a value, e.g.: 3 | 4 | SimpleEnum.GOOD 5 | 6 | is of class instance SimpleEnum. 7 | 8 | `javap -s SimpleEnum.class`:: 9 | 10 | public final class org.jnius.SimpleEnum ... { 11 | public static final org.jnius.SimpleEnum GOOD; 12 | descriptor: Lorg/jnius/SimpleEnum; <-- this 13 | ... 14 | ''' 15 | 16 | from __future__ import absolute_import 17 | 18 | import unittest 19 | from jnius.reflect import autoclass 20 | 21 | 22 | class TestSimpleEnum(unittest.TestCase): 23 | ''' 24 | Test simple enum from java-src/org/jnius/SimpleEnum.java file. 25 | ''' 26 | 27 | def test_enum(self): 28 | ''' 29 | Make sure Enum returns something. 30 | ''' 31 | SimpleEnum = autoclass('org.jnius.SimpleEnum') 32 | self.assertTrue(SimpleEnum) 33 | 34 | def test_value(self): 35 | ''' 36 | Test whether the enum values return proper types and strings. 37 | ''' 38 | SimpleEnum = autoclass('org.jnius.SimpleEnum') 39 | 40 | values = [SimpleEnum.GOOD, SimpleEnum.BAD, SimpleEnum.UGLY] 41 | for val in values: 42 | self.assertTrue(val) 43 | self.assertIsInstance(val, SimpleEnum) 44 | self.assertEqual( 45 | type(val), 46 | type(SimpleEnum.valueOf(val.toString())) 47 | ) 48 | 49 | # 'GOOD', 'BAD', 'UGLY' strings 50 | self.assertEqual( 51 | val.toString(), 52 | SimpleEnum.valueOf(val.toString()).toString() 53 | ) 54 | 55 | def test_value_nested(self): 56 | ''' 57 | Test that we cover the circular implementation of java.lang.Enum 58 | that on value returns the parent i.e. the Enum class instead of 59 | e.g. some Exception or segfault which means we can do Enum.X.X.X... 60 | 61 | Currently does not check anything, ref pyjnius#32: 62 | https://github.com/kivy/pyjnius/issues/32. 63 | ''' 64 | _ = autoclass('org.jnius.SimpleEnum') 65 | # self.assertTrue(SimpleEnum.UGLY.UGLY) 66 | 67 | 68 | if __name__ == '__main__': 69 | unittest.main() 70 | -------------------------------------------------------------------------------- /tests/test_export_class.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from __future__ import division 3 | from __future__ import absolute_import 4 | import unittest 5 | from jnius import autoclass, java_method, PythonJavaClass 6 | 7 | Iterable = autoclass('java.lang.Iterable') 8 | ArrayList = autoclass('java.util.ArrayList') 9 | Runnable = autoclass('java.lang.Runnable') 10 | Thread = autoclass('java.lang.Thread') 11 | Object = autoclass('java.lang.Object') 12 | 13 | class SampleIterable(PythonJavaClass): 14 | __javainterfaces__ = ['java/lang/Iterable'] 15 | 16 | @java_method('()Ljava/lang/Iterator;') 17 | def iterator(self): 18 | sample = ArrayList() 19 | sample.add(1) 20 | sample.add(2) 21 | return sample.iterator() 22 | 23 | class ExportClassTest(unittest.TestCase): 24 | def test_is_instance(self): 25 | array_list = ArrayList() 26 | thread = Thread() 27 | sample_iterable = SampleIterable() 28 | 29 | self.assertIsInstance(sample_iterable, Iterable) 30 | self.assertIsInstance(sample_iterable, Object) 31 | self.assertIsInstance(sample_iterable, SampleIterable) 32 | self.assertNotIsInstance(sample_iterable, Runnable) 33 | self.assertNotIsInstance(sample_iterable, Thread) 34 | 35 | self.assertIsInstance(array_list, Iterable) 36 | self.assertIsInstance(array_list, ArrayList) 37 | self.assertIsInstance(array_list, Object) 38 | 39 | self.assertNotIsInstance(thread, Iterable) 40 | self.assertIsInstance(thread, Thread) 41 | self.assertIsInstance(thread, Runnable) 42 | 43 | def test_subclasses_work_for_arg_matching(self): 44 | array_list = ArrayList() 45 | array_list.add(SampleIterable()) 46 | self.assertIsInstance(array_list.get(0), Iterable) 47 | self.assertIsInstance(array_list.get(0), SampleIterable) 48 | 49 | 50 | def assertIsSubclass(self, cls, parent): 51 | if not issubclass(cls, parent): 52 | self.fail("%s is not a subclass of %s" % 53 | (cls.__name__, parent.__name__)) 54 | 55 | def assertNotIsSubclass(self, cls, parent): 56 | if issubclass(cls, parent): 57 | self.fail("%s is a subclass of %s" % 58 | (cls.__name__, parent.__name__)) 59 | 60 | def test_is_subclass(self): 61 | self.assertIsSubclass(Thread, Runnable) 62 | self.assertIsSubclass(ArrayList, Iterable) 63 | self.assertIsSubclass(ArrayList, Object) 64 | self.assertIsSubclass(SampleIterable, Iterable) 65 | self.assertNotIsSubclass(Thread, Iterable) 66 | self.assertNotIsSubclass(ArrayList, Runnable) 67 | self.assertNotIsSubclass(Runnable, Thread) 68 | self.assertNotIsSubclass(Iterable, SampleIterable) 69 | -------------------------------------------------------------------------------- /tests/test_implementation.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import print_function 3 | from __future__ import division 4 | from __future__ import absolute_import 5 | import unittest 6 | from jnius.reflect import autoclass 7 | 8 | 9 | class ImplementationTest(unittest.TestCase): 10 | 11 | def test_println(self): 12 | # System.out.println implies recursive lookup, and j_self assignation. 13 | # It was crashing during the implementation :/ 14 | System = autoclass('java.lang.System') 15 | System.out.println('') 16 | 17 | def test_printf(self): 18 | System = autoclass('java.lang.System') 19 | System.out.printf('hi\n') 20 | System.out.printf('hi %s %s\n', 'jnius', 'other string') 21 | 22 | def test_unicode(self): 23 | System = autoclass('java.lang.System') 24 | System.out.printf(u'é') 25 | 26 | Stack = autoclass('java.util.Stack') 27 | stack = Stack() 28 | emoji = u'\U0001F602' 29 | stack.push(emoji) 30 | popped = stack.pop() 31 | self.assertEqual(emoji, popped) 32 | -------------------------------------------------------------------------------- /tests/test_inheritance.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | def test_methodcalls(): 4 | from jnius import autoclass 5 | Parent = autoclass('org.jnius.Parent') 6 | Child = autoclass('org.jnius.Child') 7 | child = Child.newInstance() 8 | parent = Parent.newInstance() 9 | assert parent.doCall(parent) == 0 10 | assert child.doCall(0) == 1 11 | assert child.doCall(child) == 0 12 | 13 | def test_fields(): 14 | from jnius import autoclass 15 | Parent = autoclass('org.jnius.Parent') 16 | Child = autoclass('org.jnius.Child') 17 | child = Child.newInstance() 18 | parent = Parent.newInstance() 19 | assert parent.PARENT_FIELD == 0 20 | assert child.CHILD_FIELD == 1 21 | assert child.PARENT_FIELD == 0 22 | 23 | def test_staticfields(): 24 | from jnius import autoclass 25 | Parent = autoclass('org.jnius.Parent') 26 | Child = autoclass('org.jnius.Child') 27 | child = Child.newInstance() 28 | parent = Parent.newInstance() 29 | assert Parent.STATIC_PARENT_FIELD == 1 30 | assert Parent.StaticGetParentStaticField() == 1 31 | assert Child.STATIC_PARENT_FIELD == 1 32 | assert Child.StaticGetParentStaticField() == 1 33 | assert parent.STATIC_PARENT_FIELD == 1 34 | assert child.STATIC_PARENT_FIELD == 1 35 | assert parent.StaticGetParentStaticField() == 1 36 | assert child.StaticGetParentStaticField() == 1 37 | assert parent.getParentStaticField() == 1 38 | assert child.getParentStaticField() == 1 39 | 40 | # now test setting in parent 41 | Parent.STATIC_PARENT_FIELD = 5 42 | assert parent.STATIC_PARENT_FIELD == 5 43 | assert Child.STATIC_PARENT_FIELD == 5 44 | assert child.STATIC_PARENT_FIELD == 5 45 | assert Parent.StaticGetParentStaticField() == 5 46 | assert Child.StaticGetParentStaticField() == 5 47 | assert parent.StaticGetParentStaticField() == 5 48 | assert child.StaticGetParentStaticField() == 5 49 | assert parent.getParentStaticField() == 5 50 | assert child.getParentStaticField() == 5 51 | 52 | # now test setting in child 53 | child.STATIC_PARENT_FIELD = 10 54 | assert Child.STATIC_PARENT_FIELD == 10 55 | assert child.STATIC_PARENT_FIELD == 10 56 | assert Parent.STATIC_PARENT_FIELD == 10 57 | assert parent.STATIC_PARENT_FIELD == 10 58 | assert Parent.StaticGetParentStaticField() == 10 59 | assert Child.StaticGetParentStaticField() == 10 60 | assert parent.StaticGetParentStaticField() == 10 61 | assert child.StaticGetParentStaticField() == 10 62 | assert parent.getParentStaticField() == 10 63 | assert child.getParentStaticField() == 10 64 | 65 | def test_newinstance(): 66 | from jnius import autoclass 67 | Parent = autoclass('org.jnius.Parent') 68 | Child = autoclass('org.jnius.Child') 69 | 70 | child = Child.newInstance() 71 | assert isinstance(child, Child) 72 | assert isinstance(child, Parent) 73 | 74 | if __name__ == "__main__": 75 | import jnius_config 76 | #jnius_config.add_options('-Xcheck:jni') 77 | test_staticfields() 78 | 79 | -------------------------------------------------------------------------------- /tests/test_int_vs_long.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, unicode_literals 2 | import unittest 3 | from jnius import autoclass, cast, PythonJavaClass, java_method 4 | 5 | 6 | class _TestImplemIterator(PythonJavaClass): 7 | __javainterfaces__ = ['java/util/ListIterator'] 8 | 9 | 10 | class _TestImplem(PythonJavaClass): 11 | __javainterfaces__ = ['java/util/List'] 12 | 13 | def __init__(self, *args): 14 | super(_TestImplem, self).__init__(*args) 15 | self.data = list(args) 16 | 17 | @java_method('()I') 18 | def size(self): 19 | return len(self.data) 20 | 21 | @java_method('(I)Ljava/lang/Object;') 22 | def get(self, index): 23 | return self.data[index] 24 | 25 | @java_method('(ILjava/lang/Object;)Ljava/lang/Object;') 26 | def set(self, index, obj): 27 | old_object = self.data[index] 28 | self.data[index] = obj 29 | return old_object 30 | 31 | 32 | class TestIntLongConversion(unittest.TestCase): 33 | def test_reverse(self): 34 | ''' 35 | String comparison because values are the same for INT and LONG, 36 | but only __str__ shows the real difference. 37 | ''' 38 | 39 | Collections = autoclass('java.util.Collections') 40 | List = autoclass('java.util.List') 41 | pylist = list(range(10)) 42 | a = _TestImplem(*pylist) 43 | self.assertEqual(a.data, pylist) 44 | self.assertEqual(str(a.data), '[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]') 45 | 46 | # reverse the array, be sure it's converted back to INT! 47 | Collections.reverse(a) 48 | 49 | # conversion to/from Java objects hides INT/LONG conv on Py2 50 | # which is wrong to switch between because even Java 51 | # recognizes INT and LONG types separately (Py3 doesn't) 52 | self.assertEqual(a.data, list(reversed(pylist))) 53 | self.assertNotIn('L', str(a.data)) 54 | self.assertEqual(str(a.data), '[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]') 55 | 56 | 57 | if __name__ == '__main__': 58 | unittest.main() 59 | -------------------------------------------------------------------------------- /tests/test_interface.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from __future__ import division 3 | from __future__ import absolute_import 4 | import unittest 5 | 6 | from jnius import autoclass, JavaException 7 | 8 | 9 | class Interface(unittest.TestCase): 10 | 11 | def test_reflect_interface(self): 12 | Interface = autoclass('org.jnius.InterfaceWithPublicEnum') 13 | self.assertTrue(Interface) 14 | 15 | def test_reflect_enum_in_interface(self): 16 | ATTITUDE = autoclass('org.jnius.InterfaceWithPublicEnum$ATTITUDE') 17 | self.assertTrue(ATTITUDE) 18 | self.assertTrue(ATTITUDE.GOOD) 19 | self.assertTrue(ATTITUDE.BAD) 20 | self.assertTrue(ATTITUDE.UGLY) 21 | -------------------------------------------------------------------------------- /tests/test_jnitable_overflow.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from __future__ import division 3 | from __future__ import absolute_import 4 | # run it, and check with Java VisualVM if we are eating too much memory or not! 5 | if __name__ == '__main__': 6 | from jnius import autoclass 7 | Stack = autoclass('java.util.Stack') 8 | i = 0 9 | while True: 10 | i += 1 11 | stack = Stack() 12 | stack.push('hello') 13 | -------------------------------------------------------------------------------- /tests/test_jnius_config.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import pytest 3 | import jnius_config 4 | 5 | 6 | class TestJniusConfig: 7 | def setup_method(self): 8 | """Resets the options global.""" 9 | jnius_config.options = [] 10 | jnius_config.vm_running = False 11 | jnius_config.classpath = None 12 | 13 | def teardown_method(self): 14 | self.setup_method() 15 | 16 | @pytest.mark.parametrize( 17 | "function,args", 18 | [ 19 | (jnius_config.set_options, ("option1",)), 20 | (jnius_config.add_options, ("option1",)), 21 | (jnius_config.set_classpath, (".",)), 22 | (jnius_config.add_classpath, (".",)), 23 | ], 24 | ) 25 | def test_set_options_vm_running(self, function, args): 26 | """The functions should only raise an error when the vm is running.""" 27 | assert jnius_config.vm_running is False 28 | function(*args) 29 | jnius_config.vm_running = True 30 | with pytest.raises(ValueError) as ex_info: 31 | function(*args) 32 | pytest.mark.skipif( 33 | sys.version_info < (3, 5), reason="Exception args are different on Python 2" 34 | ) 35 | assert "VM is already running, can't set" in ex_info.value.args[0] 36 | 37 | def test_set_options(self): 38 | assert jnius_config.vm_running is False 39 | assert jnius_config.options == [] 40 | jnius_config.set_options("option1", "option2") 41 | assert jnius_config.options == ["option1", "option2"] 42 | jnius_config.set_options("option3") 43 | assert jnius_config.options == ["option3"] 44 | 45 | def test_add_options(self): 46 | assert jnius_config.vm_running is False 47 | assert jnius_config.options == [] 48 | jnius_config.add_options("option1", "option2") 49 | assert jnius_config.options == ["option1", "option2"] 50 | jnius_config.add_options("option3") 51 | assert jnius_config.options == ["option1", "option2", "option3"] 52 | 53 | def test_set_classpath(self): 54 | assert jnius_config.vm_running is False 55 | assert jnius_config.classpath is None 56 | jnius_config.set_classpath(".") 57 | assert jnius_config.classpath == ["."] 58 | jnius_config.set_classpath(".", "/usr/local/fem/plugins/*") 59 | assert jnius_config.classpath == [".", "/usr/local/fem/plugins/*"] 60 | 61 | def test_add_classpath(self): 62 | assert jnius_config.vm_running is False 63 | assert jnius_config.classpath is None 64 | jnius_config.add_classpath(".") 65 | assert jnius_config.classpath == ["."] 66 | jnius_config.add_classpath("/usr/local/fem/plugins/*") 67 | assert jnius_config.classpath == [".", "/usr/local/fem/plugins/*"] 68 | -------------------------------------------------------------------------------- /tests/test_jvm_options.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from __future__ import division 3 | from __future__ import absolute_import 4 | import json 5 | import pytest 6 | import subprocess 7 | import sys 8 | import textwrap 9 | 10 | 11 | class TestJVMOptions: 12 | @pytest.mark.skipif( 13 | sys.platform == 'android', 14 | reason='JNIus on Android does not take JVM options' 15 | ) 16 | def test_jvm_options(self): 17 | options = ['-Dtest.var{}=value'.format(i) for i in range(40)] 18 | process = subprocess.Popen([sys.executable, '-c', textwrap.dedent( 19 | '''\ 20 | import jnius_config 21 | import json 22 | import sys 23 | jnius_config.set_options(*json.load(sys.stdin)) 24 | import jnius 25 | ManagementFactory = jnius.autoclass("java.lang.management.ManagementFactory") 26 | json.dump(list(ManagementFactory.getRuntimeMXBean().getInputArguments()), sys.stdout)''')], 27 | bufsize=-1, stdin=subprocess.PIPE, stdout=subprocess.PIPE) 28 | stdoutdata, _ = process.communicate(json.dumps(options).encode()) 29 | assert process.wait() == 0 30 | actual_options = json.loads(stdoutdata.decode()) 31 | assert list(sorted(options)) == list(sorted(actual_options)) 32 | -------------------------------------------------------------------------------- /tests/test_lambdas.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from jnius import autoclass, JavaException 4 | 5 | class TestLambdas(unittest.TestCase): 6 | 7 | def testCallable(self): 8 | callFn = lambda: "done" 9 | executor = autoclass("java.util.concurrent.Executors").newFixedThreadPool(1) 10 | future = executor.submit(callFn) 11 | print(type(future)) 12 | self.assertEqual("done", future.get()) 13 | executor.shutdownNow() 14 | 15 | def testComparator(self): 16 | numbers = autoclass('java.util.ArrayList')() 17 | Collections = autoclass('java.util.Collections') 18 | numbers.add(1) 19 | numbers.add(3) 20 | revSort = lambda i, j: j - i 21 | Collections.sort(numbers, revSort) 22 | self.assertEqual(numbers[0], 3) 23 | self.assertEqual(numbers[1], 1) 24 | 25 | def testJavaUtilFunction(self): 26 | Collectors = autoclass("java.util.stream.Collectors") 27 | numbers = autoclass('java.util.ArrayList')() 28 | numbers.add(1) 29 | numbers.add(2) 30 | numbers.add(3) 31 | 32 | def squareFn(i): 33 | return i * i 34 | 35 | 36 | #J: List squares = numbers.stream().map( i -> i*i).collect(Collectors.toList()); 37 | squares = numbers.stream().map(lambda i : i * i).collect(Collectors.toList()) 38 | 39 | self.assertEqual(len(squares), len(numbers)) 40 | self.assertEqual(squares[0], 1) 41 | self.assertEqual(squares[1], 4) 42 | self.assertEqual(squares[2], 9) 43 | 44 | squares = numbers.stream().map(squareFn).collect(Collectors.toList()) 45 | 46 | self.assertEqual(len(squares), len(numbers)) 47 | self.assertEqual(squares[0], 1) 48 | self.assertEqual(squares[1], 4) 49 | self.assertEqual(squares[2], 9) 50 | 51 | 52 | if __name__ == '__main__': 53 | unittest.main() 54 | -------------------------------------------------------------------------------- /tests/test_method_multiple_signatures.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from __future__ import division 3 | from __future__ import absolute_import 4 | import unittest 5 | from jnius.reflect import autoclass 6 | 7 | 8 | class MultipleSignature(unittest.TestCase): 9 | 10 | def test_multiple_constructors(self): 11 | String = autoclass('java.lang.String') 12 | self.assertIsNotNone(String('Hello World')) 13 | self.assertIsNotNone(String(list('Hello World'))) 14 | self.assertIsNotNone(String(list('Hello World'), 3, 5)) 15 | 16 | def test_multiple_methods(self): 17 | String = autoclass('java.lang.String') 18 | s = String('hello') 19 | self.assertEqual(s.getBytes(), [104, 101, 108, 108, 111]) 20 | self.assertEqual(s.getBytes('utf8'), [104, 101, 108, 108, 111]) 21 | self.assertEqual(s.indexOf(ord('e')), 1) 22 | self.assertEqual(s.indexOf(ord('e'), 2), -1) 23 | 24 | def test_multiple_constructors_varargs(self): 25 | VariableArgConstructors = autoclass('org.jnius.VariableArgConstructors') 26 | c1 = VariableArgConstructors(1, 'var2', 42, None, 4) 27 | self.assertEqual(c1.constructorUsed, 1) 28 | c2 = VariableArgConstructors(1, 'var2', None, 4) 29 | self.assertEqual(c2.constructorUsed, 2) 30 | 31 | def test_multiple_methods_no_args(self): 32 | MultipleMethods = autoclass('org.jnius.MultipleMethods') 33 | self.assertEqual(MultipleMethods.resolve(), 'resolved no args') 34 | 35 | def test_multiple_methods_one_arg(self): 36 | MultipleMethods = autoclass('org.jnius.MultipleMethods') 37 | self.assertEqual(MultipleMethods.resolve('arg'), 'resolved one arg') 38 | 39 | def test_multiple_methods_two_args(self): 40 | MultipleMethods = autoclass('org.jnius.MultipleMethods') 41 | self.assertEqual(MultipleMethods.resolve('one', 'two'), 'resolved two args') 42 | 43 | def test_multiple_methods_two_string_and_an_integer(self): 44 | MultipleMethods = autoclass('org.jnius.MultipleMethods') 45 | self.assertEqual(MultipleMethods.resolve('one', 'two', 1), 'resolved two string and an integer') 46 | 47 | def test_multiple_methods_two_string_and_two_integers(self): 48 | MultipleMethods = autoclass('org.jnius.MultipleMethods') 49 | self.assertEqual(MultipleMethods.resolve('one', 'two', 1, 2), 'resolved two string and two integers') 50 | 51 | def test_multiple_methods_varargs(self): 52 | MultipleMethods = autoclass('org.jnius.MultipleMethods') 53 | self.assertEqual(MultipleMethods.resolve(1, 2, 3), 'resolved varargs') 54 | 55 | def test_multiple_methods_two_args_and_varargs(self): 56 | MultipleMethods = autoclass('org.jnius.MultipleMethods') 57 | self.assertEqual(MultipleMethods.resolve('one', 'two', 1, 2, 3), 'resolved two args and varargs') 58 | 59 | def test_multiple_methods_one_int_one_small_long_and_a_string(self): 60 | MultipleMethods = autoclass('org.jnius.MultipleMethods') 61 | self.assertEqual(MultipleMethods.resolve( 62 | 1, 1, "one"), "resolved one int, one long and a string") 63 | 64 | def test_multiple_methods_one_int_one_actual_long_and_a_string(self): 65 | MultipleMethods = autoclass('org.jnius.MultipleMethods') 66 | self.assertEqual(MultipleMethods.resolve( 67 | 1, 2 ** 63 - 1, "one"), "resolved one int, one long and a string") 68 | -------------------------------------------------------------------------------- /tests/test_multidimension.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from __future__ import division 3 | from __future__ import absolute_import 4 | import unittest 5 | from jnius.reflect import autoclass 6 | 7 | class MultipleDimensionsTest(unittest.TestCase): 8 | 9 | def test_multiple_dimensions(self): 10 | MultipleDims = autoclass('org.jnius.MultipleDimensions') 11 | matrix = [[1, 2, 3], 12 | [4, 5, 6], 13 | [7, 8, 9]] 14 | self.assertEqual(MultipleDims.methodParamsMatrixI(matrix), True) 15 | self.assertEqual(MultipleDims.methodReturnMatrixI(), matrix) 16 | -------------------------------------------------------------------------------- /tests/test_object_args.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Check various function arguments to be properly passed to Java function 3 | as an Object that is not `null` except `None` itself. 4 | ''' 5 | 6 | from __future__ import print_function 7 | from __future__ import absolute_import 8 | from __future__ import unicode_literals 9 | 10 | import unittest 11 | from jnius import autoclass, JavaException 12 | 13 | 14 | ObjectArgument = autoclass('org.jnius.ObjectArgument') 15 | 16 | 17 | class ArgumentsTest(unittest.TestCase): 18 | ''' 19 | Tests for function arguments. 20 | ''' 21 | 22 | def test_argument_none(self): 23 | ''' 24 | Converts Python None to java.lang.Object. 25 | ''' 26 | self.assertEqual(ObjectArgument.checkObject(None), -1) 27 | 28 | def test_argument_emptylist(self): 29 | ''' 30 | Converts Python list to java.lang.Object. 31 | ''' 32 | self.assertEqual(ObjectArgument.checkObject([]), 0) 33 | 34 | def test_argument_emptytuple(self): 35 | ''' 36 | Converts Python tuple to java.lang.Object. 37 | ''' 38 | self.assertEqual(ObjectArgument.checkObject(()), 0) 39 | 40 | def test_argument_list_emptylist(self): 41 | ''' 42 | Converts Python list to java.lang.Object. 43 | ''' 44 | self.assertEqual(ObjectArgument.checkObject([[], ]), 0) 45 | 46 | def test_argument_tuple_emptytuple(self): 47 | ''' 48 | Converts Python tuple to java.lang.Object. 49 | ''' 50 | self.assertEqual(ObjectArgument.checkObject(((), )), 0) 51 | 52 | def test_argument_list_none(self): 53 | ''' 54 | Converts Python list to java.lang.Object. 55 | ''' 56 | self.assertEqual(ObjectArgument.checkObject([None, ]), 0) 57 | 58 | def test_argument_tuple_none(self): 59 | ''' 60 | Converts Python tuple to java.lang.Object. 61 | ''' 62 | self.assertEqual(ObjectArgument.checkObject((None, )), 0) 63 | 64 | def test_argument_emptyunicode(self): 65 | ''' 66 | Converts Python unicode to java.lang.Object. 67 | ''' 68 | self.assertEqual(ObjectArgument.checkObject(u''), 0) 69 | 70 | def test_argument_emptybytes(self): 71 | ''' 72 | Converts Python bytes to Java String. 73 | ''' 74 | self.assertEqual(ObjectArgument.checkObject(b''), 0) 75 | 76 | 77 | if __name__ == '__main__': 78 | unittest.main() 79 | -------------------------------------------------------------------------------- /tests/test_output_args.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from __future__ import division 3 | from __future__ import absolute_import 4 | import unittest 5 | from jnius import autoclass 6 | 7 | class OutputArgs(unittest.TestCase): 8 | 9 | def test_string_output_args(self): 10 | String = autoclass('java.lang.String') 11 | string = String('word'.encode('utf-8')) 12 | btarray= [0] * 4 13 | string.getBytes(0, 4, btarray, 0) 14 | self.assertEqual(btarray, [119, 111, 114, 100]) 15 | -------------------------------------------------------------------------------- /tests/test_pass_by_reference_or_value.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from __future__ import division 3 | from __future__ import absolute_import 4 | import unittest 5 | from jnius import autoclass 6 | 7 | class PassByReferenceOrValueTest(unittest.TestCase): 8 | 9 | def _verify(self, numbers, changed): 10 | for i in range(len(numbers)): 11 | self.assertEqual(numbers[i], i * i if changed else i) 12 | 13 | def _verify_all(self, numbers, changed): 14 | for n, c in zip(numbers, changed): 15 | self._verify(n, c) 16 | 17 | def test_single_param_static(self): 18 | VariablePassing = autoclass('org.jnius.VariablePassing') 19 | 20 | # passed by reference (default), numbers should change 21 | numbers = list(range(10)) 22 | VariablePassing.singleParamStatic(numbers) 23 | self._verify(numbers, True) 24 | 25 | # passed by reference, numbers should change 26 | numbers = list(range(10)) 27 | VariablePassing.singleParamStatic(numbers, pass_by_reference=True) 28 | self._verify(numbers, True) 29 | 30 | # passed by value, numbers should not change 31 | numbers = list(range(10)) 32 | VariablePassing.singleParamStatic(numbers, pass_by_reference=False) 33 | self._verify(numbers, False) 34 | 35 | def test_single_param(self): 36 | VariablePassing = autoclass('org.jnius.VariablePassing') 37 | variablePassing = VariablePassing() 38 | 39 | # passed by reference (default), numbers should change 40 | numbers = list(range(10)) 41 | variablePassing.singleParam(numbers) 42 | self._verify(numbers, True) 43 | 44 | # passed by reference, numbers should change 45 | numbers = list(range(10)) 46 | variablePassing.singleParam(numbers, pass_by_reference=True) 47 | self._verify(numbers, True) 48 | 49 | # passed by value, numbers should not change 50 | numbers = list(range(10)) 51 | variablePassing.singleParam(numbers, pass_by_reference=False) 52 | self._verify(numbers, False) 53 | 54 | def test_multiple_params_static(self): 55 | VariablePassing = autoclass('org.jnius.VariablePassing') 56 | 57 | # passed by reference (default), all numbers should change 58 | numbers = [list(range(10)) for _ in range(4)] 59 | VariablePassing.multipleParamsStatic(*numbers) 60 | self._verify_all(numbers, [True] * 4) 61 | 62 | # passed by reference, all numbers should change 63 | numbers = [list(range(10)) for _ in range(4)] 64 | VariablePassing.multipleParamsStatic(*numbers, pass_by_reference=True) 65 | self._verify_all(numbers, [True] * 4) 66 | 67 | # passed by value, no numbers should change 68 | numbers = [list(range(10)) for _ in range(4)] 69 | VariablePassing.multipleParamsStatic(*numbers, pass_by_reference=False) 70 | self._verify_all(numbers, [False] * 4) 71 | 72 | # only the first set of numbers should change 73 | numbers = [list(range(10)) for _ in range(4)] 74 | VariablePassing.multipleParamsStatic(*numbers, pass_by_reference=[True, False]) 75 | self._verify_all(numbers, [True, False, False, False]) 76 | 77 | # only the first set of numbers should not change 78 | numbers = [list(range(10)) for _ in range(4)] 79 | VariablePassing.multipleParamsStatic(*numbers, pass_by_reference=[False, True]) 80 | self._verify_all(numbers, [False, True, True, True]) 81 | 82 | # only the odd sets of numbers should change 83 | numbers = [list(range(10)) for _ in range(4)] 84 | changed = (True, False, True, False) 85 | VariablePassing.multipleParamsStatic(*numbers, pass_by_reference=changed) 86 | self._verify_all(numbers, changed) 87 | 88 | # only the even sets of numbers should change 89 | numbers = [list(range(10)) for _ in range(4)] 90 | changed = (False, True, False, True) 91 | VariablePassing.multipleParamsStatic(*numbers, pass_by_reference=changed) 92 | self._verify_all(numbers, changed) 93 | 94 | def test_multiple_params(self): 95 | VariablePassing = autoclass('org.jnius.VariablePassing') 96 | variablePassing = VariablePassing() 97 | 98 | # passed by reference (default), all numbers should change 99 | numbers = [list(range(10)) for _ in range(4)] 100 | variablePassing.multipleParams(*numbers) 101 | self._verify_all(numbers, [True] * 4) 102 | 103 | # passed by reference, all numbers should change 104 | numbers = [list(range(10)) for _ in range(4)] 105 | variablePassing.multipleParams(*numbers, pass_by_reference=True) 106 | self._verify_all(numbers, [True] * 4) 107 | 108 | # passed by value, no numbers should change 109 | numbers = [list(range(10)) for _ in range(4)] 110 | variablePassing.multipleParams(*numbers, pass_by_reference=False) 111 | self._verify_all(numbers, [False] * 4) 112 | 113 | # only the first set of numbers should change 114 | numbers = [list(range(10)) for _ in range(4)] 115 | variablePassing.multipleParams(*numbers, pass_by_reference=[True, False]) 116 | self._verify_all(numbers, [True, False, False, False]) 117 | 118 | # only the first set of numbers should not change 119 | numbers = [list(range(10)) for _ in range(4)] 120 | variablePassing.multipleParams(*numbers, pass_by_reference=[False, True]) 121 | self._verify_all(numbers, [False, True, True, True]) 122 | 123 | # only the odd sets of numbers should change 124 | numbers = [list(range(10)) for _ in range(4)] 125 | changed = (True, False, True, False) 126 | variablePassing.multipleParams(*numbers, pass_by_reference=changed) 127 | self._verify_all(numbers, changed) 128 | 129 | # only the even sets of numbers should change 130 | numbers = [list(range(10)) for _ in range(4)] 131 | changed = (False, True, False, True) 132 | variablePassing.multipleParams(*numbers, pass_by_reference=changed) 133 | self._verify_all(numbers, changed) 134 | 135 | def test_contructor_single_param(self): 136 | VariablePassing = autoclass('org.jnius.VariablePassing') 137 | 138 | # passed by reference (default), numbers should change 139 | numbers = list(range(10)) 140 | variablePassing = VariablePassing(numbers) 141 | self._verify(numbers, True) 142 | 143 | # passed by reference, numbers should change 144 | numbers = list(range(10)) 145 | variablePassing = VariablePassing(numbers, pass_by_reference=True) 146 | self._verify(numbers, True) 147 | 148 | # passed by value, numbers should not change 149 | numbers = list(range(10)) 150 | variablePassing = VariablePassing(numbers, pass_by_reference=False) 151 | self._verify(numbers, False) 152 | 153 | def test_contructor_multiple_params(self): 154 | VariablePassing = autoclass('org.jnius.VariablePassing') 155 | 156 | # passed by reference (default), all numbers should change 157 | numbers = [list(range(10)) for _ in range(4)] 158 | variablePassing = VariablePassing(*numbers) 159 | self._verify_all(numbers, [True] * 4) 160 | 161 | # passed by reference, all numbers should change 162 | numbers = [list(range(10)) for _ in range(4)] 163 | variablePassing = VariablePassing(*numbers, pass_by_reference=True) 164 | self._verify_all(numbers, [True] * 4) 165 | 166 | # passed by value, no numbers should change 167 | numbers = [list(range(10)) for _ in range(4)] 168 | variablePassing = VariablePassing(*numbers, pass_by_reference=False) 169 | self._verify_all(numbers, [False] * 4) 170 | 171 | # only the first set of numbers should change 172 | numbers = [list(range(10)) for _ in range(4)] 173 | variablePassing = VariablePassing(*numbers, pass_by_reference=[True, False]) 174 | self._verify_all(numbers, [True, False, False, False]) 175 | 176 | # only the first set of numbers should not change 177 | numbers = [list(range(10)) for _ in range(4)] 178 | variablePassing = VariablePassing(*numbers, pass_by_reference=[False, True]) 179 | self._verify_all(numbers, [False, True, True, True]) 180 | 181 | # only the odd sets of numbers should change 182 | numbers = [list(range(10)) for _ in range(4)] 183 | changed = (True, False, True, False) 184 | variablePassing = VariablePassing(*numbers, pass_by_reference=changed) 185 | self._verify_all(numbers, changed) 186 | 187 | # only the even sets of numbers should change 188 | numbers = [list(range(10)) for _ in range(4)] 189 | changed = (False, True, False, True) 190 | variablePassing = VariablePassing(*numbers, pass_by_reference=changed) 191 | self._verify_all(numbers, changed) 192 | -------------------------------------------------------------------------------- /tests/test_proxy.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from __future__ import division 3 | from __future__ import absolute_import 4 | 5 | from jnius import autoclass, java_method, PythonJavaClass, cast 6 | 7 | print('1: declare a TestImplem that implement Collection') 8 | 9 | 10 | class _TestImplemIterator(PythonJavaClass): 11 | __javainterfaces__ = [ 12 | #'java/util/Iterator', 13 | 'java/util/ListIterator', ] 14 | 15 | def __init__(self, collection, index=0): 16 | self.collection = collection 17 | self.index = index 18 | 19 | @java_method('()Z') 20 | def hasNext(self): 21 | return self.index < len(self.collection.data) - 1 22 | 23 | @java_method('()Ljava/lang/Object;') 24 | def next(self): 25 | obj = self.collection.data[self.index] 26 | self.index += 1 27 | return obj 28 | 29 | @java_method('()Z') 30 | def hasPrevious(self): 31 | return self.index >= 0 32 | 33 | @java_method('()Ljava/lang/Object;') 34 | def previous(self): 35 | self.index -= 1 36 | obj = self.collection.data[self.index] 37 | return obj 38 | 39 | @java_method('()I') 40 | def previousIndex(self): 41 | return self.index - 1 42 | 43 | @java_method('()Ljava/lang/String;') 44 | def toString(self): 45 | return repr(self) 46 | 47 | @java_method('(I)Ljava/lang/Object;') 48 | def get(self, index): 49 | return self.collection.data[index - 1] 50 | 51 | @java_method('(Ljava/lang/Object;)V') 52 | def set(self, obj): 53 | self.collection.data[self.index - 1] = obj 54 | 55 | 56 | class _TestImplem(PythonJavaClass): 57 | __javainterfaces__ = ['java/util/List'] 58 | 59 | def __init__(self, *args): 60 | super(_TestImplem, self).__init__(*args) 61 | self.data = list(args) 62 | 63 | @java_method('()Ljava/util/Iterator;') 64 | def iterator(self): 65 | it = _TestImplemIterator(self) 66 | return it 67 | 68 | @java_method('()Ljava/lang/String;') 69 | def toString(self): 70 | return repr(self) 71 | 72 | @java_method('()I') 73 | def size(self): 74 | return len(self.data) 75 | 76 | @java_method('(I)Ljava/lang/Object;') 77 | def get(self, index): 78 | return self.data[index] 79 | 80 | @java_method('(ILjava/lang/Object;)Ljava/lang/Object;') 81 | def set(self, index, obj): 82 | old_object = self.data[index] 83 | self.data[index] = obj 84 | return old_object 85 | 86 | @java_method('()[Ljava/lang/Object;') 87 | def toArray(self): 88 | return self.data 89 | 90 | @java_method('()Ljava/util/ListIterator;') 91 | def listIterator(self): 92 | it = _TestImplemIterator(self) 93 | return it 94 | 95 | @java_method('(I)Ljava/util/ListIterator;', 96 | name='ListIterator') 97 | def listIteratorI(self, index): 98 | it = _TestImplemIterator(self, index) 99 | return it 100 | 101 | 102 | class _TestBadSignature(PythonJavaClass): 103 | __javainterfaces__ = ['java/util/List'] 104 | 105 | @java_method('(Landroid/bluetooth/BluetoothDevice;IB[])V') 106 | def bad_signature(self, *args): 107 | pass 108 | 109 | 110 | print('2: instantiate the class, with some data') 111 | a = _TestImplem(*list(range(10))) 112 | print(a) 113 | print(dir(a)) 114 | 115 | print('tries to get a ListIterator') 116 | iterator = a.listIterator() 117 | print('iterator is', iterator) 118 | while iterator.hasNext(): 119 | print('at index', iterator.index, 'value is', iterator.next()) 120 | 121 | print('3: Do cast to a collection') 122 | a2 = cast('java/util/Collection', a.j_self) 123 | print(a2) 124 | 125 | print('4: Try few method on the collection') 126 | Collections = autoclass('java.util.Collections') 127 | #print Collections.enumeration(a) 128 | #print Collections.enumeration(a) 129 | ret = Collections.max(a) 130 | 131 | print("reverse") 132 | print(Collections.reverse(a)) 133 | print(a.data) 134 | 135 | print("before swap") 136 | print(Collections.swap(a, 2, 3)) 137 | print("after swap") 138 | print(a.data) 139 | 140 | print("rotate") 141 | print(Collections.rotate(a, 5)) 142 | print(a.data) 143 | 144 | print('Order of data before shuffle()', a.data) 145 | print(Collections.shuffle(a)) 146 | print('Order of data after shuffle()', a.data) 147 | 148 | 149 | # XXX We have issues for methosd with multiple signature 150 | print('-> Collections.max(a)') 151 | print(Collections.max(a2)) 152 | #print '-> Collections.shuffle(a)' 153 | #print Collections.shuffle(a2) 154 | 155 | # test bad signature 156 | threw = False 157 | try: 158 | _TestBadSignature() 159 | except Exception: 160 | threw = True 161 | 162 | if not threw: 163 | raise Exception("Failed to throw for bad signature") 164 | -------------------------------------------------------------------------------- /tests/test_reflect.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from __future__ import division 3 | from __future__ import absolute_import 4 | import unittest 5 | from jnius.reflect import autoclass 6 | from jnius import cast 7 | from jnius.reflect import identify_hierarchy 8 | from jnius import find_javaclass 9 | 10 | def identify_hierarchy_dict(cls, level, concrete=True): 11 | return({ cls.getName() : level for cls,level in identify_hierarchy(cls, level, concrete) }) 12 | 13 | class ReflectTest(unittest.TestCase): 14 | 15 | def assertContains(self, d, clsName): 16 | self.assertTrue(clsName in d, clsName + " was not found in " + str(d)) 17 | 18 | def test_hierharchy_queue(self): 19 | d = identify_hierarchy_dict(find_javaclass("java.util.Queue"), 0, False) 20 | self.assertContains(d, "java.util.Queue") 21 | # super interfaces 22 | self.assertContains(d, "java.util.Collection") 23 | self.assertContains(d, "java.lang.Iterable") 24 | # all instantiated interfaces are rooted at Object 25 | self.assertContains(d, "java.lang.Object") 26 | maxLevel = max(d.values()) 27 | self.assertEqual(d["java.lang.Object"], maxLevel) 28 | self.assertEqual(d["java.util.Queue"], 0) 29 | 30 | def test_hierharchy_arraylist(self): 31 | d = identify_hierarchy_dict(find_javaclass("java.util.ArrayList"), 0, True) 32 | self.assertContains(d, "java.util.ArrayList")# concrete 33 | self.assertContains(d, "java.util.AbstractCollection")# superclass 34 | self.assertContains(d, "java.util.Collection")# interface 35 | self.assertContains(d, "java.lang.Iterable")# interface 36 | self.assertContains(d, "java.lang.Object")# root 37 | maxLevel = max(d.values()) 38 | self.assertTrue(d["java.lang.Object"] in [maxLevel, maxLevel -1]) # Object should be pretty high up the hierarchy. 39 | self.assertEqual(d["java.util.ArrayList"], 0) 40 | 41 | def test_class(self): 42 | lstClz = autoclass("java.util.List") 43 | self.assertTrue("_class" in dir(lstClz)) 44 | self.assertEqual("java.util.List", lstClz._class.getName()) 45 | alstClz = autoclass("java.util.ArrayList") 46 | self.assertTrue("_class" in dir(alstClz)) 47 | self.assertEqual("java.util.ArrayList", alstClz._class.getName()) 48 | self.assertEqual("java.util.ArrayList", alstClz().getClass().getName()) 49 | 50 | def test_stack(self): 51 | Stack = autoclass('java.util.Stack') 52 | stack = Stack() 53 | self.assertIsInstance(stack, Stack) 54 | stack.push('hello') 55 | stack.push('world') 56 | self.assertEqual(stack.pop(), 'world') 57 | self.assertEqual(stack.pop(), 'hello') 58 | 59 | def test_collection(self): 60 | HashSet = autoclass('java.util.HashSet') 61 | aset = HashSet() 62 | aset.add('hello') 63 | aset.add('world') 64 | #check that the __len__ dunder is applied to a Collection not a List 65 | self.assertEqual(2, len(aset)) 66 | #check that the __len__ dunder is applied to it cast as a Collection 67 | self.assertEqual(2, len(cast("java.util.Collection", aset))) 68 | 69 | def test_list_interface(self): 70 | ArrayList = autoclass('java.util.ArrayList') 71 | words = ArrayList() 72 | words.add('hello') 73 | words.add('world') 74 | self.assertIsNotNone(words.stream()) 75 | self.assertIsNotNone(words.iterator()) 76 | 77 | def test_super_interface(self): 78 | LinkedList = autoclass('java.util.LinkedList') 79 | words = LinkedList() 80 | words.add('hello') 81 | words.add('world') 82 | q = cast('java.util.Queue', words) 83 | self.assertEqual(2, q.size()) 84 | self.assertEqual(2, len(q)) 85 | self.assertIsNotNone(q.iterator()) 86 | 87 | def test_super_object(self): 88 | LinkedList = autoclass('java.util.LinkedList') 89 | words = LinkedList() 90 | words.hashCode() 91 | 92 | def test_super_interface_object(self): 93 | LinkedList = autoclass('java.util.LinkedList') 94 | words = LinkedList() 95 | q = cast('java.util.Queue', words) 96 | q.hashCode() 97 | 98 | def test_list_iteration(self): 99 | ArrayList = autoclass('java.util.ArrayList') 100 | words = ArrayList() 101 | words.add('hello') 102 | words.add('world') 103 | self.assertEqual(['hello', 'world'], [word for word in words]) 104 | 105 | -------------------------------------------------------------------------------- /tests/test_signature.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from jnius import autoclass, java_method, PythonJavaClass, cast 4 | 5 | from jnius.signatures import * 6 | 7 | JObject = autoclass('java/lang/Object') 8 | JString = autoclass('java/lang/String') 9 | JListIterator = autoclass("java.util.ListIterator") 10 | 11 | class _TestImplemIterator(PythonJavaClass): 12 | __javainterfaces__ = [ 13 | 'java/util/ListIterator', ] 14 | 15 | def __init__(self, collection, index=0): 16 | super(_TestImplemIterator, self).__init__() 17 | self.collection = collection 18 | self.index = index 19 | 20 | @with_signature(jboolean, []) 21 | def hasNext(self): 22 | return self.index < len(self.collection.data) - 1 23 | 24 | @with_signature(JObject, []) 25 | def next(self): 26 | obj = self.collection.data[self.index] 27 | self.index += 1 28 | return obj 29 | 30 | @with_signature(jboolean, []) 31 | def hasPrevious(self): 32 | return self.index >= 0 33 | 34 | @with_signature(JObject, []) 35 | def previous(self): 36 | self.index -= 1 37 | obj = self.collection.data[self.index] 38 | return obj 39 | 40 | @with_signature(jint, []) 41 | def previousIndex(self): 42 | return self.index - 1 43 | 44 | @with_signature(JString, []) 45 | def toString(self): 46 | return repr(self) 47 | 48 | @with_signature(JObject, [jint]) 49 | def get(self, index): 50 | return self.collection.data[index - 1] 51 | 52 | @with_signature(jvoid, [JObject]) 53 | def set(self, obj): 54 | self.collection.data[self.index - 1] = obj 55 | 56 | 57 | class _TestImplem(PythonJavaClass): 58 | __javainterfaces__ = ['java/util/List'] 59 | 60 | def __init__(self, *args): 61 | super(_TestImplem, self).__init__(*args) 62 | self.data = list(args) 63 | 64 | @with_signature(autoclass("java.util.Iterator"), []) 65 | def iterator(self): 66 | it = _TestImplemIterator(self) 67 | return it 68 | 69 | @with_signature(JString, []) 70 | def toString(self): 71 | return repr(self) 72 | 73 | @with_signature(jint, []) 74 | def size(self): 75 | return len(self.data) 76 | 77 | @with_signature(JObject, [jint]) 78 | def get(self, index): 79 | return self.data[index] 80 | 81 | @with_signature(JObject, [jint, JObject]) 82 | def set(self, index, obj): 83 | old_object = self.data[index] 84 | self.data[index] = obj 85 | return old_object 86 | 87 | @with_signature(JArray(JObject), []) 88 | def toArray(self): 89 | return self.data 90 | 91 | @with_signature(JListIterator, []) 92 | def listIterator(self): 93 | it = _TestImplemIterator(self) 94 | return it 95 | 96 | # TODO cover this case of listIterator. 97 | @java_method(signature(JListIterator, [jint]), 98 | name='ListIterator') 99 | def listIteratorI(self, index): 100 | it = _TestImplemIterator(self, index) 101 | return it 102 | 103 | 104 | from jnius.reflect import autoclass 105 | 106 | class SignaturesTest(unittest.TestCase): 107 | 108 | def test_construct_stack_from_testimplem(self): 109 | Stack = autoclass("java.util.Stack") 110 | pyjlist = _TestImplem(1, 2, 3, 4, 5, 6, 7) 111 | stack = Stack() 112 | stack.addAll(pyjlist) 113 | self.assertEqual(7, pyjlist.size()) 114 | self.assertEqual(stack.size(), pyjlist.size()) 115 | array = pyjlist.toArray() 116 | 117 | def test_return_types(self): 118 | 119 | # Void 120 | sig = signature(jvoid, []) 121 | self.assertEqual(sig, "()V") 122 | 123 | # Boolean 124 | sig = signature(jboolean, []) 125 | self.assertEqual(sig, "()Z") 126 | 127 | # Byte 128 | sig = signature(jbyte, []) 129 | self.assertEqual(sig, "()B") 130 | 131 | # Char 132 | sig = signature(jchar, []) 133 | self.assertEqual(sig, "()C") 134 | 135 | # Double 136 | sig = signature(jdouble, []) 137 | self.assertEqual(sig, "()D") 138 | 139 | # Float 140 | sig = signature(jfloat, []) 141 | self.assertEqual(sig, "()F") 142 | 143 | # Int 144 | sig = signature(jint, []) 145 | self.assertEqual(sig, "()I") 146 | 147 | # Long 148 | sig = signature(jlong, []) 149 | self.assertEqual(sig, "()J") 150 | 151 | # Short 152 | sig = signature(jshort, []) 153 | self.assertEqual(sig, "()S") 154 | 155 | # Object return method 156 | String = autoclass("java.lang.String") 157 | sig = signature(String, []) 158 | self.assertEqual(sig, "()Ljava/lang/String;") 159 | 160 | # Array return 161 | sig = signature(JArray(jint), []) 162 | self.assertEqual(sig, "()[I") 163 | 164 | def test_params(self): 165 | String = autoclass("java.lang.String") 166 | 167 | # Return void, takes objects as parameters 168 | sig = signature(jvoid, [String, String]) 169 | self.assertEqual(sig, "(Ljava/lang/String;Ljava/lang/String;)V") 170 | 171 | # Multiple array parameter types 172 | sig = signature(jvoid, [JArray(jint), JArray(jboolean)]) 173 | self.assertEqual(sig, "([I[Z)V") 174 | 175 | -------------------------------------------------------------------------------- /tests/test_simple.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from __future__ import division 3 | from __future__ import absolute_import 4 | import unittest 5 | from jnius import JavaClass, MetaJavaClass, JavaMethod 6 | 7 | class HelloWorldTest(unittest.TestCase): 8 | 9 | def test_helloworld(self): 10 | 11 | class HelloWorld(JavaClass, metaclass=MetaJavaClass): 12 | __javaclass__ = 'org/jnius/HelloWorld' 13 | hello = JavaMethod('()Ljava/lang/String;') 14 | 15 | a = HelloWorld() 16 | self.assertEqual(a.hello(), 'world') 17 | -------------------------------------------------------------------------------- /tests/test_static.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Test calling non-static methods on classes. 3 | ''' 4 | 5 | from __future__ import absolute_import 6 | import unittest 7 | from jnius import autoclass, JavaException, JavaMethod, JavaMultipleMethod 8 | 9 | 10 | class TestStatic(unittest.TestCase): 11 | 12 | def test_method(self): 13 | ''' 14 | Call a non-static JavaMethod on a class, 15 | should raise JavaException. 16 | ''' 17 | 18 | String = autoclass('java.lang.String') 19 | self.assertIsInstance(String.replaceAll, JavaMethod) 20 | self.assertEqual(String('foo').replaceAll('foo', 'bar'), 'bar') 21 | with self.assertRaises(JavaException): 22 | String.replaceAll('foo', 'bar') 23 | 24 | def test_multiplemethod(self): 25 | ''' 26 | Call a non-static JavaMultipleMethod on a class, 27 | should raise JavaException. 28 | ''' 29 | 30 | String = autoclass('java.lang.String') 31 | self.assertIsInstance(String.toString, JavaMultipleMethod) 32 | self.assertEqual(String('baz').toString(), 'baz') 33 | with self.assertRaises(JavaException): 34 | String.toString() 35 | 36 | 37 | if __name__ == '__main__': 38 | unittest.main() 39 | -------------------------------------------------------------------------------- /tests/test_visibility_package_protected.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from __future__ import division 3 | from __future__ import absolute_import 4 | import unittest 5 | import jnius_config 6 | from jnius import JavaMethod, JavaStaticMethod, JavaException 7 | from jnius.reflect import autoclass 8 | 9 | 10 | class VisibilityPackageProtectedTest(unittest.TestCase): 11 | """This unittest verifies the correct visibility of package protected methods and fields. 12 | 13 | Observe that org.jnius2.ChildVisibilityTest is not in the same package as 14 | it's parent class. If `include_protected` is True and `include_private` 15 | is False, only the package protected methods and fields in the child class 16 | should be visible. 17 | """ 18 | 19 | def test_child_static_fields_package_protected(self): 20 | Test = autoclass('org.jnius2.ChildVisibilityTest', include_protected=True, include_private=False) 21 | 22 | self.assertTrue(hasattr(Test, 'fieldStaticPublic')) 23 | self.assertFalse(hasattr(Test, 'fieldStaticPackageProtected')) 24 | self.assertTrue(hasattr(Test, 'fieldStaticProtected')) 25 | self.assertFalse(hasattr(Test, 'fieldStaticPrivate')) 26 | 27 | self.assertEqual(Test.fieldStaticPublic, "StaticPublic") 28 | self.assertEqual(Test.fieldStaticProtected, "StaticProtected") 29 | 30 | self.assertTrue(hasattr(Test, 'fieldChildStaticPublic')) 31 | self.assertTrue(hasattr(Test, 'fieldChildStaticPackageProtected')) 32 | self.assertTrue(hasattr(Test, 'fieldChildStaticProtected')) 33 | self.assertFalse(hasattr(Test, 'fieldChildStaticPrivate')) 34 | 35 | self.assertEqual(Test.fieldChildStaticPublic, "ChildStaticPublic") 36 | self.assertEqual(Test.fieldChildStaticPackageProtected, "ChildStaticPackageProtected") 37 | self.assertEqual(Test.fieldChildStaticProtected, "ChildStaticProtected") 38 | 39 | def test_child_static_methods_package_protected(self): 40 | Test = autoclass('org.jnius2.ChildVisibilityTest', include_protected=True, include_private=False) 41 | 42 | self.assertTrue(hasattr(Test, 'methodStaticPublic')) 43 | self.assertFalse(hasattr(Test, 'methodStaticPackageProtected')) 44 | self.assertTrue(hasattr(Test, 'methodStaticProtected')) 45 | self.assertFalse(hasattr(Test, 'methodStaticPrivate')) 46 | 47 | self.assertEqual(Test.methodStaticPublic(), "StaticPublic") 48 | self.assertEqual(Test.methodStaticProtected(), "StaticProtected") 49 | 50 | self.assertTrue(hasattr(Test, 'methodChildStaticPublic')) 51 | self.assertTrue(hasattr(Test, 'methodChildStaticPackageProtected')) 52 | self.assertTrue(hasattr(Test, 'methodChildStaticProtected')) 53 | self.assertFalse(hasattr(Test, 'methodChildStaticPrivate')) 54 | 55 | self.assertEqual(Test.methodChildStaticPublic(), "ChildStaticPublic") 56 | self.assertEqual(Test.methodChildStaticPackageProtected(), "ChildStaticPackageProtected") 57 | self.assertEqual(Test.methodChildStaticProtected(), "ChildStaticProtected") 58 | 59 | def test_child_fields_package_protected(self): 60 | 61 | Test = autoclass('org.jnius2.ChildVisibilityTest', include_protected=True, include_private=False) 62 | test = Test() 63 | 64 | self.assertTrue(hasattr(test, 'fieldPublic')) 65 | self.assertFalse(hasattr(test, 'fieldPackageProtected')) 66 | self.assertTrue(hasattr(test, 'fieldProtected')) 67 | self.assertFalse(hasattr(test, 'fieldPrivate')) 68 | 69 | self.assertEqual(test.fieldPublic, "Public") 70 | self.assertEqual(test.fieldProtected, "Protected") 71 | 72 | self.assertTrue(hasattr(test, 'fieldChildPublic')) 73 | self.assertTrue(hasattr(test, 'fieldChildPackageProtected')) 74 | self.assertTrue(hasattr(test, 'fieldChildProtected')) 75 | self.assertFalse(hasattr(test, 'fieldChildPrivate')) 76 | 77 | self.assertEqual(test.fieldChildPublic, "ChildPublic") 78 | self.assertEqual(test.fieldChildPackageProtected, "ChildPackageProtected") 79 | self.assertEqual(test.fieldChildProtected, "ChildProtected") 80 | 81 | def test_child_methods_package_protected(self): 82 | 83 | Test = autoclass('org.jnius2.ChildVisibilityTest', include_protected=True, include_private=False) 84 | test = Test() 85 | 86 | self.assertTrue(hasattr(test, 'methodPublic')) 87 | self.assertFalse(hasattr(test, 'methodPackageProtected')) 88 | self.assertTrue(hasattr(test, 'methodProtected')) 89 | self.assertFalse(hasattr(test, 'methodPrivate')) 90 | 91 | self.assertEqual(test.methodPublic(), "Public") 92 | self.assertEqual(test.methodProtected(), "Protected") 93 | 94 | self.assertTrue(hasattr(test, 'methodChildPublic')) 95 | self.assertTrue(hasattr(test, 'methodChildPackageProtected')) 96 | self.assertTrue(hasattr(test, 'methodChildProtected')) 97 | self.assertFalse(hasattr(test, 'methodChildPrivate')) 98 | 99 | self.assertEqual(test.methodChildPublic(), "ChildPublic") 100 | self.assertEqual(test.methodChildPackageProtected(), "ChildPackageProtected") 101 | self.assertEqual(test.methodChildProtected(), "ChildProtected") 102 | -------------------------------------------------------------------------------- /tests/test_visibility_public_only.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from __future__ import division 3 | from __future__ import absolute_import 4 | import unittest 5 | import jnius_config 6 | from jnius import JavaMethod, JavaStaticMethod, JavaException 7 | from jnius.reflect import autoclass 8 | 9 | 10 | class VisibilityPublicOnlyTest(unittest.TestCase): 11 | 12 | def test_static_fields_public_only(self): 13 | Test = autoclass('org.jnius.VisibilityTest', include_protected=False, include_private=False) 14 | 15 | self.assertTrue(hasattr(Test, 'fieldStaticPublic')) 16 | self.assertFalse(hasattr(Test, 'fieldStaticPackageProtected')) 17 | self.assertFalse(hasattr(Test, 'fieldStaticProtected')) 18 | self.assertFalse(hasattr(Test, 'fieldStaticPrivate')) 19 | 20 | self.assertEqual(Test.fieldStaticPublic, "StaticPublic") 21 | 22 | def test_child_static_fields_public_only(self): 23 | Test = autoclass('org.jnius.ChildVisibilityTest', include_protected=False, include_private=False) 24 | 25 | self.assertTrue(hasattr(Test, 'fieldStaticPublic')) 26 | self.assertFalse(hasattr(Test, 'fieldStaticPackageProtected')) 27 | self.assertFalse(hasattr(Test, 'fieldStaticProtected')) 28 | self.assertFalse(hasattr(Test, 'fieldStaticPrivate')) 29 | 30 | self.assertEqual(Test.fieldStaticPublic, "StaticPublic") 31 | 32 | self.assertTrue(hasattr(Test, 'fieldChildStaticPublic')) 33 | self.assertFalse(hasattr(Test, 'fieldChildStaticPackageProtected')) 34 | self.assertFalse(hasattr(Test, 'fieldChildStaticProtected')) 35 | self.assertFalse(hasattr(Test, 'fieldChildStaticPrivate')) 36 | 37 | self.assertEqual(Test.fieldChildStaticPublic, "ChildStaticPublic") 38 | 39 | def test_static_methods_public_only(self): 40 | Test = autoclass('org.jnius.VisibilityTest', include_protected=False, include_private=False) 41 | 42 | self.assertTrue(hasattr(Test, 'methodStaticPublic')) 43 | self.assertFalse(hasattr(Test, 'methodStaticPackageProtected')) 44 | self.assertFalse(hasattr(Test, 'methodStaticProtected')) 45 | self.assertFalse(hasattr(Test, 'methodStaticPrivate')) 46 | 47 | self.assertEqual(Test.methodStaticPublic(), "StaticPublic") 48 | 49 | def test_child_static_methods_public_only(self): 50 | Test = autoclass('org.jnius.ChildVisibilityTest', include_protected=False, include_private=False) 51 | 52 | self.assertTrue(hasattr(Test, 'methodStaticPublic')) 53 | self.assertFalse(hasattr(Test, 'methodStaticPackageProtected')) 54 | self.assertFalse(hasattr(Test, 'methodStaticProtected')) 55 | self.assertFalse(hasattr(Test, 'methodStaticPrivate')) 56 | 57 | self.assertEqual(Test.methodStaticPublic(), "StaticPublic") 58 | 59 | self.assertTrue(hasattr(Test, 'methodChildStaticPublic')) 60 | self.assertFalse(hasattr(Test, 'methodChildStaticPackageProtected')) 61 | self.assertFalse(hasattr(Test, 'methodChildStaticProtected')) 62 | self.assertFalse(hasattr(Test, 'methodChildStaticPrivate')) 63 | 64 | self.assertEqual(Test.methodChildStaticPublic(), "ChildStaticPublic") 65 | 66 | def test_fields_public_only(self): 67 | 68 | Test = autoclass('org.jnius.VisibilityTest', include_protected=False, include_private=False) 69 | test = Test() 70 | 71 | self.assertTrue(hasattr(test, 'fieldPublic')) 72 | self.assertFalse(hasattr(test, 'fieldPackageProtected')) 73 | self.assertFalse(hasattr(test, 'fieldProtected')) 74 | self.assertFalse(hasattr(test, 'fieldPrivate')) 75 | 76 | self.assertEqual(test.fieldPublic, "Public") 77 | 78 | def test_child_fields_public_only(self): 79 | 80 | Test = autoclass('org.jnius.ChildVisibilityTest', include_protected=False, include_private=False) 81 | test = Test() 82 | 83 | self.assertTrue(hasattr(test, 'fieldPublic')) 84 | self.assertFalse(hasattr(test, 'fieldPackageProtected')) 85 | self.assertFalse(hasattr(test, 'fieldProtected')) 86 | self.assertFalse(hasattr(test, 'fieldPrivate')) 87 | 88 | self.assertEqual(test.fieldPublic, "Public") 89 | 90 | self.assertTrue(hasattr(test, 'fieldChildPublic')) 91 | self.assertFalse(hasattr(test, 'fieldChildPackageProtected')) 92 | self.assertFalse(hasattr(test, 'fieldChildProtected')) 93 | self.assertFalse(hasattr(test, 'fieldChildPrivate')) 94 | 95 | self.assertEqual(test.fieldChildPublic, "ChildPublic") 96 | 97 | def test_methods_public_only(self): 98 | 99 | Test = autoclass('org.jnius.VisibilityTest', include_protected=False, include_private=False) 100 | test = Test() 101 | 102 | self.assertTrue(hasattr(test, 'methodPublic')) 103 | self.assertFalse(hasattr(test, 'methodPackageProtected')) 104 | self.assertFalse(hasattr(test, 'methodProtected')) 105 | self.assertFalse(hasattr(test, 'methodPrivate')) 106 | 107 | self.assertEqual(test.methodPublic(), "Public") 108 | 109 | def test_child_methods_public_only(self): 110 | 111 | Test = autoclass('org.jnius.ChildVisibilityTest', include_protected=False, include_private=False) 112 | test = Test() 113 | 114 | self.assertTrue(hasattr(test, 'methodPublic')) 115 | self.assertFalse(hasattr(test, 'methodPackageProtected')) 116 | self.assertFalse(hasattr(test, 'methodProtected')) 117 | self.assertFalse(hasattr(test, 'methodPrivate')) 118 | 119 | self.assertEqual(test.methodPublic(), "Public") 120 | 121 | self.assertTrue(hasattr(test, 'methodChildPublic')) 122 | self.assertFalse(hasattr(test, 'methodChildPackageProtected')) 123 | self.assertFalse(hasattr(test, 'methodChildProtected')) 124 | self.assertFalse(hasattr(test, 'methodChildPrivate')) 125 | 126 | self.assertEqual(test.methodChildPublic(), "ChildPublic") 127 | 128 | def test_static_multi_methods(self): 129 | Test = autoclass('org.jnius.ChildVisibilityTest', include_protected=False, include_private=False) 130 | 131 | self.assertTrue(hasattr(Test, 'methodStaticMultiArgs')) 132 | self.assertTrue(isinstance(Test.methodStaticMultiArgs, JavaStaticMethod)) 133 | 134 | self.assertTrue(Test.methodStaticMultiArgs(True)) 135 | with self.assertRaises(JavaException): 136 | Test.methodStaticMultiArgs(True, False) 137 | with self.assertRaises(JavaException): 138 | Test.methodStaticMultiArgs(True, False, True) 139 | 140 | def test_multi_methods(self): 141 | Test = autoclass('org.jnius.ChildVisibilityTest', include_protected=False, include_private=False) 142 | test = Test() 143 | 144 | self.assertTrue(hasattr(test, 'methodMultiArgs')) 145 | self.assertTrue(isinstance(Test.methodMultiArgs, JavaMethod)) 146 | 147 | self.assertTrue(test.methodMultiArgs(True)) 148 | with self.assertRaises(JavaException): 149 | test.methodMultiArgs(True, False) 150 | with self.assertRaises(JavaException): 151 | test.methodMultiArgs(True, False, True) 152 | -------------------------------------------------------------------------------- /tests/test_visibility_public_protected.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from __future__ import division 3 | from __future__ import absolute_import 4 | import unittest 5 | import jnius_config 6 | from jnius import JavaMultipleMethod, JavaException 7 | from jnius.reflect import autoclass 8 | 9 | 10 | class VisibilityPublicProtectedTest(unittest.TestCase): 11 | 12 | def test_static_fields_public_protected(self): 13 | Test = autoclass('org.jnius.VisibilityTest', include_protected=True, include_private=False) 14 | 15 | self.assertTrue(hasattr(Test, 'fieldStaticPublic')) 16 | self.assertTrue(hasattr(Test, 'fieldStaticPackageProtected')) 17 | self.assertTrue(hasattr(Test, 'fieldStaticProtected')) 18 | self.assertFalse(hasattr(Test, 'fieldStaticPrivate')) 19 | 20 | self.assertEqual(Test.fieldStaticPublic, "StaticPublic") 21 | self.assertEqual(Test.fieldStaticPackageProtected, "StaticPackageProtected") 22 | self.assertEqual(Test.fieldStaticProtected, "StaticProtected") 23 | 24 | def test_child_static_fields_public_protected(self): 25 | Test = autoclass('org.jnius.ChildVisibilityTest', include_protected=True, include_private=False) 26 | 27 | self.assertTrue(hasattr(Test, 'fieldStaticPublic')) 28 | self.assertTrue(hasattr(Test, 'fieldStaticPackageProtected')) 29 | self.assertTrue(hasattr(Test, 'fieldStaticProtected')) 30 | self.assertFalse(hasattr(Test, 'fieldStaticPrivate')) 31 | 32 | self.assertEqual(Test.fieldStaticPublic, "StaticPublic") 33 | self.assertEqual(Test.fieldStaticPackageProtected, "StaticPackageProtected") 34 | self.assertEqual(Test.fieldStaticProtected, "StaticProtected") 35 | 36 | self.assertTrue(hasattr(Test, 'fieldChildStaticPublic')) 37 | self.assertTrue(hasattr(Test, 'fieldChildStaticPackageProtected')) 38 | self.assertTrue(hasattr(Test, 'fieldChildStaticProtected')) 39 | self.assertFalse(hasattr(Test, 'fieldChildStaticPrivate')) 40 | 41 | self.assertEqual(Test.fieldChildStaticPublic, "ChildStaticPublic") 42 | self.assertEqual(Test.fieldChildStaticPackageProtected, "ChildStaticPackageProtected") 43 | self.assertEqual(Test.fieldChildStaticProtected, "ChildStaticProtected") 44 | 45 | def test_static_methods_public_protected(self): 46 | Test = autoclass('org.jnius.VisibilityTest', include_protected=True, include_private=False) 47 | 48 | self.assertTrue(hasattr(Test, 'methodStaticPublic')) 49 | self.assertTrue(hasattr(Test, 'methodStaticPackageProtected')) 50 | self.assertTrue(hasattr(Test, 'methodStaticProtected')) 51 | self.assertFalse(hasattr(Test, 'methodStaticPrivate')) 52 | 53 | self.assertEqual(Test.methodStaticPublic(), "StaticPublic") 54 | self.assertEqual(Test.methodStaticPackageProtected(), "StaticPackageProtected") 55 | self.assertEqual(Test.methodStaticProtected(), "StaticProtected") 56 | 57 | def test_child_static_methods_public_protected(self): 58 | Test = autoclass('org.jnius.ChildVisibilityTest', include_protected=True, include_private=False) 59 | 60 | self.assertTrue(hasattr(Test, 'methodStaticPublic')) 61 | self.assertTrue(hasattr(Test, 'methodStaticPackageProtected')) 62 | self.assertTrue(hasattr(Test, 'methodStaticProtected')) 63 | self.assertFalse(hasattr(Test, 'methodStaticPrivate')) 64 | 65 | self.assertEqual(Test.methodStaticPublic(), "StaticPublic") 66 | self.assertEqual(Test.methodStaticPackageProtected(), "StaticPackageProtected") 67 | self.assertEqual(Test.methodStaticProtected(), "StaticProtected") 68 | 69 | self.assertTrue(hasattr(Test, 'methodChildStaticPublic')) 70 | self.assertTrue(hasattr(Test, 'methodChildStaticPackageProtected')) 71 | self.assertTrue(hasattr(Test, 'methodChildStaticProtected')) 72 | self.assertFalse(hasattr(Test, 'methodChildStaticPrivate')) 73 | 74 | self.assertEqual(Test.methodChildStaticPublic(), "ChildStaticPublic") 75 | self.assertEqual(Test.methodChildStaticPackageProtected(), "ChildStaticPackageProtected") 76 | self.assertEqual(Test.methodChildStaticProtected(), "ChildStaticProtected") 77 | 78 | def test_fields_public_protected(self): 79 | 80 | Test = autoclass('org.jnius.VisibilityTest', include_protected=True, include_private=False) 81 | test = Test() 82 | 83 | self.assertTrue(hasattr(test, 'fieldPublic')) 84 | self.assertTrue(hasattr(test, 'fieldPackageProtected')) 85 | self.assertTrue(hasattr(test, 'fieldProtected')) 86 | self.assertFalse(hasattr(test, 'fieldPrivate')) 87 | 88 | self.assertEqual(test.fieldPublic, "Public") 89 | self.assertEqual(test.fieldPackageProtected, "PackageProtected") 90 | self.assertEqual(test.fieldProtected, "Protected") 91 | 92 | def test_child_fields_public_protected(self): 93 | 94 | Test = autoclass('org.jnius.ChildVisibilityTest', include_protected=True, include_private=False) 95 | test = Test() 96 | 97 | self.assertTrue(hasattr(test, 'fieldPublic')) 98 | self.assertTrue(hasattr(test, 'fieldPackageProtected')) 99 | self.assertTrue(hasattr(test, 'fieldProtected')) 100 | self.assertFalse(hasattr(test, 'fieldPrivate')) 101 | 102 | self.assertEqual(test.fieldPublic, "Public") 103 | self.assertEqual(test.fieldPackageProtected, "PackageProtected") 104 | self.assertEqual(test.fieldProtected, "Protected") 105 | 106 | self.assertTrue(hasattr(test, 'fieldChildPublic')) 107 | self.assertTrue(hasattr(test, 'fieldChildPackageProtected')) 108 | self.assertTrue(hasattr(test, 'fieldChildProtected')) 109 | self.assertFalse(hasattr(test, 'fieldChildPrivate')) 110 | 111 | self.assertEqual(test.fieldChildPublic, "ChildPublic") 112 | self.assertEqual(test.fieldChildPackageProtected, "ChildPackageProtected") 113 | self.assertEqual(test.fieldChildProtected, "ChildProtected") 114 | 115 | def test_methods_public_protected(self): 116 | 117 | Test = autoclass('org.jnius.VisibilityTest', include_protected=True, include_private=False) 118 | test = Test() 119 | 120 | self.assertTrue(hasattr(test, 'methodPublic')) 121 | self.assertTrue(hasattr(test, 'methodPackageProtected')) 122 | self.assertTrue(hasattr(test, 'methodProtected')) 123 | self.assertFalse(hasattr(test, 'methodPrivate')) 124 | 125 | self.assertEqual(test.methodPublic(), "Public") 126 | self.assertEqual(test.methodPackageProtected(), "PackageProtected") 127 | self.assertEqual(test.methodProtected(), "Protected") 128 | 129 | def test_child_methods_public_protected(self): 130 | 131 | Test = autoclass('org.jnius.ChildVisibilityTest', include_protected=True, include_private=False) 132 | test = Test() 133 | 134 | self.assertTrue(hasattr(test, 'methodPublic')) 135 | self.assertTrue(hasattr(test, 'methodPackageProtected')) 136 | self.assertTrue(hasattr(test, 'methodProtected')) 137 | self.assertFalse(hasattr(test, 'methodPrivate')) 138 | 139 | self.assertEqual(test.methodPublic(), "Public") 140 | self.assertEqual(test.methodPackageProtected(), "PackageProtected") 141 | self.assertEqual(test.methodProtected(), "Protected") 142 | 143 | self.assertTrue(hasattr(test, 'methodChildPublic')) 144 | self.assertTrue(hasattr(test, 'methodChildPackageProtected')) 145 | self.assertTrue(hasattr(test, 'methodChildProtected')) 146 | self.assertFalse(hasattr(test, 'methodChildPrivate')) 147 | 148 | self.assertEqual(test.methodChildPublic(), "ChildPublic") 149 | self.assertEqual(test.methodChildPackageProtected(), "ChildPackageProtected") 150 | self.assertEqual(test.methodChildProtected(), "ChildProtected") 151 | 152 | def test_static_multi_methods(self): 153 | Test = autoclass('org.jnius.ChildVisibilityTest', include_protected=True, include_private=False) 154 | 155 | self.assertTrue(hasattr(Test, 'methodStaticMultiArgs')) 156 | self.assertTrue(isinstance(Test.methodStaticMultiArgs, JavaMultipleMethod)) 157 | 158 | self.assertTrue(Test.methodStaticMultiArgs(True)) 159 | self.assertTrue(Test.methodStaticMultiArgs(True, False)) 160 | with self.assertRaises(JavaException): 161 | Test.methodStaticMultiArgs(True, False, True) 162 | 163 | def test_multi_methods(self): 164 | Test = autoclass('org.jnius.ChildVisibilityTest', include_protected=True, include_private=False) 165 | test = Test() 166 | 167 | self.assertTrue(hasattr(test, 'methodMultiArgs')) 168 | self.assertTrue(isinstance(Test.methodMultiArgs, JavaMultipleMethod)) 169 | 170 | self.assertTrue(test.methodMultiArgs(True)) 171 | self.assertTrue(test.methodMultiArgs(True, False)) 172 | with self.assertRaises(JavaException): 173 | test.methodMultiArgs(True, False, True) 174 | --------------------------------------------------------------------------------