utopia-analyzer 1.0.0__tar.gz
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.
- utopia_analyzer-1.0.0/LICENSE +21 -0
- utopia_analyzer-1.0.0/PKG-INFO +194 -0
- utopia_analyzer-1.0.0/README.md +151 -0
- utopia_analyzer-1.0.0/pyproject.toml +35 -0
- utopia_analyzer-1.0.0/setup.cfg +4 -0
- utopia_analyzer-1.0.0/tests/test_archetypes.py +58 -0
- utopia_analyzer-1.0.0/tests/test_formatters.py +122 -0
- utopia_analyzer-1.0.0/tests/test_github_client.py +258 -0
- utopia_analyzer-1.0.0/tests/test_improvement_plan.py +93 -0
- utopia_analyzer-1.0.0/tests/test_recruiter.py +129 -0
- utopia_analyzer-1.0.0/tests/test_report.py +94 -0
- utopia_analyzer-1.0.0/tests/test_roast.py +102 -0
- utopia_analyzer-1.0.0/tests/test_scoring.py +109 -0
- utopia_analyzer-1.0.0/utopia/__init__.py +3 -0
- utopia_analyzer-1.0.0/utopia/__main__.py +6 -0
- utopia_analyzer-1.0.0/utopia/archetypes.py +168 -0
- utopia_analyzer-1.0.0/utopia/cli.py +107 -0
- utopia_analyzer-1.0.0/utopia/formatters/__init__.py +1 -0
- utopia_analyzer-1.0.0/utopia/formatters/json_output.py +50 -0
- utopia_analyzer-1.0.0/utopia/formatters/markdown_output.py +96 -0
- utopia_analyzer-1.0.0/utopia/formatters/terminal.py +130 -0
- utopia_analyzer-1.0.0/utopia/github_client.py +517 -0
- utopia_analyzer-1.0.0/utopia/improvement_plan.py +120 -0
- utopia_analyzer-1.0.0/utopia/recruiter.py +221 -0
- utopia_analyzer-1.0.0/utopia/report.py +76 -0
- utopia_analyzer-1.0.0/utopia/roast.py +121 -0
- utopia_analyzer-1.0.0/utopia/scoring.py +377 -0
- utopia_analyzer-1.0.0/utopia_analyzer.egg-info/PKG-INFO +194 -0
- utopia_analyzer-1.0.0/utopia_analyzer.egg-info/SOURCES.txt +31 -0
- utopia_analyzer-1.0.0/utopia_analyzer.egg-info/dependency_links.txt +1 -0
- utopia_analyzer-1.0.0/utopia_analyzer.egg-info/entry_points.txt +2 -0
- utopia_analyzer-1.0.0/utopia_analyzer.egg-info/requires.txt +4 -0
- utopia_analyzer-1.0.0/utopia_analyzer.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Khizar Arain
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: utopia-analyzer
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Transforms any GitHub profile into a professional developer intelligence report
|
|
5
|
+
Author-email: Khizer Arain <your@email.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2024 Khizar Arain
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://github.com/khizerarain/utopia
|
|
29
|
+
Project-URL: Repository, https://github.com/khizerarain/utopia
|
|
30
|
+
Keywords: github,portfolio,cli,developer-tools,analytics
|
|
31
|
+
Classifier: Programming Language :: Python :: 3
|
|
32
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
33
|
+
Classifier: Operating System :: OS Independent
|
|
34
|
+
Classifier: Environment :: Console
|
|
35
|
+
Requires-Python: >=3.10
|
|
36
|
+
Description-Content-Type: text/markdown
|
|
37
|
+
License-File: LICENSE
|
|
38
|
+
Requires-Dist: click>=8.0
|
|
39
|
+
Requires-Dist: rich>=13.0
|
|
40
|
+
Requires-Dist: requests>=2.28
|
|
41
|
+
Requires-Dist: python-dotenv>=1.0
|
|
42
|
+
Dynamic: license-file
|
|
43
|
+
|
|
44
|
+
# UTOPIA
|
|
45
|
+
|
|
46
|
+
> Analyze any GitHub profile and generate a professional developer portfolio report with scoring, archetypes, and recruiter insights.
|
|
47
|
+
|
|
48
|
+
**UTOPIA** (Ultimate Technical Overview & Portfolio Intelligence Analyzer) is a Python CLI tool that transforms any public GitHub profile into a detailed intelligence report. It scores the profile across six weighted categories, detects the developer's archetype, simulates an AI recruiter verdict, breaks down the tech stack, roasts bad habits (if asked nicely), and generates a 30-day improvement plan.
|
|
49
|
+
|
|
50
|
+
## Installation
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install utopia-cli
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Usage
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
utopia khizerarain
|
|
60
|
+
utopia khizerarain --roast
|
|
61
|
+
utopia khizerarain --output markdown --save report.md
|
|
62
|
+
utopia khizerarain --token YOUR_GITHUB_TOKEN
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Publishing to PyPI (for maintainers)
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
pip install build twine
|
|
69
|
+
python -m build
|
|
70
|
+
twine upload dist/*
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Built With
|
|
74
|
+
|
|
75
|
+
- [Python](https://www.python.org/) — core language
|
|
76
|
+
- [Click](https://click.palletsprojects.com/) — CLI framework
|
|
77
|
+
- [Rich](https://rich.readthedocs.io/) — terminal formatting and charts
|
|
78
|
+
|
|
79
|
+
## Development Installation
|
|
80
|
+
|
|
81
|
+
1. Clone the repository:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
git clone https://github.com/khizerarain/utopia.git
|
|
85
|
+
cd utopia
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
2. Install dependencies:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
pip install -r requirements.txt
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Development Usage
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
# Basic terminal report
|
|
98
|
+
python -m utopia.cli torvalds
|
|
99
|
+
|
|
100
|
+
# Use a GitHub token for higher rate limits
|
|
101
|
+
python -m utopia.cli torvalds --token ghp_xxxxxxxx
|
|
102
|
+
|
|
103
|
+
# Roast mode
|
|
104
|
+
python -m utopia.cli torvalds --roast
|
|
105
|
+
|
|
106
|
+
# Save as JSON
|
|
107
|
+
python -m utopia.cli torvalds --output json --save report.json
|
|
108
|
+
|
|
109
|
+
# Save as Markdown
|
|
110
|
+
python -m utopia.cli torvalds --output markdown --save report.md
|
|
111
|
+
|
|
112
|
+
# Disable colors
|
|
113
|
+
python -m utopia.cli torvalds --no-color
|
|
114
|
+
|
|
115
|
+
# Refresh cached data
|
|
116
|
+
python -m utopia.cli torvalds --no-cache
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Sample Output
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
┌───────────────────────────────────┐
|
|
123
|
+
│ UTOPIA Portfolio Report: torvalds │
|
|
124
|
+
│ UTOPIA SCORE: 80/100 │
|
|
125
|
+
│ Portfolio Grade: B- │
|
|
126
|
+
└───────────────────────────────────┘
|
|
127
|
+
|
|
128
|
+
Project Quality │ 23/25 │ ████████████████████████████░░ 92%
|
|
129
|
+
Activity │ 20/20 │ ██████████████████████████████ 98%
|
|
130
|
+
Documentation │ 11/15 │ ██████████████████████░░░░░░░░ 72%
|
|
131
|
+
Tech Diversity │ 2/15 │ ████░░░░░░░░░░░░░░░░░░░░░░░░░░ 13%
|
|
132
|
+
Impact │ 15/15 │ ██████████████████████████████ 100%
|
|
133
|
+
Open Source │ 10/10 │ ████████████████████████████░░ 95%
|
|
134
|
+
|
|
135
|
+
You are:
|
|
136
|
+
Backend Engineer ██████████████░░░░░░ 70.0%
|
|
137
|
+
DevOps Engineer ██████████████░░░░░░ 70.0%
|
|
138
|
+
AI/ML Developer ██████████░░░░░░░░░░ 50.0%
|
|
139
|
+
Data Engineer ██████████░░░░░░░░░░ 50.0%
|
|
140
|
+
|
|
141
|
+
Would I hire this developer?
|
|
142
|
+
YES
|
|
143
|
+
|
|
144
|
+
Reasons:
|
|
145
|
+
✓ Projects show ongoing maintenance
|
|
146
|
+
✓ Projects are well explained
|
|
147
|
+
✓ Repositories show solid engineering
|
|
148
|
+
✓ Includes automated tests
|
|
149
|
+
|
|
150
|
+
Strengths:
|
|
151
|
+
✓ Strong community impact
|
|
152
|
+
✓ Active development history
|
|
153
|
+
✓ Active open-source contributor
|
|
154
|
+
|
|
155
|
+
Weaknesses:
|
|
156
|
+
✗ Tech stack is narrow
|
|
157
|
+
✗ Needs more README documentation
|
|
158
|
+
✗ Project quality could improve
|
|
159
|
+
|
|
160
|
+
Tech Stack Breakdown
|
|
161
|
+
C ████████████████████ 97.7%
|
|
162
|
+
Assembly ░░░░░░░░░░░░░░░░░░░░ 0.7%
|
|
163
|
+
Shell ░░░░░░░░░░░░░░░░░░░░ 0.4%
|
|
164
|
+
Rust ░░░░░░░░░░░░░░░░░░░░ 0.3%
|
|
165
|
+
Other ░░░░░░░░░░░░░░░░░░░░ 0.9%
|
|
166
|
+
|
|
167
|
+
30-Day Upgrade Plan
|
|
168
|
+
Week 1:
|
|
169
|
+
• Contribute to an open-source project outside your main stack
|
|
170
|
+
Week 2:
|
|
171
|
+
• Improve README files across your top repos
|
|
172
|
+
Week 3:
|
|
173
|
+
• Refactor your most-starred project and add missing features
|
|
174
|
+
Week 4:
|
|
175
|
+
• Review and merge community PRs in your own repos
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## GitHub Token
|
|
179
|
+
|
|
180
|
+
GitHub's unauthenticated API limit is 60 requests per hour. For full analysis, create a Personal Access Token:
|
|
181
|
+
|
|
182
|
+
1. Go to **Settings → Developer settings → Personal access tokens → Tokens (classic)**
|
|
183
|
+
2. Generate a new token with `public_repo` scope
|
|
184
|
+
3. Use `--token <PAT>` or set `GITHUB_TOKEN` in a `.env` file
|
|
185
|
+
|
|
186
|
+
## Running Tests
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
python -m pytest tests/ -v
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## License
|
|
193
|
+
|
|
194
|
+
MIT
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# UTOPIA
|
|
2
|
+
|
|
3
|
+
> Analyze any GitHub profile and generate a professional developer portfolio report with scoring, archetypes, and recruiter insights.
|
|
4
|
+
|
|
5
|
+
**UTOPIA** (Ultimate Technical Overview & Portfolio Intelligence Analyzer) is a Python CLI tool that transforms any public GitHub profile into a detailed intelligence report. It scores the profile across six weighted categories, detects the developer's archetype, simulates an AI recruiter verdict, breaks down the tech stack, roasts bad habits (if asked nicely), and generates a 30-day improvement plan.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install utopia-cli
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
utopia khizerarain
|
|
17
|
+
utopia khizerarain --roast
|
|
18
|
+
utopia khizerarain --output markdown --save report.md
|
|
19
|
+
utopia khizerarain --token YOUR_GITHUB_TOKEN
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Publishing to PyPI (for maintainers)
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
pip install build twine
|
|
26
|
+
python -m build
|
|
27
|
+
twine upload dist/*
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Built With
|
|
31
|
+
|
|
32
|
+
- [Python](https://www.python.org/) — core language
|
|
33
|
+
- [Click](https://click.palletsprojects.com/) — CLI framework
|
|
34
|
+
- [Rich](https://rich.readthedocs.io/) — terminal formatting and charts
|
|
35
|
+
|
|
36
|
+
## Development Installation
|
|
37
|
+
|
|
38
|
+
1. Clone the repository:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
git clone https://github.com/khizerarain/utopia.git
|
|
42
|
+
cd utopia
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
2. Install dependencies:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install -r requirements.txt
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Development Usage
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# Basic terminal report
|
|
55
|
+
python -m utopia.cli torvalds
|
|
56
|
+
|
|
57
|
+
# Use a GitHub token for higher rate limits
|
|
58
|
+
python -m utopia.cli torvalds --token ghp_xxxxxxxx
|
|
59
|
+
|
|
60
|
+
# Roast mode
|
|
61
|
+
python -m utopia.cli torvalds --roast
|
|
62
|
+
|
|
63
|
+
# Save as JSON
|
|
64
|
+
python -m utopia.cli torvalds --output json --save report.json
|
|
65
|
+
|
|
66
|
+
# Save as Markdown
|
|
67
|
+
python -m utopia.cli torvalds --output markdown --save report.md
|
|
68
|
+
|
|
69
|
+
# Disable colors
|
|
70
|
+
python -m utopia.cli torvalds --no-color
|
|
71
|
+
|
|
72
|
+
# Refresh cached data
|
|
73
|
+
python -m utopia.cli torvalds --no-cache
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Sample Output
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
┌───────────────────────────────────┐
|
|
80
|
+
│ UTOPIA Portfolio Report: torvalds │
|
|
81
|
+
│ UTOPIA SCORE: 80/100 │
|
|
82
|
+
│ Portfolio Grade: B- │
|
|
83
|
+
└───────────────────────────────────┘
|
|
84
|
+
|
|
85
|
+
Project Quality │ 23/25 │ ████████████████████████████░░ 92%
|
|
86
|
+
Activity │ 20/20 │ ██████████████████████████████ 98%
|
|
87
|
+
Documentation │ 11/15 │ ██████████████████████░░░░░░░░ 72%
|
|
88
|
+
Tech Diversity │ 2/15 │ ████░░░░░░░░░░░░░░░░░░░░░░░░░░ 13%
|
|
89
|
+
Impact │ 15/15 │ ██████████████████████████████ 100%
|
|
90
|
+
Open Source │ 10/10 │ ████████████████████████████░░ 95%
|
|
91
|
+
|
|
92
|
+
You are:
|
|
93
|
+
Backend Engineer ██████████████░░░░░░ 70.0%
|
|
94
|
+
DevOps Engineer ██████████████░░░░░░ 70.0%
|
|
95
|
+
AI/ML Developer ██████████░░░░░░░░░░ 50.0%
|
|
96
|
+
Data Engineer ██████████░░░░░░░░░░ 50.0%
|
|
97
|
+
|
|
98
|
+
Would I hire this developer?
|
|
99
|
+
YES
|
|
100
|
+
|
|
101
|
+
Reasons:
|
|
102
|
+
✓ Projects show ongoing maintenance
|
|
103
|
+
✓ Projects are well explained
|
|
104
|
+
✓ Repositories show solid engineering
|
|
105
|
+
✓ Includes automated tests
|
|
106
|
+
|
|
107
|
+
Strengths:
|
|
108
|
+
✓ Strong community impact
|
|
109
|
+
✓ Active development history
|
|
110
|
+
✓ Active open-source contributor
|
|
111
|
+
|
|
112
|
+
Weaknesses:
|
|
113
|
+
✗ Tech stack is narrow
|
|
114
|
+
✗ Needs more README documentation
|
|
115
|
+
✗ Project quality could improve
|
|
116
|
+
|
|
117
|
+
Tech Stack Breakdown
|
|
118
|
+
C ████████████████████ 97.7%
|
|
119
|
+
Assembly ░░░░░░░░░░░░░░░░░░░░ 0.7%
|
|
120
|
+
Shell ░░░░░░░░░░░░░░░░░░░░ 0.4%
|
|
121
|
+
Rust ░░░░░░░░░░░░░░░░░░░░ 0.3%
|
|
122
|
+
Other ░░░░░░░░░░░░░░░░░░░░ 0.9%
|
|
123
|
+
|
|
124
|
+
30-Day Upgrade Plan
|
|
125
|
+
Week 1:
|
|
126
|
+
• Contribute to an open-source project outside your main stack
|
|
127
|
+
Week 2:
|
|
128
|
+
• Improve README files across your top repos
|
|
129
|
+
Week 3:
|
|
130
|
+
• Refactor your most-starred project and add missing features
|
|
131
|
+
Week 4:
|
|
132
|
+
• Review and merge community PRs in your own repos
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## GitHub Token
|
|
136
|
+
|
|
137
|
+
GitHub's unauthenticated API limit is 60 requests per hour. For full analysis, create a Personal Access Token:
|
|
138
|
+
|
|
139
|
+
1. Go to **Settings → Developer settings → Personal access tokens → Tokens (classic)**
|
|
140
|
+
2. Generate a new token with `public_repo` scope
|
|
141
|
+
3. Use `--token <PAT>` or set `GITHUB_TOKEN` in a `.env` file
|
|
142
|
+
|
|
143
|
+
## Running Tests
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
python -m pytest tests/ -v
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## License
|
|
150
|
+
|
|
151
|
+
MIT
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "utopia-analyzer"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "Transforms any GitHub profile into a professional developer intelligence report"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = { file = "LICENSE" }
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [{ name = "Khizer Arain", email = "your@email.com" }]
|
|
13
|
+
keywords = ["github", "portfolio", "cli", "developer-tools", "analytics"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
"Environment :: Console",
|
|
19
|
+
]
|
|
20
|
+
dependencies = [
|
|
21
|
+
"click>=8.0",
|
|
22
|
+
"rich>=13.0",
|
|
23
|
+
"requests>=2.28",
|
|
24
|
+
"python-dotenv>=1.0",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[project.scripts]
|
|
28
|
+
utopia = "utopia.cli:main"
|
|
29
|
+
|
|
30
|
+
[project.urls]
|
|
31
|
+
Homepage = "https://github.com/khizerarain/utopia"
|
|
32
|
+
Repository = "https://github.com/khizerarain/utopia"
|
|
33
|
+
|
|
34
|
+
[tool.setuptools.packages.find]
|
|
35
|
+
include = ["utopia*"]
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""Tests for the archetype detection module."""
|
|
2
|
+
|
|
3
|
+
from utopia.archetypes import detect_archetypes
|
|
4
|
+
from utopia.github_client import ProfileData, RepoData
|
|
5
|
+
from tests.test_scoring import make_profile, make_repo
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_backend_archetype_detected():
|
|
9
|
+
repos = [
|
|
10
|
+
make_repo(language="Python", topics=["api", "backend", "database"]),
|
|
11
|
+
make_repo(language="Go", topics=["microservices"]),
|
|
12
|
+
]
|
|
13
|
+
profile = make_profile(
|
|
14
|
+
repos=repos,
|
|
15
|
+
total_languages={"Python": 500000, "Go": 200000},
|
|
16
|
+
)
|
|
17
|
+
results = detect_archetypes(profile)
|
|
18
|
+
top = results[0]
|
|
19
|
+
assert top.key == "backend"
|
|
20
|
+
assert top.percentage > 0
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def test_frontend_archetype_detected():
|
|
24
|
+
repos = [
|
|
25
|
+
make_repo(language="TypeScript", topics=["react", "frontend", "ui"]),
|
|
26
|
+
make_repo(language="JavaScript", topics=["vue"]),
|
|
27
|
+
]
|
|
28
|
+
profile = make_profile(
|
|
29
|
+
repos=repos,
|
|
30
|
+
total_languages={"TypeScript": 400000, "JavaScript": 100000},
|
|
31
|
+
)
|
|
32
|
+
results = detect_archetypes(profile)
|
|
33
|
+
assert any(r.key == "frontend" and r.percentage > 0 for r in results)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_full_stack_derived_from_both():
|
|
37
|
+
repos = [
|
|
38
|
+
make_repo(language="Python", topics=["api", "backend"]),
|
|
39
|
+
make_repo(language="TypeScript", topics=["react", "frontend"]),
|
|
40
|
+
]
|
|
41
|
+
profile = make_profile(
|
|
42
|
+
repos=repos,
|
|
43
|
+
total_languages={"Python": 300000, "TypeScript": 300000},
|
|
44
|
+
)
|
|
45
|
+
results = detect_archetypes(profile)
|
|
46
|
+
assert any(r.key == "full_stack" for r in results)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def test_devops_signals_detected():
|
|
50
|
+
repos = [
|
|
51
|
+
make_repo(language="Python", has_workflows=True, has_dockerfile=True, topics=["docker", "kubernetes"]),
|
|
52
|
+
]
|
|
53
|
+
profile = make_profile(
|
|
54
|
+
repos=repos,
|
|
55
|
+
total_languages={"Python": 100000},
|
|
56
|
+
)
|
|
57
|
+
results = detect_archetypes(profile)
|
|
58
|
+
assert any(r.key == "devops" and r.percentage > 0 for r in results)
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"""Tests for the output formatters."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from datetime import datetime, timedelta, timezone
|
|
5
|
+
|
|
6
|
+
from utopia.formatters import json_output, markdown_output, terminal
|
|
7
|
+
from utopia.github_client import ProfileData, RepoData
|
|
8
|
+
from utopia.report import build_report
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _now_iso(days_ago: int = 0) -> str:
|
|
12
|
+
dt = datetime.now(timezone.utc) - timedelta(days=days_ago)
|
|
13
|
+
return dt.isoformat().replace("+00:00", "Z")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def make_repo(**kwargs) -> RepoData:
|
|
17
|
+
defaults = {
|
|
18
|
+
"name": "repo",
|
|
19
|
+
"description": "A repo",
|
|
20
|
+
"language": "Python",
|
|
21
|
+
"stars": 5,
|
|
22
|
+
"forks": 1,
|
|
23
|
+
"size_kb": 500,
|
|
24
|
+
"created_at": _now_iso(365),
|
|
25
|
+
"updated_at": _now_iso(10),
|
|
26
|
+
"pushed_at": _now_iso(10),
|
|
27
|
+
"has_readme": True,
|
|
28
|
+
"readme_word_count": 120,
|
|
29
|
+
"open_issues_count": 0,
|
|
30
|
+
"topics": ["api", "backend"],
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"is_fork": False,
|
|
33
|
+
"is_archived": False,
|
|
34
|
+
"languages": {"Python": 10000},
|
|
35
|
+
"commit_activity": [2] * 52,
|
|
36
|
+
"has_tests": False,
|
|
37
|
+
"has_workflows": False,
|
|
38
|
+
"has_dockerfile": False,
|
|
39
|
+
}
|
|
40
|
+
defaults.update(kwargs)
|
|
41
|
+
return RepoData(**defaults)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def make_profile(repos=None, **kwargs) -> ProfileData:
|
|
45
|
+
total_languages: dict[str, int] = {}
|
|
46
|
+
for repo in repos or []:
|
|
47
|
+
for lang, bytes_count in repo.languages.items():
|
|
48
|
+
total_languages[lang] = total_languages.get(lang, 0) + bytes_count
|
|
49
|
+
return ProfileData(
|
|
50
|
+
username="testuser",
|
|
51
|
+
name="Test",
|
|
52
|
+
bio=None,
|
|
53
|
+
followers=10,
|
|
54
|
+
following=0,
|
|
55
|
+
public_repos_count=len(repos) if repos else 0,
|
|
56
|
+
created_at=_now_iso(1000),
|
|
57
|
+
repos=repos or [],
|
|
58
|
+
merged_prs_count=2,
|
|
59
|
+
total_languages=total_languages,
|
|
60
|
+
**kwargs,
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _sample_report(roast: bool = False):
|
|
65
|
+
repos = [
|
|
66
|
+
make_repo(name="api", language="Python", topics=["api", "backend"]),
|
|
67
|
+
make_repo(name="ui", language="JavaScript", topics=["react", "frontend"]),
|
|
68
|
+
]
|
|
69
|
+
profile = make_profile(repos=repos)
|
|
70
|
+
return build_report(profile, roast_mode=roast)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def test_terminal_render_no_color():
|
|
74
|
+
report = _sample_report()
|
|
75
|
+
output = terminal.render(report, no_color=True)
|
|
76
|
+
assert "UTOPIA SCORE" in output
|
|
77
|
+
assert "Project Quality" in output
|
|
78
|
+
assert "You are:" in output
|
|
79
|
+
assert "Would I hire" in output
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def test_terminal_render_with_roast():
|
|
83
|
+
report = _sample_report(roast=True)
|
|
84
|
+
output = terminal.render(report, no_color=True)
|
|
85
|
+
assert "UTOPIA ROAST" in output
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def test_json_output_is_valid():
|
|
89
|
+
report = _sample_report()
|
|
90
|
+
output = json_output.render(report)
|
|
91
|
+
data = json.loads(output)
|
|
92
|
+
assert data["username"] == "testuser"
|
|
93
|
+
assert "score" in data
|
|
94
|
+
assert "archetypes" in data
|
|
95
|
+
assert "recruiter" in data
|
|
96
|
+
assert "improvement_plan" in data
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def test_json_output_includes_roast_when_enabled():
|
|
100
|
+
report = _sample_report(roast=True)
|
|
101
|
+
output = json_output.render(report)
|
|
102
|
+
data = json.loads(output)
|
|
103
|
+
assert "roast" in data
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def test_markdown_output_contains_sections():
|
|
107
|
+
report = _sample_report(roast=True)
|
|
108
|
+
output = markdown_output.render(report)
|
|
109
|
+
assert "# UTOPIA Portfolio Report: testuser" in output
|
|
110
|
+
assert "## Score Breakdown" in output
|
|
111
|
+
assert "## Developer Archetype" in output
|
|
112
|
+
assert "## Recruiter Verdict" in output
|
|
113
|
+
assert "## Portfolio Roast" in output
|
|
114
|
+
assert "## 30-Day Upgrade Plan" in output
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def test_markdown_output_ascii_safe():
|
|
118
|
+
report = _sample_report()
|
|
119
|
+
output = markdown_output.render(report)
|
|
120
|
+
# Markdown bars should use only ASCII chars
|
|
121
|
+
assert "█" not in output
|
|
122
|
+
assert "░" not in output
|