#!/usr/bin/env python3"""Script to create a new distribution.The following options are supported:-help Print documentation of this file and of setup.py-local Install the distribution as a local site-package. If a Pywikibot package is already there, it will be uninstalled first. Clears old dist folders first.-remote Upload the package to pypi. This cannot be done if the Pywikibot version is a development release. Clears old dist folders first.-clear Clear old dist folders and leave. Does not create a distribution.-upgrade Upgrade pip first; upgrade or install distribution packages build and twine first.Usage:: [pwb] make_dist [options].. versionadded:: 7.3.. versionchanged:: 7.4 - updates pip, setuptools, wheel and twine packages first - installs pre-releases over stable versions - also creates built distribution together with source distribution - *-upgrade* option was added.. versionchanged:: 7.5 - *clear* option was added - *nodist* option was added.. versionchanged:: 8.1 *nodist* option was removed, *clear* option does not create a distribution. *local* and *remote* option clears old distributions first... versionchanged:: 8.2 Build frontend was changed from setuptools to build. ``-upgrade`` option also installs packages if necessary."""## (C) Pywikibot team, 2022-2024## Distributed under the terms of the MIT license.#from__future__importannotationsimportabcimportshutilimportsysfromdataclassesimportdataclass,fieldfromimportlibimportimport_modulefrompathlibimportPathfromsubprocessimportcheck_call,runfrompywikibotimport__version__,error,info,input_yn,warning
[docs]@dataclassclassSetupBase(abc.ABC):"""Setup distribution base class. .. versionadded:: 8.0 .. versionchanged:: 8.1 *dataclass* is used. """local:boolremote:boolclear:boolupgrade:boolfolder:Path=field(init=False)def__post_init__(self)->None:"""Post-init initializer."""self.folder=Path().resolve()
[docs]defclear_old_dist(self)->None:# pragma: no cover"""Delete old dist folders. .. versionadded:: 7.5 """info('<<lightyellow>>Removing old dist folders... ',newline=False)shutil.rmtree(self.folder/'build',ignore_errors=True)shutil.rmtree(self.folder/'dist',ignore_errors=True)shutil.rmtree(self.folder/'pywikibot.egg-info',ignore_errors=True)info('<<lightyellow>>done')
[docs]defrun(self)->bool:"""Run the installer script. :return: True if no error occurs, else False """ifself.localorself.remoteorself.clear:self.clear_old_dist()ifself.clear:returnTrue# pragma: no coverifself.upgrade:# pragma: no covercheck_call('python -m pip install --upgrade pip',shell=True)formodulein('build','twine'):info(f'<<lightyellow>>Install or upgrade {module}')try:import_module(module)exceptModuleNotFoundError:check_call(f'pip install {module}',shell=True)else:check_call(f'pip install --upgrade {module}',shell=True)else:formodulein('build','twine'):try:import_module(module)exceptModuleNotFoundErrorase:# pragma: no covererror(f'<<lightred>>{e}')info('<<lightblue>>You may use -upgrade option to install')returnFalseself.copy_files()info('<<lightyellow>>Build package')try:check_call('python -m build')exceptExceptionase:# pragma: no covererror(e)returnFalsefinally:self.cleanup()info('<<lightyellow>>Check package and description')ifrun('twine check dist/*',shell=True).returncode:returnFalse# pragma: no coverifself.local:info('<<lightyellow>>Install locally')check_call('pip uninstall pywikibot -y',shell=True)check_call('pip install --no-index --pre --find-links=dist pywikibot',shell=True)ifself.remoteandinput_yn('<<lightblue>>Upload dist to pypi',automatic_quit=False):check_call('twine upload dist/*',shell=True)# pragma: no coverreturnTrue
[docs]classSetupPywikibot(SetupBase):"""Setup for Pywikibot distribution. .. versionadded:: 8.0 """def__init__(self,*args)->None:"""Set source and target directories."""super().__init__(*args)source=self.folder/'scripts'/'i18n'/'pywikibot'target=self.folder/'pywikibot'/'scripts'/'i18n'/'pywikibot'self.target=targetself.source=source
[docs]defcopy_files(self)->None:"""Copy i18n files to pywikibot.scripts folder. Pywikibot i18n files are used for some translations. They are copied to the pywikibot scripts folder. """info('<<lightyellow>>Copy files')info(f'directory is {self.folder}')info(f'clear {self.target} directory')shutil.rmtree(self.target,ignore_errors=True)info('copy i18n files ... ',newline=False)shutil.copytree(self.source,self.target)info('done')
[docs]defcleanup(self)->None:"""Remove all copied files from pywikibot scripts folder."""info('<<lightyellow>>Remove copied files... ',newline=False)shutil.rmtree(self.target)# restore pywikibot en.json filefilename='en.json'self.target.mkdir()shutil.copy(self.source/filename,self.target/filename)info('<<lightyellow>>done')
[docs]defhandle_args()->tuple[bool,bool,bool,bool]:"""Handle arguments and print documentation if requested. :return: Return whether dist is to be installed locally or to be uploaded """if'-help'insys.argv:importreimportsetuphelp_text=re.sub(r'^\.\. version(added|changed)::.+','',__doc__,flags=re.MULTILINE|re.DOTALL)info(help_text)info(setup.__doc__)sys.exit()local='-local'insys.argvremote='-remote'insys.argvclear='-clear'insys.argvupgrade='-upgrade'insys.argvifremoteand'dev'in__version__:# pragma: no coverwarning('Distribution must not be a developmental release to upload.')remote=Falsesys.argv=[sys.argv[0]]returnlocal,remote,clear,upgrade