Skip to content

Commit 9565a5b

Browse files
author
Chad Smith
authored
Merge pull request #1 from cs01/cs01/create-app
convert to web app
2 parents 75966b1 + 14b5369 commit 9565a5b

36 files changed

+13714
-35
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.env
2+
data.json
3+
makefile
4+
*.service

CONTRIBUTING.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
See README files in respective folders.

README.md

Lines changed: 2 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,3 @@
1-
A summary of package management tools in the Python ecosystem
1+
An interactive web app to explore, and hopefully better understand, Python packaging tools.
22

3-
## tools
4-
5-
| | poetry | pipenv | pip | virtualenv | setup.py (setuptools) | twine | pyenv | pipsi |
6-
|--------------------------------------------------------------------------------------------|------------------------------------------|----------------------------------------------------|--------------------------|------------------------------------|------------------------------------------------------------------|---------------------------------------------------------|---------------------------|--------------------------------|
7-
| installs abstract dependencies | ✔️ | ✔️ | ✔️ | ✖️ | ✔️ | ✖️ | ✖️ | ✖️ |
8-
| installs concrete dependencies | ✔️ | ✔️ | ✔️ | ✖️ | ✖️ | ✖️ | ✖️ | ✖️ |
9-
| isolates Python environments | ✔️ | ✔️ | ✖️ | ✔️ | ✖️ | ✖️ | ✖️ | ✔️ |
10-
| captures packaging metadata (name, version, author, etc) | ✔️ | ✖️ | ✖️ | ✖️ | ✔️ | ✖️ | ✖️ | ✖️ |
11-
| file format based on a PEP | ✔️ | ✖️ | ✖️ | ✖️ | ✔️ | ✖️ | ✖️ | ✖️ |
12-
| automatically creates virtual environments | ✔️ | ✔️ | ✖️ | ✖️ | ✖️ | ✖️ | ✖️ | ✖️ |
13-
| generates concrete dependencies from abstract dependencies (requirements.txt or lock file) | ✔️ | ✔️ | ✔️ | ✖️ | ✖️ | ✖️ | ✖️ | ✖️ |
14-
| can generate lock file with hashes | ✔️ | ✔️ | ✖️ | ✖️ | ✖️ | ✖️ | ✖️ | ✖️ |
15-
| builds packages suitable for distribution on PyPI | ✔️ | ✖️ | ✖️ | ✖️ | ✔️ | ✖️ | ✖️ | ✖️ |
16-
| publishes packages to PyPI | ✔️ | ✖️ | ✖️ | ✖️ | ✖️ | ✔️ | ✖️ | ✖️ |
17-
| can enter shell for virtual environment | ✖️ | ✔️ | ✖️ | ✔️ | ✖️ | ✖️ | ✖️ | ✖️ |
18-
| installs specific Python versions to system | ✖️ | ✔️ | ✖️ | ✖️ | ✖️ | ✖️ | ✔️ | ✖️ |
19-
| globally installs and sandboxes Python packages that have command-line entry points | ✖️ | ✖️ | ✖️ | ✖️ | ✖️ | ✖️ | ✖️ | ✔️ |
20-
| relies on | virtualenv | virtualenv, pew, pip-tools, requirementslib, pyenv | - | pip, shell scripts | setuptools | - | shell scripts | virtualenv |
21-
| stated purpose | dependency management and packaging tool | development workflow tool | Python package installer | Python virtual environment builder | download, build, install, upgrade, and uninstall Python packages | Collection of utilities for publishing packages on PyPI | python version management | global Python script installer |
22-
23-
24-
## File formats
25-
26-
| | requirements.txt | Pipfile | Pipfile.lock | pyproject.toml | pyproject.lock |setup.py
27-
|-------------------|-------------------|----------------------|----------------------|----------------|----------------------|-|
28-
| purpose | todo | | | | | |
29-
| metadata captured | todo | | | | | |
30-
| origin | convention of pip | convention of Pipenv | convention of Pipenv | PEP 518 | convention of Poetry | todo |
31-
32-
33-
34-
Disclaimer: I did not author or maintain any of these tools and strive to keep this list as impartial as possible.
35-
36-
This information is accurate to the best of my knowledge. If anything is incorrect or missing please submit a pull request or create an issue.
3+
https://grassfedcode.com/python-packaging

backend/README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Backend
2+
3+
## Getting Started
4+
Install dependencies:
5+
```
6+
> yarn
7+
```
8+
Start server:
9+
```
10+
> yarn start
11+
```

