xref: /aosp_15_r20/external/autotest/client/common_lib/autotemp.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1*9c5db199SXin Li"""
2*9c5db199SXin LiAutotest tempfile wrapper for mkstemp (known as tempfile here) and
3*9c5db199SXin Limkdtemp (known as tempdir).
4*9c5db199SXin Li
5*9c5db199SXin LiThis wrapper provides a mechanism to clean up temporary files/dirs once they
6*9c5db199SXin Liare no longer need.
7*9c5db199SXin Li
8*9c5db199SXin LiFiles/Dirs will have a unique_id prepended to the suffix and a
9*9c5db199SXin Li_autotmp_ tag appended to the prefix.
10*9c5db199SXin Li
11*9c5db199SXin LiIt is required that the unique_id param is supplied when a temp dir/file is
12*9c5db199SXin Licreated.
13*9c5db199SXin Li"""
14*9c5db199SXin Li
15*9c5db199SXin Liimport shutil, os, logging
16*9c5db199SXin Liimport tempfile as module_tempfile
17*9c5db199SXin Li
18*9c5db199SXin Li_TEMPLATE = '_autotmp_'
19*9c5db199SXin Li
20*9c5db199SXin Li
21*9c5db199SXin Liclass tempfile(object):
22*9c5db199SXin Li    """
23*9c5db199SXin Li    A wrapper for tempfile.mkstemp
24*9c5db199SXin Li
25*9c5db199SXin Li    @param unique_id: required, a unique string to help identify what
26*9c5db199SXin Li                      part of code created the tempfile.
27*9c5db199SXin Li    @param auto_clean: automatically delete the temporary file in destructor.
28*9c5db199SXin Li    @var name: The name of the temporary file.
29*9c5db199SXin Li    @var fd:  the file descriptor of the temporary file that was created.
30*9c5db199SXin Li    @return a tempfile object
31*9c5db199SXin Li    example usage:
32*9c5db199SXin Li        t = autotemp.tempfile(unique_id='fig')
33*9c5db199SXin Li        t.name # name of file
34*9c5db199SXin Li        t.fd   # file descriptor
35*9c5db199SXin Li        t.fo   # file object
36*9c5db199SXin Li        t.clean() # clean up after yourself
37*9c5db199SXin Li    """
38*9c5db199SXin Li    def __init__(self, unique_id, suffix='', prefix='', dir=None,
39*9c5db199SXin Li                 text=False, auto_clean=True):
40*9c5db199SXin Li        self.auto_clean = auto_clean
41*9c5db199SXin Li        suffix = unique_id + suffix
42*9c5db199SXin Li        prefix = prefix + _TEMPLATE
43*9c5db199SXin Li        self.fd, self.name = module_tempfile.mkstemp(suffix=suffix,
44*9c5db199SXin Li                                                     prefix=prefix,
45*9c5db199SXin Li                                                     dir=dir, text=text)
46*9c5db199SXin Li        self.fo = os.fdopen(self.fd)
47*9c5db199SXin Li
48*9c5db199SXin Li
49*9c5db199SXin Li    def clean(self):
50*9c5db199SXin Li        """
51*9c5db199SXin Li        Remove the temporary file that was created.
52*9c5db199SXin Li        This is also called by the destructor.
53*9c5db199SXin Li        """
54*9c5db199SXin Li        if self.fo:
55*9c5db199SXin Li            self.fo.close()
56*9c5db199SXin Li        if self.name and os.path.exists(self.name):
57*9c5db199SXin Li            os.remove(self.name)
58*9c5db199SXin Li
59*9c5db199SXin Li        self.fd = self.fo = self.name = None
60*9c5db199SXin Li
61*9c5db199SXin Li
62*9c5db199SXin Li    def __del__(self):
63*9c5db199SXin Li        try:
64*9c5db199SXin Li            if self.name is not None and self.auto_clean:
65*9c5db199SXin Li                logging.debug('Auto-cleaning %s', self.name)
66*9c5db199SXin Li                self.clean()
67*9c5db199SXin Li        except:
68*9c5db199SXin Li            try:
69*9c5db199SXin Li                msg = 'An exception occurred while calling the destructor'
70*9c5db199SXin Li                logging.exception(msg)
71*9c5db199SXin Li            except:
72*9c5db199SXin Li                pass
73*9c5db199SXin Li
74*9c5db199SXin Li
75*9c5db199SXin Liclass tempdir(object):
76*9c5db199SXin Li    """
77*9c5db199SXin Li    A wrapper for tempfile.mkdtemp
78*9c5db199SXin Li
79*9c5db199SXin Li    @var name: The name of the temporary dir.
80*9c5db199SXin Li    @return A tempdir object
81*9c5db199SXin Li    example usage:
82*9c5db199SXin Li        b = autotemp.tempdir(unique_id='exemdir')
83*9c5db199SXin Li        b.name # your directory
84*9c5db199SXin Li        b.clean() # clean up after yourself
85*9c5db199SXin Li    """
86*9c5db199SXin Li    def __init__(self,  suffix='', unique_id='', prefix='', dir=None,
87*9c5db199SXin Li                 auto_clean=True):
88*9c5db199SXin Li        """
89*9c5db199SXin Li        Initialize temp directory.
90*9c5db199SXin Li
91*9c5db199SXin Li        @param suffix: suffix for dir.
92*9c5db199SXin Li        @param prefix: prefix for dir. Defaults to '_autotmp'.
93*9c5db199SXin Li        @param unique_id: unique id of tempdir.
94*9c5db199SXin Li        @param dir: parent directory of the tempdir. Defaults to /tmp.
95*9c5db199SXin Li        @param auto_clean: automatically clean up the tempdir in destructor.
96*9c5db199SXin Li
97*9c5db199SXin Li        eg: autotemp.tempdir(suffix='suffix', unique_id='123', prefix='prefix')
98*9c5db199SXin Li            creates a dir like '/tmp/prefix_autotmp_<random hash>123suffix'
99*9c5db199SXin Li        """
100*9c5db199SXin Li        self.auto_clean = auto_clean
101*9c5db199SXin Li        suffix = unique_id + suffix
102*9c5db199SXin Li        prefix = prefix + _TEMPLATE
103*9c5db199SXin Li        self.name = module_tempfile.mkdtemp(suffix=suffix,
104*9c5db199SXin Li                                            prefix=prefix, dir=dir)
105*9c5db199SXin Li
106*9c5db199SXin Li
107*9c5db199SXin Li    def clean(self):
108*9c5db199SXin Li        """
109*9c5db199SXin Li        Remove the temporary dir that was created.
110*9c5db199SXin Li        This is also called by the destructor.
111*9c5db199SXin Li        """
112*9c5db199SXin Li        if self.name and os.path.exists(self.name):
113*9c5db199SXin Li            shutil.rmtree(self.name)
114*9c5db199SXin Li
115*9c5db199SXin Li        self.name = None
116*9c5db199SXin Li
117*9c5db199SXin Li
118*9c5db199SXin Li    def __del__(self):
119*9c5db199SXin Li        try:
120*9c5db199SXin Li            if self.name and self.auto_clean:
121*9c5db199SXin Li                logging.debug('Auto-cleaning %s', self.name)
122*9c5db199SXin Li                self.clean()
123*9c5db199SXin Li        except:
124*9c5db199SXin Li            try:
125*9c5db199SXin Li                msg = 'An exception occurred while calling the destructor'
126*9c5db199SXin Li                logging.exception(msg)
127*9c5db199SXin Li            except:
128*9c5db199SXin Li                pass
129*9c5db199SXin Li
130*9c5db199SXin Li
131*9c5db199SXin Liclass stub_dir(object):
132*9c5db199SXin Li    """A stub object representing a directory with a name.
133*9c5db199SXin Li
134*9c5db199SXin Li    Only used for compat with the tmpdir, in cases where we wish to
135*9c5db199SXin Li    reuse a dir with the same interface but not to delete it after
136*9c5db199SXin Li    we're done using it.
137*9c5db199SXin Li    """
138*9c5db199SXin Li
139*9c5db199SXin Li    def __init__(self, name):
140*9c5db199SXin Li        """Initialize the stub_dir object.
141*9c5db199SXin Li
142*9c5db199SXin Li        @param name: Path the the directory.
143*9c5db199SXin Li        """
144*9c5db199SXin Li        self.name = name
145