@krassowski/jupyterlab-lsp
Version:
Language Server Protocol integration for JupyterLab
243 lines (193 loc) • 8.08 kB
text/typescript
import { expect } from 'chai';
import { ReversibleOverridesMap } from '../../overrides/maps';
import { overrides } from './overrides';
const CELL_MAGIC_EXISTS = `%%MAGIC
some text
`;
const CELL_MAGIC_WITH_DOCSTRINGS = `%%MAGIC
text
"""a docstring"""
'''a less common docstring'''
'single quotes'
"double quotes"
text
`;
const ESCAPED_TEXT_WITH_DOCSTRINGS = `text
\\"\\"\\"a docstring\\"\\"\\"
'''a less common docstring'''
'single quotes'
"double quotes"
text
`;
const NO_CELL_MAGIC = `%MAGIC
some text
%%MAGIC
some text
`;
const LINE_MAGIC_WITH_SPACE = `%MAGIC line = dd`;
describe('Default IPython overrides', () => {
describe('IPython cell magics', () => {
let cell_magics_map = new ReversibleOverridesMap(
overrides.filter(override => override.scope == 'cell')
);
it('overrides cell magics', () => {
let override = cell_magics_map.override_for(CELL_MAGIC_EXISTS)!;
expect(override).to.equal(
'get_ipython().run_cell_magic("MAGIC", "", """some text\n""")'
);
let reverse = cell_magics_map.reverse.override_for(override);
expect(reverse).to.equal(CELL_MAGIC_EXISTS);
});
it('works for empty cells', () => {
// those are not correct syntax, but will happen when users are in the process of writing
const cell_magic_with_args = '%%MAGIC\n';
let override = cell_magics_map.override_for(cell_magic_with_args)!;
expect(override).to.equal(
'get_ipython().run_cell_magic("MAGIC", "", """""")'
);
let reverse = cell_magics_map.reverse.override_for(override);
expect(reverse).to.equal(cell_magic_with_args);
});
it('escapes arguments in the first line', () => {
const cell_magic_with_args = '%%MAGIC "arg in quotes"\ntext';
let override = cell_magics_map.override_for(cell_magic_with_args)!;
expect(override).to.equal(
'get_ipython().run_cell_magic("MAGIC", " \\"arg in quotes\\"", """text""")'
);
let reverse = cell_magics_map.reverse.override_for(override);
expect(reverse).to.equal(cell_magic_with_args);
});
it('escapes docstrings properly', () => {
let override = cell_magics_map.override_for(CELL_MAGIC_WITH_DOCSTRINGS)!;
expect(override).to.equal(
'get_ipython().run_cell_magic("MAGIC", "", """' +
ESCAPED_TEXT_WITH_DOCSTRINGS +
'""")'
);
let reverse = cell_magics_map.reverse.override_for(override);
expect(reverse).to.equal(CELL_MAGIC_WITH_DOCSTRINGS);
});
it('does not override cell-magic-like constructs', () => {
let override = cell_magics_map.override_for(NO_CELL_MAGIC);
expect(override).to.equal(null);
override = cell_magics_map.override_for(LINE_MAGIC_WITH_SPACE);
expect(override).to.equal(null);
});
});
describe('IPython line magics', () => {
let line_magics_map = new ReversibleOverridesMap(
overrides.filter(override => override.scope == 'line')
);
it('overrides line magics', () => {
let override = line_magics_map.override_for(LINE_MAGIC_WITH_SPACE)!;
expect(override).to.equal(
'get_ipython().run_line_magic("MAGIC", " line = dd")'
);
let reverse = line_magics_map.reverse.override_for(override);
expect(reverse).to.equal(LINE_MAGIC_WITH_SPACE);
});
it('overrides x =%ls and x = %ls', () => {
// this is a corner-case as described in
// https://github.com/jupyter-lsp/jupyterlab-lsp/issues/281#issuecomment-645286076
let override = line_magics_map.override_for('x =%ls');
expect(override).to.equal('x =get_ipython().run_line_magic("ls", "")');
override = line_magics_map.override_for('x = %ls');
expect(override).to.equal('x = get_ipython().run_line_magic("ls", "")');
});
it('does not override line-magic-like constructs', () => {
let override = line_magics_map.override_for('list("%")');
expect(override).to.equal(null);
override = line_magics_map.override_for('list(" %test")');
expect(override).to.equal(null);
});
it('does not override modulo operators', () => {
let override = line_magics_map.override_for('3 % 2');
expect(override).to.equal(null);
override = line_magics_map.override_for('3%2');
expect(override).to.equal(null);
});
it('escapes arguments', () => {
let line_magic_with_args = '%MAGIC "arg"';
let override = line_magics_map.override_for(line_magic_with_args)!;
expect(override).to.equal(
'get_ipython().run_line_magic("MAGIC", " \\"arg\\"")'
);
let reverse = line_magics_map.reverse.override_for(override);
expect(reverse).to.equal(line_magic_with_args);
line_magic_with_args = '%MAGIC "arg\\"';
override = line_magics_map.override_for(line_magic_with_args)!;
expect(override).to.equal(
'get_ipython().run_line_magic("MAGIC", " \\"arg\\\\\\"")'
);
reverse = line_magics_map.reverse.override_for(override);
expect(reverse).to.equal(line_magic_with_args);
});
it('overrides shell commands', () => {
let override = line_magics_map.override_for('!ls -o')!;
expect(override).to.equal('get_ipython().getoutput("ls -o")')!;
let reverse = line_magics_map.reverse.override_for(override);
expect(reverse).to.equal('!ls -o');
});
it('overrides shell commands assignments: x =!ls and x = !ls', () => {
let override = line_magics_map.override_for('x =!ls');
expect(override).to.equal('x =get_ipython().getoutput("ls")');
override = line_magics_map.override_for('x = !ls');
expect(override).to.equal('x = get_ipython().getoutput("ls")');
});
it('does not override shell-like constructs', () => {
let override = line_magics_map.override_for('"!ls"');
expect(override).to.equal(null);
});
it('does not override != comparisons', () => {
let override = line_magics_map.override_for('1 != None');
expect(override).to.equal(null);
});
});
describe('IPython help line magics', () => {
let line_magics_map = new ReversibleOverridesMap(
overrides.filter(override => override.scope == 'line')
);
it('overrides pinfo', () => {
let override = line_magics_map.override_for('?int')!;
expect(override).to.equal("get_ipython().run_line_magic('pinfo', 'int')");
let reverse = line_magics_map.reverse.override_for(override);
expect(reverse).to.equal('?int');
override = line_magics_map.override_for('int?')!;
expect(override).to.equal(
"get_ipython().run_line_magic('pinfo', 'int')"
);
reverse = line_magics_map.reverse.override_for(override);
expect(reverse).to.equal('int?');
});
it('overrides pinfo2', () => {
let override = line_magics_map.override_for('??int')!;
expect(override).to.equal(
"get_ipython().run_line_magic('pinfo2', 'int')"
);
let reverse = line_magics_map.reverse.override_for(override);
expect(reverse).to.equal('??int');
override = line_magics_map.override_for('int??')!;
expect(override).to.equal(
"get_ipython().run_line_magic('pinfo2', 'int')"
);
reverse = line_magics_map.reverse.override_for(override);
expect(reverse).to.equal('int??');
override = line_magics_map.override_for('some_func??')!;
expect(override).to.equal(
"get_ipython().run_line_magic('pinfo2', 'some_func')"
);
reverse = line_magics_map.reverse.override_for(override);
expect(reverse).to.equal('some_func??');
});
it('does not override standalone question marks', () => {
let override = line_magics_map.override_for("'q?'");
expect(override).to.equal(null);
override = line_magics_map.override_for('#?');
expect(override).to.equal(null);
override = line_magics_map.override_for("?q'");
expect(override).to.equal(null);
override = line_magics_map.override_for("?#'");
expect(override).to.equal(null);
});
});
});