Skip to content

Commit ef7834d

Browse files
committed
[feature] Add overrides decorator
1 parent dc66b97 commit ef7834d

File tree

9 files changed

+247
-98
lines changed

9 files changed

+247
-98
lines changed

.github/workflows/tests.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ jobs:
7878
- os: ubuntu-22.04
7979
python-version: '3.8'
8080

81+
env:
82+
MFUSEPY_CHECK_OVERRIDES: 1
8183
defaults:
8284
run:
8385
# This is especially important for windows because it seems to default to powershell
@@ -127,6 +129,13 @@ jobs:
127129
run: |
128130
python3 -c 'import mfusepy'
129131
132+
- name: Examples
133+
run: |
134+
# Simply parsing the source runs the @overrides check!
135+
for file in examples/*.py; do
136+
python3 "$file" -h
137+
done
138+
130139
- name: Unit Tests (FUSE 2)
131140
if: startsWith( matrix.os, 'ubuntu' )
132141
run: |

examples/context.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,19 @@
55
import logging
66
import stat
77
import time
8+
from typing import Any, Dict, Optional
89

9-
import mfusepy
10+
import mfusepy as fuse
1011

1112

12-
class Context(mfusepy.Operations):
13+
class Context(fuse.Operations):
1314
'Example filesystem to demonstrate fuse_get_context()'
1415

15-
def getattr(self, path, fh=None):
16-
uid, gid, pid = mfusepy.fuse_get_context()
16+
@fuse.overrides(fuse.Operations)
17+
def getattr(self, path: str, fh: Optional[int] = None):
18+
uid, gid, pid = fuse.fuse_get_context()
1719
if path == '/':
18-
st = {'st_mode': (stat.S_IFDIR | 0o755), 'st_nlink': 2}
20+
st: Dict[str, Any] = {'st_mode': (stat.S_IFDIR | 0o755), 'st_nlink': 2}
1921
elif path == '/uid':
2022
size = len(f'{uid}\n')
2123
st = {'st_mode': (stat.S_IFREG | 0o444), 'st_size': size}
@@ -26,12 +28,13 @@ def getattr(self, path, fh=None):
2628
size = len(f'{pid}\n')
2729
st = {'st_mode': (stat.S_IFREG | 0o444), 'st_size': size}
2830
else:
29-
raise mfusepy.FuseOSError(errno.ENOENT)
31+
raise fuse.FuseOSError(errno.ENOENT)
3032
st['st_ctime'] = st['st_mtime'] = st['st_atime'] = time.time()
3133
return st
3234

33-
def read(self, path, size, offset, fh):
34-
uid, gid, pid = mfusepy.fuse_get_context()
35+
@fuse.overrides(fuse.Operations)
36+
def read(self, path: str, size: int, offset: int, fh: int) -> bytes:
37+
uid, gid, pid = fuse.fuse_get_context()
3538

3639
def encoded(x):
3740
return (f'{x}\n').encode()
@@ -45,7 +48,8 @@ def encoded(x):
4548

4649
raise RuntimeError(f'unexpected path: {path!r}')
4750

48-
def readdir(self, path, fh):
51+
@fuse.overrides(fuse.Operations)
52+
def readdir(self, path: str, fh: int):
4953
return ['.', '..', 'uid', 'gid', 'pid']
5054

5155

@@ -55,7 +59,7 @@ def cli(args=None):
5559
args = parser.parse_args(args)
5660

5761
logging.basicConfig(level=logging.DEBUG)
58-
mfusepy.FUSE(Context(), args.mount, foreground=True, ro=True)
62+
fuse.FUSE(Context(), args.mount, foreground=True, ro=True)
5963

6064

6165
if __name__ == '__main__':

examples/ioctl.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ def __init__(self):
4242
'st_nlink': 2,
4343
}
4444

45-
def create(self, path, mode, fi=None):
45+
@fuse.overrides(fuse.Operations)
46+
def create(self, path: str, mode, fi=None) -> int:
4647
self.files[path] = {
4748
'st_mode': (stat.S_IFREG | mode),
4849
'st_nlink': 1,
@@ -55,13 +56,15 @@ def create(self, path, mode, fi=None):
5556
self.fd += 1
5657
return self.fd
5758

58-
def getattr(self, path, fh=None):
59+
@fuse.overrides(fuse.Operations)
60+
def getattr(self, path: str, fh=None):
5961
if path not in self.files:
6062
raise fuse.FuseOSError(errno.ENOENT)
6163

6264
return self.files[path]
6365

64-
def ioctl(self, path, cmd, arg, fh, flags, data):
66+
@fuse.overrides(fuse.Operations)
67+
def ioctl(self, path: str, cmd, arg, fh, flags, data) -> int:
6568
M_IOWR = IOWR(ord('M'), 1, ctypes.c_uint32)
6669
if cmd == M_IOWR:
6770
inbuf = ctypes.create_string_buffer(4)
@@ -74,14 +77,17 @@ def ioctl(self, path, cmd, arg, fh, flags, data):
7477
raise fuse.FuseOSError(errno.ENOTTY)
7578
return 0
7679

77-
def open(self, path, flags):
80+
@fuse.overrides(fuse.Operations)
81+
def open(self, path: str, flags) -> int:
7882
self.fd += 1
7983
return self.fd
8084

81-
def read(self, path, size, offset, fh):
85+
@fuse.overrides(fuse.Operations)
86+
def read(self, path: str, size, offset, fh) -> bytes:
8287
return self.data[path][offset : offset + size]
8388

84-
def readdir(self, path, fh):
89+
@fuse.overrides(fuse.Operations)
90+
def readdir(self, path: str, fh):
8591
return ['.', '..'] + [x[1:] for x in self.files if x != '/']
8692

8793

examples/loopback.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ def __init__(self, root):
2929
self.rwlock = threading.Lock()
3030

3131
@with_root_path
32+
@fuse.overrides(fuse.Operations)
3233
def access(self, path, amode):
3334
if not os.access(path, amode):
3435
raise fuse.FuseOSError(errno.EACCES)
@@ -37,21 +38,25 @@ def access(self, path, amode):
3738
chown = static_with_root_path(os.chown)
3839

3940
@with_root_path
41+
@fuse.overrides(fuse.Operations)
4042
def create(self, path, mode, fi=None):
4143
return os.open(path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC, mode)
4244

4345
@with_root_path
46+
@fuse.overrides(fuse.Operations)
4447
def flush(self, path, fh):
4548
return os.fsync(fh)
4649

4750
@with_root_path
51+
@fuse.overrides(fuse.Operations)
4852
def fsync(self, path, datasync, fh):
4953
if datasync != 0:
5054
return os.fdatasync(fh)
5155
return os.fsync(fh)
5256

5357
@fuse.log_callback
5458
@with_root_path
59+
@fuse.overrides(fuse.Operations)
5560
def getattr(self, path, fh=None):
5661
st = os.lstat(path)
5762
return {
@@ -60,6 +65,7 @@ def getattr(self, path, fh=None):
6065
}
6166

6267
@with_root_path
68+
@fuse.overrides(fuse.Operations)
6369
def link(self, target, source):
6470
return os.link(self.root + source, target)
6571

@@ -68,28 +74,33 @@ def link(self, target, source):
6874
open = static_with_root_path(os.open)
6975

7076
@with_root_path
71-
def read(self, path, size, offset, fh):
77+
@fuse.overrides(fuse.Operations)
78+
def read(self, path, size, offset, fh) -> bytes:
7279
with self.rwlock:
7380
os.lseek(fh, offset, 0)
7481
return os.read(fh, size)
7582

7683
@with_root_path
84+
@fuse.overrides(fuse.Operations)
7785
def readdir(self, path, fh):
7886
return ['.', '..', *os.listdir(path)]
7987

8088
readlink = static_with_root_path(os.readlink)
8189

8290
@with_root_path
91+
@fuse.overrides(fuse.Operations)
8392
def release(self, path, fh):
8493
return os.close(fh)
8594

8695
@with_root_path
96+
@fuse.overrides(fuse.Operations)
8797
def rename(self, old, new):
8898
return os.rename(old, self.root + new)
8999

90100
rmdir = static_with_root_path(os.rmdir)
91101

92102
@with_root_path
103+
@fuse.overrides(fuse.Operations)
93104
def statfs(self, path):
94105
stv = os.statvfs(path)
95106
return {
@@ -109,19 +120,22 @@ def statfs(self, path):
109120
}
110121

111122
@with_root_path
123+
@fuse.overrides(fuse.Operations)
112124
def symlink(self, target, source):
113125
return os.symlink(source, target)
114126

115127
@with_root_path
128+
@fuse.overrides(fuse.Operations)
116129
def truncate(self, path, length, fh=None):
117-
with open(path, 'r+') as f:
130+
with open(path, 'rb+') as f:
118131
f.truncate(length)
119132

120133
unlink = static_with_root_path(os.unlink)
121134
utimens = static_with_root_path(os.utime)
122135

123136
@fuse.log_callback
124137
@with_root_path
138+
@fuse.overrides(fuse.Operations)
125139
def write(self, path, data, offset, fh):
126140
with self.rwlock:
127141
os.lseek(fh, offset, 0)

0 commit comments

Comments
 (0)