pyrefdev 2025.6__tar.gz → 2025.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyrefdev-2025.6 → pyrefdev-2025.7}/CHANGELOG.md +5 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/CLAUDE.md +4 -1
- {pyrefdev-2025.6 → pyrefdev-2025.7}/PKG-INFO +14 -2
- {pyrefdev-2025.6 → pyrefdev-2025.7}/README.md +13 -1
- pyrefdev-2025.7/src/pyrefdev/_version.py +1 -0
- pyrefdev-2025.7/src/pyrefdev/server.py +116 -0
- pyrefdev-2025.7/static/styles.css +693 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/templates/index.html +28 -414
- pyrefdev-2025.7/templates/search.html +152 -0
- pyrefdev-2025.6/src/pyrefdev/_version.py +0 -1
- pyrefdev-2025.6/src/pyrefdev/server.py +0 -35
- {pyrefdev-2025.6 → pyrefdev-2025.7}/.github/workflows/ci.yml +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/.github/workflows/pypi_upload.yml +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/.gitignore +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/.pre-commit-config.yaml +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/LICENSE +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/pyproject.toml +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/pyrefdev.service +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/__init__.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/__main__.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/config.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/indexer/__main__.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/indexer/add_docs.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/indexer/crawl_docs.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/indexer/parse_docs.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/indexer/requests.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/indexer/schema.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/indexer/update_docs.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/indexer/update_landing_page.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/__init__.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/__python__.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/aiohttp.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/aioitertools.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/aiosignal.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/anyio.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/apache-beam.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/arrow.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/attrs.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/azure-identity.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/boto3.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/botocore.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/cachetools.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/cattrs.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/charset-normalizer.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/click.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/coverage.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/cryptography.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/cyclopts.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/distlib.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/fastapi.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/fastjsonschema.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/filelock.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/flask.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/frozenlist.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/fsspec.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/google-api-core.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/google-auth.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/grpcio.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/h11.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/h5py.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/httplib2.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/ipython.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/jinja2.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/jsonschema.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/jupyter-core.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/libcst.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/markupsafe.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/matplotlib.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/more-itertools.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/multidict.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/nbformat.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/networkx.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/numba.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/numpy.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/oauthlib.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/packaging.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/pandas.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/pathspec.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/pillow.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/platformdirs.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/pluggy.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/propcache.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/protobuf.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/psutil.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/pyOpenSSL.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/pyarrow.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/pyasn1.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/pydantic-core.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/pydantic.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/pygments.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/pyjwt.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/pyparsing.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/pytest.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/python-dateutil.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/requests-oauthlib.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/requests-toolbelt.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/requests.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/rich.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/rpds-py.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/s3fs.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/scikit-learn.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/scipy.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/semver.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/setuptools.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/six.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/sniffio.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/sqlalchemy.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/tomlkit.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/torch.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/tox.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/trio.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/typing-extensions.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/urllib3.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/werkzeug.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/wrapt.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/yarl.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/src/pyrefdev/mapping/yib.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/static/logo128.png +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/tests/test_pyrefdev.py +0 -0
- {pyrefdev-2025.6 → pyrefdev-2025.7}/uv.lock +0 -0
|
@@ -4,6 +4,11 @@
|
|
|
4
4
|
|
|
5
5
|
Nothing noticeable unreleased.
|
|
6
6
|
|
|
7
|
+
## v2025.7
|
|
8
|
+
|
|
9
|
+
- Added search to [pyref.dev](https://pyref.dev).
|
|
10
|
+
- When the symbol is not found, redirect to the search page.
|
|
11
|
+
|
|
7
12
|
## v2025.6
|
|
8
13
|
|
|
9
14
|
- Added a `-p/--print` flag to the `pyrefdev` CLI to print the URL instead of opening it in the browser.
|
|
@@ -6,7 +6,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|
|
6
6
|
|
|
7
7
|
The project has several components:
|
|
8
8
|
|
|
9
|
-
1. **Web Server** (`src/pyrefdev/server.py`): FastAPI application that serves redirects based on symbol lookup. `index.html` is the landing page of the server
|
|
9
|
+
1. **Web Server** (`src/pyrefdev/server.py`): FastAPI application that serves redirects based on symbol lookup. `templates/index.html` is the landing page of the server, `static/styles.css` contains CSS styles
|
|
10
10
|
2. **CLI Tool** (`src/pyrefdev/__main__.py`): Command-line interface that opens documentation in browser
|
|
11
11
|
3. **Indexer** (`src/pyrefdev/indexer/`): Tools for crawling, parsing, and managing documentation mappings
|
|
12
12
|
4. **Mapping System** (`src/pyrefdev/mapping/`): Individual Python files per package containing symbol-to-URL mappings
|
|
@@ -48,4 +48,7 @@ pyrefdev-indexer update-landing-page
|
|
|
48
48
|
|
|
49
49
|
## Important Notes
|
|
50
50
|
|
|
51
|
+
- Do not add tests unless explictly asked to.
|
|
52
|
+
- When creating a new file with content, ensure the file has an extra new line at the end.
|
|
53
|
+
- Do NOT add redundant comments describe what the cod does. When needed, DO add comments that explains "why".
|
|
51
54
|
- Server deployment uses systemd and is configured in `pyrefdev.service`
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyrefdev
|
|
3
|
-
Version: 2025.
|
|
3
|
+
Version: 2025.7
|
|
4
4
|
Summary: The entry point to Python reference docs
|
|
5
5
|
Project-URL: Homepage, https://pyref.dev
|
|
6
6
|
Project-URL: Source, https://github.com/mangoumbrella/pyref.dev
|
|
@@ -51,7 +51,19 @@ It allows you to quickly jump to the official documentation for Python standard
|
|
|
51
51
|
https://pyref.dev/<fully.qualified.symbol.name>
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
You can also search for symbols using:
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
https://pyref.dev/is?symbol=<SYMBOL>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
And if you are feeling lucky, ask it to redirect to the first result:
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
https://pyref.dev/is?lucky=true&symbol=<SYMBOL>
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Lastly, you can `pip install pyrefdev` and run the `pyrefdev` CLI tool.
|
|
55
67
|
|
|
56
68
|
## Examples
|
|
57
69
|
|
|
@@ -14,7 +14,19 @@ It allows you to quickly jump to the official documentation for Python standard
|
|
|
14
14
|
https://pyref.dev/<fully.qualified.symbol.name>
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
You can also search for symbols using:
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
https://pyref.dev/is?symbol=<SYMBOL>
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
And if you are feeling lucky, ask it to redirect to the first result:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
https://pyref.dev/is?lucky=true&symbol=<SYMBOL>
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Lastly, you can `pip install pyrefdev` and run the `pyrefdev` CLI tool.
|
|
18
30
|
|
|
19
31
|
## Examples
|
|
20
32
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
version = "2025.7"
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
from fastapi import FastAPI, Request
|
|
2
|
+
from fastapi.responses import RedirectResponse, PlainTextResponse
|
|
3
|
+
from fastapi.staticfiles import StaticFiles
|
|
4
|
+
from fastapi.templating import Jinja2Templates
|
|
5
|
+
import importlib.metadata
|
|
6
|
+
from urllib import parse
|
|
7
|
+
|
|
8
|
+
from pyrefdev.mapping import MAPPING
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
app = FastAPI()
|
|
12
|
+
app.mount("/static", StaticFiles(directory="static"), name="static")
|
|
13
|
+
|
|
14
|
+
templates = Jinja2Templates(directory="templates")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@app.get("/")
|
|
18
|
+
async def root(request: Request):
|
|
19
|
+
try:
|
|
20
|
+
version = importlib.metadata.version("pyrefdev")
|
|
21
|
+
version = version.split("+")[0] # Strip the git hash
|
|
22
|
+
except importlib.metadata.PackageNotFoundError:
|
|
23
|
+
version = "unknown"
|
|
24
|
+
|
|
25
|
+
return templates.TemplateResponse(
|
|
26
|
+
"index.html", {"request": request, "version": version}
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@app.get("/is")
|
|
31
|
+
async def search_symbols(request: Request, symbol: str = "", lucky: bool = False):
|
|
32
|
+
if not symbol:
|
|
33
|
+
return templates.TemplateResponse(
|
|
34
|
+
"search.html", {"request": request, "symbol": "", "results": []}
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
# Search by substring for now.
|
|
38
|
+
results = []
|
|
39
|
+
symbol_lower = symbol.lower()
|
|
40
|
+
for key in MAPPING.keys():
|
|
41
|
+
if symbol_lower in key.lower():
|
|
42
|
+
fragment = parse.urlparse(MAPPING[key]).fragment
|
|
43
|
+
if fragment.lower() == key.lower():
|
|
44
|
+
candidate = fragment
|
|
45
|
+
else:
|
|
46
|
+
candidate = key
|
|
47
|
+
results.append({"symbol": candidate, "url": MAPPING[key]})
|
|
48
|
+
|
|
49
|
+
def ranking_key(result):
|
|
50
|
+
symbol_path = result["symbol"]
|
|
51
|
+
components = symbol_path.split(".")
|
|
52
|
+
num_components = len(components)
|
|
53
|
+
|
|
54
|
+
if symbol_path.lower() == symbol_lower:
|
|
55
|
+
# Prioritize exact case matches over case-insensitive matches (only if search term has uppercase)
|
|
56
|
+
case_match_priority = 0 if (symbol != symbol_lower and symbol_path == symbol) else 1
|
|
57
|
+
return (0, 0, case_match_priority, num_components, len(symbol_path), symbol_path)
|
|
58
|
+
|
|
59
|
+
# Check for exact component matches (case-insensitive)
|
|
60
|
+
exact_component_matches = []
|
|
61
|
+
exact_case_component_matches = []
|
|
62
|
+
for i, component in enumerate(components):
|
|
63
|
+
if component.lower() == symbol_lower:
|
|
64
|
+
# Position from right (0 = rightmost, higher = more left)
|
|
65
|
+
position_from_right = len(components) - 1 - i
|
|
66
|
+
exact_component_matches.append(position_from_right)
|
|
67
|
+
|
|
68
|
+
# Check if it's also an exact case match (only if search term has uppercase)
|
|
69
|
+
if symbol != symbol_lower and component == symbol:
|
|
70
|
+
exact_case_component_matches.append(position_from_right)
|
|
71
|
+
|
|
72
|
+
if exact_case_component_matches:
|
|
73
|
+
# Prioritize rightmost position, then exact case matches
|
|
74
|
+
best_position = min(exact_case_component_matches)
|
|
75
|
+
return (1, best_position, 0, num_components, len(symbol_path), symbol_path)
|
|
76
|
+
elif exact_component_matches:
|
|
77
|
+
# Case-insensitive exact matches
|
|
78
|
+
best_position = min(exact_component_matches)
|
|
79
|
+
return (1, best_position, 1, num_components, len(symbol_path), symbol_path)
|
|
80
|
+
|
|
81
|
+
# Check for component substring matches
|
|
82
|
+
component_substring_matches = []
|
|
83
|
+
for i, component in enumerate(components):
|
|
84
|
+
if symbol_lower in component.lower():
|
|
85
|
+
position_from_right = len(components) - 1 - i
|
|
86
|
+
component_substring_matches.append(position_from_right)
|
|
87
|
+
|
|
88
|
+
if component_substring_matches:
|
|
89
|
+
best_position = min(component_substring_matches)
|
|
90
|
+
return (2, best_position, 0, num_components, len(symbol_path), symbol_path)
|
|
91
|
+
|
|
92
|
+
# Fallback to general substring match
|
|
93
|
+
return (3, 0, 0, num_components, len(symbol_path), symbol_path)
|
|
94
|
+
|
|
95
|
+
results.sort(key=ranking_key)
|
|
96
|
+
|
|
97
|
+
# If lucky=true and we have results, redirect to the first (best) result
|
|
98
|
+
if lucky and results:
|
|
99
|
+
return RedirectResponse(results[0]["url"])
|
|
100
|
+
|
|
101
|
+
return templates.TemplateResponse(
|
|
102
|
+
"search.html", {"request": request, "symbol": symbol, "results": results}
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@app.get("/{symbol}")
|
|
107
|
+
async def redirects(symbol: str, lucky: bool = False):
|
|
108
|
+
if url := MAPPING.get(symbol):
|
|
109
|
+
return RedirectResponse(url)
|
|
110
|
+
if url := MAPPING.get(symbol.lower()):
|
|
111
|
+
return RedirectResponse(url)
|
|
112
|
+
|
|
113
|
+
if lucky:
|
|
114
|
+
return RedirectResponse(f"/is?symbol={symbol}&lucky=true")
|
|
115
|
+
else:
|
|
116
|
+
return RedirectResponse(f"/is?symbol={symbol}")
|