Skip to content

Commit 4e8b2bd

Browse files
Merge pull request serge-sans-paille#1078 from serge-sans-paille/fix/improve-none-str-support
Getter str/none interaction
2 parents 83eff64 + da54d6f commit 4e8b2bd

File tree

6 files changed

+67
-2
lines changed

6 files changed

+67
-2
lines changed

pythran/pythonic/include/types/NoneType.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define PYTHONIC_INCLUDE_TYPES_NONE_HPP
33

44
#include "pythonic/include/types/assignable.hpp"
5+
#include <ostream>
56

67
PYTHONIC_NS_BEGIN
78

@@ -15,6 +16,11 @@ namespace types
1516
intptr_t id() const;
1617
};
1718

19+
std::ostream &operator<<(std::ostream &os, none_type const &)
20+
{
21+
return os << "None";
22+
}
23+
1824
template <class T, bool is_fundamental = std::is_fundamental<T>::value>
1925
struct none;
2026

@@ -40,6 +46,9 @@ namespace types
4046
explicit operator bool() const;
4147

4248
intptr_t id() const;
49+
50+
template <class T0>
51+
friend std::ostream &operator<<(std::ostream &os, none<T0, false> const &);
4352
};
4453

4554
/* specialization of none for integral types we cannot derive from

pythran/pythonic/include/types/str.hpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,12 +126,16 @@ namespace types
126126
str(std::string const &s);
127127
str(std::string &&s);
128128
str(const char *s);
129+
template <size_t N>
130+
str(const char(&s)[N]);
129131
str(const char *s, size_t n);
130132
str(char c);
131133
template <class S>
132134
str(sliced_str<S> const &other);
133135
template <class T>
134136
str(T const &begin, T const &end);
137+
template <class T>
138+
explicit str(T const &);
135139

136140
explicit operator char() const;
137141
explicit operator long int() const;
@@ -191,6 +195,11 @@ namespace types
191195

192196
explicit operator bool() const;
193197
long count(types::str const &sub) const;
198+
199+
intptr_t id() const
200+
{
201+
return reinterpret_cast<intptr_t>(&(*data));
202+
}
194203
};
195204

196205
size_t hash_value(str const &x);
@@ -204,7 +213,10 @@ namespace types
204213
str operator+(char const(&self)[N], str const &other);
205214

206215
bool operator==(char c, str const &s);
207-
bool operator==(str const &s, char c);
216+
217+
template <size_t N>
218+
bool operator==(char const(&self)[N], str const &other);
219+
208220
bool operator!=(char c, str const &s);
209221
bool operator!=(str const &s, char c);
210222
std::ostream &operator<<(std::ostream &os, str const &s);

pythran/pythonic/types/NoneType.hpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@ namespace types
6565
{
6666
return is_none ? NONE_ID : __builtin__::id(static_cast<const T &>(*this));
6767
}
68+
template <class T>
69+
std::ostream &operator<<(std::ostream &os, none<T, false> const &v)
70+
{
71+
if (v.is_none)
72+
return os << none_type();
73+
else
74+
return os << static_cast<T const &>(v);
75+
}
6876

6977
/* specialization of none for integral types we cannot derive from */
7078
template <class T>
@@ -295,7 +303,7 @@ namespace types
295303
std::ostream &operator<<(std::ostream &os, none<T, true> const &v)
296304
{
297305
if (v.is_none)
298-
return os << "None";
306+
return os << none_type();
299307
else
300308
return os << v.data;
301309
}

pythran/pythonic/types/str.hpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,12 @@ namespace types
264264
{
265265
}
266266

267+
template <size_t N>
268+
str::str(const char(&s)[N])
269+
: data(s)
270+
{
271+
}
272+
267273
str::str(const char *s, size_t n) : data(s, n)
268274
{
269275
}
@@ -284,6 +290,14 @@ namespace types
284290
{
285291
}
286292

293+
template <class T>
294+
str::str(T const &s)
295+
{
296+
std::ostringstream oss;
297+
oss << s;
298+
*data = oss.str();
299+
}
300+
287301
str::operator char() const
288302
{
289303
assert(size() == 1);
@@ -609,6 +623,12 @@ namespace types
609623
return s.size() == 1 && s[0] == c;
610624
}
611625

626+
template <size_t N>
627+
bool operator==(char const(&self)[N], str const &other)
628+
{
629+
return other == self;
630+
}
631+
612632
bool operator!=(char c, str const &s)
613633
{
614634
return s.size() != 1 || s[0] != c;

pythran/tests/test_none.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,3 +299,16 @@ def test_987_3(x):
299299
b = 1
300300
return (b, a)'''
301301
self.run_test(code, 3, test_987_3=[int])
302+
303+
def test_none_to_str(self):
304+
code = """
305+
def dump_as_str(x):
306+
y = x
307+
return str(y) + str(y) * 2
308+
def none_to_str(x):
309+
if x > 1:
310+
y = None
311+
else:
312+
y = 2
313+
return dump_as_str(None), dump_as_str(y)"""
314+
self.run_test(code, 0, none_to_str=[int])

pythran/tests/test_str.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,3 +206,6 @@ def test_str_numpy_float64(self):
206206

207207
def test_str_int(self):
208208
self.run_test("def str_int(s): return int(s)", "12", str_int=[str])
209+
210+
def test_str_id(self):
211+
self.run_test("def str_id(x): return id(x) != 0", "hello", str_id=[str])

0 commit comments

Comments
 (0)