diff --git a/tryton/CHANGELOG b/tryton/CHANGELOG index 631943eada..35ec091370 100644 --- a/tryton/CHANGELOG +++ b/tryton/CHANGELOG @@ -1,3 +1,4 @@ +* Clean temporary files and directories at exit Version 7.0.0 - 2023-10-30 -------------------------- diff --git a/tryton/tryton/common/common.py b/tryton/tryton/common/common.py index 1fcb9d4576..c8f27d18ea 100644 --- a/tryton/tryton/common/common.py +++ b/tryton/tryton/common/common.py @@ -9,7 +9,6 @@ import os import platform import re import subprocess -import tempfile import unicodedata import xml.etree.ElementTree as ET from collections import defaultdict @@ -50,6 +49,7 @@ from tryton import __version__ from tryton.exceptions import TrytonError, TrytonServerError from tryton.pyson import PYSONEncoder +from . import tempfile from .underline import set_underline from .widget_style import widget_class diff --git a/tryton/tryton/common/tempfile.py b/tryton/tryton/common/tempfile.py new file mode 100644 index 0000000000..242a27c979 --- /dev/null +++ b/tryton/tryton/common/tempfile.py @@ -0,0 +1,34 @@ +# This file is part of Tryton. The COPYRIGHT file at the top level of +# this repository contains the full copyright notices and license terms. +import atexit +import os +import shutil +import tempfile + +_files, _directories = [], [] + + +def mkstemp(*args, **kwargs): + fileno, fname = tempfile.mkstemp(*args, **kwargs) + _files.append(fname) + return fileno, fname + + +def mkdtemp(*args, **kwargs): + dname = tempfile.mkdtemp(*args, **kwargs) + _directories.append(dname) + return dname + + +@atexit.register +def clean(): + for fname in _files: + try: + os.remove(fname) + except FileNotFoundError: + pass + _files.clear() + + for dname in _directories: + shutil.rmtree(dname, ignore_errors=True) + _directories.clear() diff --git a/tryton/tryton/config.py b/tryton/tryton/config.py index 03e42a9bcc..c7a1b2664f 100644 --- a/tryton/tryton/config.py +++ b/tryton/tryton/config.py @@ -8,7 +8,7 @@ import optparse import os import shutil import sys -import tempfile +from tempfile import NamedTemporaryFile from gi.repository import GdkPixbuf @@ -185,7 +185,7 @@ class ConfigManager(object): parser.read([self.rcfile]) except configparser.Error: config_dir = os.path.dirname(self.rcfile) - with tempfile.NamedTemporaryFile( + with NamedTemporaryFile( delete=False, prefix='tryton_', suffix='.conf', dir=config_dir) as temp_file: temp_name = temp_file.name diff --git a/tryton/tryton/gui/window/dblogin.py b/tryton/tryton/gui/window/dblogin.py index 0b8b62e0c0..186b3db92a 100644 --- a/tryton/tryton/gui/window/dblogin.py +++ b/tryton/tryton/gui/window/dblogin.py @@ -7,8 +7,8 @@ import logging import os import re import shutil -import tempfile import threading +from tempfile import NamedTemporaryFile from gi.repository import GLib, GObject, Gtk @@ -501,7 +501,7 @@ class DBLogin(object): # reset self.profiles as parsing errors may leave wrong data in # the parser self.profiles = configparser.ConfigParser() - with tempfile.NamedTemporaryFile( + with NamedTemporaryFile( delete=False, prefix='profiles_', suffix='.cfg', dir=config_dir) as temp_file: temp_name = temp_file.name diff --git a/tryton/tryton/gui/window/form.py b/tryton/tryton/gui/window/form.py index cbe2d08392..744d0ce43b 100644 --- a/tryton/tryton/gui/window/form.py +++ b/tryton/tryton/gui/window/form.py @@ -5,7 +5,6 @@ import csv import gettext import locale import os -import tempfile from itertools import zip_longest from gi.repository import Gdk, GLib, Gtk @@ -13,7 +12,7 @@ from gi.repository import Gdk, GLib, Gtk import tryton.common as common from tryton import plugins from tryton.action import Action -from tryton.common import RPCException, RPCExecute, sur, sur_3b +from tryton.common import RPCException, RPCExecute, sur, sur_3b, tempfile from tryton.common.common import selection as selection_ from tryton.common.popup_menu import popup from tryton.common.underline import set_underline diff --git a/tryton/tryton/gui/window/view_form/model/field.py b/tryton/tryton/gui/window/view_form/model/field.py index 7569b0f674..097c10facf 100644 --- a/tryton/tryton/gui/window/view_form/model/field.py +++ b/tryton/tryton/gui/window/view_form/model/field.py @@ -6,7 +6,6 @@ import locale import logging import math import os -import tempfile from decimal import Decimal from itertools import chain @@ -14,7 +13,8 @@ import tryton.common as common from tryton.common import ( EvalEnvironment, RPCException, RPCExecute, concat, domain_inversion, eval_domain, extract_reference_models, filter_leaf, inverse_leaf, - localize_domain, merge, prepare_reference_domain, simplify, unique_value) + localize_domain, merge, prepare_reference_domain, simplify, tempfile, + unique_value) from tryton.common.htmltextbuffer import guess_decode from tryton.config import CONFIG from tryton.pyson import PYSONDecoder diff --git a/tryton/tryton/gui/window/win_export.py b/tryton/tryton/gui/window/win_export.py index 68950b84f4..518ec1470d 100644 --- a/tryton/tryton/gui/window/win_export.py +++ b/tryton/tryton/gui/window/win_export.py @@ -7,7 +7,6 @@ import gettext import json import locale import os -import tempfile import urllib.parse from itertools import zip_longest from numbers import Number @@ -15,7 +14,7 @@ from numbers import Number from gi.repository import Gdk, GObject, Gtk import tryton.common as common -from tryton.common import RPCException, RPCExecute +from tryton.common import RPCException, RPCExecute, tempfile from tryton.config import CONFIG from tryton.gui.window.win_csv import WinCSV from tryton.jsonrpc import JSONEncoder