Skip to content

Commit

Permalink
Sorting latest and which by SemVer (#161)
Browse files Browse the repository at this point in the history
* make proper sorting

* fix bug

* codecov -- fail_ci_if_error: false
  • Loading branch information
aguschin authored May 27, 2022
1 parent 4926966 commit 22cf39e
Show file tree
Hide file tree
Showing 8 changed files with 173 additions and 92 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/check-test-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ jobs:
- name: "Upload coverage to Codecov"
uses: codecov/codecov-action@v2
with:
fail_ci_if_error: true
fail_ci_if_error: false
token: ${{ secrets.CODECOV_TOKEN }}
deploy:
name: PyPI Deploy
Expand Down
56 changes: 41 additions & 15 deletions gto/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,24 @@ def parse_tag(name: str):
def find_latest_version(
repo: Union[str, Repo],
name: str,
all: bool = False,
registered: bool = True,
):
"""Return latest version for artifact"""
return GitRegistry.from_repo(repo).latest(name)
return GitRegistry.from_repo(repo).latest(name, all=all, registered=registered)


def find_promotion(repo: Union[str, Repo], name: str, stage: str):
def find_versions_in_stage(
repo: Union[str, Repo],
name: str,
stage: str,
all: bool = False,
registered_only: bool = False,
):
"""Return version of artifact with specific stage active"""
return GitRegistry.from_repo(repo).which(name, stage, raise_if_not_found=False)
return GitRegistry.from_repo(repo).which(
name, stage, raise_if_not_found=False, all=all, registered_only=registered_only
)


def check_ref(repo: Union[str, Repo], ref: str):
Expand All @@ -155,13 +165,15 @@ def show(
all_branches=False,
all_commits=False,
truncate_hexsha=False,
registered_only=False,
):
return (
_show_versions(
repo,
name=name,
all_branches=all_branches,
all_commits=all_commits,
registered_only=registered_only,
table=table,
truncate_hexsha=truncate_hexsha,
)
Expand All @@ -170,6 +182,7 @@ def show(
repo,
all_branches=all_branches,
all_commits=all_commits,
registered_only=registered_only,
table=table,
truncate_hexsha=truncate_hexsha,
)
Expand All @@ -180,21 +193,27 @@ def _show_registry(
repo: Union[str, Repo],
all_branches=False,
all_commits=False,
registered_only=False,
table: bool = False,
truncate_hexsha: bool = False, # pylint: disable=unused-argument
):
"""Show current registry state"""

def format_hexsha(hexsha):
return hexsha[:7] if truncate_hexsha else hexsha

reg = GitRegistry.from_repo(repo)
stages = list(reg.get_stages())
models_state = {
o.name: {
"version": o.get_latest_version(registered=True).name
if o.get_latest_version(registered=True)
"version": format_hexsha(o.get_latest_version(registered_only=True).name)
if o.get_latest_version(registered_only=True)
else None,
"stage": {
name: o.get_promotions()[name].version
if name in o.get_promotions()
name: format_hexsha(
o.get_promotions(registered_only=registered_only)[name].version
)
if name in o.get_promotions(registered_only=registered_only)
else None
for name in stages
},
Expand All @@ -221,6 +240,7 @@ def _show_versions(
raw: bool = False,
all_branches=False,
all_commits=False,
registered_only=False,
table: bool = False,
truncate_hexsha: bool = False,
):
Expand All @@ -238,7 +258,9 @@ def format_hexsha(hexsha):
name,
all_branches=all_branches,
all_commits=all_commits,
).get_versions(include_non_explicit=True, include_discovered=True)
).get_versions(
include_non_explicit=not registered_only, include_discovered=True
)
]
if not table:
return versions
Expand All @@ -251,7 +273,15 @@ def format_hexsha(hexsha):
v["stage"] = v["stage"]["stage"]
v["commit_hexsha"] = format_hexsha(v["commit_hexsha"])
v["ref"] = v["tag"] or v["commit_hexsha"]
for key in "enrichments", "discovered", "tag", "commit_hexsha", "name":
for key in (
"enrichments",
"discovered",
"tag",
"commit_hexsha",
"name",
"message",
"author_email",
):
v.pop(key)
# v["enrichments"] = [e["source"] for e in v["enrichments"]]
v = OrderedDict(
Expand All @@ -262,10 +292,6 @@ def format_hexsha(hexsha):
return versions_, "keys"


def _is_ascending(sort):
return sort in {"asc", "Asc", "ascending", "Ascending"}


def describe(
repo: Union[str, Repo], name: str, rev: str = None
) -> List[EnrichmentInfo]:
Expand All @@ -286,7 +312,7 @@ def history( # pylint: disable=too-many-locals
# action: str = None,
all_branches=False,
all_commits=False,
sort: str = "desc",
ascending: bool = False,
table: bool = False,
truncate_hexsha: bool = False,
):
Expand Down Expand Up @@ -357,7 +383,7 @@ def format_hexsha(hexsha):
commits + registration + promotion,
key=lambda x: (x["timestamp"], events_order[x["event"]]),
)
if _is_ascending(sort):
if ascending:
events.reverse()
if artifact:
events = [event for event in events if event["artifact"] == artifact]
Expand Down
113 changes: 74 additions & 39 deletions gto/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from pydantic import BaseModel

from gto.config import RegistryConfig
from gto.constants import Action
from gto.constants import Action, VersionSort
from gto.ext import Enrichment
from gto.versions import SemVer

Expand Down Expand Up @@ -75,42 +75,82 @@ def __repr__(self) -> str:
stages = ", ".join(f"'{l}'" for l in self.unique_stages)
return f"Artifact(versions=[{versions}], stages=[{stages}])"

def get_latest_version(self, registered=False) -> Optional[BaseVersion]:
versions = sorted(
(
v
for v in self.versions
if not v.discovered and (not registered or v.is_registered)
),
key=lambda x: x.created_at,
def get_versions(
self,
include_non_explicit=False,
include_discovered=False,
sort=VersionSort.SemVer,
ascending=False,
) -> List[BaseVersion]:
sort = sort if isinstance(sort, VersionSort) else VersionSort[sort]
all_versions = [
v
for v in self.versions
if (v.is_registered and not v.discovered)
or (include_discovered and v.discovered)
or (include_non_explicit and not v.is_registered)
]
if sort == VersionSort.SemVer:
# sorting SemVer versions in a right way
versions = sorted(
(v for v in all_versions if not v.discovered and v.is_registered),
key=lambda x: x.version,
)
# sorting hexsha versions alphabetically
if include_non_explicit:
versions.extend(
sorted(
(
v
for v in all_versions
if not v.discovered and not v.is_registered
),
key=lambda x: x.name,
)
)
else:
versions = sorted(
(
v
for v in all_versions
if not v.discovered and (include_non_explicit or v.is_registered)
),
key=lambda x: x.created_at,
)
if ascending:
versions.reverse()
return versions

def get_latest_version(
self, registered_only=False, sort=VersionSort.SemVer
) -> Optional[BaseVersion]:
versions = self.get_versions(
include_non_explicit=not registered_only, sort=sort
)
if versions:
return versions[-1]
return None

def get_promotions(self) -> Dict[str, BasePromotion]:
stages: Dict[str, BasePromotion] = {}
# semver
versions = sorted(
(v for v in self.versions if v.is_registered),
key=lambda x: x.version,
reverse=True,
)
# TODO: regular commits - these should be sorted by stage tag creation maybe?
# E.g. when you created "rf#prod" tag, then you created a version.
# It's probably should be a flag on CLI that will tell how to sort promoted for return.
versions.extend(
sorted(
(v for v in self.versions if not v.is_registered),
key=lambda x: x.created_at,
reverse=True,
)
def get_promotions(
self, all=False, registered_only=False, sort=VersionSort.SemVer
) -> Dict[str, Union[BasePromotion, List[BasePromotion]]]:
versions = self.get_versions(
include_non_explicit=not registered_only, sort=sort
)
if sort == VersionSort.Timestamp:
# for this sort we need to sort not versions, as above ^
# but promotions themselves
raise NotImplementedError("Sorting by timestamp is not implemented yet")
stages = {} # type: ignore
for version in versions:
promotion = version.stage
if promotion:
stages[promotion.stage] = stages.get(promotion.stage) or promotion
return stages
stages[promotion.stage] = stages.get(promotion.stage, []) + [promotion]
# else:
# stages[promotion.stage] = stages.get(promotion.stage) or promotion
if all:
return stages
return {stage: promotions[-1] for stage, promotions in stages.items()}

def add_version(self, version: BaseVersion):
self.versions.append(version)
Expand Down Expand Up @@ -159,15 +199,6 @@ def discovered(self):
# ) -> List[BaseVersion]:
# ...

def get_versions(self, include_non_explicit=False, include_discovered=False):
return [
v
for v in self.versions
if (v.is_registered and not v.discovered)
or (include_discovered and v.discovered)
or (include_non_explicit and not v.is_registered)
]

def find_version(
self,
name: str = None,
Expand Down Expand Up @@ -245,9 +276,13 @@ def find_commit(self, name, version):
.commit_hexsha
)

def which(self, name, stage, raise_if_not_found=True):
def which(
self, name, stage, raise_if_not_found=True, all=False, registered_only=False
):
"""Return stage active in specific stage"""
promoted = self.find_artifact(name).get_promotions()
promoted = self.find_artifact(name).get_promotions(
all=all, registered_only=registered_only
)
if stage in promoted:
return promoted[stage]
if raise_if_not_found:
Expand Down
Loading

0 comments on commit 22cf39e

Please sign in to comment.