Пример #1
0
 def open_file(self, root):
     '''Open the the file in vim using c.openWith.'''
     c = self.c
     efc = g.app.externalFilesController
     # Common arguments.
     tab_arg = "-tab" if self.uses_tab else ""
     remote_arg = "--remote" + tab_arg + "-silent"
     args = [self.vim_exe, "--servername", "LEO", remote_arg] # No cursor arg.
     if self.entire_file:
         # vim-open-file
         args.append('+0') # Go to first line of the file. This is an Ex command.
         assert root.isAnyAtFileNode(), root
         dir_ = g.setDefaultDirectory(c, root)
         fn = c.os_path_finalize_join(dir_, root.anyAtFileNodeName())
     else:
         # vim-open-node
         args.append(self.get_cursor_arg())
             # Set the cursor position to the current line in the node.
         ext = 'txt'
         fn = efc.create_temp_file(c, ext, c.p)
     c_arg = '%s %s' % (' '.join(args), fn)
     command = 'subprocess.Popen(%s,shell=True)' % c_arg
     try:
         subprocess.Popen(c_arg, shell=True)
     except OSError:
         g.es_print(command)
         g.es_exception()
Пример #2
0
    def connect (self,fname):

        '''Connect to the server.  Return True if the connection was established.'''

        trace = False and not g.unitTesting

        if trace: g.trace(fname,socket)

        if hasattr(socket,'AF_UNIX'):
            try:
                # pylint: disable=E1101
                # E1101:LProtoClient.connect: Module 'socket' has no 'AF_UNIX' member
                self.socket = socket.socket(socket.AF_UNIX,socket.SOCK_STREAM)
                self.socket.connect(fname)
                return True
            except Exception:
                g.es_print('lproto.py: failed to connect!',fname)
                g.es_exception(full=False,c=None)
                return False
        else:
            try:
                host = '172.16.0.0' # host is a local address.
                port = 1
                self.socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
                self.socket.connect((host,port),)
                self.socket.connect(fname)
                return True
            except Exception:
                g.es_print('lproto.py: failed to connect! host: %s, port: %s' % (
                    host,port))
                g.es_exception(full=False,c=None)
                return False
Пример #3
0
 def export_outline(self, root, fn=None):
     '''
     Entry point for export-jupyter-notebook
     Export the given .ipynb file.
     '''
     self.root = root
     if not fn:
         fn = self.get_file_name()
     if not fn:
         return False
     try:
         nb = self.make_notebook()
         s = self.convert_notebook(nb)
     except Exception:
         g.es_exception()
         return False
     if not s:
         return False
     s = g.toEncodedString(s, encoding='utf-8', reportErrors=True)
     try:
         with open(fn, 'wb') as f:
             f.write(s)
         g.es_print('wrote: %s' % fn)
     except IOError:
         g.es_print('can not open: %s' % fn)
     return True
Пример #4
0
    def listenToLog(self, event=None):
        '''
        A socket listener, listening on localhost. See:
        https://docs.python.org/2/howto/logging-cookbook.html#sending-and-receiving-logging-events-across-a-network

        Start this listener first, then start the broadcaster.

        leo/plugins/cursesGui2.py is a typical broadcaster.
        '''
        # Kill any previous listener.
        if g.app.log_listener:
            g.es_print('Killing previous listener')
            try:
                g.app.log_listener.kill()
            except Exception:
                g.es_exception()
            g.app.log_listener = None
        # Start a new listener.
        g.es_print('Starting log_listener.py')
        path = g.os_path_finalize_join(g.app.loadDir,
            '..', 'external', 'log_listener.py')
        g.app.log_listener = subprocess.Popen(
            [sys.executable, path],
            shell=False,
            universal_newlines=True,
        )
Пример #5
0
    def scan_tag(self, s, i, tag_level):
        '''
        Scan an xml tag starting with "<" or "</".

        Adjust the stack as appropriate:
        - "<" adds the tag to the stack.
        - "</" removes the top of the stack if it matches.
        '''
        assert s[i] == '<', repr(s[i])
        end_tag = self.match(s, i, '</')
        # Scan the tag.
        i += (2 if end_tag else 1)
        m = self.ch_pattern.match(s, i)
        if m:
            tag = m.group(0).lower()
            i += len(m.group(0))
        else:
            # All other '<' characters should have had xml/html escapes applied to them.
            self.error('missing tag in position %s of %r' % (i, s))
            g.es_print(repr(s))
            return i, tag_level
        if end_tag:
            self.pop_to_tag(tag, s)
            if tag in self.start_tags:
                tag_level -= 1
        else:
            self.stack.append(tag)
            if tag in self.start_tags:
                tag_level += 1
        return i, tag_level
Пример #6
0
 def open_file(self, root):
     '''Open the the file in vim using c.openWith.'''
     trace = False and not g.unitTesting
     c = self.c
     # Common arguments.
     if trace: g.trace(self.entire_file, root.h)
     cursor_arg = self.get_cursor_arg()
     tab_arg = "-tab" if self.uses_tab else ""
     remote_arg = "--remote" + tab_arg + "-silent"
     if self.entire_file:
         # vim-open-file.
         assert root.isAnyAtFileNode(), root
         args = [self.vim_exe, "--servername", "LEO", remote_arg] # No cursor arg.
         dir_ = g.setDefaultDirectory(c, root)
         fn = c.os_path_finalize_join(dir_, root.anyAtFileNodeName())
         c_arg = '%s %s' % (' '.join(args), fn)
         command = 'subprocess.Popen(%s,shell=True)' % c_arg
         if trace: g.trace(command)
         try:
             subprocess.Popen(c_arg, shell=True)
         except OSError:
             g.es_print(command)
             g.es_exception()
     else:
         # vim-open-node
         root.v._vim_old_body = root.v.b
             # Not used in existing code, but it may be used elsewhere.
         args = [self.vim_exe, "--servername", "LEO", remote_arg, cursor_arg]
         if trace: g.trace('c.openWith(%s)' % args)
         d = {'args': args,
              'ext': None,
              'kind': 'subprocess.Popen',
              'p': root.copy(),
         }
         c.openWith(d=d)
