Skip to content

Commit

Permalink
refactor(vscode): detection and running of python from vscode
Browse files Browse the repository at this point in the history
  • Loading branch information
d-biehl committed Nov 1, 2023
1 parent 4e2939e commit 6000edb
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 49 deletions.
5 changes: 5 additions & 0 deletions bundled/tool/utils/check_robot_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ def update_sys_path(path_to_add: str, strategy: str) -> None:
os.fspath(pathlib.Path(__file__).parent.parent.parent / "libs"),
os.getenv("LS_IMPORT_STRATEGY", "useBundled"),
)
try:
__import__("robot")
except ModuleNotFoundError:
print("Robot Framework not installed", file=sys.stderr)
sys.exit(1)

from robotcode.robot.utils import get_robot_version

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1759,7 +1759,7 @@ def get_test_library(
from robot.libdocpkg.datatypes import TypeDoc as RobotTypeDoc
from robot.running.arguments.argumentspec import TypeInfo

def _yield_type_info(info: TypeInfo) -> TypeInfo:
def _yield_type_info(info: TypeInfo) -> Iterable[TypeInfo]:
if not info.is_union:
yield info
for nested in info.nested:
Expand Down
8 changes: 6 additions & 2 deletions packages/robot/src/robotcode/robot/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@

from robotcode.core.utils.version import Version, create_version_from_str

import robot.version

_robot_version: Optional[Version] = None


def get_robot_version() -> Version:
global _robot_version
if _robot_version is None:
import robot.version

_robot_version = create_version_from_str(robot.version.get_version())
return _robot_version


def get_robot_version_str() -> str:
return str(robot.version.get_version())
114 changes: 68 additions & 46 deletions vscode-client/languageclientsmanger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,16 @@ interface DiscoverInfoResult {
system_version?: string;
[key: string]: string | undefined;
}

export class LanguageClientsManager {
private clientsMutex = new Mutex();
private _pythonValidPythonAndRobotEnvMutex = new Mutex();

public readonly clients: Map<string, LanguageClient> = new Map();
public readonly outputChannels: Map<string, vscode.OutputChannel> = new Map();

private _disposables: vscode.Disposable;
private _pythonValidPythonAndRobotEnv = new WeakMap<vscode.WorkspaceFolder, boolean>();
public _pythonValidPythonAndRobotEnv = new WeakMap<vscode.WorkspaceFolder, boolean>();
private _workspaceFolderDiscoverInfo = new WeakMap<vscode.WorkspaceFolder, DiscoverInfoResult>();

private readonly _onClientStateChangedEmitter = new vscode.EventEmitter<ClientStateChangedEvent>();
Expand Down Expand Up @@ -236,64 +238,84 @@ export class LanguageClientsManager {
});
}

