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
2 changes: 1 addition & 1 deletion .env.test
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ PYTEST_ADMIN_PASSWORD=start123
PYTEST_DEFAULT_MASTER_IMAGE=python/base
PYTEST_ASYNC_MAX_RETRIES=5
PYTEST_ASYNC_RETRY_DELAY_MILLIS=500
PYTEST_HUB_VERSION=0.8.37
PYTEST_HUB_VERSION=0.8.43
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
![Code Coverage](https://img.shields.io/badge/Coverage-96%25-brightgreen.svg)
![Code Coverage](https://img.shields.io/badge/Coverage-95%25-brightgreen.svg)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Code coverage decreased from 96% to 95%.

Consider verifying that the new code introduced in this PR is adequately tested. A coverage drop may indicate untested functionality or edge cases.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` at line 1, Code coverage fell from 96% to 95% after this PR; add
tests exercising the newly-introduced functionality to restore coverage, run the
project's coverage tool locally to confirm, and only update the README badge
(the image line in README.md) if the reported coverage is legitimately changed.
Identify the new or modified modules/files introduced by this PR, write
unit/integration tests that cover their edge cases and error paths, run the
repository's test/coverage command to verify coverage returns to the required
threshold, and update the README badge if the verified coverage number differs
from the current badge.


# FLAME Hub Python Client

Expand Down
14 changes: 4 additions & 10 deletions docs/types_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,9 @@
Types
=====

.. autoclass:: flame_hub.types.UNSET_T

.. autodata:: flame_hub._base_client.ResourceT
:annotation: = typing.TypeVar

.. autoclass:: flame_hub.types.FilterParams

.. autoclass:: flame_hub.types.FieldParams

.. autoclass:: flame_hub.types.IncludeParams
Expand All @@ -21,17 +17,15 @@ Types

.. autoclass:: flame_hub.types.ProjectNodeApprovalStatus

.. autoclass:: flame_hub.types.AnalysisBuildStatus

.. autoclass:: flame_hub.types.AnalysisRunStatus

.. autoclass:: flame_hub.types.AnalysisCommand

.. autoclass:: flame_hub.types.AnalysisNodeApprovalStatus

.. autoclass:: flame_hub.types.AnalysisNodeRunStatus
.. autoclass:: flame_hub.types.ProcessStatus

.. autoclass:: flame_hub.types.LogLevel

.. autoclass:: flame_hub.types.AnalysisBucketType
.. autoclass:: flame_hub.types.LogChannel

.. automodule:: flame_hub.types
:members:
Expand Down
7 changes: 4 additions & 3 deletions flame_hub/_exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
from json import JSONDecodeError

import httpx
from pydantic import ValidationError, BaseModel, ConfigDict, Field
from pydantic import ValidationError, BaseModel, ConfigDict, Field, AliasChoices


class ErrorResponse(BaseModel):
model_config = ConfigDict(extra="allow")
"""Configuration so that extra properties may be available."""
status_code: t.Annotated[int, Field(validation_alias="statusCode")]
"""The status code of the response. This attribute is mapped to the :python:`"statusCode"` field of the response."""
status_code: t.Annotated[int, Field(validation_alias=AliasChoices("statusCode", "status"))]
"""The status code of the response. This attribute is mapped to the :python:`"statusCode"` or the
:python:`"status"` field of the response."""
code: str
"""Written equivalent for ``status_code``."""
message: str
Expand Down
837 changes: 415 additions & 422 deletions poetry.lock

Large diffs are not rendered by default.

26 changes: 12 additions & 14 deletions tests/test_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@

@pytest.fixture()
def realm(auth_client):
new_realm = auth_client.create_realm(next_random_string())
new_realm = auth_client.create_realm(next_random_string().lower())
yield new_realm
auth_client.delete_realm(new_realm)


@pytest.fixture()
def robot(auth_client, master_realm):
new_robot = auth_client.create_robot(next_random_string(), master_realm, next_random_string(length=64))
new_robot = auth_client.create_robot(next_random_string().lower(), master_realm, next_random_string(length=64))
yield new_robot
auth_client.delete_robot(new_robot)

Expand All @@ -39,7 +39,7 @@ def robot_includables():

@pytest.fixture()
def permission(auth_client):
new_permission = auth_client.create_permission(next_random_string())
new_permission = auth_client.create_permission(next_random_string().lower())
yield new_permission
auth_client.delete_permission(new_permission)

Expand All @@ -51,7 +51,7 @@ def permission_includables():

@pytest.fixture()
def role(auth_client):
new_role = auth_client.create_role(next_random_string())
new_role = auth_client.create_role(next_random_string().lower())
yield new_role
auth_client.delete_role(new_role)

Expand All @@ -75,7 +75,7 @@ def role_permission_includables():

@pytest.fixture()
def user(auth_client):
new_user = auth_client.create_user(name=next_random_string(), email=f"{next_random_string()}@test.com")
new_user = auth_client.create_user(name=next_random_string().lower(), email=f"{next_random_string()}@test.com")
yield new_user
auth_client.delete_user(new_user)

Expand Down Expand Up @@ -140,7 +140,7 @@ def robot_role_includables():

@pytest.fixture()
def client(auth_client, master_realm):
new_client = auth_client.create_client(name=next_random_string(), realm_id=master_realm)
new_client = auth_client.create_client(name=next_random_string().lower(), realm_id=master_realm)
yield new_client
auth_client.delete_client(client_id=new_client)

Expand All @@ -159,7 +159,7 @@ def test_get_realm_not_found(auth_client, realm):


def test_update_realm(auth_client, realm):
new_name = next_random_string()
new_name = next_random_string().lower()
new_realm = auth_client.update_realm(realm.id, name=new_name)

assert realm != new_realm
Expand All @@ -174,7 +174,6 @@ def test_find_realms(auth_client, realm):
assert [realm] == auth_client.find_realms(filter={"id": realm.id})


@pytest.mark.xfail(reason="realm is not included in this case")
def test_get_robot(auth_client, robot, robot_includables):
robot_get = auth_client.get_robot(robot)

Expand All @@ -187,7 +186,7 @@ def test_get_robot_not_found(auth_client, robot):


def test_update_robot(auth_client, robot):
new_name = next_random_string()
new_name = next_random_string().lower()
new_robot = auth_client.update_robot(robot.id, name=new_name)

assert robot != new_robot
Expand Down Expand Up @@ -238,7 +237,7 @@ def test_find_permissions(auth_client, permission, permission_includables):

@pytest.mark.xfail(reason="policy ids should be optional for creating permissions but are currently mandatory")
def test_update_permission(auth_client, permission):
new_name = next_random_string()
new_name = next_random_string().lower()
new_permission = auth_client.update_permission(permission.id, name=new_name)

assert permission != new_permission
Expand Down Expand Up @@ -274,7 +273,7 @@ def test_find_roles(auth_client, role, role_includables):


def test_update_role(auth_client, role):
new_name = next_random_string()
new_name = next_random_string().lower()
new_role = auth_client.update_role(role.id, name=new_name)

assert role != new_role
Expand Down Expand Up @@ -341,7 +340,7 @@ def test_find_users(auth_client, user, user_fields, user_includables):


def test_update_user(auth_client, user):
new_name = next_random_string()
new_name = next_random_string().lower()
new_user = auth_client.update_user(user.id, name=new_name)

assert user != new_user
Expand Down Expand Up @@ -470,7 +469,6 @@ def test_find_robot_roles(auth_client, robot_role, robot_role_includables):
assert all(includable in rr.model_fields_set for rr in robot_roles_find for includable in robot_role_includables)


@pytest.mark.xfail(reason="realm is not included in this case")
def test_get_client(auth_client, client, client_includables):
client_get = auth_client.get_client(client_id=client)

Expand Down Expand Up @@ -498,7 +496,7 @@ def test_find_clients(auth_client, client, client_includables):


def test_update_client(auth_client, client):
new_name = next_random_string()
new_name = next_random_string().lower()
new_client = auth_client.update_client(client_id=client, name=new_name)

assert client != new_client
Expand Down
28 changes: 6 additions & 22 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,20 +127,13 @@ def analysis_node_includables():


@pytest.fixture()
def analysis_code_bucket(core_client, storage_client, analysis):
bucket = storage_client.create_bucket(name=next_random_string())
analysis_bucket = core_client.create_analysis_bucket(
bucket_type=AnalysisBucketType.CODE,
analysis_id=analysis,
bucket_id=bucket,
)

assert analysis_bucket.type == AnalysisBucketType.CODE
def analysis_code_bucket(core_client, analysis):
analysis_buckets = core_client.find_analysis_buckets(filter={"analysis_id": analysis.id})
code_buckets = [bucket for bucket in analysis_buckets if bucket.type == AnalysisBucketType.CODE]

yield analysis_bucket
assert len(code_buckets) == 1

core_client.delete_analysis_bucket(analysis_bucket)
storage_client.delete_bucket(bucket)
return code_buckets[0]


@pytest.fixture(scope="session")
Expand Down Expand Up @@ -466,17 +459,8 @@ def test_build_analysis(core_client, configured_analysis):
)

def _wait_for_successful_build():
try:
analysis = core_client.send_analysis_command(analysis_id=configured_analysis.id, command="buildCheck")
except HubAPIError as e:
if "The analysis build process has already been successfully completed." in str(e):
analysis = core_client.get_analysis(analysis_id=configured_analysis.id)
else:
raise e
analysis = core_client.get_analysis(analysis_id=configured_analysis.id)
assert analysis.build_status == "executed"
# TODO: For some reason the Hub does not set the build_progress to 100 even if the analysis was successfully
# TODO: executed.
# TODO: assert analysis.build_progress == 100

assert_eventually(_wait_for_successful_build)

Expand Down
Loading