in language-extensions/python/src/PythonLibrarySession.cpp [150:243]
SQLRETURN PythonLibrarySession::UninstallLibrary(
SQLCHAR *libraryName,
SQLINTEGER libraryNameLength,
SQLCHAR *libraryInstallDirectory,
SQLINTEGER libraryInstallDirectoryLength
)
{
LOG("PythonLibrarySession::UninstallExternalLibrary");
SQLRETURN result = SQL_ERROR;
string errorString;
vector<fs::directory_entry> artifacts;
string libName = string(reinterpret_cast<char *>(libraryName), libraryNameLength);
string installDir = string(reinterpret_cast<char *>(libraryInstallDirectory),
libraryInstallDirectoryLength);
installDir = PythonExtensionUtils::NormalizePathString(installDir);
try
{
// Save the top_level items so we can delete them if the pip uninstall fails.
// If pip uninstall succeeds, we won't need this.
//
artifacts = GetTopLevel(libName, installDir);
string pathToPython = PythonExtensionUtils::GetPathToPython();
string uninstallScript =
"newPath = ['" + installDir + "'] + _originalpath\n"
"os.environ['PYTHONPATH'] = os.pathsep.join(newPath)\n"
"import subprocess\n"
"pipresult = subprocess.run(['" + pathToPython +
"', '-m', 'pip', 'uninstall', '" + libName + "', '-y']).returncode\n";
bp::exec(uninstallScript.c_str(), m_mainNamespace);
int pipResult = bp::extract<int>(m_mainNamespace["pipresult"]);
if (pipResult == 0)
{
result = SQL_SUCCESS;
}
else
{
throw runtime_error("Pip failed to fully uninstall the package with exit code " +
to_string(pipResult));
}
}
catch (const exception & ex)
{
result = SQL_ERROR;
errorString = string(ex.what());
}
catch (const bp::error_already_set &)
{
result = SQL_ERROR;
errorString = PythonExtensionUtils::ParsePythonException();
}
catch (...)
{
result = SQL_ERROR;
errorString = "Unexpected exception occurred in function UninstallExternalLibrary()";
}
// If pip fails for some reason, we try to manually uninstall the package by deleting the
// top level package folder as well as any dist/egg/.py files that were left behind.
//
if (result != SQL_SUCCESS && fs::exists(installDir))
{
LOG("Failed to fully uninstall " + libName + " with pip, deleting files manually");
for (fs::directory_entry entry : artifacts)
{
fs::remove_all(entry);
}
vector<fs::directory_entry> newArtifacts = GetAllArtifacts(libName, installDir);
for (fs::directory_entry entry : newArtifacts)
{
fs::remove_all(entry);
}
// If we successfully removed all the files, then we have a SUCCESS result.
//
result = SQL_SUCCESS;
}
return result;
}