Skip to content

Commit 551bd20

Browse files
committed
feat: First commit with a mvp
0 parents  commit 551bd20

26 files changed

+500
-0
lines changed

.gitignore

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
# Visual Studio Code / Enviroment
2+
.vscode
3+
.envrc
4+
5+
# Byte-compiled / optimized / DLL files
6+
__pycache__/
7+
*.py[cod]
8+
*$py.class
9+
10+
# C extensions
11+
*.so
12+
13+
# Distribution / packaging
14+
.Python
15+
build/
16+
develop-eggs/
17+
dist/
18+
downloads/
19+
eggs/
20+
.eggs/
21+
lib/
22+
lib64/
23+
parts/
24+
sdist/
25+
var/
26+
wheels/
27+
pip-wheel-metadata/
28+
share/python-wheels/
29+
*.egg-info/
30+
.installed.cfg
31+
*.egg
32+
MANIFEST
33+
34+
# PyInstaller
35+
# Usually these files are written by a python script from a template
36+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
37+
*.manifest
38+
*.spec
39+
40+
# Installer logs
41+
pip-log.txt
42+
pip-delete-this-directory.txt
43+
44+
# Unit test / coverage reports
45+
htmlcov/
46+
.tox/
47+
.nox/
48+
.coverage
49+
.coverage.*
50+
.cache
51+
nosetests.xml
52+
coverage.xml
53+
*.cover
54+
*.py,cover
55+
.hypothesis/
56+
.pytest_cache/
57+
58+
# Translations
59+
*.mo
60+
*.pot
61+
62+
# Django stuff:
63+
*.log
64+
local_settings.py
65+
db.sqlite3
66+
db.sqlite3-journal
67+
68+
# Flask stuff:
69+
instance/
70+
.webassets-cache
71+
72+
# Scrapy stuff:
73+
.scrapy
74+
75+
# Sphinx documentation
76+
docs/_build/
77+
78+
# PyBuilder
79+
target/
80+
81+
# Jupyter Notebook
82+
.ipynb_checkpoints
83+
84+
# IPython
85+
profile_default/
86+
ipython_config.py
87+
88+
# pyenv
89+
.python-version
90+
91+
# pipenv
92+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
93+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
94+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
95+
# install all needed dependencies.
96+
#Pipfile.lock
97+
98+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
99+
__pypackages__/
100+
101+
# Celery stuff
102+
celerybeat-schedule
103+
celerybeat.pid
104+
105+
# SageMath parsed files
106+
*.sage.py
107+
108+
# Environments
109+
.env
110+
.venv
111+
env/
112+
venv/
113+
ENV/
114+
env.bak/
115+
venv.bak/
116+
117+
# Spyder project settings
118+
.spyderproject
119+
.spyproject
120+
121+
# Rope project settings
122+
.ropeproject
123+
124+
# mkdocs documentation
125+
/site
126+
127+
# mypy
128+
.mypy_cache/
129+
.dmypy.json
130+
dmypy.json
131+
132+
# Pyre type checker
133+
.pyre/

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# proyecto depex

app/__init__.py

Whitespace-only changes.

app/controllers/__init__.py

