Example #1
0
    def launch_convertion(self):
        """Convert build steps to target convertion.
        """

        Log.debug("Converting...")
        Converter.check() and Converter.save(self.steps)
        Log.debug("Conversion done!")
Example #2
0
    def check_instruction(self, line):
        """Check line from build steps if it's an instruction.

        Args:
            line (str): Build step line as string.

        Raises:
            Exception: If last topic is missing and step is found.

        Returns:
            self: Self instance.
        """

        if self.no_topic_skip and self.last_topic is None:
            self.last_step = None
            return self
        scan = Instruction.PATTERN.match(line)
        if scan is not None:
            step = scan.group("step")
            if Placeholder.scan_string(step):
                step = Placeholder.parse_string(step)
            punct = scan.group("punct")
            self.last_step = Instruction(self.get_line_number(), step, punct)
            if self.last_topic is None:
                Log.fatal("Unaccepted instruction: missing topic in guide")
            self.last_topic.add_step(self.last_step)
        return self
Example #3
0
 def __init__(self, args):
     self.args = args
     self.topic = None
     self.steps = None
     self.last_step = 0
     self.guide_topics = None
     self.convert = False
     self.fake_run = False
     Log.info("Initializing...")
Example #4
0
def unlock():
    """Releases a lock file.

    Raises:
        OSError: If lock file cannot be released.
    """

    if os.path.isfile(LOCK_FILE):
        os.remove(LOCK_FILE)
        Log.info("Removed temporary lock")
Example #5
0
    def output(cls):
        """Dump report of each saved property.
        """

        ran_status = (cls.current_step, cls.total_steps)
        Log.info("""Topic name: "%s" """ % cls.topic)
        Log.info("Steps ran successful %d out of %d" % ran_status)
        Log.info("""Last step error: "%s" """ % cls.error)
        Log.info("Runtime %ss" % cls.runtime)
        Log.info("Build %s" % cls.status.upper())
Example #6
0
    def run(self, ignore_fails=False):
        """Run all steps for the current selected topic.
        """

        if self.fake_run:
            Log.info("Topic '%s' faked run" % self.topic.get_title())
            Report.set_status("FAKED")
        else:
            self.launch_topic(ignore_fails)

        if self.convert:
            self.launch_convertion()
Example #7
0
 def install_packages(self, cmd, packages):
     installed = 0
     for pkg in packages:
         install_cmd = cmd_split(cmd.format(packages=pkg))
         install_output = Popen(install_cmd)
         while install_output.poll() is None:
             sleep(0.5)
         output = install_output.returncode
         Log.debug("Running (npm) %s ... %r" % (install_cmd, output == 0))
         if 0 == output:
             installed += 1
     return installed
Example #8
0
def lock():
    """Create a lock file.

    Raises:
        SystemExit: If a lock file already exists.
    """

    if os.path.isfile(LOCK_FILE):
        raise SystemExit("A build might be launched by another process")
    with open(LOCK_FILE, "a"):
        os.utime(LOCK_FILE, None)
        Log.info("Created temporary lock")
Example #9
0
 def install_packages(self, cmd, packages):
     installed = 0
     for pkg in packages:
         install_cmd = cmd_split(cmd.format(packages=pkg))
         install_output = Popen(install_cmd)
         while install_output.poll() is None:
             sleep(0.5)
         output = install_output.returncode
         log_status = (self.env.os_name, install_cmd, output == 0)
         Log.debug("Running (%s) %s ... %r" % log_status)
         if 0 == output:
             installed += 1
     return installed
Example #10
0
    def setup(self):
        """Setup project path, topic and topic pattern, convertion type.
        """

        # Look for a specific topic
        if self.args.topic is not None:
            Topic.set_project_topic(self.args.topic)
            Log.info("Topic changed to: %s" % self.args.topic)

        # Set topic pattern
        if self.args.topic_pattern is not None:
            Topic.set_project_topic_pattern(self.args.topic_pattern)
            Log.info("Topic pattern changed to: %s" % self.args.topic_pattern)

        # Change project path from current working directory to choosen path
        if self.args.guide is not None:
            Reader.set_project_path(self.args.guide)
            Log.info("Project guide location: %s" % self.args.guide)

        # Convert build steps to script before exit
        if self.args.convert is not None:
            Converter.prepare(self.args.convert)
            Log.info("Topic convertion set to: %s" % self.args.convert)
            self.convert = True

        # Toggle fake run
        self.fake_run = self.args.fake_run
Example #11
0
    def set_project_path(cls, project_path):
        """Change project path.

        Default is current working directory.

        Args:
            project_path (str): New project path.

        Raises:
            ValueError: If project path is not a string.
        """

        if not isinstance(project_path, (str, unicode)):
            Log.fatal("Project path must be string")
        cls.PATH = project_path.rstrip("/")
