Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update axiom-py fork to v0.5.0 #3

Merged
merged 29 commits into from
Sep 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
dfaf971
Update responses requirement from ^0.23.1 to ^0.25.0
dependabot[bot] Feb 20, 2024
344043d
Update black requirement from ^23.3.0 to ^24.4.2
dependabot[bot] Apr 26, 2024
e66e502
Update pytest requirement from ^7.3.2 to ^8.2.1
dependabot[bot] May 20, 2024
c3f2170
Update pylint requirement from ^2.7.2 to ^3.2.1
dependabot[bot] May 20, 2024
0630c4e
chore: new repo banner
ImLunaHey Jul 14, 2024
1eb5893
feat(typing): Prefer object over Any
mrcljx Aug 16, 2024
96590b0
chore: new repo banner
ImLunaHey Aug 19, 2024
963c0b3
feat: Add cursor, includeCursor options
bahlo Sep 6, 2024
c614f6d
chore: Bump version to 0.5.0
bahlo Sep 6, 2024
c79eebf
fix: Check if opts is None before using it
bahlo Sep 6, 2024
553c01c
fix: Make cursor Optional, improve checks
bahlo Sep 7, 2024
afafd05
Merge pull request #118 from axiomhq/arne/add-cursor
bahlo Sep 7, 2024
7ebbae8
Merge pull request #111 from axiomhq/dependabot/pip/pylint-tw-3.2.1
bahlo Sep 7, 2024
07f784f
Merge branch 'main' into dependabot/pip/pytest-tw-8.2.1
bahlo Sep 7, 2024
0215f86
Merge pull request #110 from axiomhq/dependabot/pip/pytest-tw-8.2.1
bahlo Sep 7, 2024
e642f53
Merge branch 'main' into dependabot/pip/black-tw-24.4.2
bahlo Sep 7, 2024
89eb389
Merge pull request #106 from axiomhq/dependabot/pip/black-tw-24.4.2
bahlo Sep 7, 2024
461a7d5
Bump actions/setup-python from 4 to 5
dependabot[bot] Feb 20, 2024
da58ef4
Merge branch 'main' into dependabot/pip/responses-tw-0.25.0
bahlo Sep 7, 2024
6f7f0c3
Merge pull request #94 from axiomhq/dependabot/github_actions/actions…
bahlo Sep 7, 2024
009503d
Merge branch 'main' into dependabot/pip/responses-tw-0.25.0
bahlo Sep 7, 2024
6d9e5d5
chore: Run black on client.py
bahlo Sep 7, 2024
7053320
Merge pull request #96 from axiomhq/dependabot/pip/responses-tw-0.25.0
bahlo Sep 7, 2024
c671049
Merge pull request #116 from mrcljx/avoid-any
bahlo Sep 7, 2024
7eeb14f
Address merge conflicts between API token methods and the upstream br…
WRansohoff Sep 8, 2024
1196706
Linting
WRansohoff Sep 8, 2024
eee0e09
Lint API token dataclass properties
WRansohoff Sep 9, 2024
abfa59c
poetry black reformat
WRansohoff Sep 9, 2024
b7ed013
More API token dataclass linting.
WRansohoff Sep 9, 2024
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
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- run: pip install poetry==${{ env.POETRY_VERSION }}
Expand Down Expand Up @@ -53,7 +53,7 @@ jobs:
org_id: TESTING_STAGING_ORG_ID
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
- run: pip install poetry==${{ env.POETRY_VERSION }}
Expand All @@ -72,7 +72,7 @@ jobs:
- test-integration
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- run: pip install poetry==${{ env.POETRY_VERSION }}
Expand Down
17 changes: 11 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
![axiom-py: The official Python bindings for the Axiom API](.github/images/banner-dark.svg#gh-dark-mode-only)
![axiom-py: The official Python bindings for the Axiom API](.github/images/banner-light.svg#gh-light-mode-only)

<div align="center">
# axiom-py

<a href="https://axiom.co">
<picture>
<source media="(prefers-color-scheme: dark) and (min-width: 600px)" srcset="https://axiom.co/assets/github/axiom-github-banner-light-vertical.svg">
<source media="(prefers-color-scheme: light) and (min-width: 600px)" srcset="https://axiom.co/assets/github/axiom-github-banner-dark-vertical.svg">
<source media="(prefers-color-scheme: dark) and (max-width: 599px)" srcset="https://axiom.co/assets/github/axiom-github-banner-light-horizontal.svg">
<img alt="Axiom.co banner" src="https://axiom.co/assets/github/axiom-github-banner-dark-horizontal.svg" align="right">
</picture>
</a>
&nbsp;

[![CI][ci_badge]][ci]
[![PyPI version][pypi_badge]][pypi]
[![Python version][version_badge]][pypi]

</div>

[Axiom](https://axiom.co) unlocks observability at any scale.

- **Ingest with ease, store without limits:** Axiom’s next-generation datastore enables ingesting petabytes of data with ultimate efficiency. Ship logs from Kubernetes, AWS, Azure, Google Cloud, DigitalOcean, Nomad, and others.
Expand Down
55 changes: 29 additions & 26 deletions axiom/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from .util import Util
from enum import Enum
from humps import decamelize
from typing import Optional, List, Dict, Any
from typing import Optional, List, Dict
from logging import getLogger
from dataclasses import asdict, dataclass, field
from datetime import datetime
Expand Down Expand Up @@ -100,11 +100,18 @@ class WrongQueryKindException(Exception):
class AplOptions:
"""AplOptions specifies the optional parameters for the apl query method."""

# Start time for the interval to query.
start_time: Optional[datetime] = field(default=None)
# End time for the interval to query.
end_time: Optional[datetime] = field(default=None)
no_cache: bool = field(default=False)
save: bool = field(default=False)
# The result format.
format: AplResultFormat = field(default=AplResultFormat.Legacy)
# Cursor is the query cursor. It should be set to the Cursor returned with
# a previous query result if it was partial.
cursor: Optional[str] = field(default=None)
# IncludeCursor will return the Cursor as part of the query result, if set
# to true.
includeCursor: bool = field(default=False)


def raise_response_error(r):
Expand Down Expand Up @@ -273,11 +280,8 @@ def query(self, apl: str, opts: Optional[AplOptions] = None) -> QueryResult:
def create_api_token(self, opts: TokenAttributes) -> Token:
"""Creates a new API token with permissions specified in a TokenAttributes object."""
res = self.session.post(
'/v2/tokens',
data=ujson.dumps(
asdict(opts),
default=Util.handle_json_serialization
)
"/v2/tokens",
data=ujson.dumps(asdict(opts), default=Util.handle_json_serialization),
)

# Return the new token and ID.
Expand All @@ -286,9 +290,9 @@ def create_api_token(self, opts: TokenAttributes) -> Token:

def delete_api_token(self, token_id: str) -> None:
"""Delete an API token using its ID string."""
self.session.delete(f'/v2/tokens/{token_id}')
self.session.delete(f"/v2/tokens/{token_id}")

def _prepare_query_options(self, opts: QueryOptions) -> Dict[str, Any]:
def _prepare_query_options(self, opts: QueryOptions) -> Dict[str, object]:
"""returns the query options as a Dict, handles any renaming for key fields."""
if opts is None:
return {}
Expand All @@ -304,7 +308,9 @@ def _prepare_query_options(self, opts: QueryOptions) -> Dict[str, Any]:

return params

def _prepare_ingest_options(self, opts: Optional[IngestOptions]) -> Dict[str, Any]:
def _prepare_ingest_options(
self, opts: Optional[IngestOptions]
) -> Dict[str, object]:
"""the query params for ingest api are expected in a format
that couldn't be defined as a variable name because it has a dash.
As a work around, we create the params dict manually."""
Expand All @@ -322,34 +328,31 @@ def _prepare_ingest_options(self, opts: Optional[IngestOptions]) -> Dict[str, An

return params

def _prepare_apl_options(self, opts: Optional[AplOptions]) -> Dict[str, Any]:
def _prepare_apl_options(self, opts: Optional[AplOptions]) -> Dict[str, object]:
"""Prepare the apl query options for the request."""
params = {}
params = {"format": AplResultFormat.Legacy.value}

if opts is None:
params["format"] = AplResultFormat.Legacy.value
return params

if opts.no_cache:
params["nocache"] = opts.no_cache.__str__()
if opts.save:
params["save"] = opts.save
if opts.format:
params["format"] = opts.format.value
if opts is not None:
if opts.format:
params["format"] = opts.format.value

return params

def _prepare_apl_payload(
self, apl: str, opts: Optional[AplOptions]
) -> Dict[str, Any]:
) -> Dict[str, object]:
"""Prepare the apl query options for the request."""
params = {}
params["apl"] = apl

if opts is not None:
if opts.start_time:
if opts.start_time is not None:
params["startTime"] = opts.start_time
if opts.end_time:
if opts.end_time is not None:
params["endTime"] = opts.end_time
if opts.cursor is not None:
params["cursor"] = opts.cursor
if opts.includeCursor:
params["includeCursor"] = opts.includeCursor

return params
8 changes: 4 additions & 4 deletions axiom/query/result.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from dataclasses import dataclass, field
from datetime import datetime, timedelta
from typing import List, Dict, Any, Optional
from typing import List, Dict, Optional
from enum import Enum

from .query import QueryLegacy
Expand Down Expand Up @@ -87,7 +87,7 @@ class Entry:
_rowId: str
# contains the raw data of the event (with filters and aggregations
# applied).
data: Dict[str, Any]
data: Dict[str, object]


@dataclass
Expand All @@ -96,7 +96,7 @@ class EntryGroupAgg:

# alias is the aggregations alias. If it wasn't specified at query time, it
# is the uppercased string representation of the aggregation operation.
value: Any
value: object
op: str = field(default="")
# value is the result value of the aggregation.

Expand All @@ -108,7 +108,7 @@ class EntryGroup:
# the unique id of the group.
id: int
# group maps the fieldnames to the unique values for the entry.
group: Dict[str, Any]
group: Dict[str, object]
# aggregations of the group.
aggregations: List[EntryGroupAgg]

Expand Down
78 changes: 55 additions & 23 deletions axiom/tokens.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from dataclasses import dataclass
from typing import Literal
from dataclasses import dataclass, field
from typing import Literal, Optional


@dataclass
class TokenDatasetCapabilities:
# pylint: disable=unsubscriptable-object
"""
TokenDatasetCapabilities describes the dataset-level permissions
which a token can be assigned.
Expand All @@ -12,52 +13,80 @@ class TokenDatasetCapabilities:
"""

# Ability to ingest data. Optional.
ingest: list[Literal["create"]] | None = None
ingest: Optional[list[Literal["create"]]] = field(default=None)
# Ability to query data. Optional.
query: list[Literal["read"]] | None = None
query: Optional[list[Literal["read"]]] = field(default=None)
# Ability to use starred queries. Optional.
starredQueries: list[Literal["create", "read", "update", "delete"]] | None = None
starredQueries: Optional[list[Literal["create", "read", "update", "delete"]]] = (
field(default=None)
)
# Ability to use virtual fields. Optional.
virtualFields: list[Literal["create", "read", "update", "delete"]] | None = None
virtualFields: Optional[list[Literal["create", "read", "update", "delete"]]] = (
field(default=None)
)


@dataclass
class TokenOrganizationCapabilities:
# pylint: disable=unsubscriptable-object
"""
TokenOrganizationCapabilities describes the org-level permissions
which a token can be assigned.
"""

# Ability to use annotations. Optional.
annotations: list[Literal["create", "read", "update", "delete"]] | None = None
annotations: Optional[list[Literal["create", "read", "update", "delete"]]] = field(
default=None
)
# Ability to use api tokens. Optional.
apiTokens: list[Literal["create", "read", "update", "delete"]] | None = None
apiTokens: Optional[list[Literal["create", "read", "update", "delete"]]] = field(
default=None
)
# Ability to access billing. Optional.
billing: list[Literal["read", "update"]] | None = None
billing: Optional[list[Literal["read", "update"]]] = field(default=None)
# Ability to use dashboards. Optional.
dashboards: list[Literal["create", "read", "update", "delete"]] | None = None
dashboards: Optional[list[Literal["create", "read", "update", "delete"]]] = field(
default=None
)
# Ability to use datasets. Optional.
datasets: list[Literal["create", "read", "update", "delete"]] | None = None
datasets: Optional[list[Literal["create", "read", "update", "delete"]]] = field(
default=None
)
# Ability to use endpoints. Optional.
endpoints: list[Literal["create", "read", "update", "delete"]] | None = None
endpoints: Optional[list[Literal["create", "read", "update", "delete"]]] = field(
default=None
)
# Ability to use flows. Optional.
flows: list[Literal["create", "read", "update", "delete"]] | None = None
flows: Optional[list[Literal["create", "read", "update", "delete"]]] = field(
default=None
)
# Ability to use integrations. Optional.
integrations: list[Literal["create", "read", "update", "delete"]] | None = None
integrations: Optional[list[Literal["create", "read", "update", "delete"]]] = field(
default=None
)
# Ability to use monitors. Optional.
monitors: list[Literal["create", "read", "update", "delete"]] | None = None
monitors: Optional[list[Literal["create", "read", "update", "delete"]]] = field(
default=None
)
# Ability to use notifiers. Optional.
notifiers: list[Literal["create", "read", "update", "delete"]] | None = None
notifiers: Optional[list[Literal["create", "read", "update", "delete"]]] = field(
default=None
)
# Ability to use role-based access controls. Optional.
rbac: list[Literal["create", "read", "update", "delete"]] | None = None
rbac: Optional[list[Literal["create", "read", "update", "delete"]]] = field(
default=None
)
# Ability to use shared access keys. Optional.
sharedAccessKeys: list[Literal["read", "update"]] | None = None
sharedAccessKeys: Optional[list[Literal["read", "update"]]] = field(default=None)
# Ability to use users. Optional.
users: list[Literal["create", "read", "update", "delete"]] | None = None
users: Optional[list[Literal["create", "read", "update", "delete"]]] = field(
default=None
)


@dataclass
class TokenAttributes:
# pylint: disable=unsubscriptable-object
"""
TokenAttributes describes the set of input parameters that the
POST /tokens API accepts.
Expand All @@ -66,13 +95,15 @@ class TokenAttributes:
# Name for the token. Required.
name: str
# The token's dataset-level capabilities. Keyed on dataset name. Optional.
datasetCapabilities: dict[str, TokenDatasetCapabilities] | None = None
datasetCapabilities: Optional[dict[str, TokenDatasetCapabilities]] = field(
default=None
)
# Description for the API token. Optional.
description: str | None = None
description: Optional[str] = field(default=None)
# Expiration date for the API token. Optional.
expiresAt: str | None = None
expiresAt: Optional[str] = field(default=None)
# The token's organization-level capabilities. Optional.
orgCapabilities: TokenOrganizationCapabilities | None = None
orgCapabilities: Optional[TokenOrganizationCapabilities] = field(default=None)


@dataclass
Expand All @@ -81,5 +112,6 @@ class Token:
Token contains the response from a call to POST /tokens.
It includes the API token itself, and an ID which can be used to reference it later.
"""

id: str
token: str
10 changes: 5 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "axiom-py"
version = "0.4.0"
version = "0.5.0"
description = "Axiom API Python bindings."
authors = ["Axiom, Inc."]
license = "MIT"
Expand All @@ -22,10 +22,10 @@ rfc3339 = "^6.2"
iso8601 = ">=1.0.2,<3.0.0"

[tool.poetry.dev-dependencies]
black = "^23.3.0"
pytest = "^7.3.2"
pylint = "^2.7.2"
responses = "^0.23.1"
black = "^24.4.2"
pytest = "^8.2.1"
pylint = "^3.2.1"
responses = "^0.25.0"

[build-system]
requires = ["poetry-core>=1.0.0"]
Expand Down
2 changes: 1 addition & 1 deletion tests/test_annotations.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import os

import unittest
from typing import List, Dict, Any, Optional
from typing import List, Dict, Optional
from logging import getLogger
from requests.exceptions import HTTPError
from datetime import timedelta
Expand Down
Loading