cython

Форк
0
/
Shadow.py 
611 строк · 16.9 Кб
1
# cython.* namespace for pure mode.
2

3
# Possible version formats: "3.1.0", "3.1.0a1", "3.1.0a1.dev0"
4
__version__ = "3.1.0a0"
5

6

7
# BEGIN shameless copy from Cython/minivect/minitypes.py
8

9
class _ArrayType:
10

11
    is_array = True
12
    subtypes = ['dtype']
13

14
    def __init__(self, dtype, ndim, is_c_contig=False, is_f_contig=False,
15
                 inner_contig=False, broadcasting=None):
16
        self.dtype = dtype
17
        self.ndim = ndim
18
        self.is_c_contig = is_c_contig
19
        self.is_f_contig = is_f_contig
20
        self.inner_contig = inner_contig or is_c_contig or is_f_contig
21
        self.broadcasting = broadcasting
22

23
    def __repr__(self):
24
        axes = [":"] * self.ndim
25
        if self.is_c_contig:
26
            axes[-1] = "::1"
27
        elif self.is_f_contig:
28
            axes[0] = "::1"
29

30
        return "%s[%s]" % (self.dtype, ", ".join(axes))
31

32

33
def index_type(base_type, item):
34
    """
35
    Support array type creation by slicing, e.g. double[:, :] specifies
36
    a 2D strided array of doubles. The syntax is the same as for
37
    Cython memoryviews.
38
    """
39
    class InvalidTypeSpecification(Exception):
40
        pass
41

42
    def verify_slice(s):
43
        if s.start or s.stop or s.step not in (None, 1):
44
            raise InvalidTypeSpecification(
45
                "Only a step of 1 may be provided to indicate C or "
46
                "Fortran contiguity")
47

48
    if isinstance(item, tuple):
49
        step_idx = None
50
        for idx, s in enumerate(item):
51
            verify_slice(s)
52
            if s.step and (step_idx or idx not in (0, len(item) - 1)):
53
                raise InvalidTypeSpecification(
54
                    "Step may only be provided once, and only in the "
55
                    "first or last dimension.")
56

57
            if s.step == 1:
58
                step_idx = idx
59

60
        return _ArrayType(base_type, len(item),
61
                          is_c_contig=step_idx == len(item) - 1,
62
                          is_f_contig=step_idx == 0)
63
    elif isinstance(item, slice):
64
        verify_slice(item)
65
        return _ArrayType(base_type, 1, is_c_contig=bool(item.step))
66
    else:
67
        # int[8] etc.
68
        assert int(item) == item  # array size must be a plain integer
69
        return array(base_type, item)
70

71
# END shameless copy
72

73

74
compiled = False
75

76
_Unspecified = object()
77

78
# Function decorators
79

80
def _empty_decorator(x):
81
    return x
82

83
def locals(**arg_types):
84
    return _empty_decorator
85

86
def test_assert_path_exists(*paths):
87
    return _empty_decorator
88

89
def test_fail_if_path_exists(*paths):
90
    return _empty_decorator
91

92
class _EmptyDecoratorAndManager:
93
    def __call__(self, x):
94
        return x
95
    def __enter__(self):
96
        pass
97
    def __exit__(self, exc_type, exc_value, traceback):
98
        pass
99

100
class _Optimization:
101
    pass
102

103
cclass = ccall = cfunc = _EmptyDecoratorAndManager()
104

105
annotation_typing = returns = wraparound = boundscheck = initializedcheck = \
106
    nonecheck = embedsignature = cdivision = cdivision_warnings = \
107
    always_allow_keywords = profile = linetrace = infer_types = \
108
    unraisable_tracebacks = freelist = auto_pickle = cpow = trashcan = \
109
    auto_cpdef = c_api_binop_methods = \
110
    allow_none_for_extension_args = callspec = show_performance_hints = \
111
    cpp_locals = py2_import = iterable_coroutine = remove_unreachable = \
112
        lambda _: _EmptyDecoratorAndManager()
