|
22 | 22 | orm_models as orm, # type: ignore # so we can access models easily |
23 | 23 | make_engine_from_config, # type: ignore |
24 | 24 | get_session_factory, # type: ignore |
| 25 | + search as db_search, |
25 | 26 | ) |
26 | 27 |
|
27 | 28 | if typing.TYPE_CHECKING: |
@@ -84,103 +85,34 @@ def lookup_station(self, name: str) -> orm.Station | None: |
84 | 85 | 'system name/station name' component. If the station does not |
85 | 86 | match a unique station, raises an AmbiguityError |
86 | 87 | """ |
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 |
97 | 102 |
|
98 | 103 | def lookup_system(self, name: str) -> orm.System | None: |
99 | 104 | """ Use the database to lookup a system, which accepts a name that |
100 | 105 | is either a unique system name (or partial of one), or in the |
101 | 106 | 'system name/station name' component. If the system does not |
102 | 107 | match a unique system, raises an AmbiguityError |
103 | 108 | """ |
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) |
113 | 112 |
|
114 | 113 | def lookup_place(self, name: str) -> orm.Station | orm.System | None: |
115 | 114 | """ 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 |
141 | 117 |
|
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