Example #12
0
def crash(message):
    """Crash application with message.

    Raises:
        SystemExit.
    """

    return Log.fatal("Unexpected crash! %s" % message)
Example #13
0
 def run(self, srv=None, *args, **kwargs):
     cmd = StatusService.check_systemd()
     if cmd is None:
         return self.fail("Unsupported OS: %s" % self.env.os_name)
     try:
         service_cmd = cmd.format(service=srv)
         log_status = (self.env.os_name, service_cmd)
         Log.debug("Service OS (%s) status: %s ..." % log_status)
         ok, status = StatusService.get_service_status(service_cmd)
         output = u"Service '%s' => %s" % (srv, status)
         if ok:
             self.success(output)
         else:
             self.fail(output)
     except CalledProcessError as e:
         self.fail(e.output)
     except Exception as e:
         self.fail(str(e))
Example #14
0
 def run(self, srv=None, *args, **kwargs):
     cmd = StopService.check_systemd()
     if cmd is None:
         return self.fail("Unsupported OS: %s" % self.env.os_name)
     try:
         service_cmd = cmd.format(service=srv)
         log_status = (self.env.os_name, service_cmd)
         Log.debug("Service OS (%s) stop: %s ..." % log_status)
         service_output = Popen(cmd_split(service_cmd))
         while service_output.poll() is None:
             sleep(0.5)
         if 0 != service_output.returncode:
             return self.fail(u"Service '%s' => failed to stop" % srv)
         self.success(u"Service '%s' => stopped" % srv)
     except CalledProcessError as e:
         self.fail(e.output)
     except Exception as e:
         self.fail(str(e))
Example #15
0
    def setup(self):
        """Setup if reader is properly called.

        Raises:
            ValueError: Project does not have build file.

        Returns:
            bool: Returns True if project setup is done.
        """

        if self.READER is None or self.PATH is None:
            return False
        filepath = self.PATH
        if path.isdir(filepath):
            filepath = path.join(self.PATH, self.READER)
        self.filename = path.abspath(filepath)
        if not self.exists():
            Log.fatal("Project doesn't have proper build file: %s" % filepath)
        return True
Example #16
0
    def parse(self, newlines=0):
        """Parse build steps file.

        Loop through all steps and check for topics and instructions.
        """

        Log.debug("Guide has %d lines" % len(self.content))
        self.last_guide = Guide()
        while self.has_next():
            line = self.get_line(strip=True)
            if len(line) == 0:
                newlines += 1
            else:
                newlines = 0
            if newlines >= 2:
                self.last_topic = None
            self.check_topic(line)
            self.check_instruction(line).check_payload(self.next_content())
            self.next_line()
Example #17
0
def analyze(statement, length=80):
    """Analyze all statements and print visual results.

    Returns:
        bool: True if all statements are ok, otherwise False.
    """

    lines = scan_statements(statement)
    results = self_analyze(lines)
    Log.debug("Listing all statements...")
    for action in statement.get_actions():
        try:
            text = action.parse_description()
        except Exception:
            text = "no description"
        delimiter = "-" * (length - 4)
        c_txt = u"\033[96m %-{}s \033[0m".format(length - 6)
        r_txt = u"\033[91m %-{}s \033[0m".format(length - 6)
        g_txt = u"\033[92m %-{}s \033[0m".format(length - 6)
        print(u"\033[90m|---|%-{}s|\033[0m".format(length - 4) % delimiter)
        print(u"\033[90m|   |\033[0m" + fmt(c_txt, text) + "\033[90m|\033[0m")
        print(u"\033[90m|---|%-{}s|\033[0m".format(length - 4) % delimiter)
        for line in action.parse_statements():
            if lines[line] > 1:
                status = UnicodeIcon.INVALID
                line_text = fmt(r_txt, line.strip())
            else:
                status = UnicodeIcon.VALID
                line_text = fmt(g_txt, line.strip())
            print_line = u"\033[90m|\033[0m " + status + u" \033[90m|\033[0m"
            print_line += line_text + u"\033[90m|\033[0m"
            print(print_line)
    print(u"\033[90m|---|%-{}s|\033[0m".format(length - 4) % delimiter)
    if not results:
        Log.error("Duplicated statements found!")
        for line, times in lines.iteritems():
            if times > 1:
                err = (times, line.strip())
                Log.error(" - line duplicated %d times: %s" % err)
        Log.error("Please correct these problems before running again.")
    else:
        Log.debug("Everything looks OK!")
    return results
