7

There is some python code that works under Linux. It uses the pwd module in a way like that:

import pwd
   ...
  def func():
      user=pwd.getpwnam(user)[2]

Now we have a specific need to cover this code with tests, and tests have to be runnable under Windows. The program itself is intended to run only under Linux. The problem is that pwd module is not available under Windows, so the code under test will fail with ImportError, even if the implementation of pwd functions is mocked using MagicMock.

The basic idea to solve this issue was to shadow the pwd module when running tests. So when running tests, the stub will shadow pwd and when running main program, original (Unix) pwd will be used. We created such stub at test PYTHONPATH:

# pwd.py
def getpwnam(user):
    print("YESSSSSSSS")

But it does not seem to shadow a pwd module, in a debugger we see that the built-in pwd is imported. I'm primarily a Java developer, so I'm sorry if the way of doing things is not "pythonic". Ideas are welcome.

Dmitriusan
  • 11,525
  • 3
  • 38
  • 38

2 Answers2

16

Rename your pwd.py to something else, such as winpwd.py. Then use:

try:
    import pwd
except ImportError:
    import winpwd as pwd

By importing pwd this way, you will get the built-in pwd on Linux, and winpwd on Windows. Then you should be able to run tests and mock it as you please.

unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
  • how are you supposed to install winpwd? pip doesn't have it indexed, and a google search find weird things. – syonip Dec 06 '15 at 20:46
  • 6
    @syonip, @Locane: That module doesn't exist; `winpwd` was a name that unutbu made up (see the OP) – Clément Nov 13 '16 at 04:15
  • This doesn't work. in windows server 2012 with python 3.7. The module pwd itself is not available as part of the standard install in Windows. – Soundararajan Aug 15 '20 at 04:08
6
import os
if os.name == 'nt':
    class Pwd():
        def getpwnam(self, user):
            pass
    pwd = Pwd()
else:
    import pwd

Could something similar work? No need for extra .py files within your project.
I've used it for fchown myself a couple of times...

Torxed
  • 22,866
  • 14
  • 82
  • 131
  • That won't work as written. Every method will have to be a @classmethod decorated function. – Ian Stapleton Cordasco May 13 '13 at 19:04
  • Why wouldn't this work? I just created a class that you can instanciate? There, fixed it? – Torxed May 13 '13 at 19:06
  • Just read the OP's last two lines that he wasn't a experienced Python developer, i was hoping for common sense.. but sure my pre-edit was a bit broke. so i guess thx :) – Torxed May 13 '13 at 19:09
  • Thank you for your answer. It does not completely fit our scenario, but I would definitely +1 it if could. – Dmitriusan May 13 '13 at 19:15
  • Np, just thought not having to ship extra files would be useful :) Gl with your project. – Torxed May 13 '13 at 19:31