Commits

Anonymous committed 354fd76

rope.base.pyobjects: PyDefinedObject.get_doc() always returns decoded docstrings (unicode objects) even if there was no 'u' prefix in docstring

Comments (0)

Files changed (5)

rope/base/fscommands.py

     return result
 
 def _decode_data(data, encoding):
+    if isinstance(data, unicode):
+        return data
     if encoding is None:
         encoding = read_str_coding(data)
+    if encoding is None:
+        # there is no encoding tip, we need to guess.
+        # PEP263 says that "encoding not explicitly defined" means it is ascii,
+        # but we will use utf8 instead since utf8 fully covers ascii and btw is
+        # the only non-latin sane encoding.
+        encoding = 'utf-8'
     try:
-        if encoding is not None:
-            return unicode(data, encoding)
-        return unicode(data)
-    except (UnicodeDecodeError, LookupError):
-        # Using ``utf-8`` if guessed encoding fails
-        return unicode(data, 'utf-8')
+        return data.decode(encoding)
+    except (UnicodeError, LookupError):
+        # fallback to latin1: it should never fail
+        return data.decode('latin1')
 
 
 def read_file_coding(path):

rope/base/pyobjects.py

+from rope.base.fscommands import _decode_data
 from rope.base import ast, exceptions, utils
 
 
             expr = self.get_ast().body[0]
             if isinstance(expr, ast.Expr) and \
                isinstance(expr.value, ast.Str):
-                return expr.value.s
+                docstring = expr.value.s
+                coding = self.get_module().coding
+                return _decode_data(docstring, coding)
 
     def _get_defined_objects(self):
         if self.defineds is None:

rope/base/pyobjectsdef.py

         self.source_code = source
         self.star_imports = []
         self.visitor_class = _GlobalVisitor
+        self.coding = fscommands.read_str_coding(self.source_code)
         super(PyModule, self).__init__(pycore, node, resource)
 
     def _init_source(self, pycore, source_code, resource):

ropetest/contrib/codeassisttest.py

+# coding: utf-8
 import unittest
 
 from rope.base import exceptions
         result = self._assist(code)
         proposals = sorted_proposals(result, typepref=['function'])
 
+    def test_get_pydoc_unicode(self):
+        src = u'# coding: utf-8\ndef foo():\n  u"юникод-объект"'
+        doc = get_doc(self.project, src, src.index('foo') + 1)
+        self.assertTrue(isinstance(doc, unicode))
+        self.assertTrue(u'юникод-объект' in doc)
+
+    def test_get_pydoc_utf8_bytestring(self):
+        src = u'# coding: utf-8\ndef foo():\n  "байтстринг"'
+        doc = get_doc(self.project, src, src.index('foo') + 1)
+        self.assertTrue(isinstance(doc, unicode))
+        self.assertTrue(u'байтстринг' in doc)
+
     def test_get_pydoc_for_functions(self):
         src = 'def a_func():\n' \
               '    """a function"""\n' \

ropetest/pycoretest.py

         except exceptions.ModuleSyntaxError, e:
             self.assertEquals(1, e.lineno)
 
-    @testutils.assert_raises(exceptions.ModuleDecodeError)
-    def test_not_syntax_errors_when_cannot_decode_file(self):
+    def test_no_exceptions_on_module_encoding_problems(self):
         mod = testutils.create_module(self.project, 'mod')
         contents = '\nsdsdsd\n\xa9\n'
         file = open(mod.real_path, 'wb')
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.