113

114
# Note that fast_getattr is untested and undocumented!
115
fast_getattr = lambda _: _EmptyDecoratorAndManager()
116

117
exceptval = lambda _=None, check=True: _EmptyDecoratorAndManager()
118

119
overflowcheck = lambda _: _EmptyDecoratorAndManager()
120
optimize = _Optimization()
121

122

123
embedsignature.format = overflowcheck.fold = optimize.use_switch = \
124
    optimize.unpack_method_calls = lambda arg: _EmptyDecoratorAndManager()
125

126
final = internal = type_version_tag = no_gc_clear = no_gc = total_ordering = \
127
    ufunc = _empty_decorator
128

129
binding = lambda _: _empty_decorator
130

131
class warn:
132
    undeclared = unreachable = maybe_uninitialized = unused = \
133
        unused_arg = unused_result = \
134
            lambda _: _EmptyDecoratorAndManager()
135

136

137
_cython_inline = None
138
def inline(f, *args, **kwds):
139
    if isinstance(f, str):
140
        global _cython_inline
141
        if _cython_inline is None:
142
            from Cython.Build.Inline import cython_inline as _cython_inline
143
        return _cython_inline(f, *args, **kwds)
144
    else:
145
        assert len(args) == len(kwds) == 0
146
        return f
147

148

149
def compile(f):
150
    from Cython.Build.Inline import RuntimeCompiledFunction
151
    return RuntimeCompiledFunction(f)
152

153

154
# Special functions
155

156
def cdiv(a, b):
157
    if a < 0:
158
        a = -a
159
        b = -b
160
    if b < 0:
161
        return (a + b + 1) // b
162
    return a // b
163

164
def cmod(a, b):
165
    r = a % b
166
    if (a * b) < 0 and r:
167
        r -= b
168
    return r
169

170

171
# Emulated language constructs
172

173
def cast(t, *args, **kwargs):
174
    kwargs.pop('typecheck', None)
175
    assert not kwargs
176

177
    if isinstance(t, typedef):
178
        return t(*args)
179
    elif isinstance(t, type):  # Doesn't work with old-style classes of Python 2.x
180
        if len(args) != 1 or not (args[0] is None or isinstance(args[0], t)):
181
            return t(*args)
182

183
    return args[0]
184

185
def sizeof(arg):
186
    return 1
187

188
def typeof(arg):
189
    return arg.__class__.__name__
190
    # return type(arg)
191

192
def address(arg):
193
    return pointer(type(arg))([arg])
194

195
def _is_value_type(t):
196
    if isinstance(t, typedef):
197
        return _is_value_type(t._basetype)
198

199
    return isinstance(t, type) and issubclass(t, (StructType, UnionType, ArrayType))
200

201
def declare(t=None, value=_Unspecified, **kwds):
202
    if value is not _Unspecified:
203
        return cast(t, value)
204
    elif _is_value_type(t):
205
        return t()
206
    else:
207
        return None
208

209
class _nogil:
210
    """Support for 'with nogil' statement and @nogil decorator.
211
    """
212
    def __call__(self, x):
213
        if callable(x):
214
            # Used as function decorator => return the function unchanged.
215
            return x
216
        # Used as conditional context manager or to create an "@nogil(True/False)" decorator => keep going.
217
        return self
218

219
    def __enter__(self):
220
        pass
221
    def __exit__(self, exc_class, exc, tb):
222
        return exc_class is None
223

224
nogil = _nogil()
225
gil = _nogil()
226
with_gil = _nogil()  # Actually not a context manager, but compilation will give the right error.
227
del _nogil
228

229

230
# Emulated types
231

232
class CythonMetaType(type):
233

234
    def __getitem__(type, ix):
235
        return array(type, ix)
236

237
CythonTypeObject = CythonMetaType('CythonTypeObject', (object,), {})
238

239
class CythonType(CythonTypeObject):
240

241
    def _pointer(self, n=1):
242
        for i in range(n):
