• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
AppendToPythonPath(const FilePath & dir)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.
TryRelativeToDir(const FilePath & start_dir,const FilePath & to_try,FilePath * out_dir)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 
GetPyProtoPath(FilePath * dir)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 
GetPythonRunTime(FilePath * dir)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