Skip to content

Commit

Permalink
add moves to diff route, change diff route
Browse files Browse the repository at this point in the history
  • Loading branch information
lunakv committed Jun 12, 2023
1 parent 5804e0d commit e8de00a
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 67 deletions.
43 changes: 12 additions & 31 deletions app/database/operations.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import datetime
from typing import Tuple, Type
from typing import Type

from sqlalchemy import select
from sqlalchemy.orm import Session, aliased
Expand Down Expand Up @@ -64,17 +64,20 @@ def set_pending(db: Session, resource: str, link: str) -> None:
db.add(PendingRedirect(resource=resource, link=link))


def get_cr_diff(db: Session, old_code: str, new_code: str) -> CrDiff | None:
def get_cr_diff(db: Session, old_code: str | None, new_code: str | None) -> CrDiff | None:
src = aliased(Cr)
dst = aliased(Cr)

stmt = (
select(CrDiff)
.join(src, CrDiff.source)
.join(dst, CrDiff.dest)
.where(src.set_code == old_code)
.where(dst.set_code == new_code)
)
stmt = select(CrDiff).join(src, CrDiff.source).join(dst, CrDiff.dest)

if not old_code and not new_code:
stmt = stmt.order_by(CrDiff.creation_day.desc()).limit(1)
else:
if old_code:
stmt = stmt.where(src.set_code == old_code)
if new_code:
stmt = stmt.where(dst.set_code == new_code)

return db.execute(stmt).scalar_one_or_none()


Expand Down Expand Up @@ -137,28 +140,6 @@ def get_pending_mtr_diff(db: Session) -> PendingMtrDiff:
return db.execute(select(PendingMtrDiff).join(PendingMtrDiff.dest)).scalar_one_or_none()


def get_latest_cr_diff_code(db: Session) -> (str, str):
stmt = select(CrDiff).join(CrDiff.dest).order_by(Cr.creation_day.desc())
diff: CrDiff = db.execute(stmt).scalars().first()
return diff.source.set_code, diff.dest.set_code


def get_cr_diff_codes(db: Session, old_code: str | None, new_code: str | None) -> Tuple[str, str] | None:
stmt = select(CrDiff)
if old_code:
stmt = stmt.join(Cr, CrDiff.source).where(Cr.set_code == old_code)
elif new_code:
stmt = stmt.join(Cr, CrDiff.dest).where(Cr.set_code == new_code)
else:
return None

diff: CrDiff = db.execute(stmt).scalar_one_or_none()
if not diff:
return None

return diff.source.set_code, diff.dest.set_code


def get_pending_cr_diff(db: Session) -> PendingCrDiff | None:
return db.execute(select(PendingCrDiff)).scalar_one_or_none()

Expand Down
13 changes: 8 additions & 5 deletions app/difftool/diffsorter.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def diff_to_sort_key(self, item) -> int:
pass

@abstractmethod
def move_to_sort_key(self, key: tuple[str, str]) -> int:
def move_to_sort_key(self, key: tuple[str, str]) -> int | str:
"""
Method for calculating the sort key of a given move item
"""
Expand Down Expand Up @@ -63,7 +63,10 @@ def move_to_sort_key(self, item: tuple[str, str]) -> int:

class MtrDiffSorter(DiffSorter):
def diff_to_sort_key(self, item: dict) -> int:
comparison_source = item.get("new") or item.get("old") or {}
s = comparison_source.get("section") or 0
ss = comparison_source.get("subsection") or 0
return s * 100 + ss
comparison_source = item.get("new") or item.get("old") or {}
s = comparison_source.get("section") or 0
ss = comparison_source.get("subsection") or 0
return s * 100 + ss

def move_to_sort_key(self, key: tuple[str, str]) -> str:
return key[1]
52 changes: 22 additions & 30 deletions app/routers/diff.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from datetime import date
from typing import Union

from fastapi import APIRouter, Depends, HTTPException, Path, Response
from fastapi import APIRouter, Depends, HTTPException, Path, Query, Response
from fastapi.responses import RedirectResponse
from sqlalchemy.orm import Session

