Skip to content

Remove support for Python 3.8 #105

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

Merged
merged 3 commits into from
Dec 18, 2024
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
2 changes: 1 addition & 1 deletion .github/workflows/tests-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
runs-on: arc-runner-set
strategy:
matrix:
python-version: [ "3.8", "3.9", "3.10", "3.11", "3.12", "3.13" ]
python-version: [ "3.9", "3.10", "3.11", "3.12", "3.13" ]
steps:
- name: Checkout repository
uses: actions/checkout@v4
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/unit-in-pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu, windows, macos]
python-version: ["3.8"]
os: [ ubuntu, windows, macos ]
python-version: [ "3.9" ]
name: 'test (${{ matrix.os }} - py${{ matrix.python-version }})'
runs-on: ${{ matrix.os }}-latest
steps:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/unit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
os: [ubuntu, windows, macos]
python-version: [ "3.9", "3.10", "3.11", "3.12", "3.13" ]
os: [ ubuntu, windows, macos ]

name: 'test (${{ matrix.os }} - py${{ matrix.python-version }})'
runs-on: ${{ matrix.os }}-latest
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added function `neptune_scale.list_projects()` to list all projects the current user has access to ([#97](https://github.com/neptune-ai/neptune-client-scale/pull/97))

### Changed
- Removed support for Python 3.8
- Neptune will now skip non-finite metric values by default, instead of raising an error. This can be configured using
the new `NEPTUNE_SKIP_NON_FINITE_METRICS` environment variable ([#85](https://github.com/neptune-ai/neptune-client-scale/pull/85))
- Made default error callback logs more informative ([#78](https://github.com/neptune-ai/neptune-client-scale/pull/78))
Expand Down
6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ style = "semver"
pattern = "default-unprefixed"

[tool.poetry.dependencies]
python = "^3.8"
python = "^3.9"

neptune-api = "^0.8.0"
more-itertools = "^10.0.0"
Expand Down Expand Up @@ -54,7 +54,7 @@ keywords = [

[tool.black]
line-length = 120
target_version = ['py38', 'py39', 'py310', 'py311', 'py312']
target_version = ['py39', 'py310', 'py311', 'py312', 'py313']
include = '\.pyi?$,\_pb2\.py$'
exclude = '''
/(
Expand All @@ -74,7 +74,7 @@ force_grid_wrap = 2

[tool.ruff]
line-length = 120
target-version = "py38"
target-version = "py39"

[tool.ruff.lint]
select = ["F", "UP"]
Expand Down
32 changes: 15 additions & 17 deletions src/neptune_scale/api/attribute.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import functools
import itertools
import warnings
from collections.abc import (
Collection,
Iterator,
)
from datetime import datetime
from typing import (
TYPE_CHECKING,
Any,
Callable,
Collection,
Dict,
Iterator,
List,
Optional,
Set,
Tuple,
Union,
cast,
)
Expand Down Expand Up @@ -52,7 +50,7 @@ def wrapper(*args, **kwargs): # type: ignore
class AttributeStore:
def __init__(self, run: "Run") -> None:
self._run = run
self._attributes: Dict[str, Attribute] = {}
self._attributes: dict[str, Attribute] = {}

def __getitem__(self, path: str) -> "Attribute":
path = cleanup_path(path)
Expand All @@ -72,10 +70,10 @@ def log(
self,
step: Optional[Union[float, int]] = None,
timestamp: Optional[Union[datetime, float]] = None,
configs: Optional[Dict[str, Union[float, bool, int, str, datetime, list, set, tuple]]] = None,
metrics: Optional[Dict[str, Union[float, int]]] = None,
tags_add: Optional[Dict[str, Union[List[str], Set[str], Tuple[str]]]] = None,
tags_remove: Optional[Dict[str, Union[List[str], Set[str], Tuple[str]]]] = None,
configs: Optional[dict[str, Union[float, bool, int, str, datetime, list, set, tuple]]] = None,
metrics: Optional[dict[str, Union[float, int]]] = None,
tags_add: Optional[dict[str, Union[list[str], set[str], tuple[str]]]] = None,
tags_remove: Optional[dict[str, Union[list[str], set[str], tuple[str]]]] = None,
) -> None:
# TODO: This should not call Run.log, but do the actual work. Reverse the current dependency so that this
# class handles all the logging
Expand Down Expand Up @@ -117,7 +115,7 @@ def assign(self, value: Any, *, wait: bool = False) -> None:
@warn_unsupported_params
def append(
self,
value: Union[Dict[str, Any], float],
value: Union[dict[str, Any], float],
*,
step: Union[float, int],
timestamp: Optional[Union[float, datetime]] = None,
Expand All @@ -130,15 +128,15 @@ def append(
@warn_unsupported_params
# TODO: this should be Iterable in Run as well
# def add(self, values: Union[str, Iterable[str]], *, wait: bool = False) -> None:
def add(self, values: Union[str, Union[List[str], Set[str], Tuple[str]]], *, wait: bool = False) -> None:
def add(self, values: Union[str, Union[list[str], set[str], tuple[str]]], *, wait: bool = False) -> None:
if isinstance(values, str):
values = (values,)
self._store.log(tags_add={self._path: values})

@warn_unsupported_params
# TODO: this should be Iterable in Run as well
# def remove(self, values: Union[str, Iterable[str]], *, wait: bool = False) -> None:
def remove(self, values: Union[str, Union[List[str], Set[str], Tuple[str]]], *, wait: bool = False) -> None:
def remove(self, values: Union[str, Union[list[str], set[str], tuple[str]]], *, wait: bool = False) -> None:
if isinstance(values, str):
values = (values,)
self._store.log(tags_remove={self._path: values})
Expand Down Expand Up @@ -168,7 +166,7 @@ def extend(
# TODO: change Run API to typehint timestamp as Union[datetime, float]


def iter_nested(dict_: Dict[str, ValueType], path: str) -> Iterator[Tuple[Tuple[str, ...], ValueType]]:
def iter_nested(dict_: dict[str, ValueType], path: str) -> Iterator[tuple[tuple[str, ...], ValueType]]:
"""Iterate a nested dictionary, yielding a tuple of path components and value.

>>> list(iter_nested({"foo": 1, "bar": {"baz": 2}}, "base"))
Expand All @@ -187,7 +185,7 @@ def iter_nested(dict_: Dict[str, ValueType], path: str) -> Iterator[Tuple[Tuple[
yield from _iter_nested(dict_, parts)


def _iter_nested(dict_: Dict[str, ValueType], path_acc: Tuple[str, ...]) -> Iterator[Tuple[Tuple[str, ...], ValueType]]:
def _iter_nested(dict_: dict[str, ValueType], path_acc: tuple[str, ...]) -> Iterator[tuple[tuple[str, ...], ValueType]]:
if not dict_:
raise ValueError("The dictionary cannot be empty or contain empty nested dictionaries.")

Expand Down Expand Up @@ -228,7 +226,7 @@ def cleanup_path(path: str) -> str:
return path


def accumulate_dict_values(value: Union[ValueType, Dict[str, ValueType]], path_or_base: str) -> Dict:
def accumulate_dict_values(value: Union[ValueType, dict[str, ValueType]], path_or_base: str) -> dict:
"""
>>> accumulate_dict_values(1, "foo")
{'foo': 1}
Expand Down
22 changes: 9 additions & 13 deletions src/neptune_scale/api/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,13 @@
import os
import threading
import time
from collections.abc import Callable
from contextlib import AbstractContextManager
from datetime import datetime
from typing import (
Any,
Callable,
Dict,
List,
Literal,
Optional,
Set,
Tuple,
Union,
)

Expand Down Expand Up @@ -401,7 +397,7 @@ def __setitem__(self, key: str, value: Any) -> None:

def log_metrics(
self,
data: Dict[str, Union[float, int]],
data: dict[str, Union[float, int]],
step: Union[float, int],
*,
timestamp: Optional[datetime] = None,
Expand Down Expand Up @@ -442,7 +438,7 @@ def log_metrics(
self.log(step=step, timestamp=timestamp, metrics=data)

def log_configs(
self, data: Optional[Dict[str, Union[float, bool, int, str, datetime, list, set, tuple]]] = None
self, data: Optional[dict[str, Union[float, bool, int, str, datetime, list, set, tuple]]] = None
) -> None:
"""
Logs the specified metadata to a Neptune run.
Expand Down Expand Up @@ -477,7 +473,7 @@ def log_configs(
"""
self.log(configs=data)

def add_tags(self, tags: Union[List[str], Set[str], Tuple[str]], group_tags: bool = False) -> None:
def add_tags(self, tags: Union[list[str], set[str], tuple[str]], group_tags: bool = False) -> None:
"""
Adds the list of tags to the run.

Expand All @@ -496,7 +492,7 @@ def add_tags(self, tags: Union[List[str], Set[str], Tuple[str]], group_tags: boo
name = "sys/tags" if not group_tags else "sys/group_tags"
self.log(tags_add={name: tags})

def remove_tags(self, tags: Union[List[str], Set[str], Tuple[str]], group_tags: bool = False) -> None:
def remove_tags(self, tags: Union[list[str], set[str], tuple[str]], group_tags: bool = False) -> None:
"""
Removes the specified tags from the run.

Expand All @@ -519,10 +515,10 @@ def log(
self,
step: Optional[Union[float, int]] = None,
timestamp: Optional[datetime] = None,
configs: Optional[Dict[str, Union[float, bool, int, str, datetime, list, set, tuple]]] = None,
metrics: Optional[Dict[str, Union[float, int]]] = None,
tags_add: Optional[Dict[str, Union[List[str], Set[str], Tuple[str]]]] = None,
tags_remove: Optional[Dict[str, Union[List[str], Set[str], Tuple[str]]]] = None,
configs: Optional[dict[str, Union[float, bool, int, str, datetime, list, set, tuple]]] = None,
metrics: Optional[dict[str, Union[float, int]]] = None,
tags_add: Optional[dict[str, Union[list[str], set[str], tuple[str]]]] = None,
tags_remove: Optional[dict[str, Union[list[str], set[str], tuple[str]]]] = None,
) -> None:
"""
See one of the following instead:
Expand Down
5 changes: 2 additions & 3 deletions src/neptune_scale/api/validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,15 @@

from typing import (
Any,
Type,
Union,
)


def get_type_name(var_type: Union[Type, tuple]) -> str:
def get_type_name(var_type: Union[type, tuple]) -> str:
return var_type.__name__ if hasattr(var_type, "__name__") else str(var_type)


def verify_type(var_name: str, var: Any, expected_type: Union[Type, tuple]) -> None:
def verify_type(var_name: str, var: Any, expected_type: Union[type, tuple]) -> None:
try:
if isinstance(expected_type, tuple):
type_name = " or ".join(get_type_name(t) for t in expected_type)
Expand Down
2 changes: 1 addition & 1 deletion src/neptune_scale/net/api_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@
import functools
import os
import uuid
from collections.abc import Callable
from dataclasses import dataclass
from http import HTTPStatus
from typing import (
Any,
Callable,
Literal,
)

Expand Down
6 changes: 2 additions & 4 deletions src/neptune_scale/net/projects.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
from json import JSONDecodeError
from typing import (
Any,
Dict,
List,
Optional,
cast,
)
Expand Down Expand Up @@ -93,7 +91,7 @@ def _safe_json(response: httpx.Response) -> Any:
return {}


def get_project_list(*, api_token: Optional[str] = None) -> List[Dict]:
def get_project_list(*, api_token: Optional[str] = None) -> list[dict]:
client = HostedApiClient(api_token=_get_api_token(api_token))

params = {
Expand All @@ -102,4 +100,4 @@ def get_project_list(*, api_token: Optional[str] = None) -> List[Dict]:
}

response = client.backend.get_httpx_client().request("get", PROJECTS_PATH_BASE, params=params)
return cast(List[Dict], response.json()["entries"])
return cast(list[dict], response.json()["entries"])
8 changes: 2 additions & 6 deletions src/neptune_scale/net/serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,7 @@
)

from datetime import datetime
from typing import (
List,
Set,
Union,
)
from typing import Union

from google.protobuf.timestamp_pb2 import Timestamp
from neptune_api.proto.neptune_pb.ingest.v1.common_pb2 import (
Expand All @@ -22,7 +18,7 @@
)


def make_value(value: Union[Value, float, str, int, bool, datetime, List[str], Set[str]]) -> Value:
def make_value(value: Union[Value, float, str, int, bool, datetime, list[str], set[str]]) -> Value:
if isinstance(value, Value):
return value
if isinstance(value, float):
Expand Down
6 changes: 2 additions & 4 deletions src/neptune_scale/projects.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import re
from typing import (
List,
Optional,
Tuple,
cast,
)

Expand Down Expand Up @@ -66,7 +64,7 @@ def create_project(
return normalize_project_name(name, workspace)


def extract_workspace_and_project(name: str, workspace: Optional[str] = None) -> Tuple[str, str]:
def extract_workspace_and_project(name: str, workspace: Optional[str] = None) -> tuple[str, str]:
"""Return a tuple of (workspace name, project name) from the provided
fully qualified project name, or a name + workspace

Expand Down Expand Up @@ -118,7 +116,7 @@ def normalize_project_name(name: str, workspace: Optional[str] = None) -> str:
return f"{extracted_workspace_name}/{extracted_project_name}"


def list_projects(*, api_token: Optional[str] = None) -> List[str]:
def list_projects(*, api_token: Optional[str] = None) -> list[str]:
"""Lists projects that the account has access to.

Args:
Expand Down
9 changes: 3 additions & 6 deletions src/neptune_scale/sync/errors_tracking.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,8 @@
import multiprocessing
import queue
import time
from typing import (
Callable,
Optional,
Type,
)
from collections.abc import Callable
from typing import Optional

from neptune_scale.exceptions import (
NeptuneAsyncLagThresholdExceeded,
Expand Down Expand Up @@ -90,7 +87,7 @@ def __init__(
on_warning_callback or default_warning_callback
)

self._last_raised_timestamps: dict[Type[BaseException], float] = {}
self._last_raised_timestamps: dict[type[BaseException], float] = {}

def get_next(self) -> Optional[BaseException]:
try:
Expand Down
2 changes: 1 addition & 1 deletion src/neptune_scale/sync/lag_tracking.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

__all__ = ("LagTracker",)

from collections.abc import Callable
from time import monotonic
from typing import Callable

from neptune_scale.sync.errors_tracking import ErrorsQueue
from neptune_scale.sync.operations_queue import OperationsQueue
Expand Down
Loading
Loading