Skip to content

Commit 678a040

Browse files
committed
Merge branch 'main' into release/2.3.0
2 parents 7d862ad + 44e791f commit 678a040

File tree

120 files changed

+586
-447
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

120 files changed

+586
-447
lines changed

.pre-commit-config.yaml

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,29 +5,29 @@ repos:
55
rev: v0.4.3
66
hooks:
77
- id: ruff
8-
args: [ --fix, --exit-non-zero-on-fix, --show-fixes ]
8+
args: [format, --diff]
99
- id: ruff-format
1010

1111
- repo: https://github.com/pre-commit/pre-commit-hooks
1212
rev: v4.4.0
1313
hooks:
14-
- id: end-of-file-fixer
15-
exclude_types: ["json"]
16-
- id: trailing-whitespace
17-
exclude_types: ["json"]
14+
- id: end-of-file-fixer
15+
exclude_types: ["json"]
16+
- id: trailing-whitespace
17+
exclude_types: ["json"]
1818

1919
- repo: local
2020
hooks:
21-
- id: check-tests-are-marked
22-
alias: check-tests-are-marked
23-
name: check-tests-are-marked
24-
entry: scripts/check-tests-are-marked.py
25-
language: python
26-
types: ["python"]
27-
files: "tests"
28-
exclude: "/conftest.py$"
29-
- id: check-docker-file-extension
30-
alias: docker-filename
31-
name: check-docker-file-extension
32-
entry: scripts/check-docker-extensions.py
33-
language: python
21+
- id: check-tests-are-marked
22+
alias: check-tests-are-marked
23+
name: check-tests-are-marked
24+
entry: scripts/check-tests-are-marked.py
25+
language: python
26+
types: ["python"]
27+
files: "tests"
28+
exclude: "/conftest.py$"
29+
- id: check-docker-file-extension
30+
alias: docker-filename
31+
name: check-docker-file-extension
32+
entry: scripts/check-docker-extensions.py
33+
language: python

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
# DataOps Observability
2-
![apache 2.0 license Badge](https://img.shields.io/badge/License%20-%20Apache%202.0%20-%20blue) ![PRs Badge](https://img.shields.io/badge/PRs%20-%20Welcome%20-%20green) [![Docker Pulls](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fhub.docker.com%2Fv2%2Frepositories%2Fdatakitchen%2Fdataops-testgen%2F&query=pull_count&style=flat&label=docker%20pulls&color=06A04A)](https://hub.docker.com/r/datakitchen/dataops-observability) [![Documentation](https://img.shields.io/badge/docs-On%20datakitchen.io-06A04A?style=flat)](https://docs.datakitchen.io/articles/#!dataops-observability-help/dataops-observability-help)
1+
# DataOps Observability
2+
![apache 2.0 license Badge](https://img.shields.io/badge/License%20-%20Apache%202.0%20-%20blue) ![PRs Badge](https://img.shields.io/badge/PRs%20-%20Welcome%20-%20green) [![Docker Pulls](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fhub.docker.com%2Fv2%2Frepositories%2Fdatakitchen%2Fdataops-testgen%2F&query=pull_count&style=flat&label=docker%20pulls&color=06A04A)](https://hub.docker.com/r/datakitchen/dataops-observability) [![Documentation](https://img.shields.io/badge/docs-On%20datakitchen.io-06A04A?style=flat)](https://docs.datakitchen.io/articles/#!dataops-observability-help/dataops-observability-help)
33
[![Latest Version](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fhub.docker.com%2Fv2%2Frepositories%2Fdatakitchen%2Fdataops-observability-be%2Ftags%2F&query=results%5B0%5D.name&label=latest%20version&color=06A04A)](https://hub.docker.com/r/datakitchen/dataops-observability-be)
44
[![Static Badge](https://img.shields.io/badge/Slack-Join%20Discussion-blue?style=flat&logo=slack)](https://data-observability-slack.datakitchen.io/join)
55

@@ -152,7 +152,7 @@ We recommend you start by going through the [Data Observability Overview Demo](h
152152
For support requests, [join the Data Observability Slack](https://data-observability-slack.datakitchen.io/join) and ask post on #support channel.
153153

154154
### Connect
155-
Talk and Learn with other data practitioners who are building with DataKitchen. Share knowledge, get help, and contribute to our open-source project.
155+
Talk and Learn with other data practitioners who are building with DataKitchen. Share knowledge, get help, and contribute to our open-source project.
156156

157157
Join our community here:
158158

agent_api/routes/v1_routes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
__all__ = ("build_v1_routes",)
22

3-
from typing import Callable
3+
from collections.abc import Callable
44

55
from flask import Blueprint, Flask
66

cli/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ def get_version(name: str = "cli") -> str:
1212
By default, get_version() always returns the vermin version but the **name** keyword
1313
argument can be passed to get version info for any installed package.
1414
"""
15-
1615
try:
1716
return version(name)
1817
except PackageNotFoundError:

cli/base.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
from argparse import ArgumentParser
55
from logging.config import dictConfig
66
from pathlib import Path
7-
from typing import Any, Callable, Optional
7+
from typing import Any, Optional
8+
from collections.abc import Callable
89

910
from log_color import ColorFormatter, ColorStripper
1011

cli/entry_points/database_schema.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import re
22
from argparse import ArgumentParser
3-
from typing import Any, Iterable, Optional, Pattern
3+
from typing import Any, Optional
4+
from re import Pattern
5+
from collections.abc import Iterable
46

57
from peewee import MySQLDatabase
68

cli/entry_points/gen_events.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
import time
88
from argparse import Action, ArgumentParser, Namespace
99
from datetime import datetime
10-
from typing import Any, Optional, Sequence, Type, Union
10+
from typing import Any, Optional, Union
11+
from collections.abc import Sequence
1112

1213
from requests_extensions import get_session
1314

@@ -82,7 +83,7 @@ class RunStatusEvent(BaseEvent):
8283
}
8384

8485

85-
def make_events_action(event_id: str) -> Type[Action]:
86+
def make_events_action(event_id: str) -> type[Action]:
8687
class EventsAction(Action):
8788
def __call__(
8889
self,

cli/entry_points/init.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ def collect_user_input(fields: list[str]) -> dict[str, str]:
2323
while field not in res:
2424
if value := input(f"{field.capitalize()!s: >20}: "):
2525
res[field] = value
26-
except KeyboardInterrupt:
26+
except KeyboardInterrupt as ki:
2727
print("--\n") # Moving the cursor back to the start
28-
raise OperationAborted("Operation aborted by the user")
28+
raise OperationAborted("Operation aborted by the user") from ki
2929
return res
3030

3131

@@ -39,10 +39,10 @@ def read_json_input(fields: list[str]) -> dict[str, str]:
3939
json_input = json.loads(payload)
4040
for field in fields:
4141
res[field] = json_input[field]
42-
except KeyError as e:
43-
raise OperationAborted(f"'{e}' not found in the input data")
44-
except Exception:
45-
raise OperationAborted("Invalid input data")
42+
except KeyError as ke:
43+
raise OperationAborted(f"'{ke}' not found in the input data") from ke
44+
except Exception as e:
45+
raise OperationAborted("Invalid input data") from e
4646
return res
4747

4848

cli/entry_points/migration_check.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import contextlib
33
import sys
44
from argparse import ArgumentParser
5-
from typing import Iterator
5+
from collections.abc import Iterator
66

77
from peewee import ColumnMetadata, Database, MySQLDatabase, ProgrammingError
88

cli/entry_points/yoyo.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,14 @@ def apply_migrations(self, force: bool = False) -> None:
7070
else:
7171
LOG.info("Migration '%s' SUCCEEDED", migration.id)
7272
applied.append(migration)
73-
except Exception:
73+
except Exception as e:
7474
for migration in reversed(applied):
7575
LOG.info(" '-- Rolling back '%s'", migration.id)
7676
try:
7777
backend.rollback_one(migration, force=True)
7878
except Exception as rollback_exp:
7979
LOG.exception("Error rolling back migration '%s': %s", migration.id, rollback_exp)
8080

81-
raise OperationAborted("Migration failed. The new migrations have been rolled back")
81+
raise OperationAborted("Migration failed. The new migrations have been rolled back") from e
8282

8383
backend.run_post_apply(migrations, force=force)

cli/lib.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ def uuid_type(arg: str) -> UUID:
1212
"""Argument type converter for UUID values."""
1313
try:
1414
uuid_arg = UUID(arg)
15-
except Exception:
16-
raise ArgumentTypeError(f"Invalid UUID value: `{arg}`")
15+
except Exception as e:
16+
raise ArgumentTypeError(f"Invalid UUID value: `{arg}`") from e
1717
else:
1818
return uuid_arg
1919

@@ -29,8 +29,8 @@ def _int_or_none(val: str) -> Optional[int]:
2929

3030
try:
3131
parts = [_int_or_none(x) for x in arg.split(":")]
32-
except (TypeError, ValueError):
33-
raise ArgumentTypeError(f"Invalid SLICE value: `{arg}`")
32+
except (TypeError, ValueError) as e:
33+
raise ArgumentTypeError(f"Invalid SLICE value: `{arg}`") from e
3434

3535
if len(parts) > 3 or len(parts) < 2:
3636
raise ArgumentTypeError(f"Invalid SLICE value: `{arg}`")

common/actions/action_factory.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
__all__ = ["ACTION_CLASS_MAP", "action_factory"]
22

3-
from typing import Optional, Type
3+
from typing import Optional
44

55
from common.entities import Action
66

77
from common.actions.action import BaseAction, ImplementationNotFound, InvalidActionTemplate
88
from common.actions.send_email_action import SendEmailAction
99
from common.actions.webhook_action import WebhookAction
1010

11-
ACTION_CLASS_MAP: dict[str, Type[BaseAction]] = {"CALL_WEBHOOK": WebhookAction, "SEND_EMAIL": SendEmailAction}
11+
ACTION_CLASS_MAP: dict[str, type[BaseAction]] = {"CALL_WEBHOOK": WebhookAction, "SEND_EMAIL": SendEmailAction}
1212

1313

1414
def action_factory(implementation: str, action_args: dict, template: Optional[Action]) -> BaseAction:
1515
try:
1616
action_class = ACTION_CLASS_MAP[implementation]
17-
except KeyError:
18-
raise ImplementationNotFound(f"Action implementation '{implementation}' is not recognized")
17+
except KeyError as ke:
18+
raise ImplementationNotFound(f"Action implementation '{implementation}' is not recognized") from ke
1919

2020
if template and template.action_impl.name != implementation:
2121
raise InvalidActionTemplate(

common/actions/data_points.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import logging
22
from collections.abc import Mapping
33
from datetime import datetime
4-
from typing import Any, Callable, Iterator, Optional, cast
4+
from typing import Any, Optional, cast
5+
from collections.abc import Callable, Iterator
56
from uuid import UUID
67

78
from peewee import DoesNotExist

common/actions/send_email_action.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ def _get_data_points(
4646
"""
4747
Get the data points to be used in the email template
4848
"""
49-
5049
context: dict | AgentStatusChangeDataPoints = dict()
5150

5251
match event:

common/actions/webhook_action.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
__all__ = ["WebhookAction"]
22

33
import logging
4-
from typing import Any, Optional, Union, Mapping
4+
from typing import Any, Optional, Union
5+
from collections.abc import Mapping
56
from uuid import UUID
67

78
from requests_extensions import get_session

common/api/base_view.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import logging
55
from dataclasses import dataclass
66
from functools import cached_property
7-
from typing import Any, Optional, Type
7+
from typing import Any, Optional
88

99
from flask import g, request
1010
from flask.typing import ResponseReturnValue
@@ -35,7 +35,7 @@ def __call__(self, *methods: str) -> Permission:
3535

3636

3737
class SearchableView(MethodView):
38-
FILTERS_SCHEMA: Type[Schema]
38+
FILTERS_SCHEMA: type[Schema]
3939

4040

4141
class BaseView(MethodView):
@@ -84,8 +84,8 @@ def request_body(self) -> dict[str, Any]:
8484
if request_body is None and request.data is not None:
8585
try:
8686
request_body = json.loads(request.data)
87-
except json.JSONDecodeError:
88-
raise BadRequest("The request does not contain a valid JSON body")
87+
except json.JSONDecodeError as je:
88+
raise BadRequest("The request does not contain a valid JSON body") from je
8989
return request_body
9090

9191
def parse_body(self, *, schema: Schema) -> Any:

common/api/flask_ext/authentication/jwt_plugin.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
__all__ = ["JWTAuth"]
22
import logging
33
from datetime import datetime, timedelta, timezone
4-
from typing import Callable, Optional, cast
4+
from typing import Optional, cast
5+
from collections.abc import Callable
56

67
from flask import current_app, g, request
78
from jwt import decode, encode
@@ -20,12 +21,12 @@ def get_token_expiration(claims: JWT_CLAIMS) -> datetime:
2021
"""Returns the JWT expiration as a datetime object."""
2122
try:
2223
exp_timestamp = claims["exp"]
23-
except KeyError:
24-
raise ValueError("Token claims missing 'exp' key")
24+
except KeyError as ke:
25+
raise ValueError("Token claims missing 'exp' key") from ke
2526
try:
2627
return datetime.fromtimestamp(cast(float | int, exp_timestamp), tz=timezone.utc)
27-
except Exception:
28-
raise ValueError(f"Unable to parse expiration from '{claims['exp']}'")
28+
except Exception as e:
29+
raise ValueError(f"Unable to parse expiration from '{claims['exp']}'") from e
2930

3031

3132
class JWTAuth(BaseAuthPlugin):
@@ -72,12 +73,12 @@ def pre_request_auth(cls) -> None:
7273

7374
try:
7475
user = User.select().where(User.id == claims["user_id"], User.primary_company == claims["company_id"]).get()
75-
except DoesNotExist:
76+
except DoesNotExist as dne:
7677
LOG.error("User in claims does not exist")
77-
raise Unauthorized("Invalid authentication token")
78-
except KeyError:
78+
raise Unauthorized("Invalid authentication token") from dne
79+
except KeyError as ke:
7980
LOG.error("Mandatory claims missing. Impossible to authorize user")
80-
raise Unauthorized("Invalid authentication token")
81+
raise Unauthorized("Invalid authentication token") from ke
8182

8283
g.user = user
8384
g.claims = claims

common/api/flask_ext/authentication/service_account_key_plugin.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,5 @@ def pre_request_auth(cls) -> None:
3131
try:
3232
g.project = Project.get_by_id(key_data.project_id)
3333
g.allowed_services = key_data.allowed_services
34-
except DoesNotExist:
35-
raise Unauthorized("Invalid service account key")
34+
except DoesNotExist as dne:
35+
raise Unauthorized("Invalid service account key") from dne

common/api/flask_ext/health.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import logging
22
from http import HTTPStatus
3-
from typing import Any, Callable
3+
from typing import Any
4+
from collections.abc import Callable
45

56
from flask import Blueprint, Flask, Response, make_response
67
from flask.views import MethodView

common/api/request_parsing.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
__all__ = ["get_bool_param", "no_body_allowed", "str_to_bool", "get_origin_domain"]
22

33
from functools import wraps
4-
from typing import Any, Callable, Iterable, Optional
4+
from typing import Any, Optional
5+
from collections.abc import Callable, Iterable
56
from urllib.parse import urlparse
67

78
from flask import Request, request

common/api/search_view.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Any, Optional, Type
1+
from typing import Any, Optional
22

33
from flask import Blueprint, Response, request
44
from flask.typing import RouteCallable
@@ -13,7 +13,7 @@
1313

1414
class SearchView(BaseView):
1515
args_from_post: Optional[MultiDict] = None
16-
request_body_schema: Type[Schema]
16+
request_body_schema: type[Schema]
1717

1818
def post(self, *args: Any, **kwargs: Any) -> Response:
1919
self.parse_body(schema=self.request_body_schema())
@@ -31,11 +31,11 @@ def args(self) -> MultiDict:
3131
def add_route_with_search(bp: Blueprint, rule: str, view_func: RouteCallable, **options: Any) -> RouteCallable:
3232
bp.add_url_rule(rule, view_func=view_func, **options)
3333

34-
view_class: Type[SearchableView] = view_func.view_class # type: ignore [union-attr]
34+
view_class: type[SearchableView] = view_func.view_class # type: ignore [union-attr]
3535
view_name = f"{view_class.__name__}Search"
3636
search_schema = type(f"{view_name}FilterSchema", (Schema,), {"params": Nested(view_class.FILTERS_SCHEMA)})
3737

38-
search_view_class: Type[BaseView] = type(
38+
search_view_class: type[BaseView] = type(
3939
view_name,
4040
(view_class, SearchView),
4141
{"request_body_schema": search_schema},

0 commit comments

Comments
 (0)