Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A lot of unittests tests fail under Windows due to usage of NamedTemporaryFile #550

Open
Chary314 opened this issue Sep 7, 2020 · 4 comments

Comments

@Chary314
Copy link

Chary314 commented Sep 7, 2020

I noticed, that a lot of tests fail under Windows due to usage of NamedTemporaryFile.

e.g.

  File "C:\_code\py\2009 beancount fix\beancount\beancount\utils\text_utils_test.py", line 28, in test_fix_ampersand
    tidy_file = text_utils.entitize_ampersand(input_file.name)
  File "C:\_code\py\2009 beancount fix\beancount\beancount\utils\text_utils.py", line 51, in entitize_ampersand
    with open(filename) as infile:
PermissionError: [Errno 13] Permission denied: 'C:\\Users\\chary\\AppData\\Local\\Temp\\tmpgas9aode'

Most likely it is related to different functionality of NamedTemporaryFile under Linux and Windows
As described here, NamedTemporaryFile actually creates and opens the file for you. Unix allows you to open it second time, Windows (starting from NT) apparently not.

But I can see in the code, that the usage of NamedTemporaryFile in tests already opens the file, hence operational code does not work later (on Windows)

E.g.:
beancount/utils/text_utils_test.py

    def test_fix_ampersand(self):
        #Chary: Temporary file with the name input_file is created and open here 
        with tempfile.NamedTemporaryFile('w') as input_file:  
            input_file.write('S&P 500. Some other thing and &entity;')
            input_file.flush()
            # Chary: The name of the temporary file is then gets passed to operational code, whilst the file itself is still open
            # one can try to do a input_file.close() here, but this is not the solution, 
            # as NamedTemporaryFile functionality is that file gets deleted immediately on closure 
            tidy_file = text_utils.entitize_ampersand(input_file.name) 

and then in operational code
beancount/utils/text_utils.py

def entitize_ampersand(filename):
   """    
    Chary: some code removed here
   """
    # Chary: an attempt to open file again is done here, in operational code. This attempt fails on Windows 
    with open(filename) as infile: 

Apparently it has been recognized, that it is difficult to write a cross-platform code with NamedTemporaryFile and there is an existing enhancement 14243 for python open since 2012

One of the possible googled solutions is not to use NamedTemporaryFile to open the file but only to generate candidate name as described here.

This will require however to manually take care of deleting file afterwards, which is in the current code a job of a context manager

@josephw
Copy link
Contributor

josephw commented Oct 5, 2020

For that specific failure, this commit suggests removing that method entirely. In most other cases, this suggestion to use:

tmpf = NamedTemporaryFile(delete=False)
...
tmpf.close()
os.unlink(tmpf.name)

is probably the least impactful targeted workaround.

@Chary314
Copy link
Author

Chary314 commented Oct 5, 2020

There is also now an open PR (python/cpython#22431) to have this python issue 14243 solved in the python tempfile library directly

@blais
Copy link
Member

blais commented Oct 11, 2020 via email

@Ev2geny
Copy link
Contributor

Ev2geny commented Feb 27, 2024

I think this is a duplicate issue for the previously created one #222

Any way, in python 3.12 there is now new functionality, which allows to re-write the tests in a way that they will work on Windows as well:

The tempfile.NamedTemporaryFile function has a new optional parameter delete_on_close ( gh-58451)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants