Fix non UTF8 paths for Python functions which take path arguments
Use PyC_ParseUnicodeAsBytesAndSize parser instead of "s" / "z" type specifier. This relates to #111033, resolving Python exceptions which causes icons not to load (for e.g.). Now bytes are also supported as path arguments.
This commit is contained in:
@@ -12,6 +12,9 @@
|
||||
#define PY_SSIZE_T_CLEAN
|
||||
|
||||
#include "blf_py_api.h"
|
||||
|
||||
#include "../generic/py_capi_utils.h"
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#include "../../blenfont/BLF_api.h"
|
||||
@@ -402,18 +405,24 @@ PyDoc_STRVAR(py_blf_load_doc,
|
||||
" Load a new font.\n"
|
||||
"\n"
|
||||
" :arg filepath: the filepath of the font.\n"
|
||||
" :type filepath: string\n"
|
||||
" :type filepath: string or bytes\n"
|
||||
" :return: the new font's fontid or -1 if there was an error.\n"
|
||||
" :rtype: integer\n");
|
||||
static PyObject *py_blf_load(PyObject * /*self*/, PyObject *args)
|
||||
{
|
||||
const char *filepath;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s:blf.load", &filepath)) {
|
||||
PyC_UnicodeAsBytesAndSize_Data filepath_data = {nullptr};
|
||||
if (!PyArg_ParseTuple(args,
|
||||
"O&" /* `filepath` */
|
||||
":blf.load",
|
||||
PyC_ParseUnicodeAsBytesAndSize,
|
||||
&filepath_data))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
const int font_id = BLF_load(filepath_data.value);
|
||||
Py_XDECREF(filepath_data.value_coerce);
|
||||
|
||||
return PyLong_FromLong(BLF_load(filepath));
|
||||
return PyLong_FromLong(font_id);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(py_blf_unload_doc,
|
||||
@@ -422,16 +431,21 @@ PyDoc_STRVAR(py_blf_unload_doc,
|
||||
" Unload an existing font.\n"
|
||||
"\n"
|
||||
" :arg filepath: the filepath of the font.\n"
|
||||
" :type filepath: string\n");
|
||||
" :type filepath: string or bytes\n");
|
||||
static PyObject *py_blf_unload(PyObject * /*self*/, PyObject *args)
|
||||
{
|
||||
const char *filepath;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s:blf.unload", &filepath)) {
|
||||
PyC_UnicodeAsBytesAndSize_Data filepath_data = {nullptr};
|
||||
if (!PyArg_ParseTuple(args,
|
||||
"O&" /* `filepath` */
|
||||
":blf.unload",
|
||||
PyC_ParseUnicodeAsBytesAndSize,
|
||||
&filepath_data))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BLF_unload(filepath);
|
||||
BLF_unload(filepath_data.value);
|
||||
Py_XDECREF(filepath_data.value_coerce);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
@@ -467,30 +467,8 @@ static PyObject *M_imbuf_new(PyObject * /*self*/, PyObject *args, PyObject *kw)
|
||||
return Py_ImBuf_CreatePyObject(ibuf);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_imbuf_load_doc,
|
||||
".. function:: load(filepath)\n"
|
||||
"\n"
|
||||
" Load an image from a file.\n"
|
||||
"\n"
|
||||
" :arg filepath: the filepath of the image.\n"
|
||||
" :type filepath: string\n"
|
||||
" :return: the newly loaded image.\n"
|
||||
" :rtype: :class:`ImBuf`\n");
|
||||
static PyObject *M_imbuf_load(PyObject * /*self*/, PyObject *args, PyObject *kw)
|
||||
static PyObject *imbuf_load_impl(const char *filepath)
|
||||
{
|
||||
const char *filepath;
|
||||
|
||||
static const char *_keywords[] = {"filepath", nullptr};
|
||||
static _PyArg_Parser _parser = {
|
||||
"s" /* `filepath` */
|
||||
":load",
|
||||
_keywords,
|
||||
nullptr,
|
||||
};
|
||||
if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &filepath)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const int file = BLI_open(filepath, O_BINARY | O_RDONLY, 0);
|
||||
if (file == -1) {
|
||||
PyErr_Format(PyExc_IOError, "load: %s, failed to open file '%s'", strerror(errno), filepath);
|
||||
@@ -512,6 +490,48 @@ static PyObject *M_imbuf_load(PyObject * /*self*/, PyObject *args, PyObject *kw)
|
||||
return Py_ImBuf_CreatePyObject(ibuf);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(M_imbuf_load_doc,
|
||||
".. function:: load(filepath)\n"
|
||||
"\n"
|
||||
" Load an image from a file.\n"
|
||||
"\n"
|
||||
" :arg filepath: the filepath of the image.\n"
|
||||
" :type filepath: string or bytes\n"
|
||||
" :return: the newly loaded image.\n"
|
||||
" :rtype: :class:`ImBuf`\n");
|
||||
static PyObject *M_imbuf_load(PyObject * /*self*/, PyObject *args, PyObject *kw)
|
||||
{
|
||||
PyC_UnicodeAsBytesAndSize_Data filepath_data = {nullptr};
|
||||
|
||||
static const char *_keywords[] = {"filepath", nullptr};
|
||||
static _PyArg_Parser _parser = {
|
||||
"O&" /* `filepath` */
|
||||
":load",
|
||||
_keywords,
|
||||
nullptr,
|
||||
};
|
||||
if (!_PyArg_ParseTupleAndKeywordsFast(
|
||||
args, kw, &_parser, PyC_ParseUnicodeAsBytesAndSize, &filepath_data))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
PyObject *result = imbuf_load_impl(filepath_data.value);
|
||||
Py_XDECREF(filepath_data.value_coerce);
|
||||
return result;
|
||||
}
|
||||
|
||||
static PyObject *imbuf_write_impl(ImBuf *ibuf, const char *filepath)
|
||||
{
|
||||
const bool ok = IMB_saveiff(ibuf, filepath, IB_rect);
|
||||
if (ok == false) {
|
||||
PyErr_Format(
|
||||
PyExc_IOError, "write: Unable to write image file (%s) '%s'", strerror(errno), filepath);
|
||||
return nullptr;
|
||||
}
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(
|
||||
M_imbuf_write_doc,
|
||||
".. function:: write(image, filepath=image.filepath)\n"
|
||||
@@ -521,37 +541,40 @@ PyDoc_STRVAR(
|
||||
" :arg image: the image to write.\n"
|
||||
" :type image: :class:`ImBuf`\n"
|
||||
" :arg filepath: Optional filepath of the image (fallback to the images file path).\n"
|
||||
" :type filepath: string\n");
|
||||
" :type filepath: string or bytes\n");
|
||||
static PyObject *M_imbuf_write(PyObject * /*self*/, PyObject *args, PyObject *kw)
|
||||
{
|
||||
Py_ImBuf *py_imb;
|
||||
const char *filepath = nullptr;
|
||||
PyC_UnicodeAsBytesAndSize_Data filepath_data = {nullptr};
|
||||
|
||||
static const char *_keywords[] = {"image", "filepath", nullptr};
|
||||
static _PyArg_Parser _parser = {
|
||||
"O!" /* `image` */
|
||||
"|$" /* Optional keyword only arguments. */
|
||||
"s" /* `filepath` */
|
||||
"O&" /* `filepath` */
|
||||
":write",
|
||||
_keywords,
|
||||
nullptr,
|
||||
};
|
||||
if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &Py_ImBuf_Type, &py_imb, &filepath)) {
|
||||
if (!_PyArg_ParseTupleAndKeywordsFast(args,
|
||||
kw,
|
||||
&_parser,
|
||||
&Py_ImBuf_Type,
|
||||
&py_imb,
|
||||
PyC_ParseUnicodeAsBytesAndSize,
|
||||
&filepath_data))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char *filepath = filepath_data.value;
|
||||
if (filepath == nullptr) {
|
||||
/* Argument omitted, use images path. */
|
||||
filepath = py_imb->ibuf->filepath;
|
||||
}
|
||||
|
||||
const bool ok = IMB_saveiff(py_imb->ibuf, filepath, IB_rect);
|
||||
if (ok == false) {
|
||||
PyErr_Format(
|
||||
PyExc_IOError, "write: Unable to write image file (%s) '%s'", strerror(errno), filepath);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Py_RETURN_NONE;
|
||||
PyObject *result = imbuf_write_impl(py_imb->ibuf, filepath);
|
||||
Py_XDECREF(filepath_data.value_coerce);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
@@ -221,27 +221,32 @@ static PyObject *bpy_user_resource(PyObject * /*self*/, PyObject *args, PyObject
|
||||
{0, nullptr},
|
||||
};
|
||||
PyC_StringEnum type = {type_items};
|
||||
|
||||
const char *subdir = nullptr;
|
||||
|
||||
const char *path;
|
||||
PyC_UnicodeAsBytesAndSize_Data subdir_data = {nullptr};
|
||||
|
||||
static const char *_keywords[] = {"type", "path", nullptr};
|
||||
static _PyArg_Parser _parser = {
|
||||
"O&" /* `type` */
|
||||
"|$" /* Optional keyword only arguments. */
|
||||
"s" /* `path` */
|
||||
"O&" /* `path` */
|
||||
":user_resource",
|
||||
_keywords,
|
||||
nullptr,
|
||||
};
|
||||
if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, PyC_ParseStringEnum, &type, &subdir)) {
|
||||
if (!_PyArg_ParseTupleAndKeywordsFast(args,
|
||||
kw,
|
||||
&_parser,
|
||||
PyC_ParseStringEnum,
|
||||
&type,
|
||||
PyC_ParseUnicodeAsBytesAndSize,
|
||||
&subdir_data))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* same logic as BKE_appdir_folder_id_create(),
|
||||
* but best leave it up to the script author to create */
|
||||
path = BKE_appdir_folder_id_user_notest(type.value_found, subdir);
|
||||
const char *path = BKE_appdir_folder_id_user_notest(type.value_found, subdir_data.value);
|
||||
Py_XDECREF(subdir_data.value_coerce);
|
||||
|
||||
return PyC_UnicodeFromBytes(path ? path : "");
|
||||
}
|
||||
@@ -254,7 +259,7 @@ PyDoc_STRVAR(bpy_system_resource_doc,
|
||||
" :arg type: string in ['DATAFILES', 'SCRIPTS', 'PYTHON'].\n"
|
||||
" :type type: string\n"
|
||||
" :arg path: Optional subdirectory.\n"
|
||||
" :type path: string\n");
|
||||
" :type path: string or bytes\n");
|
||||
static PyObject *bpy_system_resource(PyObject * /*self*/, PyObject *args, PyObject *kw)
|
||||
{
|
||||
const PyC_StringEnumItems type_items[] = {
|
||||
@@ -265,24 +270,30 @@ static PyObject *bpy_system_resource(PyObject * /*self*/, PyObject *args, PyObje
|
||||
};
|
||||
PyC_StringEnum type = {type_items};
|
||||
|
||||
const char *subdir = nullptr;
|
||||
|
||||
const char *path;
|
||||
PyC_UnicodeAsBytesAndSize_Data subdir_data = {nullptr};
|
||||
|
||||
static const char *_keywords[] = {"type", "path", nullptr};
|
||||
static _PyArg_Parser _parser = {
|
||||
"O&" /* `type` */
|
||||
"|$" /* Optional keyword only arguments. */
|
||||
"s" /* `path` */
|
||||
"O&" /* `path` */
|
||||
":system_resource",
|
||||
_keywords,
|
||||
nullptr,
|
||||
};
|
||||
if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, PyC_ParseStringEnum, &type, &subdir)) {
|
||||
if (!_PyArg_ParseTupleAndKeywordsFast(args,
|
||||
kw,
|
||||
&_parser,
|
||||
PyC_ParseStringEnum,
|
||||
&type,
|
||||
PyC_ParseUnicodeAsBytesAndSize,
|
||||
&subdir_data))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
path = BKE_appdir_folder_id(type.value_found, subdir);
|
||||
const char *path = BKE_appdir_folder_id(type.value_found, subdir_data.value);
|
||||
Py_XDECREF(subdir_data.value_coerce);
|
||||
|
||||
return PyC_UnicodeFromBytes(path ? path : "");
|
||||
}
|
||||
|
||||
@@ -92,28 +92,31 @@ PyDoc_STRVAR(bpy_app_icons_new_triangles_from_file_doc,
|
||||
" Create a new icon from triangle geometry.\n"
|
||||
"\n"
|
||||
" :arg filepath: File path.\n"
|
||||
" :type filepath: string.\n"
|
||||
" :type filepath: string or bytes.\n"
|
||||
" :return: Unique icon value (pass to interface ``icon_value`` argument).\n"
|
||||
" :rtype: int\n");
|
||||
static PyObject *bpy_app_icons_new_triangles_from_file(PyObject * /*self*/,
|
||||
PyObject *args,
|
||||
PyObject *kw)
|
||||
{
|
||||
/* bytes */
|
||||
char *filepath;
|
||||
PyC_UnicodeAsBytesAndSize_Data filepath_data = {nullptr};
|
||||
|
||||
static const char *_keywords[] = {"filepath", nullptr};
|
||||
static _PyArg_Parser _parser = {
|
||||
"s" /* `filepath` */
|
||||
"O&" /* `filepath` */
|
||||
":new_triangles_from_file",
|
||||
_keywords,
|
||||
nullptr,
|
||||
};
|
||||
if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &filepath)) {
|
||||
if (!_PyArg_ParseTupleAndKeywordsFast(
|
||||
args, kw, &_parser, PyC_ParseUnicodeAsBytesAndSize, &filepath_data))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Icon_Geom *geom = BKE_icon_geom_from_file(filepath);
|
||||
Icon_Geom *geom = BKE_icon_geom_from_file(filepath_data.value);
|
||||
Py_XDECREF(filepath_data.value_coerce);
|
||||
|
||||
if (geom == nullptr) {
|
||||
PyErr_SetString(PyExc_ValueError, "Unable to load from file");
|
||||
return nullptr;
|
||||
|
||||
@@ -165,7 +165,7 @@ PyDoc_STRVAR(
|
||||
" Each object has attributes matching bpy.data which are lists of strings to be linked.\n"
|
||||
"\n"
|
||||
" :arg filepath: The path to a blend file.\n"
|
||||
" :type filepath: string\n"
|
||||
" :type filepath: string or bytes\n"
|
||||
" :arg link: When False reference to the original file is lost.\n"
|
||||
" :type link: bool\n"
|
||||
" :arg relative: When True the path is stored relative to the open blend file.\n"
|
||||
@@ -186,7 +186,7 @@ static PyObject *bpy_lib_load(BPy_PropertyRNA *self, PyObject *args, PyObject *k
|
||||
Main *bmain_base = CTX_data_main(BPY_context_get());
|
||||
Main *bmain = static_cast<Main *>(self->ptr.data); /* Typically #G_MAIN */
|
||||
BPy_Library *ret;
|
||||
const char *filepath = nullptr;
|
||||
PyC_UnicodeAsBytesAndSize_Data filepath_data = {nullptr};
|
||||
bool is_rel = false, is_link = false, use_assets_only = false;
|
||||
bool create_liboverrides = false, reuse_liboverrides = false,
|
||||
create_liboverrides_runtime = false;
|
||||
@@ -202,7 +202,7 @@ static PyObject *bpy_lib_load(BPy_PropertyRNA *self, PyObject *args, PyObject *k
|
||||
nullptr,
|
||||
};
|
||||
static _PyArg_Parser _parser = {
|
||||
"s" /* `filepath` */
|
||||
"O&" /* `filepath` */
|
||||
/* Optional keyword only arguments. */
|
||||
"|$"
|
||||
"O&" /* `link` */
|
||||
@@ -218,7 +218,8 @@ static PyObject *bpy_lib_load(BPy_PropertyRNA *self, PyObject *args, PyObject *k
|
||||
if (!_PyArg_ParseTupleAndKeywordsFast(args,
|
||||
kw,
|
||||
&_parser,
|
||||
&filepath,
|
||||
PyC_ParseUnicodeAsBytesAndSize,
|
||||
&filepath_data,
|
||||
PyC_ParseBool,
|
||||
&is_link,
|
||||
PyC_ParseBool,
|
||||
@@ -252,8 +253,10 @@ static PyObject *bpy_lib_load(BPy_PropertyRNA *self, PyObject *args, PyObject *k
|
||||
|
||||
ret = PyObject_New(BPy_Library, &bpy_lib_Type);
|
||||
|
||||
STRNCPY(ret->relpath, filepath);
|
||||
STRNCPY(ret->abspath, filepath);
|
||||
STRNCPY(ret->relpath, filepath_data.value);
|
||||
Py_XDECREF(filepath_data.value_coerce);
|
||||
|
||||
STRNCPY(ret->abspath, ret->relpath);
|
||||
BLI_path_abs(ret->abspath, BKE_main_blendfile_path(bmain));
|
||||
|
||||
ret->bmain = bmain;
|
||||
|
||||
@@ -44,7 +44,7 @@ PyDoc_STRVAR(
|
||||
" Indirectly referenced data-blocks will be expanded and written too.\n"
|
||||
"\n"
|
||||
" :arg filepath: The path to write the blend-file.\n"
|
||||
" :type filepath: string\n"
|
||||
" :type filepath: string or bytes\n"
|
||||
" :arg datablocks: set of data-blocks (:class:`bpy.types.ID` instances).\n"
|
||||
" :type datablocks: set\n"
|
||||
" :arg path_remap: Optionally remap paths when writing the file:\n"
|
||||
@@ -62,7 +62,7 @@ PyDoc_STRVAR(
|
||||
static PyObject *bpy_lib_write(BPy_PropertyRNA *self, PyObject *args, PyObject *kw)
|
||||
{
|
||||
/* args */
|
||||
const char *filepath;
|
||||
PyC_UnicodeAsBytesAndSize_Data filepath_data = {nullptr};
|
||||
char filepath_abs[FILE_MAX];
|
||||
PyObject *datablocks = nullptr;
|
||||
|
||||
@@ -86,7 +86,7 @@ static PyObject *bpy_lib_write(BPy_PropertyRNA *self, PyObject *args, PyObject *
|
||||
nullptr,
|
||||
};
|
||||
static _PyArg_Parser _parser = {
|
||||
"s" /* `filepath` */
|
||||
"O&" /* `filepath` */
|
||||
"O!" /* `datablocks` */
|
||||
"|$" /* Optional keyword only arguments. */
|
||||
"O&" /* `path_remap` */
|
||||
@@ -99,7 +99,8 @@ static PyObject *bpy_lib_write(BPy_PropertyRNA *self, PyObject *args, PyObject *
|
||||
if (!_PyArg_ParseTupleAndKeywordsFast(args,
|
||||
kw,
|
||||
&_parser,
|
||||
&filepath,
|
||||
PyC_ParseUnicodeAsBytesAndSize,
|
||||
&filepath_data,
|
||||
&PySet_Type,
|
||||
&datablocks,
|
||||
PyC_ParseStringEnum,
|
||||
@@ -119,7 +120,9 @@ static PyObject *bpy_lib_write(BPy_PropertyRNA *self, PyObject *args, PyObject *
|
||||
write_flags |= G_FILE_COMPRESS;
|
||||
}
|
||||
|
||||
STRNCPY(filepath_abs, filepath);
|
||||
STRNCPY(filepath_abs, filepath_data.value);
|
||||
Py_XDECREF(filepath_data.value_coerce);
|
||||
|
||||
BLI_path_abs(filepath_abs, BKE_main_blendfile_path_from_global());
|
||||
|
||||
BKE_blendfile_write_partial_begin(bmain_src);
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
#include <Python.h>
|
||||
#include <cstddef>
|
||||
|
||||
#include "../generic/py_capi_utils.h"
|
||||
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
@@ -130,30 +132,33 @@ PyDoc_STRVAR(bpy_rna_data_context_load_doc,
|
||||
"\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 or NoneType\n"
|
||||
" :type filepath: str, bytes or NoneType\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_temp_data(PyObject * /*self*/, PyObject *args, PyObject *kw)
|
||||
{
|
||||
PyC_UnicodeAsBytesAndSize_Data filepath_data = {nullptr};
|
||||
BPy_DataContext *ret;
|
||||
const char *filepath = nullptr;
|
||||
static const char *_keywords[] = {"filepath", nullptr};
|
||||
static _PyArg_Parser _parser = {
|
||||
"|$" /* Optional keyword only arguments. */
|
||||
"z" /* `filepath` */
|
||||
"O&" /* `filepath` */
|
||||
":temp_data",
|
||||
_keywords,
|
||||
nullptr,
|
||||
};
|
||||
if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &filepath)) {
|
||||
if (!_PyArg_ParseTupleAndKeywordsFast(
|
||||
args, kw, &_parser, PyC_ParseUnicodeAsBytesAndSize_OrNone, &filepath_data))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ret = PyObject_GC_New(BPy_DataContext, &bpy_rna_data_context_Type);
|
||||
|
||||
STRNCPY(ret->filepath, filepath ? filepath : G_MAIN->filepath);
|
||||
STRNCPY(ret->filepath, filepath_data.value ? filepath_data.value : G_MAIN->filepath);
|
||||
Py_XDECREF(filepath_data.value_coerce);
|
||||
|
||||
return (PyObject *)ret;
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ PyDoc_STRVAR(
|
||||
" :arg name: The name (unique id) identifying the preview.\n"
|
||||
" :type name: string\n"
|
||||
" :arg filepath: The file path to generate the preview from.\n"
|
||||
" :type filepath: string\n"
|
||||
" :type filepath: string or bytes\n"
|
||||
" :arg filetype: The type of file, needed to generate the preview in [" STR_SOURCE_TYPES
|
||||
"].\n"
|
||||
" :type filetype: string\n"
|
||||
@@ -92,7 +92,8 @@ PyDoc_STRVAR(
|
||||
" :raises KeyError: if ``name`` already exists.");
|
||||
static PyObject *bpy_utils_previews_load(PyObject * /*self*/, PyObject *args)
|
||||
{
|
||||
char *name, *filepath;
|
||||
char *name;
|
||||
PyC_UnicodeAsBytesAndSize_Data filepath_data = {nullptr};
|
||||
const PyC_StringEnumItems path_type_items[] = {
|
||||
{THB_SOURCE_IMAGE, "IMAGE"},
|
||||
{THB_SOURCE_MOVIE, "MOVIE"},
|
||||
@@ -110,13 +111,14 @@ static PyObject *bpy_utils_previews_load(PyObject * /*self*/, PyObject *args)
|
||||
|
||||
if (!PyArg_ParseTuple(args,
|
||||
"s" /* `name` */
|
||||
"s" /* `filepath` */
|
||||
"O&" /* `filepath` */
|
||||
"O&" /* `filetype` */
|
||||
"|" /* Optional arguments. */
|
||||
"p" /* `force_reload` */
|
||||
":load",
|
||||
&name,
|
||||
&filepath,
|
||||
PyC_ParseUnicodeAsBytesAndSize,
|
||||
&filepath_data,
|
||||
PyC_ParseStringEnum,
|
||||
&path_type,
|
||||
&force_reload))
|
||||
@@ -125,7 +127,10 @@ static PyObject *bpy_utils_previews_load(PyObject * /*self*/, PyObject *args)
|
||||
}
|
||||
|
||||
PreviewImage *prv = BKE_previewimg_cached_thumbnail_read(
|
||||
name, filepath, path_type.value_found, force_reload);
|
||||
name, filepath_data.value, path_type.value_found, force_reload);
|
||||
|
||||
Py_XDECREF(filepath_data.value_coerce);
|
||||
|
||||
PointerRNA ptr;
|
||||
RNA_pointer_create(nullptr, &RNA_ImagePreview, prv, &ptr);
|
||||
return pyrna_struct_CreatePyObject(&ptr);
|
||||
|
||||
Reference in New Issue
Block a user