Beispiel #1
0
    def handle_cli_command(self, config):
        """Handle a command from the CLI.
        """
        cmd = config["cli_command"]
        # aliases
        if cmd[0] in ["mod", "module", "modules"]:
            cmd[0] = "modules"

        # allowed cli commands
        if cmd[:2] in (["modules", "list"], ["modules", "details"]):
            docstrings.show_modules(config, cmd[1:])
        # docstring formatting and checking
        elif cmd[:2] in (["docstring", "check"], ["docstring", "update"]):
            if cmd[1] == "check":
                show_diff = len(cmd) > 2 and cmd[2] == "diff"
                if show_diff:
                    mods = cmd[3:]
                else:
                    mods = cmd[2:]
                docstrings.check_docstrings(show_diff, config, mods)
            if cmd[1] == "update":
                if len(cmd) < 3:
                    print_stderr("Error: you must specify what to update")
                    sys.exit(1)

                if cmd[2] == "modules":
                    docstrings.update_docstrings()
                else:
                    docstrings.update_readme_for_modules(cmd[2:])
        elif cmd[:2] in (["modules", "enable"], ["modules", "disable"]):
            # TODO: to be implemented
            pass
        else:
            print_stderr("Error: unknown command")
            sys.exit(1)
Beispiel #2
0
    def handle_cli_command(self, config):
        """Handle a command from the CLI.
        """
        cmd = config["cli_command"]
        # aliases
        if cmd[0] in ["mod", "module", "modules"]:
            cmd[0] = "modules"

        # allowed cli commands
        if cmd[:2] in (["modules", "list"], ["modules", "details"]):
            docstrings.show_modules(config, cmd[1:])
        # docstring formatting and checking
        elif cmd[:2] in (["docstring", "check"], ["docstring", "update"]):
            if cmd[1] == "check":
                show_diff = len(cmd) > 2 and cmd[2] == "diff"
                docstrings.check_docstrings(show_diff, config)
            if cmd[1] == "update":
                if len(cmd) < 3:
                    print_stderr("Error: you must specify what to update")
                    sys.exit(1)

                if cmd[2] == "modules":
                    docstrings.update_docstrings()
                else:
                    docstrings.update_readme_for_modules(cmd[2:])
        elif cmd[:2] in (["modules", "enable"], ["modules", "disable"]):
            # TODO: to be implemented
            pass
        else:
            print_stderr("Error: unknown command")
            sys.exit(1)
Beispiel #3
0
    def handle_cli_command(self, config):
        """Handle a command from the CLI.
        """
        cmd = config['cli_command']
        # aliases
        if cmd[0] in ['mod', 'module', 'modules']:
            cmd[0] = 'modules'

        # allowed cli commands
        if cmd[:2] in (['modules', 'list'], ['modules', 'details']):
            docstrings.show_modules(config, cmd[1:])
        # docstring formatting and checking
        elif cmd[:2] in (['docstring', 'check'], ['docstring', 'update']):
            if cmd[1] == 'check':
                show_diff = len(cmd) > 2 and cmd[2] == 'diff'
                if show_diff:
                    mods = cmd[3:]
                else:
                    mods = cmd[2:]
                docstrings.check_docstrings(show_diff, config, mods)
            if cmd[1] == 'update':
                if len(cmd) < 3:
                    print_stderr('Error: you must specify what to update')
                    sys.exit(1)

                if cmd[2] == 'modules':
                    docstrings.update_docstrings()
                else:
                    docstrings.update_readme_for_modules(cmd[2:])
        elif cmd[:2] in (['modules', 'enable'], ['modules', 'disable']):
            # TODO: to be implemented
            pass
        else:
            print_stderr('Error: unknown command')
            sys.exit(1)
Beispiel #4
0
    def handle_cli_command(self, config):
        """Handle a command from the CLI.
        """
        cmd = config['cli_command']
        # aliases
        if cmd[0] in ['mod', 'module', 'modules']:
            cmd[0] = 'modules'

        # allowed cli commands
        if cmd[:2] in (['modules', 'list'], ['modules', 'details']):
            docstrings.show_modules(config, cmd[1:])
        # docstring formatting and checking
        elif cmd[:2] in (['docstring', 'check'], ['docstring', 'update']):
            if cmd[1] == 'check':
                show_diff = len(cmd) > 2 and cmd[2] == 'diff'
                if show_diff:
                    mods = cmd[3:]
                else:
                    mods = cmd[2:]
                docstrings.check_docstrings(show_diff, config, mods)
            if cmd[1] == 'update':
                if len(cmd) < 3:
                    print_stderr('Error: you must specify what to update')
                    sys.exit(1)

                if cmd[2] == 'modules':
                    docstrings.update_docstrings()
                else:
                    docstrings.update_readme_for_modules(cmd[2:])
        elif cmd[:2] in (['modules', 'enable'], ['modules', 'disable']):
            # TODO: to be implemented
            pass
        else:
            print_stderr('Error: unknown command')
            sys.exit(1)
