Skip to content

Commit

Permalink
fix(nx-python): resolve poetry export local path for windows (#244)
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasvieirasilva authored Aug 12, 2024
1 parent 07ec917 commit 6b65b68
Show file tree
Hide file tree
Showing 3 changed files with 195 additions and 1 deletion.
188 changes: 188 additions & 0 deletions packages/nx-python/src/executors/build/executor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import '../../utils/mocks/fs.mock';
import '../../utils/mocks/cross-spawn.mock';
import { uuidMock } from '../../utils/mocks/uuid.mock';
import * as poetryUtils from '../utils/poetry';
import * as osUtils from '../utils/os';
import executor from './executor';
import { existsSync, readFileSync, mkdirsSync, writeFileSync } from 'fs-extra';
import { parse } from '@iarna/toml';
Expand Down Expand Up @@ -498,6 +499,193 @@ describe('Build Executor', () => {
expect(output.success).toBe(true);
});

it('should build python project with local dependencies Windows', async () => {
vol.fromJSON({
'apps/app/.venv/pyvenv.cfg': 'fake',
'apps/app/app/index.py': 'print("Hello from app")',
'apps/app/poetry.lock': dedent`
[[package]]
name = "click"
version = "7.1.2"
description = "Composable command line interface toolkit"
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
[[package]]
name = "dep1"
version = "1.0.0"
description = "Dep1"
category = "main"
optional = false
python-versions = "^3.8"
develop = false
[package.dependencies]
numpy = "1.21.0"
[package.source]
type = "directory"
url = "../../libs/dep1"
[[package]]
name = "numpy"
version = "1.21.0"
description = "NumPy is the fundamental package for array computing with Python."
category = "main"
optional = false
python-versions = ">=3.7"
`,

'apps/app/pyproject.toml': dedent`
[tool.poetry]
name = "app"
version = "1.0.0"
[[tool.poetry.packages]]
include = "app"
[tool.poetry.dependencies]
python = "^3.8"
click = "7.1.2"
dep1 = { path = "../../libs/dep1" }
[tool.poetry.group.dev.dependencies]
pytest = "6.2.4"
`,

'libs/dep1/dep1/index.py': 'print("Hello from dep1")',
'libs/dep1/pyproject.toml': dedent`
[tool.poetry]
name = "dep1"
version = "1.0.0"
[[tool.poetry.packages]]
include = "dep1"
[tool.poetry.dependencies]
python = "^3.8"
numpy = "1.21.0"
[tool.poetry.group.dev.dependencies]
pytest = "6.2.4"
`,

'libs/dep2/dep2/index.py': 'print("Hello from dep2")',
'libs/dep2/pyproject.toml': dedent`
[tool.poetry]
name = "dep2"
version = "1.0.0"
[[tool.poetry.packages]]
include = "dep2"
[tool.poetry.dependencies]
python = "^3.8"
[tool.poetry.group.dev.dependencies]
pytest = "6.2.4"
`,
});

vi.spyOn(osUtils, 'isWindows').mockReturnValue(true);

vi.mocked(spawn.sync).mockImplementation((_, args, opts) => {
if (args[0] == 'build') {
spawnBuildMockImpl(opts);
} else if (args[0] == 'export' && opts.cwd === 'apps/app') {
writeFileSync(
join(buildPath, 'requirements.txt'),
dedent`
click==7.1.2
-e file:///${process.cwd()}/libs/dep1
numpy==1.21.0; python_version >= "3.8" and python_version < "4.0"
`, // file:///C:/Users/ (Windows) to C:/Users/
);
}
return {
status: 0,
output: [''],
pid: 0,
signal: null,
stderr: null,
stdout: null,
};
});

const options: BuildExecutorSchema = {
ignorePaths: ['.venv', '.tox', 'tests/'],
silent: false,
outputPath: 'dist/apps/app',
keepBuildFolder: true,
devDependencies: false,
lockedVersions: true,
bundleLocalDependencies: true,
};

const output = await executor(options, {
cwd: '',
root: '.',
isVerbose: false,
projectName: 'app',
workspace: {
version: 2,
projects: {
app: {
root: 'apps/app',
targets: {},
},
dep1: {
root: 'libs/dep1',
targets: {},
},
dep2: {
root: 'libs/dep2',
targets: {},
},
},
},
});

expect(checkPoetryExecutableMock).toHaveBeenCalled();
expect(activateVenvMock).toHaveBeenCalledWith('.');
expect(existsSync(buildPath)).toBeTruthy();
expect(existsSync(`${buildPath}/app`)).toBeTruthy();
expect(existsSync(`${buildPath}/dep1`)).toBeTruthy();
expect(existsSync(`${buildPath}/dist/app.fake`)).toBeTruthy();
expect(spawn.sync).toHaveBeenCalledWith('poetry', ['build'], {
cwd: buildPath,
shell: false,
stdio: 'inherit',
});

const projectTomlData = parse(
readFileSync(`${buildPath}/pyproject.toml`).toString('utf-8'),
) as PyprojectToml;

expect(projectTomlData.tool.poetry.packages).toStrictEqual([
{
include: 'app',
},
{
include: 'dep1',
},
]);

expect(projectTomlData.tool.poetry.dependencies).toStrictEqual({
python: '^3.8',
click: '7.1.2',
numpy: {
version: '1.21.0',
optional: false,
markers: 'python_version >= "3.8" and python_version < "4.0"',
},
});
expect(projectTomlData.tool.poetry.group.dev.dependencies).toStrictEqual(
{},
);

expect(output.success).toBe(true);
});

it('should throw an exception when poetry-plugin-export@1.8.0 local project is not a valid poetry project', async () => {
vol.fromJSON({
'apps/app/.venv/pyvenv.cfg': 'fake',
Expand Down
5 changes: 4 additions & 1 deletion packages/nx-python/src/executors/build/resolvers/locked.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import chalk from 'chalk';
import { parseToml, runPoetry } from '../../utils/poetry';
import uri2path from 'file-uri-to-path';
import { getLoggingTab, includeDependencyPackage } from './utils';
import { isWindows } from '../../utils/os';

export class LockedDependencyResolver {
private logger: Logger;
Expand Down Expand Up @@ -187,7 +188,9 @@ export class LockedDependencyResolver {

private extractLocalPackageInfo(exportedLineElements: string[]) {
if (exportedLineElements[0].startsWith('-e file:')) {
const location = exportedLineElements[0].substring(10).trim();
const location = isWindows()
? exportedLineElements[0].substring(11).trim() // -e file:///C:/Users/
: exportedLineElements[0].substring(10).trim(); // -e file:///Users/
const pyprojectToml = path.join(location, 'pyproject.toml');
if (!existsSync(pyprojectToml)) {
throw new Error(
Expand Down
3 changes: 3 additions & 0 deletions packages/nx-python/src/executors/utils/os.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function isWindows() {
return process.platform === 'win32';
}

0 comments on commit 6b65b68

Please sign in to comment.