details: https://code.tryton.org/hatch-tryton/commit/c1e376fe1766
branch: default
user: Cédric Krier <[email protected]>
date: Thu Mar 12 13:19:52 2026 +0100
description:
Add dynamic authors from copyright file
diffstat:
hatch_tryton/plugin.py | 28 ++++++++++++++++-
hatch_tryton/tests/test_metadata.py | 59 ++++++++++++++++++++++++++++++++++++-
2 files changed, 85 insertions(+), 2 deletions(-)
diffs (127 lines):
diff -r 4fdd86f378e3 -r c1e376fe1766 hatch_tryton/plugin.py
--- a/hatch_tryton/plugin.py Wed Mar 11 23:29:20 2026 +0100
+++ b/hatch_tryton/plugin.py Thu Mar 12 13:19:52 2026 +0100
@@ -4,12 +4,15 @@
import re
from collections import namedtuple
from configparser import ConfigParser
+from email.utils import parseaddr
from pathlib import Path
-from typing import Optional
+from typing import Generator, Optional
from hatchling.metadata.plugin.interface import MetadataHookInterface
TrytonConfig = namedtuple('TrytonConfig', ['version', 'depends'])
+Author = namedtuple('Author', ['name', 'email'])
+_COPYRIGHT_PREFIX = "Copyright (C) "
def _get_tryton_cfg(
@@ -57,6 +60,24 @@
}
+def _get_authors(root: str, path: str) -> Generator[Author, None, None]:
+ copyright_path = Path(root) / path
+ with copyright_path.open() as f:
+ for line in f:
+ line = line.strip()
+ if not line.lower().startswith(_COPYRIGHT_PREFIX.lower()):
+ continue
+ try:
+ _, name = line[len(_COPYRIGHT_PREFIX):].split(' ', 1)
+ except ValueError:
+ continue
+ if '@' in name:
+ name, email = parseaddr(name)
+ else:
+ email = ''
+ yield Author(name=name, email=email)
+
+
class TrytonMetadataHook(MetadataHookInterface):
PLUGIN_NAME = 'tryton'
@@ -112,3 +133,8 @@
or 'readme' not in metadata.get('dynamic', [])):
raise ValueError("'readme' must be dynamic")
metadata['readme'] = _get_readme(self.root, readme)
+
+ if ((copyright := self.config.get('copyright'))
+ and 'authors' in metadata.get('dynamic', [])):
+ metadata['authors'] = list(
+ map(Author._asdict, _get_authors(self.root, copyright)))
diff -r 4fdd86f378e3 -r c1e376fe1766 hatch_tryton/tests/test_metadata.py
--- a/hatch_tryton/tests/test_metadata.py Wed Mar 11 23:29:20 2026 +0100
+++ b/hatch_tryton/tests/test_metadata.py Thu Mar 12 13:19:52 2026 +0100
@@ -5,7 +5,7 @@
from textwrap import dedent
from typing import TYPE_CHECKING
-from hatch_tryton.plugin import TrytonMetadataHook
+from hatch_tryton.plugin import Author, TrytonMetadataHook, _get_authors
from .tools import with_temporay_directory
@@ -256,3 +256,60 @@
hook = TrytonMetadataHook(directory, config)
with self.assertRaisesRegex(ValueError, r"readme.*dynamic"):
hook.update(metadata)
+
+ @with_temporay_directory
+ def test_authors_from_copyright(self, directory: Path):
+ "Test authors from copyright file"
+ config = {
+ 'copyright': 'COPYRIGHT',
+ }
+ metadata = {
+ 'dynamic': ['authors'],
+ }
+ (directory / 'COPYRIGHT').write_text(dedent("""\
+ Copyright (C) 9999 John Doe
+
+ Text"""))
+ hook = TrytonMetadataHook(directory, config)
+ hook.update(metadata)
+ self.assertEqual(
+ [{'name': "John Doe", 'email': ''}],
+ metadata.get('authors'))
+
+ @with_temporay_directory
+ def test_authors_from_copyright_not_dynamic(self, directory: Path):
+ "Test authors from copyright file not dynamic"
+ config = {
+ 'copyright': 'COPYRIGHT',
+ }
+ metadata = {
+ 'authors': [{'name': "Jane Doe", 'email': ''}],
+ }
+ (directory / 'COPYRIGHT').write_text(dedent("""\
+ Copyright (C) 9999 John Doe
+
+ Text"""))
+ hook = TrytonMetadataHook(directory, config)
+ hook.update(metadata)
+ self.assertEqual(
+ [{'name': "Jane Doe", 'email': ''}],
+ metadata.get('authors'))
+
+ @with_temporay_directory
+ def test_get_authors(self, directory: Path):
+ "Test get authors from copyright file"
+ (directory / 'COPYRIGHT').write_text(dedent("""\
+ Copyright (C) 9999 John Doe
+ Copyright (C) 0000-9999 Jane Doe
+ Copyright (C) 9999 John Doe <[email protected]>
+ Copyright (C) 9999 <[email protected]>
+ junk"""))
+ authors = list(_get_authors(directory, 'COPYRIGHT'))
+
+ self.assertEqual([
+ Author("John Doe", ''),
+ Author("Jane Doe", ''),
+ Author("John Doe", '[email protected]'),
+ Author('', '[email protected]'),
+ ],
+ authors)