Beispiel #5
0
def update_docstrings():
    '''
    update the docstring of each module using info in the
    modules/README.md file
    '''
    modules_dict = parse_readme()
    files = {}
    # update modules
    for mod in modules_dict:
        mod_file = os.path.join(modules_directory(), mod + '.py')
        with open(mod_file) as f:
            files[mod] = f.readlines()

    for mod in files:
        replaced = False
        done = False
        lines = False
        out = []
        quotes = None
        for row in files[mod]:
            # deal with single or double quoted docstring
            if not quotes:
                if row.strip().startswith('"""'):
                    quotes = '"""'
                if row.strip().startswith("'''"):
                    quotes = "'''"
            if quotes and row.strip().startswith(quotes) and not done:
                out.append(row)
                if not replaced:
                    out = out + [
                        ''.join(_to_docstring(modules_dict[mod])).strip() +
                        '\n'
                    ]
                    replaced = True
                if lines:
                    done = True
                if not done and not lines:
                    lines = True
                continue
            if not lines or done:
                out.append(row)
        mod_file = os.path.join(modules_directory(), mod + '.py')
        with open(mod_file, 'w') as f:
            f.writelines(out)
    print_stderr('Modules updated from README.md')
Beispiel #6
0
def update_docstrings():
    """
    update the docstring of each module using info in the
    modules/README.md file
    """
    modules_dict = parse_readme()
    files = {}
    # update modules
    for mod in modules_dict:
        mod_file = modules_directory() / f"{mod}.py"
        with mod_file.open() as f:
            files[mod] = f.readlines()

    for mod, rows in files.items():
        replaced = False
        done = False
        lines = False
        out = []
        quotes = None
        for row in rows:
            # deal with single or double quoted docstring
            if not quotes:
                if row.strip().startswith('"""'):
                    quotes = '"""'
                if row.strip().startswith("'''"):
                    quotes = "'''"
            if quotes and row.strip().startswith(quotes) and not done:
                out.append(row)
                if not replaced:
                    out = out + [
                        "".join(_to_docstring(modules_dict[mod])).strip() +
                        "\n"
                    ]
                    replaced = True
                if lines:
                    done = True
                if not done and not lines:
                    lines = True
                continue
            if not lines or done:
                out.append(row)
        mod_file = modules_directory() / f"{mod}.py"
        with mod_file.open("w") as f:
            f.writelines(out)
    print_stderr("Modules updated from README.md")
Beispiel #7
0
def update_readme_for_modules(modules):
    """
    Update README.md updating the sections for the module names listed.
    """
    readme = parse_readme()
    module_docstrings = core_module_docstrings()
    if modules == ["__all__"]:
        modules = core_module_docstrings().keys()
    for module in modules:
        if module in module_docstrings:
            print_stderr(f"Updating README.md for module {module}")
            readme[module] = module_docstrings[module]
        else:
            print_stderr(f"Module {module} not in core modules")

    # write the file
    readme_file = modules_directory() / "README.md"
    readme_file.write_text(create_readme(readme))
Beispiel #8
0
def update_readme_for_modules(modules):
    """
    Update README.md updating the sections for the module names listed.
    """
    readme = parse_readme()
    module_docstrings = core_module_docstrings()
    if modules == ["__all__"]:
        modules = core_module_docstrings().keys()
    for module in modules:
        if module in module_docstrings:
            print_stderr("Updating README.md for module {}".format(module))
            readme[module] = module_docstrings[module]
        else:
            print_stderr("Module {} not in core modules".format(module))

    # write the file
    readme_file = os.path.join(modules_directory(), "README.md")
    with open(readme_file, "w") as f:
        f.write(create_readme(readme))
