Packaging

Summary

Package:

pyTooling

Doc-string:

documented

File

Expected

Covered

Uncovered

Coverage

__init__.py

56

54

2

96.4%

Overall (1 files)

56

54

2

96.4%

Source

pyTooling/Packaging/__init__.pydocumentedundocumentedignoredexcludednot counted
31"""
32A set of helper functions to describe a Python package for setuptools.
33
34.. hint::
35
36   See :ref:`high-level help <PACKAGING>` for explanations and usage examples.
37
38.. seealso::
39
40   :mod:`pyTooling.Versioning`
41      |rarr| The version numbers read from a package's dunder variables.
42   :mod:`pyTooling.Licensing`
43      |rarr| The license names translated for setuptools.
44   :mod:`pyTooling.Testing`
45      |rarr| Testing the console scripts a package installs.
46"""
...
62
64__all__ = [
65	"STATUS", "DEFAULT_LICENSE", "DEFAULT_PY_VERSIONS", "DEFAULT_CLASSIFIERS", "DEFAULT_README", "DEFAULT_REQUIREMENTS",
66	"DEFAULT_DOCUMENTATION_REQUIREMENTS", "DEFAULT_TEST_REQUIREMENTS", "DEFAULT_PACKAGING_REQUIREMENTS",
67	"DEFAULT_VERSION_FILE"
68]
69
71@export
72class PackagingError(ToolingException):
73	"""Base-exception of all exceptions raised by :mod:`pyTooling.Packaging`."""
74
76@export
77class DirectReferenceWarning(CriticalWarning):
78	"""
79	A requirement of an extra names its distribution by a URL, a direct reference (``name @ URL``).
80
81	The Python Package Index rejects a package whose metadata contains a direct reference, therefore
82	:func:`DescribePythonPackage` leaves such a requirement out of the extra.
83
84	.. important::
85
86	   As a critical warning, it must be collected by a :class:`~pyTooling.Warning.WarningCollector` up the
87	   call-hierarchy, otherwise :exc:`~pyTooling.Warning.UnhandledCriticalWarningError` is raised.
88	"""
89
90	_requirement: str             #: The requirement left out, as stated.
91	_extra:       str             #: The extra the requirement was left out of.
92	_filePath:    Nullable[Path]  #: The requirements file stating it; ``None`` for parameter 'additionalRequirements'.
93
94	def __init__(
95		self,
96		message: str,
97		/, *,
98		requirement: str,
99		extra: str,
100		filePath: Nullable[Path]
101	) -> None:
102		"""
103		Initializes the warning with the requirement left out, its extra and where it was stated.
104
105		:param message:     The warning's message.
106		:param requirement: The requirement left out, as stated.
107		:param extra:       The extra the requirement was left out of.
108		:param filePath:    The requirements file stating it; ``None`` for parameter 'additionalRequirements'.
109		"""
		...
114
115	@readonly
116	def Requirement(self) -> str:
117		"""
118		Read-only property to access the requirement left out, as stated (:attr:`_requirement`).
119
120		:returns: The requirement.
121		"""
		...
123
124	@readonly
125	def Extra(self) -> str:
126		"""
127		Read-only property to access the extra the requirement was left out of (:attr:`_extra`).
128
129		:returns: The extra's name.
130		"""
		...
132
133	@readonly
134	def FilePath(self) -> Nullable[Path]:
135		"""
136		Read-only property to access the requirements file stating the requirement (:attr:`_filePath`).
137
138		:returns: The file's path, or ``None`` for a requirement from parameter 'additionalRequirements'.
139		"""
		...
141
143@export
144class Readme:
145	"""Encapsulates the READMEs file content and MIME type."""
146
147	_content:  str   #: Content of the README file
148	_mimeType: str   #: MIME type of the README content
149
150	def __init__(self, content: str, mimeType: str) -> None:
151		"""
152		Initializes a README file wrapper.
153
154		:param content:  Raw content of the README file.
155		:param mimeType: MIME type of the README file.
156		"""
		...
159
160	@readonly
161	def Content(self) -> str:
162		"""
163		Read-only property to access the README's content.
164
165		:returns: Raw content of the README file.
166		"""
		...
168
169	@readonly
170	def MimeType(self) -> str:
171		"""
172		Read-only property to access the README's MIME type.
173
174		:returns: The MIME type of the README file.
175		"""
		...
