Skip to content

Commit f93aef8

Browse files
authored
Merge pull request #68 from eoyilmaz/67-mordernize-the-python-library
67 mordernize the python library
2 parents cb924ad + d38cbbb commit f93aef8

18 files changed

Lines changed: 562 additions & 361 deletions

.github/workflows/python-package.yml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,17 @@ name: Python package
55

66
on:
77
push:
8-
branches: [ master, develop ]
8+
branches: [ main, develop ]
99
pull_request:
10-
branches: [ master, develop ]
10+
branches: [ main, develop ]
1111

1212
jobs:
1313
build:
1414

1515
runs-on: ubuntu-latest
1616
strategy:
1717
matrix:
18-
python-version: [3.8, 3.9, "3.10", "3.11", "3.12"]
18+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
1919

2020
steps:
2121
- uses: actions/checkout@v2
@@ -26,14 +26,14 @@ jobs:
2626
- name: Install dependencies
2727
run: |
2828
python -m pip install --upgrade pip
29-
pip install flake8 pytest
30-
if [ -f requirements-dev.txt ]; then pip install -r requirements-dev.txt; fi
31-
- name: Lint with flake8
29+
pip install uv
30+
if [ -f requirements-dev.txt ]; then uv pip install -r requirements-dev.txt --system; fi
31+
- name: Lint with ruff
3232
run: |
3333
# stop the build if there are Python syntax errors or undefined names
34-
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
34+
ruff check --statistics ./src
3535
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
36-
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
36+
ruff check --statistics --exit-zero ./src
3737
- name: Test with pytest
3838
run: |
39-
pytest
39+
PYTHONPATH=./src pytest -n auto -W ignore --color=yes --cov-report term --cov-report html --cov=src/timecode;

