I am getting a different result for a file in os.path.abspath()
when it is run in a unit test versus when it is run in the code being tested:
The code I am testing contains:
abspath = os.path.abspath(filepath)
My test for the code copies the file into the test directory and executes the code
self.test_data = os.path.dirname(test_data.__file__)
self.test_dir = tempfile.mkdtemp(prefix="test_")
shutil.copy(
os.path.join(self.test_data, "thefile.txt"),
os.path.join(self.test_dir, "thefile.txt"),
)
When the test is executed it fails. The code being tested produces this as the path for the test file:
/private/var/folders/1w/k19bxrj1463_4j5m8xv6_6cc0000gp/T/test_z66pgwj_/thefile.txt
but the test expects the path to be:
/var/folders/1w/k19bxrj1463_4j5m8xv6_6cc0000gp/T/test_z66pgwj_/thefile.txt
When I run os.path.abspath(os.path.join(self.test_dir, thefile.txt))
in the test it returns the same path without /private
prepended.
I am using python 3.9.13 running on MacOS Monterey 12.6.2
EDIT: I have solved the issue, but the solution makes no sense to me:
os.path.abspath(os.path.join(self.test_dir, "thefile.txt"))
returns:
/var/folders/1w/k19bxrj1463_4j5m8xv6_6cc0000gp/T/test_z66pgwj_/thefile.txt
os.path.abspath("thefile.txt)
returns:
/private/var/folders/1w/k19bxrj1463_4j5m8xv6_6cc0000gp/T/test_z66pgwj_/thefile.txt
os.path.abspath()
works with paths as common strings, it doesn't even check for path to exist. And /var/
and /tmp/
are symlinks on macOS:
% ls -lh /tmp /var
lrwxr-xr-x 1 root wheel 11 Jan 11 11:03 /tmp -> private/tmp
lrwxr-xr-x 1 root wheel 11 Jan 11 11:03 /var -> private/var
Therefore there's a bunch of tools returning unexpected (at first glance) results:
% cd /tmp && touch "file.txt" && readlink -f file.txt
/private/tmp/file.txt
os.path.abspath(path)
checks if path
starts with /
. If not, it calls os.getcwd()
to get current dir, which on macOS returns the one with /private
prefix. If path
starts with /
, os.getcwd()
isn't called, and abspath()
proceeds to normalize path string.