pyOpenSourceProjects 0.2.1__tar.gz → 0.2.3__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.
- {pyopensourceprojects-0.2.1 → pyopensourceprojects-0.2.3}/.github/workflows/build.yml +4 -4
- {pyopensourceprojects-0.2.1 → pyopensourceprojects-0.2.3}/PKG-INFO +4 -3
- pyopensourceprojects-0.2.3/osprojects/__init__.py +1 -0
- {pyopensourceprojects-0.2.1 → pyopensourceprojects-0.2.3}/osprojects/checkos.py +91 -14
- {pyopensourceprojects-0.2.1 → pyopensourceprojects-0.2.3}/pyproject.toml +4 -2
- pyopensourceprojects-0.2.3/scripts/test +132 -0
- pyopensourceprojects-0.2.1/osprojects/__init__.py +0 -1
- pyopensourceprojects-0.2.1/scripts/test +0 -9
- {pyopensourceprojects-0.2.1 → pyopensourceprojects-0.2.3}/.github/workflows/upload-to-pypi.yml +0 -0
- {pyopensourceprojects-0.2.1 → pyopensourceprojects-0.2.3}/.gitignore +0 -0
- {pyopensourceprojects-0.2.1 → pyopensourceprojects-0.2.3}/.project +0 -0
- {pyopensourceprojects-0.2.1 → pyopensourceprojects-0.2.3}/.pydevproject +0 -0
- {pyopensourceprojects-0.2.1 → pyopensourceprojects-0.2.3}/LICENSE +0 -0
- {pyopensourceprojects-0.2.1 → pyopensourceprojects-0.2.3}/README.md +0 -0
- {pyopensourceprojects-0.2.1 → pyopensourceprojects-0.2.3}/mkdocs.yml +0 -0
- {pyopensourceprojects-0.2.1 → pyopensourceprojects-0.2.3}/osprojects/editor.py +0 -0
- {pyopensourceprojects-0.2.1 → pyopensourceprojects-0.2.3}/osprojects/osproject.py +0 -0
- {pyopensourceprojects-0.2.1 → pyopensourceprojects-0.2.3}/scripts/blackisort +0 -0
- {pyopensourceprojects-0.2.1 → pyopensourceprojects-0.2.3}/scripts/doc +0 -0
- {pyopensourceprojects-0.2.1 → pyopensourceprojects-0.2.3}/scripts/install +0 -0
- {pyopensourceprojects-0.2.1 → pyopensourceprojects-0.2.3}/scripts/installAndTest +0 -0
- {pyopensourceprojects-0.2.1 → pyopensourceprojects-0.2.3}/scripts/release +0 -0
- {pyopensourceprojects-0.2.1 → pyopensourceprojects-0.2.3}/tests/__init__.py +0 -0
- {pyopensourceprojects-0.2.1 → pyopensourceprojects-0.2.3}/tests/basetest.py +0 -0
- {pyopensourceprojects-0.2.1 → pyopensourceprojects-0.2.3}/tests/test_osproject.py +0 -0
|
@@ -18,10 +18,10 @@ jobs:
|
|
|
18
18
|
runs-on: ubuntu-latest
|
|
19
19
|
strategy:
|
|
20
20
|
matrix:
|
|
21
|
-
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
22
|
-
|
|
23
|
-
python-version: [ 3.9, '3.10', '3.11', '3.12' ]
|
|
24
|
-
|
|
21
|
+
#os: [ubuntu-latest, macos-latest, windows-latest]
|
|
22
|
+
os: [ubuntu-latest]
|
|
23
|
+
#python-version: [ '3.9', '3.10', '3.11', '3.12' ]
|
|
24
|
+
python-version: ["3.10"]
|
|
25
25
|
|
|
26
26
|
steps:
|
|
27
27
|
- uses: actions/checkout@v4
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: pyOpenSourceProjects
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Dynamic: Summary
|
|
5
5
|
Project-URL: Home, https://github.com/WolfgangFahl/pyOpenSourceProjects
|
|
6
6
|
Project-URL: Documentation, http://wiki.bitplan.com/index.php/pyOpenSourceProjects
|
|
@@ -15,9 +15,10 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.11
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
17
|
Requires-Python: >=3.9
|
|
18
|
+
Requires-Dist: gitpython
|
|
18
19
|
Requires-Dist: packaging>=24.1
|
|
19
|
-
Requires-Dist: py-3rdparty-mediawiki>=0.
|
|
20
|
-
Requires-Dist: pylodstorage>=0.
|
|
20
|
+
Requires-Dist: py-3rdparty-mediawiki>=0.12.0
|
|
21
|
+
Requires-Dist: pylodstorage>=0.12.2
|
|
21
22
|
Requires-Dist: python-dateutil>=2.8.2
|
|
22
23
|
Provides-Extra: test
|
|
23
24
|
Description-Content-Type: text/markdown
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.2.3"
|
|
@@ -8,6 +8,8 @@ import argparse
|
|
|
8
8
|
import os
|
|
9
9
|
from argparse import Namespace
|
|
10
10
|
from dataclasses import dataclass
|
|
11
|
+
from git import Repo
|
|
12
|
+
from git.exc import InvalidGitRepositoryError, NoSuchPathError
|
|
11
13
|
from typing import List
|
|
12
14
|
# original at ngwidgets - use redundant local copy ...
|
|
13
15
|
from osprojects.editor import Editor
|
|
@@ -49,6 +51,8 @@ class CheckOS:
|
|
|
49
51
|
self.project = project
|
|
50
52
|
self.project_path = os.path.join(self.workspace, project.id)
|
|
51
53
|
self.checks = []
|
|
54
|
+
# python 3.12 is max version
|
|
55
|
+
self.max_python_version_minor=12
|
|
52
56
|
|
|
53
57
|
@property
|
|
54
58
|
def total(self) -> int:
|
|
@@ -91,6 +95,9 @@ class CheckOS:
|
|
|
91
95
|
return local
|
|
92
96
|
|
|
93
97
|
def check_github_workflows(self):
|
|
98
|
+
"""
|
|
99
|
+
check the github workflow files
|
|
100
|
+
"""
|
|
94
101
|
workflows_path = os.path.join(self.project_path, ".github", "workflows")
|
|
95
102
|
workflows_exist = self.add_path_check(workflows_path)
|
|
96
103
|
|
|
@@ -104,8 +111,9 @@ class CheckOS:
|
|
|
104
111
|
content = file_exists.content
|
|
105
112
|
|
|
106
113
|
if file == "build.yml":
|
|
107
|
-
|
|
108
|
-
|
|
114
|
+
min_python_version_minor = int(self.requires_python.split('.')[-1])
|
|
115
|
+
self.add_check(min_python_version_minor==self.min_python_version_minor,msg=f"{min_python_version_minor} (build.yml)!={self.min_python_version_minor} (pyprojec.toml)",path=file_path)
|
|
116
|
+
python_versions = f"""python-version: [ {', '.join([f"'3.{i}'" for i in range(self.min_python_version_minor, self.max_python_version_minor+1)])} ]"""
|
|
109
117
|
self.add_content_check(
|
|
110
118
|
content,
|
|
111
119
|
python_versions,
|
|
@@ -159,12 +167,17 @@ class CheckOS:
|
|
|
159
167
|
if file=="doc":
|
|
160
168
|
self.add_content_check(content, "sphinx", file_path, negative=True)
|
|
161
169
|
self.add_content_check(content,"WF 2024-07-30 - updated",file_path)
|
|
170
|
+
if file=="test":
|
|
171
|
+
self.add_content_check(content,"WF 2024-08-03",file_path)
|
|
162
172
|
if file=="release":
|
|
163
|
-
self.add_content_check(content, "scripts/
|
|
173
|
+
self.add_content_check(content, "scripts/doc -d", file_path)
|
|
164
174
|
|
|
165
175
|
def check_readme(self):
|
|
166
176
|
readme_path = os.path.join(self.project_path, "README.md")
|
|
167
177
|
readme_exists = self.add_path_check(readme_path)
|
|
178
|
+
if not hasattr(self, "project_name"):
|
|
179
|
+
self.add_check(False, "project_name from pyproject.toml needed for README.md check", self.project_path)
|
|
180
|
+
return
|
|
168
181
|
if readme_exists.ok:
|
|
169
182
|
readme_content = readme_exists.content
|
|
170
183
|
badge_lines = [
|
|
@@ -185,7 +198,10 @@ class CheckOS:
|
|
|
185
198
|
)
|
|
186
199
|
self.add_content_check(readme_content, "readthedocs", readme_path, negative=True)
|
|
187
200
|
|
|
188
|
-
def check_pyproject_toml(self):
|
|
201
|
+
def check_pyproject_toml(self)->bool:
|
|
202
|
+
"""
|
|
203
|
+
pyproject.toml
|
|
204
|
+
"""
|
|
189
205
|
toml_path = os.path.join(self.project_path, "pyproject.toml")
|
|
190
206
|
toml_exists = self.add_path_check(toml_path)
|
|
191
207
|
if toml_exists.ok:
|
|
@@ -197,27 +213,78 @@ class CheckOS:
|
|
|
197
213
|
requires_python_check=self.add_check("requires-python" in toml_dict["project"], "requires-python", toml_path)
|
|
198
214
|
if requires_python_check.ok:
|
|
199
215
|
self.requires_python = toml_dict["project"]["requires-python"]
|
|
200
|
-
|
|
216
|
+
min_python_version = version.parse(self.requires_python.replace(">=", ""))
|
|
201
217
|
min_version_needed="3.9"
|
|
202
|
-
version_ok=
|
|
218
|
+
version_ok=min_python_version >= version.parse(min_version_needed)
|
|
203
219
|
self.add_check(version_ok, f"requires-python>={min_version_needed}", toml_path)
|
|
220
|
+
self.min_python_version_minor=int(str(min_python_version).split('.')[-1])
|
|
221
|
+
for minor_version in range(self.min_python_version_minor, self.max_python_version_minor+1):
|
|
222
|
+
needle=f"Programming Language :: Python :: 3.{minor_version}"
|
|
223
|
+
self.add_content_check(content, needle, toml_path)
|
|
204
224
|
self.add_content_check(content, "hatchling", toml_path)
|
|
205
225
|
self.add_content_check(content,"[tool.hatch.build.targets.wheel.sources]",toml_path)
|
|
226
|
+
return toml_exists.ok
|
|
227
|
+
|
|
228
|
+
def check_git(self):
|
|
229
|
+
"""
|
|
230
|
+
Check git repository information using gitpython
|
|
231
|
+
"""
|
|
232
|
+
try:
|
|
233
|
+
repo = Repo(self.project_path)
|
|
234
|
+
|
|
235
|
+
# Check if it's actually a git repository
|
|
236
|
+
if not repo.bare:
|
|
237
|
+
self.add_check(True, "Is a git repository", self.project_path)
|
|
238
|
+
|
|
239
|
+
# Get the remote URL
|
|
240
|
+
try:
|
|
241
|
+
remote_url = repo.remotes.origin.url
|
|
242
|
+
self.add_check(True, "Has remote origin", self.project_path)
|
|
206
243
|
|
|
207
|
-
|
|
244
|
+
# Extract owner and repository name from the URL
|
|
245
|
+
parts = remote_url.split('/')
|
|
246
|
+
git_owner = parts[-2]
|
|
247
|
+
git_repo = parts[-1].replace('.git', '')
|
|
248
|
+
|
|
249
|
+
# Compare with the project information we have
|
|
250
|
+
owner_match = git_owner.lower() == self.project.owner.lower()
|
|
251
|
+
self.add_check(owner_match, f"Git owner ({git_owner}) matches project owner ({self.project.owner})", self.project_path)
|
|
252
|
+
|
|
253
|
+
repo_match = git_repo.lower() == self.project.id.lower()
|
|
254
|
+
self.add_check(repo_match, f"Git repo name ({git_repo}) matches project id ({self.project.id})", self.project_path)
|
|
255
|
+
|
|
256
|
+
except AttributeError:
|
|
257
|
+
self.add_check(False, "No remote origin found", self.project_path)
|
|
258
|
+
|
|
259
|
+
# Check if there are uncommitted changes
|
|
260
|
+
if repo.is_dirty():
|
|
261
|
+
self.add_check(False, "Repository has uncommitted changes", self.project_path)
|
|
262
|
+
else:
|
|
263
|
+
self.add_check(True, "Repository is clean", self.project_path)
|
|
264
|
+
|
|
265
|
+
else:
|
|
266
|
+
self.add_check(False, "Not a valid git repository (bare repository)", self.project_path)
|
|
267
|
+
|
|
268
|
+
except InvalidGitRepositoryError:
|
|
269
|
+
self.add_check(False, "Not a valid git repository", self.project_path)
|
|
270
|
+
except NoSuchPathError:
|
|
271
|
+
self.add_check(False, "Git repository path does not exist", self.project_path)
|
|
272
|
+
|
|
273
|
+
def check(self, title:str):
|
|
208
274
|
"""
|
|
209
275
|
Check the given project and print results
|
|
210
276
|
"""
|
|
211
277
|
self.check_local()
|
|
212
|
-
self.
|
|
213
|
-
self.
|
|
214
|
-
|
|
215
|
-
|
|
278
|
+
self.check_git()
|
|
279
|
+
if self.check_pyproject_toml():
|
|
280
|
+
self.check_github_workflows()
|
|
281
|
+
self.check_readme()
|
|
282
|
+
self.check_scripts()
|
|
216
283
|
|
|
217
284
|
# ok_count=len(ok_checks)
|
|
218
285
|
failed_count = len(self.failed_checks)
|
|
219
|
-
summary = f"❌ {failed_count}/{self.total}" if failed_count > 0 else f"✅ {self.total}/{self.total}"
|
|
220
|
-
print(f"{
|
|
286
|
+
summary = f"❌ {failed_count:2}/{self.total:2}" if failed_count > 0 else f"✅ {self.total:2}/{self.total:2}"
|
|
287
|
+
print(f"{title}{summary}:{self.project}→{self.project.url}")
|
|
221
288
|
if failed_count > 0:
|
|
222
289
|
# Sort checks by path
|
|
223
290
|
sorted_checks = sorted(self.checks, key=lambda c: c.path or "")
|
|
@@ -308,9 +375,19 @@ def main(_argv=None):
|
|
|
308
375
|
local_projects.append(project)
|
|
309
376
|
projects = local_projects
|
|
310
377
|
|
|
378
|
+
# filter for git ownership
|
|
379
|
+
filtered_projects = []
|
|
311
380
|
for project in projects:
|
|
312
381
|
checker = CheckOS(args=args, project=project)
|
|
313
|
-
checker.
|
|
382
|
+
checker.check_git()
|
|
383
|
+
git_owner_check = next((check for check in checker.checks if "Git owner" in check.msg), None)
|
|
384
|
+
if git_owner_check and git_owner_check.ok:
|
|
385
|
+
filtered_projects.append(project)
|
|
386
|
+
projects = filtered_projects
|
|
387
|
+
|
|
388
|
+
for i,project in enumerate(projects):
|
|
389
|
+
checker = CheckOS(args=args, project=project)
|
|
390
|
+
checker.check(f"{i+1:3}:")
|
|
314
391
|
except Exception as ex:
|
|
315
392
|
if args.debug:
|
|
316
393
|
print(traceback.format_exc())
|
|
@@ -15,8 +15,10 @@ readme = "README.md"
|
|
|
15
15
|
license = "Apache-2.0"
|
|
16
16
|
|
|
17
17
|
dependencies = [
|
|
18
|
-
|
|
19
|
-
"
|
|
18
|
+
# https://pypi.org/project/GitPython/
|
|
19
|
+
"gitpython",
|
|
20
|
+
"pyLodStorage>=0.12.2",
|
|
21
|
+
"py-3rdparty-mediawiki>=0.12.0",
|
|
20
22
|
# https://pypi.org/project/python-dateutil/
|
|
21
23
|
"python-dateutil>=2.8.2",
|
|
22
24
|
# https://github.com/pypa/packaging
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# WF 2022-08-20
|
|
3
|
+
# WF 2024-08-03
|
|
4
|
+
|
|
5
|
+
#ansi colors
|
|
6
|
+
#http://www.csc.uvic.ca/~sae/seng265/fall04/tips/s265s047-tips/bash-using-colors.html
|
|
7
|
+
blue='\033[0;34m'
|
|
8
|
+
red='\033[0;31m'
|
|
9
|
+
green='\033[0;32m' # '\e[1;32m' is too bright for white bg.
|
|
10
|
+
endColor='\033[0m'
|
|
11
|
+
|
|
12
|
+
#
|
|
13
|
+
# a colored message
|
|
14
|
+
# params:
|
|
15
|
+
# 1: l_color - the color of the message
|
|
16
|
+
# 2: l_msg - the message to display
|
|
17
|
+
#
|
|
18
|
+
color_msg() {
|
|
19
|
+
local l_color="$1"
|
|
20
|
+
local l_msg="$2"
|
|
21
|
+
echo -e "${l_color}$l_msg${endColor}"
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
#
|
|
25
|
+
# error
|
|
26
|
+
#
|
|
27
|
+
# show the given error message on stderr and exit
|
|
28
|
+
#
|
|
29
|
+
# params:
|
|
30
|
+
# 1: l_msg - the error message to display
|
|
31
|
+
#
|
|
32
|
+
error() {
|
|
33
|
+
local l_msg="$1"
|
|
34
|
+
# use ansi red for error
|
|
35
|
+
color_msg $red "Error:" 1>&2
|
|
36
|
+
color_msg $red "\t$l_msg" 1>&2
|
|
37
|
+
exit 1
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
#
|
|
41
|
+
# show a negative message
|
|
42
|
+
#
|
|
43
|
+
negative() {
|
|
44
|
+
local l_msg="$1"
|
|
45
|
+
color_msg $red "❌:$l_msg"
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
#
|
|
49
|
+
# show a positive message
|
|
50
|
+
#
|
|
51
|
+
positive() {
|
|
52
|
+
local l_msg="$1"
|
|
53
|
+
color_msg $green "✅:$l_msg"
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
# show usage
|
|
57
|
+
#
|
|
58
|
+
usage() {
|
|
59
|
+
echo "$0 [-g|--green|-m|--module|-t|--tox|-h|--help]"
|
|
60
|
+
echo "-t |--tox: run tests with tox"
|
|
61
|
+
echo "-g |--green: run tests with green"
|
|
62
|
+
echo "-m |--module: run modulewise test"
|
|
63
|
+
echo "-h |--help: show this usage"
|
|
64
|
+
echo "default is running tests with unittest discover"
|
|
65
|
+
exit 1
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
#
|
|
69
|
+
# check and optional install the given package
|
|
70
|
+
#
|
|
71
|
+
check_package() {
|
|
72
|
+
local l_package="$1"
|
|
73
|
+
pip show $l_package > /dev/null
|
|
74
|
+
if [ $? -ne 0 ]
|
|
75
|
+
then
|
|
76
|
+
negative "$l_package"
|
|
77
|
+
color_msg $blue "installing $l_package"
|
|
78
|
+
pip install $l_package
|
|
79
|
+
else
|
|
80
|
+
positive "$l_package"
|
|
81
|
+
fi
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
#
|
|
85
|
+
# test module by module
|
|
86
|
+
#
|
|
87
|
+
modulewise_test() {
|
|
88
|
+
foundErrors=0
|
|
89
|
+
foundTests=0
|
|
90
|
+
for testmodule in tests/test*.py
|
|
91
|
+
do
|
|
92
|
+
echo "testing $testmodule ..."
|
|
93
|
+
# see https://github.com/CleanCut/green/issues/263
|
|
94
|
+
#green $testmodule -s1
|
|
95
|
+
python -m unittest $testmodule
|
|
96
|
+
exit_code=$?
|
|
97
|
+
foundErrors=$((foundErrors+exit_code))
|
|
98
|
+
foundTests=$((foundTests+1))
|
|
99
|
+
done
|
|
100
|
+
echo "$foundErrors/$foundTests module unit tests failed" 1>&2
|
|
101
|
+
if [[ $foundErrors -gt 0 ]]
|
|
102
|
+
then
|
|
103
|
+
exit 1
|
|
104
|
+
fi
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export PYTHON_PATH="."
|
|
108
|
+
while [ "$1" != "" ]
|
|
109
|
+
do
|
|
110
|
+
option="$1"
|
|
111
|
+
case $option in
|
|
112
|
+
-h|--help)
|
|
113
|
+
usage
|
|
114
|
+
exit 0
|
|
115
|
+
;;
|
|
116
|
+
-g|--green)
|
|
117
|
+
check_package green
|
|
118
|
+
green tests -s 1
|
|
119
|
+
exit 0
|
|
120
|
+
;;
|
|
121
|
+
-m|--module)
|
|
122
|
+
modulewise_test
|
|
123
|
+
exit 0
|
|
124
|
+
;;
|
|
125
|
+
-t|--tox)
|
|
126
|
+
check_package tox
|
|
127
|
+
tox -e py
|
|
128
|
+
exit 0
|
|
129
|
+
;;
|
|
130
|
+
esac
|
|
131
|
+
done
|
|
132
|
+
python3 -m unittest discover
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.2.1"
|
{pyopensourceprojects-0.2.1 → pyopensourceprojects-0.2.3}/.github/workflows/upload-to-pypi.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|