Scripts:
[blender-staging.git] / source / blender / python / api2_2x / Sys.c
1 /* 
2  *
3  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
4  *
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
11  * about this.
12  *
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.
17  *
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.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * This is a new part of Blender.
26  *
27  * Contributor(s): Willian P. Germano
28  *
29  * ***** END GPL/BL DUAL LICENSE BLOCK *****
30 */
31
32 #include <BKE_utildefines.h>
33 #include <BLI_blenlib.h>
34 #include <PIL_time.h>
35 #include <Python.h>
36 #include "gen_utils.h"
37 #include "modules.h"
38
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);
49
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\
57 \n\
58 This is a minimal system module to supply simple functionality available\n\
59 in the default Python module os.";
60
61 static char M_sys_basename_doc[] =
62 "(path) - Split 'path' in dir and filename.\n\
63 Return the filename.";
64
65 static char M_sys_dirname_doc[] =
66 "(path) - Split 'path' in dir and filename.\n\
67 Return the dir.";
68
69 static char M_sys_join_doc[] =
70 "(dir, file) - Join dir and file to form a full filename.\n\
71 Return the filename.";
72
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).";
77
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'";
88
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.";
93
94 static char M_sys_exists_doc[] =
95 "(path) - Return 1 if given pathname (file or dir) exists, 0 otherwise.";
96
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,
106                 M_sys_makename_doc},
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}
110 };
111
112 /* Module Functions */
113
114 static PyObject *g_sysmodule = NULL; /* pointer to Blender.sys module */
115
116 PyObject *sys_Init (void)
117 {
118         PyObject        *submodule, *dict, *sep;
119
120         submodule = Py_InitModule3("Blender.sys", M_sys_methods, M_sys_doc);
121
122         g_sysmodule = submodule;
123
124         dict = PyModule_GetDict(submodule);
125
126 #ifdef WIN32
127         sep = Py_BuildValue("s", "\\");
128 #else
129         sep = Py_BuildValue("s", "/");
130 #endif
131
132         if (sep) {
133                 Py_INCREF(sep);
134                 PyDict_SetItemString(dict, "dirsep" , sep);
135                 PyDict_SetItemString(dict, "sep" , sep);
136         }
137
138         return submodule;
139 }
140
141 static PyObject *M_sys_basename (PyObject *self, PyObject *args)
142 {
143         PyObject *c;
144
145         char *name, *p, basename[FILE_MAXFILE];
146         char sep;
147         int n, len;
148
149         if (!PyArg_ParseTuple(args, "s", &name))
150                 return EXPP_ReturnPyObjError (PyExc_TypeError,
151                                                         "expected string argument");
152
153         len = strlen(name);
154
155         c = PyObject_GetAttrString (g_sysmodule, "dirsep");
156         sep = PyString_AsString(c)[0];
157         Py_DECREF(c);
158
159         p = strrchr(name, sep);
160
161         if (p) {
162                 n = name + len - p - 1; /* - 1 because we don't want the sep */
163
164                 if (n > FILE_MAXFILE)
165                         return EXPP_ReturnPyObjError(PyExc_RuntimeError, "path too long");
166
167                 BLI_strncpy(basename, p + 1, n + 1);
168                 return Py_BuildValue("s", basename);
169         }
170
171         return Py_BuildValue("s", name);
172 }
173
174 static PyObject *M_sys_dirname (PyObject *self, PyObject *args)
175 {
176         PyObject *c;
177
178         char *name, *p, dirname[FILE_MAXDIR];
179         char sep;
180         int n;
181
182         if (!PyArg_ParseTuple(args, "s", &name))
183                 return EXPP_ReturnPyObjError (PyExc_TypeError,
184                                                         "expected string argument");
185
186         c = PyObject_GetAttrString (g_sysmodule, "dirsep");
187         sep = PyString_AsString(c)[0];
188         Py_DECREF(c);
189
190         p = strrchr(name, sep);
191
192         if (p) {
193                 n = p - name;
194
195                 if (n > FILE_MAXDIR)
196                         return EXPP_ReturnPyObjError (PyExc_RuntimeError, "path too long");
197
198                 BLI_strncpy(dirname, name, n + 1);
199                 return Py_BuildValue("s", dirname);
200         }
201
202         return Py_BuildValue("s", ".");
203 }
204
205 static PyObject *M_sys_join (PyObject *self, PyObject *args)
206 {
207         PyObject *c = NULL;
208         char *name = NULL, *path = NULL;
209         char filename[FILE_MAXDIR+FILE_MAXFILE];
210         char sep;
211         int pathlen = 0, namelen = 0;
212
213         if (!PyArg_ParseTuple(args, "ss", &path, &name))
214                 return EXPP_ReturnPyObjError (PyExc_TypeError,
215                                                         "expected string argument");
216
217         pathlen = strlen(path) + 1;
218         namelen = strlen(name) + 1; /* + 1 to account for '\0' for BLI_strncpy */
219
220         if (pathlen + namelen > FILE_MAXDIR+FILE_MAXFILE - 1)
221                 return EXPP_ReturnPyObjError (PyExc_RuntimeError, "filename is too long.");
222
223         c = PyObject_GetAttrString (g_sysmodule, "dirsep");
224         sep = PyString_AsString(c)[0];
225         Py_DECREF(c);
226         
227         BLI_strncpy(filename, path, pathlen);
228
229         if (filename[pathlen - 2] != sep) {
230                 filename[pathlen - 1] = sep;
231                 pathlen += 1;
232         }
233
234         BLI_strncpy(filename + pathlen - 1, name, namelen);
235
236         return Py_BuildValue("s", filename);
237 }
238
239 static PyObject *M_sys_splitext (PyObject *self, PyObject *args)
240 {
241         PyObject *c;
242
243         char *name, *dot, *p, path[FILE_MAXFILE], ext[FILE_MAXFILE];
244         char sep;
245         int n, len;
246
247         if (!PyArg_ParseTuple(args, "s", &name))
248                 return EXPP_ReturnPyObjError (PyExc_TypeError,
249                                                         "expected string argument");
250
251         len = strlen(name);
252
253         c = PyObject_GetAttrString (g_sysmodule, "dirsep");
254         sep = PyString_AsString(c)[0];
255         Py_DECREF(c);
256
257         dot = strrchr(name, '.');
258
259         if (!dot) return Py_BuildValue("ss", name, "");
260
261         p = strrchr(name, sep);
262
263         if (p) {
264                 if (p > dot) return Py_BuildValue("ss", name, "");
265         }
266
267         n = name + len - dot;
268
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");
273
274         BLI_strncpy(ext, dot, n + 1);
275         BLI_strncpy(path, name, dot - name + 1);
276
277         return Py_BuildValue("ss", path, ext);
278 }
279
280 static PyObject *M_sys_makename(PyObject *self, PyObject *args, PyObject *kw)
281 {
282         char *path = G.sce, *ext = NULL;
283         int strip = 0;
284         static char *kwlist[] = {"path", "ext", "strip", NULL};
285         char *dot = NULL, *p = NULL, basename[FILE_MAXFILE];
286         char sep;
287         int n, len, lenext = 0;
288         PyObject *c;
289
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");
294
295         len = strlen(path) + 1; /* + 1 to consider ending '\0' */
296         if (ext) lenext = strlen(ext) + 1;
297
298         if ((len + lenext) > FILE_MAXFILE)
299                 return EXPP_ReturnPyObjError(PyExc_RuntimeError, "path too long");
300
301         c = PyObject_GetAttrString (g_sysmodule, "dirsep");
302         sep = PyString_AsString(c)[0];
303         Py_DECREF(c);
304
305         p = strrchr(path, sep);
306
307         if (p && strip) {
308                 n = path + len - p;
309                 BLI_strncpy(basename, p + 1, n); /* + 1 to skip the sep */
310         }
311         else
312                 BLI_strncpy(basename, path, len);
313
314         dot = strrchr(basename, '.');
315
316         /* now the extension: always remove the one in basename */
317         if (dot || ext) {
318                 if (!ext)
319                         basename[dot - basename] = '\0';
320                 else { /* if user gave an ext, append it */
321
322                         if (dot) n = dot - basename;
323                         else n = strlen(basename);
324
325                         BLI_strncpy(basename + n, ext, lenext);
326                 }
327         }
328
329         return PyString_FromString(basename);
330 }
331
332 static PyObject *M_sys_time (PyObject *self)
333 {
334         double t = PIL_check_seconds_timer();
335         return Py_BuildValue("d", t);
336 }
337
338 static PyObject *M_sys_exists (PyObject *self, PyObject *args)
339 {
340         char *fname = NULL;
341         int i = 0;
342
343         if (!PyArg_ParseTuple(args, "s", &fname))
344                 return EXPP_ReturnPyObjError (PyExc_TypeError,
345                                                         "expected string (file path) argument");
346
347         i = BLI_exists(fname);
348
349         if (i) return Py_BuildValue("i", 1); /* path was found */
350
351         return Py_BuildValue("i", 0); /* path doesn't exist */
352 }