Index: README.md ================================================================== --- README.md +++ README.md @@ -106,10 +106,11 @@ Is mostly an alias for pkgutil.get_data(). Abstracts usage within PYZ packages a little. #### argparse_map() Provides a simpler way to specify ugly argparse definitions. And allows to amass options from plugins. + # GUI There's a Tkinter/PySimpleGUI variant of the option dialog from [streamtuner2](https://fossil.include-once.org/streamtuner2/) included: @@ -168,14 +169,30 @@ All other `setup(fields=…)` are passed on to distutils/setuptools as is. -- Btw, [setupmeta](https://pypi.org/project/setupmeta/) is an even more versatile wrapper with sensible defaults and source scanning. -# other modules +# flit wrapper + +Alternatively, there's `pluginconf.flit` to utilize pyproject.toml for +building packages, while sourcing meta data from the primary package file. + + [build-system] + requires = ["flit_core", "pluginconf"] + build-backend = "pluginconf.flit" + + [project] + name = "projectname" + +It can be invoked via `python -m pluginconf.flit build` or even +`flit-pluginconf build`. It's not very robust however. + + +## other modules * DependencyValidation is now in `pluginconf.depends` - * `pluginconf.flit` is meant as alternative to setup. + * argparse_map() might also end up in a separate module. #### Caveats * It’s mostly just an excerpt from streamtuner2. Index: pluginconf/__init__.py ================================================================== --- pluginconf/__init__.py +++ pluginconf/__init__.py @@ -2,20 +2,21 @@ # api: python ##type: extract # category: config # title: Plugin configuration # description: Read meta data, pyz/package contents, module locating -# version: 0.7.7 +# version: 0.7.8 # state: stable # classifiers: documentation # license: PD # priority: core # docs: https://fossil.include-once.org/pluginspec/ # url: http://fossil.include-once.org/streamtuner2/wiki/plugin+meta+data # config: - # format: off # pylint: disable=invalid-name +# console-scripts: flit-pluginconf=pluginconf.flit:main # # Provides plugin lookup and meta data extraction utility functions. # It's used to abstract module+option management in applications. # For consolidating internal use and external/tool accessibility. # Index: pluginconf/flit.py ================================================================== --- pluginconf/flit.py +++ pluginconf/flit.py @@ -1,45 +1,54 @@ # encoding: utf-8 # api: pep517 # title: flit backend # description: wraps flit_core.buildapi -# version: 0.1 +# version: 0.2 # depends: python:flit (>=3.0, <4.0) # license: BSD-3-Clause # priority: extra # src: ~/.local/lib/python3.8/site-packages/flit_core/ # # This is supposed to become an alternative to pluginconf.setup, # using flit as pep517 build backend. But adding automagic field # lookup of course. -# -# -# [build-system] -# requires = ["flit_core", "pluginconf"] -# build-backend = "pluginconf.flit" -# -# [project] -# name = "foobar" -# dynamic = ["version", "description"] -# -# - -import os -import re -import os.path -import pathlib +# +# It can be invoked per `flit-pluginconfig build` and requires +# a `pyproject.toml` like: +# +# [build-system] +# requires = ["flit_core", "pluginconf"] +# build-backend = "pluginconf.flit" +# +# [project] +# name = "foobar" +# #dynamic = ["version", "description"] +# +# Injecting attributes between ini reading and parameter collection +# turned out easier than expanding on flit_core.buildapi functions. +# And lastly, this just chains to flit.main() to handle setup and +# build steps. +# + +import sys +import re import functools import pluginconf -import pluginconf.setup +import pluginconf.setup as psetup import flit_core.common -#-- patch functions +#-- patchy patch +def inject(where): + def wrapped(func): + setattr(where, func.__name__, func) + return wrapped -def patch_flit_config(path): +@inject(flit_core.common) +def read_flit_config(path): """ read_flit_config() with preset dynamic fields """ d = tomllib.loads(path.read_text('utf-8')) # make fields dynamic if not "dynamic" in d["project"]: @@ -53,127 +62,89 @@ # turn it into LoadedConfig return prep_toml_config(d, path) # override make_metadata -def patch_metadata(module, ini_info): +@inject(flit_core.common) +def make_metadata(module, ini_info): meta = { "name": module.name, "provides": [module.name] } meta.update(ini_info.metadata) meta.update( - pmd_meta(filename=module.file) + pmd_meta( + pluginconf.plugin_meta(filename=module.file), + ini_info + ) ) return flit_core.common.Metadata(meta) -# inject -flit_core.common.make_metadata = patch_metadata - - -#-- map plugin meta to flit Metadata - -def pmd_meta(filename): +# map plugin meta to flit Metadata +def pmd_meta(pmd, ini): """ enjoin PMD fields with flit meta data """ - pmd = pluginconf.plugin_meta(filename=filename) - meta = dict( summary = pmd.get("description"), version = pmd.get("version"), home_page = pmd.get("url"), author = pmd.get("author"), # should split this into mail and name author_email = None, maintainer = None, maintainer_email = None, license = pmd.get("license"), - keywords = pmd.get("keywords"), + keywords = psetup._keywords(pmd), download_url = None, - requires_python = pluginconf.setup._python_requires(pmd).get("python_requires", ">= 2.7"), - platform = (), + requires_python = psetup._python_requires(pmd).get("python_requires", ">= 2.7"), + platform = pmd.get("architecture"), supported_platform = (), - classifiers = list(pluginconf.setup._classifiers(pmd)) - + pluginconf.setup._trove_license(pmd) - + pluginconf.setup._trove_status(pmd), + classifiers = list(psetup._classifiers(pmd)) + + psetup._trove_license(pmd) + + psetup._trove_status(pmd), provides = (), - requires = pluginconf.setup._install_requires(pmd).get("install_requires") or (), + requires = psetup._install_requires(pmd).get("install_requires") or (), obsoletes = (), - project_urls = [f"{k}, {v}" for k,v in pluginconf.setup._project_urls(pmd).items()], + project_urls = [f"{k}, {v}" for k,v in psetup._project_urls(pmd).items()], provides_dist = (), - requires_dist = pluginconf.setup._install_requires(pmd).get("install_requires") or (), + requires_dist = psetup._install_requires(pmd).get("install_requires") or (), obsoletes_dist = (), requires_external = (), provides_extra = (), ) - meta.update({k[5:]: v for k,v in pluginconf.setup._plugin_doc(pmd).items()}) - meta.update({k[5:]: v for k,v in pluginconf.setup._get_readme().items()}) - - return meta - - -# 'metadata', 'module', 'referenced_files', 'reqs_by_extra', -# 'sdist_exclude_patterns', 'sdist_include_patterns'] -# -# ini.metadata = -# {'name': 'basename', 'requires_dist': []} -# -# ini.module = -# basename -# -# ini.dynamic_metadata = -# {'version', 'description'} -# -# ini.__dict__ = -# { -# 'module': 'pluginconf', -# 'metadata': { -# 'name': 'pluginconf', -# 'version': '1.0', -# 'summary': '...', -# 'requires_dist': [] -# }, -# 'reqs_by_extra': {}, -# 'entrypoints': {}, -# 'referenced_files': [], -# 'sdist_include_patterns': [], -# 'sdist_exclude_patterns': [], -# 'dynamic_metadata': [], -# 'data_directory': None -# } - -#module = Module(ini.module, pathlib.Path.cwd()) -#print(module.__dict__) -#print(module.file) -# {'name': 'pluginconf', 'path': -# PosixPath('/home/mario/projects/pluginconf/pluginconf'), 'is_package': -# True, 'prefix': '', 'source_dir': -# PosixPath('/home/mario/projects/pluginconf')} - -#MD = patch_metadata(module, ini) -#print(MD.__dict__) - - -import flit_core.buildapi - -flit_core.buildapi.prepare_metadata_for_build_wheel("./build/") + + # comment/readme + for docs in psetup._plugin_doc(pmd), psetup._get_readme(): + if docs["long_description"]: + meta.update({ + k[5:]: v for k,v in docs.items() + }) + + # entry_points are in ini file + for section, entries in psetup._entry_points(pmd).items(): + ini.entrypoints[section] = ini.entrypoints.get(section, {}) + for e in entries: + ini.entrypoints[section].update( + dict(re.findall("(.+)=(.+)", e)) + ) + print(ini.entrypoints) + + # strip empty entries + return {k: v for k, v in meta.items() if v} #-- buildapi -# -# These need to be late imports; -# else they'll bind the original helper functions -from flit_core.buildapi import ( - get_requires_for_build_wheel, +from flit_core.buildapi import ( # These have to be late imports; else they'll + get_requires_for_build_wheel, # bind with the original buildapi functions. get_requires_for_build_sdist, get_requires_for_build_editable, prepare_metadata_for_build_wheel, prepare_metadata_for_build_editable, build_wheel, build_editable, build_sdist, ) -import flit +#-- invocation point +from flit import main -# as invocation point -def main(argv=None): - return flit.main(argv) +if __name__ == "__main__": + main(sys.argv) Index: pluginconf/setup.py ================================================================== --- pluginconf/setup.py +++ pluginconf/setup.py @@ -157,14 +157,24 @@ def _datafiles_man(): """ data_files= """ for man in glob.glob("man*/*.[12345678]"): section = man[-1] yield ("man/man"+section, [man],) + +def _entry_points(pmd): + """ collect console-scripts: """ + params = {} + for field in ["console_scripts", "gui_scripts"]: + if not pmd.get(field): + continue + params[field] = params.get(field, []) + re.findall("(\w+[^,;\s]+=\w+[^,;\s]+)", pmd[field]) + return params def _keywords(pmd): """ keywords= """ return pmd.get("keywords") or pmd.get("category") + def setup(debug=0, **kwargs): """ Wrapper around `setuptools.setup()` which adds some defaults @@ -196,11 +206,11 @@ # package name if "name" not in kwargs and kwargs.get("packages"): kwargs["name"] = kwargs["packages"][0] # read README - if not "long_description" in kwargs: + if re.match("^$|^[@./]*README.{0,5}$", kwargs.get("long_description", "")): kwargs.update(_get_readme()) # search name= package if no fn= given if kwargs.get("filename"): kwargs["fn"] = kwargs["filename"] @@ -244,10 +254,13 @@ if not "keywords" in kwargs: kwargs["keywords"] = _keywords(pmd) # automatic inclusions kwargs["data_files"] = kwargs.get("data_files", []) + list(_datafiles_man()) + # entry points + for section, entries in _entry_points(pmd).items(): + kwargs["entry_points"][section] = kwargs["entry_points"].get(section, []) + entries # classifiers= # license: if pmd.get("license") and not any(re.match("License ::", l) for l in kwargs["classifiers"]): kwargs["classifiers"].extend(_trove_license(pmd)) Index: setup.py ================================================================== --- setup.py +++ setup.py @@ -16,9 +16,14 @@ #system("pandoc -f markdown -t rst README.md > README.rst") pluginconf.setup.setup( fn="pluginconf/__init__.py", - long_description="README.md" + long_description="README.md", #author_email="m..@include-once.org", +# entry_points={ +# "console_scripts": [ +# "flit-pluginconf=pluginconf.flit:main", +# ] +# }, )