Skip to content

Commit

Permalink
Fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
DonJayamanne committed Nov 11, 2021
1 parent 62df52b commit fc6808b
Show file tree
Hide file tree
Showing 27 changed files with 356 additions and 247 deletions.
1 change: 1 addition & 0 deletions package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,7 @@
"DataScience.failedToInterruptKernel": "Failed to interrupt the Kernel.",
"DataScience.kernelDied": "The kernel died. View Jupyter [log](command:jupyter.viewOutput) for further details. \nError: {0}...",
"DataScience.kernelDiedWithoutError": "The kernel '{0}' died. View Jupyter [log](command:jupyter.viewOutput) for further details.",
"DataScience.fileSeemsToBeInterferingWithKernelStartup": "The file '{0}' seems to be overriding built in modules and interfering with the startup of the kernel. Consider renaming the file and starting the kernel again.",
"DataScience.cannotRunCellKernelIsDead": "Cannot run cells, as the kernel '{0}' is dead.",
"DataScience.waitingForJupyterSessionToBeIdle": "Waiting for Jupyter Session to be idle",
"DataScience.gettingListOfKernelsForLocalConnection": "Fetching Kernels",
Expand Down
9 changes: 1 addition & 8 deletions pythonFiles/vscode_datascience_helpers/kernel_launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@
# See comment at the point of our use of Popen
from subprocess import Popen, PIPE # nosec

from ipython_genutils.encoding import getdefaultencoding
from ipython_genutils.py3compat import cast_bytes_py2


