ecr.commands.cmd_run

src/ecr/commands/cmd_run.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import os
import time
from typing import cast

from watchdog.events import FileSystemEventHandler

from .. import shared, ui
from ..core import WorkItem, WorkItemType, WorkManager
from ..core.defaultData import CIO_Types, CIO_SISO
from ..ui.command import Command, Namespace, ReturnCode
from .helper import assertInited, getItem, printFileModify


class RunWatchEventHandler(FileSystemEventHandler):
    def __init__(self, file, func):
        self.func = func
        self.file = file
        self.state = False

    def on_moved(self, event):  # pylint: disable=W0235
        super().on_moved(event)
        # self.func()

        # what = 'directory' if event.is_directory else 'file'
        # logging.info("Moved %s: from %s to %s", what, event.src_path,event.dest_path)

    def on_created(self, event):  # pylint: disable=W0235
        super().on_created(event)

    def on_deleted(self, event):  # pylint: disable=W0235
        super().on_deleted(event)
        # self.func()

    def on_modified(self, event):
        super().on_modified(event)
        if not self.file or os.path.split(event.src_path)[-1] == self.file:
            self.state = not self.state
            if self.state:  # one modify raise two event
                self.func()


class RunCommand(Command):
    @staticmethod
    def default(args: Namespace)->ReturnCode:  # pylint: disable=W0613
        if not assertInited():
            return ReturnCode.UNLOADED
        tman: WorkManager = cast(WorkManager, shared.getManager())
        console = ui.getConsole()
        if not args.file and not tman.currentFile:
            console.write("Please set file first")
            return ReturnCode.ERROR

        # pylint: disable=W0105
        """def func(ret): # for async
            try:
                ret.append(tman.execute(io=args.io, file=args.file))
            except:
                ret.append(False)

        ret = []

        new_thread = threading.Thread(target=func, args=(ret,))
        new_thread.start()

        while not tman.runner:
            pass

        while tman.runner != None and tman.runner.isRunning:
            cmd = ui.console.read()
            if cmd == "kill":
                ui.console.write(cmd)
                tman.runner.terminate()
                new_thread.join()
            elif tman.runner.canInput:
                tman.runner.input(cmd)

        result = ret[0] if len(ret) > 0 else False """

        if not args.watch:
            item, file = getItem(tman, args)
            if item.type == WorkItemType.Directory:
                args.io = CIO_SISO
            result = tman.execute(io=args.io, item=item)

            if not result:
                console.error("Running failed")
                return ReturnCode.RUNERR
            return ReturnCode.OK
        else:
            file = args.file if args.file else cast(
                WorkItem, tman.currentFile).name

            def func():
                item, file = getItem(tman, args)
                if item.type == WorkItemType.Directory:
                    args.io = CIO_SISO
                console.clear()
                console.info(f"Watching", end=" ")
                printFileModify(file)
                result = tman.execute(io=args.io, item=item)
                if not result:
                    console.error("Running failed")

            from watchdog.observers import Observer
            console.info(f"Watching {file} (press ctrl+c to end)")

            path = tman.workingDirectory if item.type == WorkItemType.File else item.path
            event_handler = RunWatchEventHandler(
                file if item.type == WorkItemType.File else None, func)
            observer = Observer()
            observer.schedule(event_handler, path, recursive=False)
            observer.start()
            try:
                while True:
                    time.sleep(1)
            except KeyboardInterrupt:
                observer.stop()
                console.info("Watching end.")
            observer.join()
            return ReturnCode.OK

    def __init__(self):
        super().__init__("run", help="Run code file", func=RunCommand.default)

    def createParser(self, parsers):
        cmd = super().createParser(parsers)
        cmd.add_argument("-io", "--io", choices=CIO_Types,
                         default=None, help="Change input and output")
        cmd.add_argument(
            "file", nargs="?", default=None, help="File name (only for this command)")
        cmd.add_argument("-w", "--watch", action="store_true",
                         default=False, help="Watch the file and run auto till Ctrl-C")
        cmd.add_argument("-d", "--dir", action="store_true",
                         default=False, help="As directory")
        return cmd