Пример #7
0
 def error(self, s):
     '''Issue an error, but do *not* cause a unit test to fail.'''
     trace = False or not g.unitTesting
     if trace:
         g.es_print(s)
     # Tell i.check to strip lws.
     self.ws_error = True
Пример #8
0
    def splitList (self,ivar,setting):

        '''Process lines containing pairs of entries 
        in a list whose *name* is ivar.
        Put the results in ivars whose names are ivar1 and ivar2.'''

        result1 = [] ; result2 = []
        aList = getattr(self,ivar)

        # Look for pairs.  Comments have already been removed.
        for s in aList:
            pair = s.split(' ')
            if len(pair) == 2 and pair[0].strip() and pair[1].strip():
                result1.append(pair[0].strip())
                result2.append(pair[1].strip())
            else:
                g.es_print('%s: ignoring line: %s' % (setting,s))

        # Set the ivars.
        name1 = '%s1' % ivar
        name2 = '%s2' % ivar
        setattr(self,name1, result1)
        setattr(self,name2, result2)

        if 0:
            g.trace(name1,getattr(self,name1))
            g.trace(name2,getattr(self,name2))
Пример #9
0
 def run(self, p=None):
     '''Run flake8 on all Python @<file> nodes in c.p's tree.'''
     c = self.c
     root = p or c.p
     # Make sure Leo is on sys.path.
     leo_path = g.os_path_finalize_join(g.app.loadDir, '..')
     if leo_path not in sys.path:
         sys.path.append(leo_path)
     # Run flake8 on all Python @<file> nodes in root's tree.
     t1 = time.time()
     found = False
     for p in root.self_and_subtree():
         found |= self.find(p)
     # Look up the tree if no @<file> nodes were found.
     if not found:
         for p in root.parents():
             if self.find(p):
                 found = True
                 break
     # If still not found, expand the search if root is a clone.
     if not found:
         isCloned = any([p.isCloned() for p in root.self_and_parents()])
         # g.trace(isCloned,root.h)
         if isCloned:
             for p in c.all_positions():
                 if p.isAnyAtFileNode():
                     isAncestor = any([z.v == root.v for z in p.self_and_subtree()])
                     # g.trace(isAncestor,p.h)
                     if isAncestor and self.find(p):
                         break
     paths = list(set(self.seen))
     if paths:
         self.check_all(paths)
     g.es_print('flake8: %s file%s in %s' % (
         len(paths), g.plural(paths), g.timeSince(t1)))
Пример #10
0
 def createMenusFromTables(self):
     c = self.c
     aList = c.config.getMenusList()
     if aList:
         self.createMenusFromConfigList(aList)
     else:
         g.es_print('No @menu setting found')
Пример #11
0
 def writeAbbreviations(self, event):
     '''Write abbreviations to a file.'''
     c = self.c
     fileName = g.app.gui.runSaveFileDialog(c,
         initialfile=None,
         title='Write Abbreviations',
         filetypes=[("Text", "*.txt"), ("All files", "*")],
         defaultextension=".txt")
     if not fileName: return
     try:
         d = self.abbrevs
         f = open(fileName, 'w')
         for name in sorted(d.keys()):
             val, tag = self.abbrevs.get(name)
             val = val.replace('\n', '\\n')
             # Fix bug #236: write continuations in same format as in
             # @data abbreviations nodes
             ### New code.
             ### val = ''.join([': %s' % (z) for z in g.splitLines(val)])
             s = '%s=%s\n' % (name, val)
             if not g.isPython3:
                 s = g.toEncodedString(s, reportErrors=True)
             f.write(s)
         f.close()
         g.es_print('wrote: %s' % fileName)
     except IOError:
         g.es('can not create', fileName)
Пример #12
0
 def findNode(self,c,p,headline):
     '''Return the node in p's subtree with given headline.'''
     p = g.findNodeInTree(c,p,headline)
     if not p:
         g.es_print('can not find',headline)
         assert False
     return p
Пример #13
0
 def open_file(self, root):
     '''Open the the file in vim using c.openWith.'''
     trace = (False or self.trace) and not g.unitTesting
     c = self.c
     efc = g.app.externalFilesController
     # Common arguments.
     if trace: g.trace(self.entire_file, root.h)
     # cursor_arg = self.get_cursor_arg()
     tab_arg = "-tab" if self.uses_tab else ""
     remote_arg = "--remote" + tab_arg + "-silent"
     args = [self.vim_exe, "--servername", "LEO", remote_arg] # No cursor arg.
     if self.entire_file:
         # vim-open-file
         assert root.isAnyAtFileNode(), root
         dir_ = g.setDefaultDirectory(c, root)
         fn = c.os_path_finalize_join(dir_, root.anyAtFileNodeName())
     else:
         # vim-open-node
         ext = 'txt'
         fn = efc.create_temp_file(c, ext, c.p)
     c_arg = '%s %s' % (' '.join(args), fn)
     command = 'subprocess.Popen(%s,shell=True)' % c_arg
     if trace: g.trace(command)
     try:
         subprocess.Popen(c_arg, shell=True)
     except OSError:
         g.es_print(command)
         g.es_exception()
Пример #14
0
 def restore_gnx(self,d,gnx,root,unl):
     '''
     d is an *outer* gnx dict, associating nodes *outside* the tree with positions.
     Let p1 be the position of the node *within* root's tree corresponding to unl.
     Let p2 be the position of any node *outside* root's tree with the given gnx.
     - Set p1.v.fileIndex = gnx.
     - If p2 exists, relink p1 so it is a clone of p2.
     '''
     trace = False and not g.unitTesting
     p1 = self.find_position_for_relative_unl(root,unl)
     fn = self.c.shortFileName()
     if p1:
         p2 = d.get(gnx)
         old_gnx = p1.v.gnx
         if p2:
             if p1.h == p2.h and p1.b == p2.b:
                 p1._relinkAsCloneOf(p2)
                 # Warning: p1 *no longer exists* here.
                 # _relinkAsClone does *not* set p1.v = p2.v.
                 if trace: g.trace(fn,'clone:',old_gnx,'->',gnx,unl)
             else:
                 g.es_print('mismatch in cloned node',p1.h)
         elif trace:
             g.trace(fn,' node:',old_gnx,'->',gnx,unl)
         g.app.nodeIndices.updateLastIndex(g.toUnicode(gnx))
     else:
         if trace: g.trace('unl not found: %s' % unl)
