• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

trolldbois / ctypeslib / 4773564691

pending completion
4773564691

push

github

Loic Jaquemet
try without baipp

1601 of 1912 relevant lines covered (83.73%)

50.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

75.5
/ctypeslib/clang2py.py
1
#!/usr/bin/env python3
2
import argparse
60✔
3
import logging
60✔
4
import os
60✔
5
import platform
60✔
6
import re
60✔
7
import sys
60✔
8
import tempfile
60✔
9
import traceback
60✔
10

11
from ctypes import RTLD_GLOBAL
60✔
12

13
import ctypeslib
60✔
14
from ctypeslib.codegen import typedesc, config
60✔
15
from ctypeslib.codegen.codegenerator import translate_files
60✔
16
from ctypeslib.library import Library
60✔
17
from ctypeslib import clang_version, clang_py_version
60✔
18

19
################################################################
20
windows_dll_names = """\
48✔
21
imagehlp
×
22
user32
×
23
kernel32
×
24
gdi32
×
25
advapi32
×
26
oleaut32
×
27
ole32
×
28
imm32
×
29
comdlg32
×
30
shell32
×
31
version
×
32
winmm
×
33
mpr
×
34
winscard
×
35
winspool.drv
×
36
urlmon
×
37
crypt32
×
38
cryptnet
×
39
ws2_32
×
40
opengl32
×
41
glu32
×
42
mswsock
×
43
msvcrt
×
44
msimg32
×
45
netapi32
×
46
rpcrt4""".split()
36✔
47

48

49
# rpcndr
50
# ntdll
51

52
def _is_typedesc(item):
60✔
53
    for c in item:
60✔
54
        if c not in 'acdefmstu':
60✔
55
            raise argparse.ArgumentTypeError("types choices are 'acdefmstu'")
×
56
    return item
60✔
57

58

59
class Input:
60✔
60
    def __init__(self, options):
60✔
61
        self.files = []
60✔
62
        self._stdin = None
60✔
63
        for f in options.files:
60✔
64
            # stdin case
65
            if f == sys.stdin:
60✔
66
                _stdin = tempfile.NamedTemporaryFile(mode="w", prefix="stdin", suffix=".c", delete=False)
60✔
67
                _stdin.write(f.read())
60✔
68
                f = _stdin
60✔
69
            self.files.append(f.name)
60✔
70
            f.close()
60✔
71

72
    def __enter__(self):
60✔
73
        return self
60✔
74

75
    def __exit__(self, exc_type, exc_value, tb):
60✔
76
        if self._stdin:
60✔
77
            os.remove(self._stdin.name)
×
78
        return False
60✔
79

80

81
class Output:
60✔
82
    def __init__(self, options):
60✔
83
        # handle output
84
        if options.output == "-":
60✔
85
            self.stream = sys.stdout
60✔
86
            self.output_file = None
60✔
87
        else:
×
88
            self.stream = open(options.output, "w")
×
89
            self.output_file = self.stream
×
90

91
    def __enter__(self):
60✔
92
        return self
60✔
93

94
    def __exit__(self, exc_type, exc_value, tb):
60✔
95
        if self.output_file is not None:
60✔
96
            self.output_file.close()
×
97
            # we do not want to delete the output file.
98
            # os.remove(self.output_file.name)
99
        # If an exception is supplied, and the method wishes to suppress the exception
100
        # (i.e., prevent it from being propagated), it should return a true value.
101
        return False
60✔
102

103

104
def main(argv=None):
60✔
105
    if argv is None:
60✔
106
        argv = sys.argv[1:]
×
107
    cfg = config.CodegenConfig()
60✔
108
    cfg.local_platform_triple = "%s-%s" % (platform.machine(), platform.system())
60✔
109
    cfg.known_symbols = {}
60✔
110
    cfg.searched_dlls = []
60✔
111
    cfg.clang_opts = []
60✔
112
    files = None
60✔
113

114
    def windows_dlls(option, opt, value, parser):
60✔
115
        parser.values.dlls.extend(windows_dll_names)
×
116

117
    cfg.version = ctypeslib.__version__
60✔
118

119
    parser = argparse.ArgumentParser(prog='clang2py',
60✔
120
                                     description='Version %s. Generate python code from C headers' % cfg.version)
