~dricottone/gap

029dc0cebe4fe61dc7190ea8613713fad69a5139 — Dominic Ricottone 2 years ago 572a618 v1.0.3
Updating TOML parsing for Python 3.11

Use tomllib if available, else use toml.

An upcoming release will drop support for toml and therefore become
supported on Python 3.11+ only.
5 files changed, 81 insertions(+), 38 deletions(-)

M Makefile
M README.md
M gap/toml_parser.py
M pyproject.toml
M setup.cfg
M Makefile => Makefile +41 -17
@@ 1,10 1,14 @@
VERSION=1.0.3

PY_COMPILE_BIN=python -m py_compile

#BUILD_BIN=python -m build
BUILD_BIN=pyproject-build

#UNITTEST_BIN=python -m unittest
UNITTEST_BIN=unittest --color
#UNITTEST_FILE_BIN=python -m unittest
#UNITTEST_DIR_BIN=python -m unittest discover --top-level-directory .
UNITTEST_FILE_BIN=unittest --color
UNITTEST_DIR_BIN=unittest --color --working-directory .

#MYPY_BIN=python -m mypy
MYPY_BIN=MYPY_CACHE_DIR=gap/__mypycache__ mypy


@@ 12,39 16,59 @@ MYPY_BIN=MYPY_CACHE_DIR=gap/__mypycache__ mypy
#PIPX_BIN=python -m pipx
PIPX_BIN=pipx

.PHONY: clean bootstrap test build unittest reinstall install uninstall

.PHONY: clean
clean:
	rm -rf **/__pycache__ **/__mypycache__ **/*.pyc build *.egg-info

bootstrap:
gap/cli.py: gap/bootstrap.py
	./gap/bootstrap.py > gap/cli.py

test:
tests/__init__.py:
	touch tests/__init__.py

tests/generated_syntax:
	mkdir -p tests/generated_syntax
	touch tests/__init__.py tests/generated_syntax/__init__.py

tests/generated_syntax/__init__.py: tests/generated_syntax
	touch tests/__init__.py

TEST_FILES=tests/__init__.py tests/generated_syntax tests/generated_syntax/__init__.py

.PHONY: test
test: $(TEST_FILES)
	$(PY_COMPILE_BIN) gap/*.py
	$(UNITTEST_BIN) --working-directory . tests
	$(UNITTEST_DIR_BIN) tests
	$(PY_COMPILE_BIN) tests/generated_syntax/*.py
	$(UNITTEST_BIN) tests/generated_syntax_tests.py
	$(UNITTEST_FILE_BIN) tests/generated_syntax_tests.py
	$(MYPY_BIN) -p gap

.PHONY: unittest
# more verbose than `make test`, skips `py_compile` and `mypy`
unittest:
	mkdir -p tests/generated_syntax
	touch tests/__init__.py tests/generated_syntax/__init__.py
	$(UNITTEST_BIN) --working-directory . tests --verbose
	$(UNITTEST_BIN) tests/generated_syntax_tests.py --verbose
unittest: $(TEST_FILES)
	$(UNITTEST_DIR_BIN) tests --verbose
	$(UNITTEST_FILE_BIN) tests/generated_syntax_tests.py --verbose

PY_FILES=gap/cli.py gap/generator.py gap/__main__.py gap/toml_parser.py

build:
build/gap-$(VERSION)-py3-none-any.whl: build

.PHONY:
build: $(PY_FILES)
	mkdir -p build
	$(BUILD_BIN) --wheel --no-isolation --outdir build/

.PHONY: reinstall
reinstall: uninstall install

install:
	$(PIPX_BIN) install build/gap-1.0.2-py3-none-any.whl
.PHONY: install
install: build/gap-$(VERSION)-py3-none-any.whl
	$(PIPX_BIN) install build/gap-$(VERSION)-py3-none-any.whl

.PHONY: uninstall
uninstall:
	$(PIPX_BIN) uninstall gap

.PHONY: rc
rc:
	docker run --interactive --tty --rm --name pytest --mount type=bind,src=$(pwd),dst=/code python:3.11-rc sh


M README.md => README.md +7 -4
@@ 1,14 1,17 @@

# generated argument parser

A package that uses external configuration files to generate a static, standalone parser module.
A package that uses external configuration files to generate a static,
standalone parser module.


## To-Do

Add parsers aside from `toml`, like `json` and `configparser`.

Allow import of third-party libraries, like `toml`, to fail-just remove that format from the valid list.
Python 3.11 introduces a `tomllib` module. **Release 1.0.2** will continue to
work perfectly for Python 3.6 or later. **Release 1.0.3** will continue to
function perfectly as well, but the test suite will fail due to `mypy` not
having type stubs for `tomllib`. **Release 1.0.4** will drop `toml` as a
dependency and therefore drop support for Python 3.10 or earlier.


## Workflow

M gap/toml_parser.py => gap/toml_parser.py +29 -13
@@ 1,19 1,35 @@
#!/usr/bin/env python3
# type: ignore

from typing import MutableMapping, Any

import toml
try:
    #3.11+
    import tomllib

def data_from_file(filename: str) -> MutableMapping[str, Any]:
    try:
        with open(filename, 'r') as f:
            data = toml.load(f)
    except OSError:
        message = 'file "{0}" cannot be found'.format(filename)
        raise FileNotFoundError(message) from None
    except toml.TomlDecodeError:
        message = 'file "{0}" is invalid TOML'.format(filename)
        raise ValueError(message) from None
    return data
    def data_from_file(filename: str) -> MutableMapping[str, Any]:
        try:
            with open(filename, 'rb') as f:
                data = tomllib.load(f)
        except OSError:
            message = 'file "{0}" cannot be found'.format(filename)
            raise FileNotFoundError(message) from None
        except tomllib.TOMLDecodeError:
            message = 'file "{0}" is invalid TOML'.format(filename)
            raise ValueError(message) from None
        return data

except:
    import toml #type: ignore

    def data_from_file(filename: str) -> MutableMapping[str, Any]: #type: ignore
        try:
            with open(filename, 'r') as f:
                data = toml.load(f)
        except OSError:
            message = 'file "{0}" cannot be found'.format(filename)
            raise FileNotFoundError(message) from None
        except toml.TomlDecodeError:
            message = 'file "{0}" is invalid TOML'.format(filename)
            raise ValueError(message) from None
        return data


M pyproject.toml => pyproject.toml +2 -2
@@ 6,9 6,9 @@ build-backend = "setuptools.build_meta"
name = "gap"
description = "Generated argument parser"
readme = "README.md"
version = "1.0.2"
version = "1.0.3"
authors = [ { name = "Dominic Ricottone", email = "me@dominic-ricottone.com" } ]
urls = { source = "git.dominic-ricottone.com/gap" }
urls = { source = "git.dominic-ricottone.com/~dricottone/gap" }
license = { file = "LICENSE.md" }
requires-python = ">=3.6"
dependencies = [

M setup.cfg => setup.cfg +2 -2
@@ 1,12 1,12 @@
[metadata]
name = gap
version = 1.0.2
version = 1.0.3
description = Generated argument parser
long_description = file: README.md
license = GPL
author = Dominic Ricottone
author_email = me@dominic-ricottone.com
url = git.dominic-ricottone.com/gap
url = git.dominic-ricottone.com/~dricottone/gap

[options]
packages = gap