Skip to content

Commit

Permalink
Merge branch 'ugufugu_master'
Browse files Browse the repository at this point in the history
  • Loading branch information
HJianBo committed Apr 2, 2020
2 parents 5dad3e6 + b6268f4 commit a89ce3d
Show file tree
Hide file tree
Showing 12 changed files with 253 additions and 31 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,8 @@
/testall.log
_build
rebar.lock
.idea/
.rebar3/
.rebar/
ebin/
*.iml
24 changes: 16 additions & 8 deletions priv/python2/erlport/erlterms.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,15 +200,23 @@ def decode_term(string,
if not string:
raise IncompleteData(string)
tag = string[0]
if tag == "d":
# ATOM_EXT
if tag == "d" or tag == "w":
# ATOM_EXT, SMALL_ATOM_UTF8_EXT
ln = len(string)
if ln < 3:
raise IncompleteData(string)
length = int2_unpack(string[1:3])[0] + 3
if ln < length:
raise IncompleteData(string)
name = string[3:length]
if tag == "d":
if ln < 3:
raise IncompleteData(string)
length = int2_unpack(string[1:3])[0] + 3
if ln < length:
raise IncompleteData(string)
name = string[3:length]
else:
if ln < 2:
raise IncompleteData(string)
length = ord(string[1]) + 2
if ln < length:
raise IncompleteData(string)
name = string[2:length]
if name == "true":
return True, string[length:]
elif name == "false":
Expand Down
20 changes: 20 additions & 0 deletions priv/python2/erlport/tests/erlterms_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ def test_atom(self):
self.assertFalse(atom is Atom("test2"))
self.assertTrue(atom is Atom("test"))
self.assertEqual("X" * 255, Atom("X" * 255))
self.assertEqual("\xc3\xa4", Atom("\xc3\xa4"))
self.assertEqual("\xe4", Atom("\xe4"))

def test_invalid_atom(self):
self.assertRaises(ValueError, Atom, "X" * 256)
Expand Down Expand Up @@ -139,21 +141,39 @@ def test_decode(self):
self.assertRaises(ValueError, decode, "\x83z")

def test_decode_atom(self):
# ATOM_EXT:
self.assertRaises(IncompleteData, decode, "\x83d")
self.assertRaises(IncompleteData, decode, "\x83d\0")
self.assertRaises(IncompleteData, decode, "\x83d\0\1")
self.assertEqual((Atom(""), ""), decode("\x83d\0\0"))
self.assertEqual((Atom(""), "tail"), decode("\x83d\0\0tail"))
self.assertEqual((Atom("test"), ""), decode("\x83d\0\4test"))
self.assertEqual((Atom("test"), "tail"), decode("\x83d\0\4testtail"))
self.assertEqual((Atom("\xe4"), ""), decode("\x83d\0\1\xe4"))
# SMALL_ATOM_UTF8_EXT:
self.assertRaises(IncompleteData, decode, "\x83w")
self.assertRaises(IncompleteData, decode, "\x83w\1")
self.assertEqual((Atom(""), ""), decode("\x83w\0"))
self.assertEqual((Atom(""), "tail"), decode("\x83w\0tail"))
self.assertEqual((Atom("test"), ""), decode("\x83w\4test"))
self.assertEqual((Atom("test"), "tail"), decode("\x83w\4testtail"))
self.assertEqual((Atom("\xc3\xa4"), ""), decode("\x83w\2\xc3\xa4"))

def test_decode_predefined_atoms(self):
# ATOM_EXT:
self.assertEqual((True, ""), decode("\x83d\0\4true"))
self.assertEqual((True, "tail"), decode("\x83d\0\4truetail"))
self.assertEqual((False, ""), decode("\x83d\0\5false"))
self.assertEqual((False, "tail"), decode("\x83d\0\5falsetail"))
self.assertEqual((None, ""), decode("\x83d\0\11undefined"))
self.assertEqual((None, "tail"), decode("\x83d\0\11undefinedtail"))
# SMALL_ATOM_UTF8_EXT:
self.assertEqual((True, ""), decode("\x83w\4true"))
self.assertEqual((True, "tail"), decode("\x83w\4truetail"))
self.assertEqual((False, ""), decode("\x83w\5false"))
self.assertEqual((False, "tail"), decode("\x83w\5falsetail"))
self.assertEqual((None, ""), decode("\x83w\11undefined"))
self.assertEqual((None, "tail"), decode("\x83w\11undefinedtail"))

def test_decode_empty_list(self):
self.assertEqual(([], ""), decode("\x83j"))
Expand Down
2 changes: 0 additions & 2 deletions priv/python3/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
.cover
erlport/__init__.py
erlport/cli.py
33 changes: 33 additions & 0 deletions priv/python3/erlport/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Copyright (c) 2009-2015, Dmitry Vasiliev <[email protected]>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from this
# software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

"""Erlang port protocol."""

__author__ = "Dmitry Vasiliev <[email protected]>"
__version__ = "1.0"

from erlport.erlterms import Atom, List, ImproperList
77 changes: 77 additions & 0 deletions priv/python3/erlport/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Copyright (c) 2009-2015, Dmitry Vasiliev <[email protected]>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from this
# software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

from optparse import OptionParser, OptionValueError

from erlport import erlang
from erlport.erlproto import Port


def get_option_parser():
def packet_option_handler(option, opt_str, value, parser):
if value not in (1, 2, 4):
raise OptionValueError("Valid values for --packet are 1, 2, or 4")
setattr(parser.values, option.dest, value)

def compress_level(option, opt_str, value, parser):
if value < 0 or value > 9:
raise OptionValueError("Valid values for --compressed are 0..9")
setattr(parser.values, option.dest, value)

def buffer_size(option, opt_str, value, parser):
if not value > 0:
raise OptionValueError("Buffer size value should be greater than 0")
setattr(parser.values, option.dest, value)

parser = OptionParser(description="ErlPort - Erlang port protocol")
parser.add_option("--packet", action="callback", type="int",
help="Message length sent in N bytes. Valid values are 1, 2, or 4",
metavar="N", callback=packet_option_handler, default=4)
parser.add_option("--nouse_stdio", action="store_false",
dest="stdio", default=True,
help="Use file descriptors 3 and 4 for communication with Erlang")
parser.add_option("--use_stdio", action="store_true", dest="stdio",
default=True,
help="Use file descriptors 0 and 1 for communication with Erlang")
parser.add_option("--compressed", action="callback", type="int", default=0,
help="Compression level", metavar="LEVEL", callback=compress_level)
parser.add_option("--buffer_size", action="callback", type="int",
default=65536, help="Receive buffer size", metavar="SIZE",
callback=buffer_size)
return parser


def main(argv=None):
parser = get_option_parser()
options, args = parser.parse_args(argv)
port = Port(use_stdio=options.stdio, packet=options.packet,
compressed=options.compressed, buffer_size=options.buffer_size)
erlang.setup(port)


if __name__ == "__main__":
main()
24 changes: 16 additions & 8 deletions priv/python3/erlport/erlterms.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,15 +199,23 @@ def decode_term(string,
if not string:
raise IncompleteData(string)
tag = string[0]
if tag == 100:
# ATOM_EXT
if tag == 100 or tag == 119:
# ATOM_EXT, SMALL_ATOM_UTF8_EXT
ln = len(string)
if ln < 3:
raise IncompleteData(string)
length = int2_unpack(string[1:3])[0] + 3
if ln < length:
raise IncompleteData(string)
name = string[3:length]
if tag == 100:
if ln < 3:
raise IncompleteData(string)
length = int2_unpack(string[1:3])[0] + 3
if ln < length:
raise IncompleteData(string)
name = string[3:length]
else:
if ln < 2:
raise IncompleteData(string)
length = string[1] + 2
if ln < length:
raise IncompleteData(string)
name = string[2:length]
if name == b"true":
return True, string[length:]
elif name == b"false":
Expand Down
58 changes: 58 additions & 0 deletions priv/python3/erlport/python.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Copyright (c) 2009-2015, Dmitry Vasiliev <[email protected]>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice,
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from this
# software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.

from erlport import Atom, erlang


# TODO: Base class should be extracted so we can use it for Ruby class too
class Python(object):

def __init__(self, **kwargs):
options = self.parse_options(kwargs)
# TODO: Handle 'node' option with 'rpc' module
result = erlang.call(Atom("python"), Atom("start"), options)
if type(result) != tuple or len(result) != 2:
# TODO: Fix exception
raise Exception(result)
if result[0] is not Atom("ok"):
# TODO: Fix exception
raise Exception(result[1])
self.pid = result[1]

def parse_options(self, kwargs):
# TODO: Parse options
return []

def call(self, module, function, args):
# TODO: Check all arguments
# TODO: Reraise Python related exceptions
return erlang.call(Atom("python"), Atom("call"),
[self.pid, module, function, args])

def stop(self):
# TODO: Check result
erlang.call(Atom("python"), Atom("stop"), [self.pid])
20 changes: 20 additions & 0 deletions priv/python3/erlport/tests/erlterms_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ def test_atom(self):
self.assertFalse(atom is Atom(b"test2"))
self.assertTrue(atom is Atom(b"test"))
self.assertEqual(b"X" * 255, Atom(b"X" * 255))
self.assertEqual(b"\xc3\xa4", Atom(b"\xc3\xa4"))
self.assertEqual(b"\xe4", Atom(b"\xe4"))

def test_invalid_atom(self):
self.assertRaises(ValueError, Atom, b"X" * 256)
Expand Down Expand Up @@ -139,21 +141,39 @@ def test_decode(self):
self.assertRaises(ValueError, decode, b"\x83z")

def test_decode_atom(self):
# ATOM_EXT:
self.assertRaises(IncompleteData, decode, b"\x83d")
self.assertRaises(IncompleteData, decode, b"\x83d\0")
self.assertRaises(IncompleteData, decode, b"\x83d\0\1")
self.assertEqual((Atom(b""), b""), decode(b"\x83d\0\0"))
self.assertEqual((Atom(b""), b"tail"), decode(b"\x83d\0\0tail"))
self.assertEqual((Atom(b"test"), b""), decode(b"\x83d\0\4test"))
self.assertEqual((Atom(b"test"), b"tail"), decode(b"\x83d\0\4testtail"))
self.assertEqual((Atom(b"\xe4"), b""), decode(b"\x83d\0\1\xe4"))
# SMALL_ATOM_UTF8_EXT:
self.assertRaises(IncompleteData, decode, b"\x83w")
self.assertRaises(IncompleteData, decode, b"\x83w\1")
self.assertEqual((Atom(b""), b""), decode(b"\x83w\0"))
self.assertEqual((Atom(b""), b"tail"), decode(b"\x83w\0tail"))
self.assertEqual((Atom(b"test"), b""), decode(b"\x83w\4test"))
self.assertEqual((Atom(b"test"), b"tail"), decode(b"\x83w\4testtail"))
self.assertEqual((Atom(b"\xc3\xa4"), b""), decode(b"\x83w\2\xc3\xa4"))

def test_decode_predefined_atoms(self):
# ATOM_EXT:
self.assertEqual((True, b""), decode(b"\x83d\0\4true"))
self.assertEqual((True, b"tail"), decode(b"\x83d\0\4truetail"))
self.assertEqual((False, b""), decode(b"\x83d\0\5false"))
self.assertEqual((False, b"tail"), decode(b"\x83d\0\5falsetail"))
self.assertEqual((None, b""), decode(b"\x83d\0\11undefined"))
self.assertEqual((None, b"tail"), decode(b"\x83d\0\11undefinedtail"))
# SMALL_ATOM_UTF8_EXT:
self.assertEqual((True, b""), decode(b"\x83w\4true"))
self.assertEqual((True, b"tail"), decode(b"\x83w\4truetail"))
self.assertEqual((False, b""), decode(b"\x83w\5false"))
self.assertEqual((False, b"tail"), decode(b"\x83w\5falsetail"))
self.assertEqual((None, b""), decode(b"\x83w\11undefined"))
self.assertEqual((None, b"tail"), decode(b"\x83w\11undefinedtail"))

def test_decode_empty_list(self):
self.assertEqual(([], b""), decode(b"\x83j"))
Expand Down
17 changes: 6 additions & 11 deletions ebin/erlport.app → src/erlport.app.src
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,10 @@
{application, erlport, [
{description, "Erlang port protocol"},
{vsn, "0.9.8"},
{modules, [
erlport,
erlport_options,
erlport_utils,
python,
python_options,
ruby,
ruby_options
]},
{modules, []},
{registered, []},
{applications, [kernel, stdlib]}
]}.
{applications, [kernel, stdlib]},
{maintainers, ["Dmitry Vasiliev"]},
{licenses, ["BSD-3-Clause"]},
{links,[{"Github", "https://github.com/hdima/erlport"}]}
]}.
2 changes: 1 addition & 1 deletion src/python.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

-record(python_options, {
python = default :: string() | default,
cd :: Path :: string(),
cd :: Path :: string() | undefined,
use_stdio = use_stdio :: use_stdio | nouse_stdio,
compressed = 0 :: 0..9,
packet = 4 :: 1 | 2 | 4,
Expand Down
2 changes: 1 addition & 1 deletion src/ruby.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@

-record(ruby_options, {
ruby = default :: string() | default,
cd :: Path :: string(),
cd :: Path :: string() | undefined,
use_stdio = use_stdio :: use_stdio | nouse_stdio,
compressed = 0 :: 0..9,
packet = 4 :: 1 | 2 | 4,
Expand Down

0 comments on commit a89ce3d

Please sign in to comment.