0

I'm working with a file system mounted on linux where cp -a always fails as not permitted. Is there a way to disable shutil.copystat and shutil.copymode in Python?

I have the below workaround but it's a bit ridiculous.

import shutil
def nothin(*args, **kwargs):
    return


shutil.copymode = nothin
shutil.copystat = nothin
martineau
  • 119,623
  • 25
  • 170
  • 301
Carbon
  • 3,828
  • 3
  • 24
  • 51

1 Answers1

0

Function overriding is a usual practice for python (at least for Django Rest Framework for example).

But! the main problem in your code is the scope. When you overriding module function, the new function will be used in all other parts of the code.

See this example:

import shutil

print('first try')

try:
  print(shutil.copymode("a", "b"))
except Exception as e:
  print(e)

shutil.copymode = lambda x,y: x + y

print('second try')

print(shutil.copymode("a", "b"))

import shutil

print('third try after re-import')

try:
  print(shutil.copymode("a", "b"))
except Exception as e:
  print(e)
first try
[Errno 2] No such file or directory: 'a'
second try
ab
third try after re-import
ab

shutil already has modified copymode function even if it is re-imported. And that may be super painful for someone who will try to use shutil for this code in future.

So I recommend to import shutil as separated copy object. So changes will be affected only for one current file (thanks to this article):

import importlib.util
import sys
SPEC_OS = importlib.util.find_spec('shutil')
custom_shutil = importlib.util.module_from_spec(SPEC_OS)
SPEC_OS.loader.exec_module(custom_shutil)
sys.modules['custom_shutil'] = custom_shutil

custom_shutil.copymode = lambda x, y: x + y

# or
# setattr(custom_shutil, 'copymode', lambda x, y: x + y)

print('first try')

print(custom_shutil.copymode("a", "b"))

import shutil

print('second try')

try:
  print(shutil.copymode("a", "b"))
except Exception as e:
  print(e)
first try
ab
second try
[Errno 2] No such file or directory: 'a'

However copymode not just check for a copy mode but also check if file exists. Skipping of this checks may cause unexpected behaviour in future.

rzlvmp
  • 7,512
  • 5
  • 16
  • 45
  • Ooooh, that's a really good point about checking if the file exists. Will need to replicate that behavior. And am trying to break it all throughout code, not just for one file. – Carbon Jan 11 '22 at 14:35