Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,26 @@ universal = true
line-length = 125

[tool.ruff.lint]
select = ["E", "W", "F"]
select = ["E", "W", "F", "D"]
ignore = [
# missing-docstring: do not add docstrings where none exist
"D100",
"D101",
"D102",
"D103",
"D104",
"D105",
"D106",
"D107",
# undocumented-param: 51/54 cases are just **others/**kwargs boilerplate in Block Kit models
"D417",
]
Comment on lines +63 to +75

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👁️‍🗨️ question: Do we have a goal to remove these over time?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yess the goal is to remove them but it would introduce to many breaking changes


[tool.ruff.lint.pydocstyle]
convention = "google"

[tool.ruff.format]
docstring-code-format = true

[tool.pytest.ini_options]
testpaths = ["tests"]
Expand Down
8 changes: 4 additions & 4 deletions slack/signature/verifier.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def now() -> float:

class SignatureVerifier:
def __init__(self, signing_secret: str, clock: Clock = Clock()):
"""Slack request signature verifier
"""Slack request signature verifier.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🌟 praise: I'm so glad this can be enforced with linting.


Slack signs its requests using a secret that's unique to your app.
With the help of signing secrets, your app can more confidently verify
Expand All @@ -27,7 +27,7 @@ def is_valid_request(
body: Union[str, bytes],
headers: Dict[str, str],
) -> bool:
"""Verifies if the given signature is valid"""
"""Verifies if the given signature is valid."""
if headers is None:
return False
normalized_headers = {k.lower(): v for k, v in headers.items()}
Expand All @@ -43,7 +43,7 @@ def is_valid(
timestamp: str,
signature: str,
) -> bool:
"""Verifies if the given signature is valid"""
"""Verifies if the given signature is valid."""
if timestamp is None or signature is None:
return False

