Nuitka
The Python compiler
Loading...
Searching...
No Matches
HelpersFiles.c
1// Copyright 2025, Kay Hayen, mailto:kay.hayen@gmail.com find license text at end of file
2
3/* Small helpers to access files and their contents */
4
5// This file is included from another C file, help IDEs to still parse it on
6// its own.
7#ifdef __IDE_ONLY__
8#include "nuitka/prelude.h"
9#endif
10
11// Small helper to open files with few arguments.
12PyObject *BUILTIN_OPEN_SIMPLE(PyThreadState *tstate, PyObject *filename, char const *mode, bool buffering,
13 PyObject *encoding) {
14 PyObject *mode_obj = Nuitka_String_FromString(mode);
15 PyObject *buffering_obj = buffering ? const_int_pos_1 : const_int_0;
16
17 PyObject *result;
18
19#if PYTHON_VERSION < 0x300
20 // On Windows, it seems that line buffering is actually the default.
21#ifdef _WIN32
22 if ((strcmp(mode, "w") == 0) && buffering == true) {
23 buffering_obj = const_int_0;
24 }
25#endif
26
27 result = BUILTIN_OPEN(tstate, filename, mode_obj, buffering_obj);
28
29#else
30 if ((strcmp(mode, "w") == 0) && buffering == false) {
31 // TODO: Hard import code could be used for this.
32 static PyObject *_io_module_text_io_wrapper = NULL;
33 if (_io_module_text_io_wrapper == NULL) {
34 _io_module_text_io_wrapper = PyObject_GetAttrString(IMPORT_HARD__IO(), "TextIOWrapper");
35 CHECK_OBJECT(_io_module_text_io_wrapper);
36 }
37
38 PyObject *mode_obj2 = PyUnicode_FromString("wb");
39
40 PyObject *binary_stream =
41 BUILTIN_OPEN(tstate, filename, mode_obj2, buffering_obj, NULL, NULL, NULL, NULL, NULL);
42
43 Py_DECREF(mode_obj2);
44
45 if (binary_stream == NULL) {
46 return NULL;
47 }
48
49 PyObject *encoding_default = NULL;
50
51 if (encoding == NULL) {
52 if (encoding_default == NULL) {
53 encoding_default = Nuitka_String_FromString("utf-8");
54 }
55
56 encoding = encoding_default;
57 }
58
59 PyObject *args[] = {binary_stream, encoding, Py_None, Py_None, Py_False, Py_True};
60
61 result = CALL_FUNCTION_WITH_ARGS6(tstate, _io_module_text_io_wrapper, args);
62 } else {
63 result = BUILTIN_OPEN(tstate, filename, mode_obj, buffering_obj, encoding, NULL, NULL, NULL, NULL);
64 }
65
66#endif
67 Py_DECREF(mode_obj);
68
69 return result;
70}
71
72PyObject *BUILTIN_OPEN_BINARY_READ_SIMPLE(PyThreadState *tstate, PyObject *filename) {
73 PyObject *result;
74
75#if PYTHON_VERSION < 0x300
76 // On Windows, it seems that line buffering is actually the default.
77 result = BUILTIN_OPEN(tstate, filename, const_str_plain_rb, const_int_0);
78#else
79 result = BUILTIN_OPEN(tstate, filename, const_str_plain_rb, const_int_0, NULL, NULL, NULL, NULL, NULL);
80#endif
81
82 return result;
83}
84
85PyObject *GET_FILE_BYTES(PyThreadState *tstate, PyObject *filename) {
86 PyObject *read_result;
87
88 if (TRACE_FILE_READ(tstate, filename, &read_result)) {
89 return read_result;
90 }
91
92 PyObject *data_file = BUILTIN_OPEN_BINARY_READ_SIMPLE(tstate, filename);
93
94 if (unlikely(data_file == NULL)) {
95 // TODO: Issue a runtime warning maybe.
96 return NULL;
97 }
98
99 PyObject *read_method = LOOKUP_ATTRIBUTE(tstate, data_file, const_str_plain_read);
100 Py_DECREF(data_file);
101
102 if (unlikely(read_method == NULL)) {
103 return NULL;
104 }
105
106 PyObject *close_method = LOOKUP_ATTRIBUTE(tstate, data_file, const_str_plain_close);
107
108 if (unlikely(close_method == NULL)) {
109 Py_DECREF(read_method);
110 return NULL;
111 }
112
113 read_result = CALL_FUNCTION_NO_ARGS(tstate, read_method);
114 Py_DECREF(read_method);
115
116 if (unlikely(read_result == NULL)) {
117 Py_DECREF(close_method);
118 return NULL;
119 }
120
121 PyObject *close_result = CALL_FUNCTION_NO_ARGS(tstate, close_method);
122 Py_DECREF(close_method);
123
124 if (unlikely(close_result == NULL)) {
125 Py_DECREF(read_result);
126 return NULL;
127 }
128
129 Py_DECREF(close_result);
130
131 return read_result;
132}
133
134// TODO: Don't we have this generated.
135static PyObject *IMPORT_HARD_OS_PATH(PyThreadState *tstate) {
136 static PyObject *os_path = NULL;
137
138 if (os_path == NULL) {
139 os_path = LOOKUP_ATTRIBUTE(tstate, IMPORT_HARD_OS(), const_str_plain_path);
140
141 CHECK_OBJECT(os_path);
142 }
143
144 return os_path;
145}
146
147PyObject *OS_PATH_FILE_EXISTS(PyThreadState *tstate, PyObject *filename) {
148 PyObject *result;
149
150 if (TRACE_FILE_EXISTS(tstate, filename, &result)) {
151 return result;
152 }
153
154 PyObject *exists_func = LOOKUP_ATTRIBUTE(tstate, IMPORT_HARD_OS_PATH(tstate), const_str_plain_exists);
155
156 result = CALL_FUNCTION_WITH_SINGLE_ARG(tstate, exists_func, filename);
157
158 Py_DECREF(exists_func);
159 return result;
160}
161
162PyObject *OS_PATH_FILE_ISFILE(PyThreadState *tstate, PyObject *filename) {
163 PyObject *result;
164
165 if (TRACE_FILE_ISFILE(tstate, filename, &result)) {
166 return result;
167 }
168
169 PyObject *isfile_func = LOOKUP_ATTRIBUTE(tstate, IMPORT_HARD_OS_PATH(tstate), const_str_plain_isfile);
170
171 result = CALL_FUNCTION_WITH_SINGLE_ARG(tstate, isfile_func, filename);
172
173 Py_DECREF(isfile_func);
174 return result;
175}
176
177PyObject *OS_PATH_FILE_ISDIR(PyThreadState *tstate, PyObject *filename) {
178 PyObject *result;
179
180 if (TRACE_FILE_ISDIR(tstate, filename, &result)) {
181 return result;
182 }
183
184 PyObject *isdir_func = LOOKUP_ATTRIBUTE(tstate, IMPORT_HARD_OS_PATH(tstate), const_str_plain_isdir);
185
186 result = CALL_FUNCTION_WITH_SINGLE_ARG(tstate, isdir_func, filename);
187
188 Py_DECREF(isdir_func);
189 return result;
190}
191
192PyObject *OS_LISTDIR(PyThreadState *tstate, PyObject *path) {
193 PyObject *result;
194
195 if (TRACE_FILE_LISTDIR(tstate, path, &result)) {
196 return result;
197 }
198
199 PyObject *listdir_func = LOOKUP_ATTRIBUTE(tstate, IMPORT_HARD_OS(), const_str_plain_listdir);
200
201 if (path != NULL) {
202 result = CALL_FUNCTION_WITH_SINGLE_ARG(tstate, listdir_func, path);
203 } else {
204 result = CALL_FUNCTION_NO_ARGS(tstate, listdir_func);
205 }
206
207 Py_DECREF(listdir_func);
208 return result;
209}
210
211extern PyObject *OS_STAT(PyThreadState *tstate, PyObject *path, PyObject *dir_fd, PyObject *follow_symlinks) {
212 assert(path != NULL);
213
214 PyObject *result;
215
216 if (TRACE_FILE_STAT(tstate, path, dir_fd, follow_symlinks, &result)) {
217 return result;
218 }
219
220 PyObject *stat_func = LOOKUP_ATTRIBUTE(tstate, IMPORT_HARD_OS(), const_str_plain_stat);
221
222#if PYTHON_VERSION < 0x300
223 assert(dir_fd == NULL);
224
225 result = CALL_FUNCTION_WITH_SINGLE_ARG(tstate, stat_func, path);
226#else
227
228 PyObject *args[] = {path, dir_fd, follow_symlinks};
229
230 char const *arg_names[] = {"path", "dir_fd", "follow_symlinks"};
231 result = CALL_BUILTIN_KW_ARGS(tstate, stat_func, args, arg_names, 3, 2);
232#endif
233
234 Py_DECREF(stat_func);
235 return result;
236}
237
238extern PyObject *OS_LSTAT(PyThreadState *tstate, PyObject *path, PyObject *dir_fd) {
239 assert(path != NULL);
240 PyObject *result;
241
242#if PYTHON_VERSION < 0x300
243 if (TRACE_FILE_STAT(tstate, path, dir_fd, Py_False, &result)) {
244 return result;
245 }
246
247 assert(path != NULL);
248 assert(dir_fd == NULL);
249 PyObject *lstat_func = LOOKUP_ATTRIBUTE(tstate, IMPORT_HARD_OS(), const_str_plain_lstat);
250
251 result = CALL_FUNCTION_WITH_SINGLE_ARG(tstate, lstat_func, path);
252#else
253 if (TRACE_FILE_STAT(tstate, path, dir_fd, Py_True, &result)) {
254 return result;
255 }
256
257 PyObject *args[] = {path, dir_fd};
258
259 char const *arg_names[] = {"path", "dir_fd"};
260
261 PyObject *lstat_func = LOOKUP_ATTRIBUTE(tstate, IMPORT_HARD_OS(), const_str_plain_lstat);
262
263 result = CALL_BUILTIN_KW_ARGS(tstate, lstat_func, args, arg_names, 2, 1);
264#endif
265
266 Py_DECREF(lstat_func);
267 return result;
268}
269
270PyObject *OS_PATH_BASENAME(PyThreadState *tstate, PyObject *filename) {
271 CHECK_OBJECT(filename);
272
273 PyObject *basename_func = LOOKUP_ATTRIBUTE(tstate, IMPORT_HARD_OS_PATH(tstate), const_str_plain_basename);
274
275 PyObject *result = CALL_FUNCTION_WITH_SINGLE_ARG(tstate, basename_func, filename);
276
277 Py_DECREF(basename_func);
278 return result;
279}
280
281PyObject *OS_PATH_DIRNAME(PyThreadState *tstate, PyObject *filename) {
282 CHECK_OBJECT(filename);
283
284 PyObject *dirname_func = LOOKUP_ATTRIBUTE(tstate, IMPORT_HARD_OS_PATH(tstate), const_str_plain_dirname);
285
286 PyObject *result = CALL_FUNCTION_WITH_SINGLE_ARG(tstate, dirname_func, filename);
287
288 Py_DECREF(dirname_func);
289 return result;
290}
291
292PyObject *OS_PATH_ABSPATH(PyThreadState *tstate, PyObject *filename) {
293 CHECK_OBJECT(filename);
294
295 PyObject *abspath_func = LOOKUP_ATTRIBUTE(tstate, IMPORT_HARD_OS_PATH(tstate), const_str_plain_abspath);
296
297 PyObject *result = CALL_FUNCTION_WITH_SINGLE_ARG(tstate, abspath_func, filename);
298
299 Py_DECREF(abspath_func);
300 return result;
301}
302
303PyObject *OS_PATH_ISABS(PyThreadState *tstate, PyObject *filename) {
304 CHECK_OBJECT(filename);
305
306 PyObject *isabs_func = LOOKUP_ATTRIBUTE(tstate, IMPORT_HARD_OS_PATH(tstate), const_str_plain_isabs);
307
308 PyObject *result = CALL_FUNCTION_WITH_SINGLE_ARG(tstate, isabs_func, filename);
309
310 Py_DECREF(isabs_func);
311 return result;
312}
313
314extern PyObject *OS_PATH_NORMPATH(PyThreadState *tstate, PyObject *filename) {
315 PyObject *normpath_func = LOOKUP_ATTRIBUTE(tstate, IMPORT_HARD_OS_PATH(tstate), const_str_plain_normpath);
316
317 PyObject *result = CALL_FUNCTION_WITH_SINGLE_ARG(tstate, normpath_func, filename);
318
319 Py_DECREF(normpath_func);
320 return result;
321}
322
323nuitka_bool compareFilePaths(PyThreadState *tstate, PyObject *filename_a, PyObject *filename_b) {
324 filename_a = OS_PATH_ABSPATH(tstate, filename_a);
325
326 if (unlikely(filename_a == NULL)) {
327 return NUITKA_BOOL_EXCEPTION;
328 }
329
330 filename_b = OS_PATH_ABSPATH(tstate, filename_b);
331
332 if (unlikely(filename_b == NULL)) {
333 Py_DECREF(filename_a);
334 return NUITKA_BOOL_EXCEPTION;
335 }
336
337 return RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(filename_a, filename_b);
338}
339
340// Part of "Nuitka", an optimizing Python compiler that is compatible and
341// integrates with CPython, but also works on its own.
342//
343// Licensed under the Apache License, Version 2.0 (the "License");
344// you may not use this file except in compliance with the License.
345// You may obtain a copy of the License at
346//
347// http://www.apache.org/licenses/LICENSE-2.0
348//
349// Unless required by applicable law or agreed to in writing, software
350// distributed under the License is distributed on an "AS IS" BASIS,
351// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
352// See the License for the specific language governing permissions and
353// limitations under the License.