CITGuru / PyInquirer

A Python module for common interactive command line user interfaces
MIT License
1.92k stars 236 forks source link

AttributeError: module 'PyInquirer.prompts' has no attribute 'editor' #11

Closed Rishi-jha closed 5 years ago

Rishi-jha commented 5 years ago

I am getting this error while running the editor.py example.

Python version: 3.6

CITGuru commented 5 years ago

Hello, can you paste the error code here. To better understand the error

Rishi-jha commented 5 years ago

Yeah sure,

` PS C:\Users\Rishi\Downloads\PyInquirer-master\PyInquirer-master\examples> python .\editor.py module 'PyInquirer.prompts' has no attribute 'editor' Traceback (most recent call last): File "C:\Python37\lib\site-packages\PyInquirer\prompt.py", line 63, in prompt application = getattr(prompts, type).question(message, **_kwargs) AttributeError: module 'PyInquirer.prompts' has no attribute 'editor'

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File ".\editor.py", line 23, in answers = prompt(questions, style=default_style) File "C:\Python37\lib\site-packages\PyInquirer\prompt.py", line 84, in prompt raise ValueError('No question type \'%s\'' % type) ValueError: No question type 'editor' PS C:\Users\Rishi\Downloads\PyInquirer-master\PyInquirer-master\examples> ` It seems that it is looking for editor.py file in prompt package but unable to find so.

Rishi-jha commented 5 years ago

Hi Can you confirm if this is a bug? Or is it possible that i can work on this to fix this?

CITGuru commented 5 years ago

Hey, just added the editor fix and will take time to get that into work. But its currently working same as input. We'll have to add multiline=True or whip up something custom ourselves. :+1:

Rishi-jha commented 5 years ago

Cool, will look into something to make it more robust.

CITGuru commented 5 years ago

But the main aim, is to be able to launch default editor from the command line: https://github.com/CITGuru/PyInquirer/tree/master#editor---type-editor

I think we should just go for command line editors rather the platform default ones.

Rishi-jha commented 5 years ago

Well, opening a platform default is no big deal i guess. will try to look into that

CITGuru commented 5 years ago

Okay, I'll whip u an Editor class that will implement the default platform editor. But of course I'll prefer we just use the command line directly.

CITGuru commented 5 years ago


import os
import sys

WIN = sys.platform.startswith('win')

class Editor(object):

    def __init__(self, editor=None, env=None, require_save=True,
                 extension='.txt'):
        self.editor = editor
        self.env = env
        self.require_save = require_save
        self.extension = extension

    def get_editor(self):
        if self.editor is not None:
            return self.editor
        for key in 'VISUAL', 'EDITOR':
            rv = os.environ.get(key)
            if rv:
                return rv
        if WIN:
            return 'notepad'
        for editor in 'vim', 'nano':
            if os.system('which %s >/dev/null 2>&1' % editor) == 0:
                return editor
        return 'vi'

    def edit_file(self, filename):
        import subprocess
        editor = self.get_editor()
        if self.env:
            environ = os.environ.copy()
            environ.update(self.env)
        else:
            environ = None
        try:
            c = subprocess.Popen('%s "%s"' % (editor, filename),
                                 env=environ, shell=True)
            exit_code = c.wait()
            if exit_code != 0:
                raise Exception('%s: Editing failed!' % editor)
        except OSError as e:
            raise Exception('%s: Editing failed: %s' % (editor, e))

    def edit(self, text):
        import tempfile

        text = text or ''
        if text and not text.endswith('\n'):
            text += '\n'

        fd, name = tempfile.mkstemp(prefix='editor-', suffix=self.extension)
        try:
            if WIN:
                encoding = 'utf-8-sig'
                text = text.replace('\n', '\r\n')
            else:
                encoding = 'utf-8'
            text = text.encode(encoding)

            f = os.fdopen(fd, 'wb')
            f.write(text)
            f.close()
            timestamp = os.path.getmtime(name)

            self.edit_file(name)

            if self.require_save \
               and os.path.getmtime(name) == timestamp:
                return None

            f = open(name, 'rb')
            try:
                rv = f.read()
            finally:
                f.close()
            return rv.decode('utf-8-sig').replace('\r\n', '\n')
        finally:
            os.unlink(name)

def edit(text=None, editor=None, env=None, require_save=True,
         extension='.txt', filename=None):
    r"""Edits the given text in the defined editor.  If an editor is given
    (should be the full path to the executable but the regular operating
    system search path is used for finding the executable) it overrides
    the detected editor.  Optionally, some environment variables can be
    used.  If the editor is closed without changes, `None` is returned.  In
    case a file is edited directly the return value is always `None` and
    `require_save` and `extension` are ignored.

    If the editor cannot be opened a :exc:`UsageError` is raised.

    Note for Windows: to simplify cross-platform usage, the newlines are
    automatically converted from POSIX to Windows and vice versa.  As such,
    the message here will have ``\n`` as newline markers.

    :param text: the text to edit.
    :param editor: optionally the editor to use.  Defaults to automatic
                   detection.
    :param env: environment variables to forward to the editor.
    :param require_save: if this is true, then not saving in the editor
                         will make the return value become `None`.
    :param extension: the extension to tell the editor about.  This defaults
                      to `.txt` but changing this might change syntax
                      highlighting.
    :param filename: if provided it will edit this file instead of the
                     provided text contents.  It will not use a temporary
                     file as an indirection in that case.
    """
    editor = Editor(editor=editor, env=env, require_save=require_save,
                    extension=extension)
    if filename is None:
        return editor.edit(text)
    editor.edit_file(filename)

text = edit(text="HelloWorld")

print(text)```

This opens up a default platform text editor.
CITGuru commented 5 years ago

The fix for editor has been added to the current dev branch. You can pull the dev and run the editor.py example. You should also read about it here https://github.com/CITGuru/PyInquirer/tree/dev#editor---type-editor @Rishi-jha

jacksonbenete commented 5 years ago

To fix this same issue I needed to compile for the "examples" usage, that is if I just pip install PyInquirer I can't use editor, but if I download the github repo and pip install -e . in the repo directory then there is no problem.

CITGuru commented 5 years ago

@jacksonbenete Yea, thats because the current fix is not yet available even in the master branch. It still in dev release. You should do latter instead. In the next coming weeks I'll be pushing out all the fixes to master and on PyPI

joveice commented 5 years ago

State of this? I installed 1.0.2 and ran the example and it failed with: "ValueError: No question type 'editor'".

CITGuru commented 5 years ago

@joveice Sorry I had to delay the release of this fix cos of other fix I need to include. And my daily work has taken most of my available time. You can install from the dev branch

CITGuru commented 5 years ago

Bug release for this is here https://github.com/CITGuru/PyInquirer/releases/tag/1.0.3