mirror of
https://github.com/microsoft/pyright.git
synced 2024-07-07 04:26:31 +03:00
Create test for virtual environment (#6007)
* Create test for virtual environment * Figure out why python path test is failing * Eliminate quotes on venv_path * Actually set the python path * Try just printing path on windows * Print a different variable * Try other echo patterns * user powershell commands to append * Fix prettier
This commit is contained in:
parent
0e95e48650
commit
21aee77eb5
43
.github/workflows/validation.yml
vendored
43
.github/workflows/validation.yml
vendored
|
@ -2,6 +2,7 @@ name: 'Validation'
|
|||
|
||||
env:
|
||||
NODE_VERSION: '16' # Shipped with VS Code.
|
||||
PYTHON_VERSION: 3.11
|
||||
|
||||
on:
|
||||
push:
|
||||
|
@ -107,6 +108,48 @@ jobs:
|
|||
run: npm test
|
||||
working-directory: packages/pyright-internal
|
||||
|
||||
# Install python so we can create a VENV for tests
|
||||
- name: Use Python ${{env.PYTHON_VERSION}}
|
||||
uses: actions/setup-python@v4
|
||||
id: install_python
|
||||
with:
|
||||
python-version: ${{env.PYTHON_VERSION}}
|
||||
|
||||
- name: Create Venv
|
||||
run: |
|
||||
${{ steps.install_python.outputs.python-path }} -m venv .venv
|
||||
|
||||
- name: Activate and install pytest (linux)
|
||||
if: runner.os != 'Windows'
|
||||
run: |
|
||||
source .venv/bin/activate
|
||||
python -m pip install pytest
|
||||
python -c "import sys;print('python_venv_path=' + sys.executable)" >> $GITHUB_ENV
|
||||
|
||||
- name: Activate and install pytest (windows)
|
||||
if: runner.os == 'Windows'
|
||||
run: |
|
||||
.venv\scripts\activate
|
||||
python -m pip install pytest
|
||||
python -c "import sys;print('python_venv_path=' + sys.executable)" | Out-File -FilePath $env:GITHUB_ENV -Append
|
||||
|
||||
- name: Echo python_venv_path
|
||||
run: |
|
||||
echo python_venv_path=${{env.python_venv_path}}
|
||||
|
||||
- name: Run import tests with venv
|
||||
env:
|
||||
CI_IMPORT_TEST_VENVPATH: '../../'
|
||||
CI_IMPORT_TEST_VENV: '.venv'
|
||||
run: npm run test:imports
|
||||
working-directory: packages/pyright-internal
|
||||
|
||||
- name: Run import tests with pythonpath
|
||||
env:
|
||||
CI_IMPORT_TEST_PYTHONPATH: ${{env.python_venv_path}}
|
||||
run: npm run test:imports
|
||||
working-directory: packages/pyright-internal
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
name: Build
|
||||
|
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -123,3 +123,6 @@ junit.xml
|
|||
# OS files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Potential venv
|
||||
.venv
|
|
@ -12,7 +12,8 @@
|
|||
"build": "tsc",
|
||||
"clean": "shx rm -rf ./dist ./out",
|
||||
"test": "jest --forceExit",
|
||||
"test:coverage": "jest --forceExit --reporters=jest-junit --reporters=default --coverage --coverageReporters=cobertura --coverageReporters=html --coverageReporters=json"
|
||||
"test:coverage": "jest --forceExit --reporters=jest-junit --reporters=default --coverage --coverageReporters=cobertura --coverageReporters=html --coverageReporters=json",
|
||||
"test:imports": "jest importResolver.test --forceExit --runInBand"
|
||||
},
|
||||
"dependencies": {
|
||||
"@iarna/toml": "2.2.5",
|
||||
|
|
|
@ -6,18 +6,30 @@
|
|||
|
||||
import assert from 'assert';
|
||||
|
||||
import { Dirent, ReadStream, WriteStream } from 'fs';
|
||||
import { ImportResolver } from '../analyzer/importResolver';
|
||||
import { ConfigOptions } from '../common/configOptions';
|
||||
import { FileSystem, MkDirOptions, Stats, TmpfileOptions } from '../common/fileSystem';
|
||||
import { FileWatcher, FileWatcherEventHandler } from '../common/fileWatcher';
|
||||
import { FullAccessHost } from '../common/fullAccessHost';
|
||||
import { Host } from '../common/host';
|
||||
import { lib, sitePackages, typeshedFallback } from '../common/pathConsts';
|
||||
import { combinePaths, getDirectoryPath, normalizeSlashes } from '../common/pathUtils';
|
||||
import { createFromRealFileSystem } from '../common/realFileSystem';
|
||||
import { ServiceProvider } from '../common/serviceProvider';
|
||||
import { createServiceProvider } from '../common/serviceProviderExtensions';
|
||||
import { PyrightFileSystem } from '../pyrightFileSystem';
|
||||
import { TestAccessHost } from './harness/testAccessHost';
|
||||
import { TestFileSystem } from './harness/vfs/filesystem';
|
||||
import { ServiceProvider } from '../common/serviceProvider';
|
||||
import { createServiceProvider } from '../common/serviceProviderExtensions';
|
||||
|
||||
const libraryRoot = combinePaths(normalizeSlashes('/'), lib, sitePackages);
|
||||
|
||||
function usingTrueVenv() {
|
||||
return process.env.CI_IMPORT_TEST_VENVPATH !== undefined || process.env.CI_IMPORT_TEST_PYTHONPATH !== undefined;
|
||||
}
|
||||
|
||||
if (!usingTrueVenv()) {
|
||||
describe('Import tests that cannot run in a true venv', () => {
|
||||
test('partial stub file exists', () => {
|
||||
const files = [
|
||||
{
|
||||
|
@ -39,7 +51,8 @@ test('partial stub file exists', () => {
|
|||
assert(importResult.isStubFile);
|
||||
assert.strictEqual(
|
||||
1,
|
||||
importResult.resolvedPaths.filter((f) => f === combinePaths(libraryRoot, 'myLib', 'partialStub.pyi')).length
|
||||
importResult.resolvedPaths.filter((f) => f === combinePaths(libraryRoot, 'myLib', 'partialStub.pyi'))
|
||||
.length
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -64,10 +77,187 @@ test('partial stub __init__ exists', () => {
|
|||
assert(importResult.isStubFile);
|
||||
assert.strictEqual(
|
||||
1,
|
||||
importResult.resolvedPaths.filter((f) => f === combinePaths(libraryRoot, 'myLib', '__init__.pyi')).length
|
||||
importResult.resolvedPaths.filter((f) => f === combinePaths(libraryRoot, 'myLib', '__init__.pyi'))
|
||||
.length
|
||||
);
|
||||
});
|
||||
|
||||
test('stub package', () => {
|
||||
const files = [
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'myLib-stubs', 'stub.pyi'),
|
||||
content: '# empty',
|
||||
},
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'myLib-stubs', '__init__.pyi'),
|
||||
content: '# empty',
|
||||
},
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'myLib', 'partialStub.py'),
|
||||
content: 'def test(): pass',
|
||||
},
|
||||
];
|
||||
|
||||
// If fully typed stub package exists, that wins over the real package.
|
||||
const importResult = getImportResult(files, ['myLib', 'partialStub']);
|
||||
assert(!importResult.isImportFound);
|
||||
});
|
||||
|
||||
test('partial stub package in typing folder', () => {
|
||||
const typingFolder = combinePaths(normalizeSlashes('/'), 'typing');
|
||||
const files = [
|
||||
{
|
||||
path: combinePaths(typingFolder, 'myLib-stubs', '__init__.pyi'),
|
||||
content: 'def test(): ...',
|
||||
},
|
||||
{
|
||||
path: combinePaths(typingFolder, 'myLib-stubs', 'py.typed'),
|
||||
content: 'partial\n',
|
||||
},
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'myLib', '__init__.py'),
|
||||
content: 'def test(): pass',
|
||||
},
|
||||
];
|
||||
|
||||
const importResult = getImportResult(files, ['myLib'], (c) => (c.stubPath = typingFolder));
|
||||
assert(importResult.isImportFound);
|
||||
assert(importResult.isStubFile);
|
||||
assert.strictEqual(
|
||||
1,
|
||||
importResult.resolvedPaths.filter((f) => f === combinePaths(libraryRoot, 'myLib', '__init__.pyi'))
|
||||
.length
|
||||
);
|
||||
});
|
||||
|
||||
test('typeshed folder', () => {
|
||||
const typeshedFolder = combinePaths(normalizeSlashes('/'), 'ts');
|
||||
const files = [
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'myLib-stubs', '__init__.pyi'),
|
||||
content: 'def test(): ...',
|
||||
},
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'myLib-stubs', 'py.typed'),
|
||||
content: 'partial\n',
|
||||
},
|
||||
{
|
||||
path: combinePaths(typeshedFolder, 'stubs', 'myLibPackage', 'myLib.pyi'),
|
||||
content: '# empty',
|
||||
},
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'myLib', '__init__.py'),
|
||||
content: 'def test(): pass',
|
||||
},
|
||||
];
|
||||
|
||||
// Stub packages win over typeshed.
|
||||
const importResult = getImportResult(files, ['myLib'], (c) => (c.typeshedPath = typeshedFolder));
|
||||
assert(importResult.isImportFound);
|
||||
assert(importResult.isStubFile);
|
||||
assert.strictEqual(
|
||||
1,
|
||||
importResult.resolvedPaths.filter((f) => f === combinePaths(libraryRoot, 'myLib', '__init__.pyi'))
|
||||
.length
|
||||
);
|
||||
});
|
||||
|
||||
test('typeshed fallback folder', () => {
|
||||
const files = [
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'myLib-stubs', '__init__.pyi'),
|
||||
content: 'def test(): ...',
|
||||
},
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'myLib-stubs', 'py.typed'),
|
||||
content: 'partial\n',
|
||||
},
|
||||
{
|
||||
path: combinePaths('/', typeshedFallback, 'stubs', 'myLibPackage', 'myLib.pyi'),
|
||||
content: '# empty',
|
||||
},
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'myLib', '__init__.py'),
|
||||
content: 'def test(): pass',
|
||||
},
|
||||
];
|
||||
|
||||
// Stub packages win over typeshed.
|
||||
const importResult = getImportResult(files, ['myLib']);
|
||||
assert(importResult.isImportFound);
|
||||
assert(importResult.isStubFile);
|
||||
assert.strictEqual(
|
||||
1,
|
||||
importResult.resolvedPaths.filter((f) => f === combinePaths(libraryRoot, 'myLib', '__init__.pyi'))
|
||||
.length
|
||||
);
|
||||
});
|
||||
|
||||
test('py.typed file', () => {
|
||||
const files = [
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'myLib-stubs', '__init__.pyi'),
|
||||
content: 'def test(): ...',
|
||||
},
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'myLib-stubs', 'py.typed'),
|
||||
content: 'partial\n',
|
||||
},
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'myLib', '__init__.py'),
|
||||
content: 'def test(): pass',
|
||||
},
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'myLib', 'py.typed'),
|
||||
content: '# typed',
|
||||
},
|
||||
];
|
||||
|
||||
// Partial stub package always overrides original package.
|
||||
const importResult = getImportResult(files, ['myLib']);
|
||||
assert(importResult.isImportFound);
|
||||
assert(importResult.isStubFile);
|
||||
});
|
||||
|
||||
test('py.typed library', () => {
|
||||
const files = [
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'os', '__init__.py'),
|
||||
content: 'def test(): ...',
|
||||
},
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'os', 'py.typed'),
|
||||
content: '',
|
||||
},
|
||||
{
|
||||
path: combinePaths('/', typeshedFallback, 'stubs', 'os', 'os', '__init__.pyi'),
|
||||
content: '# empty',
|
||||
},
|
||||
];
|
||||
|
||||
const importResult = getImportResult(files, ['os']);
|
||||
assert(importResult.isImportFound);
|
||||
assert.strictEqual(files[0].path, importResult.resolvedPaths[importResult.resolvedPaths.length - 1]);
|
||||
});
|
||||
|
||||
test('import side by side file sub under lib folder', () => {
|
||||
const files = [
|
||||
{
|
||||
path: combinePaths('/lib/site-packages/myLib', 'file1.py'),
|
||||
content: 'def test1(): ...',
|
||||
},
|
||||
{
|
||||
path: combinePaths('/lib/site-packages/myLib', 'file2.py'),
|
||||
content: 'def test2(): ...',
|
||||
},
|
||||
];
|
||||
|
||||
const importResult = getImportResult(files, ['file1']);
|
||||
assert(!importResult.isImportFound);
|
||||
});
|
||||
});
|
||||
}
|
||||
describe('Import tests that can run with or without a true venv', () => {
|
||||
test('side by side files', () => {
|
||||
const myFile = combinePaths('src', 'file.py');
|
||||
const files = [
|
||||
|
@ -137,27 +327,6 @@ test('side by side files', () => {
|
|||
assert.strictEqual(1, partialStubResult.resolvedPaths.filter((f) => f === partialStubFile).length);
|
||||
});
|
||||
|
||||
test('stub package', () => {
|
||||
const files = [
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'myLib-stubs', 'stub.pyi'),
|
||||
content: '# empty',
|
||||
},
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'myLib-stubs', '__init__.pyi'),
|
||||
content: '# empty',
|
||||
},
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'myLib', 'partialStub.py'),
|
||||
content: 'def test(): pass',
|
||||
},
|
||||
];
|
||||
|
||||
// If fully typed stub package exists, that wins over the real package.
|
||||
const importResult = getImportResult(files, ['myLib', 'partialStub']);
|
||||
assert(!importResult.isImportFound);
|
||||
});
|
||||
|
||||
test('stub namespace package', () => {
|
||||
const files = [
|
||||
{
|
||||
|
@ -211,140 +380,6 @@ test('stub in typing folder over partial stub package', () => {
|
|||
);
|
||||
});
|
||||
|
||||
test('partial stub package in typing folder', () => {
|
||||
const typingFolder = combinePaths(normalizeSlashes('/'), 'typing');
|
||||
const files = [
|
||||
{
|
||||
path: combinePaths(typingFolder, 'myLib-stubs', '__init__.pyi'),
|
||||
content: 'def test(): ...',
|
||||
},
|
||||
{
|
||||
path: combinePaths(typingFolder, 'myLib-stubs', 'py.typed'),
|
||||
content: 'partial\n',
|
||||
},
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'myLib', '__init__.py'),
|
||||
content: 'def test(): pass',
|
||||
},
|
||||
];
|
||||
|
||||
const importResult = getImportResult(files, ['myLib'], (c) => (c.stubPath = typingFolder));
|
||||
assert(importResult.isImportFound);
|
||||
assert(importResult.isStubFile);
|
||||
assert.strictEqual(
|
||||
1,
|
||||
importResult.resolvedPaths.filter((f) => f === combinePaths(libraryRoot, 'myLib', '__init__.pyi')).length
|
||||
);
|
||||
});
|
||||
|
||||
test('typeshed folder', () => {
|
||||
const typeshedFolder = combinePaths(normalizeSlashes('/'), 'ts');
|
||||
const files = [
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'myLib-stubs', '__init__.pyi'),
|
||||
content: 'def test(): ...',
|
||||
},
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'myLib-stubs', 'py.typed'),
|
||||
content: 'partial\n',
|
||||
},
|
||||
{
|
||||
path: combinePaths(typeshedFolder, 'stubs', 'myLibPackage', 'myLib.pyi'),
|
||||
content: '# empty',
|
||||
},
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'myLib', '__init__.py'),
|
||||
content: 'def test(): pass',
|
||||
},
|
||||
];
|
||||
|
||||
// Stub packages win over typeshed.
|
||||
const importResult = getImportResult(files, ['myLib'], (c) => (c.typeshedPath = typeshedFolder));
|
||||
assert(importResult.isImportFound);
|
||||
assert(importResult.isStubFile);
|
||||
assert.strictEqual(
|
||||
1,
|
||||
importResult.resolvedPaths.filter((f) => f === combinePaths(libraryRoot, 'myLib', '__init__.pyi')).length
|
||||
);
|
||||
});
|
||||
|
||||
test('typeshed fallback folder', () => {
|
||||
const files = [
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'myLib-stubs', '__init__.pyi'),
|
||||
content: 'def test(): ...',
|
||||
},
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'myLib-stubs', 'py.typed'),
|
||||
content: 'partial\n',
|
||||
},
|
||||
{
|
||||
path: combinePaths('/', typeshedFallback, 'stubs', 'myLibPackage', 'myLib.pyi'),
|
||||
content: '# empty',
|
||||
},
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'myLib', '__init__.py'),
|
||||
content: 'def test(): pass',
|
||||
},
|
||||
];
|
||||
|
||||
// Stub packages win over typeshed.
|
||||
const importResult = getImportResult(files, ['myLib']);
|
||||
assert(importResult.isImportFound);
|
||||
assert(importResult.isStubFile);
|
||||
assert.strictEqual(
|
||||
1,
|
||||
importResult.resolvedPaths.filter((f) => f === combinePaths(libraryRoot, 'myLib', '__init__.pyi')).length
|
||||
);
|
||||
});
|
||||
|
||||
test('py.typed file', () => {
|
||||
const files = [
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'myLib-stubs', '__init__.pyi'),
|
||||
content: 'def test(): ...',
|
||||
},
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'myLib-stubs', 'py.typed'),
|
||||
content: 'partial\n',
|
||||
},
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'myLib', '__init__.py'),
|
||||
content: 'def test(): pass',
|
||||
},
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'myLib', 'py.typed'),
|
||||
content: '# typed',
|
||||
},
|
||||
];
|
||||
|
||||
// Partial stub package always overrides original package.
|
||||
const importResult = getImportResult(files, ['myLib']);
|
||||
assert(importResult.isImportFound);
|
||||
assert(importResult.isStubFile);
|
||||
});
|
||||
|
||||
test('py.typed library', () => {
|
||||
const files = [
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'os', '__init__.py'),
|
||||
content: 'def test(): ...',
|
||||
},
|
||||
{
|
||||
path: combinePaths(libraryRoot, 'os', 'py.typed'),
|
||||
content: '',
|
||||
},
|
||||
{
|
||||
path: combinePaths('/', typeshedFallback, 'stubs', 'os', 'os', '__init__.pyi'),
|
||||
content: '# empty',
|
||||
},
|
||||
];
|
||||
|
||||
const importResult = getImportResult(files, ['os']);
|
||||
assert(importResult.isImportFound);
|
||||
assert.strictEqual(files[0].path, importResult.resolvedPaths[importResult.resolvedPaths.length - 1]);
|
||||
});
|
||||
|
||||
test('non py.typed library', () => {
|
||||
const files = [
|
||||
{
|
||||
|
@ -394,8 +429,14 @@ test('multiple typeshedFallback', () => {
|
|||
);
|
||||
const importRoots = importResolver.getImportRoots(configOptions.getDefaultExecEnvironment());
|
||||
|
||||
assert.strictEqual(1, importRoots.filter((f) => f === combinePaths('/', typeshedFallback, 'stubs', 'aLib')).length);
|
||||
assert.strictEqual(1, importRoots.filter((f) => f === combinePaths('/', typeshedFallback, 'stubs', 'bLib')).length);
|
||||
assert.strictEqual(
|
||||
1,
|
||||
importRoots.filter((f) => f === combinePaths('/', typeshedFallback, 'stubs', 'aLib')).length
|
||||
);
|
||||
assert.strictEqual(
|
||||
1,
|
||||
importRoots.filter((f) => f === combinePaths('/', typeshedFallback, 'stubs', 'bLib')).length
|
||||
);
|
||||
});
|
||||
|
||||
test('import side by side file root', () => {
|
||||
|
@ -472,22 +513,6 @@ test('import file sub under containing folder', () => {
|
|||
);
|
||||
});
|
||||
|
||||
test('import side by side file sub under lib folder', () => {
|
||||
const files = [
|
||||
{
|
||||
path: combinePaths('/lib/site-packages/myLib', 'file1.py'),
|
||||
content: 'def test1(): ...',
|
||||
},
|
||||
{
|
||||
path: combinePaths('/lib/site-packages/myLib', 'file2.py'),
|
||||
content: 'def test2(): ...',
|
||||
},
|
||||
];
|
||||
|
||||
const importResult = getImportResult(files, ['file1']);
|
||||
assert(!importResult.isImportFound);
|
||||
});
|
||||
|
||||
test("don't walk up the root", () => {
|
||||
const files = [
|
||||
{
|
||||
|
@ -587,21 +612,72 @@ test('nested namespace package 4', () => {
|
|||
});
|
||||
assert(!importResult.isImportFound);
|
||||
});
|
||||
});
|
||||
|
||||
if (usingTrueVenv()) {
|
||||
describe('Import tests that have to run with a venv', () => {
|
||||
test('venv can find imports', () => {
|
||||
const files = [
|
||||
{
|
||||
path: combinePaths('/', 'file1.py'),
|
||||
content: 'import pytest',
|
||||
},
|
||||
];
|
||||
|
||||
const importResult = getImportResult(files, ['pytest']);
|
||||
assert(importResult.isImportFound, `Import not found: ${importResult.importFailureInfo?.join('\n')}`);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getImportResult(
|
||||
files: { path: string; content: string }[],
|
||||
nameParts: string[],
|
||||
setup?: (c: ConfigOptions) => void
|
||||
) {
|
||||
setup =
|
||||
const defaultHostFactory = (sp: ServiceProvider) => new TestAccessHost(sp.fs().getModulePath(), [libraryRoot]);
|
||||
const defaultSetup =
|
||||
setup ??
|
||||
((c) => {
|
||||
/* empty */
|
||||
});
|
||||
const defaultSpFactory = (files: { path: string; content: string }[]) => createServiceProviderFromFiles(files);
|
||||
|
||||
const sp = createServiceProviderFromFiles(files);
|
||||
// Use environment variables to determine how to create a host and how to modify the config options.
|
||||
// These are set in the CI to test imports with different options.
|
||||
let hostFactory: (sp: ServiceProvider) => Host = defaultHostFactory;
|
||||
let configModifier = defaultSetup;
|
||||
let spFactory = defaultSpFactory;
|
||||
|
||||
if (process.env.CI_IMPORT_TEST_VENVPATH) {
|
||||
configModifier = (c: ConfigOptions) => {
|
||||
defaultSetup(c);
|
||||
c.venvPath = process.env.CI_IMPORT_TEST_VENVPATH;
|
||||
c.venv = process.env.CI_IMPORT_TEST_VENV;
|
||||
};
|
||||
spFactory = (files: { path: string; content: string }[]) => createServiceProviderWithCombinedFs(files);
|
||||
} else if (process.env.CI_IMPORT_TEST_PYTHONPATH) {
|
||||
configModifier = (c: ConfigOptions) => {
|
||||
defaultSetup(c);
|
||||
c.pythonPath = process.env.CI_IMPORT_TEST_PYTHONPATH;
|
||||
};
|
||||
hostFactory = (sp: ServiceProvider) => new TruePythonTestAccessHost();
|
||||
spFactory = (files: { path: string; content: string }[]) => createServiceProviderWithCombinedFs(files);
|
||||
}
|
||||
|
||||
return getImportResultImpl(files, nameParts, spFactory, configModifier, hostFactory);
|
||||
}
|
||||
|
||||
function getImportResultImpl(
|
||||
files: { path: string; content: string }[],
|
||||
nameParts: string[],
|
||||
spFactory: (files: { path: string; content: string }[]) => ServiceProvider,
|
||||
configModifier: (c: ConfigOptions) => void,
|
||||
hostFactory: (sp: ServiceProvider) => Host
|
||||
) {
|
||||
const sp = spFactory(files);
|
||||
const configOptions = new ConfigOptions(normalizeSlashes('/'));
|
||||
setup(configOptions);
|
||||
configModifier(configOptions);
|
||||
|
||||
const file = files.length > 0 ? files[files.length - 1].path : combinePaths('src', 'file.py');
|
||||
if (files.length === 0) {
|
||||
|
@ -611,11 +687,7 @@ function getImportResult(
|
|||
});
|
||||
}
|
||||
|
||||
const importResolver = new ImportResolver(
|
||||
sp,
|
||||
configOptions,
|
||||
new TestAccessHost(sp.fs().getModulePath(), [libraryRoot])
|
||||
);
|
||||
const importResolver = new ImportResolver(sp, configOptions, hostFactory(sp));
|
||||
const importResult = importResolver.resolveImport(file, configOptions.findExecEnvironment(file), {
|
||||
leadingDots: 0,
|
||||
nameParts: nameParts,
|
||||
|
@ -624,8 +696,7 @@ function getImportResult(
|
|||
|
||||
return importResult;
|
||||
}
|
||||
|
||||
function createFileSystem(files: { path: string; content: string }[]): PyrightFileSystem {
|
||||
function createTestFileSystem(files: { path: string; content: string }[]): TestFileSystem {
|
||||
const fs = new TestFileSystem(/* ignoreCase */ false, { cwd: normalizeSlashes('/') });
|
||||
|
||||
for (const file of files) {
|
||||
|
@ -636,10 +707,158 @@ function createFileSystem(files: { path: string; content: string }[]): PyrightFi
|
|||
fs.writeFileSync(path, file.content);
|
||||
}
|
||||
|
||||
return new PyrightFileSystem(fs);
|
||||
return fs;
|
||||
}
|
||||
|
||||
function createServiceProviderFromFiles(files: { path: string; content: string }[]): ServiceProvider {
|
||||
const fs = createFileSystem(files);
|
||||
const fs = new PyrightFileSystem(createTestFileSystem(files));
|
||||
return createServiceProvider(fs);
|
||||
}
|
||||
|
||||
function createServiceProviderWithCombinedFs(files: { path: string; content: string }[]): ServiceProvider {
|
||||
const fs = new PyrightFileSystem(new CombinedFileSystem(createTestFileSystem(files)));
|
||||
return createServiceProvider(fs);
|
||||
}
|
||||
|
||||
class TruePythonTestAccessHost extends FullAccessHost {
|
||||
constructor() {
|
||||
super(createFromRealFileSystem());
|
||||
}
|
||||
}
|
||||
|
||||
class CombinedFileSystem implements FileSystem {
|
||||
private _realFS = createFromRealFileSystem();
|
||||
|
||||
constructor(private _testFS: FileSystem) {}
|
||||
|
||||
mkdirSync(path: string, options?: MkDirOptions | undefined): void {
|
||||
this._testFS.mkdirSync(path, options);
|
||||
}
|
||||
|
||||
writeFileSync(path: string, data: string | Buffer, encoding: BufferEncoding | null): void {
|
||||
this._testFS.writeFileSync(path, data, encoding);
|
||||
}
|
||||
|
||||
unlinkSync(path: string): void {
|
||||
this._testFS.unlinkSync(path);
|
||||
}
|
||||
|
||||
rmdirSync(path: string): void {
|
||||
this._testFS.rmdirSync(path);
|
||||
}
|
||||
|
||||
createFileSystemWatcher(paths: string[], listener: FileWatcherEventHandler): FileWatcher {
|
||||
return this._testFS.createFileSystemWatcher(paths, listener);
|
||||
}
|
||||
|
||||
createReadStream(path: string): ReadStream {
|
||||
return this._testFS.createReadStream(path);
|
||||
}
|
||||
|
||||
createWriteStream(path: string): WriteStream {
|
||||
return this._testFS.createWriteStream(path);
|
||||
}
|
||||
|
||||
copyFileSync(src: string, dst: string): void {
|
||||
this._testFS.copyFileSync(src, dst);
|
||||
}
|
||||
|
||||
tmpdir(): string {
|
||||
return this._testFS.tmpdir();
|
||||
}
|
||||
|
||||
tmpfile(options?: TmpfileOptions | undefined): string {
|
||||
return this._testFS.tmpfile(options);
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this._testFS.dispose();
|
||||
}
|
||||
|
||||
existsSync(path: string): boolean {
|
||||
return this._testFS.existsSync(path) || this._realFS.existsSync(path);
|
||||
}
|
||||
|
||||
chdir(path: string): void {
|
||||
this._testFS.chdir(path);
|
||||
}
|
||||
|
||||
readdirEntriesSync(path: string): Dirent[] {
|
||||
if (this._testFS.existsSync(path)) {
|
||||
return this._testFS.readdirEntriesSync(path);
|
||||
}
|
||||
return this._realFS.readdirEntriesSync(path);
|
||||
}
|
||||
|
||||
readdirSync(path: string): string[] {
|
||||
if (this._testFS.existsSync(path)) {
|
||||
return this._testFS.readdirSync(path);
|
||||
}
|
||||
return this._realFS.readdirSync(path);
|
||||
}
|
||||
|
||||
readFileSync(path: string, encoding?: null): Buffer;
|
||||
readFileSync(path: string, encoding: BufferEncoding): string;
|
||||
readFileSync(path: string, encoding?: BufferEncoding | null): string | Buffer;
|
||||
readFileSync(path: string, encoding: BufferEncoding | null = null) {
|
||||
if (this._testFS.existsSync(path)) {
|
||||
return this._testFS.readFileSync(path, encoding);
|
||||
}
|
||||
return this._realFS.readFileSync(path, encoding);
|
||||
}
|
||||
|
||||
statSync(path: string): Stats {
|
||||
if (this._testFS.existsSync(path)) {
|
||||
return this._testFS.statSync(path);
|
||||
}
|
||||
return this._realFS.statSync(path);
|
||||
}
|
||||
|
||||
realpathSync(path: string): string {
|
||||
if (this._testFS.existsSync(path)) {
|
||||
return this._testFS.realpathSync(path);
|
||||
}
|
||||
return this._realFS.realpathSync(path);
|
||||
}
|
||||
|
||||
getModulePath(): string {
|
||||
return this._testFS.getModulePath();
|
||||
}
|
||||
|
||||
readFile(path: string): Promise<Buffer> {
|
||||
if (this._testFS.existsSync(path)) {
|
||||
return this._testFS.readFile(path);
|
||||
}
|
||||
return this._realFS.readFile(path);
|
||||
}
|
||||
|
||||
readFileText(path: string, encoding?: BufferEncoding | undefined): Promise<string> {
|
||||
if (this._testFS.existsSync(path)) {
|
||||
return this._testFS.readFileText(path, encoding);
|
||||
}
|
||||
return this._realFS.readFileText(path, encoding);
|
||||
}
|
||||
|
||||
realCasePath(path: string): string {
|
||||
return this._testFS.realCasePath(path);
|
||||
}
|
||||
|
||||
isMappedFilePath(filepath: string): boolean {
|
||||
return this._testFS.isMappedFilePath(filepath);
|
||||
}
|
||||
|
||||
getOriginalFilePath(mappedFilePath: string): string {
|
||||
return this._testFS.getOriginalFilePath(mappedFilePath);
|
||||
}
|
||||
|
||||
getMappedFilePath(originalFilepath: string): string {
|
||||
return this._testFS.getMappedFilePath(originalFilepath);
|
||||
}
|
||||
|
||||
getUri(path: string): string {
|
||||
return this._testFS.getUri(path);
|
||||
}
|
||||
|
||||
isInZip(path: string): boolean {
|
||||
return this._testFS.isInZip(path);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user