177
179@export
180def loadReadmeFile(readmeFile: Path) -> Readme:
181	"""
182	Read the README file, so it can be used as long description for the package.
183
184	Supported formats:
185
186	  * Plain text (``*.txt``)
187	  * Markdown (``*.md``)
188	  * ReStructured Text (``*.rst``)
189
190	:param readmeFile:         Path to the `README` file as an instance of :class:`Path`.
191	:returns:                  A tuple containing the file content and the MIME type.
192	:raises TypeError:         If parameter 'readmeFile' is not of type :class:`~pathlib.Path`.
193	:raises ValueError:        If README file has an unsupported format.
194	:raises FileNotFoundError: If README file does not exist.
195	"""
	...
218
220@export
221def loadRequirementsFile(requirementsFile: Path, indent: int = 0, debug: bool = False) -> list[str]:
222	"""
223	Reads a `requirements.txt` file (recursively) and extracts all specified dependencies into an array.
224
225	Special dependency entries like Git repository references are translates to match the syntax expected by setuptools.
226
227	.. hint::
228
229	   Duplicates should be removed by converting the result to a :class:`set` and back to a :class:`list`.
230
231	   .. code-block:: Python
232
233	      requirements = list(set(loadRequirementsFile(requirementsFile)))
234
235	:param requirementsFile:   Path to the ``requirements.txt`` file as an instance of :class:`Path`.
236	:param indent:             Optional, indentation level used for the debug output of nested requirements files.
237	:param debug:              Optional, if ``True``, print found dependencies and recursion.
238	:returns:                  A list of dependencies.
239	:raises TypeError:         If parameter 'requirementsFile' is not of type :class:`~pathlib.Path`.
240	:raises FileNotFoundError: If requirements file does not exist.
241	"""
	...
246
247	def _loadRequirementsFile(requirementsFile: Path, indent: int) -> list[str]:
248		"""
249		Recursive variant of :func:`loadRequirementsFile`.
250
251		:param requirementsFile:   Path to the requirements file to read.
252		:param indent:             Indentation level used for the debug output of nested requirements files.
253		:returns:                  List of requirements read from that file and every file it includes.
254		:raises FileNotFoundError: If the requirements file doesn't exist.
255		"""
		...
287
	...
289
291@export
292class VersionInformation(metaclass=ExtendedType, slots=True):
293	"""Encapsulates version information extracted from a Python source file."""
294
295	_author: str          #: Author name(s).
296	_copyright: str       #: Copyright information.
297	_email: str           #: Author's email address.
298	_keywords: list[str]  #: Keywords.
299	_license: str         #: License name.
300	_description: str     #: Description of the package.
301	_version: str         #: Version number.
302
303	def __init__(
304		self,
305		author: str,
306		email: str,
307		copyright: str,
308		license: str,
309		version: str,
310		description: str,
311		keywords: Iterable[str]
312	) -> None:
313		"""
314		Initializes a Python package (version) information instance.
315
316		:param author:      Author of the Python package.
317		:param email:       The author's email address
318		:param copyright:   The copyright notice of the Package.
319		:param license:     The Python package's license.
320		:param version:     The Python package's version.
321		:param description: The Python package's short description.
322		:param keywords:    The Python package's list of keywords.
323		"""
		...
331
332	@readonly
333	def Author(self) -> str:
334		"""
335		Read-only property to access the name(s) of the package author(s) (:attr:`_author`).
336
337		:returns: Name(s) of the package author(s).
338		"""
		...
340
341	@readonly
342	def Copyright(self) -> str:
343		"""
344		Read-only property to access the package's copyright information (:attr:`_copyright`).
345
346		:returns: Copyright information.
347		"""
		...
349
350	@readonly
351	def Description(self) -> str:
352		"""
353		Read-only property to access the package description (:attr:`_description`).
354
355		:returns: Package description text.
356		"""
		...
358
359	@readonly
360	def Email(self) -> str:
361		"""
362		Read-only property to access the author's email address (:attr:`_email`).
363
364		:returns: Email address of the author.
365		"""
		...
367
368	@readonly
369	def Keywords(self) -> list[str]:
370		"""
371		Read-only property to access the package's keywords (:attr:`_keywords`).
372
373		:returns: List of keywords.
374		"""
		...
376
377	@readonly
378	def License(self) -> str:
379		"""
380		Read-only property to access the package's license (:attr:`_license`).
381
382		:returns: License name.
383		"""
		...
385
386	@readonly
387	def Version(self) -> str:
388		"""
389		Read-only property to access the package's version number (:attr:`_version`).
390
391		:returns: Version number.
392		"""
		...
394
395	def __str__(self) -> str:
396		"""
397		Return a string representation of this version information.
398
399		:returns: The version number.
400		"""
		...
