0

I've tried to understand how and why I haven't seen any answers to this specific question.

I have two functions each has an argument path

def check_sbb_name(path):
    if path is None:
        DeltaZero_Selenium_Manager.test_sbb_name_textfield(path)
        return path
    else:
        call = sbb_manager_sql()
        name = call.get_new_sbb_name()
        DeltaZero_Selenium_Manager.test_sbb_name_textfield(name)
        
        create_new_sbb("", name)
def check_sites_for_sbb(path):
    if path is None:
        DeltaZero_Selenium_Manager.test_site_combo_options_alternative_overview(path)
    else:
        call = sbb_manager_sql()
        site = call.connect_site()
        DeltaZero_Selenium_Manager.test_site_combo_options_alternative_overview(site)
        
        create_new_sbb(site, "")

Just ignore everything these functions actually do, cause everything works just perfectly until I want to pass on name & site to the following create_new_sbb function

def create_new_sbb(site_name, sbb_name):
    mycursor.execute("INSERT INTO sbb_data (site, name, is_deleted) VALUES (%s, %s, %s)",
                         (site_name, sbb_name, 0))
    db.commit()

So I want to pass on these arguments to create_new_sbb at the same time, instead of calling create_new_sbb on each function

Note that create_new_sbb is located in another file

The results in MySql DB:

enter image description here

I want site and name on the same row obviously
So only execute create_new_sbb when both arguments have been passed somehow.

Any help is very appreciated!!!

Herker
  • 552
  • 6
  • 20
  • What do you mean by "calling `create_new_sbb` on each function"? Also, you need a [minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). – jjramsey May 11 '21 at 12:03
  • What do you mean "only execute `create_new_sbb` if both arguments are passed"? If you try to call the function without its required inputs, you'll get a TypeError. If you pass them as None when they aren't defined, well then, check for None before calling the function. – Reti43 May 11 '21 at 12:06
  • I need to pass my arguments to 'create_new_sbb' and for that, you have to call it right? – Herker May 11 '21 at 12:06
  • @Reti43 - Yes I know, But I wonder if there is a workaround, if not. How can I change to make it work? – Herker May 11 '21 at 12:08
  • 1
    You literally do `create_new_sbb("", name)` in your code. Apparently that results in undesired results, so don't do that. Only call your function when both arguments are not empty strings. It's a simple condition check. – Reti43 May 11 '21 at 12:11
  • @Reti43 - Can you provide an example? – Herker May 11 '21 at 12:13
  • `if site != '' and name != '': create_new_sbb(site, name)` – Reti43 May 11 '21 at 12:14
  • Apparently, you call alternatively `check_sbb_name` and `check_sites_for_sbb`. You should have one to store its argument *somewhere* and the other to use that stored argument to feed the database. – Serge Ballesta May 11 '21 at 12:16
  • @Reti43 - Did not make any difference :( – Herker May 11 '21 at 12:23
  • Can you prove an answer for how to do it? - @SergeBallesta – Herker May 11 '21 at 12:25
  • For that you should explain what `check_ssb_name` and `check_sites_for_ssb` do, how they are used and whether you call them sequentially. Because as is I see no reason you can't fuse both of them together and get both `site` and `name` from `call` at the same time. – Reti43 May 11 '21 at 12:30

2 Answers2

1

First, please consider giving example code of the usage you would make of these functions to make more clear their usage.

To the solution itself, I will propose my solution that uses this:

def func1(value):
    print_two_values(value1 = value)

def func2(value):
    print_two_values(value2 = value)


def static_vars(**kwargs):
    def decorate(func):
        for k in kwargs:
            setattr(func, k, kwargs[k])
        return func
    return decorate

@static_vars(value1="",value2="")
def print_two_values(value1="", value2=""):
    if value1:
        print_two_values.value1 = value1
    
    if value2:
        print_two_values.value2 = value2

    if print_two_values.value1 and print_two_values.value2:
        print(print_two_values.value1, print_two_values.value2)
        print_two_values.value1 = ""
        print_two_values.value2 = ""

func1("Hello")
func2("World")

func2("1")
func1("Test")

func1("This will not")
func1("This will")
func2("be shown")

Which will then result in this output

Hello World
Test 1
This will be shown

Finally, applying this to your code, your create_new_sbb would look like

@static_vars(site_name="",sbb_name="")
def create_new_sbb(site_name="", sbb_name=""):
    if site_name:
        create_new_sbb.site_name = site_name

    if sbb_name:
        create_new_sbb.sbb_name = sbb_name

    if create_new_sbb.site_name and create_new_sbb.sbb_name:
        mycursor.execute("INSERT INTO sbb_data (site, name, is_deleted) VALUES (%s, %s, %s)",
                            (create_new_sbb.site_name, create_new_sbb.sbb_name, 0))
        db.commit()
        create_new_sbb.site_name = ""
        create_new_sbb.sbb_name = ""

and then to set site_name you just call create_new_sbb(site_name="site name") and for sbb_name you just call create_new_sbb(sbb_name="sbb name").

This solution has some limitations, like shown in the previous output if you are not careful with the order you can have data loss, which can easily happen in multi-thread scenarios, in which case you have a number of potential solutions to avoid creating a bottleneck in this function (instead of N variables, create a buffer array where you have N_thread * N_variable as index for each variable) but this is out of the scope of this answer.

Sandro Massa
  • 98
  • 1
  • 10
0

I will assume here that you always call check_sbb_name and check_sites_for_sbb in pairs with the same path. I would use:

cur_path = None
cur_name = None
cur_site = None

def check_sbb_name(path):
    ...    
    register_name(path, name)      # only register

def check_sites_for_sbb(path):
    ...
    register_site(path, site)      # only register

def register_name(path, name):
    if (path == cur_path) and (cur_site is not None): # other element already registered
        create_new_sbb(cur_site, name)                # ok, we can insert
    else:
        cur_path = path                               # register for this path
        cur_site = None
    cur_name = name

def register_site(path, site):
    if (path == cur_path) and (cur_name is not None):
        create_new_sbb(site, cur_name)
    else:
        cur_path = path
        cur_name = None
    cur_site = site

The important part is to register elements and only write to the database when you have a pair. Alternative methods (using same principle) could be used if for example you always call check_sbb_name first, then register_name would always register cur_name (no need for path) and register_site would always call create_new_bb. Or...

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252