-1

I am receiving the error as "NameError: name 'GetASetting' is not defined".

Log:

[INFO              ] Kivy v1.8.0
Purge log fired. Analysing...
Purge 60 log files
Purge finished !
[INFO              ] [Logger      ] Record log in C:\Users\Sudheer\.kivy\logs\kivy_14-07-18_10.txt
[INFO              ] [Factory     ] 157 symbols loaded
[DEBUG             ] [Cache       ] register <kv.lang> with limit=None, timeout=Nones
[DEBUG             ] [Cache       ] register <kv.image> with limit=None, timeout=60s
[DEBUG             ] [Cache       ] register <kv.atlas> with limit=None, timeout=Nones
[INFO              ] [Image       ] Providers: img_tex, img_dds, img_pygame, img_gif (img_pil ignored)
[DEBUG             ] [Cache       ] register <kv.texture> with limit=1000, timeout=60s
[DEBUG             ] [Cache       ] register <kv.shader> with limit=1000, timeout=3600s
 Traceback (most recent call last):
   File "C:\Kivy180\Python33\lib\runpy.py", line 160, in _run_module_as_main
     "__main__", fname, loader, pkg_name)
   File "C:\Kivy180\Python33\lib\runpy.py", line 73, in _run_code
     exec(code, run_globals)
   File "D:\OS Files\workspace\Org\__main__.py", line 7, in <module>
     from formcontrol import FormControl
   File "D:\OS Files\workspace\Org\formcontrol.py", line 8, in <module>
     from login.logincodes import LoginControl
   File "D:\OS Files\workspace\Org\login\logincodes.py", line 7, in <module>
     from dbcodes.logins import LoginAccess
   File "D:\OS Files\workspace\Org\dbcodes\logins.py", line 2, in <module>
     from dbcodes.settings import GetASetting, SettingList
   File "D:\OS Files\workspace\Org\dbcodes\settings.py", line 31, in <module>
     class SettingList(object):
   File "D:\OS Files\workspace\Org\dbcodes\settings.py", line 36, in SettingList
     FirstRun_Get = GetASetting(FirstRun)
 NameError: name 'GetASetting' is not defined

Both the class and def are in same .py file.

Code:

def Initiation():
    from os import path
    print(Getcwd())
    folderpath=str(Getcwd()) 
    fpath = folderpath + "/orgapp.ini"
    dbpath = folderpath + "/orgapp.db"
    if path.exists(fpath)==False:
        
        #Writing Basic Values
        f = open(fpath,'w')
        setlist=SettingList()
        f.write(setlist.FirstRun+'|True' + '\n')
        f.write(setlist.IniPath+'|'+fpath + '\n')
        f.write(setlist.DBPath+'|'+dbpath + '\n')
        f.close()
        print('File Created')
        
        
        #Creating default database
        CreateDB(dbpath)
        
        return True
    else:
        print('File exists')
        return False

def GetASetting(settingtype):
        if settingtype=='': return None
        path = Getcwd() + '/orgapp.ini'
        f1=open(path,'r')
        for k in f1:
            k=k.replace('\n','')
            c= (k.rsplit(sep='|', maxsplit=2))
            if settingtype.lower() == c[0].lower():
                f1.close()
                if c[1]=='': return None
                else: return c[1]
        f1.close()
        return None
       
class SettingList(object):
    FirstRun = 'FirstRun'
    IniPath='IniPath'
    DBPath='DBPath'
    
    FirstRun_Get = GetASetting(FirstRun)
    IniPath_Get = GetASetting(IniPath)
    DBPath_Get = GetASetting(DBPath)
       
    
    
def Getcwd():
    from os import getcwd
    p=''
    p=getcwd()
    p=p.replace('\\', '/')
    return p
    
