(request, title)
API for retrieving a shape document for a given text or category.
    For simple texts, returns a dict with keys:
	{
		"section": Category immediately above book
		"heTitle": Hebrew title of node
		"length": Number of chapters
		"chapters": List of Chapter Lengths (think about depth 1 & 3)
		"title": English title of node
		"book": English title of Book
	}
    For complex texts or categories, returns a list of dicts.
    :param title: A valid node title or a path to a category, separated by /.
    The "depth" parameter in the query string indicates how many levels in the category tree to descend.  Default is 2.
    If depth == 0, descends to end of tree
    The "dependents" parameter, if true, includes dependent texts.  By default, they are filtered out.
API for retrieving a shape document for a given text or category.
    For simple texts, returns a dict with keys:
	{
		"section": Category immediately above book
		"heTitle": Hebrew title of node
		"length": Number of chapters
		"chapters": List of Chapter Lengths (think about depth 1 & 3)
		"title": English title of node
		"book": English title of Book
	}
    For complex texts or categories, returns a list of dicts.
    :param title: A valid node title or a path to a category, separated by /.
    The "depth" parameter in the query string indicates how many levels in the category tree to descend.  Default is 2.
    If depth == 0, descends to end of tree
    The "dependents" parameter, if true, includes dependent texts.  By default, they are filtered out.
API for retrieving a shape document for a given text or category . For simple texts returns a dict with keys : { section : Category immediately above book heTitle : Hebrew title of node length : Number of chapters chapters : List of Chapter Lengths ( think about depth 1 & 3 ) title : English title of node book : English title of Book } For complex texts or categories returns a list of dicts . : param title : A valid node title or a path to a category separated by / . The depth parameter in the query string indicates how many levels in the category tree to descend . Default is 2 . If depth == 0 descends to end of tree The dependents parameter if true includes dependent texts . By default they are filtered out .
def shape_api(request, title):
    """
    API for retrieving a shape document for a given text or category.
    For simple texts, returns a dict with keys:
	{
		"section": Category immediately above book
		"heTitle": Hebrew title of node
		"length": Number of chapters
		"chapters": List of Chapter Lengths (think about depth 1 & 3)
		"title": English title of node
		"book": English title of Book
	}
    For complex texts or categories, returns a list of dicts.
    :param title: A valid node title or a path to a category, separated by /.
    The "depth" parameter in the query string indicates how many levels in the category tree to descend.  Default is 2.
    If depth == 0, descends to end of tree
    The "dependents" parameter, if true, includes dependent texts.  By default, they are filtered out.
    """
    from sefaria.model.category import TocCollectionNode

    def _simple_shape(snode):
        sn = StateNode(snode=snode)
        shape = sn.var("all", "shape")

        return {
            "section": snode.index.categories[-1],
            "heTitle": snode.full_title("he"),
            "title": snode.full_title("en"),
            "length": len(shape) if isinstance(shape, list) else 1,  # hmmmm
            "chapters": shape,
            "book": snode.index.title,
            "heBook": snode.index.get_title(lang="he"),
        }

    def _collapse_book_leaf_shapes(leaf_shapes):
        """Groups leaf node shapes for a single book into one object so that resulting list corresponds 1:1 to books"""
        if type(leaf_shapes) != list:
            return leaf_shapes

        results = []
        prev_shape = None
        complex_book_in_progress = None

        for shape in leaf_shapes:
            if prev_shape and prev_shape["book"] != shape["book"]:
                if complex_book_in_progress:
                    results.append(complex_book_in_progress)
                    complex_book_in_progress = None
                else:
                    results.append(prev_shape)
            elif prev_shape:
                complex_book_in_progress = complex_book_in_progress or {
                    "isComplex": True,
                    "section": prev_shape["section"],
                    "length": prev_shape["length"],
                    "chapters": [prev_shape],
                    "book": prev_shape["book"],
                    "heBook": prev_shape["heBook"],
                }
                complex_book_in_progress["chapters"].append(shape)
                complex_book_in_progress["length"] += shape["length"]
            prev_shape = shape

        results.append(complex_book_in_progress or prev_shape)

        return results

    title = title.replace("_", " ")

    if request.method == "GET":
        sn = library.get_schema_node(title, "en")

        # Leaf Node
        if sn and not sn.children:
            res = [_simple_shape(sn)]

        # Branch Node
        elif sn and sn.children:
            res = [_simple_shape(n) for n in sn.get_leaf_nodes()]

        # Category
        else:
            cat = library.get_toc_tree().lookup(title.split("/"))

            if not cat:
                res = {"error": "No index or category found to match {}".format(title)}
            else:
                depth = request.GET.get("depth", 2)
                include_dependents = request.GET.get("dependents", False)

                leaves = cat.get_leaf_nodes() if depth == 0 else [n for n in cat.get_leaf_nodes_to_depth(depth)]
                leaves = [n for n in leaves if not isinstance(n, TocCollectionNode)]
                if not include_dependents:
                    leaves = [n for n in leaves if not getattr(n, "dependence", None)]

                res = [_simple_shape(jan) for toc_index in leaves for jan in toc_index.get_index_object().nodes.get_leaf_nodes()]

        res = _collapse_book_leaf_shapes(res)
        return jsonResponse(res, callback=request.GET.get("callback", None))