243
            self = pointer(self)
244
        return self
245

246
class PointerType(CythonType):
247

248
    def __init__(self, value=None):
249
        if isinstance(value, (ArrayType, PointerType)):
250
            self._items = [cast(self._basetype, a) for a in value._items]
251
        elif isinstance(value, list):
252
            self._items = [cast(self._basetype, a) for a in value]
253
        elif value is None or value == 0:
254
            self._items = []
255
        else:
256
            raise ValueError
257

258
    def __getitem__(self, ix):
259
        if ix < 0:
260
            raise IndexError("negative indexing not allowed in C")
261
        return self._items[ix]
262

263
    def __setitem__(self, ix, value):
264
        if ix < 0:
265
            raise IndexError("negative indexing not allowed in C")
266
        self._items[ix] = cast(self._basetype, value)
267

268
    def __eq__(self, value):
269
        if value is None and not self._items:
270
            return True
271
        elif type(self) != type(value):
272
            return False
273
        else:
274
            return not self._items and not value._items
275

276
    def __repr__(self):
277
        return "%s *" % (self._basetype,)
278

279
class ArrayType(PointerType):
280

281
    def __init__(self, value=None):
282
        if value is None:
283
            self._items = [None] * self._n
284
        else:
285
            super().__init__(value)
286

287

288
class StructType(CythonType):
289

290
    def __init__(self, *posargs, **data):
291
        if not (posargs or data):
292
            return
293
        if posargs and data:
294
            raise ValueError('Cannot accept both positional and keyword arguments.')
295

296
        # Allow 'cast_from' as single positional or keyword argument.
297
        if data and len(data) == 1 and 'cast_from' in data:
298
            cast_from = data.pop('cast_from')
299
        elif len(posargs) == 1 and type(posargs[0]) is type(self):
300
            cast_from, posargs = posargs[0], ()
301
        elif posargs:
302
            for key, arg in zip(self._members, posargs):
303
                setattr(self, key, arg)
304
            return
305
        else:
306
            for key, value in data.items():
307
                if key not in self._members:
308
                    raise ValueError("Invalid struct attribute for %s: %s" % (
309
                        self.__class__.__name__, key))
310
                setattr(self, key, value)
311
            return
312

313
        # do cast
314
        if data:
315
            raise ValueError('Cannot accept keyword arguments when casting.')
316
        if type(cast_from) is not type(self):
317
            raise ValueError('Cannot cast from %s' % cast_from)
318
        for key, value in cast_from.__dict__.items():
319
            setattr(self, key, value)
320

321
    def __setattr__(self, key, value):
322
        if key in self._members:
323
            self.__dict__[key] = cast(self._members[key], value)
324
        else:
325
            raise AttributeError("Struct has no member '%s'" % key)
326

327

328
class UnionType(CythonType):
329

330
    def __init__(self, cast_from=_Unspecified, **data):
331
        if cast_from is not _Unspecified:
332
            # do type cast
333
            if len(data) > 0:
334
                raise ValueError('Cannot accept keyword arguments when casting.')
335
            if isinstance(cast_from, dict):
336
                datadict = cast_from
337
            elif type(cast_from) is type(self):
338
                datadict = cast_from.__dict__
339
            else:
340
                raise ValueError('Cannot cast from %s' % cast_from)
341
        else:
342
            datadict = data
343
        if len(datadict) > 1:
344
            raise AttributeError("Union can only store one field at a time.")
345
        for key, value in datadict.items():
346
            setattr(self, key, value)
347

348
    def __setattr__(self, key, value):
349
        if key == '__dict__':
350
            CythonType.__setattr__(self, key, value)
351
        elif key in self._members:
352
            self.__dict__ = {key: cast(self._members[key], value)}
353
        else:
354
            raise AttributeError("Union has no member '%s'" % key)
355

356
def pointer(basetype):
357
    class PointerInstance(PointerType):
358
        _basetype = basetype
359
    return PointerInstance
360

