Apply pre-commit Checks More Widely (#4135)

This commit is contained in:
Bibo-Joshi 2024-02-29 19:11:03 +01:00 committed by GitHub
parent 9c263fbd1a
commit 26f943771b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 104 additions and 100 deletions

View file

@ -10,7 +10,6 @@ repos:
hooks: hooks:
- id: ruff - id: ruff
name: ruff name: ruff
files: ^(telegram|examples|tests)/.*\.py$
additional_dependencies: additional_dependencies:
- httpx~=0.27.0 - httpx~=0.27.0
- tornado~=6.4 - tornado~=6.4
@ -32,7 +31,7 @@ repos:
rev: v3.0.3 rev: v3.0.3
hooks: hooks:
- id: pylint - id: pylint
files: ^(telegram|examples)/.*\.py$ files: ^(?!(tests|docs)).*\.py$
additional_dependencies: additional_dependencies:
- httpx~=0.27.0 - httpx~=0.27.0
- tornado~=6.4 - tornado~=6.4
@ -45,7 +44,7 @@ repos:
hooks: hooks:
- id: mypy - id: mypy
name: mypy-ptb name: mypy-ptb
files: ^telegram/.*\.py$ files: ^(?!(tests|examples|docs)).*\.py$
additional_dependencies: additional_dependencies:
- types-pytz - types-pytz
- types-cryptography - types-cryptography
@ -71,7 +70,6 @@ repos:
rev: v3.15.0 rev: v3.15.0
hooks: hooks:
- id: pyupgrade - id: pyupgrade
files: ^(telegram|examples|tests|docs)/.*\.py$
args: args:
- --py38-plus - --py38-plus
- repo: https://github.com/pycqa/isort - repo: https://github.com/pycqa/isort

View file

@ -108,12 +108,12 @@ You can also install ``python-telegram-bot-raw`` from source, though this is usu
$ git clone https://github.com/python-telegram-bot/python-telegram-bot $ git clone https://github.com/python-telegram-bot/python-telegram-bot
$ cd python-telegram-bot $ cd python-telegram-bot
$ python setup-raw.py install $ python setup_raw.py install
Note Note
---- ----
Installing the ``.tar.gz`` archive available on PyPi directly via ``pip`` will *not* work as expected, as ``pip`` does not recognize that it should use ``setup-raw.py`` instead of ``setup.py``. Installing the ``.tar.gz`` archive available on PyPi directly via ``pip`` will *not* work as expected, as ``pip`` does not recognize that it should use ``setup_raw.py`` instead of ``setup.py``.
Verifying Releases Verifying Releases
------------------ ------------------

0
docs/__init__.py Normal file
View file

0
docs/auxil/__init__.py Normal file
View file

View file

@ -64,7 +64,7 @@ class AdmonitionInserter:
ForwardRef('DefaultValue[DVValueType]') ForwardRef('DefaultValue[DVValueType]')
""" """
METHOD_NAMES_FOR_BOT_AND_APPBUILDER: dict[type, str] = { METHOD_NAMES_FOR_BOT_AND_APPBUILDER: typing.ClassVar[dict[type, str]] = {
cls: tuple(m[0] for m in _iter_own_public_methods(cls)) # m[0] means we take only names cls: tuple(m[0] for m in _iter_own_public_methods(cls)) # m[0] means we take only names
for cls in (telegram.Bot, telegram.ext.ApplicationBuilder) for cls in (telegram.Bot, telegram.ext.ApplicationBuilder)
} }
@ -159,7 +159,7 @@ class AdmonitionInserter:
telegram.ext, inspect.isclass telegram.ext, inspect.isclass
) )
for class_name, inspected_class in classes_to_inspect: for _class_name, inspected_class in classes_to_inspect:
# We need to make "<class 'telegram._files.sticker.StickerSet'>" into # We need to make "<class 'telegram._files.sticker.StickerSet'>" into
# "telegram.StickerSet" because that's the way the classes are mentioned in # "telegram.StickerSet" because that's the way the classes are mentioned in
# docstrings. # docstrings.
@ -197,8 +197,8 @@ class AdmonitionInserter:
"Error generating Sphinx 'Available in' admonition " "Error generating Sphinx 'Available in' admonition "
f"(admonition_inserter.py). Class {name_of_class_in_attr} present in " f"(admonition_inserter.py). Class {name_of_class_in_attr} present in "
f"attribute {target_attr} of class {name_of_inspected_class_in_docstr}" f"attribute {target_attr} of class {name_of_inspected_class_in_docstr}"
f" could not be resolved. {str(e)}" f" could not be resolved. {e!s}"
) ) from e
# Properties need to be parsed separately because they act like attributes but not # Properties need to be parsed separately because they act like attributes but not
# listed as attributes. # listed as attributes.
@ -240,8 +240,8 @@ class AdmonitionInserter:
"Error generating Sphinx 'Available in' admonition " "Error generating Sphinx 'Available in' admonition "
f"(admonition_inserter.py). Class {name_of_class_in_prop} present in " f"(admonition_inserter.py). Class {name_of_class_in_prop} present in "
f"property {prop_name} of class {name_of_inspected_class_in_docstr}" f"property {prop_name} of class {name_of_inspected_class_in_docstr}"
f" could not be resolved. {str(e)}" f" could not be resolved. {e!s}"
) ) from e
return self._generate_admonitions(attrs_for_class, admonition_type="available_in") return self._generate_admonitions(attrs_for_class, admonition_type="available_in")
@ -271,8 +271,8 @@ class AdmonitionInserter:
raise NotImplementedError( raise NotImplementedError(
"Error generating Sphinx 'Returned in' admonition " "Error generating Sphinx 'Returned in' admonition "
f"(admonition_inserter.py). {cls}, method {method_name}. " f"(admonition_inserter.py). {cls}, method {method_name}. "
f"Couldn't resolve type hint in return annotation {ret_annot}. {str(e)}" f"Couldn't resolve type hint in return annotation {ret_annot}. {e!s}"
) ) from e
return self._generate_admonitions(methods_for_class, admonition_type="returned_in") return self._generate_admonitions(methods_for_class, admonition_type="returned_in")
@ -297,7 +297,7 @@ class AdmonitionInserter:
# inspect methods of all telegram classes for return statements that indicate # inspect methods of all telegram classes for return statements that indicate
# that this given method is a shortcut for a Bot method # that this given method is a shortcut for a Bot method
for class_name, cls in inspect.getmembers(telegram, predicate=inspect.isclass): for _class_name, cls in inspect.getmembers(telegram, predicate=inspect.isclass):
# no need to inspect Bot's own methods, as Bot can't have shortcuts in Bot # no need to inspect Bot's own methods, as Bot can't have shortcuts in Bot
if cls is telegram.Bot: if cls is telegram.Bot:
continue continue
@ -344,8 +344,8 @@ class AdmonitionInserter:
raise NotImplementedError( raise NotImplementedError(
"Error generating Sphinx 'Use in' admonition " "Error generating Sphinx 'Use in' admonition "
f"(admonition_inserter.py). {cls}, method {method_name}, parameter " f"(admonition_inserter.py). {cls}, method {method_name}, parameter "
f"{param}: Couldn't resolve type hint {param.annotation}. {str(e)}" f"{param}: Couldn't resolve type hint {param.annotation}. {e!s}"
) ) from e
return self._generate_admonitions(methods_for_class, admonition_type="use_in") return self._generate_admonitions(methods_for_class, admonition_type="use_in")
@ -359,17 +359,19 @@ class AdmonitionInserter:
If no key phrases are found, the admonition will be inserted at the very end. If no key phrases are found, the admonition will be inserted at the very end.
""" """
for idx, value in list(enumerate(lines)): for idx, value in list(enumerate(lines)):
if ( if value.startswith(
value.startswith(".. seealso:") (
# The docstring contains heading "Examples:", but Sphinx will have it converted ".. seealso:",
# to ".. admonition: Examples": # The docstring contains heading "Examples:", but Sphinx will have it converted
or value.startswith(".. admonition:: Examples") # to ".. admonition: Examples":
or value.startswith(".. version") ".. admonition:: Examples",
# The space after ":param" is important because docstring can contain ":paramref:" ".. version",
# in its plain text in the beginning of a line (e.g. ExtBot): # The space after ":param" is important because docstring can contain
or value.startswith(":param ") # ":paramref:" in its plain text in the beginning of a line (e.g. ExtBot):
# some classes (like "Credentials") have no params, so insert before attrs: ":param ",
or value.startswith(".. attribute::") # some classes (like "Credentials") have no params, so insert before attrs:
".. attribute::",
)
): ):
return idx return idx
return len(lines) - 1 return len(lines) - 1
@ -411,7 +413,7 @@ class AdmonitionInserter:
# so its page needs no admonitions. # so its page needs no admonitions.
continue continue
attrs = sorted(attrs) sorted_attrs = sorted(attrs)
# e.g. for admonition type "use_in" the title will be "Use in" and CSS class "use-in". # e.g. for admonition type "use_in" the title will be "Use in" and CSS class "use-in".
admonition = f""" admonition = f"""
@ -419,11 +421,11 @@ class AdmonitionInserter:
.. admonition:: {admonition_type.title().replace("_", " ")} .. admonition:: {admonition_type.title().replace("_", " ")}
:class: {admonition_type.replace("_", "-")} :class: {admonition_type.replace("_", "-")}
""" """
if len(attrs) > 1: if len(sorted_attrs) > 1:
for target_attr in attrs: for target_attr in sorted_attrs:
admonition += "\n * " + target_attr admonition += "\n * " + target_attr
else: else:
admonition += f"\n {attrs[0]}" admonition += f"\n {sorted_attrs[0]}"
admonition += "\n " # otherwise an unexpected unindent warning will be issued admonition += "\n " # otherwise an unexpected unindent warning will be issued
admonition_for_class[cls] = admonition admonition_for_class[cls] = admonition
@ -516,12 +518,12 @@ class AdmonitionInserter:
# If it isn't resolved, we'll have the program throw an exception to be sure. # If it isn't resolved, we'll have the program throw an exception to be sure.
try: try:
cls = self._resolve_class(m.group("class_name")) cls = self._resolve_class(m.group("class_name"))
except AttributeError: except AttributeError as exc:
# skip known ForwardRef's that need not be resolved to a Telegram class # skip known ForwardRef's that need not be resolved to a Telegram class
if self.FORWARD_REF_SKIP_PATTERN.match(str(arg)): if self.FORWARD_REF_SKIP_PATTERN.match(str(arg)):
pass pass
else: else:
raise NotImplementedError(f"Could not process ForwardRef: {arg}") raise NotImplementedError(f"Could not process ForwardRef: {arg}") from exc
else: else:
yield cls yield cls
@ -587,6 +589,7 @@ class AdmonitionInserter:
# If neither option works, this is not a PTB class. # If neither option works, this is not a PTB class.
except (NameError, AttributeError): except (NameError, AttributeError):
continue continue
return None
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -16,6 +16,7 @@
# You should have received a copy of the GNU Lesser Public License # You should have received a copy of the GNU Lesser Public License
# along with this program. If not, see [http://www.gnu.org/licenses/]. # along with this program. If not, see [http://www.gnu.org/licenses/].
import inspect import inspect
from typing import List
keyword_args = [ keyword_args = [
"Keyword Arguments:", "Keyword Arguments:",
@ -84,13 +85,12 @@ get_updates_read_timeout_addition = [
] ]
def find_insert_pos_for_kwargs(lines: list[str]) -> int: def find_insert_pos_for_kwargs(lines: List[str]) -> int:
"""Finds the correct position to insert the keyword arguments and returns the index.""" """Finds the correct position to insert the keyword arguments and returns the index."""
for idx, value in reversed(list(enumerate(lines))): # reversed since :returns: is at the end for idx, value in reversed(list(enumerate(lines))): # reversed since :returns: is at the end
if value.startswith("Returns"): if value.startswith("Returns"):
return idx return idx
else: return False
return False
def check_timeout_and_api_kwargs_presence(obj: object) -> int: def check_timeout_and_api_kwargs_presence(obj: object) -> int:

View file

@ -20,6 +20,8 @@ to link to the correct files & lines on github. Can be simplified once
https://github.com/sphinx-doc/sphinx/issues/1556 is closed https://github.com/sphinx-doc/sphinx/issues/1556 is closed
""" """
import subprocess import subprocess
from pathlib import Path
from typing import Dict, Tuple
from sphinx.util import logging from sphinx.util import logging
@ -30,7 +32,7 @@ sphinx_logger = logging.getLogger(__name__)
# must be a module-level variable so that it can be written to by the `autodoc-process-docstring` # must be a module-level variable so that it can be written to by the `autodoc-process-docstring`
# event handler in `sphinx_hooks.py` # event handler in `sphinx_hooks.py`
LINE_NUMBERS = {} LINE_NUMBERS: Dict[str, Tuple[Path, int, int]] = {}
def _git_branch() -> str: def _git_branch() -> str:
@ -52,7 +54,7 @@ git_branch = _git_branch()
base_url = "https://github.com/python-telegram-bot/python-telegram-bot/blob/" base_url = "https://github.com/python-telegram-bot/python-telegram-bot/blob/"
def linkcode_resolve(_, info): def linkcode_resolve(_, info) -> str:
"""See www.sphinx-doc.org/en/master/usage/extensions/linkcode.html""" """See www.sphinx-doc.org/en/master/usage/extensions/linkcode.html"""
combined = ".".join((info["module"], info["fullname"])) combined = ".".join((info["module"], info["fullname"]))
# special casing for ExtBot which is due to the special structure of extbot.rst # special casing for ExtBot which is due to the special structure of extbot.rst
@ -71,7 +73,7 @@ def linkcode_resolve(_, info):
line_info = LINE_NUMBERS.get(info["module"]) line_info = LINE_NUMBERS.get(info["module"])
if not line_info: if not line_info:
return return None
file, start_line, end_line = line_info file, start_line, end_line = line_info
return f"{base_url}{git_branch}/{file}#L{start_line}-L{end_line}" return f"{base_url}{git_branch}/{file}#L{start_line}-L{end_line}"

View file

@ -67,9 +67,9 @@ def autodoc_skip_member(app, what, name, obj, skip, options):
return True return True
break break
if name == "filter" and obj.__module__ == "telegram.ext.filters": if name == "filter" and obj.__module__ == "telegram.ext.filters" and not included_in_obj:
if not included_in_obj: return True # return True to exclude from docs.
return True # return True to exclude from docs. return None
def autodoc_process_docstring( def autodoc_process_docstring(
@ -118,7 +118,7 @@ def autodoc_process_docstring(
): ):
effective_insert: list[str] = media_write_timeout_deprecation effective_insert: list[str] = media_write_timeout_deprecation
elif get_updates and to_insert.lstrip().startswith("read_timeout"): elif get_updates and to_insert.lstrip().startswith("read_timeout"):
effective_insert = [to_insert] + get_updates_read_timeout_addition effective_insert = [to_insert, *get_updates_read_timeout_addition]
else: else:
effective_insert = [to_insert] effective_insert = [to_insert]
@ -166,11 +166,11 @@ def autodoc_process_docstring(
autodoc_process_docstring(app, "method", f"{name}.__init__", obj.__init__, options, lines) autodoc_process_docstring(app, "method", f"{name}.__init__", obj.__init__, options, lines)
def autodoc_process_bases(app, name, obj, option, bases: list): def autodoc_process_bases(app, name, obj, option, bases: list) -> None:
"""Here we fine tune how the base class's classes are displayed.""" """Here we fine tune how the base class's classes are displayed."""
for idx, base in enumerate(bases): for idx, raw_base in enumerate(bases):
# let's use a string representation of the object # let's use a string representation of the object
base = str(base) base = str(raw_base)
# Special case for abstract context managers which are wrongly resoled for some reason # Special case for abstract context managers which are wrongly resoled for some reason
if base.startswith("typing.AbstractAsyncContextManager"): if base.startswith("typing.AbstractAsyncContextManager"):

View file

@ -81,11 +81,12 @@ class TGConstXRefRole(PyXRefRole):
): ):
return repr(value), target return repr(value), target
sphinx_logger.warning( sphinx_logger.warning(
f"%s:%d: WARNING: Did not convert reference %s. :{CONSTANTS_ROLE}: is not supposed" "%s:%d: WARNING: Did not convert reference %s. :%s: is not supposed"
" to be used with this type of target.", " to be used with this type of target.",
refnode.source, refnode.source,
refnode.line, refnode.line,
refnode.rawsource, refnode.rawsource,
CONSTANTS_ROLE,
) )
return title, target return title, target
except Exception as exc: except Exception as exc:

View file

@ -1,4 +1,3 @@
import os
import re import re
import sys import sys
from pathlib import Path from pathlib import Path
@ -8,7 +7,7 @@ from pathlib import Path
# documentation root, use os.path.abspath to make it absolute, like shown here. # documentation root, use os.path.abspath to make it absolute, like shown here.
from sphinx.application import Sphinx from sphinx.application import Sphinx
sys.path.insert(0, os.path.abspath("../..")) sys.path.insert(0, str(Path("../..").resolve().absolute()))
# -- General configuration ------------------------------------------------ # -- General configuration ------------------------------------------------
# General information about the project. # General information about the project.
@ -310,13 +309,13 @@ texinfo_documents = [
# Due to Sphinx behaviour, these imports only work when imported here, not at top of module. # Due to Sphinx behaviour, these imports only work when imported here, not at top of module.
# Not used but must be imported for the linkcode extension to find it # Not used but must be imported for the linkcode extension to find it
from docs.auxil.link_code import linkcode_resolve from docs.auxil.link_code import linkcode_resolve # noqa: E402, F401
from docs.auxil.sphinx_hooks import ( from docs.auxil.sphinx_hooks import ( # noqa: E402
autodoc_process_bases, autodoc_process_bases,
autodoc_process_docstring, autodoc_process_docstring,
autodoc_skip_member, autodoc_skip_member,
) )
from docs.auxil.tg_const_role import CONSTANTS_ROLE, TGConstXRefRole from docs.auxil.tg_const_role import CONSTANTS_ROLE, TGConstXRefRole # noqa: E402
def setup(app: Sphinx): def setup(app: Sphinx):

View file

@ -26,6 +26,7 @@ select = ["E", "F", "I", "PL", "UP", "RUF", "PTH", "C4", "B", "PIE", "SIM", "RET
[tool.ruff.lint.per-file-ignores] [tool.ruff.lint.per-file-ignores]
"tests/*.py" = ["B018"] "tests/*.py" = ["B018"]
"tests/**.py" = ["RUF012", "ASYNC101"] "tests/**.py" = ["RUF012", "ASYNC101"]
"docs/**.py" = ["INP001"]
# PYLINT: # PYLINT:
[tool.pylint."messages control"] [tool.pylint."messages control"]

View file

@ -5,4 +5,4 @@ license_files = LICENSE, LICENSE.dual, LICENSE.lesser
max-line-length = 99 max-line-length = 99
ignore = W503, W605 ignore = W503, W605
extend-ignore = E203, E704 extend-ignore = E203, E704
exclude = setup.py, setup-raw.py docs/source/conf.py exclude = setup.py, setup_raw.py docs/source/conf.py

View file

@ -4,15 +4,16 @@ import subprocess
import sys import sys
from collections import defaultdict from collections import defaultdict
from pathlib import Path from pathlib import Path
from typing import Any, Dict, List, Tuple
from setuptools import find_packages, setup from setuptools import find_packages, setup
def get_requirements(): def get_requirements() -> List[str]:
"""Build the requirements list for this project""" """Build the requirements list for this project"""
requirements_list = [] requirements_list = []
with Path("requirements.txt").open() as reqs: with Path("requirements.txt").open(encoding="utf-8") as reqs:
for install in reqs: for install in reqs:
if install.startswith("#"): if install.startswith("#"):
continue continue
@ -21,7 +22,7 @@ def get_requirements():
return requirements_list return requirements_list
def get_packages_requirements(raw=False): def get_packages_requirements(raw: bool = False) -> Tuple[List[str], List[str]]:
"""Build the package & requirements list for this project""" """Build the package & requirements list for this project"""
reqs = get_requirements() reqs = get_requirements()
@ -34,68 +35,69 @@ def get_packages_requirements(raw=False):
return packs, reqs return packs, reqs
def get_optional_requirements(raw=False): def get_optional_requirements(raw: bool = False) -> Dict[str, List[str]]:
"""Build the optional dependencies""" """Build the optional dependencies"""
requirements = defaultdict(list) requirements = defaultdict(list)
with Path("requirements-opts.txt").open() as reqs: with Path("requirements-opts.txt").open(encoding="utf-8") as reqs:
for line in reqs: for line in reqs:
line = line.strip() effective_line = line.strip()
if not line or line.startswith("#"): if not effective_line or effective_line.startswith("#"):
continue continue
dependency, names = line.split("#") dependency, names = effective_line.split("#")
dependency = dependency.strip() dependency = dependency.strip()
for name in names.split(","): for name in names.split(","):
name = name.strip() effective_name = name.strip()
if name.endswith("!ext"): if effective_name.endswith("!ext"):
if raw: if raw:
continue continue
else: effective_name = effective_name[:-4]
name = name[:-4] requirements["ext"].append(dependency)
requirements["ext"].append(dependency) requirements[effective_name].append(dependency)
requirements[name].append(dependency)
requirements["all"].append(dependency) requirements["all"].append(dependency)
return requirements return requirements
def get_setup_kwargs(raw=False): def get_setup_kwargs(raw: bool = False) -> Dict[str, Any]:
"""Builds a dictionary of kwargs for the setup function""" """Builds a dictionary of kwargs for the setup function"""
packages, requirements = get_packages_requirements(raw=raw) packages, requirements = get_packages_requirements(raw=raw)
raw_ext = "-raw" if raw else "" raw_ext = "-raw" if raw else ""
readme = Path(f'README{"_RAW" if raw else ""}.rst') readme = Path(f'README{"_RAW" if raw else ""}.rst')
version_file = Path("telegram/_version.py").read_text() version_file = Path("telegram/_version.py").read_text(encoding="utf-8")
first_part = version_file.split("# SETUP.PY MARKER")[0] first_part = version_file.split("# SETUP.PY MARKER")[0]
exec(first_part) exec(first_part) # pylint: disable=exec-used
kwargs = dict( return {
script_name=f"setup{raw_ext}.py", "script_name": f"setup{raw_ext}.py",
name=f"python-telegram-bot{raw_ext}", "name": f"python-telegram-bot{raw_ext}",
version=locals()["__version__"], "version": locals()["__version__"],
author="Leandro Toledo", "author": "Leandro Toledo",
author_email="devs@python-telegram-bot.org", "author_email": "devs@python-telegram-bot.org",
license="LGPLv3", "license": "LGPLv3",
url="https://python-telegram-bot.org/", "url": "https://python-telegram-bot.org/",
# Keywords supported by PyPI can be found at https://github.com/pypa/warehouse/blob/aafc5185e57e67d43487ce4faa95913dd4573e14/warehouse/templates/packaging/detail.html#L20-L58 # Keywords supported by PyPI can be found at
project_urls={ # https://github.com/pypa/warehouse/blob/aafc5185e57e67d43487ce4faa95913dd4573e14/
# warehouse/templates/packaging/detail.html#L20-L58
"project_urls": {
"Documentation": "https://docs.python-telegram-bot.org", "Documentation": "https://docs.python-telegram-bot.org",
"Bug Tracker": "https://github.com/python-telegram-bot/python-telegram-bot/issues", "Bug Tracker": "https://github.com/python-telegram-bot/python-telegram-bot/issues",
"Source Code": "https://github.com/python-telegram-bot/python-telegram-bot", "Source Code": "https://github.com/python-telegram-bot/python-telegram-bot",
"News": "https://t.me/pythontelegrambotchannel", "News": "https://t.me/pythontelegrambotchannel",
"Changelog": "https://docs.python-telegram-bot.org/en/stable/changelog.html", "Changelog": "https://docs.python-telegram-bot.org/en/stable/changelog.html",
}, },
download_url=f"https://pypi.org/project/python-telegram-bot{raw_ext}/", "download_url": f"https://pypi.org/project/python-telegram-bot{raw_ext}/",
keywords="python telegram bot api wrapper", "keywords": "python telegram bot api wrapper",
description="We have made you a wrapper you can't refuse", "description": "We have made you a wrapper you can't refuse",
long_description=readme.read_text(), "long_description": readme.read_text(encoding="utf-8"),
long_description_content_type="text/x-rst", "long_description_content_type": "text/x-rst",
packages=packages, "packages": packages,
install_requires=requirements, "install_requires": requirements,
extras_require=get_optional_requirements(raw=raw), "extras_require": get_optional_requirements(raw=raw),
include_package_data=True, "include_package_data": True,
classifiers=[ "classifiers": [
"Development Status :: 5 - Production/Stable", "Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers", "Intended Audience :: Developers",
"License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)", "License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)",
@ -111,16 +113,14 @@ def get_setup_kwargs(raw=False):
"Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.12",
], ],
python_requires=">=3.8", "python_requires": ">=3.8",
) }
return kwargs
def main(): def main() -> None:
# If we're building, build ptb-raw as well # If we're building, build ptb-raw as well
if set(sys.argv[1:]) in [{"bdist_wheel"}, {"sdist"}, {"sdist", "bdist_wheel"}]: if set(sys.argv[1:]) in [{"bdist_wheel"}, {"sdist"}, {"sdist", "bdist_wheel"}]:
args = ["python", "setup-raw.py"] args = ["python", "setup_raw.py"]
args.extend(sys.argv[1:]) args.extend(sys.argv[1:])
subprocess.run(args, check=True, capture_output=True) subprocess.run(args, check=True, capture_output=True)

View file

@ -60,7 +60,7 @@ class StringEnum(str, _enum.Enum):
# Apply the __repr__ modification and __str__ fix to IntEnum # Apply the __repr__ modification and __str__ fix to IntEnum
class IntEnum(_enum.IntEnum): # pylint: disable=invalid-slots class IntEnum(_enum.IntEnum):
"""Helper class for int enums where ``str(member)`` prints the value, but ``repr(member)`` """Helper class for int enums where ``str(member)`` prints the value, but ``repr(member)``
gives ``EnumName.MEMBER_NAME``. gives ``EnumName.MEMBER_NAME``.
""" """

View file

@ -29,7 +29,7 @@ those classes.
* Most of the constants in this module are grouped into enums. * Most of the constants in this module are grouped into enums.
""" """
# TODO: Remove this when https://github.com/PyCQA/pylint/issues/6887 is resolved. # TODO: Remove this when https://github.com/PyCQA/pylint/issues/6887 is resolved.
# pylint: disable=invalid-enum-extension,invalid-slots # pylint: disable=invalid-enum-extension
__all__ = [ __all__ = [
"BOT_API_VERSION", "BOT_API_VERSION",

View file

@ -40,4 +40,4 @@ def test_build():
@skip_disabled @skip_disabled
def test_build_raw(): def test_build_raw():
assert os.system("python setup-raw.py bdist_dumb") == 0 # pragma: no cover assert os.system("python setup_raw.py bdist_dumb") == 0 # pragma: no cover