I implemented a virtual file system library with POSIX file mode representation.
Any suggestions regarding optimization are welcome.
"""POSIX file system library."""
from collections import namedtuple
__all__ = ['PosixPermission', 'PosixMode']
MIN_PERM = 0b000
MAX_PERM = 0b111
DEF_PERM = 0b110 # rw-
MIN_MODE = 0o000
MAX_MODE = 0o777
DEF_MODE = 0o640
class PosixPermission(namedtuple('PosixPermission', 'read write execute')):
"""POSIX file permissions."""
@classmethod
def from_int(cls, perm=DEF_PERM):
"""Creates the file permissions from the respective integer value."""
if MIN_PERM <= perm <= MAX_PERM:
return cls(bool(perm & 4), bool(perm & 2), bool(perm & 1))
raise ValueError('Permission value must be between {} and {}.'.format(
MIN_PERM, MAX_PERM))
def __int__(self):
"""Returns the integer value of the file permission."""
return (self.read and 4) + (self.write and 2) + (self.execute and 1)
def __str__(self):
"""Returns binary representation of the file permission."""
return ''.join(map(
lambda perm: perm or '-',
(self.read and 'r', self.write and 'w', self.execute and 'x')))
class PosixMode(namedtuple('PosixMode', 'user group other')):
"""POSIX file mode."""
@classmethod
def from_int(cls, mode=DEF_MODE):
"""Creates the file mode from the respective integer value."""
if MIN_MODE <= mode <= MAX_MODE:
return cls(
PosixPermission.from_int(mode >> 6 & 7),
PosixPermission.from_int(mode >> 3 & 7),
PosixPermission.from_int(mode & 7))
raise ValueError('File mode must be between {} and {}.'.format(
oct(MIN_MODE), oct(MAX_MODE)))
def __int__(self):
"""Returns the integer value of the file mode."""
return (int(self.user) << 6) + (int(self.group) << 3) + int(self.other)
def __str__(self):
"""Returns the octal representation of the file mode."""
return ''.join((str(self.user), str(self.group), str(self.other)))
1 Answer 1
I'm confused why you're using a named tuple for PosixPermission
. To me an Enum would be a better choice:
class PosixPermission(Flag):
READ = 4
WRITE = 2
EXECUTE = 1
NONE = 0
@property
def perms(self):
return ''.join(
name if self & val else '-'
for name, val in zip('rwx', PosixPermission)
)
>>> PosixPermission(0)
<PosixPermission.NONE: 0>
>>> PosixPermission(7)
<PosixPermission.READ|WRITE|EXECUTE: 7>
>>> PosixPermission(5)
<PosixPermission.READ|EXECUTE: 5>
>>> PosixPermission(5).perms
'r-x'
>>> PosixPermission(5) & PosixPermission.READ
<PosixPermission.READ: 4>
>>> PosixPermission(5) & PosixPermission.WRITE
<PosixPermission.NONE: 0>
>>> PosixPermission(8)
Traceback (most recent call last):
ValueError: 8 is not a valid PosixPermission
Honestly PosixMode
looks pretty good, I think it's reasonable to assume it to be a namedtuple
, rather than an object
with __slots__
. I however wouldn't use __int__
and __str__
, and would instead use properties for these.
-
\$\begingroup\$ I do not understand your enum approach. How would I get a permission instance of, let's say
r-x
(read, not write, execute) with it? \$\endgroup\$Richard Neumann– Richard Neumann2017年11月22日 10:05:36 +00:00Commented Nov 22, 2017 at 10:05 -
\$\begingroup\$ @RichardNeumann As demonstrated above,
PosixPermission(5)
. \$\endgroup\$2017年11月22日 10:07:09 +00:00Commented Nov 22, 2017 at 10:07 -
\$\begingroup\$ Ah. Got it. But then I could not do
if posix_mode.user.write
without adding thewrite
property, which I already have on the namedtuple. \$\endgroup\$Richard Neumann– Richard Neumann2017年11月22日 10:09:07 +00:00Commented Nov 22, 2017 at 10:09 -
2\$\begingroup\$ @RichardNeumann You can however use
if posix_mode.user & PosixPermission.WRITE
. If you don't like the length of it, you can just makePosixPermission.WRITE
a variable, and useif posix_mode.user&WRITE
. \$\endgroup\$2017年11月22日 10:09:55 +00:00Commented Nov 22, 2017 at 10:09 -
\$\begingroup\$ @MaartenFabré That's exactly what I meant to say in my last comment. \$\endgroup\$Richard Neumann– Richard Neumann2017年11月22日 11:01:22 +00:00Commented Nov 22, 2017 at 11:01
Explore related questions
See similar questions with these tags.