Add method to OS built-in module

67 views Asked by At

My understanding is that os is not a class, but rather a built-in module. Hence i cannot subclass it ? Is that right ?

I then tried to simply add the method to os (see below). While this compiles and work correctly, the method doesnt show up in my vscode autocomplete/intellisense.

Ps. If this is indeed 'monkey patching', then please point it out as i will avoid. But generally i like to organise functions in relevant groups. So in my example below id like to add a method to os related code that i reuse often.

Thanks for your input in advance.

import os
def myfunc(): print('function works')
os.myfunc = myfunc()
os.myfunc()            # Works but doesn't autocomplete 

1

There are 1 answers

2
Benjamin Shapiro On

The code, as written, will throw a TypeError on line 4. I will assume you meant:

import os
def myfunc(): print('function works')
os.myfunc = myfunc # no invocation here
os.myfunc()   

Based on this thread, this is monkeypatching. Modules are objects in python, and thus they behave like objects when assigning to their attributes.

I believe the vscode python extension uses the pylance language server to provide the editor hints and syntax/semantic highlighting. The pylance team actually explicitly rejected the idea of providing auto-completion and hints for such scenarios by default. The listed ways to bypass this effectively involve telling the language server either to explicitly ignore the error or that you explicitly want it to ignore the introspected definition it derived and instead use your custom one. Both of these, in my eyes, defeat the purpose of a language server providing development support.

I can only think of a few situations where this is (more or less) an accepted practice in python. One of them is mocking an external service for pytest unit tests. Another one (maybe) is sanitizing some unsafe module/class after it is known a method has malicious code, for instance if your app deals with potentially unsafe user-submitted code or a pickled object, etc. The common factor between these two cases is that in both, one would monkeypatch to get around intended functionality. This is definitely a bad idea for a vast majority of potential usecases, especially if the monkeypatched object is as central and important as the os module.

EDIT:

If you are interested, you can actually see a usage of module-level monkeypatching in the pytest documentation.