60✔
121
    parser.add_argument("-c", "--comments",
60✔
122
                        dest="generate_comments",
60✔
123
                        action="store_true",
60✔
124
                        help="include source doxygen-style comments",
60✔
125
                        default=False)
60✔
126
    parser.add_argument("-d", "--doc",
60✔
127
                        dest="generate_docstrings", action="store_true",
60✔
128
                        help="include docstrings containing C prototype and source file location",
60✔
129
                        default=False)
60✔
130
    parser.add_argument("--debug",
60✔
131
                        action="store_const",
60✔
132
                        const=True,
60✔
133
                        help='setLevel to DEBUG')
60✔
134
    parser.add_argument("-e", "--show-definition-location",
60✔
135
                        dest="generate_locations",
60✔
136
                        action="store_true",
60✔
137
                        help="include source file location in comments",
60✔
138
                        default=False)
60✔
139
    parser.add_argument("-k", "--kind",
60✔
140
                        action="store",
60✔
141
                        dest="kind", help="kind of type descriptions to include: "
60✔
142
                                          "a = Alias,\n"
×
143
                                          "c = Class,\n"
×
144
                                          "d = Variable,\n"
×
145
                                          "e = Enumeration,\n"
×
146
                                          "f = Function,\n"
×
147
                                          "m = Macro, #define\n"
×
148
                                          "s = Structure,\n"
×
149
                                          "t = Typedef,\n"
×
150
                                          "u = Union\n"
×
151
                                          "default = 'cdefstu'\n",
×
152
                        metavar="TYPEKIND",
60✔
153
                        default="cdefstu",
60✔
154
                        type=_is_typedesc)
60✔
155

156
    parser.add_argument("-i", "--includes",
60✔
157
                        dest="generate_includes",
60✔
158
                        action="store_true",
60✔
159
                        help="include declaration defined outside of the sourcefiles",
60✔
160
                        default=False)
60✔
161

162
    parser.add_argument("-l", "--include-library",
60✔
163
                        dest="dll",
60✔
164
                        help="library to search for exported functions. Add multiple times if required",
60✔
165
                        action="append",
60✔
166
                        default=[])
60✔
167

168
    if os.name in ("ce", "nt"):
60✔
169
        default_modules = ["ctypes.wintypes"]
×
170
    else:
×
171
        default_modules = []  # ctypes is already imported
60✔
172

173
    parser.add_argument("-m", "--module",
60✔
174
                        dest="modules",
60✔
175
                        metavar="module",
60✔
176
                        help="Python module(s) containing symbols which will "
60✔
177
                             "be imported instead of generated",
×
178
                        action="append",
60✔
179
                        default=default_modules)
60✔
180

181
    parser.add_argument("--nm",
60✔
182
                        dest="nm",
60✔
183
                        default="nm",
60✔
184
                        help="nm program to use to extract symbols from libraries")
60✔
185

186
    parser.add_argument("-o", "--output",
60✔
187
                        dest="output",
60✔
188
                        help="output filename (if not specified, standard output will be used)",
60✔
189
                        default="-", )
60✔
190
    # type=argparse.FileType('w'))
191

192
    parser.add_argument("-p", "--preload",
60✔
193
                        dest="preload",
60✔
194
                        metavar="DLL",
60✔
195
                        help="dll to be loaded before all others (to resolve symbols)",
60✔
196
                        action="append",
60✔
197
                        default=[])
60✔
198

199
    parser.add_argument("-q", "--quiet",
60✔
200
                        action="store_const",
60✔
201
                        const="quiet",
60✔
202
                        help="Shut down warnings and below",
60✔
203
                        default=False)
60✔
204

205
    parser.add_argument("-r", "--regex",
60✔
206
                        dest="expressions",
60✔
207
                        metavar="EXPRESSION",
60✔
208
                        action="append",
60✔
209
                        help="regular expression for symbols to include "
60✔
210
                             "(if neither symbols nor expressions are specified,"
×
211
                             "everything will be included)",
×
212
                        default=[])
60✔
213

214
    parser.add_argument("-s", "--symbol",
60✔
215
                        dest="symbols",
60✔
216
                        metavar="SYMBOL",
60✔
217
                        action="append",
60✔
218
                        help="symbol to include "
60✔
219
                             "(if neither symbols nor expressions are specified,"
×
220
                             "everything will be included)",
×
221
                        default=[])