402
404def _extractDescription(docString: Nullable[str]) -> str:
405	"""
406	Read a package's short description from the first paragraph of its module doc-string.
407
408	A package's short description **is** the summary of its module doc-string - the first paragraph - so the two are
409	one text in two places, and :func:`~pyTooling.Documentation.splitDocString` reads it.
410
411	It is folded into a single line, because a short description is one line of plain text while a doc-string is
412	wrapped to the source file's line length. Strong emphasis around the whole paragraph is removed for the same
413	reason: ``**An abstract VHDL language model.**`` is markup for the rendered documentation, and nothing renders it
414	where a short description is displayed.
415
416	:param docString:           The module's doc-string, or ``None`` if it has none.
417	:returns:                   The description as a single line, or an empty string if there is no doc-string.
418	:raises DocumentationError: If the first paragraph is too long to be a description.
419
420	.. seealso::
421
422	   :func:`~pyTooling.Documentation.splitDocString`
423	      |rarr| Reads the first paragraph, and rejects one that is too long to be a summary.
424	"""
	...
432
434@export
435def extractVersionInformation(sourceFile: Path) -> VersionInformation:
436	"""
437	Extract double underscored variables from a Python source file, so these can be used for single-sourcing information.
438
439	Supported variables:
440
441	* ``__author__``
442	* ``__copyright__``
443	* ``__email__``
444	* ``__keywords__``
445	* ``__license__``
446	* ``__version__``
447
448	The package's short description is not a dunder variable - it is the first paragraph of the source file's module
449	doc-string, which is where a package already describes itself.
450
451	:param sourceFile:        Path to a Python source file as an instance of :class:`Path`.
452	:returns:                 An instance of :class:`VersionInformation` with gathered variable contents.
453	:raises TypeError:        If parameter 'sourceFile' is not of type :class:`~pathlib.Path`.
454	:raises PackagingError:   If the given file doesn't exist.
455	:raises PackagingError:   If the given file can't be parsed as Python source code.
456	:raises PackagingError:   If a dunder variable has an unexpected format.
457	:raises AssertionError:   If a dunder variable is missing in the given file.
458	"""
	...
539
541STATUS: dict[str, str] = {
542	"planning":  "1 - Planning",
543	"pre-alpha": "2 - Pre-Alpha",
544	"alpha":     "3 - Alpha",
545	"beta":      "4 - Beta",
546	"stable":    "5 - Production/Stable",
547	"mature":    "6 - Mature",
548	"inactive":  "7 - Inactive"
549}
550"""
551A dictionary of supported development status values.
552
553The mapping's value will be appended to ``Development Status :: `` to form a package classifier.
554
5551. Planning
5562. Pre-Alpha
5573. Alpha
5584. Beta
5595. Production/Stable
5606. Mature
5617. Inactive
562
563.. seealso::
564
565   `Python package classifiers <https://pypi.org/classifiers/>`__
566"""
567
568DEFAULT_LICENSE = Apache_2_0_License
569"""
570Default license (Apache License, 2.0) used by :func:`DescribePythonPackage` and :func:`DescribePythonPackageHostedOnGitHub`
571if parameter ``license`` is not assigned.
572"""
573
574DEFAULT_PY_VERSIONS = ("3.11", "3.12", "3.13", "3.14", "3.15")
575"""
576A tuple of supported CPython versions used by :func:`DescribePythonPackage` and :func:`DescribePythonPackageHostedOnGitHub`
577if parameter ``pythonVersions`` is not assigned.
578
579.. seealso::
580
581   `Status of Python versions <https://devguide.python.org/versions/>`__
582"""
583
584DEFAULT_CLASSIFIERS = (
585		"Operating System :: OS Independent",
586		"Intended Audience :: Developers",
587		"Topic :: Utilities"
588	)
589"""
590A list of Python package classifiers used by :func:`DescribePythonPackage` and :func:`DescribePythonPackageHostedOnGitHub`
591if parameter ``classifiers`` is not assigned.
592
593.. seealso::
594
595   `Python package classifiers <https://pypi.org/classifiers/>`__
596"""
597
598DEFAULT_README = Path("README.md")
599"""
600Path to the README file used by :func:`DescribePythonPackage` and :func:`DescribePythonPackageHostedOnGitHub`
601if parameter ``readmeFile`` is not assigned.
602"""
603
604DEFAULT_REQUIREMENTS = Path("requirements.txt")
605"""
606Path to the requirements file used by :func:`DescribePythonPackage` and :func:`DescribePythonPackageHostedOnGitHub`
607if parameter ``requirementsFile`` is not assigned.
608"""
609
610DEFAULT_DOCUMENTATION_REQUIREMENTS = Path("doc/requirements.txt")
611"""
612Path to the README requirements file used by :func:`DescribePythonPackage` and :func:`DescribePythonPackageHostedOnGitHub`
613if parameter ``documentationRequirementsFile`` is not assigned.
614"""
615
616DEFAULT_TEST_REQUIREMENTS = Path("tests/requirements.txt")
617"""
618Path to the README requirements file used by :func:`DescribePythonPackage` and :func:`DescribePythonPackageHostedOnGitHub`
619if parameter ``unittestRequirementsFile`` is not assigned.
620"""
621
622DEFAULT_PACKAGING_REQUIREMENTS = Path("build/requirements.txt")
623"""
624Path to the package requirements file used by :func:`DescribePythonPackage` and :func:`DescribePythonPackageHostedOnGitHub`
625if parameter ``packagingRequirementsFile`` is not assigned.
626"""
627
628DEFAULT_VERSION_FILE = Path("__init__.py")
629
630_DIRECT_REFERENCE_PATTERN = re_compile(r"^\s*[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?\s*(?:\[[^\]]*\])?\s*@")
631
633def _removeDirectReferences(requirements: Iterable[str], extra: str, filePath: Nullable[Path]) -> list[str]:
634	"""
635	Remove direct references (``name @ URL``) from the requirements of an extra.
636
637	The Python Package Index rejects a package whose metadata contains a direct reference. Each removed requirement is
638	reported as a :exc:`DirectReferenceWarning` to a :class:`~pyTooling.Warning.WarningCollector`.
639
640	:param requirements:                   Requirements of the extra.
641	:param extra:                          Name of the extra.
642	:param filePath:                       The requirements file the requirements were read from, or ``None`` for
643	                                       parameter 'additionalRequirements'.
644	:returns:                              The requirements, which aren't direct references.
645	:raises UnhandledCriticalWarningError: If a requirement is a direct reference and no
646	                                       :class:`~pyTooling.Warning.WarningCollector` collects the warning.
647	"""
	...
