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
feat: [VRD-818] Implement BuildScan
class
#3757
Changes from 23 commits
f88cd57
70f0b61
3500f4e
b458655
d50ba38
21674ff
a05c5df
bf3b056
0dd71c5
bcacbab
974d123
bb73783
8bff7cd
81cd112
7877098
7ce7ac6
26bc462
d70188d
d75585d
3c5507d
ed450bb
8b60dba
2cdd9bb
5777fa4
6d7c08b
8399340
be4e315
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
from hypothesis import given, HealthCheck, settings | ||
import pytest | ||
|
||
from tests.unit_tests.strategies import build_scan_dict | ||
|
||
from verta._internal_utils import time_utils | ||
from verta.endpoint.build import BuildScan, ScanProgressEnum, ScanStatusEnum | ||
|
||
|
||
@given(build_scan_dict=build_scan_dict()) | ||
def test_instantiation(build_scan_dict): | ||
"""Verify a BuildScan object can be instantated from a dict.""" | ||
build_scan = BuildScan(build_scan_dict) | ||
|
||
assert build_scan.date_updated == time_utils.datetime_from_iso( | ||
build_scan_dict["date_updated"], | ||
) | ||
assert build_scan.progress == ScanProgressEnum(build_scan_dict["scan_status"]) | ||
if build_scan.progress == ScanProgressEnum.SCANNED: | ||
assert build_scan.passed == (build_scan.status == ScanStatusEnum.SAFE) | ||
assert build_scan.status == ScanStatusEnum(build_scan_dict["safety_status"]) | ||
else: | ||
assert build_scan.passed is False | ||
assert build_scan.status is None |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
# -*- coding: utf-8 -*- | ||
|
||
from datetime import datetime | ||
from enum import Enum | ||
from typing import Optional | ||
|
||
from verta._internal_utils import _utils, time_utils | ||
|
||
|
||
class ScanProgressEnum(str, Enum): | ||
"""The current progress of a build scan. | ||
|
||
For all intents and purposes, this can be treated as a :class:`str`. | ||
|
||
Examples | ||
-------- | ||
.. code-block:: python | ||
|
||
assert build.get_scan().progress == "scanned" | ||
|
||
""" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
UNSCANNED = "unscanned" | ||
SCANNING = "scanning" | ||
SCANNED = "scanned" | ||
ERROR = "error" | ||
|
||
|
||
class ScanStatusEnum(str, Enum): | ||
"""The result of a build scan. | ||
|
||
For all intents and purposes, this can be treated as a :class:`str`. | ||
|
||
Examples | ||
-------- | ||
.. code-block:: python | ||
|
||
assert build.get_scan().status == "safe" | ||
|
||
""" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
UNKNOWN = "unknown" | ||
SAFE = "safe" | ||
UNSAFE = "unsafe" | ||
|
||
|
||
class BuildScan: | ||
"""A scan of a Verta model build. | ||
|
||
There should not be a need to instantiate this class directly; please use | ||
:meth:`Build.get_scan() <verta.endpoint.build.Build.get_scan>` instead. | ||
|
||
Attributes | ||
---------- | ||
date_updated : timezone-aware :class:`~datetime.datetime` | ||
The date and time when this scan was performed/updated. | ||
progress : :class:`ScanProgressEnum` | ||
The current progress of this scan. | ||
status : :class:`ScanStatusEnum` or None | ||
The result of this scan. ``None`` is returned if this scan is not yet | ||
finished, and therefore has no status. | ||
passed : bool | ||
Whether this scan finished and passed. This property is for | ||
convenience, equivalent to | ||
|
||
.. code-block:: python | ||
|
||
build_scan.status == "safe" | ||
|
||
""" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note |
||
|
||
def __init__(self, json): | ||
self._json = json | ||
|
||
def __repr__(self): | ||
detail_str = f'progress "{self.progress.value}"' | ||
if self.status is not None: | ||
detail_str += f', status "{self.status.value}"' | ||
|
||
return f"<BuildScan ({detail_str})>" | ||
|
||
@classmethod | ||
def _get(cls, conn: _utils.Connection, build_id: int): | ||
url = f"{conn.scheme}://{conn.socket}/api/v1/deployment/builds/{build_id}/scan" | ||
response = _utils.make_request("GET", url, conn) | ||
_utils.raise_for_http_error(response) | ||
|
||
return cls(response.json()) | ||
|
||
@property | ||
def date_updated(self) -> datetime: | ||
return time_utils.datetime_from_iso(self._json["date_updated"]) | ||
|
||
@property | ||
def progress(self) -> ScanProgressEnum: | ||
return ScanProgressEnum(self._json["scan_status"]) | ||
|
||
@property | ||
def status(self) -> Optional[ScanStatusEnum]: | ||
if self.progress != ScanProgressEnum.SCANNED: | ||
return None | ||
return ScanStatusEnum(self._json["safety_status"]) | ||
|
||
@property | ||
def passed(self) -> bool: | ||
return self.status == ScanStatusEnum.SAFE |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Enum
variants are technically class members, and there isn't a clean way to attach meaningful docstrings to them, so we have to clumsily tell our documentation, "If a class's name ends withEnum
, go ahead and render its undocumented members" as a bit of a hack.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This bit gives you the
OPTION = 'option'
style listing of all the possible options at the end of the doc string I assume?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes