|
145 | 145 | {
|
146 | 146 | "data": {
|
147 | 147 | "text/plain": [
|
148 |
| - "datetime.datetime(2024, 7, 11, 14, 0)" |
| 148 | + "datetime.datetime(2024, 7, 17, 14, 0)" |
149 | 149 | ]
|
150 | 150 | },
|
151 | 151 | "execution_count": null,
|
|
662 | 662 | " if res is empty or res is None:\n",
|
663 | 663 | " frm = await req.form()\n",
|
664 | 664 | " res = _formitem(frm, arg)\n",
|
665 |
| - " # Use default param if needed\n", |
| 665 | + " # Raise 400 error if the param does not include a default\n", |
| 666 | + " if (res is empty or res is None) and p.default is empty: raise HTTPException(400, f\"Missing required field: {arg}\")\n", |
| 667 | + " # If we have a default, return that if we have no value\n", |
666 | 668 | " if res is empty or res is None: res = p.default\n",
|
667 | 669 | " # We can cast str and list[str] to types; otherwise just return what we have\n",
|
668 | 670 | " if not isinstance(res, (list,str)) or anno is empty: return res\n",
|
|
1031 | 1033 | {
|
1032 | 1034 | "data": {
|
1033 | 1035 | "text/plain": [
|
1034 |
| - "'08b63b51-be3a-4f54-8d26-4cd27eb17c0d'" |
| 1036 | + "'2c25d03b-24f2-4946-833a-50ac832a1576'" |
1035 | 1037 | ]
|
1036 | 1038 | },
|
1037 | 1039 | "execution_count": null,
|
|
1453 | 1455 | "test_eq(r.headers['mykey'], 'myval')"
|
1454 | 1456 | ]
|
1455 | 1457 | },
|
| 1458 | + { |
| 1459 | + "cell_type": "code", |
| 1460 | + "execution_count": null, |
| 1461 | + "id": "a3596991", |
| 1462 | + "metadata": {}, |
| 1463 | + "outputs": [], |
| 1464 | + "source": [ |
| 1465 | + "@app.post('/profile/me')\n", |
| 1466 | + "def profile_update(username: str): return username" |
| 1467 | + ] |
| 1468 | + }, |
| 1469 | + { |
| 1470 | + "cell_type": "code", |
| 1471 | + "execution_count": null, |
| 1472 | + "id": "277b1db0", |
| 1473 | + "metadata": {}, |
| 1474 | + "outputs": [], |
| 1475 | + "source": [ |
| 1476 | + "# Working post request, this is our control\n", |
| 1477 | + "test_r(cli, '/profile/me', 'Alexis', 'post',\n", |
| 1478 | + " data={'username' : 'Alexis'})" |
| 1479 | + ] |
| 1480 | + }, |
| 1481 | + { |
| 1482 | + "cell_type": "code", |
| 1483 | + "execution_count": null, |
| 1484 | + "id": "93d18dfa", |
| 1485 | + "metadata": {}, |
| 1486 | + "outputs": [], |
| 1487 | + "source": [ |
| 1488 | + "# Failing post request due to missing required username parameter\n", |
| 1489 | + "try:\n", |
| 1490 | + " test_r(cli, '/profile/me', 'Alexis', 'post', data={})\n", |
| 1491 | + "except AssertionError as e:\n", |
| 1492 | + " assert \"Missing required field: username\" in str(e)" |
| 1493 | + ] |
| 1494 | + }, |
| 1495 | + { |
| 1496 | + "cell_type": "code", |
| 1497 | + "execution_count": null, |
| 1498 | + "id": "fdb9239c", |
| 1499 | + "metadata": {}, |
| 1500 | + "outputs": [], |
| 1501 | + "source": [ |
| 1502 | + "# Example post request with parameter that has a default value\n", |
| 1503 | + "@app.post('/pet/dog')\n", |
| 1504 | + "def pet_dog(dogname: str = None): return dogname\n", |
| 1505 | + "\n", |
| 1506 | + "# Working post request with optional parameter\n", |
| 1507 | + "test_r(cli, '/pet/dog', '', 'post', data={})" |
| 1508 | + ] |
| 1509 | + }, |
1456 | 1510 | {
|
1457 | 1511 | "cell_type": "code",
|
1458 | 1512 | "execution_count": null,
|
|
1495 | 1549 | "execution_count": null,
|
1496 | 1550 | "id": "48f0a45e",
|
1497 | 1551 | "metadata": {},
|
1498 |
| - "outputs": [], |
| 1552 | + "outputs": [ |
| 1553 | + { |
| 1554 | + "ename": "AssertionError", |
| 1555 | + "evalue": "==:\nNot Found\n{\"a\":1,\"b\":\"foo\",\"nm\":\"me\"}", |
| 1556 | + "output_type": "error", |
| 1557 | + "traceback": [ |
| 1558 | + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", |
| 1559 | + "\u001b[0;31mAssertionError\u001b[0m Traceback (most recent call last)", |
| 1560 | + "Cell \u001b[0;32mIn[89], line 3\u001b[0m\n\u001b[1;32m 1\u001b[0m d \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mdict\u001b[39m(a\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m1\u001b[39m, b\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mfoo\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[0;32m----> 3\u001b[0m \u001b[43mtest_r\u001b[49m\u001b[43m(\u001b[49m\u001b[43mcli\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m/bodie/me\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m{\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43ma\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m:1,\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mb\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m:\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mfoo\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m,\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mnm\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m:\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mme\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m}\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mpost\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdata\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43md\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;66;03m# This test should not be working, as the \"nm\" arguement isn't provided and there isn't a default\u001b[39;00m\n\u001b[1;32m 5\u001b[0m test_r(cli, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m/bodied/\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m{\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124ma\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m:\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m1\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m,\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mb\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m:\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mfoo\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m}\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mpost\u001b[39m\u001b[38;5;124m'\u001b[39m, data\u001b[38;5;241m=\u001b[39md)\n", |
| 1561 | + "Cell \u001b[0;32mIn[66], line 3\u001b[0m, in \u001b[0;36mtest_r\u001b[0;34m(cli, path, exp, meth, hx, **kwargs)\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mtest_r\u001b[39m(cli, path, exp, meth\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mget\u001b[39m\u001b[38;5;124m'\u001b[39m, hx\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m, \u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs):\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m hx: kwargs[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mheaders\u001b[39m\u001b[38;5;124m'\u001b[39m] \u001b[38;5;241m=\u001b[39m {\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mhx-request\u001b[39m\u001b[38;5;124m'\u001b[39m:\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m1\u001b[39m\u001b[38;5;124m\"\u001b[39m}\n\u001b[0;32m----> 3\u001b[0m \u001b[43mtest_eq\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mgetattr\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mcli\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mmeth\u001b[49m\u001b[43m)\u001b[49m\u001b[43m(\u001b[49m\u001b[43mpath\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtext\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mexp\u001b[49m\u001b[43m)\u001b[49m\n", |
| 1562 | + "File \u001b[0;32m~/.virtualenvs/fasthtml/lib/python3.10/site-packages/fastcore-1.5.51-py3.10.egg/fastcore/test.py:37\u001b[0m, in \u001b[0;36mtest_eq\u001b[0;34m(a, b)\u001b[0m\n\u001b[1;32m 35\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mtest_eq\u001b[39m(a,b):\n\u001b[1;32m 36\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m`test` that `a==b`\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m---> 37\u001b[0m \u001b[43mtest\u001b[49m\u001b[43m(\u001b[49m\u001b[43ma\u001b[49m\u001b[43m,\u001b[49m\u001b[43mb\u001b[49m\u001b[43m,\u001b[49m\u001b[43mequals\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcname\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m==\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m)\u001b[49m\n", |
| 1563 | + "File \u001b[0;32m~/.virtualenvs/fasthtml/lib/python3.10/site-packages/fastcore-1.5.51-py3.10.egg/fastcore/test.py:27\u001b[0m, in \u001b[0;36mtest\u001b[0;34m(a, b, cmp, cname)\u001b[0m\n\u001b[1;32m 25\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m`assert` that `cmp(a,b)`; display inputs and `cname or cmp.__name__` if it fails\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 26\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m cname \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m: cname\u001b[38;5;241m=\u001b[39mcmp\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__name__\u001b[39m\n\u001b[0;32m---> 27\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m cmp(a,b),\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mcname\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m:\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;132;01m{\u001b[39;00ma\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;132;01m{\u001b[39;00mb\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m\n", |
| 1564 | + "\u001b[0;31mAssertionError\u001b[0m: ==:\nNot Found\n{\"a\":1,\"b\":\"foo\",\"nm\":\"me\"}" |
| 1565 | + ] |
| 1566 | + } |
| 1567 | + ], |
1499 | 1568 | "source": [
|
1500 | 1569 | "d = dict(a=1, b='foo')\n",
|
1501 | 1570 | "\n",
|
1502 | 1571 | "test_r(cli, '/bodie/me', '{\"a\":1,\"b\":\"foo\",\"nm\":\"me\"}', 'post', data=d)\n",
|
| 1572 | + "# This test should not be working, as the \"nm\" arguement isn't\n", |
| 1573 | + "# provided and there isn't a default\n", |
1503 | 1574 | "test_r(cli, '/bodied/', '{\"a\":\"1\",\"b\":\"foo\"}', 'post', data=d)\n",
|
1504 | 1575 | "test_r(cli, '/bodie2/', 'a: 1; b: foo', 'post', data={'a':1})\n",
|
1505 | 1576 | "test_r(cli, '/bodient/', '{\"a\":\"1\",\"b\":\"foo\"}', 'post', data=d)\n",
|
|
1536 | 1607 | {
|
1537 | 1608 | "data": {
|
1538 | 1609 | "text/plain": [
|
1539 |
| - "'Cookie was set at time 17:11:37.078633'" |
| 1610 | + "'Cookie was set at time 23:41:43.695239'" |
1540 | 1611 | ]
|
1541 | 1612 | },
|
1542 | 1613 | "execution_count": null,
|
|
1577 | 1648 | "name": "stdout",
|
1578 | 1649 | "output_type": "stream",
|
1579 | 1650 | "text": [
|
1580 |
| - "Set to 2024-07-11 16:59:55.536116\n" |
| 1651 | + "Set to 2024-07-17 23:41:43.724183\n" |
1581 | 1652 | ]
|
1582 | 1653 | },
|
1583 | 1654 | {
|
1584 | 1655 | "data": {
|
1585 | 1656 | "text/plain": [
|
1586 |
| - "'Session time: 16:59:55.536116'" |
| 1657 | + "'Session time: 23:41:43.724183'" |
1587 | 1658 | ]
|
1588 | 1659 | },
|
1589 | 1660 | "execution_count": null,
|
|
1611 | 1682 | "\n",
|
1612 | 1683 | "<!-- do not remove -->\n",
|
1613 | 1684 | "\n",
|
1614 |
| - "## 0.1.4\n", |
| 1685 | + "## 0.1.6\n", |
1615 | 1686 | "\n",
|
1616 | 1687 | "### New Features\n",
|
1617 | 1688 | "\n",
|
1618 |
| - "- `ScriptX`\n" |
| 1689 | + "- `File` fu\n" |
1619 | 1690 | ]
|
1620 | 1691 | }
|
1621 | 1692 | ],
|
|
1715 | 1786 | "#|hide\n",
|
1716 | 1787 | "import nbdev; nbdev.nbdev_export()"
|
1717 | 1788 | ]
|
1718 |
| - }, |
1719 |
| - { |
1720 |
| - "cell_type": "code", |
1721 |
| - "execution_count": null, |
1722 |
| - "id": "ff0f002c", |
1723 |
| - "metadata": {}, |
1724 |
| - "outputs": [], |
1725 |
| - "source": [] |
1726 | 1789 | }
|
1727 | 1790 | ],
|
1728 | 1791 | "metadata": {
|
|
0 commit comments