Gentoo Archives: gentoo-portage-dev

From: "Anthony G. Basile" <basile@××××××××××××××.edu>
To: gentoo-portage-dev@l.g.o
Subject: Re: [gentoo-portage-dev] [PATCH 3/3] pym/portage/util/locale.py: add a C module to help check locale
Date: Sun, 29 May 2016 06:37:54
Message-Id: d6f34620-087b-250c-f7b8-d5231e7522af@opensource.dyc.edu
In Reply to: Re: [gentoo-portage-dev] [PATCH 3/3] pym/portage/util/locale.py: add a C module to help check locale by "Michał Górny"
1 On 5/29/16 2:30 AM, Michał Górny wrote:
2 > On Fri, 27 May 2016 10:26:44 -0400
3 > "Anthony G. Basile" <basile@××××××××××××××.edu> wrote:
4 >
5 >> From: "Anthony G. Basile" <blueness@g.o>
6 >>
7 >> The current method to check for a sane system locale is to use python's
8 >> ctypes.util.find_library() to construct a full library path to the
9 >> system libc.so and pass that path to ctypes.CDLL() so we can call
10 >> toupper() and tolower() directly. However, this gets bogged down in
11 >> implementation details and fails with musl.
12 >>
13 >> We work around this design flaw in ctypes with a small python module
14 >> written in C which provides thin wrappers to toupper() and tolower(),
15 >> and only fall back on the current ctypes-based check when this module
16 >> is not available.
17 >>
18 >> This has been tested on glibc, uClibc and musl systems.
19 >>
20 >> X-Gentoo-bug: 571444
21 >> X-Gentoo-bug-url: https://bugs.gentoo.org/show_bug.cgi?id=571444
22 >>
23 >> Signed-off-by: Anthony G. Basile <blueness@g.o>
24 >> ---
25 >> pym/portage/util/locale.py | 16 ++++++-----
26 >> setup.py | 6 +++-
27 >> src/portage_util_libc.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++
28 >> 3 files changed, 84 insertions(+), 8 deletions(-)
29 >> create mode 100644 src/portage_util_libc.c
30 >>
31 >> diff --git a/pym/portage/util/locale.py b/pym/portage/util/locale.py
32 >> index 093eb86..5b09945 100644
33 >> --- a/pym/portage/util/locale.py
34 >> +++ b/pym/portage/util/locale.py
35 >> @@ -34,13 +34,15 @@ def _check_locale(silent):
36 >> """
37 >> The inner locale check function.
38 >> """
39 >> -
40 >> - libc_fn = find_library("c")
41 >> - if libc_fn is None:
42 >> - return None
43 >> - libc = LoadLibrary(libc_fn)
44 >> - if libc is None:
45 >> - return None
46 >> + try:
47 >> + from portage.util import libc
48 >> + except ImportError:
49 >> + libc_fn = find_library("c")
50 >> + if libc_fn is None:
51 >> + return None
52 >> + libc = LoadLibrary(libc_fn)
53 >> + if libc is None:
54 >> + return None
55 >>
56 >> lc = list(range(ord('a'), ord('z')+1))
57 >> uc = list(range(ord('A'), ord('Z')+1))
58 >> diff --git a/setup.py b/setup.py
59 >> index 25429bc..5ca8156 100755
60 >> --- a/setup.py
61 >> +++ b/setup.py
62 >> @@ -47,7 +47,11 @@ x_scripts = {
63 >> # Dictionary custom modules written in C/C++ here. The structure is
64 >> # key = module name
65 >> # value = list of C/C++ source code, path relative to top source directory
66 >> -x_c_helpers = {}
67 >> +x_c_helpers = {
68 >> + 'portage.util.libc' : [
69 >> + 'src/portage_util_libc.c',
70 >> + ],
71 >> +}
72 >>
73 >> class x_build(build):
74 >> """ Build command with extra build_man call. """
75 >> diff --git a/src/portage_util_libc.c b/src/portage_util_libc.c
76 >> new file mode 100644
77 >> index 0000000..00b09c2
78 >> --- /dev/null
79 >> +++ b/src/portage_util_libc.c
80 >> @@ -0,0 +1,70 @@
81 >> +/* Copyright 2005-2016 Gentoo Foundation
82 >> + * Distributed under the terms of the GNU General Public License v2
83 >> + */
84 >> +
85 >> +#include <Python.h>
86 >> +#include <stdlib.h>
87 >> +#include <ctype.h>
88 >> +
89 >> +static PyObject * _libc_tolower(PyObject *, PyObject *);
90 >> +static PyObject * _libc_toupper(PyObject *, PyObject *);
91 >> +
92 >> +static PyMethodDef LibcMethods[] = {
93 >> + {"tolower", _libc_tolower, METH_VARARGS, "Convert to lower case using system locale."},
94 >> + {"toupper", _libc_toupper, METH_VARARGS, "Convert to upper case using system locale."},
95 >> + {NULL, NULL, 0, NULL}
96 >> +};
97 >> +
98 >> +#if PY_MAJOR_VERSION >= 3
99 >> +static struct PyModuleDef moduledef = {
100 >> + PyModuleDef_HEAD_INIT,
101 >> + "libc", /* m_name */
102 >> + "Module for converting case using the system locale", /* m_doc */
103 >> + -1, /* m_size */
104 >> + LibcMethods, /* m_methods */
105 >> + NULL, /* m_reload */
106 >> + NULL, /* m_traverse */
107 >> + NULL, /* m_clear */
108 >> + NULL, /* m_free */
109 >> +};
110 >> +#endif
111 >> +
112 >> +PyMODINIT_FUNC
113 >
114 > Now you could call it nitpicking but since it decorates the function,
115 > it would be better to have it inside the #ifdef. Otherwise, people
116 > would think it's separate from that.
117
118 You mean repeat it twice?
119
120 >
121 >> +
122 >> +#if PY_MAJOR_VERSION >= 3
123 >> +PyInit_libc(void)
124 >> +{
125 >> + PyObject *m;
126 >> + m = PyModule_Create(&moduledef);
127 >> + return m;
128 >> +}
129 >> +#else
130 >> +initlibc(void)
131 >> +{
132 >> + Py_InitModule("libc", LibcMethods);
133 >> +}
134 >> +#endif
135 >> +
136 >> +
137 >> +static PyObject *
138 >> +_libc_tolower(PyObject *self, PyObject *args)
139 >> +{
140 >> + int c;
141 >> +
142 >> + if (!PyArg_ParseTuple(args, "i", &c))
143 >> + return NULL;
144 >> +
145 >> + return Py_BuildValue("i", tolower(c));
146 >> +}
147 >> +
148 >> +
149 >> +static PyObject *
150 >> +_libc_toupper(PyObject *self, PyObject *args)
151 >> +{
152 >> + int c;
153 >> +
154 >> + if (!PyArg_ParseTuple(args, "i", &c))
155 >> + return NULL;
156 >> +
157 >> + return Py_BuildValue("i", toupper(c));
158 >> +}
159 >
160 > Aside from that, it look nice and shiny now. Thanks a lot!
161
162 so what's the other stuff that could get put into this module that you
163 mentioned?
164
165 >
166
167
168 --
169 Anthony G. Basile, Ph. D.
170 Chair of Information Technology
171 D'Youville College
172 Buffalo, NY 14201
173 (716) 829-8197

Replies