1# -*- coding: utf-8 -*- #
2# Copyright 2021 Google LLC. All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#    http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15"""Utilities for local mode."""
16
17from __future__ import absolute_import
18from __future__ import division
19from __future__ import unicode_literals
20
21import io
22import os
23import subprocess
24import sys
25
26from googlecloudsdk.core.util import files
27
28
29def ExecuteCommand(cmd, input_str=None, file=None):
30  """Executes shell commands in subprocess.
31
32  Executes the supplied command with the supplied standard input string, streams
33  the output to stdout, and returns the process's return code.
34
35  Args:
36    cmd: (List[str]) Strings to send in as the command.
37    input_str: (str) if supplied, it will be passed as stdin to the supplied
38      command. if None, stdin will get closed immediately.
39    file: optional file-like object (stream), the output from the executed
40      process's stdout will get sent to this stream. Defaults to sys.stdout.
41
42  Returns:
43    return code of the process
44  """
45  if file is None:
46    file = sys.stdout
47
48  with subprocess.Popen(
49      cmd,
50      stdin=subprocess.PIPE,
51      stdout=subprocess.PIPE,
52      stderr=subprocess.STDOUT,
53      universal_newlines=False,
54      bufsize=1) as p:
55    if input_str:
56      p.stdin.write(input_str.encode('utf-8'))
57    p.stdin.close()
58
59    out = io.TextIOWrapper(p.stdout, newline='')
60
61    for line in out:
62      file.write(line)
63      file.flush()
64    else:
65      # Flush to force the contents to display.
66      file.flush()
67
68  return p.returncode
69
70
71def ModuleToPath(module_name):
72  """Converts the supplied python module into corresponding python file.
73
74  Args:
75    module_name: (str) A python module name (separated by dots)
76
77  Returns:
78    A string representing a python file path.
79  """
80  return module_name.replace('.', os.path.sep) + '.py'
81
82
83def ClearPyCache(root_dir=None):
84  """Removes generic `__pycache__` folder and  '*.pyc' '*.pyo' files."""
85  root_dir = root_dir or files.GetCWD()
86
87  is_cleaned = False
88  for name in os.listdir(root_dir):
89    item = os.path.join(root_dir, name)
90    if os.path.isdir(item):
91      if name == '__pycache__':
92        files.RmTree(item)
93        is_cleaned = True
94    else:
95      _, ext = os.path.splitext(name)
96      if ext in ['.pyc', '.pyo']:
97        os.remove(item)
98        is_cleaned = True
99
100  return is_cleaned
101