Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for unpfs (rust-9p) server and 9P2000.L #3

Merged
merged 14 commits into from
Dec 22, 2023
23 changes: 20 additions & 3 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
name: Test

on: [pull_request]
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
run-tests:
Expand All @@ -15,8 +19,21 @@ jobs:
- "3.11"
fail-fast: false
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Checkout p9fs
uses: actions/checkout@v4

- name: Checkout rust-9p
uses: actions/checkout@v4
with:
repository: pfpacket/rust-9p
path: rust-9p

- name: Build unpfs
run: |
cd rust-9p/example/unpfs/
cargo build --release
mkdir -p ~/.local/bin
ln -s $PWD/target/release/unpfs ~/.local/bin

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.idea/
**/.pytest_cache/
**/__pycache__/
build/
**/*.egg-info/
dist/
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,35 @@

9P implementation of Python fsspec.

Supported protocols:

* [9P2000](https://ericvh.github.io/9p-rfc/rfc9p2000.html)
* [9P2000.u](https://ericvh.github.io/9p-rfc/rfc9p2000.u.html)
* [9P2000.L](https://github.com/chaos/diod/blob/master/protocol.md)

Supported servers:

* [py9p](https://github.com/pbchekin/p9fs-py/blob/main/src/py9p/__main__.py)
* [unpfs](https://github.com/pfpacket/rust-9p/blob/master/README.md#unpfs)

## Examples

```python
import p9fs

fs = p9fs.P9FileSystem(
host='127.0.0.1',
port=564,
username='nobody',
)

print(fs.ls('.'))
```

## TODO

* `auth`
* `atime`, `mtime`, `ctime`

This package contains a fork of py9p (https://github.com/svinota/py9p), which seems no longer maintained.
Minimal support for 9P2000.L has been added to the client code.
4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "p9fs"
version = "0.0.1"
version = "0.0.2"
description = "9P implementation of Python fsspec"
license = {file = "LICENSE"}
readme = "README.md"
Expand Down Expand Up @@ -36,3 +36,5 @@ build-backend = "setuptools.build_meta"
where = ["src"]
include = ["p9fs*", "py9p*"]
namespaces = false

[tool.pytest.ini_options]
88 changes: 71 additions & 17 deletions scripts/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,46 +6,84 @@ set -e

PROJECT_ROOT="$(git rev-parse --show-toplevel)"
TMP_DIRS_FILE=/tmp/p9fs-dirs
PY9S_SERVER_PID=/tmp/p9fs.pid
PY9S_SERVER_LOG=/tmp/p9fs.log

PY9P_PID=/tmp/py9p.pid
PY9P_LOG=/tmp/py9p.log

UNPFS_PID=/tmp/unpfs.pid
UNPFS_LOG=/tmp/unpfs.log

export PYTHONUNBUFFERED=1

function mymktempdir {
local tmpdir="$(mktemp -d)"
echo "$tmpdir" | tee -a $TMP_DIRS_FILE
}

function run_py9s_server {
local exported_dir="$1"
cd "$PROJECT_ROOT/src"
python -m py9p -p 1234 -w -d -r "$exported_dir" &> $PY9S_SERVER_LOG &
echo $! > $PY9S_SERVER_PID

function wait_for_server {
echo Waiting for 9p server ...
SERVER_READY=""
for i in $(seq 1 5); do
sleep 1
if nc -d -w 1 -z 127.0.0.1 1234; then
SERVER_READY="true"
break
fi
sleep 1
done
if [[ ! $SERVER_READY ]]; then
echo 9p server failed to start
exit 1
fi
}

function user_tests {
function run_py9p {
local exported_dir="$1"
local protocol="$2"

args=(
-p 1234
-w
-d
-r "$exported_dir"
)

if [[ $protocol == "9P2000.u" ]]; then
args+=( -D )
fi

cd "$PROJECT_ROOT/src"
python -m pytest -v -rA ../tests/user --exported "$exported_dir"
python -m py9p "${args[@]}" &> $PY9P_LOG &
echo $! > $PY9P_PID
wait_for_server
}

function cleanup {
if [[ -f $PY9S_SERVER_PID ]]; then
kill "$(<$PY9S_SERVER_PID)" || true
rm -f "$PY9S_SERVER_PID"
function stop_py9p {
if [[ -f $PY9P_PID ]]; then
kill "$(<$PY9P_PID)" || true
rm -f "$PY9P_PID"
fi
}

function run_unpfs {
local exported_dir="$1"
${UNPFS:-unpfs} 'tcp!0.0.0.0!1234' "$exported_dir" &> $UNPFS_LOG &
echo $! > $UNPFS_PID
wait_for_server
}

function stop_unpfs {
if [[ -f $UNPFS_PID ]]; then
kill "$(<$UNPFS_PID)" || true
rm -f "$UNPFS_PID"
fi
}

function user_tests {
cd "$PROJECT_ROOT/src"
python -m pytest -v -rA ../tests/user "$@"
}

function cleanup {
if [[ -f $TMP_DIRS_FILE ]]; then
xargs -n1 -r rm -rf < $TMP_DIRS_FILE
rm -f $TMP_DIRS_FILE
Expand All @@ -56,6 +94,22 @@ trap cleanup EXIT

rm -f "$TMP_DIRS_FILE"

echo "PROJECT_ROOT: $PROJECT_ROOT"

echo "Testing py9p server with 9P2000"
EXPORTED_DIR=""$(mymktempdir)""
run_py9p "$EXPORTED_DIR" 9P2000
user_tests --exported "$EXPORTED_DIR" --9p 9P2000
stop_py9p

echo "Testing py9p server with 9P2000.u"
EXPORTED_DIR=""$(mymktempdir)""
run_py9p "$EXPORTED_DIR" 9P2000.u
user_tests --exported "$EXPORTED_DIR" --9p 9P2000.u
stop_py9p

echo "Testing unpfs server with 9P2000.L"
EXPORTED_DIR=""$(mymktempdir)""
run_py9s_server "$EXPORTED_DIR"
user_tests "$EXPORTED_DIR"
run_unpfs "$EXPORTED_DIR"
user_tests --exported "$EXPORTED_DIR" --9p 9P2000.L
stop_unpfs
Loading