60✔
222

223
    parser.add_argument("-t", "--target",
60✔
224
                        dest="target",
60✔
225
                        help="target architecture (default: %s)" % cfg.local_platform_triple,
60✔
226
                        default=None)  # actually let clang alone decide.
60✔
227

228
    parser.add_argument("-v", "--verbose",
60✔
229
                        action="store_true",
60✔
230
                        dest="verbose",
60✔
231
                        help="verbose output",
60✔
232
                        default=False)
60✔
233
    parser.add_argument('-V', '--version',
60✔
234
                        action='version',
60✔
235
                        version="versions - %(prog)s:" + "%s clang:%s python-clang:%s" % (cfg.version, clang_version(),
60✔
236
                                                                                          clang_py_version()))
60✔
237

238
    parser.add_argument("-w",
60✔
239
                        action="store",
60✔
240
                        default=windows_dlls,
60✔
241
                        help="add all standard windows dlls to the searched dlls list")
60✔
242

243
    parser.add_argument("-x", "--exclude-includes",
60✔
244
                        action="store_true",
60✔
245
                        default=False,
60✔
246
                        help="Parse object in sources files only. Ignore includes")
60✔
247

248
    parser.add_argument("--show-ids", dest="showIDs",
60✔
249
                        help="Don't compute cursor IDs (very slow)",
60✔
250
                        default=False)
60✔
251

252
    parser.add_argument("--max-depth", dest="maxDepth",
60✔
253
                        help="Limit cursor expansion to depth N",
60✔
254
                        metavar="N",
60✔
255
                        type=int,
60✔
256
                        default=None)
60✔
257

258
    parser.add_argument("--validate", dest="validate",
60✔
259
                        help="validate the python code is correct",
60✔
260
                        type=bool,
60✔
261
                        default=True)
60✔
262

263
    # FIXME recognize - as stdin
264
    # we do NOT support stdin
265
    parser.add_argument("files", nargs="+",
60✔
266
                        help="source filenames. stdin is not supported",
60✔
267
                        type=argparse.FileType('r'))
60✔
268

269
    parser.add_argument("--clang-args",
60✔
270
                        action="store",
60✔
271
                        default=None,
60✔
272
                        required=False,
60✔
273
                        help="clang options, in quotes: --clang-args=\"-std=c99 -Wall\"",
60✔
274
                        type=str)
60✔
275

276
    parser.epilog = """Cross-architecture: You can pass target modifiers to clang.
48✔
277
    For example, try --clang-args="-target x86_64" or "-target i386-linux" to change the target CPU arch."""
12✔
278

279
    options = parser.parse_args(argv)
60✔
280

281
    # cfg is the CodegenConfig, not the runtime config.
282
    level = logging.INFO
60✔
283
    if options.debug:
60✔
284
        level = logging.DEBUG
×
285
    elif options.quiet:
60✔
286
        level = logging.ERROR
×
287
    logging.basicConfig(level=level, stream=sys.stderr)
60✔
288

289
    # capture codegen options in config
290
    cfg.parse_options(options)
60✔
291

292
    # handle input files, and outputs
293
    from ctypeslib.codegen.handler import InvalidTranslationUnitException
60✔
294
    try:
60✔
295
        with Input(options) as inputs, Output(options) as outputs:
60✔
296
            # start codegen
297
            if cfg.generate_comments:
60✔
298
                outputs.stream.write("# generated by 'clang2py'\n")
×
299
                outputs.stream.write("# flags '%s'\n" % " ".join(argv[1:]))
×
300

301
            # Preload libraries
302
            # [Library(name, mode=RTLD_GLOBAL) for name in options.preload]
303

304
            translate_files(inputs.files, outputs.stream, cfg)
60✔
305
    except InvalidTranslationUnitException:
×
306
        return 1
×
307
    return 0
60✔
308

309

310
if __name__ == "__main__":
60✔
311
    try:
×
312
        sys.exit(main(sys.argv[1:]))
×
313
    except Exception:
×
314
        # return non-zero exit status in case of an unhandled exception
315
        traceback.print_exc()
×
316
        sys.exit(1)
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc