@zzzen/pyright-internal 1.2.0-dev.20230924 → 1.2.0-dev.20231001

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/dist/analyzer/checker.js +4 -1
  2. package/dist/analyzer/checker.js.map +1 -1
  3. package/dist/analyzer/codeFlowEngine.js +7 -0
  4. package/dist/analyzer/codeFlowEngine.js.map +1 -1
  5. package/dist/analyzer/decorators.js +3 -0
  6. package/dist/analyzer/decorators.js.map +1 -1
  7. package/dist/analyzer/operations.js +4 -2
  8. package/dist/analyzer/operations.js.map +1 -1
  9. package/dist/analyzer/patternMatching.js +47 -16
  10. package/dist/analyzer/patternMatching.js.map +1 -1
  11. package/dist/analyzer/program.d.ts +2 -3
  12. package/dist/analyzer/program.js +6 -6
  13. package/dist/analyzer/program.js.map +1 -1
  14. package/dist/analyzer/service.d.ts +4 -4
  15. package/dist/analyzer/service.js +4 -18
  16. package/dist/analyzer/service.js.map +1 -1
  17. package/dist/analyzer/sourceFile.d.ts +3 -1
  18. package/dist/analyzer/sourceFile.js +9 -5
  19. package/dist/analyzer/sourceFile.js.map +1 -1
  20. package/dist/analyzer/typeEvaluator.js +64 -11
  21. package/dist/analyzer/typeEvaluator.js.map +1 -1
  22. package/dist/analyzer/typeUtils.d.ts +1 -0
  23. package/dist/analyzer/typeUtils.js +21 -2
  24. package/dist/analyzer/typeUtils.js.map +1 -1
  25. package/dist/analyzer/types.d.ts +1 -1
  26. package/dist/analyzer/types.js +6 -3
  27. package/dist/analyzer/types.js.map +1 -1
  28. package/dist/backgroundAnalysisBase.js +0 -22
  29. package/dist/backgroundAnalysisBase.js.map +1 -1
  30. package/dist/common/configOptions.d.ts +1 -0
  31. package/dist/common/configOptions.js +4 -0
  32. package/dist/common/configOptions.js.map +1 -1
  33. package/dist/common/diagnosticRules.d.ts +1 -0
  34. package/dist/common/diagnosticRules.js +1 -0
  35. package/dist/common/diagnosticRules.js.map +1 -1
  36. package/dist/common/extensibility.d.ts +9 -24
  37. package/dist/common/extensibility.js +1 -91
  38. package/dist/common/extensibility.js.map +1 -1
  39. package/dist/common/pathUtils.d.ts +3 -0
  40. package/dist/common/pathUtils.js +13 -8
  41. package/dist/common/pathUtils.js.map +1 -1
  42. package/dist/common/realFileSystem.js +1 -1
  43. package/dist/common/realFileSystem.js.map +1 -1
  44. package/dist/common/serviceProvider.d.ts +22 -3
  45. package/dist/common/serviceProvider.js +89 -9
  46. package/dist/common/serviceProvider.js.map +1 -1
  47. package/dist/common/serviceProviderExtensions.d.ts +4 -1
  48. package/dist/common/serviceProviderExtensions.js +4 -2
  49. package/dist/common/serviceProviderExtensions.js.map +1 -1
  50. package/dist/languageServerBase.js +0 -3
  51. package/dist/languageServerBase.js.map +1 -1
  52. package/dist/languageService/definitionProvider.d.ts +3 -2
  53. package/dist/languageService/definitionProvider.js +13 -10
  54. package/dist/languageService/definitionProvider.js.map +1 -1
  55. package/dist/languageService/documentSymbolCollector.js +16 -14
  56. package/dist/languageService/documentSymbolCollector.js.map +1 -1
  57. package/dist/languageService/hoverProvider.js +7 -7
  58. package/dist/languageService/hoverProvider.js.map +1 -1
  59. package/dist/localization/localize.d.ts +8 -1
  60. package/dist/localization/localize.js +4 -1
  61. package/dist/localization/localize.js.map +1 -1
  62. package/dist/localization/package.nls.cs.json +4 -1
  63. package/dist/localization/package.nls.de.json +4 -1
  64. package/dist/localization/package.nls.en-us.json +4 -1
  65. package/dist/localization/package.nls.es.json +4 -1
  66. package/dist/localization/package.nls.fr.json +4 -1
  67. package/dist/localization/package.nls.it.json +4 -1
  68. package/dist/localization/package.nls.ja.json +4 -1
  69. package/dist/localization/package.nls.ko.json +4 -1
  70. package/dist/localization/package.nls.pl.json +4 -1
  71. package/dist/localization/package.nls.pt-br.json +4 -1
  72. package/dist/localization/package.nls.qps-ploc.json +4 -1
  73. package/dist/localization/package.nls.ru.json +4 -1
  74. package/dist/localization/package.nls.tr.json +4 -1
  75. package/dist/localization/package.nls.zh-cn.json +4 -1
  76. package/dist/localization/package.nls.zh-tw.json +4 -1
  77. package/dist/tests/importResolver.test.js +654 -481
  78. package/dist/tests/importResolver.test.js.map +1 -1
  79. package/dist/tests/pathUtils.test.js +39 -1
  80. package/dist/tests/pathUtils.test.js.map +1 -1
  81. package/dist/tests/sourceFile.test.js +2 -1
  82. package/dist/tests/sourceFile.test.js.map +1 -1
  83. package/dist/tests/typeEvaluator2.test.js +3 -1
  84. package/dist/tests/typeEvaluator2.test.js.map +1 -1
  85. package/dist/tests/typeEvaluator3.test.js +7 -1
  86. package/dist/tests/typeEvaluator3.test.js.map +1 -1
  87. package/dist/tests/typeEvaluator4.test.js +1 -0
  88. package/dist/tests/typeEvaluator4.test.js.map +1 -1
  89. package/package.json +3 -2
@@ -11,498 +11,554 @@ Object.defineProperty(exports, "__esModule", { value: true });
11
11
  const assert_1 = __importDefault(require("assert"));
12
12
  const importResolver_1 = require("../analyzer/importResolver");
13
13
  const configOptions_1 = require("../common/configOptions");
14
+ const fullAccessHost_1 = require("../common/fullAccessHost");
14
15
  const pathConsts_1 = require("../common/pathConsts");
15
16
  const pathUtils_1 = require("../common/pathUtils");
17
+ const realFileSystem_1 = require("../common/realFileSystem");
18
+ const serviceProviderExtensions_1 = require("../common/serviceProviderExtensions");
16
19
  const pyrightFileSystem_1 = require("../pyrightFileSystem");
17
20
  const testAccessHost_1 = require("./harness/testAccessHost");
18
21
  const filesystem_1 = require("./harness/vfs/filesystem");
19
- const serviceProviderExtensions_1 = require("../common/serviceProviderExtensions");
20
22
  const libraryRoot = (0, pathUtils_1.combinePaths)((0, pathUtils_1.normalizeSlashes)('/'), pathConsts_1.lib, pathConsts_1.sitePackages);
21
- test('partial stub file exists', () => {
22
- const files = [
23
- {
24
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', 'partialStub.pyi'),
25
- content: 'def test(): ...',
26
- },
27
- {
28
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', 'py.typed'),
29
- content: 'partial\n',
30
- },
31
- {
32
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', 'partialStub.py'),
33
- content: 'def test(): pass',
34
- },
35
- ];
36
- const importResult = getImportResult(files, ['myLib', 'partialStub']);
37
- (0, assert_1.default)(importResult.isImportFound);
38
- (0, assert_1.default)(importResult.isStubFile);
39
- assert_1.default.strictEqual(1, importResult.resolvedPaths.filter((f) => f === (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', 'partialStub.pyi')).length);
40
- });
41
- test('partial stub __init__ exists', () => {
42
- const files = [
43
- {
44
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', '__init__.pyi'),
45
- content: 'def test(): ...',
46
- },
47
- {
48
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', 'py.typed'),
49
- content: 'partial\n',
50
- },
51
- {
52
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', '__init__.py'),
53
- content: 'def test(): pass',
54
- },
55
- ];
56
- const importResult = getImportResult(files, ['myLib']);
57
- (0, assert_1.default)(importResult.isImportFound);
58
- (0, assert_1.default)(importResult.isStubFile);
59
- assert_1.default.strictEqual(1, importResult.resolvedPaths.filter((f) => f === (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', '__init__.pyi')).length);
60
- });
61
- test('side by side files', () => {
62
- const myFile = (0, pathUtils_1.combinePaths)('src', 'file.py');
63
- const files = [
64
- {
65
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', 'partialStub.pyi'),
66
- content: 'def test(): ...',
67
- },
68
- {
69
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', 'py.typed'),
70
- content: 'partial\n',
71
- },
72
- {
73
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', 'partialStub.pyi'),
74
- content: '# empty',
75
- },
76
- {
77
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', 'partialStub.py'),
78
- content: 'def test(): pass',
79
- },
80
- {
81
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', 'partialStub2.pyi'),
82
- content: 'def test(): ...',
83
- },
84
- {
85
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', 'partialStub2.py'),
86
- content: 'def test(): pass',
87
- },
88
- {
89
- path: myFile,
90
- content: '# not used',
91
- },
92
- ];
93
- const sp = createServiceProviderFromFiles(files);
94
- const configOptions = new configOptions_1.ConfigOptions((0, pathUtils_1.normalizeSlashes)('/'));
95
- const importResolver = new importResolver_1.ImportResolver(sp, configOptions, new testAccessHost_1.TestAccessHost(sp.fs().getModulePath(), [libraryRoot]));
96
- // Stub package wins over original package (per PEP 561 rules).
97
- const sideBySideResult = importResolver.resolveImport(myFile, configOptions.findExecEnvironment(myFile), {
98
- leadingDots: 0,
99
- nameParts: ['myLib', 'partialStub'],
100
- importedSymbols: new Set(),
23
+ function usingTrueVenv() {
24
+ return process.env.CI_IMPORT_TEST_VENVPATH !== undefined || process.env.CI_IMPORT_TEST_PYTHONPATH !== undefined;
25
+ }
26
+ if (!usingTrueVenv()) {
27
+ describe('Import tests that cannot run in a true venv', () => {
28
+ test('partial stub file exists', () => {
29
+ const files = [
30
+ {
31
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', 'partialStub.pyi'),
32
+ content: 'def test(): ...',
33
+ },
34
+ {
35
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', 'py.typed'),
36
+ content: 'partial\n',
37
+ },
38
+ {
39
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', 'partialStub.py'),
40
+ content: 'def test(): pass',
41
+ },
42
+ ];
43
+ const importResult = getImportResult(files, ['myLib', 'partialStub']);
44
+ (0, assert_1.default)(importResult.isImportFound);
45
+ (0, assert_1.default)(importResult.isStubFile);
46
+ assert_1.default.strictEqual(1, importResult.resolvedPaths.filter((f) => f === (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', 'partialStub.pyi'))
47
+ .length);
48
+ });
49
+ test('partial stub __init__ exists', () => {
50
+ const files = [
51
+ {
52
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', '__init__.pyi'),
53
+ content: 'def test(): ...',
54
+ },
55
+ {
56
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', 'py.typed'),
57
+ content: 'partial\n',
58
+ },
59
+ {
60
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', '__init__.py'),
61
+ content: 'def test(): pass',
62
+ },
63
+ ];
64
+ const importResult = getImportResult(files, ['myLib']);
65
+ (0, assert_1.default)(importResult.isImportFound);
66
+ (0, assert_1.default)(importResult.isStubFile);
67
+ assert_1.default.strictEqual(1, importResult.resolvedPaths.filter((f) => f === (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', '__init__.pyi'))
68
+ .length);
69
+ });
70
+ test('stub package', () => {
71
+ const files = [
72
+ {
73
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', 'stub.pyi'),
74
+ content: '# empty',
75
+ },
76
+ {
77
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', '__init__.pyi'),
78
+ content: '# empty',
79
+ },
80
+ {
81
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', 'partialStub.py'),
82
+ content: 'def test(): pass',
83
+ },
84
+ ];
85
+ // If fully typed stub package exists, that wins over the real package.
86
+ const importResult = getImportResult(files, ['myLib', 'partialStub']);
87
+ (0, assert_1.default)(!importResult.isImportFound);
88
+ });
89
+ test('partial stub package in typing folder', () => {
90
+ const typingFolder = (0, pathUtils_1.combinePaths)((0, pathUtils_1.normalizeSlashes)('/'), 'typing');
91
+ const files = [
92
+ {
93
+ path: (0, pathUtils_1.combinePaths)(typingFolder, 'myLib-stubs', '__init__.pyi'),
94
+ content: 'def test(): ...',
95
+ },
96
+ {
97
+ path: (0, pathUtils_1.combinePaths)(typingFolder, 'myLib-stubs', 'py.typed'),
98
+ content: 'partial\n',
99
+ },
100
+ {
101
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', '__init__.py'),
102
+ content: 'def test(): pass',
103
+ },
104
+ ];
105
+ const importResult = getImportResult(files, ['myLib'], (c) => (c.stubPath = typingFolder));
106
+ (0, assert_1.default)(importResult.isImportFound);
107
+ (0, assert_1.default)(importResult.isStubFile);
108
+ assert_1.default.strictEqual(1, importResult.resolvedPaths.filter((f) => f === (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', '__init__.pyi'))
109
+ .length);
110
+ });
111
+ test('typeshed folder', () => {
112
+ const typeshedFolder = (0, pathUtils_1.combinePaths)((0, pathUtils_1.normalizeSlashes)('/'), 'ts');
113
+ const files = [
114
+ {
115
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', '__init__.pyi'),
116
+ content: 'def test(): ...',
117
+ },
118
+ {
119
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', 'py.typed'),
120
+ content: 'partial\n',
121
+ },
122
+ {
123
+ path: (0, pathUtils_1.combinePaths)(typeshedFolder, 'stubs', 'myLibPackage', 'myLib.pyi'),
124
+ content: '# empty',
125
+ },
126
+ {
127
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', '__init__.py'),
128
+ content: 'def test(): pass',
129
+ },
130
+ ];
131
+ // Stub packages win over typeshed.
132
+ const importResult = getImportResult(files, ['myLib'], (c) => (c.typeshedPath = typeshedFolder));
133
+ (0, assert_1.default)(importResult.isImportFound);
134
+ (0, assert_1.default)(importResult.isStubFile);
135
+ assert_1.default.strictEqual(1, importResult.resolvedPaths.filter((f) => f === (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', '__init__.pyi'))
136
+ .length);
137
+ });
138
+ test('typeshed fallback folder', () => {
139
+ const files = [
140
+ {
141
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', '__init__.pyi'),
142
+ content: 'def test(): ...',
143
+ },
144
+ {
145
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', 'py.typed'),
146
+ content: 'partial\n',
147
+ },
148
+ {
149
+ path: (0, pathUtils_1.combinePaths)('/', pathConsts_1.typeshedFallback, 'stubs', 'myLibPackage', 'myLib.pyi'),
150
+ content: '# empty',
151
+ },
152
+ {
153
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', '__init__.py'),
154
+ content: 'def test(): pass',
155
+ },
156
+ ];
157
+ // Stub packages win over typeshed.
158
+ const importResult = getImportResult(files, ['myLib']);
159
+ (0, assert_1.default)(importResult.isImportFound);
160
+ (0, assert_1.default)(importResult.isStubFile);
161
+ assert_1.default.strictEqual(1, importResult.resolvedPaths.filter((f) => f === (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', '__init__.pyi'))
162
+ .length);
163
+ });
164
+ test('py.typed file', () => {
165
+ const files = [
166
+ {
167
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', '__init__.pyi'),
168
+ content: 'def test(): ...',
169
+ },
170
+ {
171
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', 'py.typed'),
172
+ content: 'partial\n',
173
+ },
174
+ {
175
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', '__init__.py'),
176
+ content: 'def test(): pass',
177
+ },
178
+ {
179
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', 'py.typed'),
180
+ content: '# typed',
181
+ },
182
+ ];
183
+ // Partial stub package always overrides original package.
184
+ const importResult = getImportResult(files, ['myLib']);
185
+ (0, assert_1.default)(importResult.isImportFound);
186
+ (0, assert_1.default)(importResult.isStubFile);
187
+ });
188
+ test('py.typed library', () => {
189
+ const files = [
190
+ {
191
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'os', '__init__.py'),
192
+ content: 'def test(): ...',
193
+ },
194
+ {
195
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'os', 'py.typed'),
196
+ content: '',
197
+ },
198
+ {
199
+ path: (0, pathUtils_1.combinePaths)('/', pathConsts_1.typeshedFallback, 'stubs', 'os', 'os', '__init__.pyi'),
200
+ content: '# empty',
201
+ },
202
+ ];
203
+ const importResult = getImportResult(files, ['os']);
204
+ (0, assert_1.default)(importResult.isImportFound);
205
+ assert_1.default.strictEqual(files[0].path, importResult.resolvedPaths[importResult.resolvedPaths.length - 1]);
206
+ });
207
+ test('import side by side file sub under lib folder', () => {
208
+ const files = [
209
+ {
210
+ path: (0, pathUtils_1.combinePaths)('/lib/site-packages/myLib', 'file1.py'),
211
+ content: 'def test1(): ...',
212
+ },
213
+ {
214
+ path: (0, pathUtils_1.combinePaths)('/lib/site-packages/myLib', 'file2.py'),
215
+ content: 'def test2(): ...',
216
+ },
217
+ ];
218
+ const importResult = getImportResult(files, ['file1']);
219
+ (0, assert_1.default)(!importResult.isImportFound);
220
+ });
101
221
  });
102
- (0, assert_1.default)(sideBySideResult.isImportFound);
103
- (0, assert_1.default)(sideBySideResult.isStubFile);
104
- const sideBySideStubFile = (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', 'partialStub.pyi');
105
- assert_1.default.strictEqual(1, sideBySideResult.resolvedPaths.filter((f) => f === sideBySideStubFile).length);
106
- assert_1.default.strictEqual('def test(): ...', sp.fs().readFileSync(sideBySideStubFile, 'utf8'));
107
- // Side by side stub doesn't completely disable partial stub.
108
- const partialStubResult = importResolver.resolveImport(myFile, configOptions.findExecEnvironment(myFile), {
109
- leadingDots: 0,
110
- nameParts: ['myLib', 'partialStub2'],
111
- importedSymbols: new Set(),
222
+ }
223
+ describe('Import tests that can run with or without a true venv', () => {
224
+ test('side by side files', () => {
225
+ const myFile = (0, pathUtils_1.combinePaths)('src', 'file.py');
226
+ const files = [
227
+ {
228
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', 'partialStub.pyi'),
229
+ content: 'def test(): ...',
230
+ },
231
+ {
232
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', 'py.typed'),
233
+ content: 'partial\n',
234
+ },
235
+ {
236
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', 'partialStub.pyi'),
237
+ content: '# empty',
238
+ },
239
+ {
240
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', 'partialStub.py'),
241
+ content: 'def test(): pass',
242
+ },
243
+ {
244
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', 'partialStub2.pyi'),
245
+ content: 'def test(): ...',
246
+ },
247
+ {
248
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', 'partialStub2.py'),
249
+ content: 'def test(): pass',
250
+ },
251
+ {
252
+ path: myFile,
253
+ content: '# not used',
254
+ },
255
+ ];
256
+ const sp = createServiceProviderFromFiles(files);
257
+ const configOptions = new configOptions_1.ConfigOptions((0, pathUtils_1.normalizeSlashes)('/'));
258
+ const importResolver = new importResolver_1.ImportResolver(sp, configOptions, new testAccessHost_1.TestAccessHost(sp.fs().getModulePath(), [libraryRoot]));
259
+ // Stub package wins over original package (per PEP 561 rules).
260
+ const sideBySideResult = importResolver.resolveImport(myFile, configOptions.findExecEnvironment(myFile), {
261
+ leadingDots: 0,
262
+ nameParts: ['myLib', 'partialStub'],
263
+ importedSymbols: new Set(),
264
+ });
265
+ (0, assert_1.default)(sideBySideResult.isImportFound);
266
+ (0, assert_1.default)(sideBySideResult.isStubFile);
267
+ const sideBySideStubFile = (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', 'partialStub.pyi');
268
+ assert_1.default.strictEqual(1, sideBySideResult.resolvedPaths.filter((f) => f === sideBySideStubFile).length);
269
+ assert_1.default.strictEqual('def test(): ...', sp.fs().readFileSync(sideBySideStubFile, 'utf8'));
270
+ // Side by side stub doesn't completely disable partial stub.
271
+ const partialStubResult = importResolver.resolveImport(myFile, configOptions.findExecEnvironment(myFile), {
272
+ leadingDots: 0,
273
+ nameParts: ['myLib', 'partialStub2'],
274
+ importedSymbols: new Set(),
275
+ });
276
+ (0, assert_1.default)(partialStubResult.isImportFound);
277
+ (0, assert_1.default)(partialStubResult.isStubFile);
278
+ const partialStubFile = (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', 'partialStub2.pyi');
279
+ assert_1.default.strictEqual(1, partialStubResult.resolvedPaths.filter((f) => f === partialStubFile).length);
112
280
  });
113
- (0, assert_1.default)(partialStubResult.isImportFound);
114
- (0, assert_1.default)(partialStubResult.isStubFile);
115
- const partialStubFile = (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', 'partialStub2.pyi');
116
- assert_1.default.strictEqual(1, partialStubResult.resolvedPaths.filter((f) => f === partialStubFile).length);
117
- });
118
- test('stub package', () => {
119
- const files = [
120
- {
121
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', 'stub.pyi'),
122
- content: '# empty',
123
- },
124
- {
125
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', '__init__.pyi'),
126
- content: '# empty',
127
- },
128
- {
129
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', 'partialStub.py'),
130
- content: 'def test(): pass',
131
- },
132
- ];
133
- // If fully typed stub package exists, that wins over the real package.
134
- const importResult = getImportResult(files, ['myLib', 'partialStub']);
135
- (0, assert_1.default)(!importResult.isImportFound);
136
- });
137
- test('stub namespace package', () => {
138
- const files = [
139
- {
140
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', 'stub.pyi'),
141
- content: '# empty',
142
- },
143
- {
144
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', 'partialStub.py'),
145
- content: 'def test(): pass',
146
- },
147
- ];
148
- // If fully typed stub package exists, that wins over the real package.
149
- const importResult = getImportResult(files, ['myLib', 'partialStub']);
150
- (0, assert_1.default)(importResult.isImportFound);
151
- (0, assert_1.default)(!importResult.isStubFile);
152
- assert_1.default.strictEqual(1, importResult.resolvedPaths.filter((f) => f === (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', 'partialStub.py')).length);
153
- });
154
- test('stub in typing folder over partial stub package', () => {
155
- const typingFolder = (0, pathUtils_1.combinePaths)((0, pathUtils_1.normalizeSlashes)('/'), 'typing');
156
- const files = [
157
- {
158
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', '__init__.pyi'),
159
- content: 'def test(): ...',
160
- },
161
- {
162
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', 'py.typed'),
163
- content: 'partial\n',
164
- },
165
- {
166
- path: (0, pathUtils_1.combinePaths)(typingFolder, 'myLib.pyi'),
167
- content: '# empty',
168
- },
169
- {
170
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', '__init__.py'),
171
- content: 'def test(): pass',
172
- },
173
- ];
174
- // If the package exists in typing folder, that gets picked up first.
175
- const importResult = getImportResult(files, ['myLib'], (c) => (c.stubPath = typingFolder));
176
- (0, assert_1.default)(importResult.isImportFound);
177
- (0, assert_1.default)(importResult.isStubFile);
178
- assert_1.default.strictEqual(0, importResult.resolvedPaths.filter((f) => f === (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', '__init__.pyi')).length);
179
- });
180
- test('partial stub package in typing folder', () => {
181
- const typingFolder = (0, pathUtils_1.combinePaths)((0, pathUtils_1.normalizeSlashes)('/'), 'typing');
182
- const files = [
183
- {
184
- path: (0, pathUtils_1.combinePaths)(typingFolder, 'myLib-stubs', '__init__.pyi'),
185
- content: 'def test(): ...',
186
- },
187
- {
188
- path: (0, pathUtils_1.combinePaths)(typingFolder, 'myLib-stubs', 'py.typed'),
189
- content: 'partial\n',
190
- },
191
- {
192
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', '__init__.py'),
193
- content: 'def test(): pass',
194
- },
195
- ];
196
- const importResult = getImportResult(files, ['myLib'], (c) => (c.stubPath = typingFolder));
197
- (0, assert_1.default)(importResult.isImportFound);
198
- (0, assert_1.default)(importResult.isStubFile);
199
- assert_1.default.strictEqual(1, importResult.resolvedPaths.filter((f) => f === (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', '__init__.pyi')).length);
200
- });
201
- test('typeshed folder', () => {
202
- const typeshedFolder = (0, pathUtils_1.combinePaths)((0, pathUtils_1.normalizeSlashes)('/'), 'ts');
203
- const files = [
204
- {
205
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', '__init__.pyi'),
206
- content: 'def test(): ...',
207
- },
208
- {
209
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', 'py.typed'),
210
- content: 'partial\n',
211
- },
212
- {
213
- path: (0, pathUtils_1.combinePaths)(typeshedFolder, 'stubs', 'myLibPackage', 'myLib.pyi'),
214
- content: '# empty',
215
- },
216
- {
217
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', '__init__.py'),
218
- content: 'def test(): pass',
219
- },
220
- ];
221
- // Stub packages win over typeshed.
222
- const importResult = getImportResult(files, ['myLib'], (c) => (c.typeshedPath = typeshedFolder));
223
- (0, assert_1.default)(importResult.isImportFound);
224
- (0, assert_1.default)(importResult.isStubFile);
225
- assert_1.default.strictEqual(1, importResult.resolvedPaths.filter((f) => f === (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', '__init__.pyi')).length);
226
- });
227
- test('typeshed fallback folder', () => {
228
- const files = [
229
- {
230
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', '__init__.pyi'),
231
- content: 'def test(): ...',
232
- },
233
- {
234
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', 'py.typed'),
235
- content: 'partial\n',
236
- },
237
- {
238
- path: (0, pathUtils_1.combinePaths)('/', pathConsts_1.typeshedFallback, 'stubs', 'myLibPackage', 'myLib.pyi'),
239
- content: '# empty',
240
- },
241
- {
242
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', '__init__.py'),
243
- content: 'def test(): pass',
244
- },
245
- ];
246
- // Stub packages win over typeshed.
247
- const importResult = getImportResult(files, ['myLib']);
248
- (0, assert_1.default)(importResult.isImportFound);
249
- (0, assert_1.default)(importResult.isStubFile);
250
- assert_1.default.strictEqual(1, importResult.resolvedPaths.filter((f) => f === (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', '__init__.pyi')).length);
251
- });
252
- test('py.typed file', () => {
253
- const files = [
254
- {
255
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', '__init__.pyi'),
256
- content: 'def test(): ...',
257
- },
258
- {
259
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', 'py.typed'),
260
- content: 'partial\n',
261
- },
262
- {
263
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', '__init__.py'),
264
- content: 'def test(): pass',
265
- },
266
- {
267
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', 'py.typed'),
268
- content: '# typed',
269
- },
270
- ];
271
- // Partial stub package always overrides original package.
272
- const importResult = getImportResult(files, ['myLib']);
273
- (0, assert_1.default)(importResult.isImportFound);
274
- (0, assert_1.default)(importResult.isStubFile);
275
- });
276
- test('py.typed library', () => {
277
- const files = [
278
- {
279
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'os', '__init__.py'),
280
- content: 'def test(): ...',
281
- },
282
- {
283
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'os', 'py.typed'),
284
- content: '',
285
- },
286
- {
287
- path: (0, pathUtils_1.combinePaths)('/', pathConsts_1.typeshedFallback, 'stubs', 'os', 'os', '__init__.pyi'),
288
- content: '# empty',
289
- },
290
- ];
291
- const importResult = getImportResult(files, ['os']);
292
- (0, assert_1.default)(importResult.isImportFound);
293
- assert_1.default.strictEqual(files[0].path, importResult.resolvedPaths[importResult.resolvedPaths.length - 1]);
294
- });
295
- test('non py.typed library', () => {
296
- const files = [
297
- {
298
- path: (0, pathUtils_1.combinePaths)(libraryRoot, 'os', '__init__.py'),
299
- content: 'def test(): ...',
300
- },
301
- {
302
- path: (0, pathUtils_1.combinePaths)('/', pathConsts_1.typeshedFallback, 'stubs', 'os', 'os', '__init__.pyi'),
303
- content: '# empty',
304
- },
305
- ];
306
- const importResult = getImportResult(files, ['os']);
307
- (0, assert_1.default)(importResult.isImportFound);
308
- assert_1.default.strictEqual(files[1].path, importResult.resolvedPaths[importResult.resolvedPaths.length - 1]);
309
- });
310
- test('no empty import roots', () => {
311
- const sp = createServiceProviderFromFiles([]);
312
- const configOptions = new configOptions_1.ConfigOptions(''); // Empty, like open-file mode.
313
- const importResolver = new importResolver_1.ImportResolver(sp, configOptions, new testAccessHost_1.TestAccessHost(sp.fs().getModulePath(), [libraryRoot]));
314
- importResolver.getImportRoots(configOptions.getDefaultExecEnvironment()).forEach((path) => (0, assert_1.default)(path));
315
- });
316
- test('multiple typeshedFallback', () => {
317
- const files = [
318
- {
319
- path: (0, pathUtils_1.combinePaths)('/', pathConsts_1.typeshedFallback, 'stubs', 'aLib', 'aLib', '__init__.pyi'),
320
- content: '# empty',
321
- },
322
- {
323
- path: (0, pathUtils_1.combinePaths)('/', pathConsts_1.typeshedFallback, 'stubs', 'bLib', 'bLib', '__init__.pyi'),
324
- content: '# empty',
325
- },
326
- ];
327
- const sp = createServiceProviderFromFiles(files);
328
- const configOptions = new configOptions_1.ConfigOptions(''); // Empty, like open-file mode.
329
- const importResolver = new importResolver_1.ImportResolver(sp, configOptions, new testAccessHost_1.TestAccessHost(sp.fs().getModulePath(), [libraryRoot]));
330
- const importRoots = importResolver.getImportRoots(configOptions.getDefaultExecEnvironment());
331
- assert_1.default.strictEqual(1, importRoots.filter((f) => f === (0, pathUtils_1.combinePaths)('/', pathConsts_1.typeshedFallback, 'stubs', 'aLib')).length);
332
- assert_1.default.strictEqual(1, importRoots.filter((f) => f === (0, pathUtils_1.combinePaths)('/', pathConsts_1.typeshedFallback, 'stubs', 'bLib')).length);
333
- });
334
- test('import side by side file root', () => {
335
- const files = [
336
- {
337
- path: (0, pathUtils_1.combinePaths)('/', 'file1.py'),
338
- content: 'def test1(): ...',
339
- },
340
- {
341
- path: (0, pathUtils_1.combinePaths)('/', 'file2.py'),
342
- content: 'def test2(): ...',
343
- },
344
- ];
345
- const importResult = getImportResult(files, ['file1']);
346
- (0, assert_1.default)(importResult.isImportFound);
347
- assert_1.default.strictEqual(1, importResult.resolvedPaths.filter((f) => f === (0, pathUtils_1.combinePaths)('/', 'file1.py')).length);
348
- });
349
- test('import side by side file sub folder', () => {
350
- const files = [
351
- {
352
- path: (0, pathUtils_1.combinePaths)('/test', 'file1.py'),
353
- content: 'def test1(): ...',
354
- },
355
- {
356
- path: (0, pathUtils_1.combinePaths)('/test', 'file2.py'),
357
- content: 'def test2(): ...',
358
- },
359
- ];
360
- const importResult = getImportResult(files, ['file1']);
361
- (0, assert_1.default)(importResult.isImportFound);
362
- assert_1.default.strictEqual(1, importResult.resolvedPaths.filter((f) => f === (0, pathUtils_1.combinePaths)('/test', 'file1.py')).length);
363
- });
364
- test('import side by side file sub under src folder', () => {
365
- const files = [
366
- {
367
- path: (0, pathUtils_1.combinePaths)('/src/nested', 'file1.py'),
368
- content: 'def test1(): ...',
369
- },
370
- {
371
- path: (0, pathUtils_1.combinePaths)('/src/nested', 'file2.py'),
372
- content: 'def test2(): ...',
373
- },
374
- ];
375
- const importResult = getImportResult(files, ['file1']);
376
- (0, assert_1.default)(importResult.isImportFound);
377
- assert_1.default.strictEqual(1, importResult.resolvedPaths.filter((f) => f === (0, pathUtils_1.combinePaths)('/src/nested', 'file1.py')).length);
378
- });
379
- test('import file sub under containing folder', () => {
380
- const files = [
381
- {
382
- path: (0, pathUtils_1.combinePaths)('/src/nested', 'file1.py'),
383
- content: 'def test1(): ...',
384
- },
385
- {
386
- path: (0, pathUtils_1.combinePaths)('/src/nested/nested2', 'file2.py'),
387
- content: 'def test2(): ...',
388
- },
389
- ];
390
- const importResult = getImportResult(files, ['file1']);
391
- (0, assert_1.default)(importResult.isImportFound);
392
- assert_1.default.strictEqual(1, importResult.resolvedPaths.filter((f) => f === (0, pathUtils_1.combinePaths)('/src/nested', 'file1.py')).length);
393
- });
394
- test('import side by side file sub under lib folder', () => {
395
- const files = [
396
- {
397
- path: (0, pathUtils_1.combinePaths)('/lib/site-packages/myLib', 'file1.py'),
398
- content: 'def test1(): ...',
399
- },
400
- {
401
- path: (0, pathUtils_1.combinePaths)('/lib/site-packages/myLib', 'file2.py'),
402
- content: 'def test2(): ...',
403
- },
404
- ];
405
- const importResult = getImportResult(files, ['file1']);
406
- (0, assert_1.default)(!importResult.isImportFound);
407
- });
408
- test("don't walk up the root", () => {
409
- const files = [
410
- {
411
- path: (0, pathUtils_1.combinePaths)('/', 'file1.py'),
412
- content: 'def test1(): ...',
413
- },
414
- ];
415
- const importResult = getImportResult(files, ['notExist'], (c) => (c.projectRoot = ''));
416
- (0, assert_1.default)(!importResult.isImportFound);
417
- });
418
- test('nested namespace package 1', () => {
419
- const files = [
420
- {
421
- path: (0, pathUtils_1.combinePaths)('/', 'packages1', 'a', 'b', 'c', 'd.py'),
422
- content: 'def f(): pass',
423
- },
424
- {
425
- path: (0, pathUtils_1.combinePaths)('/', 'packages1', 'a', '__init__.py'),
426
- content: '',
427
- },
428
- {
429
- path: (0, pathUtils_1.combinePaths)('/', 'packages2', 'a', '__init__.py'),
430
- content: '',
431
- },
432
- ];
433
- const importResult = getImportResult(files, ['a', 'b', 'c', 'd'], (config) => {
434
- config.defaultExtraPaths = [(0, pathUtils_1.combinePaths)('/', 'packages1'), (0, pathUtils_1.combinePaths)('/', 'packages2')];
281
+ test('stub namespace package', () => {
282
+ const files = [
283
+ {
284
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', 'stub.pyi'),
285
+ content: '# empty',
286
+ },
287
+ {
288
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', 'partialStub.py'),
289
+ content: 'def test(): pass',
290
+ },
291
+ ];
292
+ // If fully typed stub package exists, that wins over the real package.
293
+ const importResult = getImportResult(files, ['myLib', 'partialStub']);
294
+ (0, assert_1.default)(importResult.isImportFound);
295
+ (0, assert_1.default)(!importResult.isStubFile);
296
+ assert_1.default.strictEqual(1, importResult.resolvedPaths.filter((f) => f === (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', 'partialStub.py')).length);
435
297
  });
436
- (0, assert_1.default)(importResult.isImportFound);
437
- });
438
- test('nested namespace package 2', () => {
439
- const files = [
440
- {
441
- path: (0, pathUtils_1.combinePaths)('/', 'packages1', 'a', 'b', 'c', 'd.py'),
442
- content: 'def f(): pass',
443
- },
444
- {
445
- path: (0, pathUtils_1.combinePaths)('/', 'packages1', 'a', 'b', 'c', '__init__.py'),
446
- content: '',
447
- },
448
- {
449
- path: (0, pathUtils_1.combinePaths)('/', 'packages2', 'a', 'b', 'c', '__init__.py'),
450
- content: '',
451
- },
452
- ];
453
- const importResult = getImportResult(files, ['a', 'b', 'c', 'd'], (config) => {
454
- config.defaultExtraPaths = [(0, pathUtils_1.combinePaths)('/', 'packages1'), (0, pathUtils_1.combinePaths)('/', 'packages2')];
298
+ test('stub in typing folder over partial stub package', () => {
299
+ const typingFolder = (0, pathUtils_1.combinePaths)((0, pathUtils_1.normalizeSlashes)('/'), 'typing');
300
+ const files = [
301
+ {
302
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', '__init__.pyi'),
303
+ content: 'def test(): ...',
304
+ },
305
+ {
306
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib-stubs', 'py.typed'),
307
+ content: 'partial\n',
308
+ },
309
+ {
310
+ path: (0, pathUtils_1.combinePaths)(typingFolder, 'myLib.pyi'),
311
+ content: '# empty',
312
+ },
313
+ {
314
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', '__init__.py'),
315
+ content: 'def test(): pass',
316
+ },
317
+ ];
318
+ // If the package exists in typing folder, that gets picked up first.
319
+ const importResult = getImportResult(files, ['myLib'], (c) => (c.stubPath = typingFolder));
320
+ (0, assert_1.default)(importResult.isImportFound);
321
+ (0, assert_1.default)(importResult.isStubFile);
322
+ assert_1.default.strictEqual(0, importResult.resolvedPaths.filter((f) => f === (0, pathUtils_1.combinePaths)(libraryRoot, 'myLib', '__init__.pyi')).length);
455
323
  });
456
- (0, assert_1.default)(importResult.isImportFound);
457
- });
458
- test('nested namespace package 3', () => {
459
- const files = [
460
- {
461
- path: (0, pathUtils_1.combinePaths)('/', 'packages1', 'a', 'b', 'c', 'd.py'),
462
- content: 'def f(): pass',
463
- },
464
- {
465
- path: (0, pathUtils_1.combinePaths)('/', 'packages2', 'a', '__init__.py'),
466
- content: '',
467
- },
468
- ];
469
- const importResult = getImportResult(files, ['a', 'b', 'c', 'd'], (config) => {
470
- config.defaultExtraPaths = [(0, pathUtils_1.combinePaths)('/', 'packages1'), (0, pathUtils_1.combinePaths)('/', 'packages2')];
324
+ test('non py.typed library', () => {
325
+ const files = [
326
+ {
327
+ path: (0, pathUtils_1.combinePaths)(libraryRoot, 'os', '__init__.py'),
328
+ content: 'def test(): ...',
329
+ },
330
+ {
331
+ path: (0, pathUtils_1.combinePaths)('/', pathConsts_1.typeshedFallback, 'stubs', 'os', 'os', '__init__.pyi'),
332
+ content: '# empty',
333
+ },
334
+ ];
335
+ const importResult = getImportResult(files, ['os']);
336
+ (0, assert_1.default)(importResult.isImportFound);
337
+ assert_1.default.strictEqual(files[1].path, importResult.resolvedPaths[importResult.resolvedPaths.length - 1]);
471
338
  });
472
- (0, assert_1.default)(!importResult.isImportFound);
473
- });
474
- test('nested namespace package 4', () => {
475
- const files = [
476
- {
477
- path: (0, pathUtils_1.combinePaths)('/', 'packages1', 'a', 'b', '__init__.py'),
478
- content: '',
479
- },
480
- {
481
- path: (0, pathUtils_1.combinePaths)('/', 'packages1', 'a', 'b', 'c.py'),
482
- content: 'def f(): pass',
483
- },
484
- {
485
- path: (0, pathUtils_1.combinePaths)('/', 'packages2', 'a', '__init__.py'),
486
- content: '',
487
- },
488
- {
489
- path: (0, pathUtils_1.combinePaths)('/', 'packages2', 'a', 'b', '__init__.py'),
490
- content: '',
491
- },
492
- ];
493
- const importResult = getImportResult(files, ['a', 'b', 'c'], (config) => {
494
- config.defaultExtraPaths = [(0, pathUtils_1.combinePaths)('/', 'packages1'), (0, pathUtils_1.combinePaths)('/', 'packages2')];
339
+ test('no empty import roots', () => {
340
+ const sp = createServiceProviderFromFiles([]);
341
+ const configOptions = new configOptions_1.ConfigOptions(''); // Empty, like open-file mode.
342
+ const importResolver = new importResolver_1.ImportResolver(sp, configOptions, new testAccessHost_1.TestAccessHost(sp.fs().getModulePath(), [libraryRoot]));
343
+ importResolver.getImportRoots(configOptions.getDefaultExecEnvironment()).forEach((path) => (0, assert_1.default)(path));
344
+ });
345
+ test('multiple typeshedFallback', () => {
346
+ const files = [
347
+ {
348
+ path: (0, pathUtils_1.combinePaths)('/', pathConsts_1.typeshedFallback, 'stubs', 'aLib', 'aLib', '__init__.pyi'),
349
+ content: '# empty',
350
+ },
351
+ {
352
+ path: (0, pathUtils_1.combinePaths)('/', pathConsts_1.typeshedFallback, 'stubs', 'bLib', 'bLib', '__init__.pyi'),
353
+ content: '# empty',
354
+ },
355
+ ];
356
+ const sp = createServiceProviderFromFiles(files);
357
+ const configOptions = new configOptions_1.ConfigOptions(''); // Empty, like open-file mode.
358
+ const importResolver = new importResolver_1.ImportResolver(sp, configOptions, new testAccessHost_1.TestAccessHost(sp.fs().getModulePath(), [libraryRoot]));
359
+ const importRoots = importResolver.getImportRoots(configOptions.getDefaultExecEnvironment());
360
+ assert_1.default.strictEqual(1, importRoots.filter((f) => f === (0, pathUtils_1.combinePaths)('/', pathConsts_1.typeshedFallback, 'stubs', 'aLib')).length);
361
+ assert_1.default.strictEqual(1, importRoots.filter((f) => f === (0, pathUtils_1.combinePaths)('/', pathConsts_1.typeshedFallback, 'stubs', 'bLib')).length);
362
+ });
363
+ test('import side by side file root', () => {
364
+ const files = [
365
+ {
366
+ path: (0, pathUtils_1.combinePaths)('/', 'file1.py'),
367
+ content: 'def test1(): ...',
368
+ },
369
+ {
370
+ path: (0, pathUtils_1.combinePaths)('/', 'file2.py'),
371
+ content: 'def test2(): ...',
372
+ },
373
+ ];
374
+ const importResult = getImportResult(files, ['file1']);
375
+ (0, assert_1.default)(importResult.isImportFound);
376
+ assert_1.default.strictEqual(1, importResult.resolvedPaths.filter((f) => f === (0, pathUtils_1.combinePaths)('/', 'file1.py')).length);
377
+ });
378
+ test('import side by side file sub folder', () => {
379
+ const files = [
380
+ {
381
+ path: (0, pathUtils_1.combinePaths)('/test', 'file1.py'),
382
+ content: 'def test1(): ...',
383
+ },
384
+ {
385
+ path: (0, pathUtils_1.combinePaths)('/test', 'file2.py'),
386
+ content: 'def test2(): ...',
387
+ },
388
+ ];
389
+ const importResult = getImportResult(files, ['file1']);
390
+ (0, assert_1.default)(importResult.isImportFound);
391
+ assert_1.default.strictEqual(1, importResult.resolvedPaths.filter((f) => f === (0, pathUtils_1.combinePaths)('/test', 'file1.py')).length);
392
+ });
393
+ test('import side by side file sub under src folder', () => {
394
+ const files = [
395
+ {
396
+ path: (0, pathUtils_1.combinePaths)('/src/nested', 'file1.py'),
397
+ content: 'def test1(): ...',
398
+ },
399
+ {
400
+ path: (0, pathUtils_1.combinePaths)('/src/nested', 'file2.py'),
401
+ content: 'def test2(): ...',
402
+ },
403
+ ];
404
+ const importResult = getImportResult(files, ['file1']);
405
+ (0, assert_1.default)(importResult.isImportFound);
406
+ assert_1.default.strictEqual(1, importResult.resolvedPaths.filter((f) => f === (0, pathUtils_1.combinePaths)('/src/nested', 'file1.py')).length);
407
+ });
408
+ test('import file sub under containing folder', () => {
409
+ const files = [
410
+ {
411
+ path: (0, pathUtils_1.combinePaths)('/src/nested', 'file1.py'),
412
+ content: 'def test1(): ...',
413
+ },
414
+ {
415
+ path: (0, pathUtils_1.combinePaths)('/src/nested/nested2', 'file2.py'),
416
+ content: 'def test2(): ...',
417
+ },
418
+ ];
419
+ const importResult = getImportResult(files, ['file1']);
420
+ (0, assert_1.default)(importResult.isImportFound);
421
+ assert_1.default.strictEqual(1, importResult.resolvedPaths.filter((f) => f === (0, pathUtils_1.combinePaths)('/src/nested', 'file1.py')).length);
422
+ });
423
+ test("don't walk up the root", () => {
424
+ const files = [
425
+ {
426
+ path: (0, pathUtils_1.combinePaths)('/', 'file1.py'),
427
+ content: 'def test1(): ...',
428
+ },
429
+ ];
430
+ const importResult = getImportResult(files, ['notExist'], (c) => (c.projectRoot = ''));
431
+ (0, assert_1.default)(!importResult.isImportFound);
432
+ });
433
+ test('nested namespace package 1', () => {
434
+ const files = [
435
+ {
436
+ path: (0, pathUtils_1.combinePaths)('/', 'packages1', 'a', 'b', 'c', 'd.py'),
437
+ content: 'def f(): pass',
438
+ },
439
+ {
440
+ path: (0, pathUtils_1.combinePaths)('/', 'packages1', 'a', '__init__.py'),
441
+ content: '',
442
+ },
443
+ {
444
+ path: (0, pathUtils_1.combinePaths)('/', 'packages2', 'a', '__init__.py'),
445
+ content: '',
446
+ },
447
+ ];
448
+ const importResult = getImportResult(files, ['a', 'b', 'c', 'd'], (config) => {
449
+ config.defaultExtraPaths = [(0, pathUtils_1.combinePaths)('/', 'packages1'), (0, pathUtils_1.combinePaths)('/', 'packages2')];
450
+ });
451
+ (0, assert_1.default)(importResult.isImportFound);
452
+ });
453
+ test('nested namespace package 2', () => {
454
+ const files = [
455
+ {
456
+ path: (0, pathUtils_1.combinePaths)('/', 'packages1', 'a', 'b', 'c', 'd.py'),
457
+ content: 'def f(): pass',
458
+ },
459
+ {
460
+ path: (0, pathUtils_1.combinePaths)('/', 'packages1', 'a', 'b', 'c', '__init__.py'),
461
+ content: '',
462
+ },
463
+ {
464
+ path: (0, pathUtils_1.combinePaths)('/', 'packages2', 'a', 'b', 'c', '__init__.py'),
465
+ content: '',
466
+ },
467
+ ];
468
+ const importResult = getImportResult(files, ['a', 'b', 'c', 'd'], (config) => {
469
+ config.defaultExtraPaths = [(0, pathUtils_1.combinePaths)('/', 'packages1'), (0, pathUtils_1.combinePaths)('/', 'packages2')];
470
+ });
471
+ (0, assert_1.default)(importResult.isImportFound);
472
+ });
473
+ test('nested namespace package 3', () => {
474
+ const files = [
475
+ {
476
+ path: (0, pathUtils_1.combinePaths)('/', 'packages1', 'a', 'b', 'c', 'd.py'),
477
+ content: 'def f(): pass',
478
+ },
479
+ {
480
+ path: (0, pathUtils_1.combinePaths)('/', 'packages2', 'a', '__init__.py'),
481
+ content: '',
482
+ },
483
+ ];
484
+ const importResult = getImportResult(files, ['a', 'b', 'c', 'd'], (config) => {
485
+ config.defaultExtraPaths = [(0, pathUtils_1.combinePaths)('/', 'packages1'), (0, pathUtils_1.combinePaths)('/', 'packages2')];
486
+ });
487
+ (0, assert_1.default)(!importResult.isImportFound);
488
+ });
489
+ test('nested namespace package 4', () => {
490
+ const files = [
491
+ {
492
+ path: (0, pathUtils_1.combinePaths)('/', 'packages1', 'a', 'b', '__init__.py'),
493
+ content: '',
494
+ },
495
+ {
496
+ path: (0, pathUtils_1.combinePaths)('/', 'packages1', 'a', 'b', 'c.py'),
497
+ content: 'def f(): pass',
498
+ },
499
+ {
500
+ path: (0, pathUtils_1.combinePaths)('/', 'packages2', 'a', '__init__.py'),
501
+ content: '',
502
+ },
503
+ {
504
+ path: (0, pathUtils_1.combinePaths)('/', 'packages2', 'a', 'b', '__init__.py'),
505
+ content: '',
506
+ },
507
+ ];
508
+ const importResult = getImportResult(files, ['a', 'b', 'c'], (config) => {
509
+ config.defaultExtraPaths = [(0, pathUtils_1.combinePaths)('/', 'packages1'), (0, pathUtils_1.combinePaths)('/', 'packages2')];
510
+ });
511
+ (0, assert_1.default)(!importResult.isImportFound);
495
512
  });
496
- (0, assert_1.default)(!importResult.isImportFound);
497
513
  });
498
- function getImportResult(files, nameParts, setup) {
499
- setup =
500
- setup !== null && setup !== void 0 ? setup : ((c) => {
501
- /* empty */
514
+ if (usingTrueVenv()) {
515
+ describe('Import tests that have to run with a venv', () => {
516
+ test('venv can find imports', () => {
517
+ var _a;
518
+ const files = [
519
+ {
520
+ path: (0, pathUtils_1.combinePaths)('/', 'file1.py'),
521
+ content: 'import pytest',
522
+ },
523
+ ];
524
+ const importResult = getImportResult(files, ['pytest']);
525
+ (0, assert_1.default)(importResult.isImportFound, `Import not found: ${(_a = importResult.importFailureInfo) === null || _a === void 0 ? void 0 : _a.join('\n')}`);
502
526
  });
503
- const sp = createServiceProviderFromFiles(files);
527
+ });
528
+ }
529
+ function getImportResult(files, nameParts, setup) {
530
+ const defaultHostFactory = (sp) => new testAccessHost_1.TestAccessHost(sp.fs().getModulePath(), [libraryRoot]);
531
+ const defaultSetup = setup !== null && setup !== void 0 ? setup : ((c) => {
532
+ /* empty */
533
+ });
534
+ const defaultSpFactory = (files) => createServiceProviderFromFiles(files);
535
+ // Use environment variables to determine how to create a host and how to modify the config options.
536
+ // These are set in the CI to test imports with different options.
537
+ let hostFactory = defaultHostFactory;
538
+ let configModifier = defaultSetup;
539
+ let spFactory = defaultSpFactory;
540
+ if (process.env.CI_IMPORT_TEST_VENVPATH) {
541
+ configModifier = (c) => {
542
+ defaultSetup(c);
543
+ c.venvPath = process.env.CI_IMPORT_TEST_VENVPATH;
544
+ c.venv = process.env.CI_IMPORT_TEST_VENV;
545
+ };
546
+ spFactory = (files) => createServiceProviderWithCombinedFs(files);
547
+ }
548
+ else if (process.env.CI_IMPORT_TEST_PYTHONPATH) {
549
+ configModifier = (c) => {
550
+ defaultSetup(c);
551
+ c.pythonPath = process.env.CI_IMPORT_TEST_PYTHONPATH;
552
+ };
553
+ hostFactory = (sp) => new TruePythonTestAccessHost();
554
+ spFactory = (files) => createServiceProviderWithCombinedFs(files);
555
+ }
556
+ return getImportResultImpl(files, nameParts, spFactory, configModifier, hostFactory);
557
+ }
558
+ function getImportResultImpl(files, nameParts, spFactory, configModifier, hostFactory) {
559
+ const sp = spFactory(files);
504
560
  const configOptions = new configOptions_1.ConfigOptions((0, pathUtils_1.normalizeSlashes)('/'));
505
- setup(configOptions);
561
+ configModifier(configOptions);
506
562
  const file = files.length > 0 ? files[files.length - 1].path : (0, pathUtils_1.combinePaths)('src', 'file.py');
507
563
  if (files.length === 0) {
508
564
  files.push({
@@ -510,7 +566,7 @@ function getImportResult(files, nameParts, setup) {
510
566
  content: '# not used',
511
567
  });
512
568
  }
513
- const importResolver = new importResolver_1.ImportResolver(sp, configOptions, new testAccessHost_1.TestAccessHost(sp.fs().getModulePath(), [libraryRoot]));
569
+ const importResolver = new importResolver_1.ImportResolver(sp, configOptions, hostFactory(sp));
514
570
  const importResult = importResolver.resolveImport(file, configOptions.findExecEnvironment(file), {
515
571
  leadingDots: 0,
516
572
  nameParts: nameParts,
@@ -518,7 +574,7 @@ function getImportResult(files, nameParts, setup) {
518
574
  });
519
575
  return importResult;
520
576
  }
521
- function createFileSystem(files) {
577
+ function createTestFileSystem(files) {
522
578
  const fs = new filesystem_1.TestFileSystem(/* ignoreCase */ false, { cwd: (0, pathUtils_1.normalizeSlashes)('/') });
523
579
  for (const file of files) {
524
580
  const path = (0, pathUtils_1.normalizeSlashes)(file.path);
@@ -526,10 +582,127 @@ function createFileSystem(files) {
526
582
  fs.mkdirpSync(dir);
527
583
  fs.writeFileSync(path, file.content);
528
584
  }
529
- return new pyrightFileSystem_1.PyrightFileSystem(fs);
585
+ return fs;
530
586
  }
531
587
  function createServiceProviderFromFiles(files) {
532
- const fs = createFileSystem(files);
588
+ const fs = new pyrightFileSystem_1.PyrightFileSystem(createTestFileSystem(files));
533
589
  return (0, serviceProviderExtensions_1.createServiceProvider)(fs);
534
590
  }
591
+ function createServiceProviderWithCombinedFs(files) {
592
+ const fs = new pyrightFileSystem_1.PyrightFileSystem(new CombinedFileSystem(createTestFileSystem(files)));
593
+ return (0, serviceProviderExtensions_1.createServiceProvider)(fs);
594
+ }
595
+ class TruePythonTestAccessHost extends fullAccessHost_1.FullAccessHost {
596
+ constructor() {
597
+ super((0, realFileSystem_1.createFromRealFileSystem)());
598
+ }
599
+ }
600
+ class CombinedFileSystem {
601
+ constructor(_testFS) {
602
+ this._testFS = _testFS;
603
+ this._realFS = (0, realFileSystem_1.createFromRealFileSystem)();
604
+ }
605
+ mkdirSync(path, options) {
606
+ this._testFS.mkdirSync(path, options);
607
+ }
608
+ writeFileSync(path, data, encoding) {
609
+ this._testFS.writeFileSync(path, data, encoding);
610
+ }
611
+ unlinkSync(path) {
612
+ this._testFS.unlinkSync(path);
613
+ }
614
+ rmdirSync(path) {
615
+ this._testFS.rmdirSync(path);
616
+ }
617
+ createFileSystemWatcher(paths, listener) {
618
+ return this._testFS.createFileSystemWatcher(paths, listener);
619
+ }
620
+ createReadStream(path) {
621
+ return this._testFS.createReadStream(path);
622
+ }
623
+ createWriteStream(path) {
624
+ return this._testFS.createWriteStream(path);
625
+ }
626
+ copyFileSync(src, dst) {
627
+ this._testFS.copyFileSync(src, dst);
628
+ }
629
+ tmpdir() {
630
+ return this._testFS.tmpdir();
631
+ }
632
+ tmpfile(options) {
633
+ return this._testFS.tmpfile(options);
634
+ }
635
+ dispose() {
636
+ this._testFS.dispose();
637
+ }
638
+ existsSync(path) {
639
+ return this._testFS.existsSync(path) || this._realFS.existsSync(path);
640
+ }
641
+ chdir(path) {
642
+ this._testFS.chdir(path);
643
+ }
644
+ readdirEntriesSync(path) {
645
+ if (this._testFS.existsSync(path)) {
646
+ return this._testFS.readdirEntriesSync(path);
647
+ }
648
+ return this._realFS.readdirEntriesSync(path);
649
+ }
650
+ readdirSync(path) {
651
+ if (this._testFS.existsSync(path)) {
652
+ return this._testFS.readdirSync(path);
653
+ }
654
+ return this._realFS.readdirSync(path);
655
+ }
656
+ readFileSync(path, encoding = null) {
657
+ if (this._testFS.existsSync(path)) {
658
+ return this._testFS.readFileSync(path, encoding);
659
+ }
660
+ return this._realFS.readFileSync(path, encoding);
661
+ }
662
+ statSync(path) {
663
+ if (this._testFS.existsSync(path)) {
664
+ return this._testFS.statSync(path);
665
+ }
666
+ return this._realFS.statSync(path);
667
+ }
668
+ realpathSync(path) {
669
+ if (this._testFS.existsSync(path)) {
670
+ return this._testFS.realpathSync(path);
671
+ }
672
+ return this._realFS.realpathSync(path);
673
+ }
674
+ getModulePath() {
675
+ return this._testFS.getModulePath();
676
+ }
677
+ readFile(path) {
678
+ if (this._testFS.existsSync(path)) {
679
+ return this._testFS.readFile(path);
680
+ }
681
+ return this._realFS.readFile(path);
682
+ }
683
+ readFileText(path, encoding) {
684
+ if (this._testFS.existsSync(path)) {
685
+ return this._testFS.readFileText(path, encoding);
686
+ }
687
+ return this._realFS.readFileText(path, encoding);
688
+ }
689
+ realCasePath(path) {
690
+ return this._testFS.realCasePath(path);
691
+ }
692
+ isMappedFilePath(filepath) {
693
+ return this._testFS.isMappedFilePath(filepath);
694
+ }
695
+ getOriginalFilePath(mappedFilePath) {
696
+ return this._testFS.getOriginalFilePath(mappedFilePath);
697
+ }
698
+ getMappedFilePath(originalFilepath) {
699
+ return this._testFS.getMappedFilePath(originalFilepath);
700
+ }
701
+ getUri(path) {
702
+ return this._testFS.getUri(path);
703
+ }
704
+ isInZip(path) {
705
+ return this._testFS.isInZip(path);
706
+ }
707
+ }
535
708
  //# sourceMappingURL=importResolver.test.js.map