Beispiel #9
0
def check_docstrings(show_diff=False, config=None, mods=None):
    """
    Check docstrings in module match the README.md
    """

    readme = parse_readme()
    modules_readme = core_module_docstrings(config=config)
    warned = False
    if create_readme(readme) != create_readme(modules_readme):
        for module in sorted(readme):
            if mods and module not in mods:
                continue
            err = None
            if module not in modules_readme:
                err = "Module {} in README but not in /modules".format(module)
            elif (
                "".join(readme[module]).strip()
                != "".join(modules_readme[module]).strip()
            ):
                err = "Module {} docstring does not match README".format(module)
            if err:
                if not warned:
                    print_stderr("Documentation does not match!\n")
                    warned = True
                print_stderr(err)

        for module in modules_readme:
            if mods and module not in mods:
                continue
            if module not in readme:
                print_stderr("Module {} in /modules but not in README".format(module))
        if show_diff:
            print_stderr(
                "\n".join(
                    difflib.unified_diff(
                        create_readme(readme).split("\n"),
                        create_readme(modules_readme).split("\n"),
                    )
                )
            )
        else:
            if warned:
                print_stderr("\nUse `py3-cmd docstring --diff` to view diff.")
Beispiel #10
0
def update_readme_for_modules(modules):
    '''
    Update README.md updating the sections for the module names listed.
    '''
    readme = parse_readme()
    module_docstrings = core_module_docstrings()
    if modules == ['__all__']:
        modules = core_module_docstrings().keys()
    for module in modules:
        if module in module_docstrings:
            print_stderr('Updating README.md for module {}'.format(module))
            readme[module] = module_docstrings[module]
        else:
            print_stderr('Module {} not in core modules'.format(module))

    # write the file
    readme_file = os.path.join(modules_directory(), 'README.md')
    with open(readme_file, 'w') as f:
        f.write(create_readme(readme))
Beispiel #11
0
def check_docstrings(show_diff=False, config=None, mods=None):
    '''
    Check docstrings in module match the README.md
    '''

    readme = parse_readme()
    modules_readme = core_module_docstrings(config=config)
    warned = False
    if (create_readme(readme) != create_readme(modules_readme)):
        for module in sorted(readme):
            if mods and module not in mods:
                continue
            err = None
            if module not in modules_readme:
                err = '\tModule {} in README but not in /modules'.format(
                    module
                )
            elif ''.join(readme[module]).strip() != ''.join(modules_readme[
                    module]).strip():
                err = '\tModule {} docstring does not match README'.format(
                    module
                )
            if err:
                if not warned:
                    print_stderr('Documentation does not match!\n')
                    warned = True
                print_stderr(err)

        for module in modules_readme:
            if mods and module not in mods:
                continue
            if module not in readme:
                print_stderr(
                    '\tModule {} in /modules but not in README'.format(module))
        if show_diff:
            print_stderr('\n'.join(difflib.unified_diff(
                create_readme(readme).split('\n'), create_readme(
                    modules_readme).split('\n'))))
        else:
            if warned:
                print_stderr(
                    '\nUse `py3status docstring check diff` to view diff.'
                )
Beispiel #12
0
def check_docstrings(show_diff=False, config=None, mods=None):
    """
    Check docstrings in module match the README.md
    """

    readme = parse_readme()
    modules_readme = core_module_docstrings(config=config)
    warned = False
    if create_readme(readme) != create_readme(modules_readme):
        for module in sorted(readme):
            if mods and module not in mods:
                continue
            err = None
            if module not in modules_readme:
                err = f"Module {module} in README but not in /modules"
            elif (
                "".join(readme[module]).strip()
                != "".join(modules_readme[module]).strip()
            ):
                err = f"Module {module} docstring does not match README"
            if err:
                if not warned:
                    print_stderr("Documentation does not match!\n")
                    warned = True
                print_stderr(err)

        for module in modules_readme:
            if mods and module not in mods:
                continue
            if module not in readme:
                print_stderr(f"Module {module} in /modules but not in README")
        if show_diff:
            print_stderr(
                "\n".join(
                    difflib.unified_diff(
                        create_readme(readme).split("\n"),
                        create_readme(modules_readme).split("\n"),
                    )
                )
            )
        else:
            if warned:
                print_stderr("\nUse `py3-cmd docstring --diff` to view diff.")
