summaryrefslogtreecommitdiff
path: root/tests/run/unicode_identifiers.pyx
blob: 767e3283eb3c1be1695582516b1ee5536bcbec71 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# -*- coding: utf-8 -*-
# mode: run
# tag: pep3131, traceback

# cython: language_level=3

# Code with unicode identifiers can be compiled with Cython running either Python 2 or 3.
# However Python access to unicode identifiers is only possible in Python 3. In Python 2
# it's only really safe to use the unicode identifiers for purely Cython interfaces
# (although this isn't enforced...). Therefore the majority of the doctests are
# Python3 only and only a limited set are run in Python2.
# This is controlled by putting the Python3 only tests in the module __doc__ attribute
# Most of the individual function and class docstrings are only present as a compile test

cimport cython

import sys


if sys.version_info[0] > 2:
    __doc__ = u"""
    >>> f()()
    2
    >>> f().__name__
    'nεsted'

    The test is mainly to see if the traceback is generated correctly
    >>> print_traceback_name()
    unicode_identifiers.Fα1

    Just check that a cpdef function is callable
    >>> Fα3()
    1

    >>> Γναμε2.ναμε3
    1
    >>> x = Γναμε2()
    >>> print(x.α)
    100
    >>> x.α = 200
    >>> print(x.α)
    200

    >>> B().Ƒ()
    >>> C().Ƒ()

    Test generation of locals()
    >>> sorted(Γναμε2().boring_function(1,2).keys())
    ['self', 'somevalue', 'x', 'ναμε5', 'ναμε6']

    >>> Γναμε2().boring_cpdef() - Γναμε2().εxciting_cpdef()
    0
    >>> function_taking_fancy_argument(Γναμε2()).ναμε3
    1
    >>> metho_function_taking_fancy_argument(Γναμε2()).ναμε3
    1
    >>> NormalClassΓΓ().ναμε
    10
    >>> NormalClassΓΓ().εxciting_function(None).__qualname__
    'NormalClassΓΓ.εxciting_function.<locals>.nestεd'

    Do kwargs work?
    >>> unicode_kwarg(αrγ=5)
    5
    >>> unicode_kwarg_from_cy()
    1

    Normalization of attributes
    (The cdef class version is testable in Python 2 too)
    >>> NormalizeAttrPy().get()
    5
    """
else:
    __doc__ = ""

global_ναμε1 = None
cdef double global_ναμε2 = 1.2

def f():
    """docstring"""
    ναμε2 = 2
    def nεsted():
        return ναμε2
    return nεsted

# Ƒ is notably awkward because its punycode starts with "2" causing
# C compile errors. Therefore try a few different variations...
cdef class A:
    cdef int ναμε
    def __init__(self):
        self.ναμε = 1
    cdef Ƒ(self):
        return self.ναμε == 1
    def regular_function(self):
        """
        Can use unicode cdef functions and (private) attributes internally
        >>> A().regular_function()
        True
        """
        return self.Ƒ()
cdef class B:
    cpdef Ƒ(self):
        pass
cdef class C:
    def Ƒ(self):
        pass
cdef class D:
    cdef int Ƒ

def regular_function():
    """
    Unicode names can be used internally on python2
    >>> regular_function()
    10
    """
    cdef int variableƑ = 5
    ναμε2 = 2
    return variableƑ*ναμε2

cdef Fα1():
    """docstring"""
    ναμε2 = 2
    raise RuntimeError() # forces generation of a traceback

def print_traceback_name():
    try:
        Fα1()
    except RuntimeError as e:
        import traceback
        # get the name of one level up in the traceback
        print(traceback.extract_tb(e.__traceback__,2)[1][2])


def Fα2():
    """docstring"""
    def nested_normal():
        """docstring"""
        pass
    def nεstεd_uni():
        """docstring"""
        pass
    return nested_normal, nεstεd_uni

cpdef Fα3():
    """docstring"""
    return 1

cdef class Γναμε2:
    """
    docstring
    """
    ναμε3 = 1

    def __init__(self):
        self.α = 100
    def boring_function(self,x,ναμε5):
        """docstring"""
        ναμε6 = ναμε5
        somevalue = global_ναμε1 == self.ναμε3
        return locals()
    def εxciting_function(self,y):
        """docstring"""
        def nestεd():
            pass
        return nestεd

    cdef boring_cdef(self):
        """docstring"""
        pass
    cdef εxciting_cdef(self):
        """docstring"""
        pass

    cpdef boring_cpdef(self):
        """docstring"""
        return 2
    cpdef εxciting_cpdef(self):
        """docstring"""
        return 2

cdef class Derived(Γναμε2):
    pass

cdef Γναμε2 global_ναμε3 = Γναμε2()


@cython.always_allow_keywords(False)  # METH_O signature
def metho_function_taking_fancy_argument(Γναμε2 αrγ):
    return αrγ

@cython.always_allow_keywords(True)
def function_taking_fancy_argument(Γναμε2 αrγ):
    return αrγ


class NormalClassΓΓ(Γναμε2):
    """
    docstring
    """
    def __init__(self):
        self.ναμε = 10

    def boring_function(self,x,ναμε5):
        """docstring"""
        ναμε6 = ναμε5
        somevalue = global_ναμε1 == self.ναμε3
        return locals()
    def εxciting_function(self,y):
        """docstring"""
        def nestεd():
            pass
        return nestεd

def unicode_kwarg(*, αrγ):
    return αrγ

def unicode_kwarg_from_cy():
    return unicode_kwarg(αrγ=1)

class NormalizeAttrPy:
    """Python normalizes identifier names before they are used;
    therefore fi and fi should access the same attribute"""
    def __init__(self):
        self.fi = 5 # note unicode ligature symbol
    def get(self):
        return self.fi

cdef class NormalizeAttrCdef:
    """Python normalizes identifier names before they are used;
    therefore fi and fi should access the same attribute
    >>> NormalizeAttrCdef().get()
    5
    """
    cdef int fi # note unicode ligature symbol
    def __init__(self):
        self.fi = 5
    def get(self):
        return self.fi

if sys.version_info[0]<=2:
    # These symbols are causing problems for doctest
    del NormalClassΓΓ
    del globals()[u'Γναμε2'.encode('utf-8')]