jenkins-bot submitted this change.

View Change

Approvals: Zhuyifei1999: Looks good to me, approved jenkins-bot: Verified
[IMPR] Use one central point for framework version

Use one central point for framework version and other meta datas.
Enable PEP440 versioning and also follow PEP396 when deriving
version for setup.

Start with 4.0.0 as the current version which is Python 3.5+ only

- All meta data are placed within pywikibot/__metadata__.py.
This enables setup.py to fetch metadata without importing pywikibot itself.
- Start with 4.0.0 as the next release number. Increase the minor release
number if there are other changes than just bugfixes and L10N/i18n.
- Use __metadata__ in setup.py
- explain submitting a new release to pypi in setup.__doc__

Bug: T106121
Bug: T171886
Bug: T197936
Bug: T253719
Change-Id: I7ffe9096fece8c15e770b5fe25d3ac29410924af
---
M docs/conf.py
M pywikibot/CONTENT.rst
M pywikibot/__init__.py
A pywikibot/__metadata__.py
M setup.py
M tests/utils.py
6 files changed, 140 insertions(+), 37 deletions(-)

diff --git a/docs/conf.py b/docs/conf.py
index 4b42f93..3c4077b 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -64,8 +64,8 @@
master_doc = 'index'

# General information about the project.
-project = 'Pywikibot'
-copyright = '2003-2020, Pywikibot team'
+project = pywikibot.__name__.title()
+copyright = pywikibot.__copyright__

# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
diff --git a/pywikibot/CONTENT.rst b/pywikibot/CONTENT.rst
index 883d6e3..3f606e8 100644
--- a/pywikibot/CONTENT.rst
+++ b/pywikibot/CONTENT.rst
@@ -7,6 +7,8 @@
| __init__.py | Initialization of the pywikibot framework, |
| | basic classes and methods |
+----------------------------+------------------------------------------------------+
+ | __metadata__.py | pywikibot framework metadata file |
+ +----------------------------+------------------------------------------------------+
| _wbtypes.py | Wikibase data type classes |
+----------------------------+------------------------------------------------------+
| bot.py | User-interface related functions for building bots |
diff --git a/pywikibot/__init__.py b/pywikibot/__init__.py
index 8bd01df..cbd8352 100644
--- a/pywikibot/__init__.py
+++ b/pywikibot/__init__.py
@@ -7,9 +7,6 @@
#
from __future__ import absolute_import, division, unicode_literals

-__version__ = __release__ = '4.0.dev0'
-__url__ = 'https://www.mediawiki.org/wiki/Manual:Pywikibot'
-
import atexit
import datetime
from decimal import Decimal
@@ -21,6 +18,12 @@

from warnings import warn

+from pywikibot.__metadata__ import (
+ __copyright__, __description__, __download_url__, __license__,
+ __maintainer__, __maintainer_email__, __name__, __url__, __version__)
+
+__release__ = __version__ # backward compatibility
+
from pywikibot._wbtypes import WbRepresentation as _WbRepresentation
from pywikibot.bot import (
input, input_choice, input_yn, inputChoice, handle_args, showHelp, ui,
@@ -89,6 +92,9 @@
)

