Skip to content

Commit 5e0505c

Browse files
committed
Cont'd
1 parent 5c4e541 commit 5e0505c

File tree

4 files changed

+102
-43
lines changed

4 files changed

+102
-43
lines changed

webtools/app.py

Lines changed: 46 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import string
99
import sys
1010
import traceback
11+
from http import HTTPStatus
1112
from importlib.metadata import PackageNotFoundError, distribution
1213
from pathlib import Path
1314

@@ -27,13 +28,19 @@
2728
from ingredient_parser.en._loaders import load_parser_model
2829
from ingredient_parser.en.preprocess import PreProcessor
2930

30-
# globals
31+
# globals defs
3132
parent_dir = Path(__file__).parent.parent
3233
NPM_BUILD_DIRECTORY = "build"
3334
SQL3_DATABASE_TABLE = "en"
3435
SQL3_DATABASE = parent_dir / "train/data/training.sqlite3"
3536
MODEL_REQUIREMENTS = parent_dir / "requirements-dev.txt"
36-
RESERVED_LABELLER_SEARCH_CHARS = r"\*\*|\~\~|\=\="
37+
38+
39+
# global regex
40+
RESERVED_LABELLER_SEARCH_CHARS = r"\*\*|\~\~|\=\=" # ** or ~~ or ==
41+
RESERVED_DOTNUM_RANGE_CHARS = (
42+
r"^\d*\.?\d*(?<!\.)\.\.(?!\.)\d*\.?\d*$" # {digit}..{digit}
43+
)
3744

3845
# sqlite
3946
sqlite3.register_adapter(list, json.dumps)
@@ -47,23 +54,36 @@
4754
load_parser_model.cache_clear()
4855

4956

50-
def error_response(status: int, message: str = ""):
57+
# helpers
58+
def is_valid_dotnum_range(s: str) -> bool:
59+
"""Checks a str against the format "{digit}..{digit}"""
60+
61+
return bool(re.fullmatch(RESERVED_DOTNUM_RANGE_CHARS, s))
62+
63+
64+
def error_response(
65+
status: int,
66+
traceback: str = "",
67+
):
5168
"""Boilerplate for errors"""
52-
if status == 400:
53-
return jsonify(
54-
{"status": 400, "error": "Sorry, bad params", "message": message}
55-
), 400
56-
elif status == 404:
69+
70+
try:
5771
return jsonify(
58-
{"status": 404, "error": "Sorry, resource not found", "message": message}
59-
), 404
60-
elif status == 500:
72+
{
73+
"status": HTTPStatus(status).value,
74+
"error": f"{HTTPStatus(status).name}",
75+
"traceback": traceback,
76+
"description": HTTPStatus(status).description,
77+
}
78+
), HTTPStatus(status).value
79+
except Exception:
6180
return jsonify(
62-
{"status": 404, "error": "Sorry, api failed", "message": message}
63-
), 500
64-
else:
65-
return jsonify(
66-
{"status": status, "error": "Sorry, something failed", "message": message}
81+
{
82+
"status": 500,
83+
"error": f"{HTTPStatus.INTERNAL_SERVER_ERROR.value}",
84+
"traceback": "",
85+
"description": HTTPStatus.INTERNAL_SERVER_ERROR.description,
86+
}
6787
), 500
6888

6989

@@ -99,6 +119,7 @@ def get_all_marginals(parser_info: ParserDebugInfo) -> list[dict[str, float]]:
99119
return marginals
100120

101121

122+
# routes
102123
@app.route("/parser", methods=["POST"])
103124
@cross_origin()
104125
def parser():
@@ -194,7 +215,7 @@ def parser():
194215

195216
except Exception as ex:
196217
traced = "".join(traceback.TracebackException.from_exception(ex).format())
197-
return error_response(status=500, message=traced)
218+
return error_response(status=500, traceback=traced)
198219

199220
else:
200221
return error_response(status=404)
@@ -235,7 +256,7 @@ def preupload():
235256

236257
except Exception as ex:
237258
traced = "".join(traceback.TracebackException.from_exception(ex).format())
238-
return error_response(status=500, message=traced)
259+
return error_response(status=500, traceback=traced)
239260

240261
else:
241262
return error_response(status=404)
@@ -264,7 +285,7 @@ def available_sources():
264285