665
667def _collectEntryPoints(
668	consoleScripts: Nullable[dict[str, str]],
669	guiScripts: Nullable[dict[str, str]],
670	pytestPlugins: Nullable[dict[str, str]]
671) -> Nullable[dict[str, list[str]]]:
672	"""
673	Collect what a package advertises into setuptools' entry point groups.
674
675	Each parameter names one kind of thing a package can offer, so a caller says *what* it provides and this
676	function knows *how* it is declared - which group it belongs to, and setuptools' ``"name = entry.point"``
677	spelling.
678
679	:param consoleScripts: Command line programs, declared as ``console_scripts``.
680	:param guiScripts:     Windowed programs, declared as ``gui_scripts``.
681	:param pytestPlugins:  Pytest plugins, declared as ``pytest11``.
682	:returns:              A dictionary mapping a group to its entry point lines, or ``None`` if a package
683	                       advertises nothing.
684	"""
	...
698
700@export
701def DescribePythonPackage(
702	packageName: str,
703	projectURL: str,
704	sourceCodeURL: str,
705	documentationURL: str,
706	issueTrackerCodeURL: str,
707	description: Nullable[str] = None,
708	keywords: Nullable[Iterable[str]] = None,
709	license: License = DEFAULT_LICENSE,
710	readmeFile: Path = DEFAULT_README,
711	requirementsFile: Path = DEFAULT_REQUIREMENTS,
712	documentationRequirementsFile: Path = DEFAULT_DOCUMENTATION_REQUIREMENTS,
713	unittestRequirementsFile: Path = DEFAULT_TEST_REQUIREMENTS,
714	packagingRequirementsFile: Path = DEFAULT_PACKAGING_REQUIREMENTS,
715	additionalRequirements: Nullable[dict[str, list[str]]] = None,
716	sourceFileWithVersion: Nullable[Path] = DEFAULT_VERSION_FILE,
717	classifiers: Iterable[str] = DEFAULT_CLASSIFIERS,
718	developmentStatus: str = "stable",
719	pythonVersions: Sequence[str] = DEFAULT_PY_VERSIONS,
720	consoleScripts: Nullable[dict[str, str]] = None,
721	guiScripts: Nullable[dict[str, str]] = None,
722	pytestPlugins: Nullable[dict[str, str]] = None,
723	dataFiles: Nullable[dict[str, list[str]]] = None,
724	debug: bool = False
725) -> dict[str, Any]:
726	"""
727	Helper function to describe a Python package.
728
729	.. hint::
730
731	   Some information will be gathered automatically from well-known files.
732
733	   Examples: ``README.md``, ``requirements.txt``, ``__init__.py``
734
735	.. topic:: Handling of namespace packages
736
737	   If parameter ``packageName`` contains a dot, a namespace package is assumed. Then
738	   :func:`setuptools.find_namespace_packages` is used to discover package files. |br|
739	   Otherwise, the package is considered a normal package and :func:`setuptools.find_packages` is used.
740
741	   In both cases, the following packages (directories) are excluded from search:
742
743	   * ``build``, ``build.*``
744	   * ``dist``, ``dist.*``
745	   * ``doc``, ``doc.*``
746	   * ``tests``, ``tests.*``
747
748	.. topic:: Handling of minimal Python version
749
750	   The minimal required Python version is selected from parameter ``pythonVersions``.
751
752	.. topic:: Handling of dunder variables
753
754	   A Python source file specified by parameter ``sourceFileWithVersion`` will be analyzed with Pythons parser and the
755	   resulting AST will be searched for the following dunder variables:
756
757	   * ``__author__``: :class:`str`
758	   * ``__copyright__``: :class:`str`
759	   * ``__email__``: :class:`str`
760	   * ``__keywords__``: :class:`typing.Iterable`[:class:`str`]
761	   * ``__license__``: :class:`str`
762	   * ``__version__``: :class:`str`
763
764	The gathered information be used to add further mappings in the result dictionary.
765
766	.. topic:: Handling of package classifiers
767
768	   To reduce redundantly provided parameters to this function (e.g. supported ``pythonVersions``), only additional
769	   classifiers should be provided via parameter ``classifiers``. The supported Python versions will be implicitly
770	   converted to package classifiers, so no need to specify them in parameter ``classifiers``.
771
772	   The following classifiers are implicitly handled:
773
774	   license
775	     The license specified by parameter ``license`` is translated into a classifier. |br|
776	     See also :meth:`pyTooling.Licensing.License.PythonClassifier`
777
778	   Python versions
779	     Always add ``Programming Language :: Python :: 3 :: Only``. |br|
780	     For each value in ``pythonVersions``, one ``Programming Language :: Python :: Major.Minor`` is added.
781
782	   Development status
783	     The development status specified by parameter ``developmentStatus`` is translated to a classifier and added.
784
785	.. topic:: Handling of extra requirements
786
787	   If additional requirement files are provided, e.g. requirements to build the documentation, then *extra*
788	   requirements are defined. These can be installed via ``pip install packageName[extraName]``. If so, an extra called
789	   ``all`` is added, so developers can install all dependencies needed for package development.
790
791	   ``doc``
792	     If parameter ``documentationRequirementsFile`` is present, an extra requirements called ``doc`` will be defined.
793	   ``test``
794	     If parameter ``unittestRequirementsFile`` is present, an extra requirements called ``test`` will be defined.
795	   ``build``
796	     If parameter ``packagingRequirementsFile`` is present, an extra requirements called ``build`` will be defined.
797	   User-defined
798	     If parameter ``additionalRequirements`` is present, an extra requirements for every mapping entry in the
799	     dictionary will be added.
800	   ``all``
801	     If any of the above was added, an additional extra requirement called ``all`` will be added, summarizing all
802	     extra requirements.
803
804	   A requirement with a direct reference (``name @ URL``, e.g. ``pyTooling.Sphinx @ git+https://...@dev``) is left out
805	   of every extra, because the Python Package Index rejects a package whose metadata contains one. Each one is
806	   reported as a critical :exc:`DirectReferenceWarning` to a :class:`~pyTooling.Warning.WarningCollector`; without
807	   a collector up the call-hierarchy, :exc:`~pyTooling.Warning.UnhandledCriticalWarningError` is raised. So a project
808	   can name a dependency, which isn't on PyPI yet, by its repository in e.g. ``doc/requirements.txt`` - the
809	   documentation build installs it - and still be released, if its :file:`setup.py` collects the warnings. The base
810	   requirements (``requirementsFile``) are kept as they are: without one of them, the package wouldn't work.
811
812	.. topic:: Handling of keywords
813
814	   If parameter ``keywords`` is not specified, the dunder variable ``__keywords__`` from ``sourceFileWithVersion``
815	   will be used. Otherwise, the content of the parameter, if not None or empty.
816
817	.. topic:: Handling of the description
818
819	   If parameter ``description`` is not specified, the first paragraph of the module doc-string in
820	   ``sourceFileWithVersion`` is used, so a package describes itself in one place. An explicitly passed description
821	   always wins - including an empty one.
822
823	:param packageName:                    Name of the Python package.
824	:param projectURL:                     URL to the Python project.
825	:param sourceCodeURL:                  URL to the Python source code.
826	:param documentationURL:               URL to the package's documentation.
827	:param issueTrackerCodeURL:            URL to the projects issue tracker (ticket system).
828	:param description:                    Optional, short description of the package. (Default: the first paragraph
829	                                       of the module doc-string in ``sourceFileWithVersion``.) The long description
830	                                       is read from the README file.
831	:param keywords:                       Optional, a list of keywords.
832	:param license:                        Optional, the package's license. (Default: ``Apache License, 2.0``, see
833	                                       :const:`DEFAULT_LICENSE`)
834	:param readmeFile:                     Optional, the path to the README file. (Default: ``README.md``, see
835	                                       :const:`DEFAULT_README`)
836	:param requirementsFile:               Optional, the path to the project's requirements file. (Default:
837	                                       ``requirements.txt``, see :const:`DEFAULT_REQUIREMENTS`)
838	:param documentationRequirementsFile:  Optional, the path to the project's requirements file for documentation.
839	                                       (Default: ``doc/requirements.txt``, see
840	                                       :const:`DEFAULT_DOCUMENTATION_REQUIREMENTS`)
841	:param unittestRequirementsFile:       Optional, the path to the project's requirements file for unit tests. (Default:
842	                                       ``tests/requirements.txt``, see :const:`DEFAULT_TEST_REQUIREMENTS`)
843	:param packagingRequirementsFile:      Optional, the path to the project's requirements file for packaging. (Default:
844	                                       ``build/requirements.txt``, see :const:`DEFAULT_PACKAGING_REQUIREMENTS`)
845	:param additionalRequirements:         Optional, a dictionary of a lists with additional requirements. (default: None)
846	:param sourceFileWithVersion:          Optional, the path to the project's source file containing dunder variables
847	                                       like ``__version__``. (Default: ``__init__.py``, see
848	                                       :const:`DEFAULT_VERSION_FILE`)
849	:param classifiers:                    Optional, a list of package classifiers. (Default: 3 classifiers, see
850	                                       :const:`DEFAULT_CLASSIFIERS`)
851	:param developmentStatus:              Optional, development status of the package. (Default: stable, see
852	                                       :const:`STATUS` for supported status values)
853	:param pythonVersions:                 Optional, a list of supported Python 3 version. (Default: all currently
854	                                       maintained CPython versions, see :const:`DEFAULT_PY_VERSIONS`)
855	:param consoleScripts:                 Optional, a dictionary mapping command line names to entry points, declared
856	                                       as ``console_scripts``. (Default: None)
857	:param guiScripts:                     Optional, like ``consoleScripts``, but declared as ``gui_scripts`` - on
858	                                       Windows such a program starts without a console window. (Default: None)
859	:param pytestPlugins:                  Optional, a dictionary mapping plugin names to entry points, declared as
860	                                       ``pytest11``. The classifier ``Framework :: Pytest`` is added with it.
861	                                       (Default: None)
862	:param dataFiles:                      Optional, a dictionary mapping package names to lists of additional data files.
863	:param debug:                          Optional, if ``True``, enable extended outputs for debugging.
864	:returns:                              A dictionary suitable for :func:`setuptools.setup`.
865	:raises TypeError:                     If parameter 'license' is not of type :class:`~pyTooling.Licensing.License`.
866	:raises TypeError:                     If parameter 'readmeFile' is not of type :class:`~pathlib.Path`.
867	:raises TypeError:                     If parameter 'requirementsFile' is not of type :class:`~pathlib.Path`.
868	:raises TypeError:                     If parameter 'documentationRequirementsFile' is not of type
869	                                       :class:`~pathlib.Path`.
870	:raises TypeError:                     If parameter 'unittestRequirementsFile' is not of type :class:`~pathlib.Path`.
871	:raises TypeError:                     If parameter 'packagingRequirementsFile' is not of type :class:`~pathlib.Path`.
872	:raises TypeError:                     If parameter 'sourceFileWithVersion' is not of type :class:`~pathlib.Path`.
873	:raises MissingDependencyError:        If package 'setuptools' is not available.
874	:raises FileNotFoundError:             If README file doesn't exist.
875	:raises FileNotFoundError:             If requirements file doesn't exist.
876	:raises FileNotFoundError:             If package file with dunder variables doesn't exist.
877	:raises ValueError:                    If developmentStatus uses an unsupported value. (See :const:`STATUS`)
878	:raises ValueError:                    If the content type of the README file is not supported. (See
879	                                       :func:`loadReadmeFile`)
880	:raises FileNotFoundError:             If the README file doesn't exist. (See :func:`loadReadmeFile`)
881	:raises FileNotFoundError:             If the requirements file doesn't exist. (See :func:`loadRequirementsFile`)
882	:raises Exception:                     If the package's directory doesn't exist, or if a requirements file is
883	                                       malformed.
884	:raises PackagingError:                If no description was given and the package file has no module doc-string.
885	:raises UnhandledCriticalWarningError: If an extra's requirement is a direct reference and no
886	                                       :class:`~pyTooling.Warning.WarningCollector` collects the
887	                                       :exc:`DirectReferenceWarning`.
888	"""
	...