.gitignore

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
1-
*~*
2-
*.pyc
3-
.DS_Store
41
.coverage
2+
.DS_Store
3+
.pytest_cache/*
4+
.ruff_cache/*
5+
.venv/*
6+
*.egg-info
57
*.egg-info/*
8+
*.pyc
69
*.swp
7-
.venv/*
10+
*~*
11+
build/*
12+
dist/
13+
docs/doctrees/*
814
docs/html/*
915
docs/latex/*
10-
docs/doctrees/*
1116
docs/source/generated/*
12-
dist/
13-
build/*
1417
include/*
18+
__pycache__

MANIFEST.in

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,6 @@
1-
include *.txt *.ini *.cfg *.rst *.py
2-
3-
include CHANGELOG
4-
include TODO
5-
include README
6-
include INSTALL
7-
include MANIFEST.in
1+
include CHANGELOG.rst
82
include LICENSE
9-
include timecode.py
10-
recursive-include docs *
11-
recursive-include tests *
12-
13-
prune docs/build
14-
prune docs/source/generated
3+
include MANIFEST.in
4+
include README.md
5+
global-exclude __pycache__
6+
global-exclude *.py[cod]

Makefile

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
SHELL:=bash
2+
NUM_CPUS = $(shell nproc || grep -c '^processor' /proc/cpuinfo)
3+
PACKAGE_NAME = timecode
4+
SETUP_PY_FLAGS = --use-distutils
5+
VERSION := $(shell cat VERSION)
6+
VERSION_FILE=$(CURDIR)/VERSION
7+
VIRTUALENV_DIR:=.venv
8+
SYSTEM_PYTHON?=python3
9+
10+
all: build FORCE
11+
12+
.PHONY: help
13+
help:
14+
@echo ""
15+
@echo "Available targets:"
16+
@make -qp | grep -o '^[a-z0-9-]\+' | sort
17+
18+
.PHONY: venv
19+
venv:
20+
@printf "\n\033[36m--- $@: Creating Local virtualenv '$(VIRTUALENV_DIR)' using '`which python`' ---\033[0m\n"
21+
$(SYSTEM_PYTHON) -m venv $(VIRTUALENV_DIR)
22+
23+
build:
24+
@printf "\n\033[36m--- $@: Building $(PACKAGE_NAME) ---\033[0m"
25+
@printf "\n\033[36m--- $@: Local install into virtualenv '$(VIRTUALENV_DIR)' ---\033[0m";
26+
@source ./$(VIRTUALENV_DIR)/bin/activate; \
27+
printf "\n\033[36m--- $@: Using python interpreter '`which python`' ---\033[0m\n"; \
28+
pip install uv; \
29+
uv pip install -r requirements.txt -r requirements-dev.txt; \
30+
uv build;
31+
32+
install:
33+
@printf "\n\033[36m--- $@: Installing $(PACKAGE_NAME) to virtualenv at '$(VIRTUALENV_DIR)' using '`which python`' ---\033[0m\n"
34+
source ./$(VIRTUALENV_DIR)/bin/activate; \
35+
uv pip install ./dist/$(PACKAGE_NAME)-$(VERSION)-*.whl --force-reinstall;
36+
37+
clean: FORCE
38+
@printf "\n\033[36m--- $@: Clean ---\033[0m\n"
39+
-rm -rf .pytest_cache
40+
-rm -rf .coverage
41+
-rm -rf .ruff_cache
42+
-rm -rf .tox
43+
-rm -rf $(VIRTUALENV_DIR)
44+
-rm -rf dist
45+
-rm -rf build
46+
-rm -Rf src/$(PACKAGE_NAME)/__pycache__
47+
-rm -Rf tests/__pycache__
48+
49+
clean-all: clean
50+
@printf "\n\033[36m--- $@: Clean All---\033[0m\n"
51+
-rm -f INSTALLED_FILES
52+
-rm -f setuptools-*.egg
53+
-rm -f use-distutils
54+
-rm -f main.py
55+
-rm -Rf htmlcov
56+
-rm .coverage.*
57+
-rm -Rf src/$(PACKAGE_NAME).egg-info
58+
-rm -Rf $(VIRTUALENV_DIR)
59+
60+
html:
61+
./setup.py readme
62+
63+
new-release:
64+
@printf "\n\033[36m--- $@: Generating New Release ---\033[0m\n"
65+
git add $(VERSION_FILE)
66+
git commit -m "Version $(VERSION)"
67+
git push
68+
git checkout main
69+
git pull
70+
git merge develop
71+
git tag $(VERSION)
72+
git push origin main --tags
73+
@source ./$(VIRTUALENV_DIR)/bin/activate; \
74+
printf "\n\033[36m--- $@: Using python interpreter '`which python`' ---\033[0m\n"; \
75+
uv pip install -r requirements.txt; \
76+
uv pip install -r requirements-dev.txt; \
77+
uv build; \
78+
twine check dist/$(PACKAGE_NAME)-$(VERSION).tar.gz; \
79+
twine upload dist/$(PACKAGE_NAME)-$(VERSION).tar.gz;
80+
81+
.PHONY: tests
82+
tests:
83+
@printf "\n\033[36m--- $@: Run Tests ---\033[0m"
84+
@printf "\n\033[36m--- $@: Using virtualenv at '$(VIRTUALENV_DIR)' ---\033[0m"; \
85+
source ./$(VIRTUALENV_DIR)/bin/activate; \
86+
printf "\n\033[36m--- $@: Using python interpreter '`which python`' ---\033[0m\n"; \
87+
PYTHONPATH=src pytest -n auto -W ignore --color=yes --cov-report term --cov-report html --cov=src/$(PACKAGE_NAME);
88+
89+
# https://www.gnu.org/software/make/manual/html_node/Force-Targets.html
90+
FORCE:

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
![license](https://img.shields.io/pypi/l/timecode.svg)
2+
![pyversion](https://img.shields.io/pypi/pyversions/timecode.svg)
3+
![pypiversion](https://img.shields.io/pypi/v/timecode.svg)
4+
![wheel](https://img.shields.io/pypi/wheel/timecode.svg)
5+
16
About
27
-----
38

VERSION

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
src/timecode/VERSION

pyproject.toml

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
[build-system]
2+
build-backend = "setuptools.build_meta"
3+
requires = [
4+
"setuptools",
5+
]
6+
7+
[project]
8+
authors = [
9+
{name = "Erkan Özgür Yılmaz", email = "eoyilmaz@gmail.com"},
10+
]
11+
classifiers = [
12+
"Development Status :: 5 - Production/Stable",
13+
"Environment :: MacOS X",
14+
"Environment :: Win32 (MS Windows)",
15+
"Environment :: X11 Applications",
16+
"Intended Audience :: End Users/Desktop",
17+
"Operating System :: OS Independent",
18+
"Programming Language :: Python",
19+
"Programming Language :: Python :: 3.9",
20+
"Programming Language :: Python :: 3.10",
21+
"Programming Language :: Python :: 3.11",
22+
"Programming Language :: Python :: 3.12",
23+
"Programming Language :: Python :: 3.13",
24+
"Programming Language :: Python :: 3.14",
25+
"Topic :: Software Development :: Libraries :: Python Modules",
26+
]
27+
description = "SMPTE Time Code Manipulation Library"
28+
dynamic = ["version"]
29+
keywords = ["video", "timecode", "smpte"]
30+
license = "MIT"
31+
maintainers = [
32+
{name = "Erkan Özgür Yılmaz", email = "eoyilmaz@gmail.com"},
33+
]
34+
name = "timecode"
35+
readme = "README.md"
36+
requires-python = ">= 3.9"
37+
38+
[project.urls]
39+
"Home Page" = "https://github.com/eoyilmaz/timecode"
40+
GitHub = "https://github.com/eoyilmaz/timecode"
41+
Repository = "https://github.com/eoyilmaz/timecode.git"
42+
Download = "https://github.com/eoyilmaz/timecode/releases/"
43+
44+
[tool.distutils.bdist_rpm]
45+
doc-files = "LICENSE README.md"
46+
fix-python = 1
47+
packager = "Erkan Ozgur Yilmaz <eoyilmaz@gmail.com>"
48+
release = 1
49+
50+
[tool.distutils.bdist_wheel]
51+
universal = 0
52+
53+
[tool.distutils.install]
54+
record = "INSTALLED_FILES"
55+
56+
[tool.setuptools]
57+
include-package-data = false
58+
59+
[tool.setuptools.packages.find]
60+
where = ["./src"]
61+
62+
[tool.setuptools.package-data]
63+
timecode = [
64+
"LICENSE",
65+
"src/timecode/py.typed",
66+
"README.md",
67+
"VERSION",
68+
]
69+
70+
[tool.setuptools.exclude-package-data]
71+
DisplayCAL = [
72+
"docs",
73+
"tests",
74+
"tests/__pycache__"
75+
]
76+
77+
[tool.setuptools.dynamic]
78+
dependencies = { file = ["requirements.txt"] }
79+
optional-dependencies.test = { file = ["requirements-dev.txt"] }
80+
version = { file = ["VERSION"] }
81+
82+
[tool.black]
83+
line-length = 88
84+
85+
[tool.flake8]
86+
exclude = [
87+
"__pycache__",
88+
".coverage",
89+
".DS_Store",
90+
".github",
91+
".pytest_cache",
92+
".ruff_cache",
93+
".venv",
94+
".vscode",
95+
"build",
96+
"dist",
97+
"docs",
98+
"INSTALLED_FILES",
99+
"MANIFEST.in",
100+
"tests",
101+
"timecode.egg-info",
102+
"VERSION",
103+
]
104+
extend-select = ["B950"]
105+
ignore = ["D107", "E203", "E501", "E701", "SC200", "W503"]
106+
max-complexity = 12
107+
max-line-length = 80
108+
per-file-ignores = [
109+
"DisplayCAL/lib/agw/fmresources.py: B950"
110+
]
111+
112+
[tool.ruff.lint]
113+
select = [
114+
"A", # flake8-builtins
115+
"ANN", # flake-annotations
116+
"ASYNC", # flake-async
117+
"B", # flake8-bugbear
118+
"C", # McCabe complexity
119+
"C4", # flake8-comprehensions
120+
"COM", # flake8-commas
121+
"D", # pydocstyle
122+
"E", # pycodestyle
123+
"F", # Pyflakes
124+
"FA", # flake8-future-annotations
125+
"FLY", # flynt
126+
"I", # isort
127+
"INT", # flake8-gettext
128+
"ISC", # flake8-implicit-str-concat
129+
"LOG", # flake8-logging
130+
"N", # PEP8 Naming
131+
"NPY", # NumPy-specific rules
132+
"PERF", # perflint
133+
"PIE", # flake8-pie
134+
"PLR", # Pylint - Refactor
135+
"PYI", # flake8-pyi
136+
"RET", # flake8-return
137+
"RSE", # flake8-raise
138+
"RUF", # Ruff-specific-rules
139+
"Q", # flake8-quotes
140+
"S", # flake-bandit
141+
"SIM", # flake8-simplify
142+
"SLOT", # flake8-slots
143+
"T10", # flake8-debugger
144+
"TC", # flake8-type-checking
145+
"TID", # flake8-tidy-imports
146+
"UP", # pyupgrade
147+
"YTT", # flake-2020
148+
149+
]
150+
extend-ignore = [
151+
"ANN002", # missing type annotations args
152+
"ANN003", # missing type annotations kwargs
153+
"COM812", # flake8-commas
154+
"D104", # Missing docstring in in publish package
155+
"D107", # skip docstring for __init__
156+
"D203", # Incorrect blank line before class
157+
"D209", # New line after last paragraph in docstring
158+
"D213", # Multiline docstring summary second line
159+
"D412", # Bland line between header and content
160+
"D416", # Missing section name colon
161+
"E741", # Ambiguous variable name
162+
"E402", # Module level import not at top of file
163+
"PLR0911", # Too many return statements
164+
"PLR0912", # Too many branches
165+
"PLR0913", # Too many arguments
166+
"PLR0914", # Too many local variables
167+
"PLR0915", # Too many statements
168+
"PLR2004", # Magic value comparison
169+
"PERF203", # Try..except in loop, TODO: Re-enable this later on...
170+
"RUF100", # Unused noqa
171+
"S105", # Hardcoded password
172+
"S110", # try..except..pass
173+
"S603", # Subprocess without shell=True
174+
]
175+
176+
[tool.ruff.lint.mccabe]
177+
max-complexity = 12
178+
179+
[tool.ruff.lint.pydocstyle]
180+
convention = "google"
181+
182+
[tool.pytest.ini_options]
183+
pythonpath = [
184+
".",
185+
]
186+
187+
[tool.tox]
188+
requires = ["tox>=4.23.2"]
189+
env_list = ["3.9", "3.10", "3.11", "3.12", "3.13"]
190+
191+
[tool.tox.env_run_base]
192+
description = "run the tests with pytest"
193+
package = "wheel"
194+
wheel_build_env = ".pkg"
195+
deps = [
196+
"pytest>=6",
197+
"pytest-cov",
198+
"pytest-xdist",
199+
]
200+
commands = [
201+
["pytest"],
202+
]
203+
204+
[tool.mypy]

0 commit comments

Comments
 (0)