Commits

Henning Schröder  committed db472a0

cleanup

  • Participants
  • Parent commits 0190625

Comments (0)

Files changed (10)

 
 
 
+Current public API
+------------------
 
-
+ * from pycode.outline import outline
+   outline(project, source_code) -> PythonASTOutlineNode
+ * from pycode.checks import tasks, pyflakes, pep8, lint
+ * from pycode.onlinehelp import help_for
+   help_for(fqdn)
+ * from pycode.cropeassist import completions, calltip, definition_location
+   completions(project, source_code, offset, filename=None) -> []
+   calltip(project, source_code, offset, filename=None) -> ""
+   definition_location(project, source_code, offset, filename=None) -> ""
+ * from pycode.fileio import guess_encoding, load, save
+   guess_encoding(source, peek_lines=100, encoding="utf-8")
+   load(filename) -> ""
+   save(..)
+ * from pycode.indenter import PythonCodeIndenter
+   PythonCodeIndenter(editor).correct_indention(line_no)
+ * from pycode.pyqtfrontend import PyCode
 
 Copyright
 ---------

File pycode/checks.py

 
 
 
-def pyflakes(project, source_code, filename=None):
+def flakes(project, source_code, filename=None):
     """
     Check source code with pyflakes
     Returns an empty list if pyflakes is not installed
         args += options
     source_code += '\n'
     if filename is None:
-        # Creating a temporary file because file does not exist yet 
+        # Creating a temporary file because file does not exist yet
         # or is not up-to-date
         tempfd = tempfile.NamedTemporaryFile(suffix=".py", delete=False)
         tempfd.write(source_code)
 
 
 
-def pep8_external(project, source_code, filename=None):
+def pep8(project, source_code, filename=None):
     """Check source code with pep8"""
     args = ['pep8']
     results = []
 
 
 
-def lint_external(project, source_code, filename=None):
+def lint(project, source_code, filename=None):
     args = ["pylint"]
     options = ["-f parseable", "-r", "-n", "--disable-msg-cat=C,R"]
     results = []

File pycode/libs/__init__.py

 path = os.path.dirname(os.path.abspath(__file__))
 
 for name in os.listdir(path):
-	if name.endswith(".zip"):
-		zip_module = os.path.join(path, name)
-		sys.path.insert(0, zip_module)
+    if name.endswith(".zip"):
+        zip_module = os.path.join(path, name)
+        sys.path.insert(0, zip_module)
 

File pycode/pyqtfrontend.py

 from PyQt4.QtGui import (
     QToolTip, QTreeWidget, QTreeWidgetItem, QTextCursor, QFrame, QIcon, QCompleter, QTableView, QAbstractItemView, QKeyEvent)
 
-from pycode.ropeassist import async_completions, async_calltip, async_definition_location
+from pycode.ropeassist import completions, calltip, definition_location
 from pycode.indenter import PythonCodeIndenter
 
-from pycode.utils import set_async_method, enable_ipc
 
 
 
-class AsyncQThread(QThread):
+class BackgroundOperation(QThread):
 
     
     def __init__(self, target, args, kwargs):
-        super(AsyncQThread, self).__init__()
+        super(BackgroundOperation, self).__init__()
         self.target = target
         self.args = args
-        self.callback = kwargs.pop("callback")
+        self.callback = kwargs.pop("callback", None)
         self.kwargs = kwargs
+        self.result = None
         self.finished.connect(self.on_finished)
         
 
     def run(self):
-        if ipc_client:
-            kwargs = dict(self.kwargs, callback=self.callback)
-            self.result = ipc_client.call(self.target.__name__, *self.args, **kwargs)
-        else:
-            self.result = self.target(*self.args, **self.kwargs)
+        self.result = self.target(*self.args, **self.kwargs)
 
 
     def on_finished(self):
         # slot called in main (gui) thread
-        self.callback(self.result)
+        if self.callback:
+            self.callback(self.result)
+        # To be safe, remove refernces for garbage collection
         self.args = self.kwargs = self.target = None
 
 
-        
-def async_pyqt(func, *args, **kwargs):
-    func._thread = AsyncQThread(func, args=args, kwargs=kwargs)
+
+def call_background(func, *args, **kwargs):
+    func._thread = BackgroundOperation(func, args=args, kwargs=kwargs)
     func._thread.start()
 
 
-ipc_client = None #enable_ipc()
-set_async_method(async_pyqt)
 
 
-
-class LineEditor(object):
+class RopeEditorAdapter(object):
     """
     Wrapper for PyQt4 to provide the Line-editor interface 
     for the Indenter classes
         
         
     def eventFilter(self, obj, event):
