Unable to instantiate a class defined in a subdirectory - python

My (simplified) project layout is as follows:
/__init__.py
/test.py
/lib/__init__.py
/lib/client.py
my test.py is simply:
import lib.client
A = client()
A.Test()
and my lib\client.py begins as follows:
import ui #(another class in the lib dir)
class client(object):
"""
(Blah)
"""
UI = None
def __init__():
UI = ui()
def Test():
print "Success"
When I attempt to run test.py, I can step into the code and see that the definitions in client are parsed, however, when I get to the line where I instantiate a client, I get the following exception:
NameError: name 'client' is not defined
if I change that line to be:
A = lib.client()
Then I get
'module' object is not callable
What am I missing?

the lib.client object you have after import lib.client is the module, not the class. To instantiate the class you need to call the class in the module object:
A = lib.client.client()
or, as #rantanplan said, import the class from the module
from lib.client import client
A = client()

I just understood that you do the imports the Java way.
In python when you do :
import lib.client
You don't make available all the definitions in that module. You just
made available the actual module - the client.py
So either you keep the import scheme as you have now and do
import lib.client
A = lib.client.client()
or
from lib.client import client
A = client()
Also I suggest you name your python classes with capitalized camelcase
i.e.
class Client(object):
As it is the python convention.

Related

How to populate global namespace by import?

I have written a library that is roughly structured like this:
# file library/module/core.py
class MyClass:
backend = DesignatedBackend()
# file library/backends/backend_A.py
class DesignatedBackend:
who = "I'm backend A"
# file library/backends/backend_B.py
class DesignatedBackend:
who = "I'm backend B"
Then in IPython, or when running a script I would like to be able to write:
>>> from library.module.core import MyClass
>>> import library.backends.backend_A # or something
>>> print(MyClass().backend.who)
I'm backend A
i.e. I would like to set which classes are available in the global namespace of the library by issuing an appropriate import statement.
Because your core file doesn't import anything it can't resolve what DesignatedBackEnd is. Even if you could somehow inject the DesignatedBackEnd into the namespace of core it would be too late, as the core module can't exist until you import it, and that import will fail.
You could 'contrive' to have a factory method in core, so you import the core module, inject into the namespace and then dynamically create the appropriate class.
But the nicest way to do this is use composition :
# file library/module/core.py
class MyClass:
def __init__(self, backend_type):
self.backend = backend_type()
# file library/backends/backend_A.py
class DesignatedBackend:
who = "I'm backend A"
# file library/backends/backend_B.py
class DesignatedBackend:
who = "I'm backend B"
This way you can do :
>>> from library.module.core import MyClass
>>> from library.backends.backend_A import DesignatedBacEnd # or something
>>> print(MyClass(DesignatedBackEnd).backend.who)
I'm backend A

python: call a class from a script in a different directory and get function

I have a script that I am currently working on, named exp1.py and it's located in
/project/exp1.py
In this script, I am trying to call a function named computelikelihood(), which is inside the class Class(), which is in script method.py, in a different directory:
/project/methods/c_CLASS/method.py
So, in my code in exp1.py, I do this:
import sys
sys.path.append('/project/methods/c_CLASS/')
Which gets me to the folder where method.py is located, but when I want to call the Class() from the method.py, so that I get the function computelikelihood(), that I actually want, I get error. I try this:
from method import Class
from Class import computelikelihood
But I get ImportError: No module named Class. Can anyone help?
EDIT
This is how the __init__ of my Class looks like:
class Class:
def __init__(self,e2wl,w2el,label_set):
self.e2wl = e2wl
self.w2el = w2el
self.workers = self.w2el.keys()
self.examples = self.e2wl.keys()
self.label_set = label_set
Since you are trying to use a method from a Class, you should do so via the class. Do not import the function alone as it isn't intended to be used as such:
from method import Class
Class.computelikelihood()
However, this only works if computelikelihood is a static/class method:
class Class:
#classmethod
def computelikelihood(cls):
...
# or
#staticmethod
def computelikelihood():
...
If it's an instance method:
class Class:
def computelikelihood(self):
...
You'll need to first instantiate an object of class Class:
from method import Class
classObject = Class()
classObject.computelikelihood()

How to reference unittest TestClass attribute in #patch decorator

