diff --git a/pykit/__init__.py b/pykit/__init__.py index daf9ffd..c6d82da 100644 --- a/pykit/__init__.py +++ b/pykit/__init__.py @@ -1,2 +1,10 @@ __version__ = "0.2.0" from .ClCommand import ClCommand +from .types import Integer +from .types import Float +from .types import Character +from .types import Decimal +from .types import Binary +from .types import Parameter +from .program import Program +from .program import ServiceProgram diff --git a/pykit/program.py b/pykit/program.py new file mode 100644 index 0000000..a646c48 --- /dev/null +++ b/pykit/program.py @@ -0,0 +1,45 @@ +class Program: + """ + Object for calling an IBM i Program. + """ + def __init__(self, name, library=''): + self.name = name + self.library = library + self.parameters = [] + self.payload = { + "pgm": [{"name": name, "lib": library}] + } + + def add_parameter(self, parameter): + """ + + :param parameter: Parameter to be added + :return: + """ + self.parameters.append(parameter) + + + def get_payload(self): + if len(self.parameters) is 1: + self.payload["pgm"].append({"s": self.parameters[0].get_payload()}) + else: + self.payload["pgm"].append({"s":[]}) + for p in self.parameters: + self.payload["pgm"][-1]["s"].append(p.get_payload()) + + return self.payload + + +class ServiceProgram(Program): + """ + Object for calling an IBM i Program. + """ + def __init__(self, name, library='', function=''): + self.name = name + self.library = library + self.parameters = [] + self.payload = { + "pgm": [{"name": name, "lib": library, "func": function}] + } + + \ No newline at end of file diff --git a/pykit/tests/test_command.py b/pykit/tests/test_command.py index d0dd915..bc106b4 100644 --- a/pykit/tests/test_command.py +++ b/pykit/tests/test_command.py @@ -33,6 +33,5 @@ def test_execute_exec_command(self): self.assertTrue(response) - self.assertTrue(response) if __name__ == '__main__': unittest.main() diff --git a/pykit/tests/test_http.py b/pykit/tests/test_http.py index 7cbd12c..8f2bdc3 100644 --- a/pykit/tests/test_http.py +++ b/pykit/tests/test_http.py @@ -23,6 +23,5 @@ def test_execute_payload(self): self.assertTrue(response) - self.assertTrue(response) if __name__ == '__main__': unittest.main() diff --git a/pykit/tests/test_program.py b/pykit/tests/test_program.py new file mode 100644 index 0000000..ef77dff --- /dev/null +++ b/pykit/tests/test_program.py @@ -0,0 +1,49 @@ +import unittest +import os +from pykit.transport.http import connect +from pykit import * + + +class TestProgram(unittest.TestCase): + def setUp(self): + char = Parameter(Character("char", 128, "Hi there")) + self.hello_prog = Program("HELLO", "DB2JSON") + self.hello_prog.add_parameter(char) + + def test_hello_world(self): + self.assertEqual( + self.hello_prog.get_payload(), + {"pgm":[{"name":"HELLO", "lib":"DB2JSON"}, {"s":{"name":"char", "type":"128a", "value":"Hi there"}}]} + ) + + # WIP + def test_rainbow(self): + int = Parameter(Integer("aint8", 3, 1)) + float = Parameter(Float("afloat", 4, 2, 5.55)) + char = Parameter(Character("achar", 32, "A")) + rainbow = Program("RAINBOW", "DB2JSON") + rainbow.add_parameter(int) + rainbow.add_parameter(float) + rainbow.add_parameter(char) + self.assertEqual( + rainbow.get_payload(), + {"pgm":[{"name":"RAINBOW", "lib":"DB2JSON"}, {"s": [ + {"name":"aint8", "type":"3i0", "value":1}, + {"name":"afloat", "type":"4f2", "value":5.55}, + {"name":"achar", "type":"32a", "value":"A"} + ]}]} + ) + + def test_execute_hello_world(self): + connection = connect( + os.environ['PK_DB2SOCK_URL'], + db2sock_auth=( + os.environ['PK_DB2SOCK_USER'], os.environ['PK_DB2SOCK_PASS'])) + toolkit = connection.toolkit() + toolkit.add(self.hello_prog) + response = toolkit.execute() + self.assertEqual(response, {"script": [{"pgm": ["HELLO", "DB2JSON", {"char": "Hello World"}]}]}) + + +if __name__ == '__main__': + unittest.main() diff --git a/pykit/tests/test_service_program.py b/pykit/tests/test_service_program.py new file mode 100644 index 0000000..44ff200 --- /dev/null +++ b/pykit/tests/test_service_program.py @@ -0,0 +1,43 @@ +import unittest +import os +from pykit.transport.http import connect +from pykit import * + + +class TestServiceProgram(unittest.TestCase): + def setUp(self): + char = Parameter(Character("char", 128, "Hi there")) + char_return = Parameter(Character("char", 128, "Hi back"), direction='out', byValue=False, isReturn=True) + self.hello_prog = ServiceProgram("HELLOSRV", "DB2JSON", "HELLO") + self.hello_prog.add_parameter(char) + self.hello_prog_return = ServiceProgram("HELLOSRV", "DB2JSON", "HELLOAGAIN") + self.hello_prog_return.add_parameter(char) + self.hello_prog_return.add_parameter(char_return) + + + def test_hello(self): + self.assertEqual( + self.hello_prog.get_payload(), + {"pgm":[{"name":"HELLOSRV", "lib":"DB2JSON", "func": "HELLO"}, + {"s":{"name":"char", "type":"128a", "value":"Hi there"}}]} + ) + self.assertEqual( + self.hello_prog_return.get_payload(), + {"pgm":[{"name":"HELLOSRV", "lib":"DB2JSON", "func": "HELLOAGAIN"}, + {"s":[{"name":"char", "type":"128a", "value":"Hi there"}, + {"name":"char", "type":"128a", "value":"Hi back", "by":"return"}]}]} + ) + + def test_execute_hello_world(self): + connection = connect( + os.environ['PK_DB2SOCK_URL'], + db2sock_auth=( + os.environ['PK_DB2SOCK_USER'], os.environ['PK_DB2SOCK_PASS'])) + toolkit = connection.toolkit() + toolkit.add(self.hello_prog) + response = toolkit.execute() + self.assertEqual(response, {"script": [{"pgm": ["HELLOSRV", "DB2JSON", "HELLO", {"char": "Hello World"}]}]}) + + +if __name__ == '__main__': + unittest.main() diff --git a/pykit/tests/test_toolkit.py b/pykit/tests/test_toolkit.py index ffed516..3896354 100644 --- a/pykit/tests/test_toolkit.py +++ b/pykit/tests/test_toolkit.py @@ -3,7 +3,7 @@ from pykit.transport.http import connect -class TestHttpConnection(unittest.TestCase): +class TestToolkit(unittest.TestCase): def setUp(self): self.connection = connect( os.environ['PK_DB2SOCK_URL'], diff --git a/pykit/tests/test_types.py b/pykit/tests/test_types.py new file mode 100644 index 0000000..d1187d4 --- /dev/null +++ b/pykit/tests/test_types.py @@ -0,0 +1,49 @@ +import unittest +import os +from pykit import Integer, Float, Character, Decimal, Binary, Parameter + + +class TestInteger(unittest.TestCase): + def test_integer_payload(self): + new_int = Parameter(Integer('aint8', 3, 1)) + self.assertEqual(new_int.get_payload(), {"name":"aint8", "type":"3i0", "value":1}) + + def test_unsigned_integer_payload(self): + new_int = Parameter(Integer('auint8', 3, 1, False)) + self.assertEqual(new_int.get_payload(), {"name":"auint8", "type":"3u0", "value":1}) + + +class TestFloat(unittest.TestCase): + def test_float_payload(self): + new_float = Parameter(Float('afloat', 4, 2, 5.55)) + self.assertEqual(new_float.get_payload(), {"name":"afloat", "type":"4f2", "value":5.55}) + + +class TestCharacter(unittest.TestCase): + def test_character_payload(self): + char = Parameter(Character('achar', 10, "Hello")) + self.assertEqual(char.get_payload(), {"name":"achar", "type":"10a", "value":"Hello"}) + + def test_character_varying_payload(self): + char = Parameter(Character('bchar', 100, "Bye", 2)) + self.assertEqual(char.get_payload(), {"name":"bchar", "type":"100av2", "value":"Bye"}) + + +class TestDecimal(unittest.TestCase): + def test_decimal_payload(self): + dec = Parameter(Decimal('adec', 10, 2, 850.2)) + self.assertEqual(dec.get_payload(), {"name":"adec", "type":"10p2", "value":850.2}) + + def test_signed_decimal_payload(self): + dec = Parameter(Decimal('bdec', 9, 0, 800, True)) + self.assertEqual(dec.get_payload(), {"name":"bdec", "type":"9s0", "value":800}) + +class TestBinary(unittest.TestCase): + def test_binary_payload(self): + bin = Parameter(Binary('abin', 2, "0000")) + self.assertEqual(bin.get_payload(), {"name":"abin", "type":"2b", "value":"0000"}) + + + +if __name__ == '__main__': + unittest.main() diff --git a/pykit/types.py b/pykit/types.py new file mode 100644 index 0000000..d632e44 --- /dev/null +++ b/pykit/types.py @@ -0,0 +1,157 @@ +class Parameter: + def __init__(self, parameterType, direction='inout', byValue=False, isReturn=False): + """ + :param name: + :param value: + """ + self.parameterType = parameterType + self.direction = direction + self.isReturn = isReturn + self.byValue = False + self.payload = {} + + def get_payload(self): + self.payload = self.parameterType.get_payload() + if self.isReturn: + self.payload['by'] = 'return' + if self.byValue: + self.payload['by'] = 'val' + + return self.payload + + +class ParameterType: + """ + Object for IBM i ParameterTypes. + """ + def __init__(self, name, value): + """ + :param name: + :param value: + """ + self.value = value + self.name = str(name) + self.payload = {"name":self.name} + + + def get_payload(self): + self.payload['value'] = self.value + return self.payload + +class Float(ParameterType): + """ + Object for IBM i Float. + """ + def __init__(self, name, length, precision, value): + """ + How much error checking do we want here? + Should we check that length is positive? + Should we check if value matches length? + Should we truncate the value to the length? + + :param length: + :param precision:s + :param value: + """ + ParameterType.__init__(self, name, value) + self.length = length + self.precision = precision + + def get_payload(self): + self.payload['type'] = str(self.length) + 'f' + str(self.precision) + ParameterType.get_payload(self) + return self.payload + + +class Integer(ParameterType): + """ + Object for IBM i Integer. + """ + def __init__(self, name, length, value, signed=True): + """ + How much error checking do we want here? + Should we check that length is positive? + Should we check if value matches length? + Should we truncate the value to the length? + + :param length: + :param value: + """ + ParameterType.__init__(self, name, value) + self.length = length + self.signed = signed + + def get_payload(self): + self.payload['type'] = str(self.length) + ('i' if self.signed else 'u') + '0' + ParameterType.get_payload(self) + + return self.payload + + +class Character(ParameterType): + """ + Object for IBM i Character. + """ + def __init__(self, name, length, value, varying=''): + """ + :param length: + :param value: + """ + ParameterType.__init__(self, name, value) + self.length = length + self.varying = varying + + def get_payload(self): + self.payload['type'] = str(self.length) + 'a' + if self.varying: + self.payload['type'] = self.payload['type'] + 'v' + str(self.varying) + + ParameterType.get_payload(self) + return self.payload + + +class Decimal(ParameterType): + """ + Object for IBM i Decimal. + """ + def __init__(self, name, length, decimals, value, signed=False): + """ + How much error checking do we want here? + Should we check that length is positive? + Should we check if value matches length? + Should we truncate the value to the length? + + :param length: + :param value: + """ + ParameterType.__init__(self, name, value) + self.length = length + self.signed = signed + self.decimals = decimals + + def get_payload(self): + self.payload['type'] = str(self.length) + ('s' if self.signed else 'p') + str(self.decimals) + ParameterType.get_payload(self) + + return self.payload + + +class Binary(ParameterType): + """ + Object for IBM i Binary. + """ + def __init__(self, name, length, value): + """ + + :param length: + :param value: + """ + ParameterType.__init__(self, name, value) + self.length = length + + def get_payload(self): + self.payload['type'] = str(self.length) + 'b' + ParameterType.get_payload(self) + return self.payload + + \ No newline at end of file