+        # TODO: test how many events really arrive
         if isinstance(event, QKeyEvent) and self._on_key_pressed(event):
             return True
         return super(Completer, self).eventFilter(obj, event)
     
     
 class PyCode(object):
-    
+
+    calltip_factory = CallTip
 
     def __init__(self, project_folder, textedit, filename=None):
         self._prj = project_folder
         self._textedit = textedit
         self._filename = filename
         self._completer = Completer(self._textedit)
-        self._calltip = CallTip(self._textedit)
-        self._indenter = PythonCodeIndenter(LineEditor(self._textedit))
+        self._calltip = self.calltip_factory(self._textedit)
+        self._indenter = PythonCodeIndenter(RopeEditorAdapter(self._textedit))
         self._textedit_keyPressEvent = self._textedit.keyPressEvent
         self._textedit.keyPressEvent = self.keyPressEvent
 
     
     def request_completion(self):
         src, pos = self.source()
-        async_completions(self._prj, src, pos, callback=self.got_completions)
+        call_background(completions, self._prj, src, pos, callback=self.got_completions)
 
 
     def got_completions(self, result):
         
     def request_definition(self):
         src, pos = self.source()
-        async_definition_location(self._prj, src, pos, callback=self.got_definition)
+        call_background(definition_location, self._prj, src, pos, callback=self.got_definition)
 
         
     def got_definition(self, result):
 
     def request_calltip(self):
         src, pos = self.source()
-        async_calltip(self._prj, src, pos-1, callback=self.got_calltip)
+        call_background(calltip, self._prj, src, pos-1, callback=self.got_calltip)
 
         
     def got_calltip(self, result):

File pycode/ropeassist.py

 import inspect
 from zipimport import zipimporter
 
+import libs # use internal rope (might be newer)
+
 import rope.base.libutils
 import rope.base.project
 import rope.contrib.codeassist
 
-from pycode.utils import async, register
-
 
 
 
             print "Could not create rope project", _error
             import traceback
             traceback.print_exc()
-            self._rope_prj = rope.base.project.get_no_project()
+            #self._rope_prj = rope.base.project.get_no_project()
+            self._rope_prj =  rope.base.project.NoProject()
             self._rope_prj.root = None
 
 
     return resource
 
 
-@register
 def completions(project, source_code, offset, filename="XXXunknownXXX.py"):
     # TODO:
     #  * include import completitions
 
 
 
-async_definition_location = async(definition_location)
-
-
 
 
 db = {}

File pycode/sourceindex/index.py

 class Indexer(object):
 
 
-	def __init__(self, path):
-		if not os.path.exists(path):
-			os.makedirs(path)
-		try:
-			self._ix = open_dir(path)
-			multisegment = False
-		except:
-			self._ix = create_in(path, models.name_schema)
-			multisegment = True
-		self._writer = self._ix.writer(procs=4, limitmb=128, multisegment=multisegment)
-		
-		#stem_ana = self._writer.schema["name"].format.analyzer
-		#stem_ana.cachesize = -1 # Set the cachesize to -1 to indicate unbounded caching
-		#stem_ana.clear()  # Reset the analyzer to pick up the changed attribute
+    def __init__(self, path):
+        if not os.path.exists(path):
+            os.makedirs(path)
+        try:
+            self._ix = open_dir(path)
+            multisegment = False
+        except:
+            self._ix = create_in(path, models.name_schema)
+            multisegment = True
+        self._writer = self._ix.writer(procs=4, limitmb=128, multisegment=multisegment)
 