Beispiel #13
0
def update_readme_for_modules(modules):
    """
    Update README.md updating the sections for the module names listed.
    """
    readme = parse_readme()
    module_docstrings = core_module_docstrings()
    if modules == ["__all__"]:
        modules = core_module_docstrings().keys()
    for module in modules:
        if module in module_docstrings:
            print_stderr("Updating README.md for module {}".format(module))
            readme[module] = module_docstrings[module]
        else:
            print_stderr("Module {} not in core modules".format(module))

    # write the file
    readme_file = os.path.join(modules_directory(), "README.md")
    with open(readme_file, "w") as f:
        f.write(create_readme(readme))
Beispiel #14
0
    def report_exception(self,
                         msg,
                         notify_user=True,
                         level="error",
                         error_frame=None):
        """
        Report details of an exception to the user.
        This should only be called within an except: block Details of the
        exception are reported eg filename, line number and exception type.

        Because stack trace information outside of py3status or it's modules is
        not helpful in actually finding and fixing the error, we try to locate
        the first place that the exception affected our code.

        Alternatively if the error occurs in a module via a Py3 call that
        catches and reports the error then we receive an error_frame and use
        that as the source of the error.

        NOTE: msg should not end in a '.' for consistency.
        """
        # Get list of paths that our stack trace should be found in.
        py3_paths = [os.path.dirname(__file__)] + self.config["include_paths"]
        traceback = None

        try:
            # We need to make sure to delete tb even if things go wrong.
            exc_type, exc_obj, tb = sys.exc_info()
            stack = extract_tb(tb)
            error_str = "{}: {}\n".format(exc_type.__name__, exc_obj)
            traceback = [error_str]

            if error_frame:
                # The error occurred in a py3status module so the traceback
                # should be made to appear correct.  We caught the exception
                # but make it look as though we did not.
                traceback += format_stack(error_frame, 1) + format_tb(tb)
                filename = os.path.basename(error_frame.f_code.co_filename)
                line_no = error_frame.f_lineno
            else:
                # This is a none module based error
                traceback += format_tb(tb)
                # Find first relevant trace in the stack.
                # it should be in py3status or one of it's modules.
                found = False
                for item in reversed(stack):
                    filename = item[0]
                    for path in py3_paths:
                        if filename.startswith(path):
                            # Found a good trace
                            filename = os.path.basename(item[0])
                            line_no = item[1]
                            found = True
                            break
                    if found:
                        break
            # all done!  create our message.
            msg = "{} ({}) {} line {}.".format(msg, exc_type.__name__,
                                               filename, line_no)
        except:  # noqa e722
            # something went wrong report what we can.
            msg = "{}.".format(msg)
        finally:
            # delete tb!
            del tb
        # log the exception and notify user
        self.py3_wrapper.log(msg, "warning")
        if traceback:
            # if debug is not in the config  then we are at an early stage of
            # running py3status and logging is not yet available so output the
            # error to STDERR so it can be seen
            if "debug" not in self.config:
                print_stderr("\n".join(traceback))
            elif self.config.get("log_file"):
                self.py3_wrapper.log("".join(["Traceback\n"] + traceback))
        if notify_user:
            self.py3_wrapper.notify_user(msg, level=level)
Beispiel #15
0
    def report_exception(self, msg, notify_user=True, level="error", error_frame=None):
        """
        Report details of an exception to the user.
        This should only be called within an except: block Details of the
        exception are reported eg filename, line number and exception type.

        Because stack trace information outside of py3status or it's modules is
        not helpful in actually finding and fixing the error, we try to locate
        the first place that the exception affected our code.

        Alternatively if the error occurs in a module via a Py3 call that
        catches and reports the error then we receive an error_frame and use
        that as the source of the error.

        NOTE: msg should not end in a '.' for consistency.
        """
        # Get list of paths that our stack trace should be found in.
        py3_paths = [os.path.dirname(__file__)] + self.config["include_paths"]
        traceback = None

        try:
            # We need to make sure to delete tb even if things go wrong.
            exc_type, exc_obj, tb = sys.exc_info()
            stack = extract_tb(tb)
            error_str = "{}: {}\n".format(exc_type.__name__, exc_obj)
            traceback = [error_str]

            if error_frame:
                # The error occurred in a py3status module so the traceback
                # should be made to appear correct.  We caught the exception
                # but make it look as though we did not.
                traceback += format_stack(error_frame, 1) + format_tb(tb)
                filename = os.path.basename(error_frame.f_code.co_filename)
                line_no = error_frame.f_lineno
            else:
                # This is a none module based error
                traceback += format_tb(tb)
                # Find first relevant trace in the stack.
                # it should be in py3status or one of it's modules.
                found = False
                for item in reversed(stack):
                    filename = item[0]
                    for path in py3_paths:
                        if filename.startswith(path):
                            # Found a good trace
                            filename = os.path.basename(item[0])
                            line_no = item[1]
                            found = True
                            break
                    if found:
                        break
            # all done!  create our message.
            msg = "{} ({}) {} line {}.".format(
                msg, exc_type.__name__, filename, line_no
            )
        except:  # noqa e722
            # something went wrong report what we can.
            msg = "{}.".format(msg)
        finally:
            # delete tb!
            del tb
        # log the exception and notify user
        self.py3_wrapper.log(msg, "warning")
        if traceback:
            # if debug is not in the config  then we are at an early stage of
            # running py3status and logging is not yet available so output the
            # error to STDERR so it can be seen
            if "debug" not in self.config:
                print_stderr("\n".join(traceback))
            elif self.config.get("log_file"):
                self.py3_wrapper.log("".join(["Traceback\n"] + traceback))
        if notify_user:
            self.py3_wrapper.notify_user(msg, level=level)
