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

post-v7 improvements & fixes #1533

Merged
merged 5 commits into from
Dec 4, 2023
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
3 changes: 0 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,6 @@ jobs:
poetry install

- name: Test core
env:
CI: 1
run: pytest tests/tests_unit -n8 --dist loadscope --maxfail 10 -m 'not dsl'
--test-deps-only-core

Expand Down Expand Up @@ -103,7 +101,6 @@ jobs:
COGNITE_PROJECT: python-sdk-test
COGNITE_BASE_URL: https://greenfield.cognitedata.com
COGNITE_CLIENT_NAME: python-sdk-integration-tests
CI: 1
run: |
pytest tests --durations=10 --cov --cov-report xml:coverage.xml -n8 --dist loadscope --reruns 2

Expand Down
22 changes: 9 additions & 13 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ jobs:
poetry install -E numpy

- name: Linting and static code checks
run: |
pre-commit run --all-files
run: pre-commit run --all-files

- name: Verify proto files
env:
Expand Down Expand Up @@ -53,8 +52,6 @@ jobs:
poetry install

- name: Test core
env:
CI: 1
run: pytest tests/tests_unit -n8 --dist loadscope --maxfail 10 -m 'not dsl'
--test-deps-only-core

Expand Down Expand Up @@ -86,9 +83,7 @@ jobs:
COGNITE_PROJECT: python-sdk-test
COGNITE_BASE_URL: https://greenfield.cognitedata.com
COGNITE_CLIENT_NAME: python-sdk-integration-tests
CI: 1
run: |
pytest tests --cov --cov-report xml:coverage.xml -n8 --dist loadscope --reruns 2
run: pytest tests --cov --cov-report xml:coverage.xml -n8 --dist loadscope --reruns 2 --maxfail 20

- uses: codecov/codecov-action@v3
with:
Expand All @@ -97,7 +92,7 @@ jobs:

