[Ironpython-users] Patch: Warn user when using old print syntax

Markus Schaber m.schaber at 3s-software.com
Wed Oct 12 16:44:54 CEST 2011


Hi,

Von: Markus Schaber
> Von: Dino Viehland [mailto:dinov at microsoft.com]
> > So you want to warn if the file contains a print statement w/o from
> > __future__ import print_function?  What if it's a call to print such
> > as
> > print('foo')  which is valid in both 2.x and 3.x?
> 
> Considering our user base, I could ignore this corner case, as the user can
> simply get rid of the warning by adding the import statement.
> 
> > Either way you should be able to just update ParsePrintStmt in Parser.cs.
> > But dealing w/ the case of the parens would be a little more difficult
> > - but I think you can just peek at the next token after print and see
> > if it's a parenthesis right after we eat the print keyword.
> 
> Ok, I'll see whether I can do that.

The patch below emits a warning during Compilation for print statements whose argument list does not start with a '(' if Py3k warnings are enabled.

Best regards

Markus Schaber

944eab0d7da3660001f1dabf473f48d5ddd4ee25
 Languages/IronPython/IronPython/Compiler/Parser.cs |   18 ++++++++++++++++--
 .../IronPython/IronPython/Resources.Designer.cs    |    9 +++++++++
 Languages/IronPython/IronPython/Resources.resx     |    3 +++
 3 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/Languages/IronPython/IronPython/Compiler/Parser.cs b/Languages/IronPython/IronPython/Compiler/Parser.cs
index bdef897..d756593 100644
--- a/Languages/IronPython/IronPython/Compiler/Parser.cs
+++ b/Languages/IronPython/IronPython/Compiler/Parser.cs
@@ -38,6 +38,7 @@ namespace IronPython.Compiler {
     public class Parser : IDisposable { // TODO: remove IDisposable
         // immutable properties:
         private readonly Tokenizer _tokenizer;
+        private readonly bool _warnPython30;
 
         // mutable properties:
         private ErrorSink _errors;
@@ -70,7 +71,7 @@ namespace IronPython.Compiler {
       
         #region Construction
 
-        private Parser(CompilerContext context, Tokenizer tokenizer, ErrorSink errorSink, ParserSink parserSink, ModuleOptions languageFeatures) {
+        private Parser(CompilerContext context, Tokenizer tokenizer, ErrorSink errorSink, ParserSink parserSink, ModuleOptions languageFeatures, bool warnPython30) {
             ContractUtils.RequiresNotNull(tokenizer, "tokenizer");
             ContractUtils.RequiresNotNull(errorSink, "errorSink");
             ContractUtils.RequiresNotNull(parserSink, "parserSink");
@@ -79,6 +80,7 @@ namespace IronPython.Compiler {
 
             _tokenizer = tokenizer;
             _errors = errorSink;
+            _warnPython30 = warnPython30;
             if (parserSink != ParserSink.Null) {
                 _sink = parserSink;
             }
@@ -123,7 +125,7 @@ namespace IronPython.Compiler {
             tokenizer.Initialize(null, reader, context.SourceUnit, SourceLocation.MinValue);
             tokenizer.IndentationInconsistencySeverity = options.IndentationInconsistencySeverity;
 
-            Parser result = new Parser(context, tokenizer, context.Errors, context.ParserSink, compilerOptions.Module);
+            Parser result = new Parser(context, tokenizer, context.Errors, context.ParserSink, compilerOptions.Module, options.WarnPython30);
             result._sourceReader = reader;
             return result;
         }
@@ -379,6 +381,13 @@ namespace IronPython.Compiler {
                 Severity.FatalError);
         }
 
+        private void ReportWarning(string message)
+        {
+            SourceLocation start = _tokenizer.IndexToLocation(_lookahead.Span.Start);
+            SourceLocation end = _tokenizer.IndexToLocation(_lookahead.Span.End);
+            _errors.Add(_sourceUnit, message, new SourceSpan(start, end), 0, Severity.Warning);
+        }
+
         #endregion        
 
         #region LL(1) Parsing
@@ -1017,6 +1026,11 @@ namespace IronPython.Compiler {
         //print_stmt: 'print' ( [ expression (',' expression)* [','] ] | '>>' expression [ (',' expression)+ [','] ] )
         private PrintStatement ParsePrintStmt() {
             Eat(TokenKind.KeywordPrint);
+
+            if (_warnPython30 && PeekToken().Kind != TokenKind.LeftParenthesis) {
+                ReportWarning(Resources.UsingPrintStatementWarning);
+            }
+
             var start = GetStart();
             Expression dest = null;
             PrintStatement ret;
diff --git a/Languages/IronPython/IronPython/Resources.Designer.cs b/Languages/IronPython/IronPython/Resources.Designer.cs
index b564a8e..4a5d5fe 100644
--- a/Languages/IronPython/IronPython/Resources.Designer.cs
+++ b/Languages/IronPython/IronPython/Resources.Designer.cs
@@ -419,5 +419,14 @@ namespace IronPython {
                 return ResourceManager.GetString("UnknownFutureFeature", resourceCulture);
             }
         }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Python 2 print statement found. For Python 3 compatibility, use &quot;from __future__ import print_function&quot; and the print() function instead..
+        /// </summary>
+        internal static string UsingPrintStatementWarning {
+            get {
+                return ResourceManager.GetString("UsingPrintStatementWarning", resourceCulture);
+            }
+        }
     }
 }
diff --git a/Languages/IronPython/IronPython/Resources.resx b/Languages/IronPython/IronPython/Resources.resx
index 3d89b3d..f666b1f 100644
--- a/Languages/IronPython/IronPython/Resources.resx
+++ b/Languages/IronPython/IronPython/Resources.resx
@@ -238,4 +238,7 @@
   <data name="UnknownFutureFeature" xml:space="preserve">
     <value>future feature is not defined:</value>
   </data>
+  <data name="UsingPrintStatementWarning" xml:space="preserve">
+    <value>Python 2 print statement found. For Python 3 compatibility, use "from __future__ import print_function" and the print() function instead.</value>
+  </data>
 </root>
\ No newline at end of file


More information about the Ironpython-users mailing list