Skip to content

Commit

Permalink
Fix bug in relative path translation
Browse files Browse the repository at this point in the history
  • Loading branch information
tovrstra committed Aug 14, 2024
1 parent 2f002c6 commit befc7f2
Show file tree
Hide file tree
Showing 11 changed files with 172 additions and 6 deletions.
4 changes: 4 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
The values of these two fields are paths to which the standard output and/or error
of the run part of the script are redirected.

### Fixed

- Fix corner-case bug in the translation of relative paths before they are sent to the director process.


## [1.2.8] - 2024-06-28 {: #v1.2.8 }

Expand Down
8 changes: 3 additions & 5 deletions stepup/core/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -604,13 +604,11 @@ def translate(path: str) -> Path:
"""
path = mynormpath(path)
if not path.isabs():
stepup_root = Path(os.getenv("STEPUP_ROOT", "./"))
here = os.getenv("HERE")
if here is None:
stepup_root = os.getenv("STEPUP_ROOT")
if stepup_root is not None:
here = myrelpath("./", stepup_root)
if here is not None:
path = mynormpath(here / path)
here = myrelpath("./", stepup_root)
path = myrelpath(mynormpath(stepup_root / here / path), stepup_root)
return path


Expand Down
2 changes: 1 addition & 1 deletion tests/cases/here/README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
The variable HERE is defined when running a step as the working directory relative to STEPUP_ROOT.
When running a step, the HERE variable is defined as the working directory relative to STEPUP_ROOT.
It may be convenient to create an output at a location based on the working directory.
3 changes: 3 additions & 0 deletions tests/cases/translate_external/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
projects/work/.stepup
projects/public
current*
3 changes: 3 additions & 0 deletions tests/cases/translate_external/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Relative (input, output, ...) paths given to steps are translated to relative directories to `${STEPUP_ROOT}` before they are passed to the director.
This example checks the special situation that the relative directory contains a part of the parent directories of `${STEPUP_ROOT}`.
This scenario is a bit unusual but may occur when inputs or outputs refer to external directories shared with other StepUp projects.
7 changes: 7 additions & 0 deletions tests/cases/translate_external/common/script.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env python
from stepup.core.api import amend

path_foo = "../projects/public/foo.txt"
with open(path_foo, "w") as fh:
fh.write("Test\n")
amend(out=path_foo)
103 changes: 103 additions & 0 deletions tests/cases/translate_external/expected_graph.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
root:
version = v1
creates file:../
creates file:../../
creates file:./
creates file:plan.py
creates step:./plan.py

file:plan.py
path = plan.py
state = STATIC
created by root:
consumes file:./
supplies step:./plan.py

file:./
path = ./
state = STATIC
created by root:
supplies file:../
supplies file:plan.py
supplies step:./plan.py
supplies step:mkdir -p ../public/

step:./plan.py
workdir = ./
command = ./plan.py
state = SUCCEEDED
created by root:
consumes file:./
consumes file:plan.py
creates file:../../common/
creates file:../../common/script.py
creates step:./script.py # wd=../../common/
creates step:mkdir -p ../public/

file:../../common/
path = ../../common/
state = STATIC
created by step:./plan.py
consumes file:../../
supplies file:../../common/script.py
supplies step:./script.py # wd=../../common/

file:../../
path = ../../
state = STATIC
created by root:
consumes file:../
supplies file:../../common/

file:../
path = ../
state = STATIC
created by root:
consumes file:./
supplies file:../../
supplies file:../public/
supplies step:mkdir -p ../public/

file:../../common/script.py
path = ../../common/script.py
state = STATIC
created by step:./plan.py
consumes file:../../common/

step:mkdir -p ../public/
workdir = ./
command = mkdir -p ../public/
state = SUCCEEDED
created by step:./plan.py
consumes file:../
consumes file:./
creates file:../public/
supplies file:../public/

file:../public/
path = ../public/
state = BUILT
created by step:mkdir -p ../public/
consumes file:../
consumes step:mkdir -p ../public/
supplies file:../public/foo.txt
supplies step:./script.py # wd=../../common/

step:./script.py # wd=../../common/
workdir = ../../common/
command = ./script.py
state = SUCCEEDED
consumes (amended) = file:../public/
supplies (amended) = file:../public/foo.txt
created by step:./plan.py
consumes file:../../common/
consumes file:../public/
creates file:../public/foo.txt
supplies file:../public/foo.txt

file:../public/foo.txt
path = ../public/foo.txt
state = BUILT
created by step:./script.py # wd=../../common/
consumes file:../public/
consumes step:./script.py # wd=../../common/
12 changes: 12 additions & 0 deletions tests/cases/translate_external/expected_stdout.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
DIRECTOR │ Launched worker 0
PHASE │ run
START │ ./plan.py
SUCCESS │ ./plan.py
START │ mkdir -p ../public/
SUCCESS │ mkdir -p ../public/
START │ ./script.py # wd=../../common/
SUCCESS │ ./script.py # wd=../../common/
WORKFLOW │ Dumped to .stepup/workflow.mpk.xz
PHASE │ watch
DIRECTOR │ Stopping workers.
DIRECTOR │ See you!
29 changes: 29 additions & 0 deletions tests/cases/translate_external/main.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env -S bash -x
# Exit on first error and cleanup.
set -e
trap 'kill $(pgrep -g $$ | grep -v $$) > /dev/null 2> /dev/null || :' EXIT
xargs rm -rvf < .gitignore

# Run the example
cd projects/work
stepup -w 1 plan.py & # > ../../current_stdout.txt &

# Wait for the director and get its socket.
export STEPUP_DIRECTOR_SOCKET=$(
python -c "import stepup.core.director; print(stepup.core.director.get_socket())"
)

# Get the graph after completion of the pending steps.
python3 - << EOD
from stepup.core.interact import *
wait()
graph("../../current_graph")
join()
EOD

# Wait for background processes, if any.
wait

# Check files that are expected to be present and/or missing.
[[ -f plan.py ]] || exit 1
[[ -f ../public/foo.txt ]] || exit 1
6 changes: 6 additions & 0 deletions tests/cases/translate_external/projects/work/plan.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/usr/bin/env python
from stepup.core.api import mkdir, static, step

static("../../common/", "../../common/script.py")
mkdir("../public/")
step("./script.py", workdir="../../common/")
1 change: 1 addition & 0 deletions tests/test_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
"static_nglob_recursive",
"static_nglob_subdir",
"subdir",
"translate_external",
"watch_blocked",
"watch_boot",
"watch_chain",
Expand Down

0 comments on commit befc7f2

Please sign in to comment.