Пример #15
0
    def strip(self):

        '''Display a file with all sentinel lines removed'''

        # get a path object for this position
        c = self.c
        currentPath = self.getCurrentPath()
        if currentPath.exists():
            path = currentPath.abspath()
            s = 'currentPath: %s' % path
            g.es_print(s)
            filelines = path.lines()
            # Add an @ignore directive.
            lines = ['@ignore\n']
            verbatim = False
            for line in filelines:
                if verbatim:
                    lines.append(line)
                    verbatim = False
                elif line.strip().startswith('#@verbatim'):
                    verbatim = True
                elif not line.strip().startswith('#@'):
                    lines.append(line)
            c.setBodyText(self.current,''.join(lines))
        else:
            g.warning('path does not exist: %s' % (str(currentPath)))
Пример #16
0
 def run(self):
     '''Run Pylint on all Python @<file> nodes in c.p's tree.'''
     c, root = self.c, self.c.p
     rc_fn = self.get_rc_file()
     if not rc_fn:
         return
     # Make sure Leo is on sys.path.
     leo_path = g.os_path_finalize_join(g.app.loadDir, '..')
     if leo_path not in sys.path:
         sys.path.append(leo_path)
     # Run lint on all Python @<file> nodes in root's tree.
     t1 = time.time()
     found = False
     for p in root.self_and_subtree():
         found |= self.check(p, rc_fn)
     # Look up the tree if no @<file> nodes were found.
     if not found:
         for p in root.parents():
             if self.check(p, rc_fn):
                 found = True
                 break
     # If still not found, expand the search if root is a clone.
     if not found:
         isCloned = any([p.isCloned() for p in root.self_and_parents()])
         # g.trace(isCloned,root.h)
         if isCloned:
             for p in c.all_positions():
                 if p.isAnyAtFileNode():
                     isAncestor = any([z.v == root.v for z in p.self_and_subtree()])
                     # g.trace(isAncestor,p.h)
                     if isAncestor and self.check(p, rc_fn):
                         break
     if self.wait:
         g.es_print('pylint done %s' % g.timeSince(t1))
Пример #17
0
 def regularize_node(self,p,scanner):
     '''Regularize node p so that it will not cause problems.'''
    
     ok,parts = scanner(atAuto=True,parent=p,s=p.b,prepass=True)
     if not ok and not parts:
         g.es_print('please regularize:',p.h)
     return ok,parts
Пример #18
0
 def open_index(self, idx_dir):
     global index_error_given
     if os.path.exists(idx_dir):
         try:
             return open_dir(idx_dir)
         except ValueError:
             if not index_error_given:
                 index_error_given = True
                 g.es_print('bigdash.py: exception in whoosh.open_dir')
                 g.es_print('please remove this directory:', g.os_path_normpath(idx_dir))
             return None
             # Doesn't work: open_dir apparently leaves resources open,
             # so shutil.rmtree(idx_dir) fails.
                 # g.es_print('re-creating', repr(idx_dir))
                 # try:
                     # import shutil
                     # shutil.rmtree(idx_dir)
                     # os.mkdir(idx_dir)
                     # self.create()
                     # return open_dir(idx_dir)
                 # except Exception as why:
                     # g.es_print(why)
                     # return None
     else:
         try:
             os.mkdir(idx_dir)
             self.create()
             return open_dir(idx_dir)
         except Exception:
             g.es_exception()
             return None
Пример #19
0
    def pop_to_tag(self, tag, s):
        '''
        Attempt to pop tag from the top of the stack.

        If the top doesn't match, issue a warning and attempt to recover.
        '''
        trace = False
        if not self.stack:
            self.error('Empty tag stack: %s' % tag)
            g.es_print(repr(s))
            return
        if trace:
            g.trace(tag, repr(s))
            g.printList(self.stack)
        top = self.stack[-1]
        if top == tag:
            self.stack.pop()
            return
        # Only issue one warning per file.
        if trace or self.tag_warning_given:
            self.tag_warning_given = True
            self.error('mismatched closing tag: %s top: %s' % (tag, top))
            g.es_print(repr(s))
            if trace:
                g.trace(self.root.h)
                g.printList(self.stack)
        # Attempt a recovery.
        if tag in self.stack:
            while self.stack:
                top = self.stack.pop()
                # if trace: g.trace('POP: ', top)
                if top == tag:
                    return
Пример #20
0
 def findBuffer(self, name):
     v = self.tnodes.get(name)
     for p in self.c.all_unique_positions():
         if p.v == v:
             return p
     g.es_print("no node named", name, color='orange')
     return None
Пример #21
0
 def cleanAtCleanTree(self, event):
     '''
     Adjust whitespace in the nearest @clean tree,
     searching c.p and its ancestors.
     '''
     c = self.c
     # Look for an @clean node.
     for p in c.p.self_and_parents():
         if g.match_word(p.h, 0, '@clean') and p.h.rstrip().endswith('.py'):
             break
     else:
         g.es_print('no an @clean node found', p.h, color='blue')
         return
     # pylint: disable=undefined-loop-variable
     # p is certainly defined here.
     bunch = c.undoer.beforeChangeTree(p)
     n = 0
     undoType = 'clean-@clean-tree'
     for p2 in p.subtree():
         if self.cleanAtCleanNode(p2, undoType):
             n += 1
     if n > 0:
         c.setChanged(True)
         c.undoer.afterChangeTree(p, undoType, bunch)
     g.es_print('%s node%s cleaned' % (n, g.plural(n)))
Пример #22
0
 def abort(self):
     '''undo all monkey-patches.'''
     g.es_print('exiting table.py plugin')
     c, ec = self.c, self.ec
     c.tableController = None
     c.k.handleDefaultChar = self.old_handleDefaultChar
     ec.insertNewlineBase = self.old_insert_newline
Пример #23
0
def onIdle (tag,keywords):
    """Save the current document if it has a name"""
    global gDict
    guiName = g.app.gui.guiName()
    if guiName not in ('qt','qttabs'):
        return
    c = keywords.get('c')
    d = gDict.get(c.hash())
    if c and d and c.exists and c.mFileName and not g.app.killed and not g.unitTesting:
        # Wait the entire interval after c is first changed or saved.
        # Imo (EKR) this is the desired behavior.
        # It gives the user a chance to revert changes before they are changed.
        if c.changed:
            w = c.get_focus()
            if isinstance(w, QtWidgets.QLineEdit):
                # Saving now would destroy the focus.
                # There is **no way** to recreate outline editing after a redraw.
                pass
            else:
                last = d.get('last')
                interval = d.get('interval')
                if time.time()-last >= interval:
                    g.es_print("Autosave: %s" % time.ctime(),color="orange")
                    c.fileCommands.save(c.mFileName)
                    c.set_focus(w,force=True)
                    d['last'] = time.time()
                    gDict[c.hash()] = d
        else:
            d['last'] = time.time()
            gDict[c.hash()] = d
Пример #24
0
 def diff_file(self, fn):
     '''Create an outline describing the git diffs for fn.'''
     c = self.c
     s1 = self.get_file_from_rev(self.rev1, fn)
     s2 = self.get_file_from_rev(self.rev2, fn)
     lines1 = g.splitLines(s1)
     lines2 = g.splitLines(s2)
     diff_list = list(difflib.unified_diff(
         lines1,
         lines2,
         self.rev1 or 'uncommitted',
         self.rev2 or 'uncommitted',
     ))
     diff_list.insert(0, '@language patch\n')
     self.file_node = self.create_file_node(diff_list, fn)
     if c.looksLikeDerivedFile(fn):
         c1 = self.make_at_file_outline(fn, s1, self.rev1)
         c2 = self.make_at_file_outline(fn, s2, self.rev2)
     else:
         root = self.find_file(fn)
         if root:
             c1 = self.make_at_clean_outline(fn, root, s1, self.rev1)
             c2 = self.make_at_clean_outline(fn, root, s2, self.rev2)
         else:
             g.es_print('No outline for', fn)
             c1 = c2 = None
     if c1 and c2:
         self.make_diff_outlines(fn, c1, c2)
         self.file_node.b = '%s\n@language %s\n' % (
             self.file_node.b.rstrip(), c2.target_language)
Пример #25
0
 def createMenusFromTables(self):
     '''(leoMenu) Usually over-ridden.'''
     c = self.c
     aList = c.config.getMenusList()
     if aList:
         self.createMenusFromConfigList(aList)
     else:
         g.es_print('No @menu setting found')
Пример #26
0
 def clear(self, verbose=False):
     # Deletes all files in the fcache subdirectory.
     # It would be more thorough to delete everything
     # below the root directory, but it's not necessary.
     if verbose:
         g.red('clearing cache at directory...\n')
         g.es_print(self.root)
     self.conn.execute('delete from cachevalues;')
Пример #27
0
    def reportIfNodeChanged(self, child_tuple, child_v, fileName, parent_v):
        '''
        Schedule a recovered node if child_v is substantially different from an
        earlier version.

        Issue a (rare) warning if two different files are involved.
        '''
        trace = (False or g.app.debug) and not g.unitTesting
        always_warn = True # True always warn about changed nodes.
        c = self.c
        h, b, gnx, grandChildren = child_tuple
        old_b, new_b = child_v.b, b
        old_h, new_h = child_v.h, h
        # Leo 5.6: test headlines.
        same_head = old_h == new_h
        same_body = (
            old_b == new_b or
            new_b.endswith('\n') and old_b == new_b[: -1] or
            old_b.endswith('\n') and new_b == old_b[: -1]
        )
        if same_head and same_body:
            return
        old_roots = list(getattr(child_v, 'tempRoots', set()))
        same_file = (
            len(old_roots) == 0 or
            len(old_roots) == 1 and old_roots[0] == fileName
        )
        must_warn = not same_file
        if not hasattr(child_v, 'tempRoots'):
            child_v.tempRoots = set()
        child_v.tempRoots.add(fileName)
        if trace:
            # g.trace('same h: %s, same b: %s same fn: %s' % (
                # same_head, same_body, same_file))
            g.trace('fileName', fileName)
            g.trace('tempRoots', old_roots)
        if must_warn:
            # This is the so-called "rare" case:
            # The node differs  in two different external files.
            self.warning('out-of-sync node: %s' % h)
            g.es_print('using node in %s' % fileName)
        if always_warn or must_warn:
            if c.make_node_conflicts_node:
                g.es_print('creating recovered node:', h)
            c.nodeConflictList.append(g.bunch(
                tag='(cached)',
                fileName=fileName,
                gnx=gnx,
                b_old=child_v.b,
                h_old=child_v.h,
                b_new=b,
                h_new=h,
                root_v=parent_v,
            ))
        # Always update the node.
        child_v.h, child_v.b = h, b
        child_v.setDirty()
        c.changed = True # Tell getLeoFile to propegate dirty nodes.
Пример #28
0
 def add_words_from_dict(self, kind, fn, words):
     '''For use by DefaultWrapper.'''
     trace = False and not g.unitTesting
     if trace:
         g.es_print('%6s words in %6s dictionary: %s' % (
             len(words or []), kind, g.os_path_normpath(fn)))
     for word in words or []:
         self.words.add(word)
         self.words.add(word.lower())
Пример #29
0
 def run(self):
     '''run the refactorings.'''
     proj = self.proj
     if proj:
         proj.validate(proj.root)
         self.refactor()
         proj.close()
     else:
         g.es_print('rope not found')
Пример #30
0
 def clear(self, verbose=False):
     # Deletes all files in the fcache subdirectory.
     # It would be more thorough to delete everything
     # below the root directory, but it's not necessary.
     if verbose:
         g.red('clearing cache at directory...\n')
         g.es_print(self.root)
     for z in self.keys():
         self.__delitem__(z)
Пример #31
0
    def error(self, s):

        g.es_print(s)
Пример #32
0
    def error(self, s):

        g.es_print('error: %s' % (s), color='red')
