Maximum Call Stack Size Exceeded

What I’m trying to do:

My goal is to have a list of non-identical questions & answers available for users to select what their interests are using radio buttons & checkboxes and based on provided answers anvil should hide feedback/questions not related to user input.

What I’ve tried and what’s not working:

I’m assuming to reach my goal I need a ton of if, elif, and else statements to connect multiple questions.

  1. I am unsure if I’m grouping things accordingly. Maybe there’s a better table format instead?
  2. I keep getting maximum call stack size exceedance errors. Assuming Anvil doesn’t like referencing the same design components multiple times. Have tried to see if clearing links helps. But didn’t work.

Code Sample:

# this is a formatted code snippet.
# paste your code between ``` from ._anvil_designer import EnvironmentalToolkitTemplate
from anvil import *
import anvil.tables as tables
import anvil.tables.query as q
from anvil.tables import app_tables
import anvil.server


class EnvironmentalToolkit(EnvironmentalToolkitTemplate):
  def __init__(self, **properties):
    # Set Form properties and Data Bindings.
    self.init_components(**properties)

    # Any code you write here will run before the form opens.

  def form_environmental_show(self, **event_args): #links to startup form homepage
    """This method is called when the form is shown on the page"""
    self.layout.reset_links()
    self.layout.Environmental_Toolkit.role = 'selected'
  
  def COC_Class_show(self, **event_args): #Q1 label event show
    """This method is called when the Label is shown on the screen"""
    
  def PFAS_RB_clicked(self, **event_args): #Q1 radio button event
    """This method is called when this radio button is selected"""

  def PAH_RB_clicked(self, **event_args): #Q1 radio button event
    """This method is called when this radio button is selected"""

  def PCB_RB_clicked(self, **event_args): #Q1 radio button event
    """This method is called when this radio button is selected"""

  def TM_RB_clicked(self, **event_args): #Q1 radio button event
    """This method is called when this radio button is selected"""

  def PFASofInterest_show(self, **event_args): #Q2 radio button event show
    """This method is called when the Label is shown on the screen"""

  def PFASofInterest_hide(self, **event_args): #Q2 radio button event hide
    """This method is called when the Label is removed from the screen"""

  def PFOA_CB_change(self, **event_args): #Q2 checkbox event
    """This method is called when this checkbox is checked or unchecked"""

  def LPFOS_CB_change(self, **event_args): #Q2 checkbox event
    """This method is called when this checkbox is checked or unchecked"""

  def EightTwoFTS_CB_change(self, **event_args): #Q2 checkbox event
    """This method is called when this checkbox is checked or unchecked"""

  #Create Question 1 Group
    self.COC_Class.group_name = "Q1Group"
  
#Contaminant of Concern Class radio button selections
    rb1 = self.PFAS_RB_clicked (group_name="Q1Group", value="A")
    rb2 = self.PAH_RB_clicked (group_name="Q1Group", value="B")
    rb3 = self.PCB_RB_clicked (group_name="Q1Group", value="C")
    rb4 = self.TM_RB_clicked (group_name="Q1Group", value="D")

#Create Question 2 Group
    lb2show = self.PFASofInterest_show (group_name="Q2Group")
    lb2hide = self.PFASofInterest_hide (group_name="Q2Group")
    cb1 = self.PFOA_CB_change (group_name="Q2Group")
    cb2 = self.LPFOS_CB_change (group_name="Q2Group")
    cb3 = self.EightTwoFTS_CB_change (group_name="Q2Group")

    if rb1.selected is True:
      print("Q2Group")

    elif rb1.selected is False:
      self.remove_component(lb2hide)
      self.remove_component(cb1)
      self.remove_component(cb2)
      self.remove_component(cb3)

    if rb2.selected is True:
      print("Q3Group")

    if rb3.selected is True:
      print("Q4Group")
           
    if rb4.selected is True:
      print("Q5Group")

Clone link:
share a copy of your app

Welcome to the Forum!

I can help with problem 2:

Now look at the first and last lines quoted below:

Do you see the connection to Maximum Call Stack Size Exceeded?

I know multiple events are referenced within my code. Am I supposed to try and remove one to fix the cell stack size error?

When I previously had "self.EightTwoFTS_CB (group_name=“Q2Group” I got an error message that it wasn’t callable. So maybe it’s all based on the formatting issue for grouping?

Here is what happens when you call the function self.EightTwoFTS_CB_change:

  • rb1 is defined by calling self.PFAS_RB_clicked
  • rb2 is defined by calling self.PAH_RB_clicked
  • […]
  • cb3 is defined by calling self.EightTwoFTS_CB_change, and at this time this happens:
    • rb1 is defined by calling self.PFAS_RB_clicked
    • rb2 is defined by calling self.PAH_RB_clicked
    • […]
    • cb3 is defined by calling self.EightTwoFTS_CB_change, and at this time this happens:
      • rb1 is defined by calling self.PFAS_RB_clicked
      • rb2 is defined by calling self.PAH_RB_clicked
      • […]
      • cb3 is defined by calling self.EightTwoFTS_CB_change, and at this time this happens:
        • rinse, repeat…

Python can do that a few hundreds or thousands times, then it gives up and says the stack (containing the list of pending calls waiting for their result) is full.

You can’t call a function from inside the same function.

Well, you can create a recursive function, but you need to put a conditional exit to stop the infinite recursion (see the classic fibonacci example).

1 Like

In short, before self.EightTwoFTS_CB_change can finish, it calls itself, and that call must finish before the outer call can finish.

But that inner call behaves exactly the same: it can’t finish until its invocation of self.EightTwoFTS_CB_change finishes.

As @stefano.menci points out, nothing in your code breaks this cycle. So none of these (recursive) function invocations ever gets to finish. The list (stack) of unfinished work just keeps growing, until it reaches its limit.

Perhaps it’s time to rethink what these functions do, and which of them is really in charge.

Also, if you do need the recursion in your function, I’d recommend taking a look at this tutorial for how to break the loop effectively:

2 Likes