Skip to content

Commit 935f5e4

Browse files
Issue 27 -- Command runner prefixes and deduce install command from build backend (#28)
* Deduce install command for PDM * Command prefix support for PDM and POE. * Build * Remove no longer applicable comment * Build
1 parent 2211a56 commit 935f5e4

File tree

7 files changed

+193
-37
lines changed

7 files changed

+193
-37
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ These are the fields for `project` objects in the output:
3737
- **pythonVersion**: Value of `[project.requires-python]` or `[tool.poetry.dependencies.python]` from `pyproject.toml`
3838

3939
- **installCommand**: The shell command to run to create and install dependencies into the virtual environment.
40+
This can either be specified explicitly in `[tool.tasks.install]` or deduced from the `[build-system.build-backend]`
4041

4142
- **testCommand**: The shell command to run to execute the tests for the project.
4243

__snapshots__/find-python-projects.test.js.snap

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ exports[`find-python-projects finds projects 1`] = `
1818
"test-fixtures/multi-project/project-1/pyproject.toml",
1919
"test-fixtures/multi-project/project-2/pyproject.toml",
2020
"test-fixtures/multi-project/project-4/pyproject.toml",
21+
"test-fixtures/multi-project/project-5/pyproject.toml",
22+
"test-fixtures/multi-project/project-6/pyproject.toml",
2123
],
2224
"projects": [
2325
{
@@ -42,12 +44,33 @@ exports[`find-python-projects finds projects 1`] = `
4244
},
4345
{
4446
"directory": "test-fixtures/multi-project/project-4",
47+
"installCommand": null,
4548
"name": "sub-project-4",
4649
"packageCommand": null,
4750
"path": "test-fixtures/multi-project/project-4/pyproject.toml",
4851
"pythonVersion": "^3.9",
4952
"testCommand": null,
5053
},
54+
{
55+
"buildBackend": "pdm.backend",
56+
"directory": "test-fixtures/multi-project/project-5",
57+
"installCommand": "pdm install",
58+
"name": "project-5",
59+
"packageCommand": null,
60+
"path": "test-fixtures/multi-project/project-5/pyproject.toml",
61+
"pythonVersion": "==3.12.*",
62+
"testCommand": "pdm run test",
63+
},
64+
{
65+
"buildBackend": "poetry.core.masonry.api",
66+
"directory": "test-fixtures/multi-project/project-6",
67+
"installCommand": "poetry install",
68+
"name": "sub-project-1",
69+
"packageCommand": null,
70+
"path": "test-fixtures/multi-project/project-6/pyproject.toml",
71+
"pythonVersion": "^3.9",
72+
"testCommand": "poe run test",
73+
},
5174
],
5275
"testable-projects": [
5376
{
@@ -60,6 +83,26 @@ exports[`find-python-projects finds projects 1`] = `
6083
"pythonVersion": "^3.9",
6184
"testCommand": "poetry run pytest",
6285
},
86+
{
87+
"buildBackend": "pdm.backend",
88+
"directory": "test-fixtures/multi-project/project-5",
89+
"installCommand": "pdm install",
90+
"name": "project-5",
91+
"packageCommand": null,
92+
"path": "test-fixtures/multi-project/project-5/pyproject.toml",
93+
"pythonVersion": "==3.12.*",
94+
"testCommand": "pdm run test",
95+
},
96+
{
97+
"buildBackend": "poetry.core.masonry.api",
98+
"directory": "test-fixtures/multi-project/project-6",
99+
"installCommand": "poetry install",
100+
"name": "sub-project-1",
101+
"packageCommand": null,
102+
"path": "test-fixtures/multi-project/project-6/pyproject.toml",
103+
"pythonVersion": "^3.9",
104+
"testCommand": "poe run test",
105+
},
63106
],
64107
}
65108
`;

dist/index.js

Lines changed: 51 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/index.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

find-python-projects.js

Lines changed: 51 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -50,19 +50,10 @@ async function findPythonProjects(rootDir) {
5050
const pythonVersion = get_best_config(projectTomlParsed, PYTHON_VERSION_PATHS);
5151

5252
const buildBackend = projectTomlParsed?.['build-system']?.['build-backend'];
53-
const usePoetry = (buildBackend || '').startsWith('poetry');
53+
const installCommand = determine_install_command(projectTomlParsed, buildBackend)
5454

55-
// TODO: Figure out the best way to deal with this. The issue is that some tools, like Poetry, need a separate
56-
// `poetry install` before subsequent `poetry run ...` operations can take place.
57-
// Best bet is to experiment with PDM to see how it behaves (eg does it automatically do an install when
58-
// necessary as part of executing a task/script)
59-
const installCommand = buildBackend && (usePoetry ? 'poetry install' : 'pip install');
60-
61-
// TODO : Need to make this more adaptive in how it resolves the final shell command. For instance,
62-
// if it is a POE command, the returned shell command should be `poe run test`. Similarly for other
63-
// task runners, including PDM (I think).
64-
const testCommand = get_best_config(projectTomlParsed, TEST_COMMAND_PATHS);
65-
const packageCommand = get_best_config(projectTomlParsed, PACKAGE_COMMAND_PATHS);
55+
const testCommand = get_best_command(projectTomlParsed, TEST_COMMAND_PATHS);
56+
const packageCommand = get_best_command(projectTomlParsed, PACKAGE_COMMAND_PATHS);
6657

6758
projects.push({
6859
name: projectName,
@@ -92,6 +83,45 @@ function get_best_config(configRoot, knownPaths, defaultValue = null) {
9283
return defaultValue;
9384
}
9485

86+
function get_best_command(configRoot, knownPaths) {
87+
for (const knownPath of knownPaths) {
88+
const commandPath = knownPath.tomlPath
89+
const value = _get(configRoot, commandPath)
90+
if (value) {
91+
const runnerPrefix = knownPath?.context?.runnerPrefix
92+
if(runnerPrefix) {
93+
const commandPathParts = commandPath.split('.')
94+
const commandName = commandPathParts[commandPathParts.length - 1]
95+
return [runnerPrefix, commandName].join(' ')
96+
}
97+
else
98+
return value
99+
}
100+
}
101+
return null;
102+
}
103+
104+
function determine_install_command(projectTomlParsed, buildBackend) {
105+
// First check explicit task command
106+
const explicitInstallCommand = get_best_config(projectTomlParsed, [
107+
'tool.tasks.install'
108+
])
109+
if (explicitInstallCommand) return explicitInstallCommand
110+
111+
// Otherwise deduce from the build backend.
112+
113+
if (!buildBackend) return null
114+
115+
const buildBackendPackage = buildBackend.split('.')[0]
116+
117+
return INSTALL_COMMANDS_BY_BUILD_BACKEND_PACKAGE[buildBackendPackage] ?? null
118+
}
119+
120+
const INSTALL_COMMANDS_BY_BUILD_BACKEND_PACKAGE = {
121+
poetry: 'poetry install',
122+
pdm: 'pdm install'
123+
}
124+
95125
const PROJECT_NAME_PATHS = [
96126
'project.name', // PEP-621
97127
'tool.poetry.name'
@@ -102,14 +132,17 @@ const PYTHON_VERSION_PATHS = [
102132
'tool.poetry.dependencies.python'
103133
];
104134

135+
const POE_RUN_PREFIX = 'poe run'
136+
const PDM_RUN_PREFIX = 'pdm run'
137+
105138
const TEST_COMMAND_PATHS = [
106-
'tool.tasks.test',
107-
'tool.pdm.scripts.test',
108-
'tool.poe.tasks.test'
139+
{tomlPath: 'tool.tasks.test'},
140+
{tomlPath: 'tool.pdm.scripts.test', context: {runnerPrefix: PDM_RUN_PREFIX}},
141+
{tomlPath: 'tool.poe.tasks.test', context: {runnerPrefix: POE_RUN_PREFIX}}
109142
];
110143

111144
const PACKAGE_COMMAND_PATHS = [
112-
'tool.tasks.package',
113-
'tool.pdm.scripts.package',
114-
'tool.poe.tasks.package'
145+
{tomlPath: 'tool.tasks.package'},
146+
{tomlPath: 'tool.pdm.scripts.package', context: {runnerPrefix: PDM_RUN_PREFIX}},
147+
{tomlPath: 'tool.poe.tasks.package', context: {runnerPrefix: POE_RUN_PREFIX}}
115148
];
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
[project]
2+
name = "project-5"
3+
version = "0.1.0"
4+
description = "Default template for PDM package"
5+
authors = [
6+
{name = "BrandonLWhite", email = "brandonlwhite@gmail.com"},
7+
]
8+
dependencies = []
9+
requires-python = "==3.12.*"
10+
readme = "README.md"
11+
license = {text = "MIT"}
12+
13+
[build-system]
14+
requires = ["pdm-backend"]
15+
build-backend = "pdm.backend"
16+
17+
[tool.pdm]
18+
distribution = false
19+
20+
[tool.pdm.dev-dependencies]
21+
dev = [
22+
"pytest>=8.0.0",
23+
]
24+
25+
[tool.pdm.scripts]
26+
test = "pytest"
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[tool.poetry]
2+
name = "sub-project-1"
3+
version = "0.1.0"
4+
description = ""
5+
authors = ["Your Name <you@example.com>"]
6+
readme = "README.md"
7+
8+
[tool.poetry.dependencies]
9+
python = "^3.9"
10+
11+
12+
[tool.poetry.group.dev.dependencies]
13+
pytest = "^7.4.0"
14+
15+
[build-system]
16+
requires = ["poetry-core"]
17+
build-backend = "poetry.core.masonry.api"
18+
19+
[tool.poe.tasks]
20+
test = "pytest -vv"

0 commit comments

Comments
 (0)