Changeset 1013


Ignore:
Timestamp:
07/16/20 14:37:45 (3 weeks ago)
Author:
Maciej Komosinski
Message:

Turned off echo for communication under Windows; implemented sendDirectCommand() for sending any commands and getting their output

File:
1 edited

Legend:

Unmodified
Added
Removed
  • framspy/FramsticksCLI.py

    r971 r1013  
    1 from math import sqrt
    21from subprocess import Popen, PIPE, check_output
    32from enum import Enum
     
    2928        FILE_PREFIX = 'framspy_'
    3029
    31         RANDOMIZE_CMD = "rnd" + "\n"
    32         SETEXPEDEF_CMD = "expdef standard-eval" + "\n"
     30        RANDOMIZE_CMD = "Math.randomize();"
     31        SETEXPEDEF_CMD = "Simulator.expdef=\"standard-eval\";"
    3332        GETSIMPLEST_CMD = "getsimplest"
    3433        GETSIMPLEST_FILE = "simplest.gen"
     
    4645        CLI_INPUT_FILE = "genotypes.gen"
    4746
    48         _next_instance_id = count(0)  # "static" counter incremented when a new instance is created. Used for unique filenames
     47        _next_instance_id = count(0)  # "static" counter incremented when a new instance is created. Used to ensure unique filenames for each instance.
    4948
    5049
     
    8786                        import pexpect  # https://pexpect.readthedocs.io/en/stable/
    8887                        self.child = pexpect.spawn(' '.join(args))
    89                         self.child.setecho(False)  # linux only
     88                self.child.setecho(False)  # ask the communication to not copy to stdout what we write to stdin
    9089                print('OK.')
    9190
     
    101100                print('OK.')
    102101                if not self.DETERMINISTIC:
    103                         self.child.sendline(self.RANDOMIZE_CMD)
    104                 self.child.sendline(self.SETEXPEDEF_CMD)
     102                        self.sendDirectCommand(self.RANDOMIZE_CMD)
     103                self.sendDirectCommand(self.SETEXPEDEF_CMD)
    105104
    106105
    107106        def closeFramsticksCLI(self):
    108107                # End gracefully by sending end-of-file character: ^Z or ^D
    109                 # Without -Q argument ("quiet mode"), Framsticks CLI would print "Shell closed." for goodbye.
     108                # Without the -Q argument ("quiet mode"), Framsticks CLI would print "Shell closed." for goodbye.
    110109                self.child.sendline(chr(26 if os.name == "nt" else 4))
    111110
     
    134133
    135134
    136         def __readFromFramsCLIUntil(self, until_marker: str):
     135        def __readFromFramsCLIUntil(self, until_marker: str) -> str:
     136                output = ""
    137137                while True:
    138                         self.child.expect('\n')
     138                        self.child.expect('\r\n' if os.name == "nt" else '\n')
    139139                        msg = str(self.child.before)
    140140                        if self.PRINT_FRAMSTICKS_OUTPUT or msg.startswith("[ERROR]"):
     
    142142                        if until_marker in msg:
    143143                                break
     144                        else:
     145                                output += msg + '\n'
     146                return output
    144147
    145148
     
    163166                result_file_name = self.__getPrefixedFilename(result_file_name)
    164167                cmd = command + " " + " ".join(filenames_rel) + " " + result_file_name
    165                 self.child.sendline(cmd + '\n')
     168                self.child.sendline(cmd)
    166169                self.__readFromFramsCLIUntil(self.STDOUT_ENDOPER_MARKER)
    167170                filenames_abs.append(os.path.join(self.writing_path, self.OUTPUT_DIR, result_file_name))
     
    173176                for name in filenames:
    174177                        os.remove(name)
     178
     179
     180        sendDirectCommand_counter = count(0)  # an internal counter for the sendDirectCommand() method; should be static within that method but python does not allow
     181
     182
     183        def sendDirectCommand(self, command: str) -> str:
     184                """Sends any command to Framsticks CLI. Use when you know Framsticks and its scripting language, Framscript."""
     185                self.child.sendline(command.strip())
     186                next(FramsticksCLI.sendDirectCommand_counter)
     187                STDOUT_ENDOPER_MARKER = "uniqe-marker-" + str(FramsticksCLI.sendDirectCommand_counter)
     188                self.child.sendline("Simulator.print(\"%s\");" % STDOUT_ENDOPER_MARKER)
     189                return self.__readFromFramsCLIUntil(STDOUT_ENDOPER_MARKER)
    175190
    176191
     
    202217
    203218        def mutate(self, genotype: str) -> str:
     219                """
     220                Returns:
     221                        The genotype of the mutated individual. Empty string if the mutation failed.
     222                """
    204223                files = self.__runCommand(self.MUTATE_CMD, [genotype], self.MUTATE_FILE, self.GENO_SAVE_FILE_FORMAT["RAWGENO"])
    205224                with open(files[-1]) as f:
     
    209228
    210229
    211         def crossOver(self, genotype1: str, genotype2: str) -> str:
    212                 files = self.__runCommand(self.CROSSOVER_CMD, [genotype1, genotype2], self.CROSSOVER_FILE, self.GENO_SAVE_FILE_FORMAT["RAWGENO"])
     230        def crossOver(self, genotype_parent1: str, genotype_parent2: str) -> str:
     231                """
     232                Returns:
     233                        The genotype of the offspring. Empty string if the crossing over failed.
     234                """
     235                files = self.__runCommand(self.CROSSOVER_CMD, [genotype_parent1, genotype_parent2], self.CROSSOVER_FILE, self.GENO_SAVE_FILE_FORMAT["RAWGENO"])
    213236                with open(files[-1]) as f:
    214237                        child_genotype = "".join(f.readlines())
     
    276299        parsed_args = parseArguments()
    277300        framsCLI = FramsticksCLI(parsed_args.path, parsed_args.exe, parsed_args.pid)
     301
     302        print("Sending a direct command to Framsticks CLI that calculates \"4\"+2 yields", repr(framsCLI.sendDirectCommand("Simulator.print(\"4\"+2);")))
    278303
    279304        simplest = framsCLI.getSimplest('1' if parsed_args.genformat is None else parsed_args.genformat)
Note: See TracChangeset for help on using the changeset viewer.