chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:47:58 +08:00
commit b16403ea71
789 changed files with 115226 additions and 0 deletions
@@ -0,0 +1,61 @@
from e2b.sandbox.filesystem.filesystem import WriteEntry
def test_write_and_read_with_gzip(sandbox, debug):
filename = "test_gzip_write.txt"
content = "This is a test file with gzip encoding."
info = sandbox.files.write(filename, content, gzip=True)
assert info.path == f"/home/user/{filename}"
read_content = sandbox.files.read(filename, gzip=True)
assert read_content == content
if debug:
sandbox.files.remove(filename)
def test_write_gzip_read_plain(sandbox, debug):
filename = "test_gzip_write_plain_read.txt"
content = "Written with gzip, read without."
sandbox.files.write(filename, content, gzip=True)
read_content = sandbox.files.read(filename)
assert read_content == content
if debug:
sandbox.files.remove(filename)
def test_write_files_with_gzip(sandbox, debug):
files = [
WriteEntry(path="gzip_multi_1.txt", data="File 1 content"),
WriteEntry(path="gzip_multi_2.txt", data="File 2 content"),
WriteEntry(path="gzip_multi_3.txt", data="File 3 content"),
]
infos = sandbox.files.write_files(files, gzip=True)
assert len(infos) == len(files)
for i, file in enumerate(files):
read_content = sandbox.files.read(file["path"])
assert read_content == file["data"]
if debug:
for file in files:
sandbox.files.remove(file["path"])
def test_read_bytes_with_gzip(sandbox, debug):
filename = "test_gzip_bytes.txt"
content = "Binary content with gzip."
sandbox.files.write(filename, content)
read_bytes = sandbox.files.read(filename, format="bytes", gzip=True)
assert isinstance(read_bytes, bytearray)
assert read_bytes.decode("utf-8") == content
if debug:
sandbox.files.remove(filename)
@@ -0,0 +1,8 @@
from e2b import Sandbox
def test_exists(sandbox: Sandbox):
filename = "test_exists.txt"
sandbox.files.write(filename, "test")
assert sandbox.files.exists(filename)
@@ -0,0 +1,247 @@
import uuid
from typing import Any
from e2b import Sandbox, FileType
def test_list_directory(sandbox: Sandbox):
home_dir_name = "/home/user"
parent_dir_name = f"test_directory_{uuid.uuid4()}"
sandbox.files.make_dir(parent_dir_name)
sandbox.files.make_dir(f"{parent_dir_name}/subdir1")
sandbox.files.make_dir(f"{parent_dir_name}/subdir2")
sandbox.files.make_dir(f"{parent_dir_name}/subdir1/subdir1_1")
sandbox.files.make_dir(f"{parent_dir_name}/subdir1/subdir1_2")
sandbox.files.make_dir(f"{parent_dir_name}/subdir2/subdir2_1")
sandbox.files.make_dir(f"{parent_dir_name}/subdir2/subdir2_2")
sandbox.files.write(f"{parent_dir_name}/file1.txt", "Hello, world!")
test_cases: list[dict[str, Any]] = [
{
"name": "default depth (1)",
"depth": None,
"expected_len": 3,
"expected_file_names": [
"file1.txt",
"subdir1",
"subdir2",
],
"expected_file_types": [
FileType.FILE,
FileType.DIR,
FileType.DIR,
],
"expected_file_paths": [
f"{home_dir_name}/{parent_dir_name}/file1.txt",
f"{home_dir_name}/{parent_dir_name}/subdir1",
f"{home_dir_name}/{parent_dir_name}/subdir2",
],
},
{
"name": "explicit depth 1",
"depth": 1,
"expected_len": 3,
"expected_file_names": [
"file1.txt",
"subdir1",
"subdir2",
],
"expected_file_types": [
FileType.FILE,
FileType.DIR,
FileType.DIR,
],
"expected_file_paths": [
f"{home_dir_name}/{parent_dir_name}/file1.txt",
f"{home_dir_name}/{parent_dir_name}/subdir1",
f"{home_dir_name}/{parent_dir_name}/subdir2",
],
},
{
"name": "explicit depth 2",
"depth": 2,
"expected_len": 7,
"expected_file_types": [
FileType.FILE,
FileType.DIR,
FileType.DIR,
FileType.DIR,
FileType.DIR,
FileType.DIR,
FileType.DIR,
],
"expected_file_names": [
"file1.txt",
"subdir1",
"subdir1_1",
"subdir1_2",
"subdir2",
"subdir2_1",
"subdir2_2",
],
"expected_file_paths": [
f"{home_dir_name}/{parent_dir_name}/file1.txt",
f"{home_dir_name}/{parent_dir_name}/subdir1",
f"{home_dir_name}/{parent_dir_name}/subdir1/subdir1_1",
f"{home_dir_name}/{parent_dir_name}/subdir1/subdir1_2",
f"{home_dir_name}/{parent_dir_name}/subdir2",
f"{home_dir_name}/{parent_dir_name}/subdir2/subdir2_1",
f"{home_dir_name}/{parent_dir_name}/subdir2/subdir2_2",
],
},
{
"name": "explicit depth 3 (should be the same as depth 2)",
"depth": 3,
"expected_len": 7,
"expected_file_names": [
"file1.txt",
"subdir1",
"subdir1_1",
"subdir1_2",
"subdir2",
"subdir2_1",
"subdir2_2",
],
"expected_file_types": [
FileType.FILE,
FileType.DIR,
FileType.DIR,
FileType.DIR,
FileType.DIR,
FileType.DIR,
FileType.DIR,
],
"expected_file_paths": [
f"{home_dir_name}/{parent_dir_name}/file1.txt",
f"{home_dir_name}/{parent_dir_name}/subdir1",
f"{home_dir_name}/{parent_dir_name}/subdir1/subdir1_1",
f"{home_dir_name}/{parent_dir_name}/subdir1/subdir1_2",
f"{home_dir_name}/{parent_dir_name}/subdir2",
f"{home_dir_name}/{parent_dir_name}/subdir2/subdir2_1",
f"{home_dir_name}/{parent_dir_name}/subdir2/subdir2_2",
],
},
]
for test_case in test_cases:
files = sandbox.files.list(
parent_dir_name,
depth=test_case["depth"] if test_case["depth"] is not None else None,
)
assert len(files) == test_case["expected_len"]
for i in range(len(test_case["expected_file_names"])):
assert files[i].name == test_case["expected_file_names"][i]
assert files[i].path == test_case["expected_file_paths"][i]
assert files[i].type == test_case["expected_file_types"][i]
sandbox.files.remove(parent_dir_name)
def test_list_directory_error_cases(sandbox: Sandbox):
parent_dir_name = f"test_directory_{uuid.uuid4()}"
sandbox.files.make_dir(parent_dir_name)
expected_error_message = "depth should be at least 1"
try:
sandbox.files.list(parent_dir_name, depth=-1)
assert False, "Expected error but none was thrown"
except Exception as err:
assert expected_error_message in str(err), (
f'expected error message to include "{expected_error_message}"'
)
sandbox.files.remove(parent_dir_name)
def test_file_entry_details(sandbox: Sandbox):
test_dir = "test-file-entry"
file_path = f"{test_dir}/test.txt"
content = "Hello, World!"
sandbox.files.make_dir(test_dir)
sandbox.files.write(file_path, content)
files = sandbox.files.list(test_dir, depth=1)
assert len(files) == 1
file_entry = files[0]
assert file_entry.name == "test.txt"
assert file_entry.path == f"/home/user/{file_path}"
assert file_entry.type == FileType.FILE
assert file_entry.mode == 0o644
assert file_entry.permissions == "-rw-r--r--"
assert file_entry.owner == "user"
assert file_entry.group == "user"
assert file_entry.size == len(content)
assert file_entry.modified_time is not None
assert file_entry.symlink_target is None
sandbox.files.remove(test_dir)
def test_directory_entry_details(sandbox: Sandbox):
test_dir = "test-entry-info"
sub_dir = f"{test_dir}/subdir"
sandbox.files.make_dir(test_dir)
sandbox.files.make_dir(sub_dir)
files = sandbox.files.list(test_dir, depth=1)
assert len(files) == 1
dir_entry = files[0]
assert dir_entry.name == "subdir"
assert dir_entry.path == f"/home/user/{sub_dir}"
assert dir_entry.type == FileType.DIR
assert dir_entry.mode == 0o755
assert dir_entry.permissions == "drwxr-xr-x"
assert dir_entry.owner == "user"
assert dir_entry.group == "user"
assert dir_entry.modified_time is not None
sandbox.files.remove(test_dir)
def test_mixed_entries(sandbox: Sandbox):
test_dir = "test-mixed-entries"
sub_dir = f"{test_dir}/subdir"
file_path = f"{test_dir}/test.txt"
content = "Hello, World!"
sandbox.files.make_dir(test_dir)
sandbox.files.make_dir(sub_dir)
sandbox.files.write(file_path, content)
files = sandbox.files.list(test_dir, depth=1)
assert len(files) == 2
# Create a dictionary of entries by name for easier verification
entries = {entry.name: entry for entry in files}
# Verify directory entry
dir_entry = entries.get("subdir")
assert dir_entry is not None
assert dir_entry.path == f"/home/user/{sub_dir}"
assert dir_entry.type == FileType.DIR
assert dir_entry.mode == 0o755
assert dir_entry.permissions == "drwxr-xr-x"
assert dir_entry.owner == "user"
assert dir_entry.group == "user"
assert dir_entry.modified_time is not None
# Verify file entry
file_entry = entries.get("test.txt")
assert file_entry is not None
assert file_entry.path == f"/home/user/{file_path}"
assert file_entry.type == FileType.FILE
assert file_entry.mode == 0o644
assert file_entry.permissions == "-rw-r--r--"
assert file_entry.owner == "user"
assert file_entry.group == "user"
assert file_entry.size == len(content)
assert file_entry.modified_time is not None
sandbox.files.remove(test_dir)
@@ -0,0 +1,75 @@
import pytest
from e2b.exceptions import FileNotFoundException
from e2b import Sandbox, FileType
def test_get_info_of_file(sandbox: Sandbox):
filename = "test_file.txt"
sandbox.files.write(filename, "test")
info = sandbox.files.get_info(filename)
current_path = sandbox.commands.run("pwd")
assert info.name == filename
assert info.type == FileType.FILE
assert info.path == f"{current_path.stdout.strip()}/{filename}"
assert info.size == 4
assert info.mode == 0o644
assert info.permissions == "-rw-r--r--"
assert info.owner == "user"
assert info.group == "user"
assert info.modified_time is not None
assert info.modified_time.tzinfo is not None
def test_get_info_of_nonexistent_file(sandbox: Sandbox):
filename = "test_does_not_exist.txt"
with pytest.raises(FileNotFoundException):
sandbox.files.get_info(filename)
def test_get_info_of_directory(sandbox: Sandbox):
dirname = "test_dir"
sandbox.files.make_dir(dirname)
info = sandbox.files.get_info(dirname)
current_path = sandbox.commands.run("pwd")
assert info.name == dirname
assert info.type == FileType.DIR
assert info.path == f"{current_path.stdout.strip()}/{dirname}"
assert info.size > 0
assert info.mode == 0o755
assert info.permissions == "drwxr-xr-x"
assert info.owner == "user"
assert info.group == "user"
assert info.modified_time is not None
assert info.modified_time.tzinfo is not None
def test_get_info_of_nonexistent_directory(sandbox: Sandbox):
dirname = "test_does_not_exist_dir"
with pytest.raises(FileNotFoundException):
sandbox.files.get_info(dirname)
def test_file_symlink(sandbox: Sandbox):
test_dir = "test-simlink-entry"
file_name = "test.txt"
content = "Hello, World!"
sandbox.files.make_dir(test_dir)
sandbox.files.write(f"{test_dir}/{file_name}", content)
symlink_name = "symlink_to_test.txt"
sandbox.commands.run(f"ln -s {file_name} {symlink_name}", cwd=test_dir)
file = sandbox.files.get_info(f"{test_dir}/{symlink_name}")
pwd = sandbox.commands.run("pwd")
assert file.type == FileType.FILE
assert file.symlink_target == f"{pwd.stdout.strip()}/{test_dir}/{file_name}"
sandbox.files.remove(test_dir)
@@ -0,0 +1,29 @@
import uuid
from e2b import Sandbox
def test_make_directory(sandbox: Sandbox):
dir_name = f"test_directory_{uuid.uuid4()}"
sandbox.files.make_dir(dir_name)
exists = sandbox.files.exists(dir_name)
assert exists
async def test_make_directory_already_exists(sandbox: Sandbox):
dir_name = f"test_directory_{uuid.uuid4()}"
created = sandbox.files.make_dir(dir_name)
assert created
created = sandbox.files.make_dir(dir_name)
assert not created
def test_make_nested_directory(sandbox: Sandbox):
nested_dir_name = f"test_directory_{uuid.uuid4()}/nested_directory"
sandbox.files.make_dir(nested_dir_name)
exists = sandbox.files.exists(nested_dir_name)
assert exists
@@ -0,0 +1,163 @@
import pytest
from e2b.exceptions import InvalidArgumentException
def test_write_file_with_metadata(sandbox, debug):
filename = "test_metadata.txt"
content = "This is a test file with metadata."
metadata = {"author": "mish", "purpose": "upload"}
info = sandbox.files.write(filename, content, metadata=metadata)
assert info.metadata == metadata
# Metadata is persisted and surfaced on subsequent reads.
stat = sandbox.files.get_info(filename)
assert stat.metadata == metadata
if debug:
sandbox.files.remove(filename)
def test_write_file_with_metadata_octet_stream(sandbox, debug):
filename = "test_metadata_octet.txt"
content = "This is a test file with metadata."
metadata = {"author": "mish", "purpose": "upload"}
info = sandbox.files.write(
filename, content, metadata=metadata, use_octet_stream=True
)
assert info.metadata == metadata
stat = sandbox.files.get_info(filename)
assert stat.metadata == metadata
if debug:
sandbox.files.remove(filename)
def test_write_file_without_metadata(sandbox, debug):
filename = "test_no_metadata.txt"
info = sandbox.files.write(filename, "no metadata here")
assert info.metadata is None
stat = sandbox.files.get_info(filename)
assert stat.metadata is None
if debug:
sandbox.files.remove(filename)
def test_write_files_applies_metadata_to_every_file(sandbox, debug):
from e2b.sandbox.filesystem.filesystem import WriteEntry
# The same metadata is applied to every file in the upload.
metadata = {"source": "test-suite"}
files = [
WriteEntry(path="metadata_multi_1.txt", data="File 1"),
WriteEntry(path="metadata_multi_2.txt", data="File 2"),
]
infos = sandbox.files.write_files(files, metadata=metadata)
assert len(infos) == len(files)
for info in infos:
assert info.metadata == metadata
stat = sandbox.files.get_info(info.path)
assert stat.metadata == metadata
if debug:
for file in files:
sandbox.files.remove(file["path"])
def test_metadata_surfaced_when_listing(sandbox, debug):
dirname = "metadata_list_dir"
filename = "listed.txt"
metadata = {"tag": "listed"}
sandbox.files.make_dir(dirname)
sandbox.files.write(f"{dirname}/{filename}", "content", metadata=metadata)
entries = sandbox.files.list(dirname)
entry = next((e for e in entries if e.name == filename), None)
assert entry is not None
assert entry.metadata == metadata
if debug:
sandbox.files.remove(dirname)
def test_metadata_surfaced_after_rename(sandbox, debug):
old_path = "metadata_rename_old.txt"
new_path = "metadata_rename_new.txt"
metadata = {"stage": "renamed"}
sandbox.files.write(old_path, "content", metadata=metadata)
info = sandbox.files.rename(old_path, new_path)
assert info.metadata == metadata
if debug:
sandbox.files.remove(new_path)
def test_overwriting_clears_stale_metadata(sandbox, debug):
filename = "metadata_overwrite.txt"
sandbox.files.write(filename, "first", metadata={"author": "mish"})
# Overwriting without metadata removes the previously stored metadata.
info = sandbox.files.write(filename, "second")
assert info.metadata is None
stat = sandbox.files.get_info(filename)
assert stat.metadata is None
if debug:
sandbox.files.remove(filename)
def test_metadata_set_via_xattrs_surfaced_in_get_info(sandbox, debug):
filename = "metadata_xattr.txt"
sandbox.files.write(filename, "content")
file_path = sandbox.commands.run(f"realpath {filename}").stdout.strip()
# Set an xattr directly in the `user.e2b.` namespace (out-of-band, not via
# the SDK upload); it should surface as metadata (with the namespace prefix
# stripped) when reading the file info.
sandbox.commands.run(
f"python3 -c \"import os; os.setxattr('{file_path}', 'user.e2b.author', b'mish')\""
)
info = sandbox.files.get_info(filename)
assert info.metadata == {"author": "mish"}
if debug:
sandbox.files.remove(filename)
def test_write_rejects_invalid_metadata(sandbox):
filename = "invalid_metadata.txt"
# Key with a space is not a valid HTTP header token.
with pytest.raises(InvalidArgumentException):
sandbox.files.write(filename, "x", metadata={"bad key": "value"})
# Empty key.
with pytest.raises(InvalidArgumentException):
sandbox.files.write(filename, "x", metadata={"": "value"})
# Value with a non-printable / non-ASCII character.
with pytest.raises(InvalidArgumentException):
sandbox.files.write(filename, "x", metadata={"good": "bad\nvalue"})
# Trailing newline (Python's `$` would accept it; `\Z` must not).
with pytest.raises(InvalidArgumentException):
sandbox.files.write(filename, "x", metadata={"good": "value\n"})
with pytest.raises(InvalidArgumentException):
sandbox.files.write(filename, "x", metadata={"key\n": "value"})
# The file must not have been created by a rejected write.
assert not sandbox.files.exists(filename)
@@ -0,0 +1,83 @@
import pytest
from e2b import FileNotFoundException, NotFoundException
def test_read_file(sandbox):
filename = "test_read.txt"
content = "Hello, world!"
sandbox.files.write(filename, content)
read_content = sandbox.files.read(filename)
assert read_content == content
def test_read_non_existing_file(sandbox):
filename = "non_existing_file.txt"
with pytest.raises(FileNotFoundException):
sandbox.files.read(filename)
def test_read_non_existing_file_catches_with_deprecated_not_found_exception(sandbox):
filename = "non_existing_file.txt"
with pytest.raises(NotFoundException):
sandbox.files.read(filename)
def test_read_empty_file(sandbox):
filename = "empty_file.txt"
content = ""
sandbox.commands.run(f"touch {filename}")
read_content = sandbox.files.read(filename)
assert read_content == content
def test_read_file_as_stream(sandbox):
filename = "test_read_stream.txt"
content = "Streamed read content. " * 10_000
sandbox.files.write(filename, content)
stream = sandbox.files.read(filename, format="stream")
read_content = b"".join(stream).decode("utf-8")
assert read_content == content
def test_read_file_as_stream_with_gzip(sandbox):
filename = "test_read_stream_gzip.txt"
content = "Streamed gzipped read content. " * 10_000
sandbox.files.write(filename, content)
stream = sandbox.files.read(filename, format="stream", gzip=True)
read_content = b"".join(stream).decode("utf-8")
assert read_content == content
def test_read_non_existing_file_as_stream(sandbox):
filename = "non_existing_file.txt"
with pytest.raises(FileNotFoundException):
sandbox.files.read(filename, format="stream")
def test_read_file_as_stream_context_manager(sandbox):
filename = "test_read_stream_ctx.txt"
content = "Streamed read content. " * 10_000
sandbox.files.write(filename, content)
with sandbox.files.read(filename, format="stream") as stream:
read_content = b"".join(stream).decode("utf-8")
assert read_content == content
def test_read_file_as_stream_partial_then_close(sandbox):
filename = "test_read_stream_partial.txt"
content = "Streamed read content. " * 10_000
sandbox.files.write(filename, content)
# Reading only the first chunk and closing must not raise or leak.
stream = sandbox.files.read(filename, format="stream")
first = next(iter(stream))
assert len(first) > 0
stream.close()
@@ -0,0 +1,18 @@
from e2b import Sandbox
def test_remove_file(sandbox: Sandbox):
filename = "test_remove.txt"
content = "This file will be removed."
sandbox.files.write(filename, content)
sandbox.files.remove(filename)
exists = sandbox.files.exists(filename)
assert not exists
def test_remove_non_existing_file(sandbox):
filename = "non_existing_file.txt"
sandbox.files.remove(filename)
@@ -0,0 +1,28 @@
import pytest
from e2b import FileNotFoundException, Sandbox
def test_rename_file(sandbox: Sandbox):
old_filename = "test_rename_old.txt"
new_filename = "test_rename_new.txt"
content = "This file will be renamed."
sandbox.files.write(old_filename, content)
info = sandbox.files.rename(old_filename, new_filename)
assert info.path == f"/home/user/{new_filename}"
exists_old = sandbox.files.exists(old_filename)
exists_new = sandbox.files.exists(new_filename)
assert not exists_old
assert exists_new
read_content = sandbox.files.read(new_filename)
assert read_content == content
def test_rename_non_existing_file(sandbox):
old_filename = "non_existing_file.txt"
new_filename = "new_non_existing_file.txt"
with pytest.raises(FileNotFoundException):
sandbox.files.rename(old_filename, new_filename)
@@ -0,0 +1,59 @@
import urllib.request
import urllib.error
import json
import pytest
@pytest.mark.skip_debug()
def test_download_url_with_signing(sandbox_factory):
sbx = sandbox_factory(timeout=100, secure=True)
file_path = "test_download_url_with_signing.txt"
file_content = "This file will be watched."
sbx.files.write(file_path, file_content)
signed_url = sbx.download_url(file_path, "user")
with urllib.request.urlopen(signed_url) as resp:
assert resp.status == 200
body_bytes = resp.read()
body_text = body_bytes.decode()
assert body_text == file_content
@pytest.mark.skip_debug()
def test_download_url_with_signing_and_expiration(sandbox_factory):
sbx = sandbox_factory(timeout=100, secure=True)
file_path = "test_download_url_with_signing.txt"
file_content = "This file will be watched."
sbx.files.write(file_path, file_content)
signed_url = sbx.download_url(file_path, "user", 120)
with urllib.request.urlopen(signed_url) as resp:
assert resp.status == 200
body_bytes = resp.read()
body_text = body_bytes.decode()
assert body_text == file_content
@pytest.mark.skip_debug()
def test_download_url_with_expired_signing(sandbox_factory):
sbx = sandbox_factory(timeout=100, secure=True)
file_path = "test_download_url_with_signing.txt"
file_content = "This file will be watched."
sbx.files.write(file_path, file_content)
signed_url = sbx.download_url(file_path, "user", use_signature_expiration=-120)
with pytest.raises(urllib.error.HTTPError) as exc_info:
urllib.request.urlopen(signed_url)
err = exc_info.value
assert err.code == 401, f"Unexpected status {err.code}"
error_json_str = err.read().decode() # bytes ➜ str
error_payload = json.loads(error_json_str) # str ➜ dict
expected_payload = {"code": 401, "message": "signature is already expired"}
assert error_payload == expected_payload
@@ -0,0 +1,192 @@
import pytest
from e2b import (
FileNotFoundException,
FileType,
FilesystemEventType,
Sandbox,
SandboxException,
)
def test_watch_directory_changes_with_entry_info(sandbox: Sandbox):
dirname = "test_watch_dir_entry"
filename = "test_watch.txt"
content = "This file will be watched."
new_content = "This file has been modified."
sandbox.files.make_dir(dirname)
sandbox.files.write(f"{dirname}/{filename}", content)
handle = sandbox.files.watch_dir(dirname, include_entry=True)
sandbox.files.write(f"{dirname}/{filename}", new_content)
events = handle.get_new_events()
write_event = None
for event in events:
if event.type == FilesystemEventType.WRITE and event.name == filename:
write_event = event
break
assert write_event is not None, (
f"Expected WRITE event for {filename}, but got events: {events}"
)
# The entry is populated best-effort for events where the path still exists.
assert write_event.entry is not None
assert write_event.entry.name == filename
assert write_event.entry.path == f"/home/user/{dirname}/{filename}"
assert write_event.entry.type == FileType.FILE
handle.stop()
def test_watch_directory_changes_with_network_mounts_allowed(sandbox: Sandbox):
dirname = "test_watch_dir_network_mounts"
filename = "test_watch.txt"
content = "This file will be watched."
new_content = "This file has been modified."
sandbox.files.make_dir(dirname)
sandbox.files.write(f"{dirname}/{filename}", content)
# The flag only lifts the network-mount restriction — watching a regular
# directory must work the same with it enabled.
handle = sandbox.files.watch_dir(dirname, allow_network_mounts=True)
sandbox.files.write(f"{dirname}/{filename}", new_content)
events = handle.get_new_events()
write_event = None
for event in events:
if event.type == FilesystemEventType.WRITE and event.name == filename:
write_event = event
break
assert write_event is not None, (
f"Expected WRITE event for {filename}, but got events: {events}"
)
handle.stop()
def test_watch_directory_changes(sandbox: Sandbox):
dirname = "test_watch_dir"
filename = "test_watch.txt"
content = "This file will be watched."
new_content = "This file has been modified."
sandbox.files.make_dir(dirname)
sandbox.files.write(f"{dirname}/{filename}", content)
handle = sandbox.files.watch_dir(dirname)
sandbox.files.write(f"{dirname}/{filename}", new_content)
events = handle.get_new_events()
write_event = None
for event in events:
if event.type == FilesystemEventType.WRITE and event.name == filename:
write_event = event
break
assert write_event is not None, (
f"Expected WRITE event for {filename}, but got events: {events}"
)
assert write_event.name == filename
handle.stop()
def test_watch_iterated(sandbox: Sandbox):
dirname = "test_watch_dir_iterated"
filename = "test_watch_iterated.txt"
content = "This file will be watched."
new_content = "This file has been modified."
sandbox.files.make_dir(dirname)
handle = sandbox.files.watch_dir(dirname)
sandbox.files.write(f"{dirname}/{filename}", content)
events = handle.get_new_events()
assert len(events) == 3
sandbox.files.write(f"{dirname}/{filename}", new_content)
events = handle.get_new_events()
for event in events:
if event.type == FilesystemEventType.WRITE and event.name == filename:
break
handle.stop()
def test_watch_recursive_directory_changes(sandbox: Sandbox):
dirname = "test_recursive_watch_dir"
nested_dirname = "test_nested_watch_dir"
filename = "test_watch.txt"
content = "This file will be watched."
sandbox.files.remove(dirname)
sandbox.files.make_dir(f"{dirname}/{nested_dirname}")
handle = sandbox.files.watch_dir(dirname, recursive=True)
sandbox.files.write(f"{dirname}/{nested_dirname}/{filename}", content)
events = handle.get_new_events()
assert len(events) == 3
expected_filename = f"{nested_dirname}/{filename}"
assert events[0].type == FilesystemEventType.CREATE
assert events[0].name == expected_filename
handle.stop()
def test_watch_recursive_directory_after_nested_folder_addition(sandbox: Sandbox):
dirname = "test_recursive_watch_dir_add"
nested_dirname = "test_nested_watch_dir"
filename = "test_watch.txt"
content = "This file will be watched."
sandbox.files.remove(dirname)
sandbox.files.make_dir(dirname)
handle = sandbox.files.watch_dir(dirname, recursive=True)
sandbox.files.make_dir(f"{dirname}/{nested_dirname}")
sandbox.files.write(f"{dirname}/{nested_dirname}/{filename}", content)
expected_filename = f"{nested_dirname}/{filename}"
events = handle.get_new_events()
file_changed = False
folder_created = False
for event in events:
if event.type == FilesystemEventType.WRITE and event.name == expected_filename:
file_changed = True
continue
if event.type == FilesystemEventType.CREATE and event.name == nested_dirname:
folder_created = True
assert folder_created
assert file_changed
handle.stop()
def test_watch_non_existing_directory(sandbox: Sandbox):
dirname = "non_existing_watch_dir"
with pytest.raises(FileNotFoundException):
sandbox.files.watch_dir(dirname)
def test_watch_file(sandbox: Sandbox):
filename = "test_watch.txt"
sandbox.files.write(filename, "This file will be watched.")
with pytest.raises(SandboxException):
sandbox.files.watch_dir(filename)
def test_watch_file_with_secured_envd(sandbox_factory):
sbx = sandbox_factory(timeout=30, secure=True)
sbx.files.watch_dir("/home/user/")
sbx.files.write("test_watch.txt", "This file will be watched.")
@@ -0,0 +1,218 @@
import io
import uuid
from e2b.sandbox.filesystem.filesystem import FileType, WriteInfo, WriteEntry
def test_write_text_file(sandbox, debug):
filename = "test_write.txt"
content = "This is a test file."
info = sandbox.files.write(filename, content)
assert info.path == f"/home/user/{filename}"
assert info.type == FileType.FILE
exists = sandbox.files.exists(filename)
assert exists
read_content = sandbox.files.read(filename)
assert read_content == content
if debug:
sandbox.files.remove(filename)
def test_write_binary_file(sandbox, debug):
filename = "test_write.bin"
text = "This is a test binary file."
# equivalent to `open("path/to/local/file", "rb")`
content = io.BytesIO(text.encode("utf-8"))
info = sandbox.files.write(filename, content)
assert info.path == f"/home/user/{filename}"
exists = sandbox.files.exists(filename)
assert exists
read_content = sandbox.files.read(filename)
assert read_content == text
if debug:
sandbox.files.remove(filename)
def test_write_multiple_files(sandbox, debug):
num_test_files = 10
# Attempt to write with empty files array
empty_info = sandbox.files.write_files([])
assert isinstance(empty_info, list)
assert len(empty_info) == 0
# Attempt to write with no files
assert sandbox.files.write_files([]) == []
# Attempt to write with one file in array
one_file_path = "one_test_file.txt"
info = sandbox.files.write_files(
[WriteEntry(path=one_file_path, data="This is a test file.")]
)
assert isinstance(info, list)
assert len(info) == 1
info = info[0]
assert isinstance(info, WriteInfo)
assert info.path == "/home/user/one_test_file.txt"
exists = sandbox.files.exists(info.path)
assert exists
read_content = sandbox.files.read(info.path)
assert read_content == "This is a test file."
# Attempt to write with multiple files in array
files = []
for i in range(num_test_files):
path = f"test_write_{i}.txt"
content = f"This is a test file {i}."
files.append(WriteEntry(path=path, data=content))
infos = sandbox.files.write_files(files)
assert isinstance(infos, list)
assert len(infos) == len(files)
for i, info in enumerate(infos):
assert isinstance(info, WriteInfo)
assert info.path == f"/home/user/test_write_{i}.txt"
assert info.type == FileType.FILE
exists = sandbox.files.exists(path)
assert exists
read_content = sandbox.files.read(info.path)
assert read_content == files[i]["data"]
if debug:
sandbox.files.remove(one_file_path)
for i in range(num_test_files):
sandbox.files.remove(f"test_write_{i}.txt")
def test_overwrite_file(sandbox, debug):
filename = "test_overwrite.txt"
initial_content = "Initial content."
new_content = "New content."
sandbox.files.write(filename, initial_content)
sandbox.files.write(filename, new_content)
read_content = sandbox.files.read(filename)
assert read_content == new_content
if debug:
sandbox.files.remove(filename)
def test_write_to_non_existing_directory(sandbox, debug):
filename = "non_existing_dir/test_write.txt"
content = "This should succeed too."
sandbox.files.write(filename, content)
exists = sandbox.files.exists(filename)
assert exists
read_content = sandbox.files.read(filename)
assert read_content == content
if debug:
sandbox.files.remove(filename)
def test_write_with_secured_envd(sandbox_factory):
filename = f"non_existing_dir_{uuid.uuid4()}/test_write.txt"
content = "This should succeed too."
sbx = sandbox_factory(timeout=30, secure=True)
assert sbx.is_running()
assert sbx._envd_version is not None
assert sbx._envd_access_token is not None
sbx.files.write(filename, content)
exists = sbx.files.exists(filename)
assert exists
read_content = sbx.files.read(filename)
assert read_content == content
def test_write_files_with_different_data_types(sandbox, debug):
text_data = "Text string data"
bytes_data = b"Bytes data"
bytes_io_data = io.BytesIO(b"BytesIO data")
string_io_data = io.StringIO("StringIO data")
files = [
WriteEntry(path="writefiles_text.txt", data=text_data),
WriteEntry(path="writefiles_bytes.bin", data=bytes_data),
WriteEntry(path="writefiles_bytesio.bin", data=bytes_io_data),
WriteEntry(path="writefiles_stringio.txt", data=string_io_data),
]
infos = sandbox.files.write_files(files)
assert len(infos) == 4
text_content = sandbox.files.read("writefiles_text.txt")
assert text_content == text_data
bytes_content = sandbox.files.read("writefiles_bytes.bin")
assert bytes_content == "Bytes data"
bytes_io_content = sandbox.files.read("writefiles_bytesio.bin")
assert bytes_io_content == "BytesIO data"
string_io_content = sandbox.files.read("writefiles_stringio.txt")
assert string_io_content == "StringIO data"
if debug:
for file in files:
sandbox.files.remove(file["path"])
def test_write_io_with_octet_stream(sandbox, debug):
filename = "test_write_octet_io.bin"
text = "Streamed octet-stream upload. " * 10_000
content = io.BytesIO(text.encode("utf-8"))
info = sandbox.files.write(filename, content, use_octet_stream=True)
assert info.path == f"/home/user/{filename}"
read_content = sandbox.files.read(filename)
assert read_content == text
if debug:
sandbox.files.remove(filename)
def test_write_text_io_with_octet_stream(sandbox, debug):
filename = "test_write_octet_text_io.txt"
text = "Streamed text octet-stream upload."
sandbox.files.write(filename, io.StringIO(text), use_octet_stream=True)
read_content = sandbox.files.read(filename)
assert read_content == text
if debug:
sandbox.files.remove(filename)
def test_write_io_with_octet_stream_and_gzip(sandbox, debug):
filename = "test_write_octet_io_gzip.bin"
text = "Streamed gzipped octet-stream upload. " * 10_000
content = io.BytesIO(text.encode("utf-8"))
sandbox.files.write(filename, content, use_octet_stream=True, gzip=True)
read_content = sandbox.files.read(filename)
assert read_content == text
if debug:
sandbox.files.remove(filename)