cwrap 1.6.6__py3-none-any.whl → 1.6.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cwrap/__init__.py +25 -15
- cwrap/basecclass.py +26 -31
- cwrap/basecenum.py +11 -20
- cwrap/basecvalue.py +35 -13
- cwrap/cfile.py +89 -154
- cwrap/clib.py +27 -25
- cwrap/metacwrap.py +19 -12
- cwrap/prototype.py +50 -71
- cwrap/version.py +2 -2
- {cwrap-1.6.6.dist-info → cwrap-1.6.7.dist-info}/METADATA +1 -2
- cwrap-1.6.7.dist-info/RECORD +14 -0
- cwrap-1.6.6.dist-info/RECORD +0 -14
- {cwrap-1.6.6.dist-info → cwrap-1.6.7.dist-info}/LICENSE +0 -0
- {cwrap-1.6.6.dist-info → cwrap-1.6.7.dist-info}/WHEEL +0 -0
- {cwrap-1.6.6.dist-info → cwrap-1.6.7.dist-info}/top_level.txt +0 -0
cwrap/__init__.py
CHANGED
@@ -28,26 +28,36 @@ the process of interacting with a C library:
|
|
28
28
|
FILE pointer.
|
29
29
|
"""
|
30
30
|
|
31
|
-
try:
|
32
|
-
|
31
|
+
try:
|
32
|
+
from .version import version as __version__
|
33
|
+
except ImportError:
|
34
|
+
__version__ = "0.0.0"
|
33
35
|
|
34
|
-
__author__ =
|
35
|
-
__copyright__ =
|
36
|
+
__author__ = "Statoil ASA"
|
37
|
+
__copyright__ = "Copyright 2016, Statoil ASA"
|
36
38
|
__credits__ = __author__
|
37
|
-
__license__ =
|
39
|
+
__license__ = "GPL"
|
38
40
|
__maintainer__ = __author__
|
39
|
-
__email__ =
|
40
|
-
__status__ =
|
41
|
+
__email__ = "fg_gpl@statoil.com"
|
42
|
+
__status__ = "Prototype"
|
41
43
|
|
42
44
|
from .basecclass import BaseCClass
|
43
45
|
from .basecenum import BaseCEnum
|
44
46
|
from .basecvalue import BaseCValue
|
45
|
-
|
46
|
-
from .cfile import
|
47
|
-
from .clib import
|
48
|
-
|
47
|
+
from .cfile import CFILE
|
48
|
+
from .cfile import copen as open
|
49
|
+
from .clib import lib_name, load
|
49
50
|
from .metacwrap import MetaCWrap
|
50
|
-
from .prototype import REGISTERED_TYPES, Prototype, PrototypeError
|
51
|
-
|
52
|
-
__all__ = [
|
53
|
-
|
51
|
+
from .prototype import REGISTERED_TYPES, Prototype, PrototypeError # noqa
|
52
|
+
|
53
|
+
__all__ = [
|
54
|
+
"BaseCClass",
|
55
|
+
"BaseCEnum",
|
56
|
+
"BaseCValue",
|
57
|
+
"CFILE",
|
58
|
+
"open",
|
59
|
+
"MetaCWrap",
|
60
|
+
"Prototype",
|
61
|
+
"load",
|
62
|
+
"lib_name",
|
63
|
+
]
|
cwrap/basecclass.py
CHANGED
@@ -14,16 +14,12 @@
|
|
14
14
|
# See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
15
15
|
# for more details.
|
16
16
|
|
17
|
-
from __future__ import (absolute_import, division,
|
18
|
-
print_function, unicode_literals)
|
19
|
-
|
20
|
-
import six
|
21
|
-
|
22
17
|
import ctypes
|
18
|
+
|
23
19
|
from .metacwrap import MetaCWrap
|
24
20
|
|
25
|
-
|
26
|
-
class BaseCClass(
|
21
|
+
|
22
|
+
class BaseCClass(metaclass=MetaCWrap):
|
27
23
|
namespaces = {}
|
28
24
|
|
29
25
|
def __init__(self, c_pointer, parent=None, is_reference=False):
|
@@ -31,14 +27,16 @@ class BaseCClass(object):
|
|
31
27
|
raise ValueError("Must have a valid (not null) pointer value!")
|
32
28
|
|
33
29
|
if c_pointer < 0:
|
34
|
-
raise ValueError(
|
30
|
+
raise ValueError(
|
31
|
+
"The pointer value is negative! This may be correct, but usually is not!"
|
32
|
+
)
|
35
33
|
|
36
34
|
self.__c_pointer = c_pointer
|
37
35
|
self.__parent = parent
|
38
36
|
self.__is_reference = is_reference
|
39
37
|
|
40
38
|
def __new__(cls, *more, **kwargs):
|
41
|
-
obj = super(
|
39
|
+
obj = super().__new__(cls)
|
42
40
|
obj.__c_pointer = None
|
43
41
|
obj.__parent = None
|
44
42
|
obj.__is_reference = False
|
@@ -52,7 +50,7 @@ class BaseCClass(object):
|
|
52
50
|
return self.__c_pointer
|
53
51
|
|
54
52
|
def _ad_str(self):
|
55
|
-
return
|
53
|
+
return f"at 0x{self._address():x}"
|
56
54
|
|
57
55
|
@classmethod
|
58
56
|
def from_param(cls, c_class_object):
|
@@ -61,14 +59,16 @@ class BaseCClass(object):
|
|
61
59
|
|
62
60
|
if c_class_object is None:
|
63
61
|
return ctypes.c_void_p()
|
64
|
-
|
65
|
-
|
62
|
+
|
63
|
+
return ctypes.c_void_p(c_class_object.__c_pointer)
|
66
64
|
|
67
65
|
@classmethod
|
68
66
|
def createPythonObject(cls, c_pointer):
|
69
67
|
if c_pointer is not None:
|
70
68
|
new_obj = cls.__new__(cls)
|
71
|
-
BaseCClass.__init__(
|
69
|
+
BaseCClass.__init__(
|
70
|
+
new_obj, c_pointer=c_pointer, parent=None, is_reference=False
|
71
|
+
)
|
72
72
|
return new_obj
|
73
73
|
else:
|
74
74
|
return None
|
@@ -77,7 +77,9 @@ class BaseCClass(object):
|
|
77
77
|
def createCReference(cls, c_pointer, parent=None):
|
78
78
|
if c_pointer is not None:
|
79
79
|
new_obj = cls.__new__(cls)
|
80
|
-
BaseCClass.__init__(
|
80
|
+
BaseCClass.__init__(
|
81
|
+
new_obj, c_pointer=c_pointer, parent=parent, is_reference=True
|
82
|
+
)
|
81
83
|
return new_obj
|
82
84
|
else:
|
83
85
|
return None
|
@@ -90,7 +92,6 @@ class BaseCClass(object):
|
|
90
92
|
self.__is_reference = True
|
91
93
|
self.__parent = parent
|
92
94
|
|
93
|
-
|
94
95
|
def setParent(self, parent=None):
|
95
96
|
if self.__is_reference:
|
96
97
|
self.__parent = parent
|
@@ -100,7 +101,7 @@ class BaseCClass(object):
|
|
100
101
|
return self
|
101
102
|
|
102
103
|
def isReference(self):
|
103
|
-
"""
|
104
|
+
"""@rtype: bool"""
|
104
105
|
return self.__is_reference
|
105
106
|
|
106
107
|
def parent(self):
|
@@ -113,7 +114,7 @@ class BaseCClass(object):
|
|
113
114
|
if isinstance(other, BaseCClass):
|
114
115
|
return self.__c_pointer == other.__c_pointer
|
115
116
|
else:
|
116
|
-
return super(
|
117
|
+
return super() == other
|
117
118
|
|
118
119
|
def __hash__(self):
|
119
120
|
# Similar to last resort comparison; this returns the hash of the
|
@@ -123,37 +124,31 @@ class BaseCClass(object):
|
|
123
124
|
def free(self):
|
124
125
|
raise NotImplementedError("A BaseCClass requires a free method implementation!")
|
125
126
|
|
126
|
-
def _create_repr(self, args
|
127
|
+
def _create_repr(self, args=""):
|
127
128
|
"""Representation on the form (e.g.) 'EclFile(...) at 0x1729'."""
|
128
|
-
return "{
|
129
|
+
return f"{self.__class__.__name__}({args}) {self._ad_str()}"
|
129
130
|
|
130
131
|
def __repr__(self):
|
131
132
|
"""Representation on the form (e.g.) 'EclFile(...) at 0x1729'."""
|
132
133
|
return self._create_repr()
|
133
134
|
|
134
135
|
def __del__(self):
|
135
|
-
if self.free is not None:
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
if self.__c_pointer:
|
140
|
-
self.free()
|
136
|
+
if self.free is not None and not self.__is_reference and self.__c_pointer:
|
137
|
+
# Important to check the c_pointer; in the case of failed object creation
|
138
|
+
# we can have a Python object with c_pointer == None.
|
139
|
+
self.free()
|
141
140
|
|
142
141
|
def _invalidateCPointer(self):
|
143
142
|
self.__c_pointer = None
|
144
143
|
|
145
|
-
|
146
144
|
def __bool__(self):
|
147
145
|
"""The BaseCClass instance will evaluate to true if it is bound to an
|
148
146
|
underlying C object, otherwise it will evaluate to False. More
|
149
147
|
elaborate bool tests should be implemented in the derived
|
150
148
|
class.
|
151
149
|
"""
|
152
|
-
if self.__c_pointer:
|
153
|
-
return True
|
154
|
-
else:
|
155
|
-
return False
|
156
150
|
|
151
|
+
return bool(self.__c_pointer)
|
157
152
|
|
158
153
|
def __nonzero__(self):
|
159
|
-
return self.__bool__(
|
154
|
+
return self.__bool__()
|
cwrap/basecenum.py
CHANGED
@@ -14,17 +14,12 @@
|
|
14
14
|
# See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
15
15
|
# for more details.
|
16
16
|
|
17
|
-
from __future__ import absolute_import, division, print_function, unicode_literals
|
18
|
-
|
19
17
|
import ctypes
|
20
18
|
|
21
|
-
import six
|
22
|
-
|
23
19
|
from .metacwrap import MetaCWrap
|
24
20
|
|
25
21
|
|
26
|
-
|
27
|
-
class BaseCEnum(object):
|
22
|
+
class BaseCEnum(metaclass=MetaCWrap):
|
28
23
|
enum_namespace = {}
|
29
24
|
|
30
25
|
def __init__(self, *args, **kwargs):
|
@@ -36,11 +31,11 @@ class BaseCEnum(object):
|
|
36
31
|
enum = cls.__resolveEnum(args[0])
|
37
32
|
|
38
33
|
if enum is None:
|
39
|
-
raise ValueError("Unknown enum value:
|
34
|
+
raise ValueError(f"Unknown enum value: {args[0]}")
|
40
35
|
|
41
36
|
return enum
|
42
37
|
else:
|
43
|
-
obj = super(
|
38
|
+
obj = super().__new__(cls, *args)
|
44
39
|
obj.name = None
|
45
40
|
obj.value = None
|
46
41
|
return obj
|
@@ -57,7 +52,7 @@ class BaseCEnum(object):
|
|
57
52
|
if enum.name == name:
|
58
53
|
return enum
|
59
54
|
|
60
|
-
raise ValueError("No such enum
|
55
|
+
raise ValueError(f"No such enum: {name}")
|
61
56
|
|
62
57
|
@classmethod
|
63
58
|
def addEnum(cls, name, value):
|
@@ -102,7 +97,7 @@ class BaseCEnum(object):
|
|
102
97
|
cn = self.__class__.__name__
|
103
98
|
na = self.name
|
104
99
|
va = self.value
|
105
|
-
return '
|
100
|
+
return f'{cn}(name = "{na}", value = {va})'
|
106
101
|
|
107
102
|
def __add__(self, other):
|
108
103
|
self.__assertOtherIsSameType(other)
|
@@ -126,7 +121,7 @@ class BaseCEnum(object):
|
|
126
121
|
|
127
122
|
def __int__(self):
|
128
123
|
return self.value
|
129
|
-
|
124
|
+
|
130
125
|
def __index__(self):
|
131
126
|
return self.value
|
132
127
|
|
@@ -136,7 +131,7 @@ class BaseCEnum(object):
|
|
136
131
|
@classmethod
|
137
132
|
def __createEnum(cls, value):
|
138
133
|
enum = cls.__new__(cls)
|
139
|
-
enum.name = "Unnamed '
|
134
|
+
enum.name = f"Unnamed '{cls.__name__}' enum with value: {value}"
|
140
135
|
enum.value = value
|
141
136
|
return enum
|
142
137
|
|
@@ -159,20 +154,16 @@ class BaseCEnum(object):
|
|
159
154
|
def __assertOtherIsSameType(self, other):
|
160
155
|
assert isinstance(
|
161
156
|
other, self.__class__
|
162
|
-
), "Can only operate on enums of same type:
|
163
|
-
self.__class__.__name__,
|
164
|
-
other.__class__.__name__,
|
165
|
-
)
|
157
|
+
), f"Can only operate on enums of same type: {self.__class__.__name__} =! {other.__class__.__name__}"
|
166
158
|
|
167
159
|
@classmethod
|
168
160
|
def populateEnum(cls, library, enum_provider_function):
|
169
161
|
try:
|
170
162
|
func = getattr(library, enum_provider_function)
|
171
|
-
except AttributeError:
|
163
|
+
except AttributeError as err:
|
172
164
|
raise ValueError(
|
173
|
-
"Could not find enum description function:
|
174
|
-
|
175
|
-
)
|
165
|
+
f"Could not find enum description function: {enum_provider_function} - can not load enum: {cls.__name__}."
|
166
|
+
) from err
|
176
167
|
|
177
168
|
func.restype = ctypes.c_char_p
|
178
169
|
func.argtypes = [ctypes.c_int, ctypes.POINTER(ctypes.c_int)]
|
cwrap/basecvalue.py
CHANGED
@@ -14,30 +14,52 @@
|
|
14
14
|
# See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
|
15
15
|
# for more details.
|
16
16
|
|
17
|
-
from
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
17
|
+
from ctypes import (
|
18
|
+
c_bool,
|
19
|
+
c_byte,
|
20
|
+
c_char,
|
21
|
+
c_double,
|
22
|
+
c_float,
|
23
|
+
c_int,
|
24
|
+
c_long,
|
25
|
+
c_short,
|
26
|
+
c_ubyte,
|
27
|
+
c_uint,
|
28
|
+
c_ulong,
|
29
|
+
c_ushort,
|
30
|
+
pointer,
|
31
|
+
)
|
24
32
|
|
25
33
|
from .metacwrap import MetaCWrap
|
26
34
|
|
27
|
-
|
28
|
-
class BaseCValue(
|
35
|
+
|
36
|
+
class BaseCValue(metaclass=MetaCWrap):
|
29
37
|
DATA_TYPE = None
|
30
|
-
LEGAL_TYPES = [
|
38
|
+
LEGAL_TYPES = [
|
39
|
+
c_byte,
|
40
|
+
c_ubyte,
|
41
|
+
c_short,
|
42
|
+
c_ushort,
|
43
|
+
c_int,
|
44
|
+
c_uint,
|
45
|
+
c_long,
|
46
|
+
c_ulong,
|
47
|
+
c_bool,
|
48
|
+
c_char,
|
49
|
+
c_float,
|
50
|
+
c_double,
|
51
|
+
]
|
31
52
|
|
32
53
|
def __init__(self, value):
|
33
|
-
super(
|
54
|
+
super().__init__()
|
34
55
|
|
35
56
|
if not self.DATA_TYPE in self.LEGAL_TYPES:
|
36
|
-
raise ValueError(
|
57
|
+
raise ValueError(
|
58
|
+
f"DATA_TYPE must be one of these CTypes classes: {BaseCValue.LEGAL_TYPES}"
|
59
|
+
)
|
37
60
|
|
38
61
|
self.__value = self.cast(value)
|
39
62
|
|
40
|
-
|
41
63
|
def value(self):
|
42
64
|
return self.__value.value
|
43
65
|
|
cwrap/cfile.py
CHANGED
@@ -15,160 +15,95 @@
|
|
15
15
|
# for more details.
|
16
16
|
|
17
17
|
import os
|
18
|
-
import six
|
19
|
-
import sys
|
20
|
-
from .prototype import Prototype
|
21
|
-
from .basecclass import BaseCClass
|
22
18
|
|
19
|
+
from .basecclass import BaseCClass
|
20
|
+
from .clib import load as cwrapload
|
21
|
+
from .prototype import Prototype
|
23
22
|
|
24
|
-
if six.PY2:
|
25
|
-
import ctypes
|
26
|
-
|
27
|
-
def copen(filename, mode='r'):
|
28
|
-
"""
|
29
|
-
This is a compatibility layer for functions taking FILE* pointers, and
|
30
|
-
should not be used unless absolutely needed.
|
31
23
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
if
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
def
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
CWrapFile is a very lightweight wrapper around FILE* instances. It is
|
120
|
-
meant be used inplace of python file objects that are to be passed to
|
121
|
-
foreign function calls under python 3.
|
122
|
-
|
123
|
-
Example:
|
124
|
-
with cwrap.open('filename', 'mode') as f:
|
125
|
-
foreign_function_call(f)
|
126
|
-
"""
|
127
|
-
|
128
|
-
TYPE_NAME = "FILE"
|
129
|
-
|
130
|
-
_fopen = LibcPrototype("void* fopen (char*, char*)")
|
131
|
-
_fclose = LibcPrototype("int fclose (FILE)", bind=True)
|
132
|
-
_fflush = LibcPrototype("int fflush (FILE)", bind=True)
|
133
|
-
|
134
|
-
def __init__(self, fname, mode):
|
135
|
-
c_ptr = self._fopen(fname, mode)
|
136
|
-
self._mode = mode
|
137
|
-
self._fname = fname
|
138
|
-
self._closed = False
|
139
|
-
|
140
|
-
try:
|
141
|
-
super(CWrapFile, self).__init__(c_ptr)
|
142
|
-
except ValueError:
|
143
|
-
self._closed = True
|
144
|
-
raise IOError('Could not open file "{}" in mode {}'
|
145
|
-
.format(fname, mode))
|
146
|
-
|
147
|
-
def close(self):
|
148
|
-
if not self._closed:
|
149
|
-
self._fflush()
|
150
|
-
cs = self._fclose()
|
151
|
-
if (cs != 0):
|
152
|
-
raise IOError("Failed to close file")
|
153
|
-
self._closed = True
|
154
|
-
|
155
|
-
def __enter__(self):
|
156
|
-
return self
|
157
|
-
|
158
|
-
def __exit__(self, exc_type, exc_val, exc_tb):
|
159
|
-
self.close()
|
160
|
-
return exc_type is None
|
161
|
-
|
162
|
-
def free(self):
|
163
|
-
self.close()
|
164
|
-
|
165
|
-
def __del__(self):
|
166
|
-
self.close()
|
167
|
-
|
168
|
-
def CFILE(f):
|
169
|
-
if not isinstance(f, CWrapFile):
|
170
|
-
raise TypeError("This function requires the use of CWrapFile, "
|
171
|
-
"not {} when running Python 3. See "
|
172
|
-
"help(cwrap.open) for more info"
|
173
|
-
.format(type(f).__name__))
|
174
|
-
return f
|
24
|
+
class LibcPrototype(Prototype):
|
25
|
+
# Load the c standard library (on Linux passsing None does the trick)
|
26
|
+
lib = cwrapload("msvcrt" if os.name == "nt" else None)
|
27
|
+
|
28
|
+
def __init__(self, prototype, bind=False, allow_attribute_error=False):
|
29
|
+
super().__init__(
|
30
|
+
LibcPrototype.lib,
|
31
|
+
prototype,
|
32
|
+
bind=bind,
|
33
|
+
allow_attribute_error=allow_attribute_error,
|
34
|
+
)
|
35
|
+
|
36
|
+
|
37
|
+
def copen(filename, mode="r"):
|
38
|
+
"""
|
39
|
+
This is a compatibility layer for functions taking FILE* pointers, and
|
40
|
+
should not be used unless absolutely needed.
|
41
|
+
|
42
|
+
It returns an instance of CWrapFile, a very lightweight
|
43
|
+
wrapper around a FILE* instance.
|
44
|
+
"""
|
45
|
+
return CWrapFile(filename, mode)
|
46
|
+
|
47
|
+
|
48
|
+
class CWrapFile(BaseCClass):
|
49
|
+
"""
|
50
|
+
This is a compatibility layer for functions taking FILE* pointers, and
|
51
|
+
should not be used unless absolutely needed.
|
52
|
+
|
53
|
+
CWrapFile is a very lightweight wrapper around FILE* instances. It is
|
54
|
+
meant be used inplace of python file objects that are to be passed to
|
55
|
+
foreign function calls under python 3.
|
56
|
+
|
57
|
+
Example:
|
58
|
+
with cwrap.open('filename', 'mode') as f:
|
59
|
+
foreign_function_call(f)
|
60
|
+
"""
|
61
|
+
|
62
|
+
TYPE_NAME = "FILE"
|
63
|
+
|
64
|
+
_fopen = LibcPrototype("void* fopen (char*, char*)")
|
65
|
+
_fclose = LibcPrototype("int fclose (FILE)", bind=True)
|
66
|
+
_fflush = LibcPrototype("int fflush (FILE)", bind=True)
|
67
|
+
|
68
|
+
def __init__(self, fname, mode):
|
69
|
+
c_ptr = self._fopen(fname, mode)
|
70
|
+
self._mode = mode
|
71
|
+
self._fname = fname
|
72
|
+
self._closed = False
|
73
|
+
|
74
|
+
try:
|
75
|
+
super().__init__(c_ptr)
|
76
|
+
except ValueError as err:
|
77
|
+
self._closed = True
|
78
|
+
raise OSError(f'Could not open file "{fname}" in mode {mode}') from err
|
79
|
+
|
80
|
+
def close(self):
|
81
|
+
if not self._closed:
|
82
|
+
self._fflush()
|
83
|
+
cs = self._fclose()
|
84
|
+
if cs != 0:
|
85
|
+
raise OSError("Failed to close file")
|
86
|
+
self._closed = True
|
87
|
+
|
88
|
+
def __enter__(self):
|
89
|
+
return self
|
90
|
+
|
91
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
92
|
+
self.close()
|
93
|
+
return exc_type is None
|
94
|
+
|
95
|
+
def free(self):
|
96
|
+
self.close()
|
97
|
+
|
98
|
+
def __del__(self):
|
99
|
+
self.close()
|
100
|
+
|
101
|
+
|
102
|
+
def CFILE(f):
|
103
|
+
if not isinstance(f, CWrapFile):
|
104
|
+
raise TypeError(
|
105
|
+
"This function requires the use of CWrapFile, "
|
106
|
+
f"not {type(f).__name__} when running Python 3. See "
|
107
|
+
"help(cwrap.open) for more info"
|
108
|
+
)
|
109
|
+
return f
|
cwrap/clib.py
CHANGED
@@ -31,45 +31,46 @@ be invoked when loading libert_geometry, and that could in principle
|
|
31
31
|
lead to loading a different version of libert_util.so
|
32
32
|
"""
|
33
33
|
|
34
|
-
import platform
|
35
34
|
import ctypes
|
36
35
|
import os
|
36
|
+
import platform
|
37
37
|
|
38
|
-
so_extension = {
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
38
|
+
so_extension = {
|
39
|
+
"linux": "so",
|
40
|
+
"linux2": "so",
|
41
|
+
"linux3": "so",
|
42
|
+
"windows": "dll",
|
43
|
+
"darwin": "dylib",
|
44
|
+
}
|
43
45
|
|
44
46
|
|
45
47
|
# Passing None to the CDLL() function means to open a lib handle to
|
46
48
|
# the current runnning process, i.e. like dlopen( NULL ). We must
|
47
49
|
# special case this to avoid creating the bogus argument 'None.so'.
|
48
50
|
|
49
|
-
|
51
|
+
|
52
|
+
def lib_name(lib, path=None, so_version=None, so_ext=None):
|
50
53
|
if lib is None:
|
51
54
|
return None
|
52
55
|
else:
|
53
56
|
platform_key = platform.system().lower()
|
54
57
|
if so_version is None:
|
55
|
-
so_version =
|
58
|
+
so_version = ""
|
56
59
|
|
57
60
|
if so_ext:
|
58
|
-
so_name = "
|
61
|
+
so_name = f"{lib}.{so_ext}{so_version}"
|
59
62
|
elif platform_key == "darwin":
|
60
|
-
so_name = "
|
63
|
+
so_name = f"{lib}{so_version}.{so_extension[platform_key]}"
|
61
64
|
else:
|
62
|
-
so_name = "
|
65
|
+
so_name = f"{lib}.{so_extension[platform_key]}{so_version}"
|
63
66
|
|
64
67
|
if path:
|
65
|
-
return os.path.join(
|
68
|
+
return os.path.join(path, so_name)
|
66
69
|
else:
|
67
70
|
return so_name
|
68
71
|
|
69
72
|
|
70
|
-
|
71
|
-
|
72
|
-
def load( lib, so_version = None, path = None, so_ext = None):
|
73
|
+
def load(lib, so_version=None, path=None, so_ext=None):
|
73
74
|
"""Thin wrapper around the ctypes.CDLL function for loading shared
|
74
75
|
library.
|
75
76
|
|
@@ -79,32 +80,33 @@ def load( lib, so_version = None, path = None, so_ext = None):
|
|
79
80
|
"""
|
80
81
|
|
81
82
|
dll = None
|
82
|
-
lib_files = [
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
83
|
+
lib_files = [
|
84
|
+
lib_name(lib, path=None, so_version=so_version),
|
85
|
+
lib_name(lib, path=None, so_version=so_version, so_ext=so_ext),
|
86
|
+
lib_name(lib, path=path, so_version=so_version),
|
87
|
+
lib_name(lib, path=path, so_version=so_version, so_ext=so_ext),
|
88
|
+
]
|
87
89
|
|
88
90
|
for lib_file in lib_files:
|
89
91
|
try:
|
90
|
-
dll = ctypes.CDLL(lib_file
|
92
|
+
dll = ctypes.CDLL(lib_file, ctypes.RTLD_GLOBAL)
|
91
93
|
return dll
|
92
94
|
except Exception as exc:
|
93
95
|
error = exc
|
94
96
|
|
95
|
-
error_msg = "\nFailed to load shared library
|
97
|
+
error_msg = f"\nFailed to load shared library:{lib}\n\ndlopen() error: {error}\n"
|
96
98
|
|
97
99
|
LD_LIBRARY_PATH = os.getenv("LD_LIBRARY_PATH")
|
98
100
|
if not LD_LIBRARY_PATH:
|
99
101
|
LD_LIBRARY_PATH = ""
|
100
102
|
|
101
|
-
error_msg += """
|
103
|
+
error_msg += f"""
|
102
104
|
The runtime linker has searched through the default location of shared
|
103
105
|
libraries, and also the locations mentioned in your LD_LIBRARY_PATH
|
104
106
|
variable. Your current LD_LIBRARY_PATH setting is:
|
105
107
|
|
106
|
-
LD_LIBRARY_PATH:
|
108
|
+
LD_LIBRARY_PATH: {LD_LIBRARY_PATH}
|
107
109
|
|
108
110
|
You might need to update this variable?
|
109
|
-
"""
|
111
|
+
"""
|
110
112
|
raise ImportError(error_msg)
|
cwrap/metacwrap.py
CHANGED
@@ -15,27 +15,23 @@
|
|
15
15
|
# for more details.
|
16
16
|
|
17
17
|
import re
|
18
|
-
from types import MethodType
|
19
18
|
|
20
19
|
from .prototype import Prototype
|
21
20
|
|
22
21
|
|
23
22
|
def snakeCase(name):
|
24
|
-
s1 = re.sub(
|
25
|
-
return re.sub(
|
23
|
+
s1 = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", name)
|
24
|
+
return re.sub("([a-z0-9])([A-Z])", r"\1_\2", s1).lower()
|
26
25
|
|
27
26
|
|
28
27
|
class MetaCWrap(type):
|
29
28
|
def __init__(cls, name, bases, attrs):
|
30
|
-
super(
|
29
|
+
super().__init__(name, bases, attrs)
|
31
30
|
|
32
31
|
is_return_type = False
|
33
32
|
storage_type = None
|
34
33
|
|
35
|
-
if "TYPE_NAME" in attrs
|
36
|
-
type_name = attrs["TYPE_NAME"]
|
37
|
-
else:
|
38
|
-
type_name = snakeCase(name)
|
34
|
+
type_name = attrs["TYPE_NAME"] if "TYPE_NAME" in attrs else snakeCase(name)
|
39
35
|
|
40
36
|
if hasattr(cls, "DATA_TYPE") or hasattr(cls, "enums"):
|
41
37
|
is_return_type = True
|
@@ -43,14 +39,25 @@ class MetaCWrap(type):
|
|
43
39
|
if hasattr(cls, "storageType"):
|
44
40
|
storage_type = cls.storageType()
|
45
41
|
|
46
|
-
Prototype.registerType(
|
42
|
+
Prototype.registerType(
|
43
|
+
type_name, cls, is_return_type=is_return_type, storage_type=storage_type
|
44
|
+
)
|
47
45
|
|
48
46
|
if hasattr(cls, "createCReference"):
|
49
|
-
Prototype.registerType(
|
47
|
+
Prototype.registerType(
|
48
|
+
f"{type_name}_ref",
|
49
|
+
cls.createCReference,
|
50
|
+
is_return_type=True,
|
51
|
+
storage_type=storage_type,
|
52
|
+
)
|
50
53
|
|
51
54
|
if hasattr(cls, "createPythonObject"):
|
52
|
-
Prototype.registerType(
|
53
|
-
|
55
|
+
Prototype.registerType(
|
56
|
+
f"{type_name}_obj",
|
57
|
+
cls.createPythonObject,
|
58
|
+
is_return_type=True,
|
59
|
+
storage_type=storage_type,
|
60
|
+
)
|
54
61
|
|
55
62
|
for key, attr in attrs.items():
|
56
63
|
if isinstance(attr, Prototype):
|
cwrap/prototype.py
CHANGED
@@ -20,10 +20,8 @@ import re
|
|
20
20
|
import sys
|
21
21
|
from types import MethodType
|
22
22
|
|
23
|
-
import six
|
24
23
|
|
25
|
-
|
26
|
-
class TypeDefinition(object):
|
24
|
+
class TypeDefinition:
|
27
25
|
def __init__(self, type_class_or_function, is_return_type, storage_type, errcheck):
|
28
26
|
self.storage_type = storage_type
|
29
27
|
self.is_return_type = is_return_type
|
@@ -34,36 +32,32 @@ class TypeDefinition(object):
|
|
34
32
|
self.errcheck = errcheck
|
35
33
|
|
36
34
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
"""
|
64
|
-
if result is None or result == 0:
|
65
|
-
return None
|
66
|
-
return result.decode()
|
35
|
+
class CStringHelper:
|
36
|
+
@classmethod
|
37
|
+
def from_param(cls, value):
|
38
|
+
if value is None:
|
39
|
+
return None
|
40
|
+
elif isinstance(value, (bytes, ctypes.Array)):
|
41
|
+
return value
|
42
|
+
else:
|
43
|
+
e = value.encode()
|
44
|
+
return e
|
45
|
+
|
46
|
+
@staticmethod
|
47
|
+
def toStr(result, func, arguments):
|
48
|
+
"""
|
49
|
+
Transform a foreign char* type to str.
|
50
|
+
|
51
|
+
ctypes functions have an attribute called errcheck that can not
|
52
|
+
only be used for error checking but also to alter the result. If
|
53
|
+
errcheck is defined, the value returned from that function is what
|
54
|
+
is returned from the foreign function call. In this case, C returns
|
55
|
+
strings in the form of zero-terminated char* strings. To use these
|
56
|
+
as python strings (str) they must be decoded.
|
57
|
+
"""
|
58
|
+
if result is None or result == 0:
|
59
|
+
return None
|
60
|
+
return result.decode()
|
67
61
|
|
68
62
|
|
69
63
|
REGISTERED_TYPES = {}
|
@@ -78,7 +72,7 @@ def _registerType(
|
|
78
72
|
errcheck=None,
|
79
73
|
):
|
80
74
|
if type_name in REGISTERED_TYPES:
|
81
|
-
raise PrototypeError("Type: '
|
75
|
+
raise PrototypeError(f"Type: '{type_name}' already registered!")
|
82
76
|
|
83
77
|
REGISTERED_TYPES[type_name] = TypeDefinition(
|
84
78
|
type_class_or_function, is_return_type, storage_type, errcheck
|
@@ -100,16 +94,14 @@ _registerType("bool*", ctypes.POINTER(ctypes.c_bool))
|
|
100
94
|
_registerType("long", ctypes.c_long)
|
101
95
|
_registerType("long*", ctypes.POINTER(ctypes.c_long))
|
102
96
|
_registerType("char", ctypes.c_char)
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
errcheck=CStringHelper.toStr,
|
112
|
-
)
|
97
|
+
|
98
|
+
|
99
|
+
_registerType(
|
100
|
+
"char*",
|
101
|
+
CStringHelper,
|
102
|
+
storage_type=ctypes.c_char_p,
|
103
|
+
errcheck=CStringHelper.toStr,
|
104
|
+
)
|
113
105
|
_registerType("float", ctypes.c_float)
|
114
106
|
_registerType("float*", ctypes.POINTER(ctypes.c_float))
|
115
107
|
_registerType("double", ctypes.c_double)
|
@@ -127,11 +119,11 @@ class PrototypeError(Exception):
|
|
127
119
|
pass
|
128
120
|
|
129
121
|
|
130
|
-
class Prototype
|
122
|
+
class Prototype:
|
131
123
|
pattern = re.compile(PROTOTYPE_PATTERN)
|
132
124
|
|
133
125
|
def __init__(self, lib, prototype, bind=False, allow_attribute_error=False):
|
134
|
-
super(
|
126
|
+
super().__init__()
|
135
127
|
self._lib = lib
|
136
128
|
self._prototype = prototype
|
137
129
|
self._bind = bind
|
@@ -151,7 +143,7 @@ class Prototype(object):
|
|
151
143
|
type_definition.storage_type,
|
152
144
|
type_definition.errcheck,
|
153
145
|
)
|
154
|
-
raise ValueError("Unknown type:
|
146
|
+
raise ValueError(f"Unknown type: {type_name}")
|
155
147
|
|
156
148
|
def shouldBeBound(self):
|
157
149
|
return self._bind
|
@@ -159,7 +151,7 @@ class Prototype(object):
|
|
159
151
|
def resolve(self):
|
160
152
|
match = re.match(Prototype.pattern, self._prototype)
|
161
153
|
if not match:
|
162
|
-
raise PrototypeError("Illegal prototype definition:
|
154
|
+
raise PrototypeError(f"Illegal prototype definition: {self._prototype}\n")
|
163
155
|
else:
|
164
156
|
restype = match.groupdict()["return"]
|
165
157
|
function_name = match.groupdict()["function"]
|
@@ -168,29 +160,26 @@ class Prototype(object):
|
|
168
160
|
|
169
161
|
try:
|
170
162
|
func = getattr(self._lib, function_name)
|
171
|
-
except AttributeError:
|
163
|
+
except AttributeError as err:
|
172
164
|
if self._allow_attribute_error:
|
173
165
|
return
|
174
166
|
raise PrototypeError(
|
175
|
-
"Can not find function:
|
176
|
-
|
177
|
-
)
|
167
|
+
f"Can not find function: {function_name} in library: {self._lib}"
|
168
|
+
) from err
|
178
169
|
|
179
170
|
if (
|
180
171
|
not restype in REGISTERED_TYPES
|
181
172
|
or not REGISTERED_TYPES[restype].is_return_type
|
182
173
|
):
|
183
174
|
sys.stderr.write(
|
184
|
-
"The type used as return type:
|
185
|
-
% restype
|
175
|
+
f"The type used as return type: {restype} is not registered as a return type.\n"
|
186
176
|
)
|
187
177
|
|
188
178
|
return_type, storage_type, errcheck = self._parseType(restype)
|
189
179
|
|
190
180
|
if inspect.isclass(return_type):
|
191
181
|
sys.stderr.write(
|
192
|
-
" Correct type may be:
|
193
|
-
% (restype, restype)
|
182
|
+
f" Correct type may be: {restype}_ref or {restype}_obj.\n"
|
194
183
|
)
|
195
184
|
|
196
185
|
return None
|
@@ -227,7 +216,7 @@ class Prototype(object):
|
|
227
216
|
if self._func is None:
|
228
217
|
if self._allow_attribute_error:
|
229
218
|
raise NotImplementedError(
|
230
|
-
"Function
|
219
|
+
f"Function:{self.__name__} has not been properly resolved"
|
231
220
|
)
|
232
221
|
else:
|
233
222
|
raise PrototypeError("Prototype has not been properly resolved")
|
@@ -249,15 +238,8 @@ class Prototype(object):
|
|
249
238
|
tokens = re.split("[ :]", errMsg)
|
250
239
|
argidx = int(tokens[1]) - 1 # it starts from 1
|
251
240
|
raise TypeError(
|
252
|
-
|
253
|
-
|
254
|
-
"value {actval} ({acttype})"
|
255
|
-
).format(
|
256
|
-
argtype=self._func.argtypes[argidx],
|
257
|
-
argidx=argidx,
|
258
|
-
actval=repr(args[argidx]),
|
259
|
-
acttype=type(args[argidx]),
|
260
|
-
)
|
241
|
+
f"Argument {argidx}: cannot create a {self._func.argtypes[argidx]} from the given "
|
242
|
+
f"value {repr(args[argidx])} ({type(args[argidx])})"
|
261
243
|
) from err
|
262
244
|
|
263
245
|
def __get__(self, instance, owner):
|
@@ -265,10 +247,7 @@ class Prototype(object):
|
|
265
247
|
self.resolve()
|
266
248
|
self._resolved = True
|
267
249
|
if self.shouldBeBound():
|
268
|
-
|
269
|
-
return MethodType(self, instance, owner)
|
270
|
-
if six.PY3:
|
271
|
-
return MethodType(self, instance)
|
250
|
+
return MethodType(self, instance)
|
272
251
|
else:
|
273
252
|
return self
|
274
253
|
|
@@ -277,7 +256,7 @@ class Prototype(object):
|
|
277
256
|
if self.shouldBeBound():
|
278
257
|
bound = ", bind=True"
|
279
258
|
|
280
|
-
return 'Prototype("
|
259
|
+
return f'Prototype("{self._prototype}"{bound})'
|
281
260
|
|
282
261
|
@classmethod
|
283
262
|
def registerType(
|
cwrap/version.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: cwrap
|
3
|
-
Version: 1.6.
|
3
|
+
Version: 1.6.7
|
4
4
|
Summary: cwrap - ctypes blanket
|
5
5
|
Home-page: https://github.com/Statoil/cwrap
|
6
6
|
Author: Statoil ASA
|
@@ -22,7 +22,6 @@ Classifier: Programming Language :: Python :: 3.12
|
|
22
22
|
Classifier: Topic :: Software Development :: Libraries
|
23
23
|
Classifier: Topic :: Utilities
|
24
24
|
License-File: LICENSE
|
25
|
-
Requires-Dist: six
|
26
25
|
|
27
26
|
|
28
27
|
=======
|
@@ -0,0 +1,14 @@
|
|
1
|
+
cwrap/__init__.py,sha256=jaZFUAG-rgT5RBJURcR_PCzGFmudtoAMaITTho0QIoY,1935
|
2
|
+
cwrap/basecclass.py,sha256=MtJQddSMegJ3TJ13rZM40_WV6DBnIVtdeIilbk7yLuI,4804
|
3
|
+
cwrap/basecenum.py,sha256=2Q8LsFZWMQRCuqcvkIZWczKctNCg40eaQAp8lCFoRCo,5119
|
4
|
+
cwrap/basecvalue.py,sha256=Idg2EnyVuRD6Eh8xjcXVuiGsqpjakKnq8hSwjczrAA8,2102
|
5
|
+
cwrap/cfile.py,sha256=vkVpZZ_BsM6etqnLja7XNbBR9bBSGxTYR7VhhC1qCJs,3233
|
6
|
+
cwrap/clib.py,sha256=E94IqKHOoGozwbrPFe38XCretUzPr5MEdTK0tg5_VKI,3591
|
7
|
+
cwrap/metacwrap.py,sha256=hZkY1piH7R8dahydIxIHd8RQjkKm9gqHGtUKsQhqpaE,2017
|
8
|
+
cwrap/prototype.py,sha256=Djzv6KO91VZjp-X8VOXDpEFwq1qNSBxkMnUZZv01EBg,9228
|
9
|
+
cwrap/version.py,sha256=UBH9kvxesdE0svvcKwHfK8rz5bJUzNXPBHo7APqVEfk,411
|
10
|
+
cwrap-1.6.7.dist-info/LICENSE,sha256=KdZLnTl6Qk0PT7wUW8ugRdviqwxU5wjE26sku5sicOU,674
|
11
|
+
cwrap-1.6.7.dist-info/METADATA,sha256=YlKh1653mezcM30tOrxPf6amaGscK0ql9UFx4oxYv9w,1203
|
12
|
+
cwrap-1.6.7.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
13
|
+
cwrap-1.6.7.dist-info/top_level.txt,sha256=CUjoCmJmjoO-LFc7eRvSm7AHuFbYgwHhkQ6Al-x6sTk,6
|
14
|
+
cwrap-1.6.7.dist-info/RECORD,,
|
cwrap-1.6.6.dist-info/RECORD
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
cwrap/__init__.py,sha256=u26LODQXzzMi3d43B6gHd0vX2FM44J-ooNnVp2nfKV0,1875
|
2
|
-
cwrap/basecclass.py,sha256=HgrEyQIfa5tcrOROv-4_wQfYuESJebO1HsrgIw1zL2g,5020
|
3
|
-
cwrap/basecenum.py,sha256=roAqm0v0AiVf-uDzFambT_D3YGVlQxVSweNdkJH7SFM,5319
|
4
|
-
cwrap/basecvalue.py,sha256=gEcwMHdZ7q7zn7Ou1ZG-OfLSUlIZf2X1xRVUmseo88o,2091
|
5
|
-
cwrap/cfile.py,sha256=1qdryUEMPbZbWccYyFSd_gT4EMk6CrlAvi2MEqmv-mY,5948
|
6
|
-
cwrap/clib.py,sha256=pAOc6-uEVQxzWcx2hry35WecxTi4gmv92sQcGVghiLo,3756
|
7
|
-
cwrap/metacwrap.py,sha256=He9HtExc78S9uz08u_za_N1e8DBHcyf_JT3-R3LzSNs,1931
|
8
|
-
cwrap/prototype.py,sha256=op5zQGV8rA4qodajxGN-UTfuyx6XDPjypiZAB4C1YEo,10013
|
9
|
-
cwrap/version.py,sha256=Nz1l8vGPOAOAlxWDepNu28nfH9fOKk0GnGSnVyZJsFE,411
|
10
|
-
cwrap-1.6.6.dist-info/LICENSE,sha256=KdZLnTl6Qk0PT7wUW8ugRdviqwxU5wjE26sku5sicOU,674
|
11
|
-
cwrap-1.6.6.dist-info/METADATA,sha256=bZSHL23VCIRAqONcQoeR-slRe6o-f4Fyn3ctqZTON7c,1222
|
12
|
-
cwrap-1.6.6.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
13
|
-
cwrap-1.6.6.dist-info/top_level.txt,sha256=CUjoCmJmjoO-LFc7eRvSm7AHuFbYgwHhkQ6Al-x6sTk,6
|
14
|
-
cwrap-1.6.6.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|