265286
except Exception as ex:
266287
traced = "".join(traceback.TracebackException.from_exception(ex).format())
267-
return error_response(status=500, message=traced)
288+
return error_response(status=500, traceback=traced)
268289

269290
else:
270291
return error_response(status=404)
@@ -328,7 +349,7 @@ def labeller_save():
328349
except Exception as ex:
329350
traced = "".join(traceback.TracebackException.from_exception(ex).format())
330351
print(traced)
331-
return error_response(status=500, message=traced)
352+
return error_response(status=500, traceback=traced)
332353

333354
else:
334355
return error_response(status=404)
@@ -379,18 +400,12 @@ def labeller_bulk_upload():
379400

380401
except Exception as ex:
381402
traced = "".join(traceback.TracebackException.from_exception(ex).format())
382-
return error_response(status=500, message=traced)
403+
return error_response(status=500, traceback=traced)
383404

384405
else:
385406
return error_response(status=404)
386407

387408

388-
def is_valid_dotnum_range(s: str) -> bool:
389-
"""Checks a str against the format "{digit}..{digit}"""
390-
391-
return bool(re.fullmatch(r"^\d*\.?\d*(?<!\.)\.\.(?!\.)\d*\.?\d*$", s))
392-
393-
394409
@app.route("/labeller/search", methods=["POST"])
395410
@cross_origin()
396411
def labeller_search():
@@ -427,11 +442,10 @@ def labeller_search():
427442
# reserve == for id search
428443
ids_reserved = []
429444
if reserved_char_match in ["=="]:
430-
ids_unique = map(str.strip, list(set(sentence[2:].split(","))))
431445
ids_actual = [
432-
ix
433-
for ix in ids_unique
434-
if ix.isdigit() or is_valid_dotnum_range(ix)
446+
ix.strip()
447+
for ix in set(sentence[2:].split(","))
448+
if ix.strip().isdigit() or is_valid_dotnum_range(ix.strip())
435449
]
436450

437451
for id in ids_actual:
@@ -542,7 +556,7 @@ def labeller_search():
542556

543557
except Exception as ex:
544558
traced = "".join(traceback.TracebackException.from_exception(ex).format())
545-
return error_response(status=500, message=traced)
559+
return error_response(status=500, traceback=traced)
546560

547561
else:
548562
return error_response(status=404)

