1cdef struct Point:
2    double x
3    double y
4    int color
5
6def test_constructor(x, y, int color):
7    """
8    >>> sorted(test_constructor(1,2,255).items())
9    [('color', 255), ('x', 1.0), ('y', 2.0)]
10    >>> try: test_constructor(1,None,255)
11    ... except TypeError: pass
12    """
13    cdef Point p = Point(x, y, color)
14    return p
15
16
17def return_constructor(x, y, int color):
18    """
19    >>> sorted(return_constructor(1,2,255).items())
20    [('color', 255), ('x', 1.0), ('y', 2.0)]
21    >>> try: return_constructor(1, None, 255)
22    ... except TypeError: pass
23    """
24    return Point(x, y, color)
25
26
27def test_constructor_kwds(x, y, color):
28    """
29    >>> sorted(test_constructor_kwds(1.25, 2.5, 128).items())
30    [('color', 128), ('x', 1.25), ('y', 2.5)]
31    >>> test_constructor_kwds(1.25, 2.5, None)  # doctest: +ELLIPSIS
32    Traceback (most recent call last):
33    TypeError:... int...
34    """
35    cdef Point p = Point(x=x, y=y, color=color)
36    return p
37
38
39def return_constructor_kwds(double x, y, color):
40    """
41    >>> sorted(return_constructor_kwds(1.25, 2.5, 128).items())
42    [('color', 128), ('x', 1.25), ('y', 2.5)]
43    >>> return_constructor_kwds(1.25, 2.5, None)  # doctest: +ELLIPSIS
44    Traceback (most recent call last):
45    TypeError:... int...
46    """
47    return Point(x=x, y=y, color=color)
48
49
50def test_dict_construction(x, y, color):
51    """
52    >>> sorted(test_dict_construction(4, 5, 64).items())
53    [('color', 64), ('x', 4.0), ('y', 5.0)]
54    >>> try: test_dict_construction("foo", 5, 64)
55    ... except TypeError: pass
56    """
57    cdef Point p = {'color': color, 'x': x, 'y': y}
58    return p
59
60def test_list_construction(x, y, color):
61    """
62    >>> sorted(test_list_construction(4, 5, 64).items())
63    [('color', 64), ('x', 4.0), ('y', 5.0)]
64    >>> try: test_list_construction("foo", 5, 64)
65    ... except TypeError: pass
66    """
67    cdef Point p = [x, y, color]
68    return p
69
70'''
71# FIXME: make this work
72def test_tuple_construction(x, y, color):
73    """
74    >>> sorted(test_tuple_construction(4, 5, 64).items())
75    [('color', 64), ('x', 4.0), ('y', 5.0)]
76    >>> try: test_tuple_construction("foo", 5, 64)
77    ... except TypeError: pass
78    """
79    cdef Point p = (x, y, color)
80    return p
81'''
82
83cdef union int_or_float:
84    int n
85    double x
86
87def test_union_constructor(n,x):
88    """
89    >>> test_union_constructor(1, None)
90    1
91    >>> test_union_constructor(None, 2.0)
92    2.0
93    """
94    cdef int_or_float u
95    if n is None:
96        u = int_or_float(x=x)
97        return u.x
98    else:
99        u = int_or_float(n=n)
100        return u.n
101
102cdef struct with_pointers:
103    bint is_integral
104    int_or_float data
105    void* ptr
106
107def test_pointers(int n, double x):
108    """
109    >>> test_pointers(100, 2.71828)
110    100
111    2.71828
112    True
113    """
114    cdef with_pointers a = [True, {'n': n}, NULL]
115    cdef with_pointers b = with_pointers(False, {'x': x}, NULL)
116    print a.data.n
117    print b.data.x
118    print a.ptr == b.ptr == NULL
119
120cdef struct MyStruct:
121    char c
122    int i
123    float f
124    char *s
125
126bhello = b"hello"  # must hold a C reference in PyPy
127
128def test_obj_to_struct(MyStruct mystruct):
129    """
130    >>> test_obj_to_struct(dict(c=10, i=20, f=6.7, s=bhello))
131    c=10 i=20 f=6.70 s=hello
132    >>> test_obj_to_struct(None)
133    Traceback (most recent call last):
134       ...
135    TypeError: Expected a mapping, got NoneType
136    >>> test_obj_to_struct(dict(s=b"world"))
137    Traceback (most recent call last):
138       ...
139    ValueError: No value specified for struct attribute 'c'
140    >>> test_obj_to_struct(dict(c=b"world"))
141    Traceback (most recent call last):
142       ...
143    TypeError: an integer is required
144    """
145    print 'c=%d i=%d f=%.2f s=%s' % (mystruct.c, mystruct.i, mystruct.f, mystruct.s.decode('ascii'))
146
147cdef struct NestedStruct:
148    MyStruct mystruct
149    double d
150
151def test_nested_obj_to_struct(NestedStruct nested):
152    """
153    >>> test_nested_obj_to_struct(dict(mystruct=dict(c=10, i=20, f=6.7, s=bhello), d=4.5))
154    c=10 i=20 f=6.70 s=hello d=4.50
155    >>> test_nested_obj_to_struct(dict(d=7.6))
156    Traceback (most recent call last):
157       ...
158    ValueError: No value specified for struct attribute 'mystruct'
159    >>> test_nested_obj_to_struct(dict(mystruct={}, d=7.6))
160    Traceback (most recent call last):
161       ...
162    ValueError: No value specified for struct attribute 'c'
163    """
164    print 'c=%d i=%d f=%.2f s=%s d=%.2f' % (nested.mystruct.c,
165                                            nested.mystruct.i,
166                                            nested.mystruct.f,
167                                            nested.mystruct.s.decode('UTF-8'),
168                                            nested.d)
169
170cdef struct OverriddenCname:
171    int x "not_x"
172
173def test_obj_to_struct_cnames(OverriddenCname s):
174    """
175    >>> test_obj_to_struct_cnames({ 'x': 1 })
176    1
177    """
178    print(s.x)
179
180def test_struct_to_obj_cnames():
181    """
182    >>> test_struct_to_obj_cnames()
183    {'x': 2}
184    """
185    return OverriddenCname(2)
186