def shape_api ( request , title ) : from sefaria . model . category import TocCollectionNode def _simple_shape ( snode ) : sn = StateNode ( snode = snode ) shape = sn . var ( "all" , "shape" ) return { "section" : snode . index . categories [ - 1 ] , "heTitle" : snode . full_title ( "he" ) , "title" : snode . full_title ( "en" ) , "length" : len ( shape ) if isinstance ( shape , list ) else 1 , # hmmmm "chapters" : shape , "book" : snode . index . title , "heBook" : snode . index . get_title ( lang = "he" ) , } def _collapse_book_leaf_shapes ( leaf_shapes ) : """Groups leaf node shapes for a single book into one object so that resulting list corresponds 1:1 to books""" if type ( leaf_shapes ) != list : return leaf_shapes results = [ ] prev_shape = None complex_book_in_progress = None for shape in leaf_shapes : if prev_shape and prev_shape [ "book" ] != shape [ "book" ] : if complex_book_in_progress : results . append ( complex_book_in_progress ) complex_book_in_progress = None else : results . append ( prev_shape ) elif prev_shape : complex_book_in_progress = complex_book_in_progress or { "isComplex" : True , "section" : prev_shape [ "section" ] , "length" : prev_shape [ "length" ] , "chapters" : [ prev_shape ] , "book" : prev_shape [ "book" ] , "heBook" : prev_shape [ "heBook" ] , } complex_book_in_progress [ "chapters" ] . append ( shape ) complex_book_in_progress [ "length" ] += shape [ "length" ] prev_shape = shape results . append ( complex_book_in_progress or prev_shape ) return results title = title . replace ( "_" , " " ) if request . method == "GET" : sn = library . get_schema_node ( title , "en" ) # Leaf Node if sn and not sn . children : res = [ _simple_shape ( sn ) ] # Branch Node elif sn and sn . children : res = [ _simple_shape ( n ) for n in sn . get_leaf_nodes ( ) ] # Category else : cat = library . get_toc_tree ( ) . lookup ( title . split ( "/" ) ) if not cat : res = { "error" : "No index or category found to match {}" . format ( title ) } else : depth = request . GET . get ( "depth" , 2 ) include_dependents = request . GET . get ( "dependents" , False ) leaves = cat . get_leaf_nodes ( ) if depth == 0 else [ n for n in cat . get_leaf_nodes_to_depth ( depth ) ] leaves = [ n for n in leaves if not isinstance ( n , TocCollectionNode ) ] if not include_dependents : leaves = [ n for n in leaves if not getattr ( n , "dependence" , None ) ] res = [ _simple_shape ( jan ) for toc_index in leaves for jan in toc_index . get_index_object ( ) . nodes . get_leaf_nodes ( ) ] res = _collapse_book_leaf_shapes ( res ) return jsonResponse ( res , callback = request . GET . get ( "callback" , None ) )