From e62a0fe36776f039149e7fab77323aa380b97c2e Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky <pfalcon@users.sourceforge.net>
Date: Thu, 30 Oct 2014 23:58:08 +0200
Subject: [PATCH] objstr: Allow to convert any buffer proto object to str.

Original motivation is to support converting bytearrays, but easier to just
support buffer protocol at all.
---
 py/objstr.c                | 19 +++++++++++--------
 py/objstrunicode.c         | 19 +++++++++++--------
 tests/basics/bytearray1.py |  2 ++
 3 files changed, 24 insertions(+), 16 deletions(-)

diff --git a/py/objstr.c b/py/objstr.c
index b27498d35..6a3a77c53 100644
--- a/py/objstr.c
+++ b/py/objstr.c
@@ -160,15 +160,18 @@ STATIC mp_obj_t str_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw,
         case 3:
         {
             // TODO: validate 2nd/3rd args
-            if (!MP_OBJ_IS_TYPE(args[0], &mp_type_bytes)) {
-                nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "bytes expected"));
+            if (MP_OBJ_IS_TYPE(args[0], &mp_type_bytes)) {
+                GET_STR_DATA_LEN(args[0], str_data, str_len);
+                GET_STR_HASH(args[0], str_hash);
+                mp_obj_str_t *o = mp_obj_new_str_of_type(&mp_type_str, NULL, str_len);
+                o->data = str_data;
+                o->hash = str_hash;
+                return o;
+            } else {
+                mp_buffer_info_t bufinfo;
+                mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
+                return mp_obj_new_str(bufinfo.buf, bufinfo.len, false);
             }
-            GET_STR_DATA_LEN(args[0], str_data, str_len);
-            GET_STR_HASH(args[0], str_hash);
-            mp_obj_str_t *o = mp_obj_new_str_of_type(&mp_type_str, NULL, str_len);
-            o->data = str_data;
-            o->hash = str_hash;
-            return o;
         }
 
         default:
diff --git a/py/objstrunicode.c b/py/objstrunicode.c
index 062e011fb..2c8d02491 100644
--- a/py/objstrunicode.c
+++ b/py/objstrunicode.c
@@ -142,15 +142,18 @@ STATIC mp_obj_t str_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw,
         case 3:
         {
             // TODO: validate 2nd/3rd args
-            if (!MP_OBJ_IS_TYPE(args[0], &mp_type_bytes)) {
-                nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "bytes expected"));
+            if (MP_OBJ_IS_TYPE(args[0], &mp_type_bytes)) {
+                GET_STR_DATA_LEN(args[0], str_data, str_len);
+                GET_STR_HASH(args[0], str_hash);
+                mp_obj_str_t *o = mp_obj_new_str_of_type(&mp_type_str, NULL, str_len);
+                o->data = str_data;
+                o->hash = str_hash;
+                return o;
+            } else {
+                mp_buffer_info_t bufinfo;
+                mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
+                return mp_obj_new_str(bufinfo.buf, bufinfo.len, false);
             }
-            GET_STR_DATA_LEN(args[0], str_data, str_len);
-            GET_STR_HASH(args[0], str_hash);
-            mp_obj_str_t *o = mp_obj_new_str_of_type(&mp_type_str, NULL, str_len);
-            o->data = str_data;
-            o->hash = str_hash;
-            return o;
         }
 
         default:
diff --git a/tests/basics/bytearray1.py b/tests/basics/bytearray1.py
index d8e669506..76e7e5975 100644
--- a/tests/basics/bytearray1.py
+++ b/tests/basics/bytearray1.py
@@ -18,6 +18,8 @@ print(a[1:])
 print(a[:-1])
 print(a[2:3])
 
+print(str(bytearray(b"123"), "utf-8"))
+
 # Comparisons
 print(bytearray([1]) == bytearray([1]))
 print(bytearray([1]) == bytearray([2]))
-- 
GitLab