Skip to content

Commit

Permalink
chdir fix
Browse files Browse the repository at this point in the history
  • Loading branch information
vadim0x60 committed Oct 13, 2023
1 parent ad39efc commit 78bf9d7
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 29 deletions.
32 changes: 15 additions & 17 deletions programlib/language.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import pexpect
import shutil
import os
from pathlib import Path

class Language:
"""
Expand All @@ -14,45 +15,42 @@ def __init__(self, build_cmd, run_cmd, source, artefacts, name='custom') -> None
self.artefacts = artefacts
self.name = name

def build(self, workdir, name):
def build(self, name):
if self.build_cmd:
os.chdir(workdir)
stdout, status = pexpect.run(self.build_cmd.format(name=name),
cwd=workdir, withexitstatus=True,
echo=False)
withexitstatus=True, echo=False)
return stdout.decode(), status
else:
return '', ''

def run(self, workdir, name, input_lines=[]):
child = self.spawn(workdir, name)
def run(self, name, input_lines=[]):
child = self.spawn(name)
for line in input_lines:
child.sendline(line)
output = child.read()
child.close()
return output.decode(), child.exitstatus

def spawn(self, workdir, name):
os.chdir(workdir)
child = pexpect.spawn(self.run_cmd.format(name=name), cwd=workdir)
def spawn(self, name):
child = pexpect.spawn(self.run_cmd.format(name=name))
child.setecho(False)
return child

def write_source(self, workdir, name, source):
with open(workdir / self.source.format(name=name), 'w') as f:
def write_source(self, name, source):
with open(self.source.format(name=name), 'w') as f:
f.write(source)

def read_source(self, workdir, name):
with open(workdir / self.source.format(name=name), 'r') as f:
def read_source(self, name):
with open(self.source.format(name=name), 'r') as f:
return f.read()

def copy_source(self, workdir, name, dest):
shutil.copy(workdir / self.source.format(name=name), dest)
def copy_source(self, name, dest):
shutil.copy(self.source.format(name=name), dest)

def cleanup(self, workdir, name):
def cleanup(self, name):
for path in [self.source] + self.artefacts:
try:
(workdir / path.format(name=name)).unlink()
Path(path.format(name=name)).unlink()
except FileNotFoundError:
pass

Expand Down
31 changes: 20 additions & 11 deletions programlib/program.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from uuid import uuid4
from pathlib import Path
from itertools import zip_longest
from contextlib_chdir import chdir

from programlib import Agent, language_, Terminal

Expand Down Expand Up @@ -51,12 +52,13 @@ def __init__(self, source=None, name=None, language='C++',
self.workdir = Path(__file__).parent / 'programs'
self.ephemeral = True

if source:
self.language.write_source(self.workdir, self.name, source)
else:
source = self.language.read_source(self.workdir, self.name)
with chdir(self.workdir):
if source:
self.language.write_source(self.name, source)
else:
source = self.language.read_source(self.name)

self.stdout, self.exitstatus = self.language.build(self.workdir, self.name)
self.stdout, self.exitstatus = self.language.build(self.name)

# Please send your opinions on 'not not' vs 'bool()' to [email protected]
self.compile_error = not not self.exitstatus
Expand All @@ -66,8 +68,9 @@ def __lt__(self, other):

def read(self):
"""Obtain the source code of the program"""

return self.language.read_source(self.workdir, self.name)

with chdir(self.workdir):
return self.language.read_source(self.name)

def run(self, input_lines=[], force=True):
"""
Expand All @@ -81,7 +84,8 @@ def run(self, input_lines=[], force=True):
Raw results will always be stored in `program.stdout` and `program.exitstatus` attributes
"""

self.stdout, self.exitstatus = self.language.run(self.workdir, self.name, input_lines)
with chdir(self.workdir):
self.stdout, self.exitstatus = self.language.run(self.name, input_lines)
assert force or not self.exitstatus, f'Exit status {self.exitstatus}'
return self.term.emulate(self.stdout)

Expand All @@ -90,7 +94,8 @@ def spawn(self, delimiter='\n'):
Launch the program and get a process object to communicate with it interactively
"""

process = self.language.spawn(self.workdir, self.name)
with chdir(self.workdir):
process = self.language.spawn(self.name)
return Agent(self, process, delimiter=delimiter)

def test(self, test_cases, force=True):
Expand Down Expand Up @@ -127,8 +132,12 @@ def test(self, test_cases, force=True):
return test_runs

def save(self, path):
self.language.copy_source(self.workdir, self.name, path)
path = Path(path).absolute()

with chdir(self.workdir):
self.language.copy_source(self.name, path)

def __del__(self):
if self.ephemeral:
self.language.cleanup(self.workdir, self.name)
with chdir(self.workdir):
self.language.cleanup(self.name)
4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "programlib"
version = "7.2.0"
version = "8.0.0"
description = "Programs as Objects"
authors = ["Vadim Liventsev <[email protected]>"]
license = "MIT"
Expand All @@ -17,6 +17,8 @@ pexpect = "^4.8.0"
gym = "^0.26.2"
numpy = "^1.24.2"
pyte = "^0.8.0"
contextlib-chdir = "^1.0.2"


[build-system]
requires = ["poetry-core"]
Expand Down

0 comments on commit 78bf9d7

Please sign in to comment.