def launch_kernel(
cmd,
Expand Down Expand Up @@ -79,7 +76,6 @@ def launch_kernel(

env = env if (env is not None) else os.environ.copy()

encoding = getdefaultencoding(prefer_stream=False)
kwargs = kw.copy()
main_args = dict(
stdin=_stdin,
Expand All @@ -92,18 +88,15 @@ def launch_kernel(

# Spawn a kernel.
if sys.platform == "win32":
# Popen on Python 2 on Windows cannot handle unicode args or cwd
cmd = [cast_bytes_py2(c, encoding) for c in cmd]
if cwd:
cwd = cast_bytes_py2(cwd, sys.getfilesystemencoding() or "ascii")
kwargs["cwd"] = cwd

from .win_interrupt import create_interrupt_event

# Create a Win32 event for interrupting the kernel
# and store it in an environment variable.
interrupt_event = create_interrupt_event()
env["JPY_INTERRUPT_EVENT"] = str(interrupt_event)
env[" "] = str(interrupt_event)
# deprecated old env name:
env["IPY_INTERRUPT_EVENT"] = env["JPY_INTERRUPT_EVENT"]

Expand Down
17 changes: 12 additions & 5 deletions src/client/common/cancellation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,18 @@ export class CancellationError extends BaseError {
* @param {({ defaultValue: T; token: CancellationToken; cancelAction: 'reject' | 'resolve' })} options
* @returns {Promise<T>}
*/
export function createPromiseFromCancellation<T>(options: {
defaultValue: T;
token?: CancellationToken;
cancelAction: 'reject' | 'resolve';
}): Promise<T> {
export function createPromiseFromCancellation<T>(
options:
| {
defaultValue: T;
token?: CancellationToken;
cancelAction: 'resolve';
}
| {
token?: CancellationToken;
cancelAction: 'reject';
}
): Promise<T> {
return new Promise<T>((resolve, reject) => {
// Never resolve.
if (!options.token) {
Expand Down
142 changes: 73 additions & 69 deletions src/client/common/errors/errorUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,19 +114,19 @@ export enum KernelFailureReason {
/**
* Errors specific to importing of `win32api` module.
*/
importWin32apiError = 'importWin32apiError',
importWin32apiFailure = 'importWin32apiFailure',
/**
* Errors specific to the zmq module.
*/
zmqModuleError = 'zmqModuleError',
zmqModuleFailure = 'zmqModuleFailure',
/**
* Errors specific to older versions of IPython.
*/
oldIPythonError = 'oldIPythonError',
oldIPythonFailure = 'oldIPythonFailure',
/**
* Errors specific to older versions of IPyKernel.
*/
oldIPyKernelError = 'oldIPyKernelError',
oldIPyKernelFailure = 'oldIPyKernelFailure',
/**
* Creating files such as os.py and having this in the root directory or some place where Python would load it,
* would result in the `os` module being overwritten with the users `os.py` file.
Expand All @@ -145,12 +145,12 @@ export enum KernelFailureReason {
* ImportError: No module named 'win32api'
* 2. ImportError: cannot import name 'constants' from partially initialized module 'zmq.backend.cython' (most likely due to a circular import) (C:\Users\<user>\AppData\Roaming\Python\Python38\site-packages\zmq\backend\cython\__init__.py)
*/
importError = 'importError',
importFailure = 'importFailure',
/**
* Some missing dependency is not installed.
* Error messages are of the form `ModuleNotFoundError: No module named 'zmq'`
*/
moduleNotFoundError = 'moduleNotFound',
moduleNotFoundFailure = 'moduleNotFound',
/**
* Failure to load some dll.
* Error messages are of the following form
Expand All @@ -159,66 +159,70 @@ export enum KernelFailureReason {
*/
dllLoadFailure = 'dllLoadFailure'
}
export type KernelFailure = {
type BaseFailure<Reason extends KernelFailureReason, MoreInfo = {}> = {
reason: Reason;
/**
* Classifications of the errors that is safe for telemetry (no pii).
*/
telemetrySafeTags: string[];
} & (
| {
reason: KernelFailureReason.overridingBuiltinModules;
/**
* The module that has been overwritten.
*/
moduleName: string;
/**
* Fully qualified path to the module.
*/
fileName: string;
}
| {
reason: KernelFailureReason.importError;
/**
* What is being imported from the module.
*/
name?: string;
moduleName: string;
fileName?: string;
}
| {
reason: KernelFailureReason.moduleNotFoundError;
/**
* Name of the missing module.
*/
moduleName: string;
}
| {
reason: KernelFailureReason.dllLoadFailure;
/**
* Name of the module that couldn't be loaded.
*/
moduleName?: string;
}
| {
reason: KernelFailureReason.dllLoadFailure;
/**
* Name of the module that couldn't be loaded.
*/
moduleName?: string;
}
| {
reason: KernelFailureReason.importWin32apiError;
}
| {
reason: KernelFailureReason.zmqModuleError;
}
| {
reason: KernelFailureReason.oldIPyKernelError;
}
| {
reason: KernelFailureReason.oldIPythonError;
}
);
} & MoreInfo;
export type OverridingBuiltInModulesFailure = BaseFailure<
KernelFailureReason.overridingBuiltinModules,
{
/**
* The module that has been overwritten.
*/
moduleName: string;
/**
* Fully qualified path to the module.
*/
fileName: string;
}
>;
export type ImportErrorFailure = BaseFailure<
KernelFailureReason.importFailure,
{
/**
* What is being imported from the module.
*/
name?: string;
moduleName: string;
fileName?: string;
}
>;
export type ModuleNotFoundFailure = BaseFailure<
KernelFailureReason.moduleNotFoundFailure,
{
/**
* Name of the missing module.
*/
moduleName: string;
}
>;
export type DllLoadFailure = BaseFailure<
KernelFailureReason.dllLoadFailure,
{
/**
* Name of the module that couldn't be loaded.
*/
moduleName?: string;
}
>;
export type ImportWin32ApiFailure = BaseFailure<KernelFailureReason.importWin32apiFailure>;
export type ZmqModuleFailure = BaseFailure<KernelFailureReason.zmqModuleFailure>;
export type OldIPyKernelFailure = BaseFailure<KernelFailureReason.oldIPyKernelFailure>;
export type OldIPythonFailure = BaseFailure<KernelFailureReason.oldIPythonFailure>;

export type KernelFailure =
| OverridingBuiltInModulesFailure
| ImportErrorFailure
| ModuleNotFoundFailure
| DllLoadFailure
| ImportWin32ApiFailure
| ImportWin32ApiFailure
| ZmqModuleFailure
| OldIPyKernelFailure
| OldIPythonFailure;

export function analyseKernelErrors(
stdErrOrStackTrace: string,
Expand All @@ -240,7 +244,7 @@ export function analyseKernelErrors(
ImportError: No module named 'win32api'
*/
return {
reason: KernelFailureReason.importWin32apiError,
reason: KernelFailureReason.importWin32apiFailure,
telemetrySafeTags: ['win32api']
};
}
Expand All @@ -252,7 +256,7 @@ export function analyseKernelErrors(
ImportError: DLL load failed: 找不到指定的程序。
*/
return {
reason: KernelFailureReason.importWin32apiError,
reason: KernelFailureReason.importWin32apiFailure,
telemetrySafeTags: ['dll.load.failed', 'win32api']
};
}
Expand Down Expand Up @@ -286,7 +290,7 @@ export function analyseKernelErrors(
AssertionError: Couldn't find Class NSProcessInfo
*/
return {
reason: KernelFailureReason.oldIPythonError,
reason: KernelFailureReason.oldIPythonFailure,
telemetrySafeTags: ['oldipython']
};
}
Expand All @@ -307,7 +311,7 @@ export function analyseKernelErrors(
Info 2020-08-10 12:14:11: Python Daemon (pid: 16976): write to stderr: NotImplementedError
*/
return {
reason: KernelFailureReason.oldIPyKernelError,
reason: KernelFailureReason.oldIPyKernelFailure,
telemetrySafeTags: ['oldipykernel']
};
}
Expand Down Expand Up @@ -343,7 +347,7 @@ export function analyseKernelErrors(

if (tags.length) {
return {
reason: KernelFailureReason.zmqModuleError,
reason: KernelFailureReason.zmqModuleFailure,
telemetrySafeTags: tags
};
}
Expand All @@ -359,7 +363,7 @@ export function analyseKernelErrors(
}

return {
reason: KernelFailureReason.importError,
reason: KernelFailureReason.importFailure,
moduleName: info.moduleName,
fileName: info.fileName,
telemetrySafeTags: ['import.error']
Expand All @@ -370,7 +374,7 @@ export function analyseKernelErrors(
const info = extractModuleAndFileFromImportError(lastTwolinesOfError[1]);
if (info) {
return {
reason: KernelFailureReason.moduleNotFoundError,
reason: KernelFailureReason.moduleNotFoundFailure,
moduleName: info.moduleName,
telemetrySafeTags: ['module.notfound.error']
};
Expand Down
1 change: 1 addition & 0 deletions src/client/common/errors/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export type ErrorCategory =
| 'notinstalled'
| 'kernelspecnotfound' // Left for historical purposes, not used anymore.
| 'unsupportedKernelSpec' // Left for historical purposes, not used anymore.
| 'sessionDisposed'
| 'unknown';

// If there are errors, then the are added to the telementry properties.
Expand Down
24 changes: 22 additions & 2 deletions src/client/common/platform/fs-paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Licensed under the MIT License.

import * as nodepath from 'path';
import { Uri } from 'vscode';
import { Uri, WorkspaceFolder } from 'vscode';
import { getOSType, OSType } from '../utils/platform';
import { IExecutables, IFileSystemPaths, IFileSystemPathUtils } from './types';
// eslint-disable-next-line @typescript-eslint/no-var-requires, @typescript-eslint/no-require-imports
Expand Down Expand Up @@ -145,7 +145,25 @@ export class FileSystemPathUtils implements IFileSystemPathUtils {
}

const homePath = untildify('~');
export function getDisplayPath(filename?: string | Uri) {
export function getDisplayPath(
filename?: string | Uri,
workspaceFolder: readonly WorkspaceFolder[] | WorkspaceFolder[] = []
) {
const relativeToHome = getDisplayPathImpl(filename);
const relativeToWorkspaceFolders = workspaceFolder.map((folder) => getDisplayPathImpl(filename, folder.uri.fsPath));
// Pick the shortest path for display purposes.
// As those are most likely relative to some workspace folder.
let bestDisplayPath = relativeToHome;
[relativeToHome, ...relativeToWorkspaceFolders].forEach((relativePath) => {
if (relativePath.length < bestDisplayPath.length) {
bestDisplayPath = relativePath;
}
});

return bestDisplayPath;
}

function getDisplayPathImpl(filename?: string | Uri, cwd?: string): string {
let file = '';
if (typeof filename === 'string') {
file = filename;
Expand All @@ -158,6 +176,8 @@ export function getDisplayPath(filename?: string | Uri) {
}
if (!file) {
return '';
} else if (cwd && file.startsWith(cwd)) {
return `.${nodepath.sep}${nodepath.relative(cwd, file)}`;
} else if (file.startsWith(homePath)) {
return `~${nodepath.sep}${nodepath.relative(homePath, file)}`;
} else {
Expand Down
5 changes: 5 additions & 0 deletions src/client/common/utils/localize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,11 @@ export namespace DataScience {
export const kernelCategoryForPyEnv = localize('jupyter.kernel.category.pyenv', 'PyEnv Env');
export const kernelCategoryForGlobal = localize('jupyter.kernel.category.global', 'Global Env');
export const kernelCategoryForVirtual = localize('jupyter.kernel.category.virtual', 'Virtual Env');

export const fileSeemsToBeInterferingWithKernelStartup = localize(
'DataScience.fileSeemsToBeInterferingWithKernelStartup',
"The file '{0}' seems to be overriding built in modules and interfering with the startup of the kernel. Consider renaming the file and starting the kernel again.."
);
}

// Skip using vscode-nls and instead just compute our strings based on key values. Key values
Expand Down
Loading

0 comments on commit fc6808b

Please sign in to comment.