Blender V5.0
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");
150static PyObject *bpy_rna_data_temp_data(PyObject * /*self*/, PyObject *args, PyObject *kw)
151{
152 PyC_UnicodeAsBytesAndSize_Data filepath_data = {nullptr};
154 static const char *_keywords[] = {"filepath", nullptr};
155 static _PyArg_Parser _parser = {
157 "|$" /* Optional keyword only arguments. */
158 "O&" /* `filepath` */
159 ":temp_data",
160 _keywords,
161 nullptr,
162 };
163 if (!_PyArg_ParseTupleAndKeywordsFast(
164 args, kw, &_parser, PyC_ParseUnicodeAsBytesAndSize_OrNone, &filepath_data))
165 {
166 return nullptr;
167 }
168
169 ret = PyObject_GC_New(BPy_DataContext, &bpy_rna_data_context_Type);
170
171 STRNCPY(ret->filepath, filepath_data.value ? filepath_data.value : G_MAIN->filepath);
172 Py_XDECREF(filepath_data.value_coerce);
173
174 return (PyObject *)ret;
175}
176
178{
179 Main *bmain_temp = BKE_main_new();
180 STRNCPY(bmain_temp->filepath, self->filepath);
181
182 PointerRNA ptr = RNA_pointer_create_discrete(nullptr, &RNA_BlendData, bmain_temp);
183
185
186 BLI_assert(!PyObject_GC_IsTracked((PyObject *)self));
187 PyObject_GC_Track(self);
188
189 return (PyObject *)self->data_rna;
190}
191
192static PyObject *bpy_rna_data_context_exit(BPy_DataContext *self, PyObject * /*args*/)
193{
194 BKE_main_free(static_cast<Main *>(self->data_rna->ptr->data));
195 self->data_rna->ptr->invalidate();
196 Py_RETURN_NONE;
197}
198
199#ifdef __GNUC__
200# ifdef __clang__
201# pragma clang diagnostic push
202# pragma clang diagnostic ignored "-Wcast-function-type"
203# else
204# pragma GCC diagnostic push
205# pragma GCC diagnostic ignored "-Wcast-function-type"
206# endif
207#endif
208
210 "temp_data",
211 (PyCFunction)bpy_rna_data_temp_data,
212 METH_STATIC | METH_VARARGS | METH_KEYWORDS,
213 bpy_rna_data_context_load_doc,
214};
215
216#ifdef __GNUC__
217# ifdef __clang__
218# pragma clang diagnostic pop
219# else
220# pragma GCC diagnostic pop
221# endif
222#endif
223
225{
226 if (PyType_Ready(&bpy_rna_data_context_Type) < 0) {
227 return -1;
228 }
229
230 return 0;
231}
#define G_MAIN
Main * BKE_main_new()
Definition main.cc:89
void BKE_main_free(Main *bmain)
Definition main.cc:192
#define BLI_assert(a)
Definition BLI_assert.h:46
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:693
PyObject * self
PyObject * pyrna_struct_CreatePyObject(PointerRNA *ptr)
Definition bpy_rna.cc:8496
int BPY_rna_data_context_type_ready()
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_enter(BPy_DataContext *self)
static int bpy_rna_data_context_clear(BPy_DataContext *self)
static PyTypeObject bpy_rna_data_context_Type
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:179
PointerRNA * ptr
Definition wm_files.cc:4238