I want to make use of my tempfile module to write files in my test case.
But I am having trouble referencing it when usinng mock.patch
Supposed I have this code, notice the patch as it is referencing the self.test_dir
import unittest
from unittest.mock import patch
import tempfile
class TestSomething(unittest.TestCase):
def setUp(self):
self.test_dir = tempfile.TemporaryDirectory()
def tearDown(self):
# Close the file, the directory will be removed after the test
self.test_dir.cleanup()
#patch("sample_module.SampleClass.base_url", self.test_dir)
def test_override(self):
pass
Running this code will result to this error
NameError: name 'self' is not defined
As the test_dir is being initialized in the setup and tearDown method then how can I make use of this tempfile.TemporaryDirectory
Any thoughts?

Testing class initializer using unittest in python

I am using unittest module for writing tests.
I need to test initialization of the object inside a testcase using different inputs.
For this purpose I am importing the class inside setUp(). But when I try to use the class inside test_*() functions, I get this error - NameError: name 'Example' is not defined
Here is my code sample-
import unittest
class TestExample(unittest.TestCase):
def setUp(self):
import Example
def test_sample_function(self):
e = Example(1,2)
I know that I can simply import the class at top of the script. But I do not want to do that. I need to import it only during setup of the testscript.
Looking for some help here.
import unittest
class TestExample(unittest.TestCase):
def setUp(self):
import Example
self.Example = Example
def test_sample_function(self):
e = self.Example(1,2)
There's no reason to import the module in setUp. The module is still available globally in sys.modules, but you've only bound it to a local name that goes away after setUp returns. Just import it globally.
import unittest
import Example
class TestExample(unittest.TestCase):
def test_sample_function(self):
e = Example(1,2)

NameError: name is not defined. Circular Importing

I am having difficulty with a circular import problem. I have 2 class files like so:
--/service
service_module.py
settings.py
service_module imports other various files used throughout the project and acts as a container for various functions throughout the project. I want to assert in my settings.py file that it is properly passed an instance of the service_module parent class. Removing the assert statement in settings.py fixes the issue and I am able to properly call methods in the service_module class. For code completion and error checking it makes my life easier to assert.
I have always struggled with understanding python imports but is this the right direction to handle my particular case?
service_module.py
from PyQt5.QtCore import QObject
from sqlalchemy import *
from sqlalchemy.orm import scoped_session, Session, sessionmaker
from service.logger import logger
from sqlalchemy.orm.exc import NoResultFound
from database.tables import *
from database.load_db import load_db
from service.settings import settings
from service.web_listener import web_listener
from service.character_manager import character_manager
class Service_Module(QObject):
def __init__(self):
super(Service_Module, self).__init__()
load_database = load_db()
self.sc_session: scoped_session = load_database.get_scoped_session()
tb_scopes.make_default_scopes(service_module=self)
self.logger = logger(service_module=self)
self.settings = settings(service_module=self)
self.characters = character_manager(service_module=self)
self.callback_listener: web_listener = web_listener(service_module=self)
self.callback_listener.start()
assert isinstance(self.sc_session, scoped_session)
assert isinstance(self.logger, logger)
assert isinstance(self.settings, settings)
assert isinstance(self.callback_listener, web_listener)
settings.py
from service.service_module import *
class settings(QObject):
def __init__(self, service_module):
super(settings, self).__init__()
self.service = service_module
assert isinstance(self.service, Service_Module) ##raises NameError: name 'Service_Module' is not defined
Edit:
So changing to this solves my issue although I feel like it's kind of hacky and somehow incorrect.
from service.service_module import *
import service.service_module
class settings(QObject):
def __init__(self, service_module):
super(settings, self).__init__()
self.service = service_module
assert isinstance(self.service, service.service_module.Service_Module)
You need to delay the importing of one (or both) of the files, to break the circular import. You can do this by moving the import statement from file-scope (where it is executed as soon as the module is imported) into the execution scope of a function or method, where is not executed until that method is called. Ie)
class setting(QObject):
def __init__(self, service_module):
from service.service_module import Service_Module # <-- import is here
assert isinstance(self.service, Service_Module)
Of course, this may affect other usages of the imported symbols from that module into this file, so you may need to specify the import in more than one place.

Categories