__all__ = (
+ '__copyright__', '__description__', '__download_url__', '__license__',
+ '__maintainer__', '__maintainer_email__', '__name__', '__release__',
+ '__url__', '__version__',
'BadTitle', 'Bot', 'calledModuleName', 'CaptchaError', 'CascadeLockedPage',
'Category', 'CircularRedirect', 'Claim', 'config',
'CoordinateGlobeUnknownException', 'critical', 'CurrentPageBot', 'debug',
diff --git a/pywikibot/__metadata__.py b/pywikibot/__metadata__.py
new file mode 100644
index 0000000..468a3fb
--- /dev/null
+++ b/pywikibot/__metadata__.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+"""Pywikibot metadata file."""
+#
+# (C) Pywikibot team, 2020
+#
+# Distributed under the terms of the MIT license.
+#
+from __future__ import unicode_literals
+
+__name__ = 'pywikibot'
+__version__ = '4.0.0.dev0'
+__description__ = 'Python MediaWiki Bot Framework'
+__maintainer__ = 'The Pywikibot team'
+__maintainer_email__ = 'pywikibot@lists.wikimedia.org'
+__license__ = 'MIT License'
+__url__ = 'https://www.mediawiki.org/wiki/Manual:Pywikibot'
+__download_url__ = 'https://tools.wmflabs.org/pywikibot/'
+__copyright__ = '(C) Pywikibot team, 2003-2020'
+__keywords__ = 'API bot client framework mediawiki pwb python pywiki ' \
+ 'pywikibase pywikibot pywikipedia pywikipediabot wiki ' \
+ 'wikibase wikidata wikimedia wikipedia'
diff --git a/setup.py b/setup.py
index ca96d76..fe41208 100644
--- a/setup.py
+++ b/setup.py
@@ -1,5 +1,28 @@
# -*- coding: utf-8 -*-
-"""Installer script for Pywikibot framework."""
+"""Installer script for Pywikibot framework.
+
+To create a new distribution:
+-----------------------------
+
+- replace the developmental version string in ``pywikibot.__metadata.py``
+ by the corresponing final release
+- create the package with::
+
+ python setup.py sdist
+
+- push the change to gerrit and merge it to the repository
+- upload the package to pypy by::
+
+ twine upload dist/*
+
+- create a new tag with the version number of the final release
+- move the existing 'stable' tag to that new tag
+- delete 'stable' tag in gerrit to be overridden later
+- synchronize the local tags with the remote repositoy
+- prepare the next release by increasing the version number in
+ ``pywikibot.__metadata.py`` and adding developmental identifier
+- upload this patchset to gerrit and merge it.
+"""
#
# (C) Pywikibot team, 2009-2020
#
@@ -8,6 +31,7 @@
import os
import sys

+from pkg_resources import parse_version, safe_version
from setuptools import setup

PYTHON_VERSION = sys.version_info[:3]
@@ -117,32 +141,80 @@
test_deps += ['six']


-def get_version(name):
- """Get a valid pywikibot module version string.
+class _DottedDict(dict):
+ __getattr__ = dict.__getitem__

- Either create a timebased version number for the package
- or read the version number from the package.
+
+# import metadata
+metadata = _DottedDict()
+name = 'pywikibot'
+path = os.path.abspath(os.path.dirname(__file__))
+with open(os.path.join(path, name, '__metadata__.py')) as f:
+ exec(f.read(), metadata)
+assert metadata.__name__ == name
+
+
+def get_validated_version():
+ """Get a validated pywikibot module version string.
+
+ The version number from pywikibot.__metadata__.__version__ is used.
+ setup.py with 'sdist' option is used to create a new source distribution.
+ In that case the version number is validated: Read tags from git.
+ Verify that the new release is higher than the last repository tag
+ and is not a developmental release.

@return: pywikibot module version string
@rtype: str
"""
- version = '4.0'
+ version = metadata.__version__
+ if 'sdist' not in sys.argv:
+ return version
+
+ if PY2:
+ raise RuntimeError(
+ 'A new distribution cannot be created with Python {}'
+ .format(sys.version.split(None, 1)[0]))
+
+ # validate version for sdist
+ from contextlib import suppress
+ from subprocess import run, PIPE
try:
- import subprocess
- date = subprocess.check_output(
- ['git', 'log', '-1', '--format=%ci']).strip()
- date = date.decode().split(' ', 1)[0].replace('-', '')
- version += '.' + date
- if 'sdist' not in sys.argv:
- version += '.dev0'
+ tags = run(['git', 'tag'], check=True, stdout=PIPE,
+ universal_newlines=True).stdout.splitlines()
except Exception as e:
print(e)
- from pkg_resources import get_distribution, DistributionNotFound
- try:
- version = get_distribution(name).version
- except DistributionNotFound as e:
- print(e)
- version += '.dev0'
+ sys.exit('Creating source distribution canceled.')
+
+ for tag in ('stable', 'python2'):
+ with suppress(ValueError):
+ tags.remove(tag)
+
+ last_tag = tags[-1]
+
+ warnings = []
+ if 'dev' in version:
+ warnings.append('Distribution must not be a developmental release.')
+
+ if parse_version(version) < parse_version('0'):
+ # any version which is not a valid PEP 440 version will be considered
+ # less than any valid PEP 440 version
+ warnings.append(
+ version + ' is not a valid version string following PEP 440.')
+ elif safe_version(version) != version:
+ warnings.append(
+ '{} does not follow PEP 440. Use {} as version string instead.'
+ .format(version, safe_version(version)))
+
+ if parse_version(version) <= parse_version(last_tag):
+ warnings.append(
+ 'New version "{}" is not higher than last version "{}".'
+ .format(version, last_tag))
+
+ if warnings:
+ print(__doc__)
+ print('\n\n'.join(warnings))
+ sys.exit('\nBuild of distribution package canceled.')
+
return version


@@ -176,24 +248,22 @@

def main():
"""Setup entry point."""
- name = 'pywikibot'
+ version = get_validated_version()
setup(
- name=name,
- version=get_version(name),
- description='Python MediaWiki Bot Framework',
+ name=metadata.__name__,
+ version=version,
+ description=metadata.__description__,
long_description=read_desc('README.rst'),
- keywords=['API', 'bot', 'framework', 'mediawiki', 'pwb', 'python',
- 'pywikibot', 'pywikipedia', 'pywikipediabot', 'wiki',
- 'wikimedia', 'wikipedia'],
- maintainer='The Pywikibot team',
- maintainer_email='pywikibot@lists.wikimedia.org',
- license='MIT License',
+ keywords=metadata.__keywords__.split(),
+ maintainer=metadata.__maintainer__,
+ maintainer_email=metadata.__maintainer_email__,
+ license=metadata.__license__,
packages=get_packages(name),
python_requires='>=3.5.0',
install_requires=dependencies,
extras_require=extra_deps,
- url='https://www.mediawiki.org/wiki/Manual:Pywikibot',
- download_url='https://tools.wmflabs.org/pywikibot/',
+ url=metadata.__url__,
+ download_url=metadata.__download_url__,
test_suite='tests.collector',
tests_require=test_deps,
classifiers=[
@@ -217,6 +287,10 @@
use_2to3=False
)

+ # Finally show distribution version before uploading
+ if 'sdist' in sys.argv:
+ print('\nDistribution package created for version {}'.format(version))
+

if __name__ == '__main__':
main()
diff --git a/tests/utils.py b/tests/utils.py
index 8571d6c..8686e90 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -601,7 +601,7 @@
@type command: list of unicode
"""
if PY2 or PYTHON_VERSION < (3, 5, 0):
- command.insert(1, '-W ignore::FutureWarning:pywikibot:125')
+ command.insert(1, '-W ignore::FutureWarning:pywikibot:131')
if cryptography_version and cryptography_version < [1, 3, 4]:
command.insert(1, '-W ignore:Old version of cryptography:Warning')
# Any environment variables added on Windows must be of type

To view, visit change 409823. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: pywikibot/core
Gerrit-Branch: master
Gerrit-Change-Id: I7ffe9096fece8c15e770b5fe25d3ac29410924af
Gerrit-Change-Number: 409823
Gerrit-PatchSet: 58
Gerrit-Owner: Xqt <info@gno.de>
Gerrit-Reviewer: D3r1ck01 <xsavitar.wiki@aol.com>
Gerrit-Reviewer: Dalba <dalba.wiki@gmail.com>
Gerrit-Reviewer: Framawiki <framawiki@tools.wmflabs.org>
Gerrit-Reviewer: John Vandenberg <jayvdb@gmail.com>
Gerrit-Reviewer: Matěj Suchánek <matejsuchanek97@gmail.com>
Gerrit-Reviewer: Merlijn van Deen <valhallasw@arctus.nl>
Gerrit-Reviewer: Mpaa <mpaa.wiki@gmail.com>
Gerrit-Reviewer: Siebrand <siebrand@kitano.nl>
Gerrit-Reviewer: Xqt <info@gno.de>
Gerrit-Reviewer: Zhuyifei1999 <zhuyifei1999@gmail.com>
Gerrit-Reviewer: Zoranzoki21 <zorandori4444@gmail.com>
Gerrit-Reviewer: jenkins-bot
Gerrit-CC: DannyS712 <DannyS712.enwiki@gmail.com>
Gerrit-CC: Dvorapa <dvorapa@seznam.cz>
Gerrit-MessageType: merged