361
def array(basetype, n):
362
    class ArrayInstance(ArrayType):
363
        _basetype = basetype
364
        _n = n
365
    return ArrayInstance
366

367
def struct(**members):
368
    class StructInstance(StructType):
369
        _members = members
370
    for key in members:
371
        setattr(StructInstance, key, None)
372
    return StructInstance
373

374
def union(**members):
375
    class UnionInstance(UnionType):
376
        _members = members
377
    for key in members:
378
        setattr(UnionInstance, key, None)
379
    return UnionInstance
380

381
class typedef(CythonType):
382

383
    def __init__(self, type, name=None):
384
        self._basetype = type
385
        self.name = name
386

387
    def __call__(self, *arg):
388
        value = cast(self._basetype, *arg)
389
        return value
390

391
    def __repr__(self):
392
        return self.name or str(self._basetype)
393

394
    __getitem__ = index_type
395

396
class _FusedType(CythonType):
397
    __getitem__ = index_type
398

399

400
def fused_type(*args):
401
    if not args:
402
        raise TypeError("Expected at least one type as argument")
403

404
    # Find the numeric type with biggest rank if all types are numeric
405
    rank = -1
406
    for type in args:
407
        if type not in (py_int, py_long, py_float, py_complex):
408
            break
409

410
        if type_ordering.index(type) > rank:
411
            result_type = type
412
    else:
413
        return result_type
414

415
    # Not a simple numeric type, return a fused type instance. The result
416
    # isn't really meant to be used, as we can't keep track of the context in
417
    # pure-mode. Casting won't do anything in this case.
418
    return _FusedType()
419

420

421
def _specialized_from_args(signatures, args, kwargs):
422
    "Perhaps this should be implemented in a TreeFragment in Cython code"
423
    raise Exception("yet to be implemented")
424

425

426
py_int = typedef(int, "int")
427
py_long = typedef(int, "long")  # for legacy Py2 code only
428
py_float = typedef(float, "float")
429
py_complex = typedef(complex, "double complex")
430

431

432
# Predefined types
433

434
int_types = [
435
    'char',
436
    'short',
437
    'Py_UNICODE',
438
    'int',
439
    'Py_UCS4',
440
    'long',
441
    'longlong',
442
    'Py_hash_t',
443
    'Py_ssize_t',
444
    'size_t',
445
    'ssize_t',
446
    'ptrdiff_t',
447
]
448
float_types = [
449
    'longdouble',
450
    'double',
451
    'float',
452
]
453
complex_types = [
454
    'longdoublecomplex',
455
    'doublecomplex',
456
    'floatcomplex',
457
    'complex',
458
]
459
other_types = [
460
    'bint',
461
    'void',
462
    'Py_tss_t',
463
]
464

465
to_repr = {
466
    'longlong': 'long long',
467
    'longdouble': 'long double',
468
    'longdoublecomplex': 'long double complex',
469
    'doublecomplex': 'double complex',
470
    'floatcomplex': 'float complex',
471
}.get
472

473
gs = globals()
474

475
gs['unicode'] = typedef(str, 'unicode')
476

477
for name in int_types:
478
    reprname = to_repr(name, name)
479
    gs[name] = typedef(py_int, reprname)
480
    if name not in ('Py_UNICODE', 'Py_UCS4', 'Py_hash_t', 'ptrdiff_t') and not name.endswith('size_t'):
481
        gs['u'+name] = typedef(py_int, "unsigned " + reprname)
482
        gs['s'+name] = typedef(py_int, "signed " + reprname)
483

484
for name in float_types:
485
    gs[name] = typedef(py_float, to_repr(name, name))
486

487
for name in complex_types:
488
    gs[name] = typedef(py_complex, to_repr(name, name))
489

490
del name, reprname
491

492
bint = typedef(bool, "bint")
493
void = typedef(None, "void")
494
Py_tss_t = typedef(None, "Py_tss_t")
495

496
for t in int_types:
497
    for i in range(1, 4):
