Skip to content

Commit

Permalink
deregister objects after being merged into another
Browse files Browse the repository at this point in the history
  • Loading branch information
iiiii7d committed Jun 2, 2024
1 parent c923ded commit ea1406f
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 44 deletions.
4 changes: 4 additions & 0 deletions gatelogue-aggregator/src/gatelogue_aggregator/downloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ def get_url(url: str, cache: Path, timeout: int = 60) -> str:
status = rich.status.Status(f"Downloading {url}")
status.start()
response = requests.get(url, timeout=timeout).text
try:
response = response.encode("latin").decode("utf-8")
except (UnicodeEncodeError, UnicodeDecodeError):
pass
status.stop()
cache.parent.mkdir(parents=True, exist_ok=True)
cache.touch()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def __init__(self, cache_dir: Path = DEFAULT_CACHE_DIR, timeout: int = DEFAULT_T
"https://docs.google.com/spreadsheets/d/1wzvmXHQZ7ee7roIvIrJhkP6oCegnB8-nefWpd8ckqps/export?format=csv&gid=248317803",
cache1,
timeout=timeout,
).encode("latin").decode("utf-8")
)
df = pd.read_csv(cache1, header=1)

df.rename(
Expand All @@ -40,7 +40,7 @@ def __init__(self, cache_dir: Path = DEFAULT_CACHE_DIR, timeout: int = DEFAULT_T
"https://docs.google.com/spreadsheets/d/1wzvmXHQZ7ee7roIvIrJhkP6oCegnB8-nefWpd8ckqps/export?format=csv&gid=379342597",
cache2,
timeout=timeout,
).encode("latin").decode("utf-8")
)
df2 = pd.read_csv(cache2, header=1)