private async getServerOptions(folder: vscode.WorkspaceFolder, mode: string): Promise<ServerOptions | undefined> {
const config = vscode.workspace.getConfiguration(CONFIG_SECTION, folder);

const pythonCommand = this.pythonManager.getPythonCommand(folder);
public async isValidRobotEnvironmentInFolder(
folder: vscode.WorkspaceFolder,
showDialogs?: boolean,
): Promise<boolean> {
return await this._pythonValidPythonAndRobotEnvMutex.dispatch(() => {
if (this._pythonValidPythonAndRobotEnv.has(folder)) {
return this._pythonValidPythonAndRobotEnv.get(folder) ?? false;
}

const envOk = this._pythonValidPythonAndRobotEnv.get(folder);
if (envOk === false) return undefined;
const pythonCommand = this.pythonManager.getPythonCommand(folder);
if (!pythonCommand) {
this._pythonValidPythonAndRobotEnv.set(folder, false);
if (showDialogs) {
this.showErrorWithSelectPythonInterpreter(
`Can't find a valid python executable for workspace folder '${folder.name}'. ` +
"Check if python and the python extension is installed.",
folder,
);
}

if (!pythonCommand) {
this._pythonValidPythonAndRobotEnv.set(folder, false);
return false;
}

this.showErrorWithSelectPythonInterpreter(
`Can't find a valid python executable for workspace folder '${folder.name}'. ` +
"Check if python and the python extension is installed.",
folder,
);
if (!this.pythonManager.checkPythonVersion(pythonCommand)) {
this._pythonValidPythonAndRobotEnv.set(folder, false);
if (showDialogs) {
this.showErrorWithSelectPythonInterpreter(
`Invalid python version for workspace folder '${folder.name}'. Only python version >= 3.8 supported. ` +
"Please update to a newer python version or select a valid python environment.",
folder,
);
}

return undefined;
}
return false;
}

if (!this.pythonManager.checkPythonVersion(pythonCommand)) {
this._pythonValidPythonAndRobotEnv.set(folder, false);
const robotCheck = this.pythonManager.checkRobotVersion(pythonCommand);
if (robotCheck === undefined) {
this._pythonValidPythonAndRobotEnv.set(folder, false);

this.showErrorWithSelectPythonInterpreter(
`Invalid python version for workspace folder '${folder.name}'. Only python version >= 3.8 supported. ` +
"Please update to a newer python version or select a valid python environment.",
folder,
);
if (showDialogs) {
this.showErrorWithSelectPythonInterpreter(
`Robot Framework package not found in workspace folder '${folder.name}'. ` +
"Please install Robot Framework >= version 4.1 to the current python environment or select a valid python environment.",
folder,
);
}

return undefined;
}
return false;
}

const robotCheck = this.pythonManager.checkRobotVersion(pythonCommand);
if (robotCheck === undefined) {
this._pythonValidPythonAndRobotEnv.set(folder, false);
if (robotCheck === false) {
this._pythonValidPythonAndRobotEnv.set(folder, false);

this.showErrorWithSelectPythonInterpreter(
`Robot Framework package not found in workspace folder '${folder.name}'. ` +
"Please install Robot Framework >= Version 4.0 to the current python environment or select a valid python environment.",
folder,
);
if (showDialogs) {
this.showErrorWithSelectPythonInterpreter(
`Robot Framework version in workspace folder '${folder.name}' not supported. Only Robot Framework version >= 4.1 supported. ` +
"Please install or update to Robot Framework >= version 4.1 to the current python environment or select a valid python environment.",
folder,
);
}

return undefined;
}
return false;
}

if (robotCheck === false) {
this._pythonValidPythonAndRobotEnv.set(folder, false);
this._pythonValidPythonAndRobotEnv.set(folder, true);
return true;
});
}

this.showErrorWithSelectPythonInterpreter(
`Robot Framework version in workspace folder '${folder.name}' not supported. Only Robot Framework version >= 4.0.0 supported. ` +
"Please install or update Robot Framework >= Version 4.0 to the current python environment or select a valid python environment.",
folder,
);
private async getServerOptions(folder: vscode.WorkspaceFolder, mode: string): Promise<ServerOptions | undefined> {
const config = vscode.workspace.getConfiguration(CONFIG_SECTION, folder);

return undefined;
}
const envOk = await this.isValidRobotEnvironmentInFolder(folder, true);
if (envOk === false) return undefined;

this._pythonValidPythonAndRobotEnv.set(folder, true);
const pythonCommand = this.pythonManager.getPythonCommand(folder);
if (!pythonCommand) return undefined;

const robotCodeExtraArgs = config.get<string[]>("languageServer.extraArgs", []);

Expand Down Expand Up @@ -714,7 +736,7 @@ export class LanguageClientsManager {
try {
const folder = vscode.workspace.getWorkspaceFolder(editor.document.uri);
if (folder) {
if (!this._workspaceFolderDiscoverInfo.has(folder)) {
if (!this._workspaceFolderDiscoverInfo.has(folder) && (await this.isValidRobotEnvironmentInFolder(folder))) {
this._workspaceFolderDiscoverInfo.set(
folder,
(await this.pythonManager.executeRobotCode(folder, ["discover", "info"])) as DiscoverInfoResult,
Expand Down
10 changes: 10 additions & 0 deletions vscode-client/testcontrollermanager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,12 @@ export class TestControllerManager {
folder: vscode.WorkspaceFolder,
profiles?: string[],
): Promise<RobotCodeProfilesResult> {
if (!(await this.languageClientsManager.isValidRobotEnvironmentInFolder(folder))) {
return {
profiles: [],
messages: [],
} as RobotCodeProfilesResult;
}
const config = vscode.workspace.getConfiguration(CONFIG_SECTION, folder);
const paths = config.get<string[] | undefined>("robot.paths", undefined);

Expand Down Expand Up @@ -523,6 +529,10 @@ export class TestControllerManager {
stdioData?: string,
token?: vscode.CancellationToken,
): Promise<RobotCodeDiscoverResult> {
if (!(await this.languageClientsManager.isValidRobotEnvironmentInFolder(folder))) {
return {};
}

const config = vscode.workspace.getConfiguration(CONFIG_SECTION, folder);
const profiles = config.get<string[]>("profiles", []);
const pythonPath = config.get<string[]>("robot.pythonPath", []);
Expand Down

0 comments on commit 6000edb

Please sign in to comment.