Example #18
0
    def check_payload(self, content):
        """Check line from build steps if it's an instruction payload.

        Args:
            content (list): Build step lines ahead of current cursor.

        Returns:
            self: Self instance.
        """

        if self.last_step is None:
            return self
        if self.last_step.punct != Instruction.RunType.ARGS:
            return self
        newlines, borders = 0, []
        for i, next_line in enumerate(content):
            if len(borders) == 0 and newlines > 1:
                raise self.NoPayloadError(self.last_step)
            if next_line.strip() == "":
                newlines += 1
                continue
            if next_line.strip() == self.delimiter:
                borders.append(i)
            if len(borders) == 2:
                break
        if len(borders) == 1:
            raise self.UnclosedPayloadError(self.last_step)
        try:
            a, z = borders
            payload = content[1 + a:z]
            if Placeholder.scan_list(payload):
                payload = Placeholder.parse_list(payload)
            self.last_step.set_payload(payload)
            self.skip_line(lines=z + 1)
            self.last_step = None
        except Exception as e:
            Log.error(str(e))
            raise self.BadFormatError(self.last_step)
        return self
Example #19
0
def scan_lookup(statements, lookup, length=80):
    """Lookup a statement with example usage.

    Args:
        statements (Statement): Statement instance will all known statements.
        lookup           (str): String to lookup after in all statements.
    """

    Log.debug("Lookup after %s ..." % lookup)
    known_statements = statements.get_actions()
    actions = []

    # Check available statements
    if len(known_statements) == 0:
        return Log.error("Statements are missing")

    # Search in all statemnts
    for stmt in known_statements:
        if lookup.lower() in stmt.parse_description().lower():
            if stmt not in actions:
                actions.append(stmt)
        else:
            for exp in stmt.parse_statements():
                if lookup.lower() in exp.lower():
                    if stmt not in actions:
                        actions.append(stmt)

    # Handle missing action
    if len(actions) == 0:
        return Log.error("Nothing found for '%s'" % lookup)

    # Print lookup
    for action in actions:
        delimiter = "-" * (length)
        description = action.parse_description()
        desc = u"\033[96m %-{}s \033[0m".format(length - 2) % description
        print(u"\033[90m|%-{}s|\033[0m".format(length - 4) % delimiter)
        print(u"\033[90m|\033[0m" + desc + "\033[90m|\033[0m")
        print(u"\033[90m|%-{}s|\033[0m".format(length - 4) % delimiter)
        for text in action.parse_statements():
            stmt = u"\033[95m %-{}s \033[0m".format(length - 6) % text.strip()
            print(u"\033[90m|   |\033[0m" + stmt + "\033[90m|\033[0m")
        print(u"\033[90m|%-{}s|\033[0m".format(length - 4) % delimiter)
        for text in action.parse("sample"):
            sample = u"\033[93m %-{}s \033[0m".format(length -
                                                      6) % text.strip()
            print(u"\033[90m|   |\033[0m" + sample + "\033[90m|\033[0m")

    # Done
    print(u"\033[90m|%-{}s|\033[0m".format(length - 4) % delimiter)
    Log.debug("Done...")
Example #20
0
    def prepare(cls):
        """Statement initialization.

        Loops through all supported actions, validates and maps statements with
        actions.

        Returns:
            bool: True if statements are mapped successful.
        """

        Log.debug("Preparing to scan %d actions" % len(cls.__actions))
        for action in cls.__actions:
            if not callable(action):
                raise SystemExit("Expected action to be callable")
            Log.debug("Scanning action: %s" % action.parse_description())
            for line in action.parse_statements():
                exp = compile(line.strip(), IGNORECASE | UNICODE)
                cls.statements.update({exp: action})
                Log.debug("Updating known patterns: %s" % exp.pattern)
        if len(cls.statements) < len(cls.__actions):
            raise SystemExit("Unable to map statements to action")
        cls.ready = True
        Log.debug("All statements are scanned")
Example #21
0
    def print_report(self):
        """Dumps a report of the script outcome.
        """

        Log.info("Preparing to print report...")
        Report.output()
