forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
python_utils.cc
135 lines (116 loc) · 4.13 KB
/
python_utils.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "net/test/python_utils.h"
#include <memory>
#include "base/base_paths.h"
#include "base/command_line.h"
#include "base/environment.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/process/launch.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#if defined(OS_MACOSX)
#include "base/mac/foundation_util.h"
#endif
const char kPythonPathEnv[] = "PYTHONPATH";
const char kPythonVirtualEnv[] = "VIRTUAL_ENV";
void ClearPythonPath() {
std::unique_ptr<base::Environment> env(base::Environment::Create());
env->UnSetVar(kPythonPathEnv);
}
void AppendToPythonPath(const base::FilePath& dir) {
std::unique_ptr<base::Environment> env(base::Environment::Create());
std::string old_path;
std::string dir_path;
#if defined(OS_WIN)
dir_path = base::WideToUTF8(dir.value());
#elif defined(OS_POSIX)
dir_path = dir.value();
#endif
if (!env->GetVar(kPythonPathEnv, &old_path)) {
env->SetVar(kPythonPathEnv, dir_path.c_str());
} else if (old_path.find(dir_path) == std::string::npos) {
std::string new_path(old_path);
#if defined(OS_WIN)
new_path.append(";");
#elif defined(OS_POSIX)
new_path.append(":");
#endif
new_path.append(dir_path.c_str());
env->SetVar(kPythonPathEnv, new_path);
}
}
bool GetPyProtoPath(base::FilePath* dir) {
// Locate the Python code generated by the protocol buffers compiler.
base::FilePath generated_code_dir;
if (!PathService::Get(base::DIR_EXE, &generated_code_dir)) {
LOG(ERROR) << "Can't find " << generated_code_dir.value();
return false;
}
#if defined(OS_MACOSX)
if (base::mac::AmIBundled())
generated_code_dir = generated_code_dir.DirName().DirName().DirName();
#endif
// Used for GYP. TODO(jam): remove after GN conversion.
const base::FilePath kPyProto(FILE_PATH_LITERAL("pyproto"));
if (base::DirectoryExists(generated_code_dir.Append(kPyProto))) {
*dir = generated_code_dir.Append(kPyProto);
return true;
}
// Used for GN.
const base::FilePath kGen(FILE_PATH_LITERAL("gen"));
if (base::DirectoryExists(generated_code_dir.Append(kGen))) {
*dir = generated_code_dir.Append(kGen);
return true;
}
return false;
}
#if defined(OS_WIN)
struct PythonExePath {
PythonExePath() {
// This is test-only code, so CHECK with a subprocess invocation is ok.
base::CommandLine command(base::FilePath(FILE_PATH_LITERAL("cmd")));
command.AppendArg("/c");
command.AppendArg("python");
command.AppendArg("-c");
command.AppendArg("import sys; print sys.executable");
std::string output;
CHECK(GetAppOutput(command, &output));
// This does only work if cmd.exe doesn't use a non-US codepage.
path_ = base::ASCIIToUTF16(output);
TrimWhitespace(path_, base::TRIM_ALL, &path_);
}
base::string16 path_;
};
static base::LazyInstance<PythonExePath>::Leaky g_python_path;
#endif
bool IsInPythonVirtualEnv() {
return base::Environment::Create()->HasVar(kPythonVirtualEnv);
}
bool GetPythonCommand(base::CommandLine* python_cmd) {
DCHECK(python_cmd);
#if defined(OS_WIN)
// Most developers have depot_tools in their path, which only has a
// python.bat, not a python.exe. Go through cmd to find the path to
// the python executable.
// (Don't just return a a "cmd /c python" command line, because then tests
// that try to kill the python process will kill the cmd process instead,
// which can cause flakiness.)
python_cmd->SetProgram(base::FilePath(g_python_path.Get().path_));
#else
python_cmd->SetProgram(base::FilePath(FILE_PATH_LITERAL("python")));
#endif
// Launch python in unbuffered mode, so that python output doesn't mix with
// gtest output in buildbot log files. See http://crbug.com/147368.
python_cmd->AppendArg("-u");
if (!IsInPythonVirtualEnv()) {
// Prevent using system-installed libraries. Use hermetic versioned copies.
python_cmd->AppendArg("-S");
}
return true;
}