diff python/pydc/test/types.py @ 34:2682a627168c

- breaking changes: * restrict 'Z' conversions to immutable types * restrict 'p' to mutable types (and handles)
author Tassilo Philipp
date Sun, 12 Apr 2020 19:37:37 +0200
parents 6cc2b7fc7ea2
children 0f86a5ecfe61
line wrap: on
line diff
--- a/python/pydc/test/types.py	Sat Apr 11 20:00:25 2020 +0200
+++ b/python/pydc/test/types.py	Sun Apr 12 19:37:37 2020 +0200
@@ -6,11 +6,15 @@
 
 
 def theader(title):
-  print(title)
-  print('%8s %20s %16s %-20s %12s %-12s -> %16s %-16s    # %s' % ('DC_SIG', 'C_RET_T', 'C_FSYM', 'C_PARAMLIST', 'PYTHON_ARG_T', 'IN_ARGS', 'RET_VAL', 'PYTHON_RET_T', 'NOTES'))
+  print("\n"+title)
+  print('%8s %20s %16s %-20s %11s %-16s -> %16s %-16s %12s %-16s  # %s' % ('DC_SIG', 'C_RET_T', 'C_FSYM', 'C_PARAMLIST', 'PY_ARG_T', 'IN_ARGS', 'RET_VAL', 'PY_RET_T', 'OUT_ARGS', 'OUT_ARGS_T', 'NOTES'))
 
 
 def t(lib, dcsig, c_rtype, c_fsym, c_paramlist, extra_msg, *args):
+  # before call
+  inarg_types = '('+','.join(map(lambda x: type(x).__name__, args))+')'
+  inargs = ','.join(map(str, args))
+  # call
   try:
     fp = pydc.find(lib, c_fsym)
     r = pydc.call(fp, dcsig, *args)
@@ -18,11 +22,12 @@
   except:
     r = '[EXCEPTION]'
     rt = '!'
-    extra_msg += ' "'+str(sys.exc_info()[1])+'"'
-
-  inarg_types = '('+','.join(map(lambda x: type(x).__name__, args))+')'
-  inargs = ','.join(map(str, args))
-  print('%8s %20s %16s %-20s %12s %-12s -> %16.16s %-16s    # %s' % (dcsig, c_rtype, c_fsym, c_paramlist, inarg_types, inargs, str(r), '('+rt+')', extra_msg))
+    e = str(sys.exc_info()[1])
+    extra_msg += ' "'+(e if len(e)<32 else e[0:32]+'...')+'"'
+  # after call
+  outarg_types = '('+','.join(map(lambda x: type(x).__name__, args))+')'
+  outargs = ','.join(map(str, args))
+  print('%8s %20s %16s %-20s %11s \033[33m%-16s\033[0m -> \033[32m%16.16s\033[0m %-16s %12s \033[32m%-16s\033[0m  # %s' % (dcsig, c_rtype, c_fsym, c_paramlist, inarg_types, inargs, str(r), '('+rt+')', outarg_types, outargs, extra_msg))
 
 
 
@@ -84,28 +89,57 @@
 
 l = pydc.load(sys.path[0]+"/test.so")
 
+# "long" typed test value use for Python 2
+long_i = 11234
+long_h = 0xdeadc0de
+if sys.version_info < (3, 0):
+  long_i = long(11234)
+  long_h = long(0xdeadc0de)
+
 # test all possible arg types and their conversions to and from python, with
 # specific focus/tests in areas where python 2 and 3 differ
 theader('ARG & RET TYPE CONVERSION TESTS:')
 t(l, "B)B", "int",                  "i_plus_one", "(int)",                '      False =>  True (using int func in C)', False)
+
 t(l, "c)c", "char",                 "c_plus_one", "(char)",               '   "a" (97) =>    98',                         'a')
 t(l, "C)C", "unsigned char",       "uc_plus_one", "(unsigned char)",      '   "a" (97) =>    98',                         'a')
 t(l, "c)c", "char",                 "c_plus_one", "(char)",               '         -2 =>    -1',                          -2)
 t(l, "C)C", "unsigned char",       "uc_plus_one", "(unsigned char)",      '         10 =>    11',                          10)
+
 t(l, "s)s", "short",                "s_plus_one", "(short)",              '         10 =>    11',                          10)
 t(l, "S)S", "unsigned short",      "us_plus_one", "(unsigned short)",     '         10 =>    11',                          10)
+
 t(l, "i)i", "int",                  "i_plus_one", "(int)",                '         10 =>    11',                          10)
 t(l, "I)I", "unsigned int",        "ui_plus_one", "(unsigned int)",       '         10 =>    11',                          10)
