diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0c893394..68074ac9 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,15 +11,13 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["pypy2", "pypy3", "2.7", "3.5", "3.6", "3.7", "3.8", "3.9", "3.10"] + python-version: ["pypy-2.7", "pypy-3.8", "2.7", "3.7", "3.8", "3.9", "3.10"] os: [ubuntu-latest, macos-latest, windows-latest] include: # Add new helper variables to existing jobs - - {python-version: "pypy2", toxenv: "pypy"} - - {python-version: "pypy3", toxenv: "pypy3"} + - {python-version: "pypy-2.7", toxenv: "pypy"} + - {python-version: "pypy-3.8", toxenv: "pypy3"} - {python-version: "2.7", toxenv: "py27"} - - {python-version: "3.5", toxenv: "py35"} - - {python-version: "3.6", toxenv: "py36"} - {python-version: "3.7", toxenv: "py37"} - {python-version: "3.8", toxenv: "py38"} - {python-version: "3.9", toxenv: "py39"} diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 83fc7f22..9d1e3cda 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,10 +1,12 @@ -0.4.5 In progress, unreleased +0.4.5 Current release + * Catch a racy ValueError that could occur on exit. * Create README-hacking.md, for Colorama contributors. * Tweak some README unicode characters that don't render correctly on PyPI. * Fix some tests that were failing on some operating systems. * Add support for Python 3.9. * Add support for PyPy3. -0.4.4 Current release + * Add support for pickling with the ``dill`` module. +0.4.4 * Re-org of README, to put the most insteresting parts near the top. * Added Linux makefile targets and Windows powershell scripts to automate bootstrapping a development environment, and automate the diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 016aa76d..00000000 --- a/MANIFEST.in +++ /dev/null @@ -1,2 +0,0 @@ -include LICENSE.txt CHANGELOG.rst -recursive-include demos *.py *.bat *.sh diff --git a/Makefile b/Makefile index a0b8987c..d56a3f79 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,6 @@ pip=$(virtualenv)/bin/pip syspython=python3.8 python=$(virtualenv)/bin/python twine=$(virtualenv)/bin/twine -version=$(shell $(python) setup.py --version) clean: ## Remove build artifacts, .pyc files, virtualenv -rm -rf build dist MANIFEST colorama.egg-info $(virtualenv) @@ -51,8 +50,7 @@ test: ## Run tests # build packages build: ## Build a release (sdist and wheel) - $(python) -m pip install --upgrade setuptools wheel - $(python) setup.py sdist bdist_wheel + $(python) -m build .PHONY: build test-release: build ## Test a built release @@ -60,6 +58,5 @@ test-release: build ## Test a built release .PHONY: test-release release: ## Upload a built release - $(twine) upload dist/colorama-$(version)*{.whl,.tar.gz} + $(twine) upload dist/colorama-* .PHONY: release - diff --git a/README-hacking.md b/README-hacking.md index b7c93961..21fab3e9 100644 --- a/README-hacking.md +++ b/README-hacking.md @@ -66,53 +66,75 @@ target. ## Release checklist -TODO: Add the use of release candidate versions to this checklist. - 1. Check the CHANGELOG is updated with everything since the last release. -2. Remove the '-pre' suffix from `__version__` in `colorama/__init.py__.py`. + Update CHANGELOG.rst with the new release version (move the comment for + "Current release") + +2. First we'll make a candidate release. Ensure the '.rc1' suffix is + present on `__version__` in `colorama/__init.py__.py`. + 3. Run the tests locally on your preferred OS, just to save you from doing the following time-consuming steps while there are still obvious problems in the code: - * Windows: `./test.ps1` - * Linux: `make test` + * Windows: + * First allow powershell to execute scripts, see: + https://stackoverflow.com/a/32328091 + * `powershell bootstrap.ps1` + * `powershell test.ps1` + * Linux: + * `make bootstrap` + * `make test` 4. Verify you're all committed, merged to master, and pushed to origin (This triggers a CI build, which we'll check later on) -5. Build the distributables (sdist and wheel), on either OS: +5. Tag the current commit with the `__version__` from `colorama/__init__.py`. + We should start using + [annotated tags for releases](https://www.tartley.com/posts/til-git-annotated-tags/), so: + + git tag -a -m "" $version + git push --follow-tags + +6. Build the distributables (sdist and wheel), on either OS: * Windows: `.\build.ps1` * Linux: `make build` -6. Test the distributables on both OS. Whichever one you do 2nd will get an +7. Test the distributables on both OS. Whichever one you do 2nd will get an HTTP 400 response on uploading to test.pypi.org, but outputs a message saying this is expected and carries on: - * Windows: `./clean.ps1 && .\bootstrap.ps1 && .\build.ps1 && - .\test-release.ps1` - * Linux: `make clean bootstrap build test-release` + * Windows: `.\test-release.ps1` + * Linux: `make test-release` - (This currently only tests the wheel, but - [should soon test the sdist too](https://github.com/tartley/colorama/issues/286).) + (This currently only tests the wheel, but + [should soon test the sdist too](https://github.com/tartley/colorama/issues/286).) -7. Check the [CI builds](https://github.com/tartley/colorama/actions/) +8. Check the [CI builds](https://github.com/tartley/colorama/actions/) are complete and all passing. -8. Upload the distributables to PyPI: +9. Upload the distributables to PyPI: * On Windows: `.\release.ps1` * On Linux: `make release` - This [should soon tag the release for you](https://github.com/tartley/colorama/issues/282). Until then: +10. Test by installing the candidate version from PyPI, and sanity check it with + 'demo.sh', making sure this is running against the PyPI installation, not + local source. -9. Tag the current commit with the `__version__` from `colorama/__init__.py`. - We should start using - [annotated tags for releases](https://www.tartley.com/posts/til-git-annotated-tags/), so: +11. Maybe wait a day for anyone using pre-release installs to report any + problems? - git tag -a -m "" $version - git push --follow-tags +12. Remove the '.rcX' suffix from `__version__` in + `colorama/__init__.py`. + +13. Repeat steps 5 to 10, for the actual (non-candidate) release. + +14. Bump the version number in `colorama/__init__.py`, and add a 'dev1' + suffix, eg: + + `0.4.5dev1` -10. Bump the version number in `colorama/__init__.py`, and add the '-pre' - suffix again, ready for the next release. Commit and push this (directly to - master is fine.) + so that any build artifacts created are clearly labelled as not a real + release. Commit and push this (directly to master is fine.) diff --git a/README.rst b/README.rst index 9a349ac1..fb0b75f3 100644 --- a/README.rst +++ b/README.rst @@ -30,7 +30,7 @@ If you find Colorama useful, please |donate| to the authors. Thank you! Installation ------------ -Tested on CPython 2.7, 3.5, 3.6, 3.7, 3.8, 3.9 and 3.10 and Pypy 2.7 and 3.6. +Tested on CPython 2.7, 3.7, 3.8, 3.9 and 3.10 and Pypy 2.7 and 3.8. No requirements other than the standard library. diff --git a/bootstrap.ps1 b/bootstrap.ps1 index 3260f8b4..53ba3314 100644 --- a/bootstrap.ps1 +++ b/bootstrap.ps1 @@ -1,4 +1,4 @@ -$syspython="python3.8.exe" +$syspython="python.exe" $ve="$HOME\.virtualenvs\colorama" $bin="$ve\Scripts" diff --git a/build.ps1 b/build.ps1 index a48e3578..bf26ebac 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,6 +1,5 @@ $ve="$HOME\.virtualenvs\colorama" $bin="$ve\Scripts" -& $bin\python.exe -m pip install --upgrade setuptools wheel -& $bin\python.exe setup.py sdist bdist_wheel - +& $bin\python.exe -m pip install --upgrade build +& $bin\python.exe -m build diff --git a/clean.ps1 b/clean.ps1 index de9ba5ae..a2a59af3 100644 --- a/clean.ps1 +++ b/clean.ps1 @@ -1,4 +1,4 @@ -$syspython="python3.8.exe" +$syspython="python.exe" $ve="$HOME\.virtualenvs\colorama" remove-item -r -fo * -I build,dist,MANIFEST,colorama.egg-info,$ve,sandbox diff --git a/colorama/__init__.py b/colorama/__init__.py index 641fd6fc..518ac808 100644 --- a/colorama/__init__.py +++ b/colorama/__init__.py @@ -3,4 +3,4 @@ from .ansi import Fore, Back, Style, Cursor from .ansitowin32 import AnsiToWin32 -__version__ = '0.4.5-pre' +__version__ = '0.4.6dev1' diff --git a/colorama/ansitowin32.py b/colorama/ansitowin32.py index 0cf7c397..20603111 100644 --- a/colorama/ansitowin32.py +++ b/colorama/ansitowin32.py @@ -37,6 +37,12 @@ def __enter__(self, *args, **kwargs): def __exit__(self, *args, **kwargs): return self.__wrapped.__exit__(*args, **kwargs) + def __setstate__(self, state): + self.__dict__ = state + + def __getstate__(self): + return self.__dict__ + def write(self, text): self.__convertor.write(text) @@ -57,7 +63,9 @@ def closed(self): stream = self.__wrapped try: return stream.closed - except AttributeError: + # AttributeError in the case that the stream doesn't support being closed + # ValueError for the case that the stream has already been detached when atexit runs + except (AttributeError, ValueError): return True diff --git a/colorama/tests/ansitowin32_test.py b/colorama/tests/ansitowin32_test.py index 380a99b7..91ca551f 100644 --- a/colorama/tests/ansitowin32_test.py +++ b/colorama/tests/ansitowin32_test.py @@ -1,5 +1,5 @@ # Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. -from io import StringIO +from io import StringIO, TextIOWrapper from unittest import TestCase, main try: from contextlib import ExitStack @@ -46,6 +46,17 @@ def testProxyNoContextManager(self): with StreamWrapper(mockStream, mockConverter) as wrapper: wrapper.write('hello') + def test_closed_shouldnt_raise_on_closed_stream(self): + stream = StringIO() + stream.close() + wrapper = StreamWrapper(stream, None) + self.assertEqual(wrapper.closed, True) + + def test_closed_shouldnt_raise_on_detached_stream(self): + stream = TextIOWrapper(StringIO()) + stream.detach() + wrapper = StreamWrapper(stream, None) + self.assertEqual(wrapper.closed, True) class AnsiToWin32Test(TestCase): diff --git a/demos/demo.sh b/demos/demo.sh index d8cbbcca..eb05b076 100644 --- a/demos/demo.sh +++ b/demos/demo.sh @@ -27,8 +27,9 @@ rm -f demo04.out # Demonstrate the difference between colorama initialized with wrapping on and off. python demo05.py -# Demonstrate printing colored, random characters at random positions on the screen -python demo06.py +# Skip demo06 +# It is too visually disruptive, +# making it hard to see whether any of the demos are working correctly. # Demonstrate cursor relative movement: UP, DOWN, FORWARD, and BACK in colorama.CURSOR python demo07.py diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..7f539788 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,64 @@ +[build-system] +requires = [ + "hatchling>=0.25.1", +] +build-backend = "hatchling.build" + +[project] +name = "colorama" +description = "Cross-platform colored terminal text." +readme = "README.rst" +license = "BSD-3-Clause" +requires-python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" +authors = [ + { name = "Jonathan Hartley", email = "tartley@tartley.com" }, +] +keywords = [ + "ansi", + "color", + "colour", + "crossplatform", + "terminal", + "text", + "windows", + "xplatform", +] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Environment :: Console", + "Intended Audience :: Developers", + "License :: OSI Approved :: BSD License", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Programming Language :: Python :: 2", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: PyPy", + "Topic :: Terminals", +] +dynamic = [ + "version", +] + +[project.urls] +Homepage = "https://github.com/tartley/colorama" + +[tool.hatch.version] +path = "colorama/__init__.py" + +[tool.hatch.build.targets.sdist] +include = [ + "/colorama", + "/demos", + "/CHANGELOG.rst", +] + +[tool.hatch.build.targets.wheel] +include = [ + "/colorama/*", +] diff --git a/release.ps1 b/release.ps1 index ac4e2682..a9753bd9 100644 --- a/release.ps1 +++ b/release.ps1 @@ -1,7 +1,5 @@ $ve="$HOME\.virtualenvs\colorama" $bin="$ve\Scripts" -$version="$(& $bin\python.exe setup.py --version)" # Upload to PyPI. -& $bin\twine.exe upload dist\colorama-$version*.tar.gz dist\colorama-$version-*.whl - +& $bin\twine.exe upload dist\colorama-*.tar.gz dist\colorama-*.whl diff --git a/requirements-dev.txt b/requirements-dev.txt index 296bb90c..2f92fc49 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,4 +1,5 @@ mock>=1.0.1;python_version<"3.3" twine>=3.1.1 contextlib2;python_version<"3" +build -e . diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 2e9053c0..00000000 --- a/setup.cfg +++ /dev/null @@ -1,5 +0,0 @@ -[bdist_wheel] -universal = 1 - -[metadata] -license_file = LICENSE.txt diff --git a/setup.py b/setup.py deleted file mode 100644 index 4221fe1b..00000000 --- a/setup.py +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/env python -# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. - -from __future__ import with_statement - -from io import open -import os -import re -try: - from setuptools import setup -except ImportError: - from distutils.core import setup - - -NAME = 'colorama' - - -def read_file(path, encoding='ascii'): - with open(os.path.join(os.path.dirname(__file__), path), - encoding=encoding) as fp: - return fp.read() - -def _get_version_match(content): - # Search for lines of the form: # __version__ = 'ver' - regex = r"^__version__ = ['\"]([^'\"]*)['\"]" - version_match = re.search(regex, content, re.M) - if version_match: - return version_match.group(1) - raise RuntimeError("Unable to find version string.") - -def get_version(path): - return _get_version_match(read_file(path)) - -setup( - name=NAME, - version=get_version(os.path.join('colorama', '__init__.py')), - description='Cross-platform colored terminal text.', - long_description=read_file('README.rst'), - keywords='color colour terminal text ansi windows crossplatform xplatform', - author='Jonathan Hartley', - author_email='tartley@tartley.com', - maintainer='Arnon Yaari', - url='https://github.com/tartley/colorama', - license='BSD', - packages=[NAME], - python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*', - # see classifiers https://pypi.org/pypi?%3Aaction=list_classifiers - classifiers=[ - 'Development Status :: 5 - Production/Stable', - 'Environment :: Console', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: BSD License', - 'Operating System :: OS Independent', - 'Programming Language :: Python', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.5', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Programming Language :: Python :: 3.10', - 'Programming Language :: Python :: Implementation :: CPython', - 'Programming Language :: Python :: Implementation :: PyPy', - 'Topic :: Terminals', - ] -) diff --git a/test-release b/test-release index 15812eff..e89d5dac 100644 --- a/test-release +++ b/test-release @@ -13,13 +13,12 @@ # Exit on error set -eu -o pipefail -syspython=python3.8 +syspython=python3 bin="$HOME/.virtualenvs/colorama/bin" -version=$($bin/python setup.py --version) sandbox=test-release-playground # Upload to the test PyPI. -$bin/twine upload --repository testpypi dist/colorama-$version-* \ +$bin/twine upload --repository testpypi dist/colorama-* \ || echo " > Expect a 400 if package was already uploaded." # cd elsewhere so we cannot import from local source. @@ -30,6 +29,11 @@ mkdir -p $sandbox # Create a temporary disposable virtualenv. $syspython -m venv --clear venv + # voodoo sleep. I saw the following install fail, due to expected version + # not being listed at test.pypi.org, but then a few seconds later, re-run + # manually. it worked fine. + sleep 5 + # Install the package we just uploaded. # (--extra-index-url for this project's requirements) venv/bin/python -m pip --quiet install --index-url https://test.pypi.org/simple --extra-index-url https://pypi.org/simple colorama==$version @@ -40,4 +44,3 @@ mkdir -p $sandbox # Tidy up rm -rf $sandbox - diff --git a/test-release.ps1 b/test-release.ps1 index 19c6967b..e9af4a88 100644 --- a/test-release.ps1 +++ b/test-release.ps1 @@ -1,10 +1,9 @@ -$syspython="python3.8.exe" +$syspython="python.exe" $ve="$HOME\.virtualenvs\colorama" $bin="$ve\Scripts" -$version="$(& $bin\python.exe setup.py --version)" # Upload to the test PyPI. -& $bin\twine.exe upload --repository testpypi dist\colorama-$version-* +& $bin\twine.exe upload --repository testpypi dist\colorama-* if(!$?) { write-host " > Expect a 400 if package was already uploaded" } @@ -27,4 +26,3 @@ print(colorama.Fore.GREEN + ""OK Colorama "" + colorama.__version__ + "" from te "@ cd .. - diff --git a/tox.ini b/tox.ini index 721d811d..179745ac 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,6 @@ [tox] -envlist = py27, py35, py36, py37, py38, py39, py310, pypy, pypy3 +isolated_build = true +envlist = py27, py37, py38, py39, py310, pypy, pypy3 [testenv] deps = py27,pypy: mock