Expand All @@ -22,32 +22,41 @@ class MtrDiffError(Error):


@router.get(
"/cr/{old}-{new}",
"/cr",
summary="CR diff",
response_model=Union[CrDiffError, CRDiff],
responses={200: {"model": CRDiff}, 404: {"model": CrDiffError}},
)
async def cr_diff(
response: Response,
old: str = Path(description="Set code of the old set.", min_length=3, max_length=5),
new: str = Path(description="Set code of the new set", min_length=3, max_length=5),
old: str | None = Query(None, description="Set code of the old set.", min_length=3, max_length=5),
new: str | None = Query(None, description="Set code of the new set", min_length=3, max_length=5),
db: Session = Depends(get_db),
):
"""
Returns a diff of the CR between the two specified sets. Diffs only exist for neighboring CR releases. The path
parameters are **not** case sensitive.
Returns a diff of the CR between the two specified sets. Diffs only exist for neighboring CR releases.
The set code query parameters are **not** case sensitive. If both are supplied, the server attempts to find a
diff between exactly those two sets. If only one is supplied, a diff with that set at the provided end is found.
If neither is supplied, the latest CR diff is returned.
The `changes` property is an ordered array of diff items, with each item consisting of the `old` and `new`
versions of a rule. If a new rule is added, `old` is `null`. If an old rule is deleted, `new` is `null`.
Otherwise, the differing parts of the `ruleText` string are wrapped between "<<<<" and ">>>>". Rules with
identical text but changed rule number aren't part of this array, and neither are rules whose only change in text
was a reference to a renumbered rule.
`source_set` and `dest_set` contain full names of the sets being diffed, and the `nav` property stores set codes
of diffs immediately preceding/following this one
The `moves` property contains an ordered array representing the rules that changed their number but didn't change
their content. This property may be `null` or missing. If present, each element in the array is a two-item tuple
of strings, containing the old and new numbers for the given rule. No items that are part of the `changes`
property are included here. In particular, this means that both elements of each two-tuple are always valid strings.
`sourceSet` and `destSet` contain full names of the sets being diffed, and `sourceCode` and `destCode` contain
the canonical set codes of those sets.
"""
old = old.upper()
new = new.upper()
old = old and old.upper()
new = new and new.upper()

diff = ops.get_cr_diff(db, old, new)
if diff is None:
response.status_code = 404
Expand All @@ -57,34 +66,17 @@ async def cr_diff(
"new": new,
}

def format_nav(codes):
if not codes:
return None
return {"old": codes[0], "new": codes[1]}

nav = {
"next": format_nav(ops.get_cr_diff_codes(db, new, None)),
"prev": format_nav(ops.get_cr_diff_codes(db, None, old)),
}

return {
"creationDay": diff.creation_day,
"changes": diff.changes,
"sourceSet": diff.source.set_name,
"sourceCode": diff.source.set_code,
"destSet": diff.dest.set_name,
"nav": nav,
"destCode": diff.dest.set_code,
"moves": diff.moves,
}


@router.get("/cr/", status_code=307, summary="Latest CR diff", responses={307: {"content": None}})
async def latest_cr_diff(db: Session = Depends(get_db)):
"""
Redirects to the latest CR diff available
"""
old, new = ops.get_latest_cr_diff_code(db)
return RedirectResponse(f"./{old}-{new}")


@router.get(
"/mtr/{effective_date}",
summary="MTR diff",
Expand Down
4 changes: 3 additions & 1 deletion app/utils/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,11 @@ class CRDiffNav:
class CRDiff:
creation_day: datetime.date = Field(..., alias="creationDay")
source_set: str = Field(..., alias="sourceSet")
source_code: str = Field(..., alias="sourceCode")
dest_set: str = Field(..., alias="destSet")
dest_code: str = Field(..., alias="destCode")
changes: list[CRDiffItem] = Field(...)
nav: CRDiffNav = Field(..., description="Connections to neighboring diffs")
moves: list[tuple[str, str]] = Field(description="List of moved rules")


@dataclass(config=Config)
Expand Down

0 comments on commit e8de00a

Please sign in to comment.