df2.rename(
Expand Down
74 changes: 53 additions & 21 deletions gatelogue-aggregator/src/gatelogue_aggregator/types/air.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

import msgspec

from gatelogue_aggregator.types.base import IdObject, MergeableObject, Sourced, ToSerializable
from gatelogue_aggregator.types.base import IdObject, MergeableObject, Sourced, ToSerializable, BaseContext


class Flight(IdObject, ToSerializable, kw_only=True):
Expand All @@ -27,7 +27,14 @@ def ctx(self, ctx: AirContext):
ctx.flight.append(self)

@override
def update(self):
def de_ctx(self, ctx: AirContext):
try:
ctx.flight.remove(self)
except ValueError:
pass

@override
def update(self, ctx: AirContext):
new_gates = []
for gate in self.gates:
try:
Expand All @@ -42,7 +49,7 @@ def update(self):
elif existing_gate.v.code is not None and gate.v.code is None:
gate.v.flights = [a for a in gate.v.flights if a.v != self]
elif existing_gate.v.code == gate.v.code:
existing_gate.merge(gate)
existing_gate.merge(ctx, gate)
self.gates = [v for _, v in {str(a.v.id): a for a in new_gates}.items()]

for gate in self.gates:
Expand All @@ -54,14 +61,15 @@ def update(self):
def equivalent(self, other: Self) -> bool:
return len(self.codes.intersection(other.codes)) != 0 and self.airline.equivalent(other.airline)

def merge(self, other: Self):
def merge(self, ctx: AirContext, other: Self):
if other.id != self.id:
other.id.id = self.id
other.de_ctx(ctx)
else:
return
self.codes.update(other.codes)
self.airline.merge(other.airline)
MergeableObject.merge_lists(self.gates, other.gates)
self.airline.merge(ctx, other.airline)
MergeableObject.merge_lists(ctx, self.gates, other.gates)


class Airport(IdObject, ToSerializable, kw_only=True):
Expand Down Expand Up @@ -97,24 +105,32 @@ def ctx(self, ctx: AirContext):
ctx.airport.append(self)

@override
def update(self):
def de_ctx(self, ctx: AirContext):
try:
ctx.airport.remove(self)
except ValueError:
pass

@override
def update(self, ctx: AirContext):
for gate in self.gates:
gate.v.airport = self.source(gate)
self.gates = [v for _, v in {str(a.v.id): a for a in self.gates}.items()]

def equivalent(self, other: Self) -> bool:
return self.code == other.code

def merge(self, other: Self):
def merge(self, ctx: AirContext, other: Self):
if other.id != self.id:
other.id.id = self.id
other.de_ctx(ctx)
else:
return
self.name = self.name or other.name
self.world = self.world or other.world
self.coordinates = self.coordinates or other.coordinates
self.link = self.link or other.link
MergeableObject.merge_lists(self.gates, other.gates)
MergeableObject.merge_lists(ctx, self.gates, other.gates)


class Gate(IdObject, ToSerializable, kw_only=True):
Expand Down Expand Up @@ -147,7 +163,14 @@ def ctx(self, ctx: AirContext):
ctx.gate.append(self)

@override
def update(self):
def de_ctx(self, ctx: AirContext):
try:
ctx.gate.remove(self)
except ValueError:
pass

@override
def update(self, ctx: AirContext):
for flight in self.flights:
if self not in (o.v for o in flight.v.gates):
flight.v.gates.append(self.source(flight))
Expand All @@ -158,15 +181,16 @@ def update(self):
def equivalent(self, other: Self) -> bool:
return self.code == other.code and self.airport.equivalent(other.airport)

def merge(self, other: Self):
def merge(self, ctx: AirContext, other: Self):
if other.id != self.id:
other.id.id = self.id
other.de_ctx(ctx)
else:
return
self.size = self.size or other.size
self.airline = self.airline or other.airline
MergeableObject.merge_lists(self.flights, other.flights)
self.airport.merge(other.airport)
MergeableObject.merge_lists(ctx, self.flights, other.flights)
self.airport.merge(ctx, other.airport)


class Airline(IdObject, ToSerializable, kw_only=True):
Expand All @@ -193,24 +217,32 @@ def ctx(self, ctx: AirContext):
ctx.airline.append(self)

@override
def update(self):
def de_ctx(self, ctx: AirContext):
try:
ctx.airline.remove(self)
except ValueError:
pass

@override
def update(self, ctx: AirContext):
for flight in self.flights:
flight.v.airline = self.source(flight)
self.flights = [v for _, v in {str(a.v.id): a for a in self.flights}.items()]

def equivalent(self, other: Self) -> bool:
return self.name == other.name

def merge(self, other: Self):
def merge(self, ctx: AirContext, other: Self):
if other.id != self.id:
other.id.id = self.id
other.de_ctx(ctx)
else:
return
MergeableObject.merge_lists(self.flights, other.flights)
MergeableObject.merge_lists(ctx, self.flights, other.flights)
self.link = self.link or other.link


class AirContext(ToSerializable):
class AirContext(BaseContext):
__slots__ = ("flight", "airport", "gate", "airline")
flight: list[Flight]
airport: list[Airport]
Expand Down Expand Up @@ -257,13 +289,13 @@ def get_airline(self, **query) -> Airline:

def update(self):
for o in self.flight:
o.update()
o.update(self)
for o in self.airport:
o.update()
o.update(self)
for o in self.gate:
o.update()
o.update(self)
for o in self.airline:
o.update()
o.update(self)

@override
class SerializableClass(msgspec.Struct):
Expand Down
33 changes: 22 additions & 11 deletions gatelogue-aggregator/src/gatelogue_aggregator/types/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,20 +38,20 @@ class MergeableObject:
def equivalent(self, other: Self) -> bool:
raise NotImplementedError

def merge(self, other: Self):
def merge(self, ctx: BaseContext, other: Self):
raise NotImplementedError

def merge_if_equivalent(self, other: Self) -> bool:
def merge_if_equivalent(self, ctx: BaseContext, other: Self) -> bool:
if self.equivalent(other):
self.merge(other)
self.merge(ctx, other)
return True
return False

@staticmethod
def merge_lists[T: MergeableObject](self: list[T], other: list[T]):
def merge_lists[T: MergeableObject](ctx: BaseContext, self: list[T], other: list[T]):
for o in other:
for s in self:
if s.merge_if_equivalent(o):
if s.merge_if_equivalent(ctx, o):
break
else:
self.append(o)
Expand All @@ -60,10 +60,13 @@ def merge_lists[T: MergeableObject](self: list[T], other: list[T]):
class IdObject(msgspec.Struct, MergeableObject, kw_only=True):
id: ID = msgspec.field(default_factory=ID)

def ctx(self, ctx: Context):
def ctx(self, ctx: BaseContext):
raise NotImplementedError

def update(self):
def de_ctx(self, ctx: BaseContext):
raise NotImplementedError

def update(self, ctx: BaseContext):
raise NotImplementedError

def source(self, source: Sourced | Source) -> Sourced[Self]:
Expand Down Expand Up @@ -101,9 +104,9 @@ def source(self, source: Sourced | Source) -> Self:
def equivalent(self, other: Self) -> bool:
return self.v.equivalent(other.v) if isinstance(self.v, MergeableObject) else self.v == other.v

def merge(self, other: Self):
def merge(self, ctx: BaseContext, other: Self):
if isinstance(self.v, MergeableObject):
self.v.merge(other.v)
self.v.merge(ctx, other.v)
self.s.update(other.s)


Expand All @@ -114,14 +117,20 @@ def __init__(self):
rich.print(f"[yellow]Retrieving from {self.name}")


class BaseContext(ToSerializable):
pass


def search_all(regex: re.Pattern[str], text: str) -> Generator[re.Match[str], None, None]:
pos = 0
while (match := regex.search(text, pos)) is not None:
pos = match.end()
yield match


def process_code(s: str) -> str:
def process_code[T: (str, None)](s: T) -> T:
if s is None:
return None
res = ""
hyphen = False
for match in search_all(re.compile(r"\d+|[A-Za-z]+|[^\dA-Za-z]+"), str(s).strip()):
Expand All @@ -142,7 +151,9 @@ def process_code(s: str) -> str:
return res


def process_airport_code(s: str) -> str:
def process_airport_code[T: (str, None)](s: T) -> T:
if s is None:
return None
s = str(s).upper()
if len(s) == 4 and s[3] == "T":
return s[:3]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ def from_sources(cls, sources: Iterable[Source]) -> Self:
self = cls()
for source in rich.progress.track(sources, f"[yellow]Merging sources: {', '.join(s.name for s in sources)}"):
if isinstance(source, AirContext):
MergeableObject.merge_lists(self.flight, source.flight)
MergeableObject.merge_lists(self.airport, source.airport)
MergeableObject.merge_lists(self.gate, source.gate)
MergeableObject.merge_lists(self.airline, source.airline)
MergeableObject.merge_lists(self, self.flight, source.flight)
MergeableObject.merge_lists(self, self.airport, source.airport)
MergeableObject.merge_lists(self, self.gate, source.gate)
MergeableObject.merge_lists(self, self.airline, source.airline)
return self

def update(self):
Expand Down
16 changes: 10 additions & 6 deletions gatelogue-client/src/views/airport/Gate.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@ const props = defineProps<{
const gate = computed(
() => props.gate ?? gatelogueData.value!.gate[props.gateId]!,
);
const airline = computed(() =>
gate.value.airline ??
(gate.value.code && gate.value.code !== "?" && gate.value.flights.length > 0)
? gatelogueData.value!.flight[gate.value.flights[0].v]!.airline
: undefined,
);
const airline = computed(() => {
if (gate.value.airline) return gate.value.airline;
if (
gate.value.code &&
gate.value.code !== "?" &&
gate.value.flights.length > 0
)
return gatelogueData.value!.flight[gate.value.flights[0].v]!.airline;
return undefined;
});
</script>

<template>
Expand Down

0 comments on commit ea1406f

Please sign in to comment.