Example #22
0
    def parse(self):
        """Parse guide and extract topics.

        User prompter asks to choose a topic from the selection in order to
        know what steps are queued.
        """

        rr = ReadmeReader(validate=True)
        rr.read()
        rr.parse()
        Log.info("Parsing guide...")

        # Preview scanned guide
        if self.args.preview:
            Log.info("Loading guide preview...")
            rr.preview(150)

        # Scan guide for topics
        if self.args.topic is None:
            guide = rr.get_guide()
        else:
            guide = rr.get_guide_by_topic()
        if guide is None:
            Log.fatal("Guide has no such topic")

        # Prepare guide topics
        self.guide_topics = guide.get_topics()

        # Pair each step with appropriate statement
        if self.args.strict:
            if not all([self.pair_steps(t) for t in self.guide_topics]):
                Report.set_status("Halted")
                Report.set_error("Unsupported steps")
                Log.fatal("Cannot continue because of unsupported steps")
        else:
            for t in self.guide_topics:
                for step in t.get_steps():
                    pair = Matcher.pair_one(step)
                    if not pair:
                        self.guide_topics.remove(t)

        # Scan topics
        topics = [t.get_title() for t in guide.get_topics()]
        topics_len = len(topics)

        # Handle no topics
        if topics_len == 0:
            Log.fatal("No topics found")
        else:
            Log.info("Guide has %d topics" % topics_len)

        # Handle topics
        Log.info("Found the following topics...")
        print("")
        for pos, name in enumerate(topics):
            print(("%" + str(len(str(topics_len)) + 5) + "d) %s") %
                  (pos + 1, name))
        print(RUN_INSTRUCTIONS)

        # Display warnings
        if self.args.unsafe_shell:
            print(WARNING_UNSAFE_SHELL)

        # Save topic and topic's steps
        self.topic = self.get_user_input()
        self.steps = self.topic.get_steps()

        # Confirm topic
        print("")
        Log.info(u"Matching topic \033[92m%s\033[0m" % self.topic.get_title())

        # Patch topic imports
        self.patch_topic_invoke(self.steps)

        # Prepare report
        Report.set_total_steps(len(self.steps))
        Report.set_topic(self.topic.get_title())
        return self
Example #23
0
    def launch_topic(self, ignore_fails=False, failed=False):
        """Launch topic and run all steps.
        """

        total_steps = len(self.topic.get_steps())
        Log.info("Preparing to run %d steps from topic..." % total_steps)

        # Loop steps and run each one
        start_time = default_timer()
        Log.debug("Setting start time: %s" % start_time)

        success_log = u"\033[92m\u2713 (Success)\033[0m \033[93m%s\033[0m"
        failed_log = u"\033[91m? (Failed)\033[0m \033[95m%s\033[0m"
        error_log = u"\033[91m? (Error) %s\033[0m"

        for self.last_step, step in enumerate(self.steps):
            step_count, step_desc = self.last_step + 1, step.get_description()
            Log.debug("Preparing step (%d) %s" % (step_count, step_desc))
            Log.info(u"Running \033[93m%s\033[0m ..." % step.get_step())
            try:
                success, output = step.run()
                if success:
                    Log.info(success_log % output)
                else:
                    Log.info(failed_log % output)
                    if not ignore_fails:
                        failed = True
                        Report.set_error(output)
                        break
                Report.inc_step(1)
            except KeyboardInterrupt:
                Log.info("Stopping current step...")
                Log.warn("Interrupting may lead to unexpected results")
                Log.warn("Stop master process at your own risk (PID %s)" % PID)
            except Exception as e:
                failed = True
                Report.set_error(e)
                Log.info(error_log % str(e))
                break

        stop_time = default_timer()
        Log.debug("Set stop time: %s" % stop_time)
        Log.debug("Runtime %ss" % (stop_time - start_time))

        # Save runtime
        Report.set_runtime(stop_time - start_time)

        # Wrap up...
        Log.debug("Done running steps...")
        title = self.topic.get_title()
        if failed:
            Log.info("An error occured while topic '%s' was running" % title)
            Report.set_status("Failed")
        else:
            Log.info("Topic '%s' has ran all steps with no errors" % title)
            Report.set_status("OK")
        Log.debug("Closing...")
Example #24
0
def main(error=None):

    # Parse command line args
    args = Shell.parse()

    # System setup
    Sysenv.setup(__version__, args)

    # Check version and exit
    if args.version:
        return Sysenv.print_version()

    # Output application intro headers
    Sysenv.print_headers()

    # Set log verbose level
    Log.configure(verbose=args.verbose)

    # Set console verbose level
    Console.verbose = args.verbose

    # Prepare all statements
    Statement.prepare()

    # Lookup statement and example usage
    if args.lookup is not None:
        return scan_lookup(Statement, args.lookup)

    # Run analysis and exit
    if args.analyze:
        return analyze(Statement)

    # Self-analyze buildok and continue or crash
    self_analyze(None, Statement) or crash("Run an analyze and fix problems")

    # Setup placeholders
    Placeholder.config(args.placeholder)

    # Attach system environment to all actions
    Action.set_env(Sysenv)

    # Initialize script and run all steps
    guide_script = Script(args)
    guide_script.setup()

    # Create a lock file
    lock()
    try:

        # Parse guide and run all steps
        guide_script.parse().run()

    except Exception as e:
        if str(e) != "":
            error = e

    # Free lock file
    unlock()

    # Display report
    guide_script.print_report()

    # Throw any errors found...
    if environ.get("DEBUG") is not None and error is not None:
        raise Console.fatal(error)