diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 3ae086301f..ee8b41b4c7 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -17,7 +17,7 @@ jobs: - name: Install dependencies run: | python -m pip install -U pip - pip install -U sphinx sphinxcontrib-trio aiohttp sphinxcontrib-websupport myst-parser + pip install ".[docs]" - name: Compile to html run: | cd docs diff --git a/.isort.cfg b/.isort.cfg deleted file mode 100644 index f238bf7ea1..0000000000 --- a/.isort.cfg +++ /dev/null @@ -1,2 +0,0 @@ -[settings] -profile = black diff --git a/.pylintrc b/.pylintrc deleted file mode 100644 index ccb1249f6b..0000000000 --- a/.pylintrc +++ /dev/null @@ -1,15 +0,0 @@ -[MASTER] -extension-pkg-whitelist=pydantic,ujson -py-version=3.8 - -[MESSAGES CONTROL] - -enable=bad-indentation,line-too-long -disable=protected-access,fixme - - -[FORMAT] - -indent-string=' ' - -max-line-length=120 diff --git a/MANIFEST.in b/MANIFEST.in index e623df089b..747a5007bf 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -3,3 +3,17 @@ include LICENSE include requirements.txt include discord/bin/*.dll include discord/py.typed + +prune .github +prune docs +prune examples +prune tests +exclude discord/bin/COPYING +exclude .flake8 +exclude .gitignore +exclude .pre-commit-config.yaml +exclude .prettierrc +exclude .readthedocs.yml +exclude CHANGELOG.md +exclude FUNDING.yml +exclude requirements-dev.txt diff --git a/discord/__init__.py b/discord/__init__.py index 62531cd5b4..8196c56e1c 100644 --- a/discord/__init__.py +++ b/discord/__init__.py @@ -12,12 +12,17 @@ __author__ = "Pycord Development" __license__ = "MIT" __copyright__ = "Copyright 2015-2021 Rapptz & Copyright 2021-present Pycord Development" -__version__ = "2.2.2" __path__ = __import__("pkgutil").extend_path(__path__, __name__) import logging -from typing import Literal, NamedTuple + +# We need __version__ to be imported first +# isort: off +from ._version import * + +# isort: on + from . import abc, opus, sinks, ui, utils from .activity import * @@ -66,17 +71,4 @@ from .welcome_screen import * from .widget import * - -class VersionInfo(NamedTuple): - major: int - minor: int - micro: int - releaselevel: Literal["alpha", "beta", "candidate", "final"] - serial: int - - -version_info: VersionInfo = VersionInfo( - major=2, minor=2, micro=2, releaselevel="final", serial=0 -) - logging.getLogger(__name__).addHandler(logging.NullHandler()) diff --git a/discord/_version.py b/discord/_version.py new file mode 100644 index 0000000000..8a1e28c691 --- /dev/null +++ b/discord/_version.py @@ -0,0 +1,115 @@ +""" +The MIT License (MIT) + +Copyright (c) 2015-2021 Rapptz +Copyright (c) 2021-present Pycord Development + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the "Software"), +to deal in the Software without restriction, including without limitation +the rights to use, copy, modify, merge, publish, distribute, sublicense, +and/or sell copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. +""" +from __future__ import annotations + +import re +import warnings +from datetime import date +from importlib.metadata import PackageNotFoundError, version + +__all__ = ("__version__", "VersionInfo", "version_info") + +from typing import Literal, NamedTuple + +from .utils import deprecated + +try: + __version__ = version("py-cord") +except PackageNotFoundError: + # Package is not installed + try: + from setuptools_scm import get_version # type: ignore[import] + + __version__ = get_version() + except ImportError: + # setuptools_scm is not installed + __version__ = "0.0.0" + warnings.warn( + "Package is not installed, and setuptools_scm is not installed. " + f"As a fallback, {__name__}.__version__ will be set to {__version__}", + RuntimeWarning, + stacklevel=2, + ) + + +class VersionInfo(NamedTuple): + major: int + minor: int + micro: int + release_level: Literal["alpha", "beta", "candidate", "final"] + serial: int + build: int | None = None + commit: str | None = None + date: date | None = None + + @property + @deprecated("release_level", "2.3") + def releaselevel(self) -> Literal["alpha", "beta", "candidate", "final"]: + return self.release_level + + +version_regex = re.compile( + r"^(?P\d+)(?:\.(?P\d+))?(?:\.(?P\d+))?" + r"(?:(?Prc|a|b)(?P\d+))?" + r"(?:\.dev(?P\d+))?" + r"(?:\+(?:(?:g(?P[a-fA-F0-9]{4,40})(?:\.d(?P\d{4}\d{2}\d{2})|))|d(?P\d{4}\d{2}\d{2})))?$" +) +version_match = version_regex.match(__version__) +if version_match is None: + raise RuntimeError(f"Invalid version string: {__version__}") +raw_info = version_match.groupdict() + +level_info: Literal["alpha", "beta", "candidate", "final"] + +if raw_info["level"] == "a": + level_info = "alpha" +elif raw_info["level"] == "b": + level_info = "beta" +elif raw_info["level"] == "rc": + level_info = "candidate" +elif raw_info["level"] is None: + level_info = "final" +else: + raise RuntimeError("Invalid release level") + +if (raw_date := raw_info["date"] or raw_info["date1"]) is not None: + date_info = date( + int(raw_date[:4]), + int(raw_date[4:6]), + int(raw_date[6:]), + ) +else: + date_info = None + +version_info: VersionInfo = VersionInfo( + major=raw_info["major"], + minor=raw_info["minor"], + micro=raw_info["patch"], + release_level=level_info, + serial=raw_info["serial"], + build=raw_info["build"], + commit=raw_info["commit"], + date=date_info, +) diff --git a/docs/conf.py b/docs/conf.py index 590e8eccf9..b9dc673694 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -12,8 +12,8 @@ # serve to show the default. import os -import re import sys +from importlib.metadata import version as get_version # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the @@ -90,20 +90,16 @@ # |version| and |release|, also used in various other places throughout the # built documents. # -# The short X.Y version. - -version = "" -with open("../discord/__init__.py") as f: - version = re.search( - r'^__version__\s*=\s*[\'"]([^\'"]*)[\'"]', f.read(), re.MULTILINE - ).group(1) # The full version, including alpha/beta/rc tags. -release = version +release = get_version("py-cord") + +# The short X.Y version. +version = ".".join(release.split(".")[:2]) # This assumes a tag is available for final releases branch = ( - "master" if "a" in version or "b" in version or "rc" in version else f"v{version}" + "master" if "a" in version or "b" in version or "rc" in version else f"v{release}" ) # The language for content autogenerated by Sphinx. Refer to documentation diff --git a/mypy.ini b/mypy.ini deleted file mode 100644 index c5189579f6..0000000000 --- a/mypy.ini +++ /dev/null @@ -1,8 +0,0 @@ -[mypy] -namespace_packages = True -install_types = True -strict = True -show_error_codes = True -;allow_untyped_decorators = True -;allow_untyped_calls = True -ignore_errors = True diff --git a/pyproject.toml b/pyproject.toml index 28256f5e78..75569297ec 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,2 +1,116 @@ +[build-system] +requires = [ + "setuptools==65.4.1", + "setuptools-scm==7.0.5" +] +build-backend = "setuptools.build_meta" + +[project] +name = "py-cord" +authors = [ + {name = "Pycord Development"} +] +description = "A Python wrapper for the Discord API" +readme = "README.rst" +requires-python = ">=3.8" +license = {text = "MIT"} +classifiers = [ + "Development Status :: 5 - Production/Stable", + "License :: OSI Approved :: MIT License", + "Intended Audience :: Developers", + "Natural Language :: English", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Topic :: Internet", + "Topic :: Software Development :: Libraries", + "Topic :: Software Development :: Libraries :: Python Modules", + "Topic :: Utilities", + "Typing :: Typed", +] +dynamic = ["version", "dependencies"] + +[project.urls] +Homepage = "https://pycord.dev" +Changelog = "https://github.com/Pycord-Development/pycord/blob/master/CHANGELOG.md" +Source = "https://github.com/Pycord-Development/pycord" +Documentation = "https://docs.pycord.dev" +Tracker = "https://github.com/Pycord-Development/pycord/issues" +Funding = "https://patreon.com/pycord" + +[project.optional-dependencies] +voice = [ + "PyNaCl>=1.3.0,<1.6", +] +docs = [ + "sphinx==4.5.0", + "sphinxcontrib_trio==1.1.2", + "sphinxcontrib-websupport", + "myst-parser", +] +speed = [ + "orjson>=3.5.4", + "aiodns>=1.1", + "Brotlipy", + "cchardet", +] + +[tool.setuptools] +packages = [ + "discord", + "discord.types", + "discord.sinks", + "discord.ui", + "discord.webhook", + "discord.commands", + "discord.ext.commands", + "discord.ext.tasks", + "discord.ext.pages", + "discord.ext.bridge", +] + +[tool.setuptools.dynamic] +dependencies = {file = "requirements.txt"} + +[tool.setuptools_scm] + [tool.black] target-version = ['py38', 'py39', 'py310', 'py311'] + +[tool.isort] +profile = "black" + +[tool.mypy] +namespace_packages = true +install_types = true +strict = true +show_error_codes = true +#allow_untyped_decorators = true +#allow_untyped_calls = true +ignore_errors = true + +[tool.pylint.main] +extension-pkg-whitelist = [ + "pydantic", + "ujson" +] +py-version = 3.8 + +[tool.pylint.messages_control] +enable = [ + "bad-indentation", + "line-too-long" +] +disable = [ + "protected-access", + "fixme" +] + +[tool.pylint.format] +indent-string = ' ' +max-line-length = 120 + +[tool.pytest.ini_options] +asyncio_mode = "auto" diff --git a/pytest.ini b/pytest.ini deleted file mode 100644 index 2f4c80e307..0000000000 --- a/pytest.ini +++ /dev/null @@ -1,2 +0,0 @@ -[pytest] -asyncio_mode = auto diff --git a/setup.py b/setup.py index e0320894a3..7f1a1763ca 100644 --- a/setup.py +++ b/setup.py @@ -1,126 +1,4 @@ -import re - from setuptools import setup -# Requirements -requirements = [] -with open("requirements.txt") as f: - requirements = f.read().splitlines() - -# Version Info -version = "" -with open("discord/__init__.py") as f: - - search = re.search( - r'^__version__\s*=\s*[\'"]([^\'"]*)[\'"]', f.read(), re.MULTILINE - ) - - if search is not None: - version = search.group(1) - - else: - raise RuntimeError("Could not grab version string") - -if not version: - raise RuntimeError("version is not set") - -if version.endswith(("a", "b", "rc")): - # append version identifier based on commit count - try: - import subprocess - - p = subprocess.Popen( - ["git", "rev-list", "--count", "HEAD"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - ) - out, err = p.communicate() - if out: - version += out.decode("utf-8").strip() - p = subprocess.Popen( - ["git", "rev-parse", "--short", "HEAD"], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - ) - out, err = p.communicate() - if out: - version += f"+g{out.decode('utf-8').strip()}" - except Exception: - pass - -# README -readme = "" -with open("README.rst") as f: - readme = f.read() - -# Extra Requirements -# Ex: pip install py-cord[voice] or [speed] -extras_require = { - "voice": ["PyNaCl>=1.3.0,<1.6"], - "docs": [ - "sphinx==4.5.0", - "sphinxcontrib_trio==1.1.2", - "sphinxcontrib-websupport", - "myst-parser", - ], - "speed": [ - "orjson>=3.5.4", - "aiodns>=1.1", - "Brotlipy", - "cchardet", - ], -} - -# Folders And Such Included -packages = [ - "discord", - "discord.types", - "discord.sinks", - "discord.ui", - "discord.webhook", - "discord.commands", - "discord.ext.commands", - "discord.ext.tasks", - "discord.ext.pages", - "discord.ext.bridge", -] - - -setup( - name="py-cord", - author="Pycord Development", - url="https://pycord.dev/github", - project_urls={ - "Changelog": "https://github.com/Pycord-Development/pycord/blob/master/CHANGELOG.md", - "Website": "https://pycord.dev", - "Documentation": "https://docs.pycord.dev/en/master/", - "Issue tracker": "https://github.com/Pycord-Development/pycord/issues", - }, - version=version, - packages=packages, - license="MIT", - description="A Python wrapper for the Discord API", - long_description=readme, - long_description_content_type="text/x-rst", - include_package_data=True, - install_requires=requirements, - extras_require=extras_require, - python_requires=">=3.8.0", - classifiers=[ - "Development Status :: 5 - Production/Stable", - "License :: OSI Approved :: MIT License", - "Intended Audience :: Developers", - "Natural Language :: English", - "Operating System :: OS Independent", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Topic :: Internet", - "Topic :: Software Development :: Libraries", - "Topic :: Software Development :: Libraries :: Python Modules", - "Topic :: Utilities", - "Typing :: Typed", - ], - test_suite="tests", # Test Folder For Workflows -) +if __name__ == "__main__": + setup()