Пример #33
0
def find_missing_docstrings(event):
    '''Report missing docstrings in the log, with clickable links.'''
    c = event.get('c')
    if not c:
        return

    #@+others # Define functions
    #@+node:ekr.20190615181104.1: *4* function: has_docstring
    def has_docstring(lines, n):
        '''
        Returns True if function/method/class whose definition
        starts on n-th line in lines has a docstring
        '''
        # By Виталије Милошевић.
        for line in lines[n:]:
            s = line.strip()
            if not s or s.startswith('#'):
                continue
            if s.startswith(('"""', "'''")):
                return True
        return False

    #@+node:ekr.20190615181104.2: *4* function: is_a_definition
    def is_a_definition(line):
        '''Return True if line is a definition line.'''
        # By Виталије Милошевић.
        # It may be useful to skip __init__ methods because their docstring
        # is usually docstring of the class
        return (line.startswith(('def ', 'class '))
                and not line.partition(' ')[2].startswith('__init__'))

    #@+node:ekr.20190615182754.1: *4* function: is_root
    def is_root(p):
        '''
        A predicate returning True if p is an @<file> node that is not under @nopylint.
        '''
        for parent in p.self_and_parents():
            if g.match_word(parent.h, 0, '@nopylint'):
                return False
        return p.isAnyAtFileNode() and p.h.strip().endswith('.py')

    #@+node:ekr.20190615180900.1: *4* function: clickable_link
    def clickable_link(p, i):
        '''Return a clickable link to line i of p.b.'''
        link = p.get_UNL(with_proto=True, with_count=True, with_index=True)
        return "%s,%d" % (link, i)

    #@-others

    count, found, t1 = 0, [], time.clock()
    for root in g.findRootsWithPredicate(c, c.p, predicate=is_root):
        for p in root.self_and_subtree():
            lines = p.b.split('\n')
            for i, line in enumerate(lines):
                if is_a_definition(line) and not has_docstring(lines, i):
                    count += 1
                    if root.v not in found:
                        found.append(root.v)
                        g.es_print('')
                        g.es_print(root.h)
                    print(line)
                    g.es(line, nodeLink=clickable_link(p, i + 1))
                    break
    g.es_print('')
    g.es_print('found %s missing docstring%s in %s file%s in %5.2f sec.' %
               (count, g.plural(count), len(found), g.plural(len(found)),
                (time.clock() - t1)))
Пример #34
0
def note(s):

    g.es_print(s)
Пример #35
0
 def warning(self, s):
     g.es_print(f"Warning: {s}")
Пример #36
0
 def oops(message, i, j):
     # This can be called from c-to-python, in which case warnings should be suppressed.
     if giveWarnings:
         g.error('** changed ', p.h)
         g.es_print('%s after\n%s' % (message, repr(''.join(s[i:j]))))
Пример #37
0
    def warning (self,s):

        g.es_print('Warning: %s' % (s))
Пример #38
0
    def add_bookmark(self):
        """Return the file like 'f' that leo_interface.send_head makes

        """

        parsed_url = urlparse.urlparse(self.request_handler.path)
        query = urlparse.parse_qs(parsed_url.query)

        # print(parsed_url.query)
        # print(query)

        name = query.get('name', ['NO TITLE'])[0]
        url = query['url'][0]

        c = None  # outline for bookmarks
        previous = None  # previous bookmark for adding selections
        parent = None  # parent node for new bookmarks
        using_root = False

        path = self.bookmark_unl

        # g.trace(path)

        if path:
            # EKR
            i = path.find('#')
            if i > -1:
                path = path[:i].strip()
                unl = path[i + 1:].strip()
            else:
                path = path
                unl = ''

            parsed = urlparse.urlparse(path)  # self.bookmark_unl) # EKR
            leo_path = os.path.expanduser(parsed.path)

            c = g.openWithFileName(leo_path, old_c=None)

            if c:
                g.es_print("Opened '%s' for bookmarks" %
                           path)  # self.bookmark_unl)

                parsed = urlparse.urlparse(unl)  # self.bookmark_unl) # EKR
                if parsed.fragment:
                    g.recursiveUNLSearch(parsed.fragment.split("-->"), c)
                parent = c.currentPosition()
                if parent.hasChildren():
                    previous = parent.getFirstChild()
            else:
                g.es_print("Failed to open '%s' for bookmarks" %
                           self.bookmark_unl)

        if c is None:
            using_root = True
            c = g.app.commanders()[0]
            parent = c.rootPosition()
            previous = c.rootPosition()

        f = StringIO()

        if previous and url == previous.b.split('\n', 1)[0]:
            # another marking of the same page, just add selection
            self.add_bookmark_selection(previous,
                                        query.get('selection', [''])[0])

            c.selectPosition(previous)  # required for body text redraw
            c.redraw()

            f.write("""
    <body onload="setTimeout('window.close();', 350);" style='font-family:mono'>
    <p>Selection added</p></body>""")

            return f

        if '_form' in query:
            # got extra details, save to new node

            f.write("""
    <body onload="setTimeout('window.close();', 350);" style='font-family:mono'>
    <p>Bookmark saved</p></body>""")

            if using_root:
                nd = parent.insertAfter()
                nd.moveToRoot(c.rootPosition())
            else:
                nd = parent.insertAsNthChild(0)
            if g.pluginIsLoaded('leo.plugins.bookmarks'):
                nd.h = name
            else:
                nd.h = '@url ' + name

            selection = query.get('selection', [''])[0]
            if selection:
                selection = '\n\n"""\n' + selection + '\n"""'

            nd.b = "%s\n\nTags: %s\n\n%s\n\nCollected: %s%s\n\n%s" % (
                url,
                query.get('tags', [''])[0],
                query.get('_name', [''])[0],
                time.strftime("%c"),
                selection,
                query.get('description', [''])[0],
            )
            c.setChanged(True)
            c.selectPosition(nd)  # required for body text redraw
            c.redraw()

            return f

        # send form to collect extra details

        f.write("""
    <html><head><style>
    body {font-family:mono; font-size: 80%%;}
    th {text-align:right}
    </style>
    </head><body onload='document.getElementById("tags").focus();'>
    <form method='GET' action='/_/add/bkmk/'>
    <input type='hidden' name='_form' value='1'/>
    <input type='hidden' name='_name' value=%s/>
    <input type='hidden' name='selection' value=%s/>
    <table>
    <tr><th>Tags:</th><td><input id='tags' name='tags' size='60'/>(comma sep.)</td></tr>
    <tr><th>Title:</th><td><input name='name' value=%s size='60'/></td></tr>
    <tr><th>URL:</th><td><input name='url' value=%s size='60'/></td></tr>
    <tr><th>Notes:</th><td><textarea name='description' cols='60' rows='6'></textarea></td></tr>
    </table>
    <input type='submit' value='Save'/><br/>
    </form>
    </body></html>""" %
                (quoteattr(name), quoteattr(query.get(
                    'selection', [''])[0]), quoteattr(name), quoteattr(url)))

        return f
