mirror of
https://github.com/python-telegram-bot/python-telegram-bot.git
synced 2024-12-22 06:25:12 +01:00
Apply pre-commit
Checks More Widely (#4135)
This commit is contained in:
parent
9c263fbd1a
commit
26f943771b
17 changed files with 104 additions and 100 deletions
|
@ -10,7 +10,6 @@ repos:
|
|||
hooks:
|
||||
- id: ruff
|
||||
name: ruff
|
||||
files: ^(telegram|examples|tests)/.*\.py$
|
||||
additional_dependencies:
|
||||
- httpx~=0.27.0
|
||||
- tornado~=6.4
|
||||
|
@ -32,7 +31,7 @@ repos:
|
|||
rev: v3.0.3
|
||||
hooks:
|
||||
- id: pylint
|
||||
files: ^(telegram|examples)/.*\.py$
|
||||
files: ^(?!(tests|docs)).*\.py$
|
||||
additional_dependencies:
|
||||
- httpx~=0.27.0
|
||||
- tornado~=6.4
|
||||
|
@ -45,7 +44,7 @@ repos:
|
|||
hooks:
|
||||
- id: mypy
|
||||
name: mypy-ptb
|
||||
files: ^telegram/.*\.py$
|
||||
files: ^(?!(tests|examples|docs)).*\.py$
|
||||
additional_dependencies:
|
||||
- types-pytz
|
||||
- types-cryptography
|
||||
|
@ -71,7 +70,6 @@ repos:
|
|||
rev: v3.15.0
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
files: ^(telegram|examples|tests|docs)/.*\.py$
|
||||
args:
|
||||
- --py38-plus
|
||||
- repo: https://github.com/pycqa/isort
|
||||
|
|
|
@ -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
|
||||
$ cd python-telegram-bot
|
||||
$ python setup-raw.py install
|
||||
$ python setup_raw.py install
|
||||
|
||||
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
|
||||
------------------
|
||||
|
|
0
docs/__init__.py
Normal file
0
docs/__init__.py
Normal file
0
docs/auxil/__init__.py
Normal file
0
docs/auxil/__init__.py
Normal file
|
@ -64,7 +64,7 @@ class AdmonitionInserter:
|
|||
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
|
||||
for cls in (telegram.Bot, telegram.ext.ApplicationBuilder)
|
||||
}
|
||||
|
@ -159,7 +159,7 @@ class AdmonitionInserter:
|
|||
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
|
||||
# "telegram.StickerSet" because that's the way the classes are mentioned in
|
||||
# docstrings.
|
||||
|
@ -197,8 +197,8 @@ class AdmonitionInserter:
|
|||
"Error generating Sphinx 'Available in' admonition "
|
||||
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" 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
|
||||
# listed as attributes.
|
||||
|
@ -240,8 +240,8 @@ class AdmonitionInserter:
|
|||
"Error generating Sphinx 'Available in' admonition "
|
||||
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" 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")
|
||||
|
||||
|
@ -271,8 +271,8 @@ class AdmonitionInserter:
|
|||
raise NotImplementedError(
|
||||
"Error generating Sphinx 'Returned in' admonition "
|
||||
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")
|
||||
|
||||
|
@ -297,7 +297,7 @@ class AdmonitionInserter:
|
|||
|
||||
# inspect methods of all telegram classes for return statements that indicate
|
||||
# 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
|
||||
if cls is telegram.Bot:
|
||||
continue
|
||||
|
@ -344,8 +344,8 @@ class AdmonitionInserter:
|
|||
raise NotImplementedError(
|
||||
"Error generating Sphinx 'Use in' admonition "
|
||||
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")
|
||||
|
||||
|
@ -359,17 +359,19 @@ class AdmonitionInserter:
|
|||
If no key phrases are found, the admonition will be inserted at the very end.
|
||||
"""
|
||||
for idx, value in list(enumerate(lines)):
|
||||
if (
|
||||
value.startswith(".. seealso:")
|
||||
# The docstring contains heading "Examples:", but Sphinx will have it converted
|
||||
# to ".. admonition: Examples":
|
||||
or value.startswith(".. admonition:: Examples")
|
||||
or value.startswith(".. version")
|
||||
# The space after ":param" is important because docstring can contain ":paramref:"
|
||||
# in its plain text in the beginning of a line (e.g. ExtBot):
|
||||
or value.startswith(":param ")
|
||||
# some classes (like "Credentials") have no params, so insert before attrs:
|
||||
or value.startswith(".. attribute::")
|
||||
if value.startswith(
|
||||
(
|
||||
".. seealso:",
|
||||
# The docstring contains heading "Examples:", but Sphinx will have it converted
|
||||
# to ".. admonition: Examples":
|
||||
".. admonition:: Examples",
|
||||
".. version",
|
||||
# The space after ":param" is important because docstring can contain
|
||||
# ":paramref:" in its plain text in the beginning of a line (e.g. ExtBot):
|
||||
":param ",
|
||||
# some classes (like "Credentials") have no params, so insert before attrs:
|
||||
".. attribute::",
|
||||
)
|
||||
):
|
||||
return idx
|
||||
return len(lines) - 1
|
||||
|
@ -411,7 +413,7 @@ class AdmonitionInserter:
|
|||
# so its page needs no admonitions.
|
||||
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".
|
||||
admonition = f"""
|
||||
|
@ -419,11 +421,11 @@ class AdmonitionInserter:
|
|||
.. admonition:: {admonition_type.title().replace("_", " ")}
|
||||
:class: {admonition_type.replace("_", "-")}
|
||||
"""
|
||||
if len(attrs) > 1:
|
||||
for target_attr in attrs:
|
||||
if len(sorted_attrs) > 1:
|
||||
for target_attr in sorted_attrs:
|
||||
admonition += "\n * " + target_attr
|
||||
else:
|
||||
admonition += f"\n {attrs[0]}"
|
||||
admonition += f"\n {sorted_attrs[0]}"
|
||||
|
||||
admonition += "\n " # otherwise an unexpected unindent warning will be issued
|
||||
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.
|
||||
try:
|
||||
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
|
||||
if self.FORWARD_REF_SKIP_PATTERN.match(str(arg)):
|
||||
pass
|
||||
else:
|
||||
raise NotImplementedError(f"Could not process ForwardRef: {arg}")
|
||||
raise NotImplementedError(f"Could not process ForwardRef: {arg}") from exc
|
||||
else:
|
||||
yield cls
|
||||
|
||||
|
@ -587,6 +589,7 @@ class AdmonitionInserter:
|
|||
# If neither option works, this is not a PTB class.
|
||||
except (NameError, AttributeError):
|
||||
continue
|
||||
return None
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
# You should have received a copy of the GNU Lesser Public License
|
||||
# along with this program. If not, see [http://www.gnu.org/licenses/].
|
||||
import inspect
|
||||
from typing import List
|
||||
|
||||
keyword_args = [
|
||||
"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."""
|
||||
for idx, value in reversed(list(enumerate(lines))): # reversed since :returns: is at the end
|
||||
if value.startswith("Returns"):
|
||||
return idx
|
||||
else:
|
||||
return False
|
||||
return False
|
||||
|
||||
|
||||
def check_timeout_and_api_kwargs_presence(obj: object) -> int:
|
||||
|
|
|
@ -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
|
||||
"""
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
from typing import Dict, Tuple
|
||||
|
||||
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`
|
||||
# event handler in `sphinx_hooks.py`
|
||||
LINE_NUMBERS = {}
|
||||
LINE_NUMBERS: Dict[str, Tuple[Path, int, int]] = {}
|
||||
|
||||
|
||||
def _git_branch() -> str:
|
||||
|
@ -52,7 +54,7 @@ git_branch = _git_branch()
|
|||
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"""
|
||||
combined = ".".join((info["module"], info["fullname"]))
|
||||
# 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"])
|
||||
|
||||
if not line_info:
|
||||
return
|
||||
return None
|
||||
|
||||
file, start_line, end_line = line_info
|
||||
return f"{base_url}{git_branch}/{file}#L{start_line}-L{end_line}"
|
||||
|
|
|
@ -67,9 +67,9 @@ def autodoc_skip_member(app, what, name, obj, skip, options):
|
|||
return True
|
||||
break
|
||||
|
||||
if name == "filter" and obj.__module__ == "telegram.ext.filters":
|
||||
if not included_in_obj:
|
||||
return True # return True to exclude from docs.
|
||||
if name == "filter" and obj.__module__ == "telegram.ext.filters" and not included_in_obj:
|
||||
return True # return True to exclude from docs.
|
||||
return None
|
||||
|
||||
|
||||
def autodoc_process_docstring(
|
||||
|
@ -118,7 +118,7 @@ def autodoc_process_docstring(
|
|||
):
|
||||
effective_insert: list[str] = media_write_timeout_deprecation
|
||||
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:
|
||||
effective_insert = [to_insert]
|
||||
|
||||
|
@ -166,11 +166,11 @@ def autodoc_process_docstring(
|
|||
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."""
|
||||
for idx, base in enumerate(bases):
|
||||
for idx, raw_base in enumerate(bases):
|
||||
# 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
|
||||
if base.startswith("typing.AbstractAsyncContextManager"):
|
||||
|
|
|
@ -81,11 +81,12 @@ class TGConstXRefRole(PyXRefRole):
|
|||
):
|
||||
return repr(value), target
|
||||
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.",
|
||||
refnode.source,
|
||||
refnode.line,
|
||||
refnode.rawsource,
|
||||
CONSTANTS_ROLE,
|
||||
)
|
||||
return title, target
|
||||
except Exception as exc:
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import os
|
||||
import re
|
||||
import sys
|
||||
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.
|
||||
from sphinx.application import Sphinx
|
||||
|
||||
sys.path.insert(0, os.path.abspath("../.."))
|
||||
sys.path.insert(0, str(Path("../..").resolve().absolute()))
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
# 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.
|
||||
|
||||
# Not used but must be imported for the linkcode extension to find it
|
||||
from docs.auxil.link_code import linkcode_resolve
|
||||
from docs.auxil.sphinx_hooks import (
|
||||
from docs.auxil.link_code import linkcode_resolve # noqa: E402, F401
|
||||
from docs.auxil.sphinx_hooks import ( # noqa: E402
|
||||
autodoc_process_bases,
|
||||
autodoc_process_docstring,
|
||||
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):
|
||||
|
|
|
@ -26,6 +26,7 @@ select = ["E", "F", "I", "PL", "UP", "RUF", "PTH", "C4", "B", "PIE", "SIM", "RET
|
|||
[tool.ruff.lint.per-file-ignores]
|
||||
"tests/*.py" = ["B018"]
|
||||
"tests/**.py" = ["RUF012", "ASYNC101"]
|
||||
"docs/**.py" = ["INP001"]
|
||||
|
||||
# PYLINT:
|
||||
[tool.pylint."messages control"]
|
||||
|
|
|
@ -5,4 +5,4 @@ license_files = LICENSE, LICENSE.dual, LICENSE.lesser
|
|||
max-line-length = 99
|
||||
ignore = W503, W605
|
||||
extend-ignore = E203, E704
|
||||
exclude = setup.py, setup-raw.py docs/source/conf.py
|
||||
exclude = setup.py, setup_raw.py docs/source/conf.py
|
||||
|
|
86
setup.py
86
setup.py
|
@ -4,15 +4,16 @@ import subprocess
|
|||
import sys
|
||||
from collections import defaultdict
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List, Tuple
|
||||
|
||||
from setuptools import find_packages, setup
|
||||
|
||||
|
||||
def get_requirements():
|
||||
def get_requirements() -> List[str]:
|
||||
"""Build the requirements list for this project"""
|
||||
requirements_list = []
|
||||
|
||||
with Path("requirements.txt").open() as reqs:
|
||||
with Path("requirements.txt").open(encoding="utf-8") as reqs:
|
||||
for install in reqs:
|
||||
if install.startswith("#"):
|
||||
continue
|
||||
|
@ -21,7 +22,7 @@ def get_requirements():
|
|||
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"""
|
||||
reqs = get_requirements()
|
||||
|
||||
|
@ -34,68 +35,69 @@ def get_packages_requirements(raw=False):
|
|||
return packs, reqs
|
||||
|
||||
|
||||
def get_optional_requirements(raw=False):
|
||||
def get_optional_requirements(raw: bool = False) -> Dict[str, List[str]]:
|
||||
"""Build the optional dependencies"""
|
||||
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:
|
||||
line = line.strip()
|
||||
if not line or line.startswith("#"):
|
||||
effective_line = line.strip()
|
||||
if not effective_line or effective_line.startswith("#"):
|
||||
continue
|
||||
dependency, names = line.split("#")
|
||||
dependency, names = effective_line.split("#")
|
||||
dependency = dependency.strip()
|
||||
for name in names.split(","):
|
||||
name = name.strip()
|
||||
if name.endswith("!ext"):
|
||||
effective_name = name.strip()
|
||||
if effective_name.endswith("!ext"):
|
||||
if raw:
|
||||
continue
|
||||
else:
|
||||
name = name[:-4]
|
||||
requirements["ext"].append(dependency)
|
||||
requirements[name].append(dependency)
|
||||
effective_name = effective_name[:-4]
|
||||
requirements["ext"].append(dependency)
|
||||
requirements[effective_name].append(dependency)
|
||||
requirements["all"].append(dependency)
|
||||
|
||||
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"""
|
||||
packages, requirements = get_packages_requirements(raw=raw)
|
||||
|
||||
raw_ext = "-raw" if raw else ""
|
||||
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]
|
||||
exec(first_part)
|
||||
exec(first_part) # pylint: disable=exec-used
|
||||
|
||||
kwargs = dict(
|
||||
script_name=f"setup{raw_ext}.py",
|
||||
name=f"python-telegram-bot{raw_ext}",
|
||||
version=locals()["__version__"],
|
||||
author="Leandro Toledo",
|
||||
author_email="devs@python-telegram-bot.org",
|
||||
license="LGPLv3",
|
||||
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
|
||||
project_urls={
|
||||
return {
|
||||
"script_name": f"setup{raw_ext}.py",
|
||||
"name": f"python-telegram-bot{raw_ext}",
|
||||
"version": locals()["__version__"],
|
||||
"author": "Leandro Toledo",
|
||||
"author_email": "devs@python-telegram-bot.org",
|
||||
"license": "LGPLv3",
|
||||
"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
|
||||
"project_urls": {
|
||||
"Documentation": "https://docs.python-telegram-bot.org",
|
||||
"Bug Tracker": "https://github.com/python-telegram-bot/python-telegram-bot/issues",
|
||||
"Source Code": "https://github.com/python-telegram-bot/python-telegram-bot",
|
||||
"News": "https://t.me/pythontelegrambotchannel",
|
||||
"Changelog": "https://docs.python-telegram-bot.org/en/stable/changelog.html",
|
||||
},
|
||||
download_url=f"https://pypi.org/project/python-telegram-bot{raw_ext}/",
|
||||
keywords="python telegram bot api wrapper",
|
||||
description="We have made you a wrapper you can't refuse",
|
||||
long_description=readme.read_text(),
|
||||
long_description_content_type="text/x-rst",
|
||||
packages=packages,
|
||||
install_requires=requirements,
|
||||
extras_require=get_optional_requirements(raw=raw),
|
||||
include_package_data=True,
|
||||
classifiers=[
|
||||
"download_url": f"https://pypi.org/project/python-telegram-bot{raw_ext}/",
|
||||
"keywords": "python telegram bot api wrapper",
|
||||
"description": "We have made you a wrapper you can't refuse",
|
||||
"long_description": readme.read_text(encoding="utf-8"),
|
||||
"long_description_content_type": "text/x-rst",
|
||||
"packages": packages,
|
||||
"install_requires": requirements,
|
||||
"extras_require": get_optional_requirements(raw=raw),
|
||||
"include_package_data": True,
|
||||
"classifiers": [
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
"Intended Audience :: Developers",
|
||||
"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.12",
|
||||
],
|
||||
python_requires=">=3.8",
|
||||
)
|
||||
|
||||
return kwargs
|
||||
"python_requires": ">=3.8",
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
def main() -> None:
|
||||
# If we're building, build ptb-raw as well
|
||||
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:])
|
||||
subprocess.run(args, check=True, capture_output=True)
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ class StringEnum(str, _enum.Enum):
|
|||
|
||||
|
||||
# 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)``
|
||||
gives ``EnumName.MEMBER_NAME``.
|
||||
"""
|
||||
|
|
|
@ -29,7 +29,7 @@ those classes.
|
|||
* Most of the constants in this module are grouped into enums.
|
||||
"""
|
||||
# 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__ = [
|
||||
"BOT_API_VERSION",
|
||||
|
|
|
@ -40,4 +40,4 @@ def test_build():
|
|||
|
||||
@skip_disabled
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue