xref: /aosp_15_r20/external/yapf/yapftests/utils.py (revision 7249d1a64f4850ccf838e62a46276f891f72998e)
1*7249d1a6SKrzysztof Kosiński# -*- coding: utf-8 -*-
2*7249d1a6SKrzysztof Kosiński# Copyright 2017 Google Inc. All Rights Reserved.
3*7249d1a6SKrzysztof Kosiński#
4*7249d1a6SKrzysztof Kosiński# Licensed under the Apache License, Version 2.0 (the "License");
5*7249d1a6SKrzysztof Kosiński# you may not use this file except in compliance with the License.
6*7249d1a6SKrzysztof Kosiński# You may obtain a copy of the License at
7*7249d1a6SKrzysztof Kosiński#
8*7249d1a6SKrzysztof Kosiński#     http://www.apache.org/licenses/LICENSE-2.0
9*7249d1a6SKrzysztof Kosiński#
10*7249d1a6SKrzysztof Kosiński# Unless required by applicable law or agreed to in writing, software
11*7249d1a6SKrzysztof Kosiński# distributed under the License is distributed on an "AS IS" BASIS,
12*7249d1a6SKrzysztof Kosiński# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*7249d1a6SKrzysztof Kosiński# See the License for the specific language governing permissions and
14*7249d1a6SKrzysztof Kosiński# limitations under the License.
15*7249d1a6SKrzysztof Kosiński"""Utilities for tests."""
16*7249d1a6SKrzysztof Kosiński
17*7249d1a6SKrzysztof Kosińskiimport contextlib
18*7249d1a6SKrzysztof Kosińskiimport io
19*7249d1a6SKrzysztof Kosińskiimport os
20*7249d1a6SKrzysztof Kosińskiimport sys
21*7249d1a6SKrzysztof Kosińskiimport tempfile
22*7249d1a6SKrzysztof Kosiński
23*7249d1a6SKrzysztof Kosiński
24*7249d1a6SKrzysztof Kosiński@contextlib.contextmanager
25*7249d1a6SKrzysztof Kosińskidef stdout_redirector(stream):  # pylint: disable=invalid-name
26*7249d1a6SKrzysztof Kosiński  old_stdout = sys.stdout
27*7249d1a6SKrzysztof Kosiński  sys.stdout = stream
28*7249d1a6SKrzysztof Kosiński  try:
29*7249d1a6SKrzysztof Kosiński    yield
30*7249d1a6SKrzysztof Kosiński  finally:
31*7249d1a6SKrzysztof Kosiński    sys.stdout = old_stdout
32*7249d1a6SKrzysztof Kosiński
33*7249d1a6SKrzysztof Kosiński
34*7249d1a6SKrzysztof Kosiński# NamedTemporaryFile is useless because on Windows the temporary file would be
35*7249d1a6SKrzysztof Kosiński# created with O_TEMPORARY, which would not allow the file to be opened a
36*7249d1a6SKrzysztof Kosiński# second time, even by the same process, unless the same flag is used.
37*7249d1a6SKrzysztof Kosiński# Thus we provide a simplified version ourselves.
38*7249d1a6SKrzysztof Kosiński#
39*7249d1a6SKrzysztof Kosiński# Note: returns a tuple of (io.file_obj, file_path), instead of a file_obj with
40*7249d1a6SKrzysztof Kosiński# a .name attribute
41*7249d1a6SKrzysztof Kosiński#
42*7249d1a6SKrzysztof Kosiński# Note: `buffering` is set to -1 despite documentation of NamedTemporaryFile
43*7249d1a6SKrzysztof Kosiński# says None. This is probably a problem with the python documentation.
44*7249d1a6SKrzysztof Kosiński@contextlib.contextmanager
45*7249d1a6SKrzysztof Kosińskidef NamedTempFile(mode='w+b',
46*7249d1a6SKrzysztof Kosiński                  buffering=-1,
47*7249d1a6SKrzysztof Kosiński                  encoding=None,
48*7249d1a6SKrzysztof Kosiński                  errors=None,
49*7249d1a6SKrzysztof Kosiński                  newline=None,
50*7249d1a6SKrzysztof Kosiński                  suffix=None,
51*7249d1a6SKrzysztof Kosiński                  prefix=None,
52*7249d1a6SKrzysztof Kosiński                  dirname=None,
53*7249d1a6SKrzysztof Kosiński                  text=False):
54*7249d1a6SKrzysztof Kosiński  """Context manager creating a new temporary file in text mode."""
55*7249d1a6SKrzysztof Kosiński  if sys.version_info < (3, 5):  # covers also python 2
56*7249d1a6SKrzysztof Kosiński    if suffix is None:
57*7249d1a6SKrzysztof Kosiński      suffix = ''
58*7249d1a6SKrzysztof Kosiński    if prefix is None:
59*7249d1a6SKrzysztof Kosiński      prefix = 'tmp'
60*7249d1a6SKrzysztof Kosiński  (fd, fname) = tempfile.mkstemp(
61*7249d1a6SKrzysztof Kosiński      suffix=suffix, prefix=prefix, dir=dirname, text=text)
62*7249d1a6SKrzysztof Kosiński  f = io.open(
63*7249d1a6SKrzysztof Kosiński      fd,
64*7249d1a6SKrzysztof Kosiński      mode=mode,
65*7249d1a6SKrzysztof Kosiński      buffering=buffering,
66*7249d1a6SKrzysztof Kosiński      encoding=encoding,
67*7249d1a6SKrzysztof Kosiński      errors=errors,
68*7249d1a6SKrzysztof Kosiński      newline=newline)
69*7249d1a6SKrzysztof Kosiński  yield f, fname
70*7249d1a6SKrzysztof Kosiński  f.close()
71*7249d1a6SKrzysztof Kosiński  os.remove(fname)
72*7249d1a6SKrzysztof Kosiński
73*7249d1a6SKrzysztof Kosiński
74*7249d1a6SKrzysztof Kosiński@contextlib.contextmanager
75*7249d1a6SKrzysztof Kosińskidef TempFileContents(dirname,
76*7249d1a6SKrzysztof Kosiński                     contents,
77*7249d1a6SKrzysztof Kosiński                     encoding='utf-8',
78*7249d1a6SKrzysztof Kosiński                     newline='',
79*7249d1a6SKrzysztof Kosiński                     suffix=None):
80*7249d1a6SKrzysztof Kosiński  # Note: NamedTempFile properly handles unicode encoding when using mode='w'
81*7249d1a6SKrzysztof Kosiński  with NamedTempFile(
82*7249d1a6SKrzysztof Kosiński      dirname=dirname,
83*7249d1a6SKrzysztof Kosiński      mode='w',
84*7249d1a6SKrzysztof Kosiński      encoding=encoding,
85*7249d1a6SKrzysztof Kosiński      newline=newline,
86*7249d1a6SKrzysztof Kosiński      suffix=suffix) as (f, fname):
87*7249d1a6SKrzysztof Kosiński    f.write(contents)
88*7249d1a6SKrzysztof Kosiński    f.flush()
89*7249d1a6SKrzysztof Kosiński    yield fname
90