Пример #39
0
def pwd_command(self, event=None):
    """Refresh an @<file> node from disk."""
    g.es_print('pwd:', os.getcwd())
Пример #40
0
def hello_command2(event):
    g.es_print('Hello 2 from %s' % (g.shortFileName(__file__)), color='red')
Пример #41
0
def hello_command(event):
    g.es_print('Hello from %s' % (g.shortFileName(__file__)), color='purple')
Пример #42
0
 def pr(*args, **keys):
     if not g.app.unitTesting:
         g.es_print(*args, **keys)
Пример #43
0
 def report(message):
     g.es_print('loadOnePlugin: %s' % message)
Пример #44
0
    def getScript(
        c,
        p,
        useSelectedText=True,
        forcePythonSentinels=True,
        sentinels=True,
        language='python',
    ):
        '''
        Return the expansion of the selected text of node p.
        Return the expansion of all of node p's body text if
        p is not the current node or if there is no text selection.
        '''

        #@+others
        #@+node:bob.20170726143458.18: *4* extractExecutableString()
        def extractExecutableString(c, p, s, language='python'):
            '''
            Return all lines for the given @language directive.

            Ignore all lines under control of any other @language directive.
            '''
            if leoG.unitTesting:
                return s  # Regretable, but necessary.

            langCur = language
            pattern = re.compile(r'\s*@language\s+(\w+)')
            result = []
            for line in leoG.splitLines(s):
                m = pattern.match(line)
                if m:  # Found an @language directive.
                    langCur = m.group(1)
                elif langCur == language:
                    result.append(line)
            return ''.join(result)

        #@+node:bob.20170726143458.19: *4* composeScript()
        def composeScript(c, p, s, forcePythonSentinels=True, sentinels=True):
            '''Compose a script from p.b.'''

            if s.strip():
                # Important: converts unicode to utf-8 encoded strings.
                script = c.atFileCommands.stringToString(
                    p.copy(),
                    s,
                    forcePythonSentinels=forcePythonSentinels,
                    sentinels=sentinels)
                script = script.replace("\r\n", "\n")  # Use brute force.
                # Important, the script is an **encoded string**, not a unicode string.
                return script
            else:
                return ''

        #@-others

        w = c.frame.body.wrapper
        if not p: p = c.p
        try:
            if leoG.app.inBridge:
                s = p.b
            elif w and p == c.p and useSelectedText and w.hasSelection():
                s = w.getSelectedText()
            else:
                s = p.b
            # Remove extra leading whitespace so the user may execute indented code.
            s = leoG.removeExtraLws(s, c.tab_width)
            s = extractExecutableString(c, p, s, language)
            script = composeScript(c,
                                   p,
                                   s,
                                   forcePythonSentinels=forcePythonSentinels,
                                   sentinels=sentinels)
        except Exception:
            leoG.es_print("unexpected exception in Leo-Babel getScript()")
            raise
        return script
Пример #45
0
    def open_temp_file(self, c, d, fn, testing=False):
        '''
        Open a temp file corresponding to fn in an external editor.

        d is a dictionary created from an @openwith settings node.

        'args':     the command-line arguments to be used to open the file.
        'ext':      the file extension.
        'kind':     the method used to open the file, such as subprocess.Popen.
        'name':     menu label (used only by the menu code).
        'shortcut': menu shortcut (used only by the menu code).
        '''
        trace = False and not g.unitTesting
        testing = testing or g.unitTesting
        arg_tuple = d.get('args', [])
        arg = ' '.join(arg_tuple)
        kind = d.get('kind')
        try:
            # All of these must be supported because they
            # could exist in @open-with nodes.
            command = '<no command>'
            if kind == 'os.startfile':
                command = 'os.startfile(%s)' % self.join(arg, fn)
                if trace: g.trace(command)
                # pylint: disable=no-member
                # trust the user not to use this option on Linux.
                if not testing: os.startfile(self.join(arg, fn))
            elif kind == 'exec':
                g.es_print('open-with exec no longer valid.')
                # command = 'exec(%s)' % self.join(arg,fn)
                # if trace: g.trace(command)
                # if not testing:
                # exec(self.join(arg,fn),{},{})
            elif kind == 'os.spawnl':
                filename = g.os_path_basename(arg)
                command = 'os.spawnl(%s,%s,%s)' % (arg, filename, fn)
                if trace: g.trace(command)
                if not testing: os.spawnl(os.P_NOWAIT, arg, filename, fn)
            elif kind == 'os.spawnv':
                filename = os.path.basename(arg_tuple[0])
                vtuple = arg_tuple[1:]
                vtuple.insert(0, filename)
                # add the name of the program as the first argument.
                # Change suggested by Jim Sizelove.
                vtuple.append(fn)
                command = 'os.spawnv(%s)' % (vtuple)
                if trace: g.trace(command)
                if not testing:
                    os.spawnv(os.P_NOWAIT, arg[0], vtuple)  #???
            elif kind == 'subprocess.Popen':
                c_arg = self.join(arg, fn)
                command = 'subprocess.Popen(%s)' % c_arg
                if trace: g.trace(command)
                if not testing:
                    try:
                        subprocess.Popen(c_arg, shell=True)
                    except OSError:
                        g.es_print('c_arg', repr(c_arg))
                        g.es_exception()
            elif g.isCallable(kind):
                # Invoke openWith like this:
                # c.openWith(data=[func,None,None])
                # func will be called with one arg, the filename
                if trace: g.trace('%s(%s)' % (kind, fn))
                command = '%s(%s)' % (kind, fn)
                if not testing: kind(fn)
            else:
                command = 'bad command:' + str(kind)
                if not testing: g.trace(command)
            return command  # for unit testing.
        except Exception:
            g.es('exception executing open-with command:', command)
            g.es_exception()
            return 'oops: %s' % command