Whitespace-only changes.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
from fastapi import APIRouter, Body, status
2+
from fastapi.responses import JSONResponse
3+
from fastapi.encoders import jsonable_encoder
4+
5+
from app.models.graph_model import GraphModel
6+
from app.models.package_model import PackageModel
7+
from app.models.version_model import VersionModel
8+
9+
from app.services.graph_service import add_graph
10+
from app.services.package_service import add_package
11+
from app.services.version_package import add_version
12+
13+
from app.utils.json_encoder import JSONEncoder
14+
from app.utils.ctc_parser import parse_constraints
15+
from app.utils.filter import filter_versions
16+
17+
from app.managers.pypi import requires_dist
18+
19+
20+
router = APIRouter()
21+
22+
@router.post("/graph", response_description="Generate graph", response_model = GraphModel)
23+
async def generate_graph(graph: GraphModel = Body(...)):
24+
graph = jsonable_encoder(graph)
25+
graph['packages'] = list()
26+
req_dist = requires_dist(graph['name'])
27+
28+
for dist in req_dist:
29+
30+
package: PackageModel = {
31+
'name': dist,
32+
'versions': list()
33+
}
34+
35+
constraints = parse_constraints(req_dist[dist])
36+
37+
versions = filter_versions(dist, constraints)
38+
39+
for version in versions:
40+
version: VersionModel = version
41+
42+
new_version = await add_version(version)
43+
44+
package['versions'].append(new_version['_id'])
45+
46+
new_package = await add_package(package)
47+
48+
graph['packages'].append(new_package['_id'])
49+
50+
new_graph = await add_graph(graph)
51+
52+
return JSONResponse(status_code = status.HTTP_201_CREATED, content = JSONEncoder().encode(new_graph))

app/managers/__init__.py

Whitespace-only changes.

app/managers/pypi.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
from requests import get
2+
3+
def get_all_versions(pkg_name: str) -> list[str]:
4+
url = f'https://pypi.python.org/pypi/{pkg_name}/json'
5+
releases = get(url).json()['releases']
6+
versions = list()
7+
8+
for release in releases:
9+
release_date = None
10+
for item in releases[release]:
11+
release_date = item['upload_time']
12+
13+
aux = release.replace('.', '')
14+
15+
if aux.isdigit():
16+
versions.append({
17+
'release': release,
18+
'release_date': release_date
19+
})
20+
21+
return versions
22+
23+
def requires_dist(pkg_name):
24+
url = f'https://pypi.python.org/pypi/{pkg_name}/json'
25+
requires_dist = get(url).json()['info']['requires_dist']
26+
dists = dict()
27+
28+
for dist in requires_dist:
29+
dist, raw_ctcs = dist.split(' ')[0:2]
30+
ctcs = list()
31+
32+
for ctc in raw_ctcs.split(','):
33+
raw_ctc = ctc.replace('(', '').replace(')', '')
34+
35+
pos: int = 0
36+
for char in raw_ctc:
37+
if char.isdigit():
38+
pos = raw_ctc.index(char)
39+
break
40+
41+
version = raw_ctc[:pos]
42+
op = raw_ctc[pos:]
43+
44+
op = 'Any' if op.__eq__(';') else op
45+
46+
ctcs.append(f'{version} {op}')
47+
48+
dists[dist] = ctcs
49+
50+
return dists

app/models/__init__.py

Whitespace-only changes.

app/models/graph_model.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
from pydantic import BaseModel, Field
2+
3+
from app.models.package_model import PackageModel
4+
5+
6+
class GraphModel(BaseModel):
7+
owner: str = Field(...)
8+
name: str = Field(...)
9+
manager: str = Field(...)
10+
# root: PackageModel | None = None
11+
packages: list[PackageModel] | None = None
12+
# relationships: list['RelationshipModel'] | None = None
13+
14+
class Config:
15+
allow_population_by_field_name = True
16+
arbitrary_types_allowed = True
17+
schema_extra = {
18+
"example": {
19+
"owner": "urllib3",
20+
"name": "urllib3",
21+
"manager": "PIP"
22+
}
23+
}

app/models/package_edge_model.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from pydantic import BaseModel, Field
2+
3+
from app.models.version_model import VersionModel
4+
5+
6+
class PackageEdgeModel(BaseModel):
7+
parent: 'VersionModel' = Field(...)
8+
# child: 'PackageModel' | None = None
9+
constraints: list[str] | None = None
10+
schema_extra = {
11+
"example": {
12+
"constraints": "[<=0.7.0, ==1.2.1, >2.3]",
13+
}
14+
}
15+
16+
class Config:
17+
allow_population_by_field_name = True
18+
arbitrary_types_allowed = True

0 commit comments

Comments
 (0)