Expand All @@ -56,7 +56,7 @@ def is_valid(
return hmac.compare_digest(calculated_signature, signature)

def generate_signature(self, *, timestamp: str, body: Union[str, bytes]) -> Optional[str]:
"""Generates a signature"""
"""Generates a signature."""
if timestamp is None:
return None
if body is None:
Expand Down
3 changes: 2 additions & 1 deletion slack/web/async_base_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ async def api_call( # skipcq: PYL-R1710
SlackRequestError: Json data can only be submitted as
POST requests.
"""

api_url = _get_url(self.base_url, api_method)
headers = headers or {}
headers.update(self.headers)
Expand Down Expand Up @@ -128,6 +127,7 @@ async def _send(self, http_verb: str, api_url: str, req_args: dict) -> AsyncSlac
'channel': '#random'
}
}

Returns:
The response parsed into a AsyncSlackResponse object.
"""
Expand All @@ -152,6 +152,7 @@ async def _send(self, http_verb: str, api_url: str, req_args: dict) -> AsyncSlac

async def _request(self, *, http_verb, api_url, req_args) -> Dict[str, any]:
"""Submit the HTTP request with the running session or a new session.

Returns:
A dictionary of the response data.
"""
Expand Down
2 changes: 2 additions & 0 deletions slack/web/async_internal_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ def _get_headers(
request_specific_headers: Optional[dict],
) -> Dict[str, str]:
"""Constructs the headers need for a request.

Args:
has_json (bool): Whether or not the request has json.
has_files (bool): Whether or not the request has files.
Expand Down Expand Up @@ -163,6 +164,7 @@ async def _request_with_session(
req_args: dict,
) -> Dict[str, any]:
"""Submit the HTTP request with the running session or a new session.

Returns:
A dictionary of the response data.
"""
Expand Down
11 changes: 6 additions & 5 deletions slack/web/async_slack_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,17 @@ class AsyncSlackResponse:
import os
import slack

client = slack.AsyncWebClient(token=os.environ['SLACK_API_TOKEN'])
client = slack.AsyncWebClient(token=os.environ["SLACK_API_TOKEN"])

response1 = await client.auth_revoke(test='true')
assert not response1['revoked']
response1 = await client.auth_revoke(test="true")
assert not response1["revoked"]

response2 = await client.auth_test()
assert response2.get('ok', False)
assert response2.get("ok", False)

users = []
async for page in await client.users_list(limit=2):
users = users + page['members']
users = users + page["members"]
```

Note:
Expand Down Expand Up @@ -100,6 +100,7 @@ def __getitem__(self, key):

def __aiter__(self):
"""Enables the ability to iterate over the response.

It's required async-for the iterator protocol.

Note:
Expand Down
11 changes: 6 additions & 5 deletions slack/web/base_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ def api_call( # skipcq: PYL-R1710
SlackRequestError: Json data can only be submitted as
POST requests.
"""

api_url = _get_url(self.base_url, api_method)
headers = headers or {}
headers.update(self.headers)
Expand Down Expand Up @@ -165,6 +164,7 @@ async def _send(self, http_verb: str, api_url: str, req_args: dict) -> SlackResp
'channel': '#random'
}
}

Returns:
The response parsed into a SlackResponse object.
"""
Expand All @@ -190,6 +190,7 @@ async def _send(self, http_verb: str, api_url: str, req_args: dict) -> SlackResp

async def _request(self, *, http_verb, api_url, req_args) -> Dict[str, any]:
"""Submit the HTTP request with the running session or a new session.

Returns:
A dictionary of the response data.
"""
Expand Down Expand Up @@ -239,7 +240,7 @@ def _sync_send(self, api_url, req_args) -> SlackResponse:
)

def _request_for_pagination(self, api_url, req_args) -> Dict[str, any]:
"""This method is supposed to be used only for SlackResponse pagination
"""This method is supposed to be used only for SlackResponse pagination.

You can paginate using Python's for iterator as below:

Expand Down Expand Up @@ -463,9 +464,9 @@ def _build_urllib_request_headers(

@staticmethod
def validate_slack_signature(*, signing_secret: str, data: str, timestamp: str, signature: str) -> bool:
"""
Slack creates a unique string for your app and shares it with you. Verify
requests from Slack with confidence by verifying signatures using your
"""Slack creates a unique string for your app and shares it with you.

Verify requests from Slack with confidence by verifying signatures using your
signing secret.

On each HTTP request that Slack sends, we add an X-Slack-Signature HTTP
Expand Down
18 changes: 6 additions & 12 deletions slack/web/classes/interactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@


class IDNamePair(NamedTuple):
"""Simple type used to help with unpacking event data"""
"""Simple type used to help with unpacking event data."""

id: str
name: str
Expand Down Expand Up @@ -33,8 +33,7 @@ class MessageInteractiveEvent(InteractiveEvent):
message: dict

def __init__(self, event: dict):
"""
Convenience class to parse an interactive message payload from the events API
"""Convenience class to parse an interactive message payload from the events API.

Args:
event: the raw event dictionary
Expand Down Expand Up @@ -64,8 +63,7 @@ class DialogInteractiveEvent(InteractiveEvent):
state: dict

def __init__(self, event: dict):
"""
Convenience class to parse a dialog interaction payload from the events API
"""Convenience class to parse a dialog interaction payload from the events API.

Args:
event: the raw event dictionary
Expand All @@ -83,9 +81,7 @@ def __init__(self, event: dict):
self.state = {}

def require_any(self, requirements: List[str]) -> dict:
"""
Convenience method to construct the 'errors' response to send directly back to
the invoking HTTP request
"""Convenience method to construct the 'errors' response to send directly back to the invoking HTTP request.

Args:
requirements: List of required dialog components, by name
Expand All @@ -106,8 +102,7 @@ class SlashCommandInteractiveEvent(InteractiveEvent):
text: str

def __init__(self, event: dict):
"""
Convenience class to parse a slash command payload from the events API
"""Convenience class to parse a slash command payload from the events API.

Args:
event: the raw event dictionary
Expand All @@ -122,8 +117,7 @@ def __init__(self, event: dict):

@staticmethod
def create_reply(message, ephemeral=False) -> dict:
"""
Create a reply suitable to send directly back to the invoking HTTP request
"""Create a reply suitable to send directly back to the invoking HTTP request.

Args:
message: Text to send
Expand Down
3 changes: 1 addition & 2 deletions slack/web/deprecation.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@


def show_2020_01_deprecation(method_name: str):
"""Prints a warning if the given method is deprecated"""

"""Prints a warning if the given method is deprecated."""
skip_deprecation = os.environ.get("SLACKCLIENT_SKIP_DEPRECATION") # for unit tests etc.
if skip_deprecation:
return
Expand Down
3 changes: 1 addition & 2 deletions slack/web/internal_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ def _update_call_participants(kwargs, users: Union[str, List[Dict[str, str]]]) -


def _next_cursor_is_present(data) -> bool:
"""Determine if the response contains 'next_cursor'
and 'next_cursor' is not empty.
"""Determine if the response contains 'next_cursor' and 'next_cursor' is not empty.

Returns:
A boolean value.
Expand Down
4 changes: 2 additions & 2 deletions slack_sdk/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
* The SDK website: https://docs.slack.dev/tools/python-slack-sdk
"""* The SDK website: https://docs.slack.dev/tools/python-slack-sdk.

* PyPI package: https://pypi.org/project/slack-sdk/

Here is the list of key modules in this SDK:
Expand Down
2 changes: 1 addition & 1 deletion slack_sdk/aiohttp_version_checker.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Internal module for checking aiohttp compatibility of async modules"""
"""Internal module for checking aiohttp compatibility of async modules."""

import logging
from typing import Callable
Expand Down
16 changes: 9 additions & 7 deletions slack_sdk/audit_logs/v1/async_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ def __init__(
logger: Optional[logging.Logger] = None,
retry_handlers: Optional[List[AsyncRetryHandler]] = None,
):
"""API client for Audit Logs API
"""API client for Audit Logs API.

See https://docs.slack.dev/admins/audit-logs-api/ for more details

Args:
Expand Down Expand Up @@ -100,9 +101,9 @@ async def schemas(
query_params: Optional[Dict[str, Any]] = None,
headers: Optional[Dict[str, str]] = None,
) -> AuditLogsResponse:
"""Returns information about the kind of objects which the Audit Logs API
returns as a list of all objects and a short description.
Authentication not required.
"""Returns information about the kind of objects the Audit Logs API returns.

Returned as a list of all objects, each with a short description. Authentication not required.

Args:
query_params: Set any values if you want to add query params
Expand All @@ -122,9 +123,9 @@ async def actions(
query_params: Optional[Dict[str, Any]] = None,
headers: Optional[Dict[str, str]] = None,
) -> AuditLogsResponse:
"""Returns information about the kind of actions that the Audit Logs API
returns as a list of all actions and a short description of each.
Authentication not required.
"""Returns information about the kind of actions the Audit Logs API returns.

Returned as a list of all actions, each with a short description. Authentication not required.

Args:
query_params: Set any values if you want to add query params
Expand Down Expand Up @@ -153,6 +154,7 @@ async def logs(
headers: Optional[Dict[str, str]] = None,
) -> AuditLogsResponse:
"""This is the primary endpoint for retrieving actual audit events from your organization.

It will return a list of actions that have occurred on the installed workspace or grid organization.
Authentication required.

Expand Down
16 changes: 9 additions & 7 deletions slack_sdk/audit_logs/v1/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ def __init__(
logger: Optional[logging.Logger] = None,
retry_handlers: Optional[List[RetryHandler]] = None,
):
"""API client for Audit Logs API
"""API client for Audit Logs API.

See https://docs.slack.dev/admins/audit-logs-api/ for more details

Args:
Expand Down Expand Up @@ -89,9 +90,9 @@ def schemas(
query_params: Optional[Dict[str, Any]] = None,
headers: Optional[Dict[str, str]] = None,
) -> AuditLogsResponse:
"""Returns information about the kind of objects which the Audit Logs API
returns as a list of all objects and a short description.
Authentication not required.
"""Returns information about the kind of objects the Audit Logs API returns.

Returned as a list of all objects, each with a short description. Authentication not required.

Args:
query_params: Set any values if you want to add query params
Expand All @@ -111,9 +112,9 @@ def actions(
query_params: Optional[Dict[str, Any]] = None,
headers: Optional[Dict[str, str]] = None,
) -> AuditLogsResponse:
"""Returns information about the kind of actions that the Audit Logs API
returns as a list of all actions and a short description of each.
Authentication not required.
"""Returns information about the kind of actions the Audit Logs API returns.

Returned as a list of all actions, each with a short description. Authentication not required.

Args:
query_params: Set any values if you want to add query params
Expand Down Expand Up @@ -142,6 +143,7 @@ def logs(
headers: Optional[Dict[str, str]] = None,
) -> AuditLogsResponse:
"""This is the primary endpoint for retrieving actual audit events from your organization.

It will return a list of actions that have occurred on the installed workspace or grid organization.
Authentication required.

Expand Down
Loading
Loading