Пример #46
0
    def ad_command(self, event=None):
        #@+<< adoc command docstring >>
        #@+node:ekr.20190515115100.1: *3* << adoc command docstring >>
        '''
        The adoc command writes all @adoc nodes in the selected tree to the
        files given in each @doc node. If no @adoc nodes are found, the
        command looks up the tree.

        Each @adoc node should have the form: `@adoc x.adoc`. Relative file names
        are relative to the base directory.  See below.

        By default, the adoc command creates AsciiDoctor headings from Leo
        headlines. However, the following kinds of nodes are treated differently:
            
        - @ignore-tree: Ignore the node and its descendants.
        - @ignore-node: Ignore the node.
        - @no-head:     Ignore the headline. Do not generate a heading.

        After running the adoc command, use the asciidoctor command to convert the
        x.adoc files to x.html.
            
        Settings
        --------

        AsciiDoctor itself provides many settings, including::
            
            = Title
            :stylesdir: mystylesheets/
            :stylesheet: mystyles.css
            
        These can also be specified on the command line::

            asciidoctor -a stylesdir=mystylesheets/ -a stylesheet=mystyles.css 

        @string adoc-base-directory specifies the base for relative file names.
        The default is c.frame.openDirectory

        Scripting interface
        -------------------

        Scripts may invoke the adoc command as follows::
            
            event = g.Bunch(base_dicrectory=my_directory, p=some_node)
            c.asciiDoctorCommands.ad_command(event=event)
            
        This @button node runs the adoc command and coverts all results to .html::
            
            import os
            paths = c.asciiDoctorCommands.ad_command(event=g.Bunch(p=p))
            paths = [z.replace('/', os.path.sep) for z in paths]
            input_paths = ' '.join(paths)
            g.execute_shell_commands(['asciidoctor %s' % input_paths])

        '''
        #@-<< adoc command docstring >>

        def predicate(p):
            return self.ad_filename(p)

        # Find all roots.
        t1 = time.time()
        c = self.c
        p = event.p if event and hasattr(event, 'p') else c.p
        if event and hasattr(event, 'base_directory'):
            self.base_directory = event.base_directory
        else:
            directory = c.config.getString('adoc-base-directory')
            self.base_directory = directory or c.frame.openDirectory
        roots = g.findRootsWithPredicate(c, p, predicate=predicate)
        if not roots:
            g.warning('No @ascii-doctor nodes in', p.h)
            return []
        # Write each root.
        paths = []
        for p in roots:
            path = self.write_root(p)
            if path:
                paths.append(path)
        t2 = time.time()
        g.es_print('adoc: wrote %s file%s in %4.2f sec.' % (
            len(paths), g.plural(len(paths)), t2 - t1))
        return paths
Пример #47
0
 def error(self, s):
     '''Issue an error, but do *not* cause a unit test to fail.'''
     g.es_print('\nin %s' % self.root.h)
     g.es_print(s)
     # Tell i.check to strip lws.
     self.ws_error = True
Пример #48
0
 def report(message):
     if trace and not g.unitTesting:
         g.es_print(f"loadOnePlugin: {message}")
Пример #49
0
    def do_fts(self, tgt, qs):

        ss = g.toUnicode(qs)
        q = None
        if ss.startswith("f "):
            q = ss[2:]
        if not (q or ss.startswith("fts ")):
            return False
        if not whoosh:
            g.es("Whoosh not installed (easy_install whoosh)")
            return False
        # print("Doing fts: %s" % qs)
        fts = self.fts
        if ss.strip() == "fts init":
            fts.create()
            for c2 in g.app.commanders():
                g.es_print("Scanning: %s" % c2.shortFileName())
                fts.index_nodes(c2)
            g.es_print('Scan complete')
        if ss.strip() == "fts add":
            # print("Add new docs")
            docs = set(fts.statistics()["documents"])
            # print("Have docs", docs)
            for c2 in g.app.commanders():
                fn = c2.mFileName
                if fn not in docs:
                    g.es_print("Adding document to index: %s" %
                               c2.shortFileName())
                    fts.index_nodes(c2)
            g.es_print('Add complete')
        if ss.strip() == "fts refresh":
            for c2 in g.app.commanders():
                fn = c2.mFileName
                g.es_print("Refreshing: %s" % c2.shortFileName())
                fts.drop_document(fn)
                fts.index_nodes(c2)
            g.es_print('Refresh complete')
            gc = self.gnxcache
            gc.clear()
            gc.update_new_cs()
        if q:
            self.do_find(tgt, q)
Пример #50
0
 def convert_at_file_to_at_auto(self, root):
     if root.isAtFileNode():
         ConvertController(self.c, root).run()
     else:
         g.es_print('not an @file node:', root.h)
Пример #51
0
    def open_file_in_external_editor(self, c, d, fn, testing=False):
        """
        Open a file fn in an external editor.

        This will be an entire external file, or a temp file for a single node.

        d is a dictionary created from an @openwith settings node.

            'args':     the command-line arguments to be used to open the file.
            'ext':      the file extension.
            'kind':     the method used to open the file, such as subprocess.Popen.
            'name':     menu label (used only by the menu code).
            'p':        the nearest @<file> node, or None.
            'shortcut': menu shortcut (used only by the menu code).
        """
        testing = testing or g.unitTesting
        arg_tuple = d.get('args', [])
        arg = ' '.join(arg_tuple)
        kind = d.get('kind')
        try:
            # All of these must be supported because they
            # could exist in @open-with nodes.
            command = '<no command>'
            if kind in ('os.system', 'os.startfile'):
                # New in Leo 5.7:
                # Use subProcess.Popen(..., shell=True)
                c_arg = self.join(arg, fn)
                if not testing:
                    try:
                        subprocess.Popen(c_arg, shell=True)
                    except OSError:
                        g.es_print('c_arg', repr(c_arg))
                        g.es_exception()
            elif kind == 'exec':
                g.es_print('open-with exec no longer valid.')
            elif kind == 'os.spawnl':
                filename = g.os_path_basename(arg)
                command = f"os.spawnl({arg},{filename},{fn})"
                if not testing: os.spawnl(os.P_NOWAIT, arg, filename, fn)
            elif kind == 'os.spawnv':
                filename = os.path.basename(arg_tuple[0])
                vtuple = arg_tuple[1:]
                vtuple.insert(0, filename)
                    # add the name of the program as the first argument.
                    # Change suggested by Jim Sizelove.
                vtuple.append(fn)
                command = f"os.spawnv({vtuple})"
                if not testing:
                    os.spawnv(os.P_NOWAIT, arg[0], vtuple)  #???
            elif kind == 'subprocess.Popen':
                c_arg = self.join(arg, fn)
                command = f"subprocess.Popen({c_arg})"
                if not testing:
                    try:
                        subprocess.Popen(c_arg, shell=True)
                    except OSError:
                        g.es_print('c_arg', repr(c_arg))
                        g.es_exception()
            elif hasattr(kind, '__call__'):
                # Invoke openWith like this:
                # c.openWith(data=[func,None,None])
                # func will be called with one arg, the filename
                command = f"{kind}({fn})"
                if not testing: kind(fn)
            else:
                command = 'bad command:' + str(kind)
                if not testing: g.trace(command)
            return command  # for unit testing.
        except Exception:
            g.es('exception executing open-with command:', command)
            g.es_exception()
            return f"oops: {command}"