webtools/src/Styles.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,14 @@ export function GlobalStyles({ children }: { children: React.ReactNode }) {
269269
const theme = createTheme({
270270
scale: 1,
271271
components: components,
272+
shadows: {
273+
// rgba(251, 241, 199) = var(--fg)
274+
xs: "0 0.0625rem 0.1875rem rgba(251,241,199,0.05) , 0 0.0625rem 0.125rem rgba(251,241,199,0.05)",
275+
sm: "0 0.0625rem 0.1875rem rgba(251,241,199,0.05), rgba(251,241,199,0.05) 0 0.625rem 0.9375rem -0.3125rem, rgba(251,241,199,0.04) 0 0.4375rem 0.4375rem -0.3125rem",
276+
md: "0 0.0625rem 0.1875rem rgba(251,241,199,0.05), rgba(251,241,199,0.05) 0 1.25rem 1.5625rem -0.3125rem, rgba(251,241,199,0.04) 0 0.625rem 0.625rem -0.3125rem",
277+
lg: "0 0.0625rem 0.1875rem rgba(251,241,199,0.05), rgba(251,241,199,0.05) 0 1.75rem 1.4375rem -0.4375rem, rgba(251,241,199,0.04) 0 0.75rem 0.75rem -0.4375rem",
278+
xl: "0 0.0625rem 0.1875rem rgba(251,241,199,0.05), rgba(251,241,199,0.05) 0 2.25rem 1.75rem -0.4375rem, rgba(251,241,199,0.04) 0 1.0625rem 1.0625rem -0.4375rem",
279+
},
272280
});
273281

274282
return (

webtools/src/components/PageTabLabeller/TextInputSubmit/TextInputSubmit.tsx

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import {
3838
labellers,
3939
useTabLabellerStore,
4040
} from "../../../domain";
41+
import { PopoverQuestionMark } from "../../Shared";
4142

4243
interface ReservedChars {
4344
chars: {
@@ -55,8 +56,8 @@ const reservedCharacters: ReservedChars[] = [
5556
],
5657
description: (
5758
<span>
58-
Reserved for wildcard searches. Use this to search the ingredient
59-
database without a keyword. For example, input only <Code>**</Code>.
59+
Reserved for wildcard searches. Use this to search the database without
60+
a keyword. For example, input only <Code>**</Code>.
6061
</span>
6162
),
6263
},
@@ -66,10 +67,9 @@ const reservedCharacters: ReservedChars[] = [
6667
],
6768
description: (
6869
<span>
69-
Reserved for ID matched searches. Use this to directly query the
70-
ingredient database row IDs. Supports double dot notation for ID ranges.
71-
For example the input <Code>== 1,2,10..14</Code> would be interpreted as{" "}
72-
<Code>== 1,2,10,11,12,13,14</Code>.
70+
Reserved for seaching by ID, with dot notation support for ranges. Use
71+
this to directly query the database rows. For example, input{" "}
72+
<Code>== 1,2,10..14</Code> or <Code>== 1,2,10,11,12,13,14</Code>.
7373
</span>
7474
),
7575
},
@@ -101,13 +101,28 @@ function ReservedCharDescriptor({
101101
);
102102
}
103103

104+
function PopoverQuestionMarkWrapper({
105+
label,
106+
description,
107+
}: {
108+
label?: string;
109+
description?: string;
110+
}) {
111+
return (
112+
<Flex gap="xs" justify="flex-start">
113+
<div>{label}</div>
114+
<PopoverQuestionMark>{description}</PopoverQuestionMark>
115+
</Flex>
116+
);
117+
}
118+
104119
function ActionIconQuestion(props: ActionIconProps) {
105120
const [opened, { close, open }] = useDisclosure(false);
106121

107122
return (
108123
<Popover
109124
opened={opened}
110-
shadow="md"
125+
shadow="xs"
111126
keepMounted={false}
112127
position="bottom-end"
113128
width={350}
@@ -141,6 +156,13 @@ function ActionIconQuestion(props: ActionIconProps) {
141156
{i + 1 !== reservedCharacters.length && <Divider />}
142157
</>
143158
))}
159+
<Divider />
160+
<Box px="xs" py="xs" bg="var(--bg-s)">
161+
<Text size="xs" fs="italic">
162+
For full querying capabilities, use a standard SQLite adapter or
163+
browser
164+
</Text>
165+
</Box>
144166
</Popover.Dropdown>
145167
</Popover>
146168
);
@@ -253,7 +275,12 @@ function ActionIconFilter(props: ActionIconProps) {
253275
</Menu.Target>
254276

255277
<Menu.Dropdown>
256-
<Menu.Label>Keyword (options)</Menu.Label>
278+
<Menu.Label>
279+
<PopoverQuestionMarkWrapper
280+
label="Keyword matching"
281+
description="Additional keyword matching options"
282+
/>
283+
</Menu.Label>
257284
<Box py="xs" px="sm">
258285
<Checkbox
259286
defaultChecked
@@ -287,12 +314,22 @@ function ActionIconFilter(props: ActionIconProps) {
287314
/>
288315
</Box>
289316
<Menu.Divider />
290-
<Menu.Label>Labels (to search against)</Menu.Label>
317+
<Menu.Label>
318+
<PopoverQuestionMarkWrapper
319+
label="Labels"
320+
description="The labels (tokens) to search against"
321+
/>
322+
</Menu.Label>
291323
<Box py="xs" px="sm">
292324
{labelFilters}
293325
</Box>
294326
<Menu.Divider />
295-
<Menu.Label>Sources (to search against)</Menu.Label>
327+
<Menu.Label>
328+
<PopoverQuestionMarkWrapper
329+
label="Source datasets"
330+
description="The datasets to search against"
331+
/>
332+
</Menu.Label>
296333
<Box py="xs" px="sm">
297334
{labelSources}
298335
</Box>

webtools/src/components/Shared/PopoverQuestionMark/PopoverQuestionMark.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { useDisclosure } from "@mantine/hooks";
1313
import { IconQuestionMark } from "@tabler/icons-react";
1414

1515
export function PopoverQuestionMark({
16-
shadow = "sm",
16+
shadow = "none",
1717
withArrow = true,
1818
width = 200,
1919
position = "top",

0 commit comments

Comments
 (0)