Use encoding from Python source file header
authorVincent van der Leun <vincentvdl@netbeans.org>
Thu, 16 Jul 2015 21:56:13 +0200
changeset 18286b0eed920d5f0
parent 18285 b047cef8879f
child 18287 e6da6973208f
Use encoding from Python source file header
python.core/nbproject/project.xml
python.core/src/org/netbeans/modules/python/api/PythonExecution.java
python.debugger/nbproject/project.xml
python.debugger/src/org/netbeans/modules/python/debugger/backend/PythonDebugClient.java
python.debugger/src/org/netbeans/modules/python/debugger/gui/PythonDebugContainer.java
python.debugger/src/org/netbeans/modules/python/debugger/resources/python/nbpythondebug/dbgnetwork.py
python.debugger/src/org/netbeans/modules/python/debugger/resources/python/nbpythondebug/jpydaemon.py
python.editor/nbproject/project.xml
python.editor/src/org/netbeans/modules/python/editor/PythonParser.java
python.editor/src/org/netbeans/modules/python/editor/templates/executable_module.py.ftl
python.project/src/org/netbeans/modules/python/project/PythonProject.java
     1.1 --- a/python.core/nbproject/project.xml	Wed Jul 08 15:32:47 2015 +0200
     1.2 +++ b/python.core/nbproject/project.xml	Thu Jul 16 21:56:13 2015 +0200
     1.3 @@ -59,6 +59,15 @@
     1.4                      </run-dependency>
     1.5                  </dependency>
     1.6                  <dependency>
     1.7 +                    <code-name-base>org.netbeans.modules.queries</code-name-base>
     1.8 +                    <build-prerequisite/>
     1.9 +                    <compile-dependency/>
    1.10 +                    <run-dependency>
    1.11 +                        <release-version>1</release-version>
    1.12 +                        <specification-version>1.41</specification-version>
    1.13 +                    </run-dependency>
    1.14 +                </dependency>
    1.15 +                <dependency>
    1.16                      <code-name-base>org.openide.awt</code-name-base>
    1.17                      <build-prerequisite/>
    1.18                      <compile-dependency/>
    1.19 @@ -123,14 +132,6 @@
    1.20                      </run-dependency>
    1.21                  </dependency>
    1.22                  <dependency>
    1.23 -                    <code-name-base>org.openide.util.ui</code-name-base>
    1.24 -                    <build-prerequisite/>
    1.25 -                    <compile-dependency/>
    1.26 -                    <run-dependency>
    1.27 -                        <specification-version>9.3</specification-version>
    1.28 -                    </run-dependency>
    1.29 -                </dependency>
    1.30 -                <dependency>
    1.31                      <code-name-base>org.openide.util</code-name-base>
    1.32                      <build-prerequisite/>
    1.33                      <compile-dependency/>
    1.34 @@ -147,6 +148,14 @@
    1.35                      </run-dependency>
    1.36                  </dependency>
    1.37                  <dependency>
    1.38 +                    <code-name-base>org.openide.util.ui</code-name-base>
    1.39 +                    <build-prerequisite/>
    1.40 +                    <compile-dependency/>
    1.41 +                    <run-dependency>
    1.42 +                        <specification-version>9.3</specification-version>
    1.43 +                    </run-dependency>
    1.44 +                </dependency>
    1.45 +                <dependency>
    1.46                      <code-name-base>org.openide.windows</code-name-base>
    1.47                      <build-prerequisite/>
    1.48                      <compile-dependency/>
     2.1 --- a/python.core/src/org/netbeans/modules/python/api/PythonExecution.java	Wed Jul 08 15:32:47 2015 +0200
     2.2 +++ b/python.core/src/org/netbeans/modules/python/api/PythonExecution.java	Thu Jul 16 21:56:13 2015 +0200
     2.3 @@ -10,6 +10,7 @@
     2.4  import java.io.Reader;
     2.5  import java.io.StringReader;
     2.6  import java.io.Writer;
     2.7 +import java.nio.charset.Charset;
     2.8  import java.util.ArrayList;
     2.9  import java.util.List;
    2.10  import java.util.concurrent.Future;
    2.11 @@ -21,6 +22,8 @@
    2.12  import org.netbeans.api.extexecution.input.InputProcessor;
    2.13  import org.netbeans.api.extexecution.print.LineConvertor;
    2.14  import org.netbeans.api.extexecution.print.LineConvertors.FileLocator;
    2.15 +import org.openide.filesystems.FileObject;
    2.16 +import org.openide.filesystems.FileUtil;
    2.17  import org.openide.util.Exceptions;
    2.18  
    2.19  /**
    2.20 @@ -108,11 +111,23 @@
    2.21              
    2.22              // Setup Descriptor Information
    2.23              //descriptor = buildDescriptor();
    2.24 +            String encoding = null;
    2.25 +            if (script != null) {
    2.26 +                File scriptFile = new File(script);
    2.27 +                FileObject scriptFileObject = FileUtil.toFileObject(scriptFile);
    2.28 +                
    2.29 +                PythonFileEncodingQuery encodingQuery = new PythonFileEncodingQuery();
    2.30 +                encoding = encodingQuery.getPythonFileEncoding(scriptFileObject.getInputStream());
    2.31 +                if (encoding != null) {
    2.32 +                    descriptor = descriptor.charset(Charset.forName(encoding));                    
    2.33 +                }
    2.34 +            }
    2.35 +            
    2.36              //process.
    2.37              //build Service
    2.38              ExecutionService service = 
    2.39                      ExecutionService.newService(
    2.40 -                    buildProcess(),
    2.41 +                    buildProcess(encoding),
    2.42                      descriptor, displayName);
    2.43              //io = descriptor.getInputOutput();
    2.44              // Start Service
    2.45 @@ -126,7 +141,7 @@
    2.46      }
    2.47  
    2.48  
    2.49 -    public ExternalProcessBuilder buildProcess() throws IOException{
    2.50 +    public ExternalProcessBuilder buildProcess(String encoding) throws IOException{
    2.51          ExternalProcessBuilder processBuilder =
    2.52                      new ExternalProcessBuilder(command);
    2.53              processBuilder = processBuilder.workingDirectory(new File(workingDirectory));
    2.54 @@ -162,6 +177,10 @@
    2.55              }
    2.56              processBuilder = processBuilder.redirectErrorStream(redirect);
    2.57              if(path != null){
    2.58 +                if (encoding != null) {
    2.59 +                    processBuilder = 
    2.60 +                            processBuilder.addEnvironmentVariable("PYTHONIOENCODING", encoding); // NOI18N
    2.61 +                }
    2.62                  if(command.toLowerCase().contains("jython")){
    2.63  //                    String commandPath = "-Dpython.path=" + path;
    2.64  //                    processBuilder = processBuilder.addArgument(commandPath);
     3.1 --- a/python.debugger/nbproject/project.xml	Wed Jul 08 15:32:47 2015 +0200
     3.2 +++ b/python.debugger/nbproject/project.xml	Thu Jul 16 21:56:13 2015 +0200
     3.3 @@ -58,6 +58,15 @@
     3.4                      </run-dependency>
     3.5                  </dependency>
     3.6                  <dependency>
     3.7 +                    <code-name-base>org.netbeans.modules.queries</code-name-base>
     3.8 +                    <build-prerequisite/>
     3.9 +                    <compile-dependency/>
    3.10 +                    <run-dependency>
    3.11 +                        <release-version>1</release-version>
    3.12 +                        <specification-version>1.41</specification-version>
    3.13 +                    </run-dependency>
    3.14 +                </dependency>
    3.15 +                <dependency>
    3.16                      <code-name-base>org.netbeans.spi.debugger.ui</code-name-base>
    3.17                      <build-prerequisite/>
    3.18                      <compile-dependency/>
     4.1 --- a/python.debugger/src/org/netbeans/modules/python/debugger/backend/PythonDebugClient.java	Wed Jul 08 15:32:47 2015 +0200
     4.2 +++ b/python.debugger/src/org/netbeans/modules/python/debugger/backend/PythonDebugClient.java	Thu Jul 16 21:56:13 2015 +0200
     4.3 @@ -235,7 +235,8 @@
     4.4            String pythonPath,
     4.5            String classPath,
     4.6            String pythonLoc,
     4.7 -          String jnetPyLoc)
     4.8 +          String jnetPyLoc,
     4.9 +          String codePage)
    4.10            throws PythonDebugException {
    4.11      if (pythonLoc == null) {
    4.12        throw new PythonDebugException("python.exe location not specified => check configuration");
    4.13 @@ -266,6 +267,9 @@
    4.14      if (classPath != null) {
    4.15        launcher.setEnv("CLASSPATH", classPath);
    4.16      }
    4.17 +    if (codePage != null) {
    4.18 +      launcher.setEnv("PYTHONIOENCODING", codePage); //NOI18N
    4.19 +    }
    4.20      launcher.start();
    4.21    }
    4.22  
    4.23 @@ -298,7 +302,7 @@
    4.24            String codePage)
    4.25            throws PythonDebugException {
    4.26      try {
    4.27 -      _codePage = System.getProperty(_ENCODING_PROPERTY_);
    4.28 +      _codePage = codePage==null ? System.getProperty(_ENCODING_PROPERTY_) : codePage;
    4.29        // parsing initialization   
    4.30        _parser = new JPyDebugXmlParser();
    4.31        _parser.init(null);
    4.32 @@ -311,12 +315,7 @@
    4.33          ServerSocket tcpOutServer = new ServerSocket(listeningPort, 1);
    4.34          ServerSocket tcpInServer = new ServerSocket(listeningPort + 1, 1);
    4.35          if (localHost(debuggingHost)) {
    4.36 -          localPythonLaunch(debuggingHost, listeningPort, pyPath, classPath, pythonLoc, jnetPyLoc);
    4.37 -        } else {
    4.38 -          // use configuration codepage for remote connection only
    4.39 -          if (codePage != null) {
    4.40 -            _codePage = codePage;
    4.41 -          }
    4.42 +          localPythonLaunch(debuggingHost, listeningPort, pyPath, classPath, pythonLoc, jnetPyLoc, codePage);
    4.43          }
    4.44          tcpOutServer.setSoTimeout(20000) ;
    4.45          _outCnx = tcpOutServer.accept();
     5.1 --- a/python.debugger/src/org/netbeans/modules/python/debugger/gui/PythonDebugContainer.java	Wed Jul 08 15:32:47 2015 +0200
     5.2 +++ b/python.debugger/src/org/netbeans/modules/python/debugger/gui/PythonDebugContainer.java	Thu Jul 16 21:56:13 2015 +0200
     5.3 @@ -63,6 +63,7 @@
     5.4  import org.netbeans.api.debugger.Breakpoint;
     5.5  import org.netbeans.api.debugger.Breakpoint.HIT_COUNT_FILTERING_STYLE;
     5.6  import org.netbeans.api.debugger.DebuggerManager;
     5.7 +import org.netbeans.modules.python.api.PythonFileEncodingQuery;
     5.8  import org.netbeans.modules.python.api.PythonOptions;
     5.9  import org.netbeans.modules.python.api.PythonPlatform;
    5.10  import org.netbeans.modules.python.debugger.CompositeCallback;
    5.11 @@ -1109,6 +1110,9 @@
    5.12          }
    5.13          PythonPlatform platform = _debuggee.getPlatform();
    5.14  
    5.15 +        // Use encoding from running file
    5.16 +        PythonFileEncodingQuery pythonEncodingQuery = new PythonFileEncodingQuery();
    5.17 +        String encoding = pythonEncodingQuery.getPythonFileEncoding(_debuggee.getFileObject().getInputStream());
    5.18  
    5.19          _pyClient.init(dbgHost,
    5.20                  PythonDebugParameters.get_listeningPort(),
    5.21 @@ -1118,8 +1122,8 @@
    5.22                  platform.getInterpreterCommand(),
    5.23                  PythonDebugParameters.get_jpydbgScript(),
    5.24                  PythonDebugParameters.get_jpydbgScriptArgs(),
    5.25 -                PythonDebugParameters.get_codePage());
    5.26 -      } catch (PythonDebugException e) {
    5.27 +                encoding);
    5.28 +      } catch (PythonDebugException | IOException e) {
    5.29          _msgBar.setError(e.getMessage());
    5.30        }
    5.31      }
     6.1 --- a/python.debugger/src/org/netbeans/modules/python/debugger/resources/python/nbpythondebug/dbgnetwork.py	Wed Jul 08 15:32:47 2015 +0200
     6.2 +++ b/python.debugger/src/org/netbeans/modules/python/debugger/resources/python/nbpythondebug/dbgnetwork.py	Thu Jul 16 21:56:13 2015 +0200
     6.3 @@ -43,6 +43,7 @@
     6.4  import socket
     6.5  import dbgutils
     6.6  import __builtin__
     6.7 +import sys
     6.8  
     6.9  __author__="jean-Yves Mengant"
    6.10  __date__ ="$Jan 13, 2009 10:03:05 AM$"
    6.11 @@ -59,7 +60,7 @@
    6.12          self._connections = { 'in' : socket.socket( socket.AF_INET , socket.SOCK_STREAM ) ,
    6.13                               'out': socket.socket( socket.AF_INET , socket.SOCK_STREAM )
    6.14                             }
    6.15 -
    6.16 +        self._encoding = sys.stdout.encoding
    6.17          if  host == None :
    6.18              # listening mode
    6.19              print "JPyDbg listening on in=" , port ,"/ out=",port+1
    6.20 @@ -152,7 +153,11 @@
    6.21          """ populate JpyDbg Xml buffer back """
    6.22          mbuffer = '<JPY>'
    6.23          for element in bufferList:
    6.24 -            mbuffer = mbuffer + ' ' + str(element)
    6.25 +            if isinstance(element, unicode):
    6.26 +                elm = element.encode(self._encoding)
    6.27 +            else:
    6.28 +                elm = str(element)
    6.29 +            mbuffer = mbuffer + ' ' + elm
    6.30          mbuffer = mbuffer + '</JPY>\n'
    6.31          self._DBG( "populateToClient --> " + mbuffer )
    6.32          self._send( mbuffer )
     7.1 --- a/python.debugger/src/org/netbeans/modules/python/debugger/resources/python/nbpythondebug/jpydaemon.py	Wed Jul 08 15:32:47 2015 +0200
     7.2 +++ b/python.debugger/src/org/netbeans/modules/python/debugger/resources/python/nbpythondebug/jpydaemon.py	Thu Jul 16 21:56:13 2015 +0200
     7.3 @@ -207,6 +207,7 @@
     7.4  
     7.5      def __init__( self ) :
     7.6          bdb.Bdb.__init__( self)
     7.7 +        self.encoding = sys.stdout.encoding
     7.8          self.lock = threading.Lock()
     7.9          self._acquire_lock = self.lock.acquire
    7.10          self._release_lock = self.lock.release
    7.11 @@ -1212,9 +1213,12 @@
    7.12              variables = stackElement[0].f_locals
    7.13          xmlVariables = ['<VARIABLES type="'+type+'">' ]
    7.14          for mapElement in variables.items():
    7.15 +            mapElmValue = mapElement[1]
    7.16 +            if isinstance(mapElmValue, unicode):
    7.17 +                mapElmValue = mapElmValue.encode(sys.stdout.encoding)
    7.18              xmlVariables.append('<VARIABLE ')
    7.19              xmlVariables.append('name="'+ _utils.removeForXml(mapElement[0])+'" ')
    7.20 -            xmlVariables.append('content="'+ _utils.removeForXml(__builtin__.str(mapElement[1]))+'" ')
    7.21 +            xmlVariables.append('content="'+ _utils.removeForXml(__builtin__.str(mapElmValue))+'" ')
    7.22              xmlVariables.append('vartype="'+ self.getVarType(mapElement[1])+'" ')
    7.23              xmlVariables.append( '/>')
    7.24          xmlVariables.append('</VARIABLES>')
     8.1 --- a/python.editor/nbproject/project.xml	Wed Jul 08 15:32:47 2015 +0200
     8.2 +++ b/python.editor/nbproject/project.xml	Thu Jul 16 21:56:13 2015 +0200
     8.3 @@ -6,15 +6,6 @@
     8.4              <code-name-base>org.netbeans.modules.python.editor</code-name-base>
     8.5              <module-dependencies>
     8.6                  <dependency>
     8.7 -                    <code-name-base>org.jython</code-name-base>
     8.8 -                    <build-prerequisite/>
     8.9 -                    <compile-dependency/>
    8.10 -                    <run-dependency>
    8.11 -                        <release-version>2</release-version>
    8.12 -                        <specification-version>2.10</specification-version>
    8.13 -                    </run-dependency>
    8.14 -                </dependency>
    8.15 -                <dependency>
    8.16                      <code-name-base>org.eclipse.mylyn.wikitext.confluence.core</code-name-base>
    8.17                      <build-prerequisite/>
    8.18                      <compile-dependency/>
    8.19 @@ -39,6 +30,15 @@
    8.20                      </run-dependency>
    8.21                  </dependency>
    8.22                  <dependency>
    8.23 +                    <code-name-base>org.jython</code-name-base>
    8.24 +                    <build-prerequisite/>
    8.25 +                    <compile-dependency/>
    8.26 +                    <run-dependency>
    8.27 +                        <release-version>2</release-version>
    8.28 +                        <specification-version>2.10</specification-version>
    8.29 +                    </run-dependency>
    8.30 +                </dependency>
    8.31 +                <dependency>
    8.32                      <code-name-base>org.netbeans.api.annotations.common</code-name-base>
    8.33                      <build-prerequisite/>
    8.34                      <compile-dependency/>
    8.35 @@ -66,6 +66,14 @@
    8.36                      </run-dependency>
    8.37                  </dependency>
    8.38                  <dependency>
    8.39 +                    <code-name-base>org.netbeans.api.templates</code-name-base>
    8.40 +                    <build-prerequisite/>
    8.41 +                    <compile-dependency/>
    8.42 +                    <run-dependency>
    8.43 +                        <specification-version>1.4</specification-version>
    8.44 +                    </run-dependency>
    8.45 +                </dependency>
    8.46 +                <dependency>
    8.47                      <code-name-base>org.netbeans.core.multiview</code-name-base>
    8.48                      <build-prerequisite/>
    8.49                      <compile-dependency/>
    8.50 @@ -265,7 +273,7 @@
    8.51                      <compile-dependency/>
    8.52                      <run-dependency>
    8.53                          <release-version>1</release-version>
    8.54 -                        <specification-version>1.15</specification-version>
    8.55 +                        <specification-version>1.63</specification-version>
    8.56                      </run-dependency>
    8.57                  </dependency>
    8.58                  <dependency>
    8.59 @@ -388,7 +396,7 @@
    8.60                      <build-prerequisite/>
    8.61                      <compile-dependency/>
    8.62                      <run-dependency>
    8.63 -                        <specification-version>8.0</specification-version>
    8.64 +                        <specification-version>8.31</specification-version>
    8.65                      </run-dependency>
    8.66                  </dependency>
    8.67                  <dependency>
     9.1 --- a/python.editor/src/org/netbeans/modules/python/editor/PythonParser.java	Wed Jul 08 15:32:47 2015 +0200
     9.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/PythonParser.java	Thu Jul 16 21:56:13 2015 +0200
     9.3 @@ -47,6 +47,7 @@
     9.4  import org.netbeans.modules.parsing.api.Task;
     9.5  import org.netbeans.modules.parsing.spi.Parser;
     9.6  import org.netbeans.modules.parsing.spi.SourceModificationEvent;
     9.7 +import org.netbeans.modules.python.api.PythonFileEncodingQuery;
     9.8  import org.openide.filesystems.FileObject;
     9.9  import org.python.antlr.runtime.ANTLRStringStream;
    9.10  import org.python.antlr.runtime.BaseRecognizer;
    9.11 @@ -88,6 +89,9 @@
    9.12      }
    9.13      
    9.14      private Result lastResult;
    9.15 +    private final PythonFileEncodingQuery fileEncodingQuery = new PythonFileEncodingQuery();
    9.16 +    private String headerCached = null;
    9.17 +    private String encodingCache = null;
    9.18  
    9.19      public mod file_input(CharStream charStream, String fileName) throws RecognitionException {
    9.20          ListErrorHandler eh = new ListErrorHandler();
    9.21 @@ -177,7 +181,14 @@
    9.22              //String charset = "ISO8859_1"; // NOI18N
    9.23              //String charset = "UTF-8"; // NOI18N
    9.24              //String charset = "iso8859_1"; // NOI18N
    9.25 -            String charset = null;
    9.26 +            // TODO: improve this check.
    9.27 +            int cache_len = sourceCode.length() >= 64 ? 64 : sourceCode.length();
    9.28 +            if (headerCached == null || cache_len != headerCached.length() || !headerCached.equals(sourceCode.substring(0, cache_len))) {
    9.29 +                headerCached = sourceCode.substring(0, cache_len);
    9.30 +                encodingCache = fileEncodingQuery.getPythonFileEncoding(sourceCode.split("\n", 2));                
    9.31 +            }
    9.32 +            String charset = encodingCache;            
    9.33 +                
    9.34              final boolean ignoreErrors = sanitizedSource;
    9.35              ListErrorHandler errorHandler = new ListErrorHandler() {
    9.36                  @Override
    9.37 @@ -311,7 +322,12 @@
    9.38              tokens.discardOffChannelTokens(true);
    9.39              PythonTokenSource indentedSource = new PythonTokenSource(tokens, fileName);
    9.40              CommonTokenStream indentedTokens = new CommonTokenStream(indentedSource);
    9.41 -            org.python.antlr.PythonParser parser = new org.python.antlr.PythonParser(indentedTokens);
    9.42 +            org.python.antlr.PythonParser parser;
    9.43 +            if (charset != null) {
    9.44 +                parser = new org.python.antlr.PythonParser(indentedTokens, charset);
    9.45 +            } else {
    9.46 +                parser = new org.python.antlr.PythonParser(indentedTokens);
    9.47 +            }
    9.48              parser.setTreeAdaptor(new PythonTreeAdaptor());
    9.49              parser.setErrorHandler(errorHandler);
    9.50              org.python.antlr.PythonParser.file_input_return r = parser.file_input();
    10.1 --- a/python.editor/src/org/netbeans/modules/python/editor/templates/executable_module.py.ftl	Wed Jul 08 15:32:47 2015 +0200
    10.2 +++ b/python.editor/src/org/netbeans/modules/python/editor/templates/executable_module.py.ftl	Thu Jul 16 21:56:13 2015 +0200
    10.3 @@ -3,6 +3,9 @@
    10.4  <#else>
    10.5  #!/usr/bin/env python2
    10.6  </#if>
    10.7 +<#if encoding??>
    10.8 +#encoding: ${encoding}
    10.9 +</#if>
   10.10  
   10.11  <#-- This is a FreeMarker template -->
   10.12  <#-- You can change the contents of the license inserted into
    11.1 --- a/python.project/src/org/netbeans/modules/python/project/PythonProject.java	Wed Jul 08 15:32:47 2015 +0200
    11.2 +++ b/python.project/src/org/netbeans/modules/python/project/PythonProject.java	Thu Jul 16 21:56:13 2015 +0200
    11.3 @@ -11,6 +11,7 @@
    11.4  import javax.swing.ImageIcon;
    11.5  import org.netbeans.api.java.classpath.ClassPath;
    11.6  import org.netbeans.api.java.classpath.GlobalPathRegistry;
    11.7 +import org.netbeans.modules.python.api.PythonFileEncodingQuery;
    11.8  import org.netbeans.modules.python.api.PythonPlatformProvider;
    11.9  import org.netbeans.modules.python.project.gsf.ClassPathProviderImpl;
   11.10  import org.netbeans.modules.python.project.ui.customizer.PythonCustomizerProvider;
   11.11 @@ -107,7 +108,8 @@
   11.12              new PythonProjectOperations(this), //move, rename, copy of project
   11.13              new RecommendedTemplatesImpl(this.updateHelper), // Recommended Templates
   11.14              new PythonCustomizerProvider(this), //Project custmoizer
   11.15 -            new PythonProjectFileEncodingQuery(getEvaluator()), //Provides encoding of the project - used by editor, runtime
   11.16 +            new PythonFileEncodingQuery(),
   11.17 +            new PythonProjectTemplateAttributesProvider(getEvaluator()),
   11.18              new PythonSharabilityQuery(helper, getEvaluator(), getSourceRoots(), getTestRoots()), //Sharabilit info - used by VCS
   11.19              helper.createCacheDirectoryProvider(), //Cache provider
   11.20              helper.createAuxiliaryProperties(), // AuxiliaryConfiguraion provider - used by bookmarks, project Preferences, etc