Skip to content

Commit

Permalink
runslog changes for enterrepl, better printing (#41)
Browse files Browse the repository at this point in the history
* runslog changes for enterrepl, better printing

* this should fix the CI error

* CI test for validation

* slog file and out dir are optional non tagged args

* usage text change

* completer exit fix
  • Loading branch information
Michaelgathara authored Aug 3, 2023
1 parent c6e3cac commit 4174d23
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 34 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ temp-out/
test-input
souffle-out
compiler/test/
.DS_Store
73 changes: 51 additions & 22 deletions runslog
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,17 @@
"""
Runs a slog file on server or locally.
USAGE: `./runslog -s <server-address IP> <slogfile> <out-dir> -f <factdir>`
`./runslog -j4 -s <server-address IP> <slogfile> <out-dir> -f onerel.facts`
./runslog <slogfile> <out-dir> --cores=8
`./runslog -j4 -s <server-address IP> <slogfile> <out-dir> -f onerel.facts`
`./runslog <slogfile> <out-dir> --cores=8`
`./runslog --help`
`./runslog -e <out-dir>
fact directory is optional.
However, the output will be stored on the server, and `dumpslog` needs to be used
to get the output... dumpslog does not exist at the moment.
"""

import argparse
import os
import shutil
import subprocess
import time
import argparse, os, shutil, subprocess, time, sys

from yaspin import yaspin

Expand Down Expand Up @@ -149,9 +147,10 @@ def run_local(file, out_path, factloc, cores, verbose, slog_root=None, compile_b
backend_dir = os.path.join(slog_root, "backend")
backend_build_dir = os.path.join(backend_dir, "build")
tsv_bin_path = os.path.join(backend_build_dir, "tsv_to_bin")
# make inputs absolute paths, so we can chdir more carelessly
# make inputs absolute pathdums, so we can chdir more carelessly
file = os.path.realpath(file)
outloc = os.path.realpath("out")
# outloc = out_path
factloc = os.path.realpath(factloc) if factloc else None
inputloc = os.path.join(outloc, "input-data")
checkpointloc = os.path.join(outloc, "checkpoints")
Expand Down Expand Up @@ -270,11 +269,12 @@ def run_local(file, out_path, factloc, cores, verbose, slog_root=None, compile_b
print("Output dir exists, overwrite it? (temporary result under `$SLOG_HOME/out`)")
while True:
confirm_flag = input("(Y/n): ")
if confirm_flag.strip() == 'Y':
confirm_flag = confirm_flag.strip()
if confirm_flag in ["y", "Y"]:
shutil.rmtree(out_path)
shutil.copytree(outloc, out_path)
break
elif confirm_flag.strip() == 'n':
else:
break
#7: Open the repl if needed
shutil.copy(os.path.join(inputloc, '$strings.csv'),
Expand Down Expand Up @@ -315,10 +315,30 @@ def run_server(file, outloc, factloc, server, cores, verbose):
spinner.write(f"Final DB:\n{cur_db}")
spinner.text = "FINISHED!"

def enterrepl(base_folder):
source_file = os.path.join(base_folder, "input-data", "$strings.csv")
destination_folder = os.path.join(base_folder, "checkpoints", "checkpoint-final")
destination_file = os.path.join(destination_folder, "$strings.csv")
os.makedirs(destination_folder, exist_ok=True)

if os.path.exists(source_file):
shutil.copy(source_file, destination_file)
else:
open(destination_file, 'a').close()

base_folder = base_folder + "/checkpoints/checkpoint-final/"
repl = Repl(local_db_path=base_folder)

try:
while True:
repl.loop()
except KeyboardInterrupt:
repl.exit()

if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument("slogfile", help="The file to be compiled and ran.")
parser.add_argument("out_dir",
parser.add_argument("slogfile", nargs='?', help="The file to be compiled and ran.")
parser.add_argument("out_dir", nargs='?',
help="Where output information should be put. "
"This includes compiled files, build files, input data, and output data."
"FOR NOW THIS MUST BE A DIR NEXT TO THIS SCRIPT!!")
Expand All @@ -344,16 +364,25 @@ if __name__ == '__main__':
help="compile only without running it")
parser.add_argument('-ov', "--overwrite_out", action="store_true",
help="overwrite, if output dir already exists.")
parser.add_argument('-e', "--enterrepl",
help="enter the REPL on an already existing slog out directory.")
args = parser.parse_args()

slogfile = os.path.realpath(args.slogfile)
os.makedirs(args.out_dir, exist_ok=True)
if args.server:
run_server(slogfile, args.out_dir, args.facts, args.server + ":5108", args.verbose,
args.cores)
if args.enterrepl:
enterrepl(args.enterrepl)

if args.out_dir and args.slogfile:
slogfile = os.path.realpath(args.slogfile)
os.makedirs(args.out_dir, exist_ok=True)

if args.server:
run_server(slogfile, args.out_dir, args.facts, args.server + ":5108", args.verbose,
args.cores)
else:
run_local(slogfile, args.out_dir, args.facts, args.cores, args.verbose, args.root,
compile_backend=args.compile_backend, debug_flag=args.debug,
profile_flag=args.profile, repl_flag=args.repl,
compile_only=args.compile_only,
overwrite_out=args.overwrite_out)
else:
run_local(slogfile, args.out_dir, args.facts, args.cores, args.verbose, args.root,
compile_backend=args.compile_backend, debug_flag=args.debug,
profile_flag=args.profile, repl_flag=args.repl,
compile_only=args.compile_only,
overwrite_out=args.overwrite_out)
parser.print_help()
41 changes: 33 additions & 8 deletions slog/repl/repl.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,15 @@
help print help info
dump <rel> dump all facts inside a relation
relations print all relation meta info in current database
find find facts containing a specific piece of text
'''

CMD = ['help', 'run', 'connect', 'dump', 'showdb', 'relations',
'load', 'compile', 'tag', 'switch', 'fact-depth',
'fact-cardi', 'clear', 'fresh']
'fact-cardi', 'clear', 'fresh', 'find', 'exit']

# in run slog CLI, you can only do fact dumping, we need better pagenation
CMD_RUNSLOG = ['help', 'dump', 'relations']
CMD_RUNSLOG = ['help', 'dump', 'relations', 'find', 'exit']

kb = KeyBindings()

Expand All @@ -84,9 +85,20 @@ def _(event):
def _(event):
event.current_buffer.validate_and_handle()

class colors:
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKCYAN = '\033[96m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'

def invalid_alert(message):
""" print alert for command exectution """
print(f"Invalid command: {message}")
print(f"{colors.FAIL}Invalid command: {colors.ENDC}{message}")

def prompt_continuation(width, line_number, is_soft_wrap):
return '.' * width
Expand All @@ -103,7 +115,7 @@ def exec_command(client: SlogClient, raw_input: str):
# check if it a query
if (raw_input.startswith('(') and raw_input.endswith(')')) or \
(raw_input.startswith('[') and raw_input.endswith(']')):
client.slog_add_rule(raw_input, client.cur_db, ConsoleWriter())
client.slog_add_rule(raw_input[1:], client.cur_db, ConsoleWriter())
return
if raw_input.startswith('?(') and raw_input.endswith(')'):
client.pretty_print_slog_query(raw_input, ConsoleWriter())
Expand Down Expand Up @@ -154,6 +166,15 @@ def exec_command(client: SlogClient, raw_input: str):
invalid_alert(f'{cmd} expect a string at postion 2 as arg')
else:
invalid_alert(f'{cmd} expect 1/2 arg, but get {len(args)}')
elif cmd == 'find':
if len(args) == 0:
invalid_alert(f'{cmd} expects a string at position 1 as arg')
elif args[0].startswith('"') and args[0].endswith('"'):
print(args[0][1:-1])
client.find(args[0][1:-1], ConsoleWriter())
else:
client.find(" ".join(args))
# invalid_alert(f'{cmd} ran into some random error')
elif cmd == 'fact-depth':
if len(args) == 1 and args[0].isnumeric():
client.unroll_depth = int(args[0])
Expand Down Expand Up @@ -212,6 +233,8 @@ def exec_command(client: SlogClient, raw_input: str):
client.switchto_db(args[0])
else:
invalid_alert(f'{cmd} expected 1 argument, got {len(args)}.')
elif cmd == 'exit':
client.exit()
else:
invalid_alert(f'{cmd} is not a valid command, type `help to see help`')

Expand Down Expand Up @@ -263,10 +286,10 @@ def bottom_toolbar(self):
else:
return HTML('Disconnected. Use `connect <host>`')

def exit(self):
""" exit REPL """
print('Goodbye.')
sys.exit(0)
# def exit(self):
# """ exit REPL """
# print('See you again')
# sys.exit(0)

def loop(self):
""" REPL main entrance """
Expand Down Expand Up @@ -295,6 +318,7 @@ def loop(self):
completer_map['load'] = StringPathCompeleter()
completer_map['compile'] = StringPathCompeleter()
completer_map['switch'] = FuzzyWordCompleter(possible_db_hash + possible_db_tag)
# completer_map['exit'] = repl.exit()
relname_par_completer = WordCompleter([f"({n}" for n in relation_names])
for rname in relation_names:
completer_map[f'?({rname}'] = relname_par_completer
Expand All @@ -312,6 +336,7 @@ def loop(self):
continue
prev_time = time.time()
exec_command(self.client, text)

after_time = time.time()
print("\033[93mCommand cost {:10.2f} sec.\033[4m".format(after_time - prev_time))
except EOFError:
Expand Down
4 changes: 0 additions & 4 deletions slog/tests/server_log

This file was deleted.

0 comments on commit 4174d23

Please sign in to comment.