diff --git a/Makefile b/Makefile index 16c9659..ba0b4d7 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: help wheel test-behave test test-behave-cov coverage lint +.PHONY: help wheel test-behave test test-behave-cov coverage lint publish version help: @echo "Targets:" @@ -9,6 +9,8 @@ help: @echo " test-behave-cov Run behave with coverage (appends to .coverage)" @echo " coverage Run combined pytest + behave coverage and export reports" @echo " lint Run pylint with fail-under threshold" + @echo " publish Upload dist/* to PyPI via twine" + @echo " version Show package version and git SHA" test-behave: PYTHONPATH=. behave -f progress2 @@ -36,4 +38,22 @@ lint: PYLINTHOME=.pylint.d pylint jsocket tests features/steps --fail-under=9.0 --persistent=n --disable=duplicate-code wheel: - python setup.py bdist_wheel + python -m build --wheel + +publish: + python -m build + python -m twine check dist/* + python -m twine upload dist/* + +version: + @python -c "import pathlib, re; p = pathlib.Path('jsocket/_version.py'); m = re.search(r'__version__\\s*=\\s*[\\\"\\']([^\\\"\\']+)[\\\"\\']', p.read_text(encoding='utf-8')); print(f\"version: {m.group(1) if m else 'unknown'}\")" + @sha=$$(git log -1 --format=%h 2>/dev/null); \ + if [ -n "$$sha" ]; then \ + if [ -n "$$(git status --porcelain 2>/dev/null)" ]; then \ + echo "git: $$sha (dirty)"; \ + else \ + echo "git: $$sha"; \ + fi; \ + else \ + echo "git: unknown"; \ + fi diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..0a1867d --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,34 @@ +[build-system] +requires = ["setuptools>=61", "wheel"] +build-backend = "setuptools.build_meta" + +[project] +name = "jsocket" +dynamic = ["version"] +description = "Python JSON Server & Client" +readme = "README.md" +requires-python = ">=3.8" +license = {file = "LICENSE"} +authors = [{name = "Christopher Piekarski", email = "chris@cpiekarski.com"}] +maintainers = [{name = "Christopher Piekarski", email = "chris@cpiekarski.com"}] +keywords = ["json", "socket", "server", "client"] +classifiers = [ + "Intended Audience :: Developers", + "Programming Language :: Python :: 3.9", + "Operating System :: OS Independent", + "Development Status :: 5 - Production/Stable", + "Topic :: System :: Networking", + "Topic :: Software Development :: Libraries :: Application Frameworks", + "Topic :: System :: Distributed Computing", + "Topic :: System :: Hardware :: Symmetric Multi-processing", +] + +[project.urls] +Homepage = "https://cpiekarski.com/2012/01/25/python-json-client-server-redux/" + +[tool.setuptools] +packages = ["jsocket"] +license-files = ["LICENSE"] + +[tool.setuptools.dynamic] +version = {attr = "jsocket._version.__version__"} diff --git a/requirements-dev.txt b/requirements-dev.txt index e5c0dab..48d632b 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -4,3 +4,5 @@ pytest-timeout>=2.1 coverage>=7.5 pytest-cov>=4.1 pylint>=3.2 +build>=1.0 +twine>=5.0 diff --git a/setup.py b/setup.py index 6e9303a..2553605 100644 --- a/setup.py +++ b/setup.py @@ -1,47 +1,6 @@ #!/usr/bin/env python -from setuptools import setup, Extension -import pathlib -import re +from setuptools import setup - -def _read_version(): - version_file = pathlib.Path(__file__).parent / "jsocket" / "_version.py" - content = version_file.read_text(encoding="utf-8") - match = re.search(r'^__version__\s*=\s*[\'"]([^\'"]+)[\'"]', content, re.M) - if not match: - raise RuntimeError("Unable to find __version__ in jsocket/_version.py") - return match.group(1) - - -def _read_long_description(): - readme = pathlib.Path(__file__).parent / "README.md" - return readme.read_text(encoding="utf-8") - -setup(name='jsocket', - version=_read_version(), - description='Python JSON Server & Client', - long_description=_read_long_description(), - long_description_content_type='text/markdown', - author='Christopher Piekarski', - author_email='chris@cpiekarski.com', - maintainer='Christopher Piekarski', - maintainer_email='chris@cpiekarski.com', - license='OSI Approved Apache Software License', - keywords=['json','socket','server','client'], - packages=['jsocket'], - provides=['jsocket'], - python_requires='>=3.8', - license_files=['LICENSE'], - classifiers=[ - 'Intended Audience :: Developers', - 'Programming Language :: Python :: 3.9', - 'Operating System :: OS Independent', - 'Development Status :: 5 - Production/Stable', - 'Topic :: System :: Networking', - 'Topic :: Software Development :: Libraries :: Application Frameworks', - 'Topic :: System :: Distributed Computing', - 'Topic :: System :: Hardware :: Symmetric Multi-processing', - ], - url='https://cpiekarski.com/2012/01/25/python-json-client-server-redux/' - ) +if __name__ == "__main__": + setup()