Skip to content

Commit a9701a5

Browse files
committed
feat: wire db.search into tradeorm
1 parent 7d013d5 commit a9701a5

File tree

1 file changed

+21
-89
lines changed

1 file changed

+21
-89
lines changed

tradedangerous/tradeorm.py

Lines changed: 21 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
orm_models as orm, # type: ignore # so we can access models easily
2323
make_engine_from_config, # type: ignore
2424
get_session_factory, # type: ignore
25+
search as db_search,
2526
)
2627

2728
if typing.TYPE_CHECKING:
@@ -84,103 +85,34 @@ def lookup_station(self, name: str) -> orm.Station | None:
8485
'system name/station name' component. If the station does not
8586
match a unique station, raises an AmbiguityError
8687
"""
87-
if "%" in name:
88-
raise TradeException("wildcards ('%') are not supported in station names")
89-
if "/" not in name:
90-
if (station := self._station_lookup(name, exact=True, partial=False)):
91-
return station
92-
if self._system_lookup(name, exact=True, partial=False):
93-
raise SystemNotStationError(f'"{name}" is a system name, use "/{name}" if you meant it as a station')
94-
name = "/" + name
95-
station: orm.Station | None = self.lookup_place(name)
96-
return station
88+
if (fast_candidate := db_search.fast_find_sub(self.session, "Station", name, orm.Station, orm.System)):
89+
if isinstance(fast_candidate, orm.Station):
90+
return fast_candidate
91+
if isinstance(fast_candidate, orm.System) and fast_candidate.name.lower() == name.lower():
92+
raise TradeException(
93+
f"expected a station, '{name}' is a system."
94+
f" you can use '/{name}' to ignore the system match."
95+
)
96+
97+
fuzzy_candidate = db_search.fuzzy_like(self.session, "Station", name, table=orm.Station, group_table=orm.System)
98+
if isinstance(fuzzy_candidate, orm.Station):
99+
return fuzzy_candidate
100+
101+
return None
97102

98103
def lookup_system(self, name: str) -> orm.System | None:
99104
""" Use the database to lookup a system, which accepts a name that
100105
is either a unique system name (or partial of one), or in the
101106
'system name/station name' component. If the system does not
102107
match a unique system, raises an AmbiguityError
103108
"""
104-
if "%" in name:
105-
raise TradeException("wildcards ('%') are not supported in system names")
106-
system_name, _, _ = name.partition("/")
107-
if not system_name:
108-
raise TradeException(f"system name required for system lookup, got {name}")
109-
result: orm.Station | orm.System | None = self.lookup_place(system_name)
110-
if isinstance(result, orm.Station):
111-
return result.system
112-
return result
109+
if (system := db_search.fast_find(self.session, "System", name, table=orm.System)):
110+
return system
111+
return db_search.fuzzy_like(self.session, "System", name, table=orm.System, group_table=None)
113112

114113
def lookup_place(self, name: str) -> orm.Station | orm.System | None:
115114
""" Using a "[<system>]/[<station>]" style name, look up either a Station or a System."""
116-
if "%" in name:
117-
raise TradeException("wildcards ('%') are not supported in names")
118-
sys_name, slashed, stn_name = name.partition("/")
119-
if not slashed:
120-
if stn_name:
121-
station: orm.Station | None = self._station_lookup(stn_name, exact=True, partial=False)
122-
if station:
123-
return station
124-
if sys_name:
125-
system: orm.System | None = self._system_lookup(sys_name, exact=True, partial=False)
126-
if system:
127-
return system
128-
129-
if sys_name:
130-
system = self._system_lookup(sys_name)
131-
if not system:
132-
raise TradeException(f"unknown system: {sys_name}")
133-
if not stn_name:
134-
return system
135-
136-
# Now we match the list of station names for this system.
137-
stmt = self.session.query(orm.Station).filter(orm.Station.system_id == system.system_id).filter(orm.Station.name == stn_name)
138-
results = stmt.all()
139-
if len(results) == 1:
140-
return results[0]
115+
if (candidate := db_search.fast_find_sub(self.session, "Place", name, orm.Station, orm.System)):
116+
return candidate
141117

142-
stmt = self.session.query(orm.Station).filter(orm.Station.system_id == system.system_id).filter(orm.Station.name.like(f"%{stn_name}%"))
143-
results = stmt.all()
144-
if not results:
145-
raise TradeException(f"no station in {sys_name} matches '{stn_name}'")
146-
if len(results) > 1:
147-
raise AmbiguityError("Station", stn_name, [s.name for s in results])
148-
return results[0]
149-
150-
station = self._station_lookup(stn_name, exact=False)
151-
return station
152-
153-
def _system_lookup(self, name: str, *, exact: bool = True, partial: bool = True) -> orm.System | None:
154-
""" Look up a model by exact name match. """
155-
assert exact or partial, "at least one of exact or partial must be True"
156-
results: list[orm.System] | None = None
157-
if exact:
158-
results = self.session.query(orm.System).filter(orm.System.name == name).all()
159-
if len(results) == 1:
160-
partial = False
161-
if partial:
162-
like_pattern = f"%{name}%"
163-
results = self.session.query(orm.System).filter(orm.System.name.like(like_pattern)).all()
164-
165-
if not results:
166-
return None
167-
if len(results) > 1:
168-
raise AmbiguityError("System", name, results, key=lambda s: s.dbname())
169-
return results[0]
170-
171-
def _station_lookup(self, name: str, *, exact: bool = True, partial: bool = True) -> orm.Station | None:
172-
""" Look up a model by exact name match. """
173-
assert exact or partial, "at least one of exact or partial must be True"
174-
results: list[orm.Station] | None = None
175-
if exact:
176-
results = self.session.query(orm.Station).filter(orm.Station.name == name).all()
177-
if len(results) == 1:
178-
partial = False
179-
if partial:
180-
like_pattern = f"%{name}%"
181-
results = self.session.query(orm.Station).filter(orm.Station.name.like(like_pattern)).all()
182-
if not results:
183-
return None
184-
if len(results) > 1:
185-
raise AmbiguityError("Station", name, results, key=lambda s: s.dbname())
186-
return results[0]
118+
return db_search.fuzzy_like(self.session, "Place", name, orm.Station, orm.System)

0 commit comments

Comments
 (0)