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 136
|
// Copyright © 2016 Alexandre Detiste <alexandre@detiste.be>
// SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm>
#include <cstring>
#include <iostream>
#include <dirent.h>
#include <sys/stat.h>
#include "python.h"
#ifdef BUSTER
#include <experimental/string_view>
using namespace std::experimental;
#endif
using namespace std;
vector<string> versions;
void init_python()
{
DIR *dp;
struct dirent *dirp;
dp = opendir("/usr/bin");
while ((dirp = readdir(dp)) != nullptr) {
string entry { dirp->d_name };
if (entry.rfind("python3.") == 0 && entry.find("-") == string::npos) {
string pyc_ver = "3" + entry.substr(8);
versions.emplace_back(pyc_ver);
}
}
closedir(dp);
sort(versions.begin(), versions.end());
}
static bool ends_with(string_view str, string_view suffix)
{
if (suffix.size() > str.size())
return false;
return std::equal(suffix.rbegin(), suffix.rend(), str.rbegin());
}
bool pyc_has_py(string pyc, bool debug)
{
if (pyc.length() < 15)
return false;
// #366616: Don't report .pyc files if a .py file exist
// also ignore __pycache__ dirs
// if .py are found in the same directory
if (ends_with(pyc, "/__pycache__")) {
string dir;
DIR *dp;
struct dirent *dirp;
dir = pyc.substr(0, pyc.length()-12);
dp = opendir(dir.c_str());
if(dp == nullptr) {
cerr << "Failed to open directory " << dir << ": " << strerror(errno) << endl;
return false;
}
while ((dirp = readdir(dp)) != nullptr) {
string_view entry { dirp->d_name };
if (entry.length() < 4)
continue;
//cerr << ' ' << entry << endl;
if (ends_with(entry, ".py")) {
if (debug) cerr << "match: " << dir << '/' << entry << endl;
closedir(dp);
return true;
}
}
closedir(dp);
return false;
}
if (!ends_with(pyc, ".pyc"))
return false;
struct stat buffer;
#ifdef BUSTER
// python2 support
string py;
py = pyc.substr(0, pyc.length()-1);
if (stat(py.c_str(), &buffer) == 0) {
if (debug) cerr << "match: " << py << endl;
return true;
}
#endif
/* TODO: consider old .pyc from old uinstalled Python3.x as leftover garbage
$ py3versions -s
python3.11
tchet@brix ~/git/cruft-ng $ grep ^supported-versions /usr/share/python3/debian_defaults
supported-versions = python3.11
take 3.11 as a baseline but also support the next expected version 3.12
$ ls /usr/bin/python3\.* | grep 3\.[0-9]*$
/usr/bin/python3.11
/usr/bin/python3.12
*/
/*
/usr/share/pgcli/pgcli/packages/counter.py
/usr/share/pgcli/pgcli/packages/__pycache__/counter.cpython-34.pyc
*/
size_t pos = pyc.find("/__pycache__/");
if (pos == string::npos)
return false;
pyc.replace(pos, 13, "/");
pos = pyc.find(".cpython-");
if (pos == string::npos)
return false;
bool installed = false;
int offset;
for (unsigned int i=0;i<versions.size();i++) {
if(pyc.find(versions[i], pos) != string::npos) {
installed = true;
offset = 13 + versions[i].length();
break;
}
}
if (!installed) return false;
pyc.replace(pos, offset, ".py");
bool matched;
matched = (stat(pyc.c_str(), &buffer) == 0);
if (matched && debug) cerr << "match: " << pyc << endl;
return matched;
}
|