+
 t(l, "j)j", "long",                 "l_plus_one", "(long)",               '         10 =>    11',                          10)
 t(l, "J)J", "unsigned long",       "ul_plus_one", "(unsigned long)",      '         10 =>    11',                          10)
+
 t(l, "l)l", "long long",           "ll_plus_one", "(long long)",          '         10 =>    11',                          10)
 t(l, "L)L", "unsigned long long", "ull_plus_one", "(unsigned long long)", '         10 =>    11',                          10)
+t(l, "l)l", "long long",           "ll_plus_one", "(long long)",          '      11234 => 11235',                      long_i)
+t(l, "L)L", "unsigned long long", "ull_plus_one", "(unsigned long long)", '      11234 => 11235',                      long_i)
+
 t(l, "f)f", "float",                "f_plus_one", "(float)",              '      -1.23 => -0.23',                       -1.23)
 t(l, "d)d", "double",               "d_plus_one", "(double)",             '       5.67 =>  6.67',                        5.67)
-t(l, "Z)Z", "const char*",         "cc_plus_one", "(const char*)",        '"lose char" => "ose char"',            'lose char')
-t(l, "p)Z", "const char*",         "cc_plus_one", "(const char*)",        '"w/pointer" => "/pointer"',            'w/pointer')
-t(l, "p)p", "const char*",         "cc_plus_one", "(const char*)",        '        "x" => p+1 (retval is prob odd addr)', 'x')
-t(l, "p)p", "const char*",         "cc_plus_one", "(const char*)",        ' 0xdeadc0de => 0xdeadc0de+1=3735929055',0xdeadc0de)
+
+t(l, "Z)Z", "const char*",        "ccp_plus_one", "(const char*)",        '"lose char" => "ose char"',            'lose char') # string object
+t(l, "Z)Z", "const char*",        "ccp_plus_one", "(const char*)",        '"X_unicode" => "_unicode"',           u'X_unicode') # string object (unicode in Python 2)
+t(l, "Z)Z", "const char*",        "ccp_plus_one", "(const char*)",        '"1lessbyte" => "lessbyte"',           b'1lessbyte') # bytes object
+t(l, "Z)Z", "const char*",        "ccp_plus_one", "(const char*)",        '       "xY" =>    "Y"',           bytearray(b'xY')) # bytearray object
+
+t(l, "p)Z", "const char*",        "ccp_plus_one", "(const char*)",        '       "xY" =>    "Y"',           bytearray(b'xY')) # bytearray object
+t(l, "p)p", "const char*",        "ccp_plus_one", "(const char*)",        '       "xY" => p+1 (~ odd addr)', bytearray(b'xY')) # bytearray object
+t(l, "p)p", "const char*",        "ccp_plus_one", "(const char*)",        ' 0xdeadc0de => 0xdeadc0de+1=3735929055',    long_h) # handle (integer interpreted as ptr)
+t(l, "p)p", "const char*",        "ccp_plus_one", "(const char*)",        ' 0xdeadc0de => 0xdeadc0de+1=3735929055',    long_h) # handle (integer interpreted as ptr, long in Python 2)
+
+# functions that change buffers
+theader('TESTS OF IMMUTABLE AND MUTABLE PYTHON BUFFERS:')
+t(l, "Z)v", "const char*",        "cp_head_incr", "(const char*)",        '   "string" => None / arg => "string"  (not modified)"',         'string') # string object
+t(l, "Z)v", "const char*",        "cp_head_incr", "(const char*)",        '  "UnIcOdE" => None / arg => "UnIcOdE" (not modified)"',       u'UnIcOdE') # string object (unicode in Python 2)
+t(l, "Z)v", "const char*",        "cp_head_incr", "(const char*)",        '   "BCssk#" => None / arg => "BCssk#"  (not modified)"',        b'BCssk#') # bytes object
+t(l, "Z)v", "const char*",        "cp_head_incr", "(const char*)",        '       "xY" => None / arg => "xY"      (not modified)"', bytearray(b'xY')) # bytearray object
+t(l, "p)v", "const char*",        "cp_head_incr", "(const char*)",        '       "xY" => None / arg => "yY"       (!MODIFIED!)"',  bytearray(b'xY')) # bytearray object
 
 # tested checked value conversions
 theader('ARG & RET TYPE CONVERSION TESTS FOR RANGE CHECKED TYPES:')
@@ -136,47 +170,8 @@
 t(l, "S)S", "unsigned short",      "us_plus_one", "(unsigned short)",     '         -1 => input exc:',          -1)
 t(l, "S)S", "unsigned short",      "us_plus_one", "(unsigned short)",     '      65536 => input exc:',       65536)
 