498
        gs["%s_%s" % ('p'*i, t)] = gs[t]._pointer(i)
499
        if 'u'+t in gs:
500
            gs["%s_u%s" % ('p'*i, t)] = gs['u'+t]._pointer(i)
501
            gs["%s_s%s" % ('p'*i, t)] = gs['s'+t]._pointer(i)
502

503
for t in float_types + complex_types + other_types:
504
    for i in range(1, 4):
505
        gs["%s_%s" % ('p'*i, t)] = gs[t]._pointer(i)
506

507
del t, i
508

509
NULL = gs['p_void'](0)
510

511
del gs
512

513

514
def __getattr__(name):
515
    # looks like 'gs' has some users out there by now...
516
    if name == 'gs':
517
        import warnings
518
        warnings.warn(
519
            "'gs' is not a publicly exposed name in cython.*. Use vars() or globals() instead.",
520
            DeprecationWarning)
521
        return globals()
522
    raise AttributeError(f"'cython' has no attribute {name!r}")
523

524

525
integral = floating = numeric = _FusedType()
526

527
type_ordering = [py_int, py_long, py_float, py_complex]
528

529
class CythonDotParallel:
530
    """
531
    The cython.parallel module.
532
    """
533

534
    __all__ = ['parallel', 'prange', 'threadid']
535

536
    def parallel(self, num_threads=None):
537
        return nogil
538

539
    def prange(self, start=0, stop=None, step=1, nogil=False, schedule=None, chunksize=None, num_threads=None):
540
        if stop is None:
541
            stop = start
542
            start = 0
543
        return range(start, stop, step)
544

545
    def threadid(self):
546
        return 0
547

548
    # def threadsavailable(self):
549
        # return 1
550

551
class CythonDotImportedFromElsewhere:
552
    """
553
    cython.dataclasses just shadows the standard library modules of the same name
554
    """
555
    def __init__(self, module):
556
        self.__path__ = []
557
        self.__file__ = None
558
        self.__name__ = module
559
        self.__package__ = module
560

561
    def __getattr__(self, attr):
562
        # we typically only expect this to be called once
563
        from importlib import import_module
564
        import sys
565
        try:
566
            mod = import_module(self.__name__)
567
        except ImportError:
568
            # but if they don't exist (Python is not sufficiently up-to-date) then
569
            # you can't use them
570
            raise AttributeError("%s: the standard library module %s is not available" %
571
                                 (attr, self.__name__))
572
        sys.modules['cython.%s' % self.__name__] = mod
573
        return getattr(mod, attr)
574

575
class CythonCImports:
576
    """
577
    Simplistic module mock to make cimports sort-of work in Python code.
578
    """
579
    def __init__(self, module, **attributes):
580
        self.__path__ = []
581
        self.__file__ = None
582
        self.__name__ = module
583
        self.__package__ = module
584
        if attributes:
585
            self.__dict__.update(attributes)
586

587
    def __getattr__(self, item):
588
        if item.startswith('__') and item.endswith('__'):
589
            raise AttributeError(item)
590

591
        package = self.__package__[len('cython.cimports.'):]
592

593
        from importlib import import_module
594
        try:
595
            return import_module(item, package or None)
596
        except ImportError:
597
            ex = AttributeError(item)
598
            ex.__cause__ = None
599
            raise ex
600

601

602
import math, sys
603
sys.modules['cython.parallel'] = CythonDotParallel()
604
sys.modules['cython.cimports.libc.math'] = math
605
sys.modules['cython.cimports.libc'] = CythonCImports('cython.cimports.libc', math=math)
606
sys.modules['cython.cimports'] = CythonCImports('cython.cimports', libc=sys.modules['cython.cimports.libc'])
607

608
# In pure Python mode @cython.dataclasses.dataclass and dataclass field should just
609
# shadow the standard library ones (if they are available)
610
dataclasses = sys.modules['cython.dataclasses'] = CythonDotImportedFromElsewhere('dataclasses')
611
del math, sys
612

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.