diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index bacc54b49..bb88d11fb 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -36,8 +36,8 @@ jobs: - name: Install dependencies run: | pip install -U pip wheel - pip install -e ".[testing]" - pip install -e ".[optional]" + pip install -r requirements/testing.txt + pip install -r requirements/optional.txt - name: Run validation (black/flake8/pytest) run: | python setup.py validate diff --git a/.github/workflows/pytype.yml b/.github/workflows/pytype.yml index ada1b1b48..d5782e111 100644 --- a/.github/workflows/pytype.yml +++ b/.github/workflows/pytype.yml @@ -21,8 +21,8 @@ jobs: - name: Install dependencies run: | pip install -U pip - pip install -e ".[testing]" - pip install -e ".[optional]" + pip install -r requirements/testing.txt + pip install -r requirements/optional.txt # As pytype can change its behavior in newer versions, we manually upgrade it # 2023.9.11 fails due to errors that only happen on GH Actions pip install "pytype==2023.5.24" diff --git a/pyproject.toml b/pyproject.toml index 0cda914cd..1976da1ae 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,4 +1,69 @@ -# black project prefers pyproject.toml -# that's why we have this file in addition to other setting files +[build-system] +requires = ["setuptools", "pytest-runner"] +build-backend = "setuptools.build_meta" + +[project] +name = "slack_sdk" +dynamic = ["version", "readme", "authors"] +description = "The Slack API Platform SDK for Python" +license = { text = "MIT" } +requires-python = ">=3.6" +keywords = [ + "slack", + "slack-api", + "web-api", + "slack-rtm", + "websocket", + "chat", + "chatbot", + "chatops", +] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Topic :: Communications :: Chat", + "Topic :: System :: Networking", + "Topic :: Office/Business", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: PyPy", +] + + +[project.urls] +Documentation = "https://slack.dev/python-slack-sdk/" + +[tool.setuptools.packages.find] +include = ["slack*", "slack_sdk*"] + +[tool.setuptools.dynamic] +version = { attr = "slack_sdk.version.__version__" } +readme = { file = ["README.md"], content-type = "text/markdown" } + +[tool.distutils.bdist_wheel] +universal = true + [tool.black] -line-length = 125 \ No newline at end of file +line-length = 125 + +[tool.pytest.ini_options] +testpaths = ["tests"] +log_file = "logs/pytest.log" +log_file_level = "DEBUG" +log_format = "%(asctime)s %(levelname)s %(message)s" +log_date_format = "%Y-%m-%d %H:%M:%S" +filterwarnings = [ + "ignore:\"@coroutine\" decorator is deprecated since Python 3.8, use \"async def\" instead:DeprecationWarning", + "ignore:The loop argument is deprecated since Python 3.8, and scheduled for removal in Python 3.10.:DeprecationWarning", + "ignore:slack.* package is deprecated. Please use slack_sdk.* package instead.*:UserWarning", +] +asyncio_mode = "auto" diff --git a/pytest.ini b/pytest.ini deleted file mode 100644 index 7e88e4b78..000000000 --- a/pytest.ini +++ /dev/null @@ -1,10 +0,0 @@ -[pytest] -log_file = logs/pytest.log -log_file_level = DEBUG -log_format = %(asctime)s %(levelname)s %(message)s -log_date_format = %Y-%m-%d %H:%M:%S -filterwarnings = - ignore:"@coroutine" decorator is deprecated since Python 3.8, use "async def" instead:DeprecationWarning - ignore:The loop argument is deprecated since Python 3.8, and scheduled for removal in Python 3.10.:DeprecationWarning - ignore:slack.* package is deprecated. Please use slack_sdk.* package instead.*:UserWarning -asyncio_mode = auto diff --git a/requirements/optional.txt b/requirements/optional.txt new file mode 100644 index 000000000..0f1d6cd58 --- /dev/null +++ b/requirements/optional.txt @@ -0,0 +1,17 @@ +# pip install -r requirements/optional.txt +# async modules depend on aiohttp +aiodns>1.0 +# We recommend using 3.7.1+ for RTMClient +# https://github.com/slackapi/python-slack-sdk/issues/912 +aiohttp>=3.7.3,<4 +# used only under slack_sdk/*_store +boto3<=2 +# InstallationStore/OAuthStateStore +# Since v3.20, we no longer support SQLAlchemy 1.3 or older. +# If you need to use a legacy version, please add our v3.19.5 code to your project. +SQLAlchemy>=1.4,<3 +# Socket Mode +# websockets 9 is not compatible with Python 3.10 +websockets>=9.1,<10; python_version=="3.6" +websockets>=10,<11; python_version>"3.6" +websocket-client>=1,<2 diff --git a/requirements/testing.txt b/requirements/testing.txt new file mode 100644 index 000000000..06555a553 --- /dev/null +++ b/requirements/testing.txt @@ -0,0 +1,21 @@ +# pip install -r requirements/testing.txt +pytest>=7.0.1,<8 +pytest-asyncio<1 # for async +Flask-Sockets>=0.2,<1 +Flask>=1,<2 # TODO: Flask-Sockets is not yet compatible with Flask 2.x +Werkzeug<2 # TODO: Flask-Sockets is not yet compatible with Flask 2.x +itsdangerous==1.1.0 # TODO: Flask-Sockets is not yet compatible with Flask 2.x +Jinja2==3.0.3 # https://github.com/pallets/flask/issues/4494 +pytest-cov>=2,<3 +# while flake8 5.x have issues with Python 3.12, flake8 6.x requires Python >= 3.8.1, +# so 5.x should be kept in order to stay compatible with Python 3.6/3.7 +flake8>=5.0.4,<7 +# Don't change this version without running CI builds; +# The latest version may not be available for older Python runtime +black>=22.8.0; python_version=="3.6" +black==22.10.0; python_version>"3.6" +click==8.0.4 # black is affected by https://github.com/pallets/click/issues/2225 +psutil>=5,<6 +# used only under slack_sdk/*_store +boto3<=2 +moto>=3,<4 # For AWS tests diff --git a/scripts/build_pypi_package.sh b/scripts/build_pypi_package.sh new file mode 100755 index 000000000..e4acb96bb --- /dev/null +++ b/scripts/build_pypi_package.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +script_dir=`dirname $0` +cd ${script_dir}/.. +rm -rf ./slack_sdk.egg-info + +pip install -U pip && \ + pip install twine build && \ + rm -rf dist/ build/ slack_sdk.egg-info/ && \ + python -m build --sdist --wheel && \ + twine check dist/* diff --git a/scripts/deploy_to_prod_pypi_org.sh b/scripts/deploy_to_prod_pypi_org.sh index 4b15fef2c..01863545c 100755 --- a/scripts/deploy_to_prod_pypi_org.sh +++ b/scripts/deploy_to_prod_pypi_org.sh @@ -1,3 +1,12 @@ #!/bin/bash -python setup.py upload +script_dir=`dirname $0` +cd ${script_dir}/.. +rm -rf ./slack_sdk.egg-info + +pip install -U pip && \ + pip install twine build && \ + rm -rf dist/ build/ slack_sdk.egg-info/ && \ + python -m build --sdist --wheel && \ + twine check dist/* && \ + twine upload dist/* diff --git a/scripts/deploy_to_test_pypi_org.sh b/scripts/deploy_to_test_pypi_org.sh new file mode 100755 index 000000000..01f6a9818 --- /dev/null +++ b/scripts/deploy_to_test_pypi_org.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +script_dir=`dirname $0` +cd ${script_dir}/.. +rm -rf ./slack_sdk.egg-info + +pip install -U pip && \ + pip install twine build && \ + rm -rf dist/ build/ slack_sdk.egg-info/ && \ + python -m build --sdist --wheel && \ + twine check dist/* && \ + twine upload --repository testpypi dist/* diff --git a/scripts/run_integration_tests.sh b/scripts/run_integration_tests.sh index ee12d155f..c67a4a086 100755 --- a/scripts/run_integration_tests.sh +++ b/scripts/run_integration_tests.sh @@ -8,7 +8,9 @@ cd ${script_dir}/.. test_target="$1" python_version=`python --version | awk '{print $2}'` -pip install -e . +pip install -U pip && \ + pip install -r requirements/testing.txt && \ + pip install -r requirements/optional.txt && \ if [[ $test_target != "" ]] then diff --git a/scripts/run_unit_tests.sh b/scripts/run_unit_tests.sh index 80d4119d0..b9090c019 100755 --- a/scripts/run_unit_tests.sh +++ b/scripts/run_unit_tests.sh @@ -8,7 +8,9 @@ cd ${script_dir}/.. test_target="$1" python_version=`python --version | awk '{print $2}'` -pip install -e . +pip install -U pip && \ + pip install -r requirements/testing.txt && \ + pip install -r requirements/optional.txt && \ if [[ $test_target != "" ]] then diff --git a/scripts/run_validation.sh b/scripts/run_validation.sh index 8e11f0f62..cca0dd8eb 100755 --- a/scripts/run_validation.sh +++ b/scripts/run_validation.sh @@ -4,8 +4,8 @@ script_dir=`dirname $0` cd ${script_dir}/.. pip install -U pip && \ - pip install -e ".[testing]" && \ - pip install -e ".[optional]" && \ + pip install -r requirements/testing.txt && \ + pip install -r requirements/optional.txt && \ black slack_sdk/ slack/ tests/ integration_tests/ && \ python setup.py codegen && \ python setup.py validate diff --git a/scripts/uninstall_all.sh b/scripts/uninstall_all.sh new file mode 100755 index 000000000..1ce28826e --- /dev/null +++ b/scripts/uninstall_all.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +pip uninstall -y slack-sdk && \ + pip freeze | grep -v "^-e" | xargs pip uninstall -y diff --git a/setup.cfg b/setup.cfg index b7e478982..384126b63 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,2 +1,5 @@ -[aliases] -test=pytest +; Legacy package configuration, prefer pyproject.toml over setup.cfg or setup.py +[metadata] +url=https://github.com/slackapi/python-slack-sdk +author=Slack Technologies, LLC +author_email=opensource@slack.com diff --git a/setup.py b/setup.py index fd391b1b2..6be1405b9 100644 --- a/setup.py +++ b/setup.py @@ -1,52 +1,22 @@ # -*- coding: utf-8 -*- -import codecs import os import subprocess import sys -from shutil import rmtree -from setuptools import setup, find_packages, Command +from setuptools import setup, Command + +################################################################################### +# Legacy package configuration, prefer pyproject.toml over setup.cfg or setup.py # +################################################################################### here = os.path.abspath(os.path.dirname(__file__)) -__version__ = None -exec(open(f"{here}/slack_sdk/version.py").read()) - -long_description = "" -with codecs.open(os.path.join(here, "README.md"), encoding="utf-8") as readme: - long_description = readme.read() - -validate_dependencies = [ - "pytest>=7.0.1,<8", - "pytest-asyncio<1", # for async - "Flask-Sockets>=0.2,<1", - "Flask>=1,<2", # TODO: Flask-Sockets is not yet compatible with Flask 2.x - "Werkzeug<2", # TODO: Flask-Sockets is not yet compatible with Flask 2.x - "itsdangerous==1.1.0", # TODO: Flask-Sockets is not yet compatible with Flask 2.x - "Jinja2==3.0.3", # https://github.com/pallets/flask/issues/4494 - "pytest-cov>=2,<3", - # while flake8 5.x have issues with Python 3.12, flake8 6.x requires Python >= 3.8.1, - # so 5.x should be kept in order to stay compatible with Python 3.6/3.7 - "flake8>=5.0.4,<7", - # Don't change this version without running CI builds; - # The latest version may not be available for older Python runtime - "black==22.8.0", - "click==8.0.4", # black is affected by https://github.com/pallets/click/issues/2225 - "psutil>=5,<6", - # used only under slack_sdk/*_store - "boto3<=2", - "moto>=3,<4", # For AWS tests -] codegen_dependencies = [ # Don't change this version without running CI builds; # The latest version may not be available for older Python runtime "black==22.10.0", ] -needs_pytest = {"pytest", "test", "ptr"}.intersection(sys.argv) -pytest_runner = ["pytest-runner"] if needs_pytest else [] - - class BaseCommand(Command): user_options = [] @@ -69,37 +39,6 @@ def _run(self, s, command): sys.exit(error.returncode) -class UploadCommand(BaseCommand): - """Support setup.py upload. Thanks @kennethreitz!""" - - description = "Build and publish the package." - - def run(self): - self._run( - "Installing upload dependencies ...", - [sys.executable, "-m", "pip", "install", "wheel"], - ) - try: - self.status("Removing previous builds ...") - rmtree(os.path.join(here, "dist")) - rmtree(os.path.join(here, "build")) - except OSError: - pass - - self._run( - "Building Source and Wheel (universal) distribution ...", - [sys.executable, "setup.py", "sdist", "bdist_wheel", "--universal"], - ) - self._run( - "Installing Twine dependency ...", - [sys.executable, "-m", "pip", "install", "twine"], - ) - self._run( - "Uploading the package to PyPI via Twine ...", - [sys.executable, "-m", "twine", "upload", "dist/*"], - ) - - class CodegenCommand(BaseCommand): def run(self): self._run( @@ -212,7 +151,7 @@ def initialize_options(self): def run(self): self._run( "Installing test dependencies ...", - [sys.executable, "-m", "pip", "install"] + validate_dependencies, + [sys.executable, "-m", "pip", "install", "-r", "requirements/testing.txt"], ) self._run("Running black for legacy packages ...", [sys.executable, "-m", "black", f"{here}/slack"]) @@ -285,81 +224,7 @@ def run(self): setup( - name="slack_sdk", - version=__version__, - description="The Slack API Platform SDK for Python", - long_description=long_description, - long_description_content_type="text/markdown", - url="https://github.com/slackapi/python-slack-sdk", - author="Slack Technologies, LLC", - author_email="opensource@slack.com", - python_requires=">=3.6.0", - include_package_data=True, - license="MIT", - classifiers=[ - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Developers", - "Topic :: Communications :: Chat", - "Topic :: System :: Networking", - "Topic :: Office/Business", - "License :: OSI Approved :: MIT License", - "Programming Language :: Python", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: Implementation :: CPython", - "Programming Language :: Python :: Implementation :: PyPy", - ], - keywords="slack slack-api web-api slack-rtm websocket chat chatbot chatops", - packages=find_packages( - exclude=[ - "docs", - "docs-src", - "docs-v2", - "docs-src-v2", - "docs-v3", - "docs-src-v3", - "integration_tests", - "integration_tests_legacy", - "tests", - "tests.*", - "tutorial", - ] - ), - install_requires=[], - extras_require={ - # pip install -e ".[testing]" - "testing": validate_dependencies, - # pip install -e ".[optional]" - "optional": [ - # async modules depend on aiohttp - "aiodns>1.0", - # We recommend using 3.7.1+ for RTMClient - # https://github.com/slackapi/python-slack-sdk/issues/912 - "aiohttp>=3.7.3,<4", - # used only under slack_sdk/*_store - "boto3<=2", - # InstallationStore/OAuthStateStore - # Since v3.20, we no longer support SQLAlchemy 1.3 or older. - # If you need to use a legacy version, please add our v3.19.5 code to your project. - "SQLAlchemy>=1.4,<3", - # Socket Mode - # websockets 9 is not compatible with Python 3.10 - "websockets>=10,<11" if sys.version_info.minor > 6 else "websockets>=9.1,<10", - "websocket-client>=1,<2", - ], - }, - setup_requires=pytest_runner, - test_suite="tests", - tests_require=validate_dependencies, cmdclass={ - "upload": UploadCommand, "codegen": CodegenCommand, "validate": ValidateCommand, "unit_tests": UnitTestsCommand,