3

Python has spwd module to interact with shadow password file.

You must be root to use spwd module.

>>> import spwd;

>>> a = spwd.getspnam('bin')

>>> type(a)
<class 'spwd.struct_spwd'>

>>> a.__gt__
<method-wrapper '__gt__' of spwd.struct_spwd object at 0x7fd017641b80>

Now I want to add a new attribute to object 'a' (or class 'struct_spwd'). How do I do that?

Inheritance does not work.

import spwd

class Abc(spwd.struct_spwd):
    pass

I got "TypeError: type 'spwd.struct_spwd' is not an acceptable base type".

Adding dynamic attributes to object does not work.

import spwd

a = spwd.getspnam('bin')
a.new_attribute = lambda: print('hello world')

I got "AttributeError: 'spwd.struct_spwd' object has no attribute 'new_attribute'".

Using delegation could work, though. But I want to preserve its original attributes.

import spwd

class Abc(object):
    def __init__(self, struct_spwd):
        self.struct_spwd = struct_spwd

    def __getattribute__(self, name):
        if name=='new_attribute':
            print('hello world')
        else:
            self.struct_spwd.__getattribute__(name)

a = spwd.getspnam('bin')
b = Abc(a)
b.new_attribute
b.__gt__

I got "RuntimeError: maximum recursion depth exceeded in comparison".

Any idea? Or should I use other ways to achieve my goal? Thx.

arjunaskykok
  • 946
  • 10
  • 17

2 Answers2

3
class Wrapper(object):
    def __init__(self, wrapped):
        self.wrapped = wrapped

    def __getattr__(self, name):
        if name.startswith('sp_'):
            value = getattr(self.wrapped, name)
            setattr(self, name, value)
            return value

        raise AttributeError

The code also caches the values, so that __getattr__ is only called once per each member.

2

Check out this thread:

How is the __getattribute__ method used?

What you want to use is getattr():


class Abc(object):
    def __init__(self, struct_spwd):
        self.struct_spwd = struct_spwd

    def __getattr__(self, name):
        if name=='new_attribute':
            print('hello world')
        else:
            return getattr(self.struct_spwd, name)

Community
  • 1
  • 1
Joohwan
  • 2,374
  • 1
  • 19
  • 30