cython-devel

changeset 3049:6c0c2ae56034

implemented 'print >> stream'
author Stefan Behnel <scoder@users.berlios.de>
date Tue Mar 09 09:29:47 2010 +0100 (23 months ago)
parents 058a70c40bf0
children a95dff390f68
files Cython/Compiler/Nodes.py Cython/Compiler/Parsing.py tests/run/print.pyx
line diff
1.1 --- a/Cython/Compiler/Nodes.py Sat Mar 06 18:14:05 2010 +0100 1.2 +++ b/Cython/Compiler/Nodes.py Tue Mar 09 09:29:47 2010 +0100 1.3 @@ -3447,11 +3447,15 @@ 1.4 # print statement 1.5 # 1.6 # arg_tuple TupleNode 1.7 + # stream ExprNode or None (stdout) 1.8 # append_newline boolean 1.9 1.10 - child_attrs = ["arg_tuple"] 1.11 - 1.12 - def analyse_expressions(self, env): 1.13 + child_attrs = ["arg_tuple", "stream"] 1.14 + 1.15 + def analyse_expressions(self, env): 1.16 + if self.stream: 1.17 + self.stream.analyse_expressions(env) 1.18 + self.stream = self.stream.coerce_to_pyobject(env) 1.19 self.arg_tuple.analyse_expressions(env) 1.20 self.arg_tuple = self.arg_tuple.coerce_to_pyobject(env) 1.21 env.use_utility_code(printing_utility_code) 1.22 @@ -3462,12 +3466,18 @@ 1.23 gil_message = "Python print statement" 1.24 1.25 def generate_execution_code(self, code): 1.26 + if self.stream: 1.27 + self.stream.generate_evaluation_code(code) 1.28 + stream_result = self.stream.py_result() 1.29 + else: 1.30 + stream_result = '0' 1.31 if len(self.arg_tuple.args) == 1 and self.append_newline: 1.32 arg = self.arg_tuple.args[0] 1.33 arg.generate_evaluation_code(code) 1.34 1.35 code.putln( 1.36 - "if (__Pyx_PrintOne(%s) < 0) %s" % ( 1.37 + "if (__Pyx_PrintOne(%s, %s) < 0) %s" % ( 1.38 + stream_result, 1.39 arg.py_result(), 1.40 code.error_goto(self.pos))) 1.41 arg.generate_disposal_code(code) 1.42 @@ -3475,14 +3485,21 @@ 1.43 else: 1.44 self.arg_tuple.generate_evaluation_code(code) 1.45 code.putln( 1.46 - "if (__Pyx_Print(%s, %d) < 0) %s" % ( 1.47 + "if (__Pyx_Print(%s, %s, %d) < 0) %s" % ( 1.48 + stream_result, 1.49 self.arg_tuple.py_result(), 1.50 self.append_newline, 1.51 code.error_goto(self.pos))) 1.52 self.arg_tuple.generate_disposal_code(code) 1.53 self.arg_tuple.free_temps(code) 1.54 1.55 - def annotate(self, code): 1.56 + if self.stream: 1.57 + self.stream.generate_disposal_code(code) 1.58 + self.stream.free_temps(code) 1.59 + 1.60 + def annotate(self, code): 1.61 + if self.stream: 1.62 + self.stream.annotate(code) 1.63 self.arg_tuple.annotate(code) 1.64 1.65 1.66 @@ -5028,7 +5045,7 @@ 1.67 1.68 printing_utility_code = UtilityCode( 1.69 proto = """ 1.70 -static int __Pyx_Print(PyObject *, int); /*proto*/ 1.71 +static int __Pyx_Print(PyObject*, PyObject *, int); /*proto*/ 1.72 #if PY_MAJOR_VERSION >= 3 1.73 static PyObject* %s = 0; 1.74 static PyObject* %s = 0; 1.75 @@ -5044,13 +5061,14 @@ 1.76 return f; 1.77 } 1.78 1.79 -static int __Pyx_Print(PyObject *arg_tuple, int newline) { 1.80 - PyObject *f; 1.81 +static int __Pyx_Print(PyObject* f, PyObject *arg_tuple, int newline) { 1.82 PyObject* v; 1.83 int i; 1.84 1.85 - if (!(f = __Pyx_GetStdout())) 1.86 - return -1; 1.87 + if (!f) { 1.88 + if (!(f = __Pyx_GetStdout())) 1.89 + return -1; 1.90 + } 1.91 for (i=0; i < PyTuple_GET_SIZE(arg_tuple); i++) { 1.92 if (PyFile_SoftSpace(f, 1)) { 1.93 if (PyFile_WriteString(" ", f) < 0) 1.94 @@ -5078,7 +5096,7 @@ 1.95 1.96 #else /* Python 3 has a print function */ 1.97 1.98 -static int __Pyx_Print(PyObject *arg_tuple, int newline) { 1.99 +static int __Pyx_Print(PyObject* stream, PyObject *arg_tuple, int newline) { 1.100 PyObject* kwargs = 0; 1.101 PyObject* result = 0; 1.102 PyObject* end_string; 1.103 @@ -5087,27 +5105,43 @@ 1.104 if (!%(PRINT_FUNCTION)s) 1.105 return -1; 1.106 } 1.107 + if (stream) { 1.108 + kwargs = PyDict_New(); 1.109 + if (unlikely(!kwargs)) 1.110 + return -1; 1.111 + if (unlikely(PyDict_SetItemString(kwargs, "file", stream) < 0)) 1.112 + goto bad; 1.113 + } 1.114 + } 1.115 if (!newline) { 1.116 - if (!%(PRINT_KWARGS)s) { 1.117 + if (!kwargs) 1.118 + kwargs = %(PRINT_KWARGS)s; 1.119 + if (!kwargs) { 1.120 %(PRINT_KWARGS)s = PyDict_New(); 1.121 - if (!%(PRINT_KWARGS)s) 1.122 + if unlikely((!%(PRINT_KWARGS)s)) 1.123 return -1; 1.124 - end_string = PyUnicode_FromStringAndSize(" ", 1); 1.125 - if (!end_string) 1.126 - return -1; 1.127 - if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) { 1.128 - Py_DECREF(end_string); 1.129 - return -1; 1.130 - } 1.131 + kwargs = %(PRINT_KWARGS)s; 1.132 + } 1.133 + end_string = PyUnicode_FromStringAndSize(" ", 1); 1.134 + if (unlikely(!end_string)) 1.135 + goto bad; 1.136 + if (PyDict_SetItemString(%(PRINT_KWARGS)s, "end", end_string) < 0) { 1.137 Py_DECREF(end_string); 1.138 - } 1.139 - kwargs = %(PRINT_KWARGS)s; 1.140 + goto bad; 1.141 + } 1.142 + Py_DECREF(end_string); 1.143 } 1.144 result = PyObject_Call(%(PRINT_FUNCTION)s, arg_tuple, kwargs); 1.145 + if (unlikely(kwargs) && (kwargs != %(PRINT_FUNCTION)s)) 1.146 + Py_DECREF(kwargs); 1.147 if (!result) 1.148 return -1; 1.149 Py_DECREF(result); 1.150 return 0; 1.151 +bad: 1.152 + if (kwargs != %(PRINT_FUNCTION)s) 1.153 + Py_XDECREF(kwargs); 1.154 + return -1; 1.155 } 1.156 1.157 #endif 1.158 @@ -5119,15 +5153,16 @@ 1.159 1.160 printing_one_utility_code = UtilityCode( 1.161 proto = """ 1.162 -static int __Pyx_PrintOne(PyObject *o); /*proto*/ 1.163 +static int __Pyx_PrintOne(PyObject* stream, PyObject *o); /*proto*/ 1.164 """, 1.165 impl = r""" 1.166 #if PY_MAJOR_VERSION < 3 1.167 1.168 -static int __Pyx_PrintOne(PyObject *o) { 1.169 - PyObject *f; 1.170 - if (!(f = __Pyx_GetStdout())) 1.171 - return -1; 1.172 +static int __Pyx_PrintOne(PyObject* f, PyObject *o) { 1.173 + if (!f) { 1.174 + if (!(f = __Pyx_GetStdout())) 1.175 + return -1; 1.176 + } 1.177 if (PyFile_SoftSpace(f, 0)) { 1.178 if (PyFile_WriteString(" ", f) < 0) 1.179 return -1; 1.180 @@ -5139,19 +5174,19 @@ 1.181 return 0; 1.182 /* the line below is just to avoid compiler 1.183 * compiler warnings about unused functions */ 1.184 - return __Pyx_Print(NULL, 0); 1.185 + return __Pyx_Print(f, NULL, 0); 1.186 } 1.187 1.188 #else /* Python 3 has a print function */ 1.189 1.190 -static int __Pyx_PrintOne(PyObject *o) { 1.191 +static int __Pyx_PrintOne(PyObject* stream, PyObject *o) { 1.192 int res; 1.193 PyObject* arg_tuple = PyTuple_New(1); 1.194 if (unlikely(!arg_tuple)) 1.195 return -1; 1.196 Py_INCREF(o); 1.197 PyTuple_SET_ITEM(arg_tuple, 0, o); 1.198 - res = __Pyx_Print(arg_tuple, 1); 1.199 + res = __Pyx_Print(stream, arg_tuple, 1); 1.200 Py_DECREF(arg_tuple); 1.201 return res; 1.202 }
2.1 --- a/Cython/Compiler/Parsing.py Sat Mar 06 18:14:05 2010 +0100 2.2 +++ b/Cython/Compiler/Parsing.py Tue Mar 09 09:29:47 2010 +0100 2.3 @@ -929,11 +929,17 @@ 2.4 def p_print_statement(s): 2.5 # s.sy == 'print' 2.6 pos = s.position() 2.7 + ends_with_comma = 0 2.8 s.next() 2.9 if s.sy == '>>': 2.10 - s.error("'print >>' not yet implemented") 2.11 + s.next() 2.12 + stream = p_simple_expr(s) 2.13 + if s.sy == ',': 2.14 + s.next() 2.15 + ends_with_comma = s.sy in ('NEWLINE', 'EOF') 2.16 + else: 2.17 + stream = None 2.18 args = [] 2.19 - ends_with_comma = 0 2.20 if s.sy not in ('NEWLINE', 'EOF'): 2.21 args.append(p_simple_expr(s)) 2.22 while s.sy == ',': 2.23 @@ -944,7 +950,8 @@ 2.24 args.append(p_simple_expr(s)) 2.25 arg_tuple = ExprNodes.TupleNode(pos, args = args) 2.26 return Nodes.PrintStatNode(pos, 2.27 - arg_tuple = arg_tuple, append_newline = not ends_with_comma) 2.28 + arg_tuple = arg_tuple, stream = stream, 2.29 + append_newline = not ends_with_comma) 2.30 2.31 def p_exec_statement(s): 2.32 # s.sy == 'exec'
3.1 --- a/tests/run/print.pyx Sat Mar 06 18:14:05 2010 +0100 3.2 +++ b/tests/run/print.pyx Tue Mar 09 09:29:47 2010 +0100 3.3 @@ -14,3 +14,29 @@ 3.4 print a, b 3.5 print a, b, 3.6 print 42, u"spam" 3.7 + 3.8 + 3.9 +try: 3.10 + from StringIO import StringIO 3.11 +except ImportError: 3.12 + from io import StringIO 3.13 + 3.14 +def s(stream, a, b): 3.15 + """ 3.16 + >>> stream = StringIO() 3.17 + >>> s(stream, 1, 'test') 3.18 + >>> print(stream.getvalue()) 3.19 + <BLANKLINE> 3.20 + 1 3.21 + 1 test 3.22 + 1 test 3.23 + 1 test 42 spam 3.24 + <BLANKLINE> 3.25 + """ 3.26 + print >> stream 3.27 + print >> stream, a 3.28 + print >> stream, a, 3.29 + print >> stream, b 3.30 + print >> stream, a, b 3.31 + print >> stream, a, b, 3.32 + print >> stream, 42, u"spam"