1037
1038	def _naturalSorting(array: Iterable[str]) -> list[str]:
1039		"""
1040		A simple natural sorting implementation.
1041
1042		:param array: The strings to sort.
1043		:returns:     The strings, sorted with embedded numbers compared numerically.
1044		"""
1046		def _toInt(text: str) -> Union[str, int]:
1047			"""
1048			Try to convert a :class:`str` to :class:`int` if possible, otherwise preserve the string.
1049
1050			:param text: The text to convert.
1051			:returns:    The converted integer, or the unchanged string.
1052			"""
			...
1054
1055		def _createKey(text: str) -> tuple[Union[str, float], ...]:
1056			"""
1057			Split the text into a tuple of multiple :class:`str` and :class:`int` fields, so embedded numbers can be sorted by
1058			their value.
1059
1060			:param text: The text to split.
1061			:returns:    Tuple of string and integer fields, usable as a sort key.
1062			"""
			...
1064
		...
1068
	...
1115
1117@export
1118def DescribePythonPackageHostedOnGitHub(
1119	packageName: str,
1120	gitHubNamespace: str,
1121	gitHubRepository: Nullable[str] = None,
1122	projectURL: Nullable[str] = None,
1123	description: Nullable[str] = None,
1124	keywords: Nullable[Iterable[str]] = None,
1125	license: License = DEFAULT_LICENSE,
1126	readmeFile: Path = DEFAULT_README,
1127	requirementsFile: Path = DEFAULT_REQUIREMENTS,
1128	documentationRequirementsFile: Path = DEFAULT_DOCUMENTATION_REQUIREMENTS,
1129	unittestRequirementsFile: Path = DEFAULT_TEST_REQUIREMENTS,
1130	packagingRequirementsFile: Path = DEFAULT_PACKAGING_REQUIREMENTS,
1131	additionalRequirements: Nullable[dict[str, list[str]]] = None,
1132	sourceFileWithVersion: Path = DEFAULT_VERSION_FILE,
1133	classifiers: Iterable[str] = DEFAULT_CLASSIFIERS,
1134	developmentStatus: str = "stable",
1135	pythonVersions: Sequence[str] = DEFAULT_PY_VERSIONS,
1136	consoleScripts: Nullable[dict[str, str]] = None,
1137	guiScripts: Nullable[dict[str, str]] = None,
1138	pytestPlugins: Nullable[dict[str, str]] = None,
1139	dataFiles: Nullable[dict[str, list[str]]] = None,
1140	debug: bool = False
1141) -> dict[str, Any]:
1142	"""
1143	Helper function to describe a Python package when the source code is hosted on GitHub.
1144
1145	This is a wrapper for :func:`DescribePythonPackage`, because some parameters can be simplified by knowing the GitHub
1146	namespace and repository name: issue tracker URL, source code URL, ...
1147
1148	:param packageName:                    Name of the Python package.
1149	:param gitHubNamespace:                Name of the GitHub namespace (organization or user).
1150	:param gitHubRepository:               Optional, name of the GitHub repository.
1151	:param projectURL:                     Optional, URL to the Python project.
1152	:param description:                    Optional, short description of the package. (Default: the first paragraph
1153	                                       of the module doc-string in ``sourceFileWithVersion``.) The long description
1154	                                       is read from the README file.
1155	:param keywords:                       Optional, a list of keywords.
1156	:param license:                        Optional, the package's license. (Default: ``Apache License, 2.0``, see
1157	                                       :const:`DEFAULT_LICENSE`)
1158	:param readmeFile:                     Optional, the path to the README file. (Default: ``README.md``, see
1159	                                       :const:`DEFAULT_README`)
1160	:param requirementsFile:               Optional, the path to the project's requirements file. (Default:
1161	                                       ``requirements.txt``, see :const:`DEFAULT_REQUIREMENTS`)
1162	:param documentationRequirementsFile:  Optional, the path to the project's requirements file for documentation.
1163	                                       (Default: ``doc/requirements.txt``, see
1164	                                       :const:`DEFAULT_DOCUMENTATION_REQUIREMENTS`)
1165	:param unittestRequirementsFile:       Optional, the path to the project's requirements file for unit tests. (Default:
1166	                                       ``tests/requirements.txt``, see :const:`DEFAULT_TEST_REQUIREMENTS`)
1167	:param packagingRequirementsFile:      Optional, the path to the project's requirements file for packaging. (Default:
1168	                                       ``build/requirements.txt``, see :const:`DEFAULT_PACKAGING_REQUIREMENTS`)
1169	:param additionalRequirements:         Optional, a dictionary of a lists with additional requirements. (default: None)
1170	:param sourceFileWithVersion:          Optional, the path to the project's source file containing dunder variables
1171	                                       like ``__version__``. (Default: ``__init__.py``, see
1172	                                       :const:`DEFAULT_VERSION_FILE`)
1173	:param classifiers:                    Optional, a list of package classifiers. (Default: 3 classifiers, see
1174	                                       :const:`DEFAULT_CLASSIFIERS`)
1175	:param developmentStatus:              Optional, development status of the package. (Default: stable, see
1176	                                       :const:`STATUS` for supported status values)
1177	:param pythonVersions:                 Optional, a list of supported Python 3 version. (Default: all currently
1178	                                       maintained CPython versions, see :const:`DEFAULT_PY_VERSIONS`)
1179	:param consoleScripts:                 Optional, a dictionary mapping command line names to entry points, declared
1180	                                       as ``console_scripts``. (Default: None)
1181	:param guiScripts:                     Optional, like ``consoleScripts``, but declared as ``gui_scripts`` - on
1182	                                       Windows such a program starts without a console window. (Default: None)
1183	:param pytestPlugins:                  Optional, a dictionary mapping plugin names to entry points, declared as
1184	                                       ``pytest11``. The classifier ``Framework :: Pytest`` is added with it.
1185	                                       (Default: None)
1186	:param dataFiles:                      Optional, a dictionary mapping package names to lists of additional data files.
1187	:param debug:                          Optional, if ``True``, enable extended outputs for debugging.
1188	:returns:                              A dictionary suitable for :func:`setuptools.setup`.
1189	:raises TypeError:                     If parameter 'license' is not of type :class:`~pyTooling.Licensing.License`.
1190	:raises TypeError:                     If parameter 'readmeFile' is not of type :class:`~pathlib.Path`.
1191	:raises TypeError:                     If parameter 'requirementsFile' is not of type :class:`~pathlib.Path`.
1192	:raises TypeError:                     If parameter 'documentationRequirementsFile' is not of type
1193	                                       :class:`~pathlib.Path`.
1194	:raises TypeError:                     If parameter 'unittestRequirementsFile' is not of type :class:`~pathlib.Path`.
1195	:raises TypeError:                     If parameter 'packagingRequirementsFile' is not of type :class:`~pathlib.Path`.
1196	:raises TypeError:                     If parameter 'sourceFileWithVersion' is not of type :class:`~pathlib.Path`.
1197	:raises MissingDependencyError:        If package 'setuptools' is not available.
1198	:raises FileNotFoundError:             If README file doesn't exist.
1199	:raises FileNotFoundError:             If requirements file doesn't exist.
1200	:raises FileNotFoundError:             If package file with dunder variables doesn't exist.
1201	:raises ValueError:                    If developmentStatus uses an unsupported value. (See :const:`STATUS`)
1202	:raises ValueError:                    If the content type of the README file is not supported. (See
1203	                                       :func:`loadReadmeFile`)
1204	:raises FileNotFoundError:             If the README file doesn't exist. (See :func:`loadReadmeFile`)
1205	:raises FileNotFoundError:             If the requirements file doesn't exist. (See :func:`loadRequirementsFile`)
1206	:raises PackagingError:                If no description was given and the package file has no module doc-string.
1207	:raises UnhandledCriticalWarningError: If an extra's requirement is a direct reference and no
1208	                                       :class:`~pyTooling.Warning.WarningCollector` collects the
1209	                                       :exc:`DirectReferenceWarning`.
1210	"""
	...