+        #stem_ana = self._writer.schema["name"].format.analyzer
+        #stem_ana.cachesize = -1 # Set the cachesize to -1 to indicate unbounded caching
+        #stem_ana.clear()  # Reset the analyzer to pick up the changed attribute
 
-	def close(self):
-		self._writer.commit()
 
-	
-	def _add(self, **kwargs):
-		for key, value in kwargs.items():
-			if isinstance(value, str):
-				kwargs[key] = unicode(value)
-		self._writer.add_document(**kwargs)
-		#self._writer.commit()
+    def close(self):
+        self._writer.commit()
 
-		
-	def remove_filename(self, filename):
-		# TODO: remove documents where file does not exist anymore
-		self._writer.delete_by_term("filename", filename)
-	
-			
-	def add_filename(self, filename, module_name):
-		try:
-			items = list(parser.parse(filename))
-		except Exception, exc:
-			print filename, exc
-			return
-		self.remove_filename(filename)
-		for entry in items:
-			kind, scope, name, lineno = entry
-			self._add(kind=kind, name=name, line=lineno, filename=filename, scope=module_name + "." + scope)
-		self._add(kind="module", name=module_name, line=0, filename=filename)
 
+    def _add(self, **kwargs):
+        for key, value in kwargs.items():
+            if isinstance(value, str):
+                kwargs[key] = unicode(value)
+        self._writer.add_document(**kwargs)
+        #self._writer.commit()
 
-	def add_path(self, path):
-		for kind, filename, module_name in parser.modules(path):
-			yield filename
-			if kind == "mod":
-				self.add_filename(filename, module_name)
-			else: # kind == "pkg"
-				base = os.path.basename(filename)
-				for pkg_filename in parser.tree(filename):
-					pkg_mod = pkg_filename[len(filename)+1:].rstrip(".py")
-					pkg = os.path.join(base, pkg_mod).replace("/", ".")
-					self.add_filename(pkg_filename, pkg)
 
-				
-	def add_all(self):
-		for path in sys.path:
-			for entry in self.add_path(path):
-				yield entry
-		
-				
-	def add_stdlib(self):
-		for entry in self.add_path(parser.stdlib_path()):
-			yield entry
+    def remove_filename(self, filename):
+        # TODO: remove documents where file does not exist anymore
+        self._writer.delete_by_term("filename", filename)
 
-		
+
+    def add_filename(self, filename, module_name):
+        try:
+            items = list(parser.parse(filename))
+        except Exception, exc:
+            print filename, exc
+            return
+        self.remove_filename(filename)
+        for entry in items:
+            kind, scope, name, lineno = entry
+            self._add(kind=kind, name=name, line=lineno, filename=filename, scope=module_name + "." + scope)
+        self._add(kind="module", name=module_name, line=0, filename=filename)
+
+
+    def add_path(self, path):
+        for kind, filename, module_name in parser.modules(path):
+            yield filename
+            if kind == "mod":
+                self.add_filename(filename, module_name)
+            else: # kind == "pkg"
+                base = os.path.basename(filename)
+                for pkg_filename in parser.tree(filename):
+                    pkg_mod = pkg_filename[len(filename)+1:].rstrip(".py")
+                    pkg = os.path.join(base, pkg_mod).replace("/", ".")
+                    self.add_filename(pkg_filename, pkg)
+
+
+    def add_all(self):
+        for path in sys.path:
+            for entry in self.add_path(path):
+                yield entry
+
+
+    def add_stdlib(self):
+        for entry in self.add_path(parser.stdlib_path()):
+            yield entry
+
+
 
 if __name__ == "__main__":
-	idx = Indexer("index")
-	for found in idx.add_all():
-		print found
-	idx.close()
+    idx = Indexer("index")
+    for found in idx.add_all():
+        print found
+    idx.close()

