3 * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version. The Blender
9 * Foundation also sells licenses for use in proprietary software under
10 * the Blender License. See http://www.blender.org/BL/ for information
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23 * All rights reserved.
25 * This is a new part of Blender.
27 * Contributor(s): Willian P. Germano
29 * ***** END GPL/BL DUAL LICENSE BLOCK *****
32 #include <BKE_utildefines.h>
33 #include <BLI_blenlib.h>
36 #include "gen_utils.h"
39 /*****************************************************************************/
40 /* Python API function prototypes for the sys module. */
41 /*****************************************************************************/
42 static PyObject *M_sys_basename (PyObject *self, PyObject *args);
43 static PyObject *M_sys_dirname (PyObject *self, PyObject *args);
44 static PyObject *M_sys_join (PyObject *self, PyObject *args);
45 static PyObject *M_sys_splitext (PyObject *self, PyObject *args);
46 static PyObject *M_sys_makename (PyObject *self, PyObject *args, PyObject *kw);
47 static PyObject *M_sys_exists (PyObject *self, PyObject *args);
48 static PyObject *M_sys_time (PyObject *self);
50 /*****************************************************************************/
51 /* The following string definitions are used for documentation strings. */
52 /* In Python these will be written to the console when doing a */
53 /* Blender.sys.__doc__ */
54 /*****************************************************************************/
55 static char M_sys_doc[] =
56 "The Blender.sys submodule\n\
58 This is a minimal system module to supply simple functionality available\n\
59 in the default Python module os.";
61 static char M_sys_basename_doc[] =
62 "(path) - Split 'path' in dir and filename.\n\
63 Return the filename.";
65 static char M_sys_dirname_doc[] =
66 "(path) - Split 'path' in dir and filename.\n\
69 static char M_sys_join_doc[] =
70 "(dir, file) - Join dir and file to form a full filename.\n\
71 Return the filename.";
73 static char M_sys_splitext_doc[] =
74 "(path) - Split 'path' in root and extension:\n\
75 /this/that/file.ext -> ('/this/that/file','.ext').\n\
76 Return the pair (root, extension).";
78 static char M_sys_makename_doc[] =
79 "(path = Blender.Get('filename'), ext = \"\", strip = 0) -\n\
80 Strip dir and extension from path, leaving only a name, then append 'ext'\n\
81 to it (if given) and return the resulting string.\n\n\
82 (path) - string: a pathname -- Blender.Get('filename') if 'path' isn't given;\n\
83 (ext = \"\") - string: the extension to append.\n\
84 (strip = 0) - int: strip dirname from 'path' if given and non-zero.\n\
85 Ex: makename('/path/to/file/myfile.foo','-01.abc') returns 'myfile-01.abc'\n\
86 Ex: makename(ext='.txt') returns 'untitled.txt' if Blender.Get('filename')\n\
87 returns a path to the file 'untitled.blend'";
89 static char M_sys_time_doc[] =
90 "() - Return a float representing time elapsed in seconds.\n\
91 Each successive call is garanteed to return values greater than or\n\
92 equal to the previous call.";
94 static char M_sys_exists_doc[] =
95 "(path) - Return 1 if given pathname (file or dir) exists, 0 otherwise.";
97 /*****************************************************************************/
98 /* Python method structure definition for Blender.sys module: */
99 /*****************************************************************************/
100 struct PyMethodDef M_sys_methods[] = {
101 {"basename", M_sys_basename, METH_VARARGS, M_sys_basename_doc},
102 {"dirname", M_sys_dirname, METH_VARARGS, M_sys_dirname_doc},
103 {"join", M_sys_join, METH_VARARGS, M_sys_join_doc},
104 {"splitext", M_sys_splitext, METH_VARARGS, M_sys_splitext_doc},
105 {"makename", (PyCFunction)M_sys_makename, METH_VARARGS|METH_KEYWORDS,
107 {"exists", M_sys_exists, METH_VARARGS, M_sys_exists_doc},
108 {"time", (PyCFunction)M_sys_time, METH_NOARGS, M_sys_time_doc},
109 {NULL, NULL, 0, NULL}
112 /* Module Functions */
114 static PyObject *g_sysmodule = NULL; /* pointer to Blender.sys module */
116 PyObject *sys_Init (void)
118 PyObject *submodule, *dict, *sep;
120 submodule = Py_InitModule3("Blender.sys", M_sys_methods, M_sys_doc);
122 g_sysmodule = submodule;
124 dict = PyModule_GetDict(submodule);
127 sep = Py_BuildValue("s", "\\");
129 sep = Py_BuildValue("s", "/");
134 PyDict_SetItemString(dict, "dirsep" , sep);
135 PyDict_SetItemString(dict, "sep" , sep);
141 static PyObject *M_sys_basename (PyObject *self, PyObject *args)
145 char *name, *p, basename[FILE_MAXFILE];
149 if (!PyArg_ParseTuple(args, "s", &name))
150 return EXPP_ReturnPyObjError (PyExc_TypeError,
151 "expected string argument");
155 c = PyObject_GetAttrString (g_sysmodule, "dirsep");
156 sep = PyString_AsString(c)[0];
159 p = strrchr(name, sep);
162 n = name + len - p - 1; /* - 1 because we don't want the sep */
164 if (n > FILE_MAXFILE)
165 return EXPP_ReturnPyObjError(PyExc_RuntimeError, "path too long");
167 BLI_strncpy(basename, p + 1, n + 1);
168 return Py_BuildValue("s", basename);
171 return Py_BuildValue("s", name);
174 static PyObject *M_sys_dirname (PyObject *self, PyObject *args)
178 char *name, *p, dirname[FILE_MAXDIR];
182 if (!PyArg_ParseTuple(args, "s", &name))
183 return EXPP_ReturnPyObjError (PyExc_TypeError,
184 "expected string argument");
186 c = PyObject_GetAttrString (g_sysmodule, "dirsep");
187 sep = PyString_AsString(c)[0];
190 p = strrchr(name, sep);
196 return EXPP_ReturnPyObjError (PyExc_RuntimeError, "path too long");
198 BLI_strncpy(dirname, name, n + 1);
199 return Py_BuildValue("s", dirname);
202 return Py_BuildValue("s", ".");
205 static PyObject *M_sys_join (PyObject *self, PyObject *args)
208 char *name = NULL, *path = NULL;
209 char filename[FILE_MAXDIR+FILE_MAXFILE];
211 int pathlen = 0, namelen = 0;
213 if (!PyArg_ParseTuple(args, "ss", &path, &name))
214 return EXPP_ReturnPyObjError (PyExc_TypeError,
215 "expected string argument");
217 pathlen = strlen(path) + 1;
218 namelen = strlen(name) + 1; /* + 1 to account for '\0' for BLI_strncpy */
220 if (pathlen + namelen > FILE_MAXDIR+FILE_MAXFILE - 1)
221 return EXPP_ReturnPyObjError (PyExc_RuntimeError, "filename is too long.");
223 c = PyObject_GetAttrString (g_sysmodule, "dirsep");
224 sep = PyString_AsString(c)[0];
227 BLI_strncpy(filename, path, pathlen);
229 if (filename[pathlen - 2] != sep) {
230 filename[pathlen - 1] = sep;
234 BLI_strncpy(filename + pathlen - 1, name, namelen);
236 return Py_BuildValue("s", filename);
239 static PyObject *M_sys_splitext (PyObject *self, PyObject *args)
243 char *name, *dot, *p, path[FILE_MAXFILE], ext[FILE_MAXFILE];
247 if (!PyArg_ParseTuple(args, "s", &name))
248 return EXPP_ReturnPyObjError (PyExc_TypeError,
249 "expected string argument");
253 c = PyObject_GetAttrString (g_sysmodule, "dirsep");
254 sep = PyString_AsString(c)[0];
257 dot = strrchr(name, '.');
259 if (!dot) return Py_BuildValue("ss", name, "");
261 p = strrchr(name, sep);
264 if (p > dot) return Py_BuildValue("ss", name, "");
267 n = name + len - dot;
269 /* loong extensions are supported -- foolish, but Python's os.path.splitext
270 * supports them, so ... */
271 if (n > FILE_MAXFILE || (len - n ) > FILE_MAXFILE)
272 EXPP_ReturnPyObjError(PyExc_RuntimeError, "path too long");
274 BLI_strncpy(ext, dot, n + 1);
275 BLI_strncpy(path, name, dot - name + 1);
277 return Py_BuildValue("ss", path, ext);
280 static PyObject *M_sys_makename(PyObject *self, PyObject *args, PyObject *kw)
282 char *path = G.sce, *ext = NULL;
284 static char *kwlist[] = {"path", "ext", "strip", NULL};
285 char *dot = NULL, *p = NULL, basename[FILE_MAXFILE];
287 int n, len, lenext = 0;
290 if (!PyArg_ParseTupleAndKeywords(args, kw, "|ssi", kwlist,
291 &path, &ext, &strip))
292 return EXPP_ReturnPyObjError (PyExc_TypeError,
293 "expected one or two strings and an int (or nothing) as arguments");
295 len = strlen(path) + 1; /* + 1 to consider ending '\0' */
296 if (ext) lenext = strlen(ext) + 1;
298 if ((len + lenext) > FILE_MAXFILE)
299 return EXPP_ReturnPyObjError(PyExc_RuntimeError, "path too long");
301 c = PyObject_GetAttrString (g_sysmodule, "dirsep");
302 sep = PyString_AsString(c)[0];
305 p = strrchr(path, sep);
309 BLI_strncpy(basename, p + 1, n); /* + 1 to skip the sep */
312 BLI_strncpy(basename, path, len);
314 dot = strrchr(basename, '.');
316 /* now the extension: always remove the one in basename */
319 basename[dot - basename] = '\0';
320 else { /* if user gave an ext, append it */
322 if (dot) n = dot - basename;
323 else n = strlen(basename);
325 BLI_strncpy(basename + n, ext, lenext);
329 return PyString_FromString(basename);
332 static PyObject *M_sys_time (PyObject *self)
334 double t = PIL_check_seconds_timer();
335 return Py_BuildValue("d", t);
338 static PyObject *M_sys_exists (PyObject *self, PyObject *args)
343 if (!PyArg_ParseTuple(args, "s", &fname))
344 return EXPP_ReturnPyObjError (PyExc_TypeError,
345 "expected string (file path) argument");
347 i = BLI_exists(fname);
349 if (i) return Py_BuildValue("i", 1); /* path was found */
351 return Py_BuildValue("i", 0); /* path doesn't exist */