Skip to content

Commit 35d9519

Browse files
committed
Fix issues related to tempfile on Windows
1 parent 58e1d8e commit 35d9519

File tree

9 files changed

+68
-42
lines changed

9 files changed

+68
-42
lines changed

tests/agent_features/test_agent_control_health_check.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414
import re
15+
import sys
1516
import threading
1617
import time
1718
from pathlib import Path
1819

1920
import pytest
20-
import sys
2121
from testing_support.fixtures import initialize_agent
2222
from testing_support.http_client_recorder import HttpClientRecorder
2323

tests/agent_features/test_configuration.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@
1717
import logging
1818
import pathlib
1919
import sys
20-
import tempfile
2120
import urllib.parse as urlparse
2221

2322
import pytest
2423
from testing_support.fixtures import override_generic_settings
24+
from testing_support.util import NamedTemporaryFile
2525

2626
from newrelic.api.exceptions import ConfigurationError
2727
from newrelic.common.object_names import callable_name
@@ -637,7 +637,7 @@ def test_initialize():
637637
def test_initialize_raises_if_config_does_not_match_previous():
638638
error_message = "Configuration has already been done against differing configuration file or environment.*"
639639
with pytest.raises(ConfigurationError, match=error_message):
640-
with tempfile.NamedTemporaryFile() as f:
640+
with NamedTemporaryFile() as f:
641641
f.write(newrelic_ini_contents)
642642
f.seek(0)
643643

@@ -646,7 +646,7 @@ def test_initialize_raises_if_config_does_not_match_previous():
646646

647647
def test_initialize_via_config_file():
648648
_reset_configuration_done()
649-
with tempfile.NamedTemporaryFile() as f:
649+
with NamedTemporaryFile() as f:
650650
f.write(newrelic_ini_contents)
651651
f.seek(0)
652652

@@ -667,7 +667,7 @@ def test_initialize_config_file_does_not_exist():
667667

668668
def test_initialize_environment():
669669
_reset_configuration_done()
670-
with tempfile.NamedTemporaryFile() as f:
670+
with NamedTemporaryFile() as f:
671671
f.write(newrelic_ini_contents)
672672
f.seek(0)
673673

@@ -676,7 +676,7 @@ def test_initialize_environment():
676676

677677
def test_initialize_log_level():
678678
_reset_configuration_done()
679-
with tempfile.NamedTemporaryFile() as f:
679+
with NamedTemporaryFile() as f:
680680
f.write(newrelic_ini_contents)
681681
f.seek(0)
682682

@@ -685,7 +685,7 @@ def test_initialize_log_level():
685685

686686
def test_initialize_log_file():
687687
_reset_configuration_done()
688-
with tempfile.NamedTemporaryFile() as f:
688+
with NamedTemporaryFile() as f:
689689
f.write(newrelic_ini_contents)
690690
f.seek(0)
691691

