You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
|`s3_files.py`| Downloads `params["answer_files"]`/`params["response_files"]` objects into the per-request working directory |
14
+
|`s3_files.py`| Downloads `params["files"]` objects from S3 into the per-request working directory |
15
15
|`dev.py`| CLI wrapper for local manual testing |
16
16
17
17
### Evaluation pipeline (`evaluation.py`)
18
18
19
19
1. Run AST security check on student code
20
-
2.Gather file specs from params via `_collect_file_specs`: `params["answer_files"]` (teacher, plus legacy `params["files"]`) and `params["response_files"]` (student); teacher files win on a name clash. The response and answer are plain code strings. If any files are listed, download the listed objects once into a per-request working directory (see `s3_files.py`), used as the subprocess `cwd` for every run in this request
20
+
2.Resolve the submission into `(code, file_specs)`via `_resolve_submission`: the response may be a bare code string, or a `{"code", "files"}` object (or JSON string of one) as sent by the LF web client's upload widget. If `file_specs` (from `response["files"]`, else `params["files"]`) is non-empty, download the listed objects once into a per-request working directory (see `s3_files.py`), used as the subprocess `cwd` for every run in this request
21
21
3. Dispatch by `params["mode"]` (required):
22
22
-**`demo`**: execute code with no stdin; return stdout/plots as `output` feedback (no pass/fail)
23
23
-**`io_test`**: for each test in `params["tests"]`, execute with `test["input"]` as stdin and compare stdout against `test["expected_output"]`; upload matplotlib plots on pass or fail
@@ -93,28 +93,32 @@ All source lives in `evaluation_function/`:
93
93
"tests": [...]
94
94
}
95
95
96
-
# answer_files / response_files — optional, work with all modes
97
-
# answer_files: the teacher's files, saved in the response area's gradeParams.
98
-
# response_files: the student's uploads, sent with each check as additionalParams.
99
-
# params["files"] is still accepted as a legacy alias for answer_files.
100
-
# All listed files are downloaded into one per-request working directory
101
-
# (the subprocess's cwd) before student code runs, given a pre-signed or
102
-
# public HTTPS URL per file (fetched directly with a GET — no AWS
103
-
# credentials needed here). On a name clash the teacher's file wins. Entries
104
-
# may be dicts or JSON strings of dicts. Data files can be read with
105
-
# open()/pandas.read_csv()/etc.; .py files are importable since they're
106
-
# co-located with the generated script. The same files are also available
107
-
# to the answer code when use_answer_as_expected_output/use_answer_as_test_code is set.
96
+
# files — optional, works with all modes
97
+
# Downloads files into a per-request working directory (the subprocess's
98
+
# cwd) before student code runs, given a pre-signed or public HTTPS URL per
99
+
# file (fetched directly with a GET — no AWS credentials needed here). Data
100
+
# files can be read with open()/pandas.read_csv()/etc.; .py files are
101
+
# importable by student code since they're co-located with the generated
102
+
# script. The same files are also available to the answer code when
103
+
# use_answer_as_expected_output/use_answer_as_test_code is set.
-**Dunder attribute access**: any `__attr__` style attribute
127
131
128
-
`open`/`pathlib` are intentionally **not** blocked here — they're needed to read files loaded via `params["answer_files"]`/`params["response_files"]` (see above). **Important caveat**: `preview_function` (this check) and `evaluation_function` (actual grading) are registered as two independent RPC methods in `main.py`; `evaluation.py` never calls `preview.py`. This check only powers editor-time linting feedback — it does not gate what code can do at grading time. The real, load-bearing control for file access is a runtime-injected restricted `open`/`io.open` in `evaluation.py`'s subprocess preamble (`_safe_open`), which blocks *write* access to anything inside the per-run files directory. It is not a hard sandbox boundary — since `os`/`subprocess` remain fully importable and runnable at grading time regardless of this feature, a student can bypass file restrictions entirely via `os`. Treat this as scoping the intended file-access path, not as isolation.
132
+
`open`/`pathlib` are intentionally **not** blocked here — they're needed to read files loaded via `params["files"]` (see above). **Important caveat**: `preview_function` (this check) and `evaluation_function` (actual grading) are registered as two independent RPC methods in `main.py`; `evaluation.py` never calls `preview.py`. This check only powers editor-time linting feedback — it does not gate what code can do at grading time. The real, load-bearing control for file access is a runtime-injected restricted `open`/`io.open` in `evaluation.py`'s subprocess preamble (`_safe_open`), which blocks *write* access to anything inside the per-run files directory. It is not a hard sandbox boundary — since `os`/`subprocess` remain fully importable and runnable at grading time regardless of this feature, a student can bypass file restrictions entirely via `os`. Treat this as scoping the intended file-access path, not as isolation.
129
133
130
134
## Key commands
131
135
@@ -180,7 +184,7 @@ CI runs on Python 3.12 and uploads JUnit XML results (`.github/workflows/test-li
180
184
|`LOG_LEVEL`|`debug`| Logging verbosity |
181
185
|`IMAGE_UPLOAD_BACKEND`|`gcs`| Plot upload backend in lf_toolkit (`gcs` set in Dockerfile; override to `s3` on the service to use AWS) |
182
186
|`GCS_BUCKET`| Runtime env | Target bucket for matplotlib plot uploads; set per-environment on the Cloud Run service. Auth is via the runtime service account (ADC) — no keys |
183
-
|`AWS_*` / `S3_BUCKET_URI`| Runtime env | Only for the legacy S3 plot-upload backend (`IMAGE_UPLOAD_BACKEND=s3`). Not needed for `answer_files` / `response_files` downloads — those are plain HTTPS GETs from a pre-signed/public URL |
187
+
|`AWS_*` / `S3_BUCKET_URI`| Runtime env | Only for the legacy S3 plot-upload backend (`IMAGE_UPLOAD_BACKEND=s3`). Not needed for `params["files"]` / response-payload file downloads — those are plain HTTPS GETs from a pre-signed/public URL |
184
188
|`SANDBOX_ENABLED`|`true`| Wrap the worker in shimmy's nsjail sandbox (needs `--privileged` at run time) |
0 commit comments