Пример #52
0
 def drop_document(self, docfile):
     writer = self.ix.writer()
     g.es_print("Drop index: %s" % g.shortFileName(docfile))
     writer.delete_by_term("doc", docfile)
     writer.commit()
Пример #53
0
 def error(self, s):
     '''Report an error.'''
     g.es_print(s, color='red')
Пример #54
0
 def write(self, s):
     if s.strip():
         g.es_print(s)
Пример #55
0
 def findNode(self, c, p, headline):
     p = g.findNodeInTree(c, p, headline)
     if not p:
         g.es_print('can not find', headline)
         assert False
     return p
Пример #56
0
 def message(self, s):
     g.es_print(s, color='orange')
Пример #57
0
#@+leo-ver=5-thin
#@+node:ekr.20160412101008.1: * @file importers/ipynb.py
'''The @auto importer for Jupyter (.ipynb) files.'''
import re
import leo.core.leoGlobals as g
trace_import = False
try:
    import nbformat
except ImportError:
    if trace_import:
        g.es_print('import-jupyter-notebook requires nbformat package')
    nbformat = None


#@+others
#@+node:ekr.20160412101537.2: ** class Import_IPYNB
class Import_IPYNB(object):
    '''A class to import .ipynb files.'''

    #@+others
    #@+node:ekr.20160412101537.3: *3* ctor
    def __init__(self, c=None, importCommands=None, atAuto=None):
        '''Ctor for Import_IPYNB class.'''
        self.c = importCommands.c if importCommands else c
        # Commander of present outline.
        # g.trace('(Import_IPYNB)', self.c)
        self.cell = None
        # The present cell node.
        self.cell_n = None
        # The number of the top-level node being scanned.
        self.code_language = None
Пример #58
0
 def report(self, s):
     '''Issue a message.'''
     g.es_print(s)
Пример #59
0
 def regularize_node(self, p, scanner):
     '''Regularize node p so that it will not cause problems.'''
     ok, parts = scanner(atAuto=True, parent=p, s=p.b, prepass=True)
     if not ok and not parts:
         g.es_print('please regularize:', p.h)
     return ok, parts
Пример #60
0
 def run(self):
     '''Convert an @file tree to @auto tree.'''
     trace = True and not g.unitTesting
     trace_s = False
     cc = self
     c = cc.c
     root, pd = cc.root, c.persistenceController
     # set the expected imported headline for all vnodes.
     t1 = time.clock()
     cc.set_expected_imported_headlines(root)
     t2 = time.clock()
     # Delete all previous @data nodes for this tree.
     cc.delete_at_data_nodes(root)
     t3 = time.clock()
     # Ensure that all nodes of the tree are regularized.
     ok = pd.prepass(root)
     t4 = time.clock()
     if not ok:
         g.es_print('Can not convert', root.h, color='red')
         if trace:
             g.trace(
                 '\n  set_expected_imported_headlines: %4.2f sec' %
                 (t2 - t1),
                 # '\n  delete_at_data_nodes:          %4.2f sec' % (t3-t2),
                 '\n  prepass:                         %4.2f sec' %
                 (t4 - t3),
                 '\n  total:                           %4.2f sec' %
                 (t4 - t1))
         return
     # Create the appropriate @data node.
     at_auto_view = pd.update_before_write_foreign_file(root)
     t5 = time.clock()
     # Write the @file node as if it were an @auto node.
     s = cc.strip_sentinels()
     t6 = time.clock()
     if trace and trace_s:
         g.trace('source file...\n', s)
     # Import the @auto string.
     ok, p = cc.import_from_string(s)
     t7 = time.clock()
     if ok:
         # Change at_auto_view.b so it matches p.gnx.
         at_auto_view.b = pd.at_data_body(p)
         # Recreate the organizer nodes, headlines, etc.
         pd.update_after_read_foreign_file(p)
         t8 = time.clock()
         # if not ok:
         # p.h = '@@' + p.h
         # g.trace('restoring original @auto file')
         # ok,p = cc.import_from_string(s)
         # if ok:
         # p.h = '@@' + p.h + ' (restored)'
         # if p.next():
         # p.moveAfter(p.next())
         t9 = time.clock()
     else:
         t8 = t9 = time.clock()
     if trace:
         g.trace(
             '\n  set_expected_imported_headlines: %4.2f sec' % (t2 - t1),
             # '\n  delete_at_data_nodes:          %4.2f sec' % (t3-t2),
             '\n  prepass:                         %4.2f sec' % (t4 - t3),
             '\n  update_before_write_foreign_file:%4.2f sec' % (t5 - t4),
             '\n  strip_sentinels:                 %4.2f sec' % (t6 - t5),
             '\n  import_from_string:              %4.2f sec' % (t7 - t6),
             '\n  update_after_read_foreign_file   %4.2f sec' % (t8 - t7),
             '\n  import_from_string (restore)     %4.2f sec' % (t9 - t8),
             '\n  total:                           %4.2f sec' % (t9 - t1))
     if p:
         c.selectPosition(p)
     c.redraw()