File pycode/sourceindex/models.py

 
 # for fulltext search in comments and doc-strings
 comments_schema = Schema(
-	filename=ID(stored=True), 
-	comments=TEXT)
+    filename=ID(stored=True),
+    comments=TEXT)
 
 
 analyzer = NgramWordAnalyzer()
 name_field = TEXT(analyzer=analyzer, phrase=False)
 
-	
+
 # for name search
 name_schema = Schema(
-	filename=ID(stored=True), 
-    name=TEXT(stored=True), 
-	kind=KEYWORD(stored=True), 
-	scope=KEYWORD(stored=True), 
-	line=NUMERIC(stored=True)
-	)
+    filename=ID(stored=True),
+    name=TEXT(stored=True),
+    kind=KEYWORD(stored=True),
+    scope=KEYWORD(stored=True),
+    line=NUMERIC(stored=True))

File pycode/sourceindex/quickfix.py

 from search import Search
 
 class QuickFixer(object):
-	
-	
-	def __init__(self, source):
-		self.source = source
-		self._search = None
-		
-		
-	def search(self, qs):
-		if self._search is None:
-			self._search = Search()
-		return self._search(qs)
 
-		
-	def is_constant(self, ident):
-		return ident.upper() == ident and "." not in ident
-	
-	
-	def is_call(self, expr):
-		popen = expr.find("(")
-		if popen == -1:
-			return False
-		pclose = expr.find(")", popen)
-		prefix = expr[:popen]
-	
-	
-	def add_constant(self, source, name, val):
-		pass
-	
 
-	def add_import(source, name, from_list=None):
-		pass
-	
-	
-	def add_function(source, name, params):
-		pass
+    def __init__(self, source):
+        self.source = source
+        self._search = None
 
-	
-	def add_method(self, name, params):
-		pass
+
+    def search(self, qs):
+        if self._search is None:
+            self._search = Search()
+        return self._search(qs)
+
+
+    def is_constant(self, ident):
+        return ident.upper() == ident and "." not in ident
+
+
+    def is_call(self, expr):
+        popen = expr.find("(")
+        if popen == -1:
+            return False
+        pclose = expr.find(")", popen)
+        prefix = expr[:popen]
+
+
+    def add_constant(self, source, name, val):
+        pass
+
+
+    def add_import(source, name, from_list=None):
+        pass
+
+
+    def add_function(source, name, params):
+        pass
+
+
+    def add_method(self, name, params):
+        pass

File pycode/sourceindex/search.py

 
 class Search(object):
 
-	
-	def __init__(self, path):
-		self._ix = open_dir(path)
 
+    def __init__(self, path):
+        self._ix = open_dir(path)
 
-	def search(self, qs):
-		with self._ix.searcher() as searcher:
-			query = QueryParser("name", self._ix.schema).parse(qs)
-			results = searcher.search(query, limit=100)
-			for hit in results:
-				yield hit
 
+    def search(self, qs):
+        with self._ix.searcher() as searcher:
+            query = QueryParser("name", self._ix.schema).parse(qs)
+            results = searcher.search(query, limit=100)
+            for hit in results:
+                yield hit
 
-				
+
+
 if __name__ == "__main__":
-	import sys
-	s = Search("index")
-	qs = " ".join(sys.argv[1:]) or "line:130 OR template"
-	for num, hit in enumerate(s.search(qs)):
-		print num+1, hit
+    import sys
+    s = Search("index")
+    qs = " ".join(sys.argv[1:]) or "line:130 OR template"
+    for num, hit in enumerate(s.search(qs)):
+        print num + 1, hit
 from PyQt4.QtCore import Qt
 from PyQt4.QtGui import QApplication, QPlainTextEdit, QMainWindow, QFont
 
-from pycode.project import Project
 from pycode.pyqtfrontend import PyCode
 
 sys.path.append("syntaxhighlighter")