diff options
author | Alexander Kanavin <alex.kanavin@gmail.com> | 2022-10-05 11:39:49 +0200 |
---|---|---|
committer | Khem Raj <raj.khem@gmail.com> | 2022-10-05 08:24:50 -0700 |
commit | 7b2503f531820647419be004e6cc0b71335097d5 (patch) | |
tree | d65e84491f5aeeacd2752f90bc178860311395b9 /meta-python/recipes-devtools/python/python3-pybluez | |
parent | 8a4a47286ddcd4287b44d1815fcb199e483d88d2 (diff) | |
download | meta-openembedded-7b2503f531820647419be004e6cc0b71335097d5.tar.gz |
python3-pybluez: add python 3.11 patch
Signed-off-by: Alexander Kanavin <alex@linutronix.de>
Signed-off-by: Khem Raj <raj.khem@gmail.com>
Diffstat (limited to 'meta-python/recipes-devtools/python/python3-pybluez')
-rw-r--r-- | meta-python/recipes-devtools/python/python3-pybluez/py-3.11.patch | 454 |
1 files changed, 454 insertions, 0 deletions
diff --git a/meta-python/recipes-devtools/python/python3-pybluez/py-3.11.patch b/meta-python/recipes-devtools/python/python3-pybluez/py-3.11.patch new file mode 100644 index 000000000..af4869f73 --- /dev/null +++ b/meta-python/recipes-devtools/python/python3-pybluez/py-3.11.patch | |||
@@ -0,0 +1,454 @@ | |||
1 | From f83d38687fec2239c517037453ed4a2191279796 Mon Sep 17 00:00:00 2001 | ||
2 | From: Victor Stinner <vstinner@python.org> | ||
3 | Date: Fri, 28 Jan 2022 00:14:04 +0100 | ||
4 | Subject: [PATCH] Port to Python 3.11 (#410) | ||
5 | |||
6 | * Replace "arg == Py_None" with Py_IsNone(arg) | ||
7 | * Replace arg->ob_type with Py_TYPE(arg) | ||
8 | * Replace "Py_TYPE(obj) = type" with Py_SET_TYPE(obj, type). | ||
9 | * Copy pythoncapi_compat.h from: | ||
10 | https://github.com/pythoncapi/pythoncapi_compat | ||
11 | * pythoncapi_compat.h provides Py_SET_TYPE() and Py_IsNone() to old | ||
12 | Python versions. | ||
13 | |||
14 | Upstream-Status: Backport [https://github.com/pybluez/pybluez/commit/5096047f90a1f6a74ceb250aef6243e144170f92] | ||
15 | Signed-off-by: Alexander Kanavin <alex@linutronix.de> | ||
16 | --- | ||
17 | bluez/btmodule.c | 14 +- | ||
18 | bluez/pythoncapi_compat.h | 364 ++++++++++++++++++++++++++++++++++++++ | ||
19 | 2 files changed, 372 insertions(+), 6 deletions(-) | ||
20 | create mode 100644 bluez/pythoncapi_compat.h | ||
21 | |||
22 | diff --git a/bluez/btmodule.c b/bluez/btmodule.c | ||
23 | index 912a489..b61f74a 100644 | ||
24 | --- a/bluez/btmodule.c | ||
25 | +++ b/bluez/btmodule.c | ||
26 | @@ -21,6 +21,8 @@ Local naming conventions: | ||
27 | #include "btmodule.h" | ||
28 | #include "structmember.h" | ||
29 | |||
30 | +#include "pythoncapi_compat.h" | ||
31 | + | ||
32 | #include <stdio.h> | ||
33 | #include <unistd.h> | ||
34 | #include <stdlib.h> | ||
35 | @@ -678,7 +680,7 @@ sock_settimeout(PySocketSockObject *s, PyObject *arg) | ||
36 | { | ||
37 | double timeout; | ||
38 | |||
39 | - if (arg == Py_None) | ||
40 | + if (Py_IsNone(arg)) | ||
41 | timeout = -1.0; | ||
42 | else { | ||
43 | timeout = PyFloat_AsDouble(arg); | ||
44 | @@ -1752,7 +1754,7 @@ bt_btohl(PyObject *self, PyObject *args) | ||
45 | else | ||
46 | return PyErr_Format(PyExc_TypeError, | ||
47 | "expected int/long, %s found", | ||
48 | - arg->ob_type->tp_name); | ||
49 | + Py_TYPE(arg)->tp_name); | ||
50 | if (x == (unsigned long) -1 && PyErr_Occurred()) | ||
51 | return NULL; | ||
52 | return PyInt_FromLong(btohl(x)); | ||
53 | @@ -1816,7 +1818,7 @@ bt_htobl(PyObject *self, PyObject *args) | ||
54 | else | ||
55 | return PyErr_Format(PyExc_TypeError, | ||
56 | "expected int/long, %s found", | ||
57 | - arg->ob_type->tp_name); | ||
58 | + Py_TYPE(arg)->tp_name); | ||
59 | return PyInt_FromLong(htobl(x)); | ||
60 | } | ||
61 | |||
62 | @@ -1889,7 +1891,7 @@ bt_setdefaulttimeout(PyObject *self, PyObject *arg) | ||
63 | { | ||
64 | double timeout; | ||
65 | |||
66 | - if (arg == Py_None) | ||
67 | + if (Py_IsNone(arg)) | ||
68 | timeout = -1.0; | ||
69 | else { | ||
70 | timeout = PyFloat_AsDouble(arg); | ||
71 | @@ -2980,8 +2982,8 @@ PyMODINIT_FUNC | ||
72 | init_bluetooth(void) | ||
73 | #endif | ||
74 | { | ||
75 | - Py_TYPE(&sock_type) = &PyType_Type; | ||
76 | - Py_TYPE(&sdp_session_type) = &PyType_Type; | ||
77 | + Py_SET_TYPE(&sock_type, &PyType_Type); | ||
78 | + Py_SET_TYPE(&sdp_session_type, &PyType_Type); | ||
79 | #if PY_MAJOR_VERSION >= 3 | ||
80 | PyObject *m = PyModule_Create(&moduledef); | ||
81 | #else | ||
82 | diff --git a/bluez/pythoncapi_compat.h b/bluez/pythoncapi_compat.h | ||
83 | new file mode 100644 | ||
84 | index 0000000..e660b61 | ||
85 | --- /dev/null | ||
86 | +++ b/bluez/pythoncapi_compat.h | ||
87 | @@ -0,0 +1,364 @@ | ||
88 | +// Header file providing new functions of the Python C API to old Python | ||
89 | +// versions. | ||
90 | +// | ||
91 | +// File distributed under the MIT license. | ||
92 | +// Copyright Contributors to the pythoncapi_compat project. | ||
93 | +// | ||
94 | +// Homepage: | ||
95 | +// https://github.com/pythoncapi/pythoncapi_compat | ||
96 | +// | ||
97 | +// Latest version: | ||
98 | +// https://raw.githubusercontent.com/pythoncapi/pythoncapi_compat/master/pythoncapi_compat.h | ||
99 | +// | ||
100 | +// SPDX-License-Identifier: MIT | ||
101 | + | ||
102 | +#ifndef PYTHONCAPI_COMPAT | ||
103 | +#define PYTHONCAPI_COMPAT | ||
104 | + | ||
105 | +#ifdef __cplusplus | ||
106 | +extern "C" { | ||
107 | +#endif | ||
108 | + | ||
109 | +#include <Python.h> | ||
110 | +#include "frameobject.h" // PyFrameObject, PyFrame_GetBack() | ||
111 | + | ||
112 | + | ||
113 | +// Compatibility with Visual Studio 2013 and older which don't support | ||
114 | +// the inline keyword in C (only in C++): use __inline instead. | ||
115 | +#if (defined(_MSC_VER) && _MSC_VER < 1900 \ | ||
116 | + && !defined(__cplusplus) && !defined(inline)) | ||
117 | +# define inline __inline | ||
118 | +# define PYTHONCAPI_COMPAT_MSC_INLINE | ||
119 | + // These two macros are undefined at the end of this file | ||
120 | +#endif | ||
121 | + | ||
122 | + | ||
123 | +// Cast argument to PyObject* type. | ||
124 | +#ifndef _PyObject_CAST | ||
125 | +# define _PyObject_CAST(op) ((PyObject*)(op)) | ||
126 | +#endif | ||
127 | +#ifndef _PyObject_CAST_CONST | ||
128 | +# define _PyObject_CAST_CONST(op) ((const PyObject*)(op)) | ||
129 | +#endif | ||
130 | + | ||
131 | + | ||
132 | +// bpo-42262 added Py_NewRef() to Python 3.10.0a3 | ||
133 | +#if PY_VERSION_HEX < 0x030A00A3 && !defined(Py_NewRef) | ||
134 | +static inline PyObject* _Py_NewRef(PyObject *obj) | ||
135 | +{ | ||
136 | + Py_INCREF(obj); | ||
137 | + return obj; | ||
138 | +} | ||
139 | +#define Py_NewRef(obj) _Py_NewRef(_PyObject_CAST(obj)) | ||
140 | +#endif | ||
141 | + | ||
142 | + | ||
143 | +// bpo-42262 added Py_XNewRef() to Python 3.10.0a3 | ||
144 | +#if PY_VERSION_HEX < 0x030A00A3 && !defined(Py_XNewRef) | ||
145 | +static inline PyObject* _Py_XNewRef(PyObject *obj) | ||
146 | +{ | ||
147 | + Py_XINCREF(obj); | ||
148 | + return obj; | ||
149 | +} | ||
150 | +#define Py_XNewRef(obj) _Py_XNewRef(_PyObject_CAST(obj)) | ||
151 | +#endif | ||
152 | + | ||
153 | + | ||
154 | +// See https://bugs.python.org/issue42522 | ||
155 | +#if !defined(_Py_StealRef) | ||
156 | +static inline PyObject* __Py_StealRef(PyObject *obj) | ||
157 | +{ | ||
158 | + Py_DECREF(obj); | ||
159 | + return obj; | ||
160 | +} | ||
161 | +#define _Py_StealRef(obj) __Py_StealRef(_PyObject_CAST(obj)) | ||
162 | +#endif | ||
163 | + | ||
164 | + | ||
165 | +// See https://bugs.python.org/issue42522 | ||
166 | +#if !defined(_Py_XStealRef) | ||
167 | +static inline PyObject* __Py_XStealRef(PyObject *obj) | ||
168 | +{ | ||
169 | + Py_XDECREF(obj); | ||
170 | + return obj; | ||
171 | +} | ||
172 | +#define _Py_XStealRef(obj) __Py_XStealRef(_PyObject_CAST(obj)) | ||
173 | +#endif | ||
174 | + | ||
175 | + | ||
176 | +// bpo-39573 added Py_SET_REFCNT() to Python 3.9.0a4 | ||
177 | +#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_REFCNT) | ||
178 | +static inline void _Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) | ||
179 | +{ | ||
180 | + ob->ob_refcnt = refcnt; | ||
181 | +} | ||
182 | +#define Py_SET_REFCNT(ob, refcnt) _Py_SET_REFCNT(_PyObject_CAST(ob), refcnt) | ||
183 | +#endif | ||
184 | + | ||
185 | + | ||
186 | +// Py_SETREF() and Py_XSETREF() were added to Python 3.5.2. | ||
187 | +// It is excluded from the limited C API. | ||
188 | +#if (PY_VERSION_HEX < 0x03050200 && !defined(Py_SETREF)) && !defined(Py_LIMITED_API) | ||
189 | +#define Py_SETREF(op, op2) \ | ||
190 | + do { \ | ||
191 | + PyObject *_py_tmp = _PyObject_CAST(op); \ | ||
192 | + (op) = (op2); \ | ||
193 | + Py_DECREF(_py_tmp); \ | ||
194 | + } while (0) | ||
195 | + | ||
196 | +#define Py_XSETREF(op, op2) \ | ||
197 | + do { \ | ||
198 | + PyObject *_py_tmp = _PyObject_CAST(op); \ | ||
199 | + (op) = (op2); \ | ||
200 | + Py_XDECREF(_py_tmp); \ | ||
201 | + } while (0) | ||
202 | +#endif | ||
203 | + | ||
204 | + | ||
205 | +// bpo-43753 added Py_Is(), Py_IsNone(), Py_IsTrue() and Py_IsFalse() | ||
206 | +// to Python 3.10.0b1. | ||
207 | +#if PY_VERSION_HEX < 0x030A00B1 && !defined(Py_Is) | ||
208 | +# define Py_Is(x, y) ((x) == (y)) | ||
209 | +#endif | ||
210 | +#if PY_VERSION_HEX < 0x030A00B1 && !defined(Py_IsNone) | ||
211 | +# define Py_IsNone(x) Py_Is(x, Py_None) | ||
212 | +#endif | ||
213 | +#if PY_VERSION_HEX < 0x030A00B1 && !defined(Py_IsTrue) | ||
214 | +# define Py_IsTrue(x) Py_Is(x, Py_True) | ||
215 | +#endif | ||
216 | +#if PY_VERSION_HEX < 0x030A00B1 && !defined(Py_IsFalse) | ||
217 | +# define Py_IsFalse(x) Py_Is(x, Py_False) | ||
218 | +#endif | ||
219 | + | ||
220 | + | ||
221 | +// bpo-39573 added Py_SET_TYPE() to Python 3.9.0a4 | ||
222 | +#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_TYPE) | ||
223 | +static inline void | ||
224 | +_Py_SET_TYPE(PyObject *ob, PyTypeObject *type) | ||
225 | +{ | ||
226 | + ob->ob_type = type; | ||
227 | +} | ||
228 | +#define Py_SET_TYPE(ob, type) _Py_SET_TYPE(_PyObject_CAST(ob), type) | ||
229 | +#endif | ||
230 | + | ||
231 | + | ||
232 | +// bpo-39573 added Py_SET_SIZE() to Python 3.9.0a4 | ||
233 | +#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_SIZE) | ||
234 | +static inline void | ||
235 | +_Py_SET_SIZE(PyVarObject *ob, Py_ssize_t size) | ||
236 | +{ | ||
237 | + ob->ob_size = size; | ||
238 | +} | ||
239 | +#define Py_SET_SIZE(ob, size) _Py_SET_SIZE((PyVarObject*)(ob), size) | ||
240 | +#endif | ||
241 | + | ||
242 | + | ||
243 | +// bpo-40421 added PyFrame_GetCode() to Python 3.9.0b1 | ||
244 | +#if PY_VERSION_HEX < 0x030900B1 | ||
245 | +static inline PyCodeObject* | ||
246 | +PyFrame_GetCode(PyFrameObject *frame) | ||
247 | +{ | ||
248 | + assert(frame != NULL); | ||
249 | + assert(frame->f_code != NULL); | ||
250 | + return (PyCodeObject*)Py_NewRef(frame->f_code); | ||
251 | +} | ||
252 | +#endif | ||
253 | + | ||
254 | +static inline PyCodeObject* | ||
255 | +_PyFrame_GetCodeBorrow(PyFrameObject *frame) | ||
256 | +{ | ||
257 | + return (PyCodeObject *)_Py_StealRef(PyFrame_GetCode(frame)); | ||
258 | +} | ||
259 | + | ||
260 | + | ||
261 | +// bpo-40421 added PyFrame_GetCode() to Python 3.9.0b1 | ||
262 | +#if PY_VERSION_HEX < 0x030900B1 && !defined(PYPY_VERSION) | ||
263 | +static inline PyFrameObject* | ||
264 | +PyFrame_GetBack(PyFrameObject *frame) | ||
265 | +{ | ||
266 | + assert(frame != NULL); | ||
267 | + return (PyFrameObject*)Py_XNewRef(frame->f_back); | ||
268 | +} | ||
269 | +#endif | ||
270 | + | ||
271 | +#if !defined(PYPY_VERSION) | ||
272 | +static inline PyFrameObject* | ||
273 | +_PyFrame_GetBackBorrow(PyFrameObject *frame) | ||
274 | +{ | ||
275 | + return (PyFrameObject *)_Py_XStealRef(PyFrame_GetBack(frame)); | ||
276 | +} | ||
277 | +#endif | ||
278 | + | ||
279 | + | ||
280 | +// bpo-39947 added PyThreadState_GetInterpreter() to Python 3.9.0a5 | ||
281 | +#if PY_VERSION_HEX < 0x030900A5 | ||
282 | +static inline PyInterpreterState * | ||
283 | +PyThreadState_GetInterpreter(PyThreadState *tstate) | ||
284 | +{ | ||
285 | + assert(tstate != NULL); | ||
286 | + return tstate->interp; | ||
287 | +} | ||
288 | +#endif | ||
289 | + | ||
290 | + | ||
291 | +// bpo-40429 added PyThreadState_GetFrame() to Python 3.9.0b1 | ||
292 | +#if PY_VERSION_HEX < 0x030900B1 && !defined(PYPY_VERSION) | ||
293 | +static inline PyFrameObject* | ||
294 | +PyThreadState_GetFrame(PyThreadState *tstate) | ||
295 | +{ | ||
296 | + assert(tstate != NULL); | ||
297 | + return (PyFrameObject *)Py_XNewRef(tstate->frame); | ||
298 | +} | ||
299 | +#endif | ||
300 | + | ||
301 | +#if !defined(PYPY_VERSION) | ||
302 | +static inline PyFrameObject* | ||
303 | +_PyThreadState_GetFrameBorrow(PyThreadState *tstate) | ||
304 | +{ | ||
305 | + return (PyFrameObject *)_Py_XStealRef(PyThreadState_GetFrame(tstate)); | ||
306 | +} | ||
307 | +#endif | ||
308 | + | ||
309 | + | ||
310 | +// bpo-39947 added PyInterpreterState_Get() to Python 3.9.0a5 | ||
311 | +#if PY_VERSION_HEX < 0x030900A5 | ||
312 | +static inline PyInterpreterState * | ||
313 | +PyInterpreterState_Get(void) | ||
314 | +{ | ||
315 | + PyThreadState *tstate; | ||
316 | + PyInterpreterState *interp; | ||
317 | + | ||
318 | + tstate = PyThreadState_GET(); | ||
319 | + if (tstate == NULL) { | ||
320 | + Py_FatalError("GIL released (tstate is NULL)"); | ||
321 | + } | ||
322 | + interp = tstate->interp; | ||
323 | + if (interp == NULL) { | ||
324 | + Py_FatalError("no current interpreter"); | ||
325 | + } | ||
326 | + return interp; | ||
327 | +} | ||
328 | +#endif | ||
329 | + | ||
330 | + | ||
331 | +// bpo-39947 added PyInterpreterState_Get() to Python 3.9.0a6 | ||
332 | +#if 0x030700A1 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x030900A6 && !defined(PYPY_VERSION) | ||
333 | +static inline uint64_t | ||
334 | +PyThreadState_GetID(PyThreadState *tstate) | ||
335 | +{ | ||
336 | + assert(tstate != NULL); | ||
337 | + return tstate->id; | ||
338 | +} | ||
339 | +#endif | ||
340 | + | ||
341 | + | ||
342 | +// bpo-37194 added PyObject_CallNoArgs() to Python 3.9.0a1 | ||
343 | +#if PY_VERSION_HEX < 0x030900A1 | ||
344 | +static inline PyObject* | ||
345 | +PyObject_CallNoArgs(PyObject *func) | ||
346 | +{ | ||
347 | + return PyObject_CallFunctionObjArgs(func, NULL); | ||
348 | +} | ||
349 | +#endif | ||
350 | + | ||
351 | + | ||
352 | +// bpo-39245 made PyObject_CallOneArg() public (previously called | ||
353 | +// _PyObject_CallOneArg) in Python 3.9.0a4 | ||
354 | +#if PY_VERSION_HEX < 0x030900A4 | ||
355 | +static inline PyObject* | ||
356 | +PyObject_CallOneArg(PyObject *func, PyObject *arg) | ||
357 | +{ | ||
358 | + return PyObject_CallFunctionObjArgs(func, arg, NULL); | ||
359 | +} | ||
360 | +#endif | ||
361 | + | ||
362 | + | ||
363 | +// bpo-1635741 added PyModule_AddObjectRef() to Python 3.10.0a3 | ||
364 | +#if PY_VERSION_HEX < 0x030A00A3 | ||
365 | +static inline int | ||
366 | +PyModule_AddObjectRef(PyObject *module, const char *name, PyObject *value) | ||
367 | +{ | ||
368 | + Py_XINCREF(value); | ||
369 | + int res = PyModule_AddObject(module, name, value); | ||
370 | + if (res < 0) { | ||
371 | + Py_XDECREF(value); | ||
372 | + } | ||
373 | + return res; | ||
374 | +} | ||
375 | +#endif | ||
376 | + | ||
377 | + | ||
378 | +// bpo-40024 added PyModule_AddType() to Python 3.9.0a5 | ||
379 | +#if PY_VERSION_HEX < 0x030900A5 | ||
380 | +static inline int | ||
381 | +PyModule_AddType(PyObject *module, PyTypeObject *type) | ||
382 | +{ | ||
383 | + const char *name, *dot; | ||
384 | + | ||
385 | + if (PyType_Ready(type) < 0) { | ||
386 | + return -1; | ||
387 | + } | ||
388 | + | ||
389 | + // inline _PyType_Name() | ||
390 | + name = type->tp_name; | ||
391 | + assert(name != NULL); | ||
392 | + dot = strrchr(name, '.'); | ||
393 | + if (dot != NULL) { | ||
394 | + name = dot + 1; | ||
395 | + } | ||
396 | + | ||
397 | + return PyModule_AddObjectRef(module, name, (PyObject *)type); | ||
398 | +} | ||
399 | +#endif | ||
400 | + | ||
401 | + | ||
402 | +// bpo-40241 added PyObject_GC_IsTracked() to Python 3.9.0a6. | ||
403 | +// bpo-4688 added _PyObject_GC_IS_TRACKED() to Python 2.7.0a2. | ||
404 | +#if PY_VERSION_HEX < 0x030900A6 && !defined(PYPY_VERSION) | ||
405 | +static inline int | ||
406 | +PyObject_GC_IsTracked(PyObject* obj) | ||
407 | +{ | ||
408 | + return (PyObject_IS_GC(obj) && _PyObject_GC_IS_TRACKED(obj)); | ||
409 | +} | ||
410 | +#endif | ||
411 | + | ||
412 | +// bpo-40241 added PyObject_GC_IsFinalized() to Python 3.9.0a6. | ||
413 | +// bpo-18112 added _PyGCHead_FINALIZED() to Python 3.4.0 final. | ||
414 | +#if PY_VERSION_HEX < 0x030900A6 && PY_VERSION_HEX >= 0x030400F0 && !defined(PYPY_VERSION) | ||
415 | +static inline int | ||
416 | +PyObject_GC_IsFinalized(PyObject *obj) | ||
417 | +{ | ||
418 | + return (PyObject_IS_GC(obj) && _PyGCHead_FINALIZED((PyGC_Head *)(obj)-1)); | ||
419 | +} | ||
420 | +#endif | ||
421 | + | ||
422 | + | ||
423 | +// bpo-39573 added Py_IS_TYPE() to Python 3.9.0a4 | ||
424 | +#if PY_VERSION_HEX < 0x030900A4 && !defined(Py_IS_TYPE) | ||
425 | +static inline int | ||
426 | +_Py_IS_TYPE(const PyObject *ob, const PyTypeObject *type) { | ||
427 | + return ob->ob_type == type; | ||
428 | +} | ||
429 | +#define Py_IS_TYPE(ob, type) _Py_IS_TYPE(_PyObject_CAST_CONST(ob), type) | ||
430 | +#endif | ||
431 | + | ||
432 | + | ||
433 | +// Py_UNUSED() was added to Python 3.4.0b2. | ||
434 | +#if PY_VERSION_HEX < 0x030400B2 && !defined(Py_UNUSED) | ||
435 | +# if defined(__GNUC__) || defined(__clang__) | ||
436 | +# define Py_UNUSED(name) _unused_ ## name __attribute__((unused)) | ||
437 | +# else | ||
438 | +# define Py_UNUSED(name) _unused_ ## name | ||
439 | +# endif | ||
440 | +#endif | ||
441 | + | ||
442 | + | ||
443 | +#ifdef PYTHONCAPI_COMPAT_MSC_INLINE | ||
444 | +# undef inline | ||
445 | +# undef PYTHONCAPI_COMPAT_MSC_INLINE | ||
446 | +#endif | ||
447 | + | ||
448 | +#ifdef __cplusplus | ||
449 | +} | ||
450 | +#endif | ||
451 | +#endif // PYTHONCAPI_COMPAT | ||
452 | -- | ||
453 | 2.30.2 | ||
454 | |||