def CreateDB(dbpath):
    import sqlite3
    
    conn = sqlite3.Connection(dbpath, detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
    conn.execute('''
    create table login
    (loginid text, password text)    
    ''')
    
    #default user
    id='admin'
    pw='1234'
    conn.execute("insert into login (loginid, password) values (?,?)",(id,pw))
    
    
    conn.commit()
    conn.close()
     

I did a work around by placing the def in class, but, the above code should work, could you please enlighten me as to what error I did above, I checked the names and they are correct?

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
surpavan
  • 1,372
  • 7
  • 34
  • 66

2 Answers2

2

GetASetting needs to exist before you can use it. With the way your code is structured, it does not. Define GetASetting before the class definition.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • I edited the question with full code, when I am changing the places of functions/methods, it is getting effected. I understand what you said now. However, how could I correct that, and is this the correct way to code in python, in VB this flow code would not get effected, could you please explain in more in detail. Thank you for your time. – surpavan Jul 18 '14 at 06:32
  • @surpavan: See my answer below. – balu Jul 18 '14 at 06:51
0

As Ignacio said, GetASetting needs to exist before you can use it. The exact reason is this: Class definitions as well as function signatures (where default values for arguments might contain executable code) are executed when the Python interpreter comes across them for the first time – hence, your function GetASetting needs to exist at this time already. (On the other hand, this also means that you could use if/else and other control flow statements in your class definition, too.)

Anyway, if you do not want this (and you usually don't—due to unintuitive errors like the one you encountered), you should use a constructor for your class:

class SettingList(object):
    # All code in here is executed when the interpreter first
    # encounters the class definition
    def __init__(self): # The same applies for this line
        # This code only run when __init__() is actually called.
        self.FirstRun = 'FirstRun'
        self.IniPath='IniPath'
        self.DBPath='DBPath'

        # Now, the function definition below poses no problem.
        self.FirstRun_Get = GetASetting(FirstRun)
        self.IniPath_Get = GetASetting(IniPath)
        self.DBPath_Get = GetASetting(DBPath)

def GetASetting(settingtype):
    # […]
    return None


# usage example
settings = SettingList()
print(settings.FirstRun_Get) 

This is also a good idea in terms of testability – now every instance of SettingList is initialized upon creation such that, in theory, you could mock out dependencies like file access, i.e. the settings file on your disk.

balu
  • 3,500
  • 4
  • 34
  • 35
  • Yes, but now I need to intantialise the class, is it possible to do wihtout instantialising? like single method etc? – surpavan Jul 18 '14 at 07:11
  • No, you're not initializing the class but an instance of it. Apart from that, the whole point of a class is to create instances of it. If you want global state (which I would avoid, see my statement on testability), don't use a class (or the [evil singleton-pattern](http://stackoverflow.com/q/2551112/36253)) and define it in the module scope, instead. I understand that this is not possible in languages like Java (I don't know about VB) but in Python it is and it makes sense to do it that way. :) – balu Jul 18 '14 at 10:32
  • Of course, you could define a [class method](https://docs.python.org/3/library/functions.html#classmethod) to initialize your class but I would strongly advise against that because 1. you'd introduce global state again, 2. you'd still rely on calling the method at the right time, i.e. before the class is used anywhere else. But now you depend on the order of execution again and completely obscure the dependendies of your code. – balu Jul 18 '14 at 10:41
  • How can be define global variables a Application level, I am using kivy framework, it would be helpful to under stand. – surpavan Jul 18 '14 at 18:05
  • In Python (and thus, Kivy) you can simply define variables in the module scope (= everything that is not indented), e.g. all the functions you defined above live in the module scope. These are then globally accessible in the rest of your module's code simply by their name. Also, you import this module (including its global variables) in another module if needed. Take a look at this [answer](https://stackoverflow.com/questions/44834/can-someone-explain-all-in-python/64130#64130) to a related question but ignore the first two sentences for the time being and look at the code example instead. – balu Jul 19 '14 at 08:42
  • Thank you for sparing your time and sharing knowledge. – surpavan Jul 19 '14 at 09:06
  • Could the downvoter please let me know what's wrong with my answer? Note that the original question apparently was edited while I answering it and the current code no longer matches the original one. In particular, in the original code `GetASetting` was defined *below* the class `SettingList`, not before. – balu Nov 10 '20 at 21:43