Beispiel #16
0
def check_docstrings(show_diff=False, config=None):
    '''
    Check docstrings in module match the README.md
    '''

    readme = parse_readme()
    modules_readme = core_module_docstrings(config=config)
    if (create_readme(readme) != create_readme(modules_readme)):
        print_stderr('Documentation does not match!\n')
        for module in readme:
            if module not in modules_readme:
                print_stderr(
                    '\tModule {} in README but not in /modules'.format(module))
            elif ''.join(readme[module]).strip() != ''.join(modules_readme[
                    module]).strip():
                print_stderr(
                    '\tModule {} docstring does not match README'.format(
                        module))

        for module in modules_readme:
            if module not in readme:
                print_stderr(
                    '\tModule {} in /modules but not in README'.format(module))
        if show_diff:
            print_stderr('\n'.join(difflib.unified_diff(
                create_readme(readme).split('\n'), create_readme(
                    modules_readme).split('\n'))))
        else:
            print_stderr()
            print_stderr('Use `py3status docstring check diff` to view diff.')
Beispiel #17
0
def show_modules(config, params):
    '''
    List modules available optionally with details.
    '''
    details = params[0] == 'details'
    if details:
        modules_list = params[1:]
        core_mods = True
        user_mods = True
    else:
        user_mods = True
        core_mods = True
        modules_list = []
        if len(params) == 2:
            if params[1] == 'user':
                user_mods = True
                core_mods = False
            elif params[1] == 'core':
                user_mods = False
                core_mods = True
    if details:
        print_stderr('Module details:')
    else:
        print_stderr('Available modules:')
    modules = core_module_docstrings(include_core=core_mods,
                                     include_user=user_mods,
                                     config=config)
    for name in sorted(modules.keys()):
        if modules_list and name not in modules_list:
            continue
        module = _to_docstring(modules[name])
        desc = module[0][:-1]
        if details:
            dash_len = len(name)
            print_stderr('=' * dash_len)
            print_stderr(name)
            print_stderr('=' * dash_len)
            for description in module:
                print_stderr(description[:-1])
        else:
            print_stderr('  %-22s %s' % (name, desc))
Beispiel #18
0
def check_docstrings(show_diff=False, config=None):
    '''
    Check docstrings in module match the README.md
    '''

    readme = parse_readme()
    modules_readme = core_module_docstrings(config=config)
    if (create_readme(readme) != create_readme(modules_readme)):
        print_stderr('Documentation does not match!\n')
        for module in readme:
            if module not in modules_readme:
                print_stderr(
                    '\tModule {} in README but not in /modules'.format(module))
            elif ''.join(readme[module]).strip() != ''.join(
                    modules_readme[module]).strip():
                print_stderr(
                    '\tModule {} docstring does not match README'.format(
                        module))

        for module in modules_readme:
            if module not in readme:
                print_stderr(
                    '\tModule {} in /modules but not in README'.format(module))
        if show_diff:
            print_stderr('\n'.join(
                difflib.unified_diff(
                    create_readme(readme).split('\n'),
                    create_readme(modules_readme).split('\n'))))
        else:
            print_stderr()
            print_stderr('Use `py3status docstring check diff` to view diff.')