bytestring support for py/rna - this is so py can access data which
authorCampbell Barton <ideasman42@gmail.com>
Tue, 15 Nov 2011 07:09:41 +0000 (07:09 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 15 Nov 2011 07:09:41 +0000 (07:09 +0000)
isn't meant to be accessed as unicode text.

source/blender/editors/interface/interface_handlers.c
source/blender/makesrna/RNA_types.h
source/blender/makesrna/intern/makesrna.c
source/blender/python/intern/bpy_props.c
source/blender/python/intern/bpy_rna.c

index ee1f96178137023ea56bf24fa58ee0a25a9aa62b..688e8f95ac780669166c3d8f2edc3b08b2ca3f60 100644 (file)
@@ -271,7 +271,7 @@ int ui_is_but_utf8(uiBut *but)
 {
        if (but->rnaprop) {
                const int subtype= RNA_property_subtype(but->rnaprop);
-               return !(ELEM3(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME));
+               return !(ELEM4(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME, PROP_BYTESTRING));
        }
        else {
                return !(but->flag & UI_BUT_NO_UTF8);
index 1655665efe3736d5e4b3b4e36ec5fc4197a3f4fc..e768594fe7314c0d265e7606bb069a9808e34e42 100644 (file)
@@ -108,7 +108,9 @@ typedef enum PropertySubType {
        PROP_FILEPATH = 1,
        PROP_DIRPATH = 2,
        PROP_FILENAME = 3,
-       PROP_TRANSLATE = 4, /* a string which should be translated */
+       PROP_BYTESTRING = 4, /* a string which should be represented as bytes
+                             * in python, still NULL terminated though. */
+       PROP_TRANSLATE = 5, /* a string which should be translated */
 
        /* numbers */
        PROP_UNSIGNED = 13,
index 1eaeaf8278fd2ae3c716d9a3f3454173e07d0d2a..a3054b889605457bcfed1790f048b6280e9d74e6 100644 (file)
@@ -1816,6 +1816,7 @@ static const char *rna_property_subtypename(PropertySubType type)
                case PROP_FILEPATH: return "PROP_FILEPATH";
                case PROP_FILENAME: return "PROP_FILENAME";
                case PROP_DIRPATH: return "PROP_DIRPATH";
+               case PROP_BYTESTRING: return "PROP_BYTESTRING";
                case PROP_TRANSLATE: return "PROP_TRANSLATE";
                case PROP_UNSIGNED: return "PROP_UNSIGNED";
                case PROP_PERCENTAGE: return "PROP_PERCENTAGE";
index 2b71cdd4ffcbc581ae1e927f5fe36bc498522638..950aa9458d5fb9d80a0c74f3b3484adbf54b17cb 100644 (file)
@@ -74,6 +74,7 @@ static EnumPropertyItem property_subtype_string_items[]= {
        {PROP_FILEPATH, "FILE_PATH", 0, "File Path", ""},
        {PROP_DIRPATH, "DIR_PATH", 0, "Directory Path", ""},
        {PROP_FILENAME, "FILENAME", 0, "Filename", ""},
+       {PROP_BYTESTRING, "BYTE_STRING", 0, "Byte String", ""},
        {PROP_TRANSLATE, "TRANSLATE", 0, "Translate", ""},
 
        {PROP_NONE, "NONE", 0, "None", ""},
index 15a9ba44552ee03092851640d264cbbffbd2b81b..5ac83b8bf796f3ce5fff63033895cf1f83e04a40 100644 (file)
@@ -1328,14 +1328,22 @@ PyObject *pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop)
                buf= RNA_property_string_get_alloc(ptr, prop, buf_fixed, sizeof(buf_fixed), &buf_len);
 #ifdef USE_STRING_COERCE
                /* only file paths get special treatment, they may contain non utf-8 chars */
-               if (ELEM3(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) {
+               if (subtype == PROP_BYTESTRING) {
+                       ret= PyBytes_FromStringAndSize(buf, buf_len);
+               }
+               else if (ELEM3(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) {
                        ret= PyC_UnicodeFromByteAndSize(buf, buf_len);
                }
                else {
                        ret= PyUnicode_FromStringAndSize(buf, buf_len);
                }
 #else // USE_STRING_COERCE
-               ret= PyUnicode_FromStringAndSize(buf, buf_len);
+               if (subtype == PROP_BYTESTRING) {
+                       ret= PyBytes_FromStringAndSize(buf, buf_len);
+               }
+               else {
+                       ret= PyUnicode_FromStringAndSize(buf, buf_len);
+               }
 #endif // USE_STRING_COERCE
                if (buf_fixed != buf) {
                        MEM_freeN((void *)buf);
@@ -1534,53 +1542,91 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb
                }
                case PROP_STRING:
                {
-                       const char *param;
-#ifdef USE_STRING_COERCE
-                       PyObject *value_coerce= NULL;
                        int subtype= RNA_property_subtype(prop);
-                       if (ELEM3(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) {
-                               /* TODO, get size */
-                               param= PyC_UnicodeAsByte(value, &value_coerce);
+                       const char *param;
+
+                       if (subtype == PROP_BYTESTRING) {
+
+                               /* Byte String */
+
+                               param= PyBytes_AsString(value);
+
+                               if (param==NULL) {
+                                       if (PyBytes_Check(value)) {
+                                               /* there was an error assigning a string type,
+                                                * rather than setting a new error, prefix the existing one
+                                                */
+                                               PyC_Err_Format_Prefix(PyExc_TypeError,
+                                                                     "%.200s %.200s.%.200s error assigning bytes",
+                                                                     error_prefix, RNA_struct_identifier(ptr->type),
+                                                                     RNA_property_identifier(prop));
+                                       }
+                                       else {
+                                               PyErr_Format(PyExc_TypeError,
+                                                            "%.200s %.200s.%.200s expected a bytes type, not %.200s",
+                                                            error_prefix, RNA_struct_identifier(ptr->type),
+                                                            RNA_property_identifier(prop), Py_TYPE(value)->tp_name);
+                                       }
+
+                                       return -1;
+                               }
+                               else {
+                                       /* same as unicode */
+                                       if (data)   *((char**)data)= (char *)param; /*XXX, this is suspect but needed for function calls, need to see if theres a better way */
+                                       else        RNA_property_string_set(ptr, prop, param);
+                               }
                        }
                        else {
-                               param= _PyUnicode_AsString(value);
-#ifdef WITH_INTERNATIONAL
-                               if (subtype == PROP_TRANSLATE) {
-                                       param= IFACE_(param);
+
+                               /* Unicode String */
+
+#ifdef USE_STRING_COERCE
+                               PyObject *value_coerce= NULL;
+                               if (ELEM3(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) {
+                                       /* TODO, get size */
+                                       param= PyC_UnicodeAsByte(value, &value_coerce);
                                }
+                               else {
+                                       param= _PyUnicode_AsString(value);
+#ifdef WITH_INTERNATIONAL
+                                       if (subtype == PROP_TRANSLATE) {
+                                               param= IFACE_(param);
+                                       }
 #endif // WITH_INTERNATIONAL
 
-                       }
+                               }
 #else // USE_STRING_COERCE
-                       param= _PyUnicode_AsString(value);
+                               param= _PyUnicode_AsString(value);
 #endif // USE_STRING_COERCE
 
-                       if (param==NULL) {
-                               if (PyUnicode_Check(value)) {
-                                       /* there was an error assigning a string type,
-                                        * rather than setting a new error, prefix the existing one
-                                        */
-                                       PyC_Err_Format_Prefix(PyExc_TypeError,
-                                                             "%.200s %.200s.%.200s error assigning string",
-                                                                                 error_prefix, RNA_struct_identifier(ptr->type),
-                                                                                 RNA_property_identifier(prop));
+                               if (param==NULL) {
+                                       if (PyUnicode_Check(value)) {
+                                               /* there was an error assigning a string type,
+                                                * rather than setting a new error, prefix the existing one
+                                                */
+                                               PyC_Err_Format_Prefix(PyExc_TypeError,
+                                                                     "%.200s %.200s.%.200s error assigning string",
+                                                                     error_prefix, RNA_struct_identifier(ptr->type),
+                                                                     RNA_property_identifier(prop));
+                                       }
+                                       else {
+                                               PyErr_Format(PyExc_TypeError,
+                                                            "%.200s %.200s.%.200s expected a string type, not %.200s",
+                                                            error_prefix, RNA_struct_identifier(ptr->type),
+                                                            RNA_property_identifier(prop), Py_TYPE(value)->tp_name);
+                                       }
+
+                                       return -1;
                                }
                                else {
-                                       PyErr_Format(PyExc_TypeError,
-                                                                "%.200s %.200s.%.200s expected a string type, not %.200s",
-                                                                error_prefix, RNA_struct_identifier(ptr->type),
-                                                                RNA_property_identifier(prop), Py_TYPE(value)->tp_name);
+                                       /* same as bytes */
+                                       if (data)   *((char**)data)= (char *)param; /*XXX, this is suspect but needed for function calls, need to see if theres a better way */
+                                       else        RNA_property_string_set(ptr, prop, param);
                                }
-
-                               return -1;
-                       }
-                       else {
-                               if (data)   *((char**)data)= (char *)param; /*XXX, this is suspect but needed for function calls, need to see if theres a better way */
-                               else        RNA_property_string_set(ptr, prop, param);
-                       }
 #ifdef USE_STRING_COERCE
-                       Py_XDECREF(value_coerce);
+                               Py_XDECREF(value_coerce);
 #endif // USE_STRING_COERCE
+                       }
                        break;
                }
                case PROP_ENUM:
@@ -2751,7 +2797,7 @@ static int pyrna_struct_ass_subscript(BPy_StructRNA *self, PyObject *key, PyObje
        if (rna_disallow_writes && rna_id_write_error(&self->ptr, key)) {
                return -1;
        }
-#endif // USE_STRING_COERCE
+#endif // USE_PEDANTIC_WRITE
 
        if (group==NULL) {
                PyErr_SetString(PyExc_TypeError, "bpy_struct[key]= val: id properties not supported for this type");
@@ -3440,7 +3486,7 @@ static int pyrna_struct_setattro(BPy_StructRNA *self, PyObject *pyname, PyObject
        if (rna_disallow_writes && rna_id_write_error(&self->ptr, pyname)) {
                return -1;
        }
-#endif // USE_STRING_COERCE
+#endif // USE_PEDANTIC_WRITE
 
        if (name == NULL) {
                PyErr_SetString(PyExc_AttributeError, "bpy_struct: __setattr__ must be a string");
@@ -3600,7 +3646,7 @@ static int pyrna_prop_collection_setattro(BPy_PropertyRNA *self, PyObject *pynam
        if (rna_disallow_writes && rna_id_write_error(&self->ptr, pyname)) {
                return -1;
        }
-#endif // USE_STRING_COERCE
+#endif // USE_PEDANTIC_WRITE
 
        if (name == NULL) {
                PyErr_SetString(PyExc_AttributeError, "bpy_prop: __setattr__ must be a string");
@@ -4450,14 +4496,22 @@ static PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *dat
                                data_ch= *(char **)data;
 
 #ifdef USE_STRING_COERCE
-                       if (ELEM3(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) {
+                       if (subtype == PROP_BYTESTRING) {
+                               ret= PyBytes_FromString(data_ch);
+                       }
+                       else if (ELEM3(subtype, PROP_FILEPATH, PROP_DIRPATH, PROP_FILENAME)) {
                                ret= PyC_UnicodeFromByte(data_ch);
                        }
                        else {
                                ret= PyUnicode_FromString(data_ch);
                        }
 #else
-                       ret= PyUnicode_FromString(data_ch);
+                       if (subtype == PROP_BYTESTRING) {
+                               ret= PyBytes_FromString(buf);
+                       }
+                       else {
+                               ret= PyUnicode_FromString(data_ch);
+                       }
 #endif
 
 #ifdef USE_STRING_COERCE