+t(l, "p)Z", "const char*",        "ccp_plus_one", "(const char*)",        '"w/pointer" => input exc:', 'w/pointer') # string object, not passable as 'p'ointer
+t(l, "p)Z", "const char*",        "ccp_plus_one", "(const char*)",        '"X_unicode" => input exc:',u'X_unicode') # string object (unicode in Python 2), not passable as 'p'ointer
+t(l, "p)Z", "const char*",        "ccp_plus_one", "(const char*)",        '"1less/ptr" => input exc:',b'1less/ptr') # bytes object, not passable as 'p'ointer
+t(l, "p)p", "const char*",        "ccp_plus_one", "(const char*)",        '        "x" => input exc:',         'x') # string object, not passable as 'p'ointer
 
-#     int
-#     rand(void);
-#rand()
-#define DC_SIGCHAR_VOID         'v' ra
-#define DC_SIGCHAR_BOOL         'B'
-#define DC_SIGCHAR_CHAR         'c'    2 versions
-#define DC_SIGCHAR_UCHAR        'C'
-#define DC_SIGCHAR_SHORT        's'
-#define DC_SIGCHAR_USHORT       'S'
-#define DC_SIGCHAR_INT          'i' r
-#define DC_SIGCHAR_UINT         'I'  a
-#define DC_SIGCHAR_LONG         'j' ra
-#define DC_SIGCHAR_ULONG        'J'
-#define DC_SIGCHAR_LONGLONG     'l' ra
-#define DC_SIGCHAR_ULONGLONG    'L'
-#define DC_SIGCHAR_FLOAT        'f'
-#define DC_SIGCHAR_DOUBLE       'd'
-#define DC_SIGCHAR_POINTER      'p'
-#define DC_SIGCHAR_STRING       'Z'
-#define DC_SIGCHAR_STRUCT       'T'
-#define DC_SIGCHAR_ENDARG       ')' /* also works for end struct */
-
-
-
-#  SIG | FROM PYTHON 2                      | FROM PYTHON 3 @@@                  | C/C++                           | TO PYTHON 2                        | TO PYTHON 3 @@@
-#  ----+------------------------------------+------------------------------------+---------------------------------+------------------------------------+-----------------------------------
-#  'v' |                                    |                                    | void                            | ?NoneType (returned for "xxx)v")    | NoneType (returned for "xxx)v")
-#  'B' | ?PyBool                             | ?PyBool                             | bool                            | ?PyBool                             | ?PyBool
-#  'c' | ?PyInt (range checked)              | ?PyLong (range checked)             | char                            | ?PyInt                              | ?PyLong
-#  'C' | ?PyInt (range checked)              | ?PyLong (range checked)             | unsigned char                   | ?PyInt                              | ?PyLong
-#  's' | ?PyInt (range checked)              | ?PyLong (range checked)             | short                           | ?PyInt                              | ?PyLong
-#  'S' | ?PyInt (range checked)              | ?PyLong (range checked)             | unsigned short                  | ?PyInt                              | ?PyLong
-#  'i' | ?PyInt                              | ?PyLong                             | int                             | ?PyInt                              | ?PyLong
-#  'I' | ?PyInt                              | ?PyLong                             | unsigned int                    | ?PyInt                              | ?PyLong
-#  'j' | ?PyLong                             | ?PyLong                             | long                            | ?PyLong                             | ?PyLong
-#  'J' | ?PyLong                             | ?PyLong                             | unsigned long                   | ?PyLong                             | ?PyLong
-#  'l' | ?PyLongLong                         | ?PyLongLong                         | long long                       | ?PyLongLong                         | ?PyLongLong
-#  'L' | ?PyLongLong                         | ?PyLongLong                         | unsigned long long              | ?PyLongLong                         | ?PyLongLong
-#  'f' | ?PyFloat (cast to single precision) | ?PyFloat (cast to single precision) | float                           | ?PyFloat (cast to double precision) | ?PyFloat (cast to double precision)
-#  'd' | ?PyFloat                            | ?PyFloat                            | double                          | ?PyFloat                            | ?PyFloat
-#  'p' | ?PyUnicode/PyString/PyLong          | ?PyUnicode/PyBytes/PyLong           | void*                           | ?Py_ssize_t                         | ?Py_ssize_t
-#  'Z' | ?PyUnicode/PyString                 | ?PyUnicode/PyBytes                  | const char* (UTF-8 for unicode) | ?PyString                           | ?PyUnicode
-