project-compass 4.3.2 → 4.3.6
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.
- package/package.json +2 -2
- package/src/detectors/python.js +51 -47
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "project-compass",
|
|
3
|
-
"version": "4.3.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "4.3.6",
|
|
4
|
+
"description": "\ud83e\udded Futuristic TUI workspace navigator & runner - AI-powered project detection for Node, Python, Rust, Go, Java, PHP, Ruby, .NET",
|
|
5
5
|
"main": "src/cli.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"project-compass": "src/cli.js"
|
package/src/detectors/python.js
CHANGED
|
@@ -23,27 +23,39 @@ function getPythonPackageManager(projectPath) {
|
|
|
23
23
|
|
|
24
24
|
function gatherPythonDependencies(projectPath) {
|
|
25
25
|
const deps = new Set();
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
|
|
27
|
+
// Only read requirements.txt
|
|
28
|
+
const reqPath = path.join(projectPath, 'requirements.txt');
|
|
29
|
+
if (fs.existsSync(reqPath)) {
|
|
30
|
+
const raw = fs.readFileSync(reqPath, 'utf-8');
|
|
29
31
|
raw.split(/\r?\n/).forEach((line) => {
|
|
30
32
|
const clean = line.trim().split('#')[0].trim();
|
|
31
33
|
if (!clean || clean.startsWith('-') || clean.startsWith('"') || clean.startsWith("'")) return;
|
|
32
34
|
const match = clean.match(/^([a-zA-Z0-9_.-]+)/);
|
|
33
35
|
if (match) deps.add(match[1].toLowerCase());
|
|
34
36
|
});
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Only read requirements-dev.txt
|
|
40
|
+
const reqDevPath = path.join(projectPath, 'requirements-dev.txt');
|
|
41
|
+
if (fs.existsSync(reqDevPath)) {
|
|
42
|
+
const raw = fs.readFileSync(reqDevPath, 'utf-8');
|
|
43
|
+
raw.split(/\r?\n/).forEach((line) => {
|
|
44
|
+
const clean = line.trim().split('#')[0].trim();
|
|
45
|
+
if (!clean || clean.startsWith('-') || clean.startsWith('"') || clean.startsWith("'")) return;
|
|
46
|
+
const match = clean.match(/^([a-zA-Z0-9_.-]+)/);
|
|
47
|
+
if (match) deps.add(match[1].toLowerCase());
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Only read pyproject.toml dependencies section
|
|
40
52
|
const pyproject = path.join(projectPath, 'pyproject.toml');
|
|
41
53
|
if (fs.existsSync(pyproject)) {
|
|
42
54
|
const content = fs.readFileSync(pyproject, 'utf-8');
|
|
43
55
|
const depSection = content.match(/(?:dependencies|requires)\s*=\s*\[([^\]]+)\]/g);
|
|
44
56
|
if (depSection) {
|
|
45
57
|
depSection.forEach((section) => {
|
|
46
|
-
const matches = section.match(/["']([^"']+)
|
|
58
|
+
const matches = section.match(/["']([^"']+)/g);
|
|
47
59
|
if (matches) {
|
|
48
60
|
matches.forEach((m) => {
|
|
49
61
|
const dep = m.replace(/["']/g, '').split(/[>=<=~!]/)[0].trim();
|
|
@@ -53,11 +65,12 @@ function gatherPythonDependencies(projectPath) {
|
|
|
53
65
|
});
|
|
54
66
|
}
|
|
55
67
|
}
|
|
56
|
-
|
|
68
|
+
|
|
69
|
+
// Only read Pipfile
|
|
57
70
|
const pipfile = path.join(projectPath, 'Pipfile');
|
|
58
71
|
if (fs.existsSync(pipfile)) {
|
|
59
72
|
const content = fs.readFileSync(pipfile, 'utf-8');
|
|
60
|
-
const matches = content.match(/["']([^"']+)
|
|
73
|
+
const matches = content.match(/["']([^"']+)/g);
|
|
61
74
|
if (matches) {
|
|
62
75
|
matches.forEach((m) => {
|
|
63
76
|
const dep = m.replace(/["']/g, '').split(/[>=<=~!]/)[0].trim();
|
|
@@ -65,15 +78,15 @@ function gatherPythonDependencies(projectPath) {
|
|
|
65
78
|
});
|
|
66
79
|
}
|
|
67
80
|
}
|
|
68
|
-
|
|
81
|
+
|
|
69
82
|
return Array.from(deps);
|
|
70
83
|
}
|
|
71
84
|
|
|
72
85
|
function detectPythonFramework(deps) {
|
|
73
86
|
const frameworks = [];
|
|
74
87
|
|
|
75
|
-
const hasDep = (pattern) =>
|
|
76
|
-
deps.some(dep => {
|
|
88
|
+
const hasDep = (pattern) => {
|
|
89
|
+
return deps.some((dep) => {
|
|
77
90
|
const depLower = dep.toLowerCase();
|
|
78
91
|
return depLower === pattern.toLowerCase() ||
|
|
79
92
|
depLower.startsWith(pattern.toLowerCase() + '==') ||
|
|
@@ -81,24 +94,25 @@ function detectPythonFramework(deps) {
|
|
|
81
94
|
depLower.startsWith(pattern.toLowerCase() + '<=') ||
|
|
82
95
|
depLower.startsWith(pattern.toLowerCase() + '~=');
|
|
83
96
|
});
|
|
97
|
+
};
|
|
84
98
|
|
|
85
|
-
if (hasDep('fastapi')) frameworks.push({ name: 'FastAPI', icon: '
|
|
86
|
-
if (hasDep('flask')) frameworks.push({ name: 'Flask', icon: '
|
|
87
|
-
if (hasDep('django')) frameworks.push({ name: 'Django', icon: '
|
|
88
|
-
if (hasDep('tornado')) frameworks.push({ name: 'Tornado', icon: '
|
|
89
|
-
if (hasDep('aiohttp')) frameworks.push({ name: 'AioHTTP', icon: '
|
|
90
|
-
if (hasDep('sanic')) frameworks.push({ name: 'Sanic', icon: '
|
|
91
|
-
if (hasDep('pyramid')) frameworks.push({ name: 'Pyramid', icon: '
|
|
92
|
-
if (hasDep('falcon')) frameworks.push({ name: 'Falcon', icon: '
|
|
93
|
-
if (hasDep('starlette')) frameworks.push({ name: 'Starlette', icon: '
|
|
94
|
-
if (hasDep('pandas')) frameworks.push({ name: 'Pandas', icon: '
|
|
95
|
-
if (hasDep('numpy')) frameworks.push({ name: 'NumPy', icon: '
|
|
96
|
-
if (hasDep('scipy')) frameworks.push({ name: 'SciPy', icon: '
|
|
97
|
-
if (hasDep('torch') || hasDep('pytorch')) frameworks.push({ name: 'PyTorch', icon: '
|
|
98
|
-
if (hasDep('tensorflow')) frameworks.push({ name: 'TensorFlow', icon: '
|
|
99
|
-
if (hasDep('sqlalchemy')) frameworks.push({ name: 'SQLAlchemy', icon: '
|
|
100
|
-
if (hasDep('pytest')) frameworks.push({ name: 'Pytest', icon: '
|
|
101
|
-
if (hasDep('celery')) frameworks.push({ name: 'Celery', icon: '
|
|
99
|
+
if (hasDep('fastapi')) frameworks.push({ name: 'FastAPI', icon: '⚡' });
|
|
100
|
+
if (hasDep('flask')) frameworks.push({ name: 'Flask', icon: '🌶️' });
|
|
101
|
+
if (hasDep('django')) frameworks.push({ name: 'Django', icon: '🌿' });
|
|
102
|
+
if (hasDep('tornado')) frameworks.push({ name: 'Tornado', icon: '🌪️' });
|
|
103
|
+
if (hasDep('aiohttp')) frameworks.push({ name: 'AioHTTP', icon: '🔄' });
|
|
104
|
+
if (hasDep('sanic')) frameworks.push({ name: 'Sanic', icon: '🚀' });
|
|
105
|
+
if (hasDep('pyramid')) frameworks.push({ name: 'Pyramid', icon: '🔺' });
|
|
106
|
+
if (hasDep('falcon')) frameworks.push({ name: 'Falcon', icon: '🦅' });
|
|
107
|
+
if (hasDep('starlette')) frameworks.push({ name: 'Starlette', icon: '⭐' });
|
|
108
|
+
if (hasDep('pandas')) frameworks.push({ name: 'Pandas', icon: '🐼' });
|
|
109
|
+
if (hasDep('numpy')) frameworks.push({ name: 'NumPy', icon: '🔢' });
|
|
110
|
+
if (hasDep('scipy')) frameworks.push({ name: 'SciPy', icon: '🔬' });
|
|
111
|
+
if (hasDep('torch') || hasDep('pytorch')) frameworks.push({ name: 'PyTorch', icon: '🔥' });
|
|
112
|
+
if (hasDep('tensorflow')) frameworks.push({ name: 'TensorFlow', icon: '🧠' });
|
|
113
|
+
if (hasDep('sqlalchemy')) frameworks.push({ name: 'SQLAlchemy', icon: '🗄️' });
|
|
114
|
+
if (hasDep('pytest')) frameworks.push({ name: 'Pytest', icon: '✅' });
|
|
115
|
+
if (hasDep('celery')) frameworks.push({ name: 'Celery', icon: '🥬' });
|
|
102
116
|
|
|
103
117
|
return frameworks;
|
|
104
118
|
}
|
|
@@ -117,8 +131,10 @@ export default {
|
|
|
117
131
|
const isPoetry = pkgManager === 'poetry';
|
|
118
132
|
const isPipenv = pkgManager === 'pipenv';
|
|
119
133
|
|
|
134
|
+
const allDeps = gatherPythonDependencies(projectPath);
|
|
135
|
+
const detectedFrameworks = detectPythonFramework(allDeps);
|
|
136
|
+
|
|
120
137
|
const commands = {};
|
|
121
|
-
|
|
122
138
|
if (isUV) {
|
|
123
139
|
commands.install = { label: 'UV Sync', command: ['uv', 'sync'], source: 'builtin' };
|
|
124
140
|
commands.add = { label: 'UV Add', command: ['uv', 'add'], source: 'builtin' };
|
|
@@ -151,28 +167,16 @@ export default {
|
|
|
151
167
|
|
|
152
168
|
if (hasProjectFile(projectPath, 'manage.py')) {
|
|
153
169
|
const djangoCmd = isUV ? ['uv', 'run', 'python', 'manage.py'] :
|
|
154
|
-
|
|
155
|
-
['python', 'manage.py'];
|
|
170
|
+
['python', 'manage.py'];
|
|
156
171
|
commands['runserver'] = { label: 'Django Runserver', command: [...djangoCmd, 'runserver'], source: 'builtin' };
|
|
157
172
|
commands['migrate'] = { label: 'Django Migrate', command: [...djangoCmd, 'migrate'], source: 'builtin' };
|
|
158
173
|
commands['test'] = { label: 'Django Test', command: [...djangoCmd, 'test'], source: 'builtin' };
|
|
159
174
|
}
|
|
160
175
|
|
|
161
|
-
if (hasProjectFile(projectPath, 'fastapi') || hasProjectFile(projectPath, 'main.py')) {
|
|
162
|
-
if (hasProjectFile(projectPath, 'main.py')) {
|
|
163
|
-
const fastapiCmd = isUV ? ['uv', 'run', 'uvicorn', 'main:app', '--reload'] :
|
|
164
|
-
['uvicorn', 'main:app', '--reload'];
|
|
165
|
-
commands['dev'] = { label: 'FastAPI Dev', command: fastapiCmd, source: 'builtin' };
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const allDeps = gatherPythonDependencies(projectPath);
|
|
170
|
-
const detectedFrameworks = detectPythonFramework(allDeps);
|
|
171
|
-
|
|
172
176
|
const metadata = {
|
|
173
177
|
dependencies: allDeps,
|
|
174
|
-
|
|
175
|
-
|
|
178
|
+
frameworks: detectedFrameworks,
|
|
179
|
+
packageManager: pkgManager
|
|
176
180
|
};
|
|
177
181
|
|
|
178
182
|
const setupHints = [];
|