backend/githubData.ts

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import { Octokit } from "@octokit/core";
2+
import * as dotenv from "dotenv";
3+
import * as fs from "fs";
4+
5+
const env = dotenv.config().parsed;
6+
const apiKey = env.API_KEY;
7+
const octokit = new Octokit({ auth: apiKey });
8+
9+
const tools = [
10+
{
11+
name: "pip",
12+
owner: "pypa",
13+
},
14+
{
15+
name: "tox",
16+
owner: "tox-dev",
17+
},
18+
{
19+
name: "nox",
20+
owner: "theacodes",
21+
},
22+
{
23+
owner: "pipxproject",
24+
name: "pipx",
25+
},
26+
{
27+
name: "poetry",
28+
owner: "python-poetry",
29+
},
30+
{
31+
name: "pipenv",
32+
owner: "pypa",
33+
},
34+
{
35+
name: "virtualenv",
36+
owner: "pypa",
37+
},
38+
{
39+
name: "pipenv",
40+
owner: "pypa",
41+
},
42+
{
43+
name: "pyenv",
44+
owner: "pyenv",
45+
},
46+
{
47+
name: "twine",
48+
owner: "pypa",
49+
},
50+
{
51+
name: "setuptools",
52+
owner: "pypa",
53+
},
54+
{
55+
name: "pip-tools",
56+
owner: "jazzband",
57+
},
58+
];
59+
60+
function getQuery(name: string, owner: string) {
61+
return `query {
62+
repository(owner: "${owner}", name: "${name}") {
63+
stargazers {
64+
totalCount
65+
}
66+
pushedAt
67+
createdAt
68+
description
69+
name
70+
issues {
71+
totalCount
72+
}
73+
licenseInfo {
74+
name
75+
}
76+
primaryLanguage {
77+
name
78+
}
79+
url
80+
homepageUrl
81+
}
82+
}`;
83+
}
84+
85+
export async function fetchGithubData() {
86+
// try {
87+
// console.error("Attempting to read data");
88+
// return JSON.parse(String(fs.readFileSync("./data.json")));
89+
// } catch (e) {
90+
// console.error(e.message);
91+
// console.error("Failed to read, fetching...");
92+
const data = (
93+
await Promise.all(
94+
tools.map((t) => {
95+
return octokit.graphql(getQuery(t.name, t.owner));
96+
})
97+
)
98+
).map((d) => d["repository"]);
99+
fs.writeFileSync("./data.json", JSON.stringify(data, null, 4));
100+
return data;
101+
// }
102+
}
103+
104+
async function main() {
105+
const response = await fetchGithubData();
106+
console.error(response);
107+
}
108+
109+
// (async () => {
110+
// try {
111+
// var text = await main();
112+
// console.log(text);
113+
// } catch (e) {
114+
// console.error(e);
115+
// }
116+
// })();

backend/package.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"name": "backend",
3+
"version": "1.0.0",
4+
"scripts": {
5+
"start": "rm ./data.json; ts-node server.ts"
6+
},
7+
"main": "index.js",
8+
"license": "MIT",
9+
"dependencies": {
10+
"@octokit/core": "^3.1.2",
11+
"@types/dotenv": "^8.2.0",
12+
"dotenv": "^8.2.0",
13+
"express": "^4.17.1",
14+
"ts-node": "^9.0.0",
15+
"typescript": "^4.0.2"
16+
},
17+
"devDependencies": {
18+
"@types/express": "^4.17.8",
19+
"@types/node": "^14.6.4"
20+
}
21+
}

backend/server.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import * as express from "express";
2+
import { fetchGithubData } from "./githubData";
3+
import * as path from "path";
4+
const app = express();
5+
const port = process.env.PORT ?? 3001;
6+
7+
const secPerMin = 60;
8+
const minPerHour = 60;
9+
const msPerSec = 1000;
10+
const hourInMs = secPerMin * minPerHour * msPerSec;
11+
let cachedData: { cachedAt: number; data: any } = {
12+
cachedAt: 0,
13+
data: null,
14+
};
15+
const maxCacheAgeMs = hourInMs;
16+
17+
const msToMinutes = (1 / msPerSec) * (1 / secPerMin);
18+
19+
app.get("/package_data", async (req, res) => {
20+
const now = Date.now();
21+
const age = now - cachedData.cachedAt;
22+
const timeUntilRefetch = maxCacheAgeMs - age;
23+
console.error(
24+
`Cache is ${age * msToMinutes} minutes old. ${
25+
timeUntilRefetch * msToMinutes
26+
} minutes left until new data is used`
27+
);
28+
if (timeUntilRefetch <= 0) {
29+
cachedData.data = await fetchGithubData();
30+
cachedData.cachedAt = now;
31+
} else {
32+
console.error("using cached data");
33+
}
34+
res.json(cachedData.data);
35+
});
36+
37+
app.use("/", express.static(path.join(__dirname, "..", "frontend", "build")));
38+
39+
app.listen(port, () => {
40+
console.log(`Example app listening at http://localhost:${port}`);
41+
});

backend/start.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#/bin/bash
2+
yarn
3+
yarn start

0 commit comments

Comments
 (0)