@@ -700,7 +700,7 @@ def test_initialize_config_file_feature_flag(feature_flag, expect_warning, logge
700700
apply_config_setting(settings, "feature_flag", feature_flag)
701701
_reset_configuration_done()
702702

703-
with tempfile.NamedTemporaryFile() as f:
703+
with NamedTemporaryFile() as f:
704704
f.write(newrelic_ini_contents)
705705
f.seek(0)
706706

@@ -759,7 +759,7 @@ def test_initialize_config_file_with_traces(setting_name, setting_value, expect_
759759
apply_config_setting(settings, setting_name, setting_value)
760760
_reset_configuration_done()
761761

762-
with tempfile.NamedTemporaryFile() as f:
762+
with NamedTemporaryFile() as f:
763763
f.write(newrelic_ini_contents)
764764
f.seek(0)
765765

@@ -951,7 +951,7 @@ def test_initialize_developer_mode(section, expect_error, logger):
951951
_reset_instrumentation_done()
952952
_reset_config_parser()
953953

954-
with tempfile.NamedTemporaryFile() as f:
954+
with NamedTemporaryFile() as f:
955955
f.write(newrelic_ini_contents)
956956
f.write(section)
957957
f.seek(0)
@@ -1019,7 +1019,7 @@ def test_toml_parse_development():
10191019
_reset_config_parser()
10201020
_reset_instrumentation_done()
10211021

1022-
with tempfile.NamedTemporaryFile(suffix=".toml") as f:
1022+
with NamedTemporaryFile(suffix=".toml") as f:
10231023
f.write(newrelic_toml_contents)
10241024
f.seek(0)
10251025

@@ -1041,7 +1041,7 @@ def test_toml_parse_production():
10411041
_reset_config_parser()
10421042
_reset_instrumentation_done()
10431043

1044-
with tempfile.NamedTemporaryFile(suffix=".toml") as f:
1044+
with NamedTemporaryFile(suffix=".toml") as f:
10451045
f.write(newrelic_toml_contents)
10461046
f.seek(0)
10471047

@@ -1061,7 +1061,7 @@ def test_config_file_path_types_ini(pathtype):
10611061
_reset_config_parser()
10621062
_reset_instrumentation_done()
10631063

1064-
with tempfile.NamedTemporaryFile(suffix=".ini") as f:
1064+
with NamedTemporaryFile(suffix=".ini") as f:
10651065
f.write(newrelic_ini_contents)
10661066
f.seek(0)
10671067

@@ -1081,7 +1081,7 @@ def test_config_file_path_types_toml(pathtype):
10811081
_reset_config_parser()
10821082
_reset_instrumentation_done()
10831083

1084-
with tempfile.NamedTemporaryFile(suffix=".toml") as f:
1084+
with NamedTemporaryFile(suffix=".toml") as f:
10851085
f.write(newrelic_toml_contents)
10861086
f.seek(0)
10871087

tests/agent_unittests/conftest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@
1313
# limitations under the License.
1414

1515
import sys
16-
import tempfile
1716
from importlib import reload
1817

1918
import pytest
2019
from testing_support.fixtures import collector_agent_registration_fixture, collector_available_fixture
2120
from testing_support.fixtures import newrelic_caplog as caplog
21+
from testing_support.util import NamedTemporaryFile
2222

2323
from newrelic.core.agent import agent_instance
2424

@@ -72,7 +72,7 @@ def global_settings(request, monkeypatch):
7272
reload(core_config)
7373
reload(config)
7474

75-
with tempfile.NamedTemporaryFile() as ini_file:
75+
with NamedTemporaryFile() as ini_file:
7676
ini_file.write(ini_contents)
7777
ini_file.seek(0)
7878

tests/agent_unittests/test_agent_protocol.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,8 @@ def test_audit_logging():
522522
protocol = AgentProtocol(settings, client_cls=HttpClientRecorder)
523523
protocol.send("preconnect")
524524

525-
with Path(f.name).open() as f:
525+
audit_log_path = Path(f.name)
526+
with audit_log_path.open() as f:
526527
audit_log_contents = f.read()
527528

528529
assert audit_log_contents.startswith("*\n")

tests/agent_unittests/test_utilization_settings.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,11 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
import os
16-
import tempfile
1715
from importlib import reload
1816

1917
import pytest
2018
from testing_support.fixtures import Environ
19+
from testing_support.util import NamedTemporaryFile
2120

2221
# these will be reloaded for each test
2322
import newrelic.config
@@ -73,8 +72,7 @@
7372
def reset_agent_config(ini_contents, env_dict):
7473
@function_wrapper
7574
def reset(wrapped, instance, args, kwargs):
76-
with Environ(env_dict):
77-
ini_file = tempfile.NamedTemporaryFile()
75+
with Environ(env_dict), NamedTemporaryFile() as ini_file:
7876
ini_file.write(ini_contents)
7977
ini_file.seek(0)
8078

tests/cross_agent/test_boot_id_utilization_data.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@
1414

1515
import json
1616
import sys
17-
import tempfile
1817
from pathlib import Path
1918

2019
import pytest
20+
from testing_support.util import NamedTemporaryFile
2121
from testing_support.validators.validate_internal_metrics import validate_internal_metrics
2222

2323
from newrelic.common.system_info import BootIdUtilization
@@ -57,7 +57,7 @@ def __init__(self, boot_id):
5757

5858
def __enter__(self):
5959
if self.boot_id is not None:
60-
self.boot_id_file = tempfile.NamedTemporaryFile()
60+
self.boot_id_file = NamedTemporaryFile().__enter__()
6161
self.boot_id_file.write(self.boot_id.encode("utf8"))
6262
self.boot_id_file.seek(0)
6363
BootIdUtilization.METADATA_URL = self.boot_id_file.name
@@ -68,7 +68,7 @@ def __enter__(self):
6868
def __exit__(self, *args, **kwargs):
6969
sys.platform = SYS_PLATFORM
7070
if self.boot_id:
71-
del self.boot_id_file # close and thus delete the tempfile
71+
self.boot_id_file.__exit__(*args, **kwargs) # close and thus delete the tempfile
7272

7373

7474
@pytest.mark.parametrize(_parameters, _boot_id_tests)

tests/cross_agent/test_collector_hostname.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@
1616
import multiprocessing
1717
import os
1818
import sys
19-
import tempfile
2019
from importlib import reload
2120
from pathlib import Path
2221

2322
import pytest
23+
from testing_support.util import NamedTemporaryFile
2424

2525
FIXTURE = Path(__file__).parent / "fixtures" / "collector_hostname.json"
2626

@@ -70,11 +70,12 @@ def _test_collector_hostname(
7070
reload(core_config)
7171
reload(config)
7272

73-
ini_file = tempfile.NamedTemporaryFile()
74-
ini_file.write(ini_contents.encode("utf-8"))
75-
ini_file.seek(0)
73+
with NamedTemporaryFile() as ini_file:
74+
ini_file.write(ini_contents.encode("utf-8"))
75+
ini_file.seek(0)
76+
77+
config.initialize(ini_file.name)
7678

77-
config.initialize(ini_file.name)
7879
settings = core_config.global_settings()
7980
assert settings.host == hostname
8081

tests/cross_agent/test_utilization_configs.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
import json
1616
import os
1717
import sys
18-
import tempfile
1918
from importlib import reload
2019
from pathlib import Path
2120

@@ -24,6 +23,7 @@
2423
# NOTE: the test_utilization_settings_from_env_vars test mocks several of the
2524
# methods in newrelic.core.data_collector and does not put them back!
2625
from testing_support.mock_http_client import create_client_cls
26+
from testing_support.util import NamedTemporaryFile
2727

2828
import newrelic.core.config
2929
from newrelic.common.object_wrapper import function_wrapper
@@ -132,19 +132,19 @@ def _patch_boot_id_file(wrapped, instance, args, kwargs):
132132
boot_id_file = None
133133
initial_sys_platform = sys.platform
134134

135-
if test.get("input_boot_id"):
136-
boot_id_file = tempfile.NamedTemporaryFile()
137-
boot_id_file.write(test.get("input_boot_id"))
138-
boot_id_file.seek(0)
139-
BootIdUtilization.METADATA_URL = boot_id_file.name
140-
sys.platform = "linux-mock-testing" # ensure boot_id is gathered
141-
else:
142-
# do not gather boot_id at all, this will ensure there is nothing
143-
# extra in the gathered utilizations data
144-
sys.platform = "not-linux"
145-
146135
try:
147-
return wrapped(*args, **kwargs)
136+
if test.get("input_boot_id"):
137+
with NamedTemporaryFile() as boot_id_file:
138+
boot_id_file.write(test.get("input_boot_id"))
139+
boot_id_file.seek(0)
140+
BootIdUtilization.METADATA_URL = boot_id_file.name
141+
sys.platform = "linux-mock-testing" # ensure boot_id is gathered
142+
return wrapped(*args, **kwargs)
143+
else:
144+
# do not gather boot_id at all, this will ensure there is nothing
145+
# extra in the gathered utilizations data
146+
sys.platform = "not-linux"
147+
return wrapped(*args, **kwargs)
148148
finally:
149149
del boot_id_file # close and thus delete the tempfile
150150
sys.platform = initial_sys_platform

tests/testing_support/util.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,11 @@
1414

1515
import re
1616
import socket
17+
import sys
18+
import tempfile
1719
import time
1820
from functools import wraps
21+
from pathlib import Path
1922

2023

2124
def _to_int(version_str):
@@ -83,3 +86,26 @@ def wrapper(*args, **kwargs):
8386
return wrapper
8487

8588
return decorator
89+
90+
91+
def NamedTemporaryFile(*args, **kwargs):
92+
"""A wrapper around tempfile.NamedTemporaryFile that fixes issues with file flags on Windows."""
93+
if sys.platform == "win32":
94+
# Set delete=False to prevent file flags being set incorrectly on Windows.
95+
kwargs["delete"] = False
96+
97+
# Create the temporary file
98+
temp_file = tempfile.NamedTemporaryFile(*args, **kwargs)
99+
temp_file.path = Path(temp_file.name) # Add path attribute for convenience
100+
101+
# Patch the __exit__ method to manually remove the file on exit
102+
original_exit = temp_file.__exit__
103+
104+
def remove_on_exit(*args, **kwargs):
105+
original_exit(*args, **kwargs)
106+
# Clean up the file manually
107+
temp_file.path.unlink(missing_ok=True)
108+
109+
temp_file.__exit__ = remove_on_exit
110+
111+
return temp_file

0 commit comments

Comments
 (0)