Skip to main content
Code Review

Return to Answer

replaced http://stackoverflow.com/ with https://stackoverflow.com/
Source Link

In order to be trully versatile, we should be able to parametrize the building of this bitfield by its length. Unfortunately, integers are immutable and we can modify them in their __init__ method integers are immutable and we can modify them in their __init__ method. So we need to use __new__ instead:

In order to be trully versatile, we should be able to parametrize the building of this bitfield by its length. Unfortunately, integers are immutable and we can modify them in their __init__ method. So we need to use __new__ instead:

In order to be trully versatile, we should be able to parametrize the building of this bitfield by its length. Unfortunately, integers are immutable and we can modify them in their __init__ method. So we need to use __new__ instead:

Source Link

#Interface usage

Given an AppliancePerms instance app_perm, you have app_perm.rest, app_perm.ssh and app_perm.cmd accept and return integers while app_perm.permissions accept an integer but return a string. This is, at best, confusing.

Furthermore, reading at the variable names, the intended usage for setting rest, ssh and cmd is to use app_perm.ssh = True or app_perm.cmd = False whereas getting the value app_perm.ssh will return 2 or 0.

You should improve the consistency here:

  • return booleans when accessing individual fields;
  • return integers when accessing the whole permissions.

#Proper formatting

On the other hand, I understand that you would like to have an pretty rendering of the selected bits. One way of doing it, is returning a subclass of int that will show itself as a bitfield:

class BitField(int):
 def __repr__(self):
 return '{:0{}b}'.format(self, 3)

You’ll note that I simplified the formating from integer to string. str.format is very versatile and you should favor it instead of manually manipulating string. Usage of this class being:

>>> five = BitField(5)
>>> print(five)
5
>>> str(five)
'5'
>>> repr(five)
'101'
>>> five
101

In order to be trully versatile, we should be able to parametrize the building of this bitfield by its length. Unfortunately, integers are immutable and we can modify them in their __init__ method. So we need to use __new__ instead:

class BitField(int):
 def __new__(cls, value, length):
 the_integer = super().__new__(cls, value)
 the_integer._field_length = length
 return the_integer
 def __repr__(self):
 return '{:0{}b}'.format(self, self._field_length)

#Parsing provided permissions

In the same vein, using app_perms.permissions = int('101', 2) is unfriendly. So you should parse it in your @permissions.setter. Getting a bitfield and setting it back should obviously work, but you could support being assigned a string or even an integer reprensenting a bitfield so '101', 101 or BitField(5) could work the same.

#Proposed improvements

class BitField(int):
 def __new__(cls, value, length):
 the_integer = super().__new__(cls, value)
 the_integer._field_length = length
 return the_integer
 def __repr__(self):
 return '{:0{}b}'.format(self, self._field_length)
class AppliancePerms(object):
 """Permissions for the Appliance class."""
 _cmd_right = 2 ** 0
 _rest_right = 2 ** 1
 _ssh_right = 2 ** 2
 _num_of_rights = 3
 _all_rights = _cmd_right + _rest_right + _ssh_right
 def __init__(self, perm_digits=None):
 # default to all rights
 if perm_digits is None:
 self._perms = AppliancePerms._all_rights
 else:
 self._perms = perm_digits
 @property
 def permissions(self):
 return BitField(self._perms, AppliancePerms._num_of_rights)
 @permissions.setter
 def permissions(self, perm_digits):
 self._perms = int(repr(perm_digits), 2)
 @permissions.deleter
 def permissions(self):
 self._perms = 0
 @property
 def rest(self):
 return bool(self._perms & AppliancePerms._rest_right)
 @rest.setter
 def rest(self, boolean):
 if boolean:
 self._perms |= AppliancePerms._rest_right
 else:
 del self.rest
 @rest.deleter
 def rest(self):
 if self._perms & AppliancePerms._rest_right:
 self._perms -= AppliancePerms._rest_right
 @property
 def ssh(self):
 return bool(self._perms & AppliancePerms._ssh_right)
 @ssh.setter
 def ssh(self, boolean):
 if boolean:
 self._perms |= AppliancePerms._ssh_right
 else:
 del self.ssh
 @ssh.deleter
 def ssh(self):
 if self._perms & AppliancePerms._ssh_right:
 self.perms -= AppliancePerms._ssh_right
 @property
 def cmd(self):
 return bool(self._perms & AppliancePerms._cmd_right)
 @cmd.setter
 def cmd(self, boolean):
 if boolean:
 self._perms |= AppliancePerms._cmd_right
 else:
 del self.cmd
 @cmd.deleter
 def cmd(self):
 if self._perms & AppliancePerms._cmd_right:
 self._perms -= AppliancePerms._cmd_right
lang-py

AltStyle によって変換されたページ (->オリジナル) /