build:
runs-on: ubuntu-latest
needs: [lint, test_full]
needs: [lint, test_core, test_full]
environment: CD
steps:
- uses: actions/checkout@v4
Expand All @@ -123,8 +118,9 @@ jobs:
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
run: twine upload --verbose dist/* || echo 'Version exists'

- name: Push code snippets to service-contracts
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: sh ./scripts/deploy_code_snippets.sh || echo 'PR failed. There is probably
nothing to commit'
# TODO: Make this work again
# - name: Push code snippets to service-contracts
# env:
# GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# run: sh ./scripts/deploy_code_snippets.sh || echo 'PR failed. There is probably
# nothing to commit'
18 changes: 13 additions & 5 deletions cognite/client/data_classes/capabilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,21 @@ class Capability(ABC):
def __post_init__(self) -> None:
if (capability_cls := type(self)) is UnknownAcl:
return
acl = capability_cls.__name__
try:
# There are so many things that may fail validation; non-enum passed, not iterable etc.
# We always want to show the example usage to the user.
self._validate()
except Exception as err:
raise ValueError(
f"Could not instantiate {capability_cls.__name__} due to: {err}. " + self.show_example_usage()
) from err

def _validate(self) -> None:
acl = (capability_cls := type(self)).__name__
if bad_actions := [a for a in self.actions if a not in capability_cls.Action]:
full_action_examples = ", ".join(f"{acl}.Action.{action.name}" for action in capability_cls.Action)
raise ValueError(
f"{acl} got unknown action(s): {bad_actions}, expected a subset of: [{full_action_examples}]. "
+ self.show_example_usage()
f"{acl} got unknown action(s): {bad_actions}, expected a subset of: [{full_action_examples}]."
)
allowed_scopes, scope_names = _VALID_SCOPES_BY_CAPABILITY[capability_cls]
if type(self.scope) in allowed_scopes or not allowed_scopes:
Expand All @@ -52,8 +61,7 @@ def __post_init__(self) -> None:
else:
full_scope_examples = ", ".join(f"{acl}.Scope.{name}" for name in scope_names)
raise ValueError(
f"{acl} got an unknown scope: {self.scope}, expected an instance of one of: [{full_scope_examples}]. "
+ self.show_example_usage()
f"{acl} got an unknown scope: {self.scope}, expected an instance of one of: [{full_scope_examples}]."
)

@classmethod
Expand Down
9 changes: 6 additions & 3 deletions cognite/client/data_classes/iam.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ class Group(CogniteResource):
Args:
name (str): Name of the group
source_id (str | None): ID of the group in the source. If this is the same ID as a group in the IDP, a service account in that group will implicitly be a part of this group as well.
capabilities (list[Capability] | None): No description.
id (int | None): No description.
capabilities (list[Capability] | None): List of capabilities (acls) this group should grant its users.
id (int | None): A server-generated ID for the object.
is_deleted (bool | None): No description.
deleted_time (int | None): No description.
metadata (dict[str, Any] | None): Custom, immutable application specific metadata. String key -> String value. Limits:
metadata (dict[str, Any] | None): Custom, immutable application specific metadata. String key -> String value.
Limits: Key are at most 32 bytes. Values are at most 512 bytes. Up to 16 key-value pairs. Total size is at most 4096.
cognite_client (CogniteClient | None): The client to associate with this object.
"""

Expand All @@ -42,6 +43,8 @@ def __init__(
self.name = name
self.source_id = source_id
self.capabilities = capabilities
if isinstance(self.capabilities, Capability):
self.capabilities = [capabilities]
self.id = id
self.is_deleted = is_deleted
self.deleted_time = deleted_time
Expand Down
2 changes: 2 additions & 0 deletions tests/tests_unit/test_api_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import json
import math
import random
import time
import unittest
from collections import namedtuple
from typing import Any, ClassVar, Literal, cast
Expand Down Expand Up @@ -495,6 +496,7 @@ def request_callback(request):
if int(np) == 3:
return 503, {}, json.dumps({"message": "Service Unavailable"})
else:
time.sleep(0.001) # ensures bad luck race condition where 503 above executes last
return 200, {}, json.dumps({"items": [{"x": 42, "y": 13}]})

rsps.add_callback(
Expand Down
10 changes: 5 additions & 5 deletions tests/tests_unit/test_data_classes/test_capabilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,13 +249,13 @@ def test_create_capability_forget_initializing_scope(self):
assert grp1.dump() == grp2.dump()

def test_create_capability_forget_initializing_scope__not_supported(self):
with pytest.raises(ValueError, match="^DataSetsAcl got an unknown scope"):
with pytest.raises(ValueError, match="DataSetsAcl got an unknown scope"):
DataSetsAcl(actions=[DataSetsAcl.Action.Read], scope=CurrentUserScope)

with pytest.raises(ValueError, match="^DataSetsAcl got an unknown scope"):
with pytest.raises(ValueError, match="DataSetsAcl got an unknown scope"):
DataSetsAcl(actions=[DataSetsAcl.Action.Read], scope=GroupsAcl.Scope.CurrentUser)

with pytest.raises(ValueError, match="^ExperimentsAcl got an unknown scope"):
with pytest.raises(ValueError, match="ExperimentsAcl got an unknown scope"):
ExperimentsAcl(actions=[ExperimentsAcl.Action.Use], scope=AllScope)


Expand Down Expand Up @@ -412,8 +412,8 @@ def test_idscopes_camel_case():
with pytest.raises(ValueError) as err:
Capability.load(dct)
assert err.value.args[0].startswith(
"DataSetsAcl got an unknown scope: IDScopeLowerCase(ids=[2495]), expected an instance of one of: "
"[DataSetsAcl.Scope.All, DataSetsAcl.Scope.ID]"
"Could not instantiate DataSetsAcl due to: DataSetsAcl got an unknown scope: IDScopeLowerCase(ids=[2495]), "
"expected an instance of one of: [DataSetsAcl.Scope.All, DataSetsAcl.Scope.ID]"
)


Expand Down
5 changes: 5 additions & 0 deletions tests/tests_unit/test_data_classes/test_groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import pytest

from cognite.client.data_classes import Group, GroupList
from cognite.client.data_classes.capabilities import DataModelInstancesAcl


def raw_groups():
Expand Down Expand Up @@ -39,6 +40,10 @@ def raw_groups():


class TestGroups:
def test_group_init__accept_single_acl(self) -> None:
acl = DataModelInstancesAcl([DataModelInstancesAcl.Action.Write], DataModelInstancesAcl.Scope.All())
assert Group(name="a", capabilities=acl) == Group(name="a", capabilities=[acl])

@pytest.mark.parametrize("raw", list(raw_groups()))
def test_load_dump_unknown_group(self, raw: dict[str, Any]) -> None:
group = Group.load(raw)
Expand Down