Blender V4.5
bpy_rna_data.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
15
16#include <Python.h>
17#include <cstddef>
18
20#include "../generic/python_compat.hh" /* IWYU pragma: keep. */
21
22#include "BLI_string.h"
23
24#include "BKE_global.hh"
25#include "BKE_main.hh"
26
27#include "RNA_access.hh"
28#include "RNA_prototypes.hh"
29
30#include "bpy_rna.hh"
31#include "bpy_rna_data.hh"
32
34 PyObject_HEAD /* Required Python macro. */
36 char filepath[1024];
37};
38
39static PyObject *bpy_rna_data_temp_data(PyObject *self, PyObject *args, PyObject *kw);
41static PyObject *bpy_rna_data_context_exit(BPy_DataContext *self, PyObject *args);
42
43#ifdef __GNUC__
44# ifdef __clang__
45# pragma clang diagnostic push
46# pragma clang diagnostic ignored "-Wcast-function-type"
47# else
48# pragma GCC diagnostic push
49# pragma GCC diagnostic ignored "-Wcast-function-type"
50# endif
51#endif
52
53static PyMethodDef bpy_rna_data_context_methods[] = {
54 {"__enter__", (PyCFunction)bpy_rna_data_context_enter, METH_NOARGS},
55 {"__exit__", (PyCFunction)bpy_rna_data_context_exit, METH_VARARGS},
56 {nullptr} /* sentinel */
57};
58
59#ifdef __GNUC__
60# ifdef __clang__
61# pragma clang diagnostic pop
62# else
63# pragma GCC diagnostic pop
64# endif
65#endif
66
67static int bpy_rna_data_context_traverse(BPy_DataContext *self, visitproc visit, void *arg)
68{
69 Py_VISIT(self->data_rna);
70 return 0;
71}
72
74{
75 Py_CLEAR(self->data_rna);
76 return 0;
77}
78
80{
81 PyObject_GC_UnTrack(self);
82 Py_CLEAR(self->data_rna);
83 PyObject_GC_Del(self);
84}
85static PyTypeObject bpy_rna_data_context_Type = {
86 /*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
87 /*tp_name*/ "bpy_rna_data_context",
88 /*tp_basicsize*/ sizeof(BPy_DataContext),
89 /*tp_itemsize*/ 0,
90 /*tp_dealloc*/ (destructor)bpy_rna_data_context_dealloc,
91 /*tp_vectorcall_offset*/ 0,
92 /*tp_getattr*/ nullptr,
93 /*tp_setattr*/ nullptr,
94 /*tp_as_async*/ nullptr,
95 /*tp_repr*/ nullptr,
96 /*tp_as_number*/ nullptr,
97 /*tp_as_sequence*/ nullptr,
98 /*tp_as_mapping*/ nullptr,
99 /*tp_hash*/ nullptr,
100 /*tp_call*/ nullptr,
101 /*tp_str*/ nullptr,
102 /*tp_getattro*/ nullptr,
103 /*tp_setattro*/ nullptr,
104 /*tp_as_buffer*/ nullptr,
105 /*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
106 /*tp_doc*/ nullptr,
107 /*tp_traverse*/ (traverseproc)bpy_rna_data_context_traverse,
108 /*tp_clear*/ (inquiry)bpy_rna_data_context_clear,
109 /*tp_richcompare*/ nullptr,
110 /*tp_weaklistoffset*/ 0,
111 /*tp_iter*/ nullptr,
112 /*tp_iternext*/ nullptr,
113 /*tp_methods*/ bpy_rna_data_context_methods,
114 /*tp_members*/ nullptr,
115 /*tp_getset*/ nullptr,
116 /*tp_base*/ nullptr,
117 /*tp_dict*/ nullptr,
118 /*tp_descr_get*/ nullptr,
119 /*tp_descr_set*/ nullptr,
120 /*tp_dictoffset*/ 0,
121 /*tp_init*/ nullptr,
122 /*tp_alloc*/ nullptr,
123 /*tp_new*/ nullptr,
124 /*tp_free*/ nullptr,
125 /*tp_is_gc*/ nullptr,
126 /*tp_bases*/ nullptr,
127 /*tp_mro*/ nullptr,
128 /*tp_cache*/ nullptr,
129 /*tp_subclasses*/ nullptr,
130 /*tp_weaklist*/ nullptr,
131 /*tp_del*/ nullptr,
132 /*tp_version_tag*/ 0,
133 /*tp_finalize*/ nullptr,
134 /*tp_vectorcall*/ nullptr,
135};
136
138 /* Wrap. */
139 bpy_rna_data_context_load_doc,
140 ".. method:: temp_data(filepath=None)\n"
141 "\n"
142 " A context manager that temporarily creates blender file data.\n"
143 "\n"
144 " :arg filepath: The file path for the newly temporary data. "
145 "When None, the path of the currently open file is used.\n"
146 " :type filepath: str | bytes | None\n"
147 "\n"
148 " :return: Blend file data which is freed once the context exists.\n"
149 " :rtype: :class:`bpy.types.BlendData`\n");
150
151static PyObject *bpy_rna_data_temp_data(PyObject * /*self*/, PyObject *args, PyObject *kw)
152{
153 PyC_UnicodeAsBytesAndSize_Data filepath_data = {nullptr};
155 static const char *_keywords[] = {"filepath", nullptr};
156 static _PyArg_Parser _parser = {
158 "|$" /* Optional keyword only arguments. */
159 "O&" /* `filepath` */
160 ":temp_data",
161 _keywords,
162 nullptr,
163 };
164 if (!_PyArg_ParseTupleAndKeywordsFast(
165 args, kw, &_parser, PyC_ParseUnicodeAsBytesAndSize_OrNone, &filepath_data))
166 {
167 return nullptr;
168 }
169
170 ret = PyObject_GC_New(BPy_DataContext, &bpy_rna_data_context_Type);
171
172 STRNCPY(ret->filepath, filepath_data.value ? filepath_data.value : G_MAIN->filepath);
173 Py_XDECREF(filepath_data.value_coerce);
174
175 return (PyObject *)ret;
176}
177
179{
180 Main *bmain_temp = BKE_main_new();
181 STRNCPY(bmain_temp->filepath, self->filepath);
182
183 PointerRNA ptr = RNA_pointer_create_discrete(nullptr, &RNA_BlendData, bmain_temp);
184
186
187 BLI_assert(!PyObject_GC_IsTracked((PyObject *)self));
188 PyObject_GC_Track(self);
189
190 return (PyObject *)self->data_rna;
191}
192
193static PyObject *bpy_rna_data_context_exit(BPy_DataContext *self, PyObject * /*args*/)
194{
195 BKE_main_free(static_cast<Main *>(self->data_rna->ptr->data));
196 self->data_rna->ptr->invalidate();
197 Py_RETURN_NONE;
198}
199
200#ifdef __GNUC__
201# ifdef __clang__
202# pragma clang diagnostic push
203# pragma clang diagnostic ignored "-Wcast-function-type"
204# else
205# pragma GCC diagnostic push
206# pragma GCC diagnostic ignored "-Wcast-function-type"
207# endif
208#endif
209
211 "temp_data",
212 (PyCFunction)bpy_rna_data_temp_data,
213 METH_STATIC | METH_VARARGS | METH_KEYWORDS,
214 bpy_rna_data_context_load_doc,
215};
216
217#ifdef __GNUC__
218# ifdef __clang__
219# pragma clang diagnostic pop
220# else
221# pragma GCC diagnostic pop
222# endif
223#endif
224
226{
227 if (PyType_Ready(&bpy_rna_data_context_Type) < 0) {
228 return -1;
229 }
230
231 return 0;
232}
#define G_MAIN
Main * BKE_main_new()
Definition main.cc:48
void BKE_main_free(Main *bmain)
Definition main.cc:175
#define BLI_assert(a)
Definition BLI_assert.h:46
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
PyObject * self
PyObject * pyrna_struct_CreatePyObject(PointerRNA *ptr)
Definition bpy_rna.cc:8384
int BPY_rna_data_context_type_ready()
static PyObject * bpy_rna_data_context_enter(BPy_DataContext *self)
static int bpy_rna_data_context_clear(BPy_DataContext *self)
static PyTypeObject bpy_rna_data_context_Type
PyDoc_STRVAR(bpy_rna_data_context_load_doc, ".. method:: temp_data(filepath=None)\n" "\n" " A context manager that temporarily creates blender file data.\n" "\n" " :arg filepath: The file path for the newly temporary data. " "When None, the path of the currently open file is used.\n" " :type filepath: str | bytes | None\n" "\n" " :return: Blend file data which is freed once the context exists.\n" " :rtype: :class:`bpy.types.BlendData`\n")
static PyObject * bpy_rna_data_context_exit(BPy_DataContext *self, PyObject *args)
static int bpy_rna_data_context_traverse(BPy_DataContext *self, visitproc visit, void *arg)
PyMethodDef BPY_rna_data_context_method_def
static PyObject * bpy_rna_data_temp_data(PyObject *self, PyObject *args, PyObject *kw)
static void bpy_rna_data_context_dealloc(BPy_DataContext *self)
static PyMethodDef bpy_rna_data_context_methods[]
int PyC_ParseUnicodeAsBytesAndSize_OrNone(PyObject *o, void *p)
header-only compatibility defines.
#define PY_ARG_PARSER_HEAD_COMPAT()
return ret
PointerRNA RNA_pointer_create_discrete(ID *id, StructRNA *type, void *data)
char filepath[1024]
PyObject_HEAD BPy_StructRNA * data_rna
char filepath[1024]
Definition BKE_main.hh:155
PointerRNA * ptr
Definition wm_files.cc:4226