1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "net/test/python_utils.h" 6 7 #include "base/base_paths.h" 8 #include "base/environment.h" 9 #include "base/file_path.h" 10 #include "base/file_util.h" 11 #include "base/logging.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "base/path_service.h" 14 #include "base/utf_string_conversions.h" 15 16 const char kPythonPathEnv[] = "PYTHONPATH"; 17 18 void AppendToPythonPath(const FilePath& dir) { 19 scoped_ptr<base::Environment> env(base::Environment::Create()); 20 std::string old_path; 21 std::string dir_path; 22 #if defined(OS_WIN) 23 dir_path = WideToUTF8(dir.value()); 24 #elif defined(OS_POSIX) 25 dir_path = dir.value(); 26 #endif 27 if (!env->GetVar(kPythonPathEnv, &old_path)) { 28 env->SetVar(kPythonPathEnv, dir_path.c_str()); 29 } else if (old_path.find(dir_path) == std::string::npos) { 30 std::string new_path(old_path); 31 #if defined(OS_WIN) 32 new_path.append(";"); 33 #elif defined(OS_POSIX) 34 new_path.append(":"); 35 #endif 36 new_path.append(dir_path.c_str()); 37 env->SetVar(kPythonPathEnv, new_path); 38 } 39 } 40 41 namespace { 42 43 // Search for |to_try|, rolling up the directory tree from 44 // |start_dir|. If found, return true and put the path to |to_try| in 45 // |out_dir|. If not, return false and leave |out_dir| untouched. 46 bool TryRelativeToDir(const FilePath& start_dir, 47 const FilePath& to_try, 48 FilePath* out_dir) { 49 FilePath dir(start_dir); 50 while (!file_util::DirectoryExists(dir.Append(to_try))) { 51 FilePath parent = dir.DirName(); 52 if (parent == dir) { 53 // We hit the root directory. 54 return false; 55 } 56 dir = parent; 57 } 58 *out_dir = dir; 59 return true; 60 } 61 62 } // namespace 63 64 bool GetPyProtoPath(FilePath* dir) { 65 // Locate the Python code generated by the protocol buffers compiler. 66 FilePath generated_code_dir; 67 if (!PathService::Get(base::DIR_EXE, &generated_code_dir)) { 68 LOG(ERROR) << "Can't find " << generated_code_dir.value(); 69 return false; 70 } 71 72 const FilePath kPyProto(FILE_PATH_LITERAL("pyproto")); 73 74 #if defined(OS_MACOSX) || defined(OS_CHROMEOS) 75 FilePath source_dir; 76 if (!PathService::Get(base::DIR_SOURCE_ROOT, &source_dir)) { 77 LOG(ERROR) << "Can't find " << source_dir.value(); 78 return false; 79 } 80 // On Mac, and possibly Chrome OS, DIR_EXE might be pointing deep 81 // into the Release/ (or Debug/) directory and we can't depend on 82 // how far down it goes. So we walk upwards from DIR_EXE until we 83 // find a likely looking spot. 84 if (!TryRelativeToDir(generated_code_dir, kPyProto, dir)) { 85 LOG(WARNING) << "Can't find " << kPyProto.value() 86 << " next to " << generated_code_dir.value(); 87 // On Chrome OS, we may have installed the test binaries and support tools 88 // in a wholly separate location, relative to DIR_SOURCE_ROOT. We'll want 89 // to do a similar investigation from that point as well. 90 generated_code_dir = source_dir 91 .Append(FILE_PATH_LITERAL("out")) 92 .Append(FILE_PATH_LITERAL("Release")); 93 if (!TryRelativeToDir(generated_code_dir, kPyProto, dir)) { 94 LOG(WARNING) << "Can't find " << kPyProto.value() 95 << " next to " << generated_code_dir.value(); 96 return false; 97 } 98 } 99 generated_code_dir = *dir; 100 #endif 101 *dir = generated_code_dir.Append(kPyProto); 102 VLOG(2) << "Found " << kPyProto.value() << " in " << dir->value(); 103 return true; 104 } 105 106 bool GetPythonRunTime(FilePath* dir) { 107 #if defined(OS_WIN) 108 if (!PathService::Get(base::DIR_SOURCE_ROOT, dir)) 109 return false; 110 *dir = dir->Append(FILE_PATH_LITERAL("third_party")) 111 .Append(FILE_PATH_LITERAL("python_26")) 112 .Append(FILE_PATH_LITERAL("python.exe")); 113 #elif defined(OS_POSIX) 114 *dir = FilePath("python"); 115 #endif 116 return true; 117 } 118