Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
9bdbd75
feat(toc): expose authors in TOC serialization
yonadavGit Mar 22, 2026
8e07fdd
feat(toc): add option to include or exclude authors in TOC response
yonadavGit Mar 23, 2026
6f9ae0e
fix(toc): update query parameter to use snake_case for include author…
yonadavGit Mar 23, 2026
371e5a8
feat(api): add include_authors parameter to Table of Contents endpoint
yonadavGit Mar 23, 2026
83ff5da
feat(links): add category filters to get_links API and update tests
yonadavGit Mar 23, 2026
8a7c6c1
feat(wrapper): implement category filtering for links in wrapper.py
yonadavGit Mar 23, 2026
b6ce27f
feat: deploy MaxRSS memory logging middleware to single production po…
yodem Mar 24, 2026
91602dc
chore: enable webMemlog in production values
yodem Mar 24, 2026
7dde2c3
Revert "chore: enable webMemlog in production values"
yodem Mar 24, 2026
6c7a1ed
chore: enable webMemlog in production values
yodem Mar 24, 2026
b4db24d
feat(toc): add options parameter to TOC serialization and update rela…
yonadavGit Mar 24, 2026
03c3e66
feat(toc): refactor TOC serialization to use serialization_options pa…
yonadavGit Mar 24, 2026
c1f09b5
feat(toc): explicit initialization of options object
yonadavGit Mar 24, 2026
5c20ebb
refactor: remove Helm deployment — will be applied manually instead
yodem Mar 24, 2026
5f6fd61
deploy(staging): app=6.81.0 chart=0.79.1 [skip ci]
yodem Mar 24, 2026
dbb1cf6
deploy(preprod): app=6.81.1-preprod.1 chart=0.79.2-preprod.1 [skip ci]
yodem Mar 24, 2026
eee1ade
Merge pull request #3165 from Sefaria/feature/sc-42920/add-learning-o…
nsantacruz Mar 24, 2026
9575b5c
deploy(staging): app=6.82.0 chart=0.79.1 [skip ci]
nsantacruz Mar 24, 2026
0b8b8d8
Merge pull request #3163 from Sefaria/feature/sc-42995/expose-library…
yonadavGit Mar 24, 2026
00c26ce
deploy(staging): app=6.83.0 chart=0.79.1 [skip ci]
github-merge-queue[bot] Mar 24, 2026
2f6a709
fix: update comment formatting in values.yaml for clarity
yodem Mar 24, 2026
d7fec28
Merge pull request #3172 from Sefaria/feature/sc-42011/deploy-memory-…
yodem Mar 24, 2026
f0d4cc2
deploy(staging): app=6.84.0 chart=0.80.0 [skip ci]
yodem Mar 24, 2026
e43b47f
Merge pull request #3179 from Sefaria/master
yodem Mar 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 52 additions & 2 deletions docs/openAPI.json
Original file line number Diff line number Diff line change
Expand Up @@ -2473,6 +2473,22 @@
"tags": [
"Index"
],
"parameters": [
{
"name": "include_authors",
"in": "query",
"description": "When set to `1`, include author metadata on text entries in the table of contents response.",
"required": false,
"schema": {
"type": "integer",
"enum": [
0,
1
],
"default": 0
}
}
],
"responses": {
"200": {
"content": {
Expand All @@ -2486,7 +2502,7 @@
}
},
"summary": "Table of Contents",
"description": "This API endpoint returns the titles of all the books in the Sefaria Library arranged by their category along with some additional metadata. This is a large and rarely changing request and should be cached locally if you utilize it."
"description": "This API endpoint returns the titles of all the books in the Sefaria Library arranged by their category along with some additional metadata. This is a large and rarely changing request and should be cached locally if you utilize it. By default, author metadata is omitted from text entries; set `include_authors=1` to include it."
}
},
"/api/shape/{title}": {
Expand Down Expand Up @@ -3617,6 +3633,22 @@
"type": "string"
},
"in": "query"
},
{
"name": "category",
"description": "Optional repeatable filter. Only include links whose API response `category` exactly matches this value. May be passed multiple times, e.g. `?category=Commentary&category=Midrash`.",
"schema": {
"type": "string"
},
"in": "query"
},
{
"name": "categories",
"description": "Optional multi-value category filter. Only include links whose API response `category` exactly matches one of the provided values. Values may be separated by commas or pipes, e.g. `?categories=Commentary,Midrash` or `?categories=Commentary|Midrash`.",
"schema": {
"type": "string"
},
"in": "query"
}
],
"responses": {
Expand All @@ -3635,7 +3667,7 @@
}
},
"summary": "Links",
"description": "Returns a list of known connections for the submitted text `ref` along with some additional metadata."
"description": "Returns a list of known connections for the submitted text `ref` along with some additional metadata. Category filters apply to the derived `category` value returned in the API payload, such as `Commentary`, `Midrash`, `Essay`, or `Quoting Commentary`."
},
"parameters": [
{
Expand Down Expand Up @@ -8634,6 +8666,24 @@
"description": "The corpus that this work belongs to e.g. `Tanakh` or `Mishnah` etc.",
"type": "string"
},
"authors": {
"description": "Returned only when `include_authors=1`. Author metadata for the text.",
"type": "array",
"items": {
"type": "object",
"properties": {
"en": {
"type": "string"
},
"he": {
"type": "string"
},
"slug": {
"type": "string"
}
}
}
},
"heTitle": {
"description": "The Hebrew title of this work.",
"type": "string"
Expand Down
8 changes: 4 additions & 4 deletions envs/preprod/helmrelease.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ spec:
web:
containerImage:
imageRegistry: us-east1-docker.pkg.dev/production-deployment/containers/sefaria-web
tag: "v6.80.1-preprod.1"
tag: "v6.81.1-preprod.1"
replicaCount: 2
resources:
web:
Expand Down Expand Up @@ -79,7 +79,7 @@ spec:
nodejs:
containerImage:
imageRegistry: us-east1-docker.pkg.dev/production-deployment/containers/sefaria-node
tag: "v6.80.1-preprod.1"
tag: "v6.81.1-preprod.1"
replicaCount: 1
resources:
requests:
Expand Down Expand Up @@ -164,7 +164,7 @@ spec:
nginx:
containerImage:
imageRegistry: us-east1-docker.pkg.dev/production-deployment/containers/sefaria-asset
tag: "v6.80.1-preprod.1"
tag: "v6.81.1-preprod.1"
SEARCH_HOST: "elasticsearch-1b-es-http.elasticsearch.svc"
SEARCH_PORT: "9200"
SEARCH_PATH: ""
Expand All @@ -181,7 +181,7 @@ spec:
monitor:
containerImage:
imageRegistry: us-east1-docker.pkg.dev/production-deployment/containers/sefaria-web
tag: "v6.80.1-preprod.1"
tag: "v6.81.1-preprod.1"
replicaCount: 1
resources:
requests:
Expand Down
10 changes: 5 additions & 5 deletions envs/staging/helmrelease.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ spec:
chart:
spec:
chart: sefaria
version: "0.79.1"
version: "0.80.0"
sourceRef:
kind: HelmRepository
name: sefaria-project-helm-repo
Expand All @@ -30,7 +30,7 @@ spec:
web:
containerImage:
imageRegistry: us-east1-docker.pkg.dev/production-deployment/containers/sefaria-web
tag: "v6.80.0"
tag: "v6.84.0"
resources:
web:
resources:
Expand All @@ -54,7 +54,7 @@ spec:
nodejs:
containerImage:
imageRegistry: us-east1-docker.pkg.dev/production-deployment/containers/sefaria-node
tag: "v6.80.0"
tag: "v6.84.0"
resources:
requests:
memory: "400Mi"
Expand All @@ -76,11 +76,11 @@ spec:
nginx:
containerImage:
imageRegistry: us-east1-docker.pkg.dev/production-deployment/containers/sefaria-asset
tag: "v6.80.0"
tag: "v6.84.0"
monitor:
containerImage:
imageRegistry: us-east1-docker.pkg.dev/production-deployment/containers/sefaria-web
tag: "v6.80.0"
tag: "v6.84.0"
tasks:
enabled: false
postgres:
Expand Down
2 changes: 1 addition & 1 deletion helm-chart/promotions/staging
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.79.1
0.80.0
2 changes: 1 addition & 1 deletion helm-chart/sefaria/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ rollouts:

# enabling this feature creates an ephemeral database image prepopulated with test data
# It is intended for use within the sefaria automated testing environment
# For development environments
# For development environments:
# - install mongo using an upstream chart
# - enable restore
# - populate the settings with the appropriate connection details
Expand Down
2 changes: 1 addition & 1 deletion promotions/preprod
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6.80.1-preprod.1
6.81.1-preprod.1
2 changes: 1 addition & 1 deletion promotions/staging
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6.80.0
6.84.0
22 changes: 20 additions & 2 deletions reader/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
from remote_config import remoteConfigCache

from sefaria.model import *
from sefaria.model.text import TocSerializationOptions
from sefaria.google_storage_manager import GoogleStorageManager
from sefaria.model.text_request_adapter import TextRequestAdapter
from sefaria.model.user_profile import UserProfile, user_link, public_user_data, UserWrapper
Expand Down Expand Up @@ -1829,7 +1830,14 @@ def find_holiday_in_hebcal_results(response):

@catch_error_as_json
def table_of_contents_api(request):
return jsonResponse(library.get_toc(), callback=request.GET.get("callback", None))
include_authors = bool(int(request.GET.get("include_authors", False)))
toc = library.get_toc(serialization_options=TocSerializationOptions(
include_first_section=False,
include_flags=False,
include_base_texts=True,
include_authors=include_authors,
))
return jsonResponse(toc, callback=request.GET.get("callback", None))


@catch_error_as_json
Expand Down Expand Up @@ -2173,6 +2181,15 @@ def _internal_do_delete(request, link_id_or_ref, uid):
obj = tracker.delete(uid, Link, link_id_or_ref, callback=revarnish_link)
return obj

def _get_requested_categories(request):
categories = []
categories += request.GET.getlist("category")
raw_categories = request.GET.get("categories", "")
if raw_categories:
categories += re.split(r"[|,]", raw_categories)
categories = [c.strip() for c in categories if c and c.strip()]
return categories or None

if request.method == "GET":
callback=request.GET.get("callback", None)
if link_id_or_ref is None:
Expand All @@ -2182,7 +2199,8 @@ def _internal_do_delete(request, link_id_or_ref, uid):
Ref(link_id_or_ref)
with_text = int(request.GET.get("with_text", 1))
with_sheet_links = int(request.GET.get("with_sheet_links", 0))
return jsonResponse(get_links(link_id_or_ref, with_text=with_text, with_sheet_links=with_sheet_links), callback)
categories = _get_requested_categories(request)
return jsonResponse(get_links(link_id_or_ref, with_text=with_text, with_sheet_links=with_sheet_links, categories=categories), callback)

if not request.user.is_authenticated:
delete_query = QueryDict(request.body)
Expand Down
7 changes: 6 additions & 1 deletion sefaria/client/wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,13 +161,15 @@ def get_notes(oref, public=True, uid=None, context=1):
return notes


def get_links(tref, with_text=True, with_sheet_links=False):
def get_links(tref, with_text=True, with_sheet_links=False, categories=None):
"""
Return a list of links tied to 'ref' in client format.
If `with_text`, retrieve texts for each link.
If `with_sheet_links` include sheet results for sheets in collections which are listed in the TOC.
If `categories` is provided, only include links whose derived client-facing category matches.
"""
links = []
categories = set(categories) if categories else None
oref = Ref(tref)
nRef = oref.normal()
lenRef = len(nRef)
Expand Down Expand Up @@ -319,4 +321,7 @@ def add_prefix(link):
formatted_sheet_links = [format_sheet_as_link(sheet) for sheet in sheet_links]
links += formatted_sheet_links

if categories is not None:
links = [link for link in links if link["category"] in categories]

return links
31 changes: 26 additions & 5 deletions sefaria/model/category.py
Original file line number Diff line number Diff line change
Expand Up @@ -296,16 +296,22 @@ def _explicit_order_and_title(node):
else:
cat.children.sort(key=_explicit_order_and_title)

def _make_index_node(self, index, old_title=None, mobile=False, include_first_section=False):
d = index.toc_contents(include_first_section=include_first_section, include_flags=False, include_base_texts=True)
def _make_index_node(self, index, old_title=None, mobile=False, serialization_options=None):
serialization_options = serialization_options or text.TocSerializationOptions(
include_first_section=False,
include_flags=False,
include_base_texts=True,
include_authors=False,
)
d = index.toc_contents(serialization_options=serialization_options)

title = old_title or d["title"]

if mobile:
vs = self._vs_lookup.get(title, {})
d["firstSection"] = vs.get("first_section_ref", None)

if "base_text_titles" in d and len(d["base_text_titles"]) > 0 and include_first_section:
if "base_text_titles" in d and len(d["base_text_titles"]) > 0 and serialization_options.include_first_section:
# `d["firstSection"]` assumes `include_first_section` is True
# this code seems to never actually get run
d["refs_to_base_texts"] = {btitle:
Expand All @@ -327,8 +333,8 @@ def _add_category(self, cat):
def get_root(self):
return self._root

def get_serialized_toc(self):
return self._root.serialize().get("contents", [])
def get_serialized_toc(self, serialization_options=None):
return self._root.serialize(serialization_options=serialization_options).get("contents", [])

def get_collections_in_library(self):
return self._collections_in_library
Expand Down Expand Up @@ -510,6 +516,20 @@ def __init__(self, serial=None, **kwargs):
def get_index_object(self):
return self._index_object

def serialize(self, **kwargs):
d = super(TocTextIndex, self).serialize(**kwargs)
serialization_options = kwargs.get("serialization_options") or text.TocSerializationOptions(
include_first_section=False,
include_flags=False,
include_base_texts=True,
include_authors=False,
)
if serialization_options.include_authors and self._index_object:
authors = self._index_object.toc_contents(serialization_options=serialization_options).get("authors")
if authors:
d["authors"] = authors
return d

optional_param_keys = [
"categories",
"dependence",
Expand All @@ -524,6 +544,7 @@ def get_index_object(self):
"base_text_titles",
"base_text_mapping",
"heCollectiveTitle",
"authors",
"commentator",
"heCommentator",
"refs_to_base_texts",
Expand Down
Loading
Loading