ML - displaying all Python and R packages (including system ones) (#10603)

* displaying all packages including readonly
This commit is contained in:
Leila Lali
2020-05-29 13:52:37 -07:00
committed by GitHub
parent 0e0eb7f237
commit 5955953b4a
7 changed files with 77 additions and 54 deletions

View File

@@ -19,8 +19,8 @@ EXEC sp_execute_external_script
@script=N'import pkg_resources
import pandas
OutputDataSet = pandas.DataFrame([(d.project_name, d.version) for d in pkg_resources.working_set])'
select e.name, version from sys.external_libraries e join @tablevar t on e.name = t.name
where [language] = 'PYTHON'
select t.name, (CASE WHEN e.name is NULL THEN 1 ELSE 0 END) as isReadOnly , version from @tablevar t
left join sys.external_libraries e on e.name = t.name and upper(e.[language]) = 'PYTHON'
`;
const listRPackagesQuery = `
@@ -30,9 +30,8 @@ EXEC sp_execute_external_script
@language=N'R',
@script=N'
OutputDataSet <- as.data.frame(installed.packages()[,c(1,3)])'
select e.name, version from sys.external_libraries e join @tablevar t on e.name = t.name
where [language] = 'R'
select t.name, (CASE WHEN e.name is NULL THEN 1 ELSE 0 END) as isReadOnly , version from @tablevar t
left join sys.external_libraries e on e.name = t.name and upper(e.[language]) = 'R'
`;
const checkMlInstalledQuery = `
@@ -100,7 +99,8 @@ export class QueryRunner {
packages = result.rows.map(row => {
return {
name: row[0].displayValue,
version: row[1].displayValue
readonly: row[1].displayValue === '1',
version: row[2].displayValue
};
});
}

View File

@@ -70,8 +70,17 @@ export abstract class SqlPackageManageProviderBase {
* @param packages Packages to uninstall
*/
public async uninstallPackages(packages: nbExtensionApis.IPackageDetails[], databaseName: string): Promise<void> {
let allPackages = await this.listPackages(databaseName);
if (packages) {
await Promise.all(packages.map(x => this.executeScripts(ScriptMode.Uninstall, x, databaseName)));
await Promise.all(packages.map(x => {
const originalPackage = allPackages.find(p => p.name === x.name && p.version === x.version);
if (originalPackage && originalPackage.readonly) {
return Promise.reject(`Cannot uninstalled system package '${x.name}'`);
} else {
return this.executeScripts(ScriptMode.Uninstall, x, databaseName);
}
}));
}
}

View File

@@ -68,9 +68,10 @@ export class SqlRPackageManageProvider extends SqlPackageManageProviderBase impl
let credentials = await this._apiWrapper.getCredentials(connection.connectionId);
if (connection) {
let server = connection.serverName.replace('\\', '\\\\');
let database = databaseName ? `, database="${databaseName}"` : '';
const auth = connection.userName ? `, uid="${connection.userName}", pwd="${credentials[azdata.ConnectionOptionSpecialType.password]}"` : '';
let connectionParts = `server="${connection.serverName}"${auth}${database}`;
let connectionParts = `server="${server}"${auth}${database}`;
let rCommandScript = scriptMode === ScriptMode.Install ? 'sql_install.packages' : 'sql_remove.packages';
let scripts: string[] = [

View File

@@ -21,32 +21,32 @@ function createContext(): TestContext {
apiWrapper: TypeMoq.Mock.ofType(ApiWrapper),
queryProvider: {
providerId: '',
cancelQuery: () => {return Promise.reject();},
runQuery: () => {return Promise.reject();},
runQueryStatement: () => {return Promise.reject();},
runQueryString: () => {return Promise.reject();},
cancelQuery: () => { return Promise.reject(); },
runQuery: () => { return Promise.reject(); },
runQueryStatement: () => { return Promise.reject(); },
runQueryString: () => { return Promise.reject(); },
runQueryAndReturn: () => { return Promise.reject(); },
parseSyntax: () => {return Promise.reject();},
getQueryRows: () => {return Promise.reject();},
disposeQuery: () => {return Promise.reject();},
saveResults: () => {return Promise.reject();},
setQueryExecutionOptions: () => {return Promise.reject();},
registerOnQueryComplete: () => {return Promise.reject();},
registerOnBatchStart: () => {return Promise.reject();},
registerOnBatchComplete: () => {return Promise.reject();},
registerOnResultSetAvailable: () => {return Promise.reject();},
registerOnResultSetUpdated: () => {return Promise.reject();},
registerOnMessage: () => {return Promise.reject();},
commitEdit: () => {return Promise.reject();},
createRow: () => {return Promise.reject();},
deleteRow: () => {return Promise.reject();},
disposeEdit: () => {return Promise.reject();},
initializeEdit: () => {return Promise.reject();},
revertCell: () => {return Promise.reject();},
revertRow: () => {return Promise.reject();},
updateCell: () => {return Promise.reject();},
getEditRows: () => {return Promise.reject();},
registerOnEditSessionReady: () => {return Promise.reject();},
parseSyntax: () => { return Promise.reject(); },
getQueryRows: () => { return Promise.reject(); },
disposeQuery: () => { return Promise.reject(); },
saveResults: () => { return Promise.reject(); },
setQueryExecutionOptions: () => { return Promise.reject(); },
registerOnQueryComplete: () => { return Promise.reject(); },
registerOnBatchStart: () => { return Promise.reject(); },
registerOnBatchComplete: () => { return Promise.reject(); },
registerOnResultSetAvailable: () => { return Promise.reject(); },
registerOnResultSetUpdated: () => { return Promise.reject(); },
registerOnMessage: () => { return Promise.reject(); },
commitEdit: () => { return Promise.reject(); },
createRow: () => { return Promise.reject(); },
deleteRow: () => { return Promise.reject(); },
disposeEdit: () => { return Promise.reject(); },
initializeEdit: () => { return Promise.reject(); },
revertCell: () => { return Promise.reject(); },
revertRow: () => { return Promise.reject(); },
updateCell: () => { return Promise.reject(); },
getEditRows: () => { return Promise.reject(); },
registerOnEditSessionReady: () => { return Promise.reject(); },
}
};
}
@@ -54,7 +54,7 @@ function createContext(): TestContext {
describe('Query Runner', () => {
it('getPythonPackages Should return empty list if not provider found', async function (): Promise<void> {
let testContext = createContext();
let connection = new azdata.connection.ConnectionProfile();
let connection = new azdata.connection.ConnectionProfile();
let queryRunner = new QueryRunner(testContext.apiWrapper.object);
let queryProvider: azdata.QueryProvider;
testContext.apiWrapper.setup(x => x.getProvider<azdata.QueryProvider>(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => queryProvider);
@@ -65,7 +65,7 @@ describe('Query Runner', () => {
it('getPythonPackages Should return empty list if not provider throws', async function (): Promise<void> {
let testContext = createContext();
let connection = new azdata.connection.ConnectionProfile();
let connection = new azdata.connection.ConnectionProfile();
let queryRunner = new QueryRunner(testContext.apiWrapper.object);
testContext.queryProvider.runQueryAndReturn = () => { return Promise.reject(); };
testContext.apiWrapper.setup(x => x.getProvider<azdata.QueryProvider>(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => testContext.queryProvider);
@@ -82,6 +82,11 @@ describe('Query Runner', () => {
isNull: false,
invariantCultureDisplayValue: ''
}, {
displayValue: '0',
isNull: false,
invariantCultureDisplayValue: ''
},
{
displayValue: '1.1.1',
isNull: false,
invariantCultureDisplayValue: ''
@@ -90,6 +95,10 @@ describe('Query Runner', () => {
displayValue: 'p2',
isNull: false,
invariantCultureDisplayValue: ''
}, {
displayValue: '1',
isNull: false,
invariantCultureDisplayValue: ''
}, {
displayValue: '1.1.2',
isNull: false,
@@ -99,20 +108,22 @@ describe('Query Runner', () => {
let expected = [
{
'name': 'p1',
'readonly': false,
'version': '1.1.1'
},
{
'name': 'p2',
'readonly': true,
'version': '1.1.2'
}
];
let result : azdata.SimpleExecuteResult = {
let result: azdata.SimpleExecuteResult = {
rowCount: 2,
columnInfo: [],
rows: rows,
};
let connection = new azdata.connection.ConnectionProfile();
let connection = new azdata.connection.ConnectionProfile();
let queryRunner = new QueryRunner(testContext.apiWrapper.object);
testContext.queryProvider.runQueryAndReturn = () => { return Promise.resolve(result); };
testContext.apiWrapper.setup(x => x.getProvider<azdata.QueryProvider>(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => testContext.queryProvider);
@@ -128,12 +139,12 @@ describe('Query Runner', () => {
];
let expected: IPackageDetails[] = [];
let result : azdata.SimpleExecuteResult = {
let result: azdata.SimpleExecuteResult = {
rowCount: 2,
columnInfo: [],
rows: rows,
};
let connection = new azdata.connection.ConnectionProfile();
let connection = new azdata.connection.ConnectionProfile();
let queryRunner = new QueryRunner(testContext.apiWrapper.object);
testContext.queryProvider.runQueryAndReturn = () => { return Promise.resolve(result); };
testContext.apiWrapper.setup(x => x.getProvider<azdata.QueryProvider>(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => testContext.queryProvider);
@@ -148,12 +159,12 @@ describe('Query Runner', () => {
let rows: azdata.DbCellValue[][] = [
];
let result : azdata.SimpleExecuteResult = {
let result: azdata.SimpleExecuteResult = {
rowCount: 2,
columnInfo: [],
rows: rows,
};
let connection = new azdata.connection.ConnectionProfile();
let connection = new azdata.connection.ConnectionProfile();
let queryRunner = new QueryRunner(testContext.apiWrapper.object);
testContext.queryProvider.runQueryAndReturn = () => { return Promise.resolve(result); };
testContext.apiWrapper.setup(x => x.getProvider<azdata.QueryProvider>(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => testContext.queryProvider);
@@ -173,12 +184,12 @@ describe('Query Runner', () => {
];
let expected = true;
let result : azdata.SimpleExecuteResult = {
let result: azdata.SimpleExecuteResult = {
rowCount: 2,
columnInfo: [],
rows: rows,
};
let connection = new azdata.connection.ConnectionProfile();
let connection = new azdata.connection.ConnectionProfile();
let queryRunner = new QueryRunner(testContext.apiWrapper.object);
testContext.queryProvider.runQueryAndReturn = () => { return Promise.resolve(result); };
testContext.apiWrapper.setup(x => x.getProvider<azdata.QueryProvider>(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => testContext.queryProvider);
@@ -198,12 +209,12 @@ describe('Query Runner', () => {
];
let expected = false;
let result : azdata.SimpleExecuteResult = {
let result: azdata.SimpleExecuteResult = {
rowCount: 2,
columnInfo: [],
rows: rows,
};
let connection = new azdata.connection.ConnectionProfile();
let connection = new azdata.connection.ConnectionProfile();
let queryRunner = new QueryRunner(testContext.apiWrapper.object);
testContext.queryProvider.runQueryAndReturn = () => { return Promise.resolve(result); };
testContext.apiWrapper.setup(x => x.getProvider<azdata.QueryProvider>(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => testContext.queryProvider);
@@ -217,12 +228,12 @@ describe('Query Runner', () => {
let rows: azdata.DbCellValue[][] = [];
let expected = false;
let result : azdata.SimpleExecuteResult = {
let result: azdata.SimpleExecuteResult = {
rowCount: 2,
columnInfo: [],
rows: rows,
};
let connection = new azdata.connection.ConnectionProfile();
let connection = new azdata.connection.ConnectionProfile();
let queryRunner = new QueryRunner(testContext.apiWrapper.object);
testContext.queryProvider.runQueryAndReturn = () => { return Promise.resolve(result); };
testContext.apiWrapper.setup(x => x.getProvider<azdata.QueryProvider>(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => testContext.queryProvider);
@@ -242,12 +253,12 @@ describe('Query Runner', () => {
];
let expected = true;
let result : azdata.SimpleExecuteResult = {
let result: azdata.SimpleExecuteResult = {
rowCount: 2,
columnInfo: [],
rows: rows,
};
let connection = new azdata.connection.ConnectionProfile();
let connection = new azdata.connection.ConnectionProfile();
let queryRunner = new QueryRunner(testContext.apiWrapper.object);
testContext.queryProvider.runQueryAndReturn = () => { return Promise.resolve(result); };
testContext.apiWrapper.setup(x => x.getProvider<azdata.QueryProvider>(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => testContext.queryProvider);
@@ -267,12 +278,12 @@ describe('Query Runner', () => {
];
let expected = false;
let result : azdata.SimpleExecuteResult = {
let result: azdata.SimpleExecuteResult = {
rowCount: 2,
columnInfo: [],
rows: rows,
};
let connection = new azdata.connection.ConnectionProfile();
let connection = new azdata.connection.ConnectionProfile();
let queryRunner = new QueryRunner(testContext.apiWrapper.object);
testContext.queryProvider.runQueryAndReturn = () => { return Promise.resolve(result); };
testContext.apiWrapper.setup(x => x.getProvider<azdata.QueryProvider>(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => testContext.queryProvider);
@@ -286,12 +297,12 @@ describe('Query Runner', () => {
let rows: azdata.DbCellValue[][] = [];
let expected = false;
let result : azdata.SimpleExecuteResult = {
let result: azdata.SimpleExecuteResult = {
rowCount: 2,
columnInfo: [],
rows: rows,
};
let connection = new azdata.connection.ConnectionProfile();
let connection = new azdata.connection.ConnectionProfile();
let queryRunner = new QueryRunner(testContext.apiWrapper.object);
testContext.queryProvider.runQueryAndReturn = () => { return Promise.resolve(result); };
testContext.apiWrapper.setup(x => x.getProvider<azdata.QueryProvider>(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => testContext.queryProvider);

View File

@@ -38,6 +38,7 @@ export interface IJupyterServerInstallation {
export interface IPackageDetails {
name: string;
version: string;
readonly?: boolean;
}
export interface IPackageTarget {