Skip to content

Commit

Permalink
add java -> py object conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
plandes committed Nov 18, 2017
1 parent 824d9bb commit 2d6903b
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 5 deletions.
15 changes: 12 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,23 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).


## [Unreleased]


## [0.0.5] - 2017-11-17
Python only release.

### Added
- Java to python object conversion.


## [0.0.4] - 2017-11-16
### Changed
- Fixed integration test.
- Adding shutdown timeout semantics.
- Fixed python namespace bug.


## [0.0.3] - 2017-11-16
### Changed
- Better namespace handing.
Expand All @@ -31,7 +39,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Added
- Initial version

[Unreleased]: https://github.com/plandes/clj-py4j/compare/v0.0.2...HEAD
[0.0.3]: https://github.com/plandes/clj-py4j/compare/v0.0.3...v0.0.4
[Unreleased]: https://github.com/plandes/clj-py4j/compare/v0.0.5...HEAD
[0.0.5]: https://github.com/plandes/clj-py4j/compare/v0.0.4...v0.0.5
[0.0.4]: https://github.com/plandes/clj-py4j/compare/v0.0.3...v0.0.5
[0.0.3]: https://github.com/plandes/clj-py4j/compare/v0.0.2...v0.0.3
[0.0.2]: https://github.com/plandes/clj-py4j/compare/v0.0.1...v0.0.2
4 changes: 2 additions & 2 deletions src/python/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
setup(
name = "zensols.clojure",
packages = ['zensols'],
version = '0.4',
version = '0.5',
description = 'Python to Clojure Bridge using a Py4J Gateway',
author = 'Paul Landes',
author_email = 'landes@mailc.net',
url = 'https://github.com/plandes/clj-py4j',
download_url = 'https://github.com/plandes/clj-py4j/releases/download/v0.0.4/zensols.clojure-0.3-py3-none-any.whl',
download_url = 'https://github.com/plandes/clj-py4j/releases/download/v0.0.5/zensols.clojure-0.5-py3-none-any.whl',
keywords = ['clojure', 'py4j', 'gateway'],
classifiers = [],
)
26 changes: 26 additions & 0 deletions src/python/zensols/clojure.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import py4j
from py4j.java_gateway import JavaGateway, GatewayParameters
import logging

Expand Down Expand Up @@ -40,6 +41,31 @@ def _java_map(self, odict):
m.put(k, v)
return m

def _python_array(self, arr):
size = len(arr)
pa = size * [None]
for i in range(size):
pa[i] = self.python_object(arr[i])
return pa

def _python_dict(self, m):
pm = self.eval("""(->> m (map (fn [[k v]] {(name k) v})) (apply merge))""",
{'m': m})
pd = {}
for e in pm.entrySet():
pd[e.getKey()] = self.python_object(e.getValue())
return pd

def python_object(self, o):
if isinstance(o, py4j.java_collections.JavaList):
return self._python_array(o)
elif isinstance(o, py4j.java_collections.JavaMap):
return self._python_dict(o)
elif isinstance(o, py4j.java_gateway.JavaObject) and \
o.getClass().getName() == 'clojure.lang.Keyword':
return o.toString()
else: return o;

@property
def _gw(self):
"""Return the gateway"""
Expand Down
34 changes: 34 additions & 0 deletions test/python/tests.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/usr/bin/env python

import py4j
import unittest, logging, sys
from zensols.clojure import Clojure

Expand Down Expand Up @@ -84,6 +85,39 @@ def test_entrypoint_ns(self):
finally:
cw.close()

def test_python_object(self):
cw = Clojure()
try:
o = cw.eval("""{:a 1 :b 2 :arr [{:animal "dog"} 99.2 :kw]}""")
o = cw.python_object(o)
self.assertTrue(isinstance(o, dict))
aval = o['a']
self.assertTrue(isinstance(aval, int))
self.assertEqual(aval, 1)
arr = o['arr']
self.assertTrue(isinstance(arr, list))
arrmap = arr[0]
self.assertTrue(isinstance(arrmap, dict))
mval = arrmap['animal']
self.assertTrue(isinstance(mval, str))
self.assertEqual('dog', mval)
self.assertEqual(arr[1], 99.2)
self.assertTrue(isinstance(arr[2], str))
self.assertEqual(arr[2], ':kw')
finally:
cw.close()

def test_embedded_python_object(self):
cw = Clojure()
try:
o = cw.eval("""{:last :map}""")
o = cw.eval("""{:a 1 :b 2 :arr [{:animal "dog"} 99.2 :kw lm]}""", {'lm': o})
o = cw.python_object(o)
self.assertEqual(o['arr'][3]['last'], ':map')
finally:
cw.close()


def enable_debug():
logging.basicConfig(level=logging.WARN)
logger.setLevel(logging.INFO)
Expand Down

0 comments on commit 2d6903b

Please sign in to comment.