Importing Your Own Module Python Attribute Error - python-2.7

so I am trying to import my own python module into a new script that I have written. I get the error:
AttributeError: 'module' object has no attribute 'getSessionIds'
In my main file, I am importing as such:
import UnityAppSessionSummary
class ScheduledGenSummaries(DatabaseModule):
def __init__(self):
super(ScheduledGenSummaries, self).__init__()
def run(self):
... (some db connection stuff)
sessionIds = UnityAppSessionSummary.getSessionIds(db, user)
if __name__ == '__main__':
testrun = ScheduledGenSummaries()
testrun.run()
In my UnityAppSessionSummary.py file, I have something as such:
class UnityAppSessionSummary():
# This method is used to obtain a list of all session ID's for a certain user
def getSessionIds(self, db, user):
....code....
I am not sure why I am getting this error and I have looked at other previous posts. I have tried 'import UnityAppSessionSummary as app' and then app.(some function in UnityAppSessionSummary), but it still gives me the error. Thank you in advance.

You have a file UnityAppSessionSummary.py that is being imported when you run
import UnityAppSessionSummary
However, inside that .py file you have a class named UnityAppSessionSummary as well, and inside that is your getSessionIds() method. Try this:
from UnityAppSessionSummary import UnityAppSessionSummary as app
# ...
sessionIds = app.getSessionIds(db, user)

Related

Get access to class attributes

import yaml
class Import_Yaml_Setting():
def __init__(self, path):
self.read_yaml(path)
def read_yaml(self, path):
stream = open(path, 'r')
self.settings = yaml.load(stream)
stream.close()
class MasterDef(Import_Yaml_Setting):
def __init__(self, path):
Import_Yaml_Setting.__init__(self, path)
def function_1():
path = 'path_to_settings\\yaml_file.yaml'
MasterDef(path)
def function_2():
MasterDef.settings
if __name__ == '__main__':
function_1()
function_2()
My plan is it to have a class Import_Yaml_Setting which imports settings from a yaml file. The class MasterDef inherits the class Import_Yaml_Setting.
After 'function_1' calls MasterDef in order to import the settings. I want to do this once in my program. After, I just want to get access to the imported settings
without import them again. This should do function_2.
My problem
I don't know how I have to call MasterDef at the first place. If I would create an instance of MasterDef them I wouldn't have access to this instance in function_2.
Also, I get an error that says MasterDef has no attribute settings.
What would be the right way to do this.
There are a few things incorrect, so lets start with the most obvious.
If you have a class MasterDef, calling MasterDef() creates an instance
of that class. If you don't assign that to a variable, that instance will
immediately disappear.
Doing MasterDef.settings later on could work if the class had a
class attribute or method called settings, but in that case you are not accessing
the settings attribute on an instance.
Typical such global settings are passed around, or implemented as a function object that
does the loading only once, or are made into a global variable (as
shown in the following example). Simplified you would do:
from __future__ import print_function, absolute_import, division, unicode_literals
class MasterDef(object):
def __init__(self):
self.settings = dict(some='setting')
master_def = None
def function_1():
global master_def
if master_def is None:
master_def = MasterDef()
def function_2():
print('master_def:', master_def.settings)
if __name__ == '__main__':
function_1()
function_2()
which gives:
master_def: {'some': 'setting'}
A few notes to the above:
If, for whatever reason, you are doing anything new on Python 2.7
make things more Python3 compatible by including the from
__future__ import as indicated. Even if you are just using the
print function (instead of the outdated print statement). It
will make transitioning easier (2.7 goes EOL in 2020)
Again in 2.7 make your base classes a subclass of object, that
makes it e.g. possible to have properties.
By testing that master_def is None you can invoke function_1 multiple
times
You should also be aware that PyYAML load, as is written in its
documentation, can be unsafe when you don't have full control over
your input. There is seldom need to use load() so use safe_load()
or upgrade to my ruamel.yaml package which implements the newer YAML
1.2 standard (released 2009, so there is no excuse for using PyYAML
that still doesn't support that).
As you also seem to be on Windows (assumed from you using \\), consider using raw strings
where you don't need to escape the backslash, using os.path.join(). I am leaving out
your path part in my full example as I am not on Windows:
from __future__ import print_function, absolute_import, division, unicode_literals
import ruamel.yaml
class Import_Yaml_Setting(object):
def __init__(self, path):
self._path = path # stored in case you want to write out the configuration
self.settings = self.read_yaml(path)
def read_yaml(self, path):
yaml = ruamel.yaml.YAML(typ='safe')
with open(path, 'r') as stream:
return yaml.load(stream)
class MasterDef(Import_Yaml_Setting):
def __init__(self, path):
Import_Yaml_Setting.__init__(self, path)
master_def = None
def function_1():
global master_def
path = 'yaml_file.yaml'
if master_def is None:
master_def = MasterDef(path)
def function_2():
print('master_def:', master_def.settings)
if __name__ == '__main__':
function_1()
function_2()
If your YAML file looks like:
example: file
very: simple
the output of the above program will be:
master_def: {'example': 'file', 'very': 'simple'}

Avoiding circular imports in Django Models (Config class)

I've created a Configuration model in django so that the site admin can change some settings on the fly, however some of the models are reliant on these configurations. I'm using Django 2.0.2 and Python 3.6.4.
I created a config.py file in the same directory as models.py.
Let me paracode (paraphase the code? Real Enum has many more options):
# models.py
from .config import *
class Configuration(models.Model):
starting_money = models.IntegerField(default=1000)
class Person(models.Model):
funds = models.IntegarField(default=getConfig(ConfigData.STARTING_MONEY))
# config.py
from .models import Configuration
class ConfigData(Enum):
STARTING_MONEY = 1
def getConfig(data):
if not isinstance(data, ConfigData):
raise TypeError(f"{data} is not a valid configuration type")
try:
config = Configuration.objects.get_or_create()
except Configuration.MultipleObjectsReturned:
# Cleans database in case multiple configurations exist.
Configuration.objects.exclude(Configuration.objects.first()).delete()
return getConfig(data)
if data is ConfigData.MAXIMUM_STAKE:
return config.max_stake
How can I do this without an import error? I've tried absolute imports
You can postpone loading the models.py by loading it in the getConfig(data) function, as a result we no longer need models.py at the time we load config.py:
# config.py (no import in the head)
class ConfigData(Enum):
STARTING_MONEY = 1
def getConfig(data):
from .models import Configuration
if not isinstance(data, ConfigData):
raise TypeError(f"{data} is not a valid configuration type")
try:
config = Configuration.objects.get_or_create()
except Configuration.MultipleObjectsReturned:
# Cleans database in case multiple configurations exist.
Configuration.objects.exclude(Configuration.objects.first()).delete()
return getConfig(data)
if data is ConfigData.MAXIMUM_STAKE:
return config.max_stake
We thus do not load models.py in the config.py. We only check if it is loaded (and load it if not) when we actually execute the getConfig function, which is later in the process.
Willem Van Onsem's solution is a good one. I have a different approach which I have used for circular model dependencies using django's Applications registry. I post it here as an alternate solution, in part because I'd like feedback from more experienced python coders as to whether or not there are problems with this approach.
In a utility module, define the following method:
from django.apps import apps as django_apps
def model_by_name(app_name, model_name):
return django_apps.get_app_config(app_name).get_model(model_name)
Then in your getConfig, omit the import and replace the line
config = Configuration.objects.get_or_create()
with the following:
config_class = model_by_name(APP_NAME, 'Configuration')
config = config_class.objects.get_or_create()

How to fix circular importing?

It seems I have a circular importing error. I currently just struggling to fix it. Does anyone know what I should do?
In my models.py, containing ReservedItems & Order:
def reserveditem_pre_save_receiver(sender, instance, **kwargs):
if not instance.order_reference:
instance.order_reference = unique_order_reference_generator()
In my utils.py
from lumis.utils import get_random_string
from .models import Order, ReservedItem
def unique_order_reference_generator():
new_id = get_random_string(length=10)
reserved_item = ReservedItem.objects.filter(
order_reference=new_id
).exists()
order = Order.objects.filter(order_reference=new_id).exists()
if reserved_item or order:
return unique_order_reference_generator()
else:
return new_id
You can import modules locally in the body of the function, so:
from lumis.utils import get_random_string
def unique_order_reference_generator():
from .models import Order, ReservedItem
new_id = get_random_string(length=10)
reserved_item = ReservedItem.objects.filter(
order_reference=new_id
).exists()
order = Order.objects.filter(order_reference=new_id).exists()
if reserved_item or order:
return unique_order_reference_generator()
else:
return new_id
This thus means that the module is not loaded when Python loads the file, but when the function is actually called. As a result, we can load the unique_order_reference_generator function, without having to load a the module that actually depends on this function.
Note that, like #Alasdair says, signals are typically defined in a dedicated file (signals.py) for example which should be loaded in the ready() function of the app. But regardless how you structure code, frequently local imports should be used to avoid circular imports.
All the current suggestions are good. Move your signal handlers out of models. Models are prone to circular imports because they are used everywhere, so it is a good idea to keep only model code in models.py.
Personally, I don't like imports in the middle of the code
import-outside-toplevel / Import outside toplevel
Instead I use Django application API to load models without importing
from django.apps import apps
def signal_handler(instance, *args, **kwargs):
Order = apps.get_model('your_app', 'Order')
...

How to mock redis for Django tests

I am trying to mock out redis in my Django application. I have tried several different methods but none seem to work. What am I doing wrong?
My primary redis instance is called with:
redis_client = redis.from_url(os.environ.get("REDIS_URL"))
That instance is imported in other parts of the app in order to add and retrieve data.
In my tests I tried doing:
import fakeredis
from mock import patch
class TestViews(TestCase):
def setUp(self):
redis_patcher = patch('redis.Redis', fakeredis.FakeRedis)
self.redis = redis_patcher.start()
self.redis.set('UPDATE', 'Spring')
print(redis_client.get('UPDATE'))
def tearDown(self):
self.redis_patcher.stop
When running the tests I want the 'UPDATE' variable to be set. But instead every instance of redis_client fails saying the server is not available. How can I mock out redis and set values, so that they are available when testing my app?
You should mock an item where it is used, not where it came from.
So if redis_client is used in a view like this:
myapp/views.py
from somemodule import redis_client
def some_view_that_uses_redis(request):
result = redis_client(...)
Then in your TestViews you should patch redis_client like this:
class TestViews(TestCase):
def setUp(self):
redis_patcher = patch('myapp.views.redis_client', fakeredis.FakeRedis)
self.redis = redis_patcher.start()

How to add a event to a function from parent class without changing the previous code

I am making a GUI in Pyqt4
I have a main.py file which has a structre like this:
Main.py
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName(_fromUtf8("MainWindow"))
MainWindow.resize(1291, 893)
self.pushButton_3 = QtGui.QPushButton(self.newDealer)
self.pushButton_3.setMinimumSize(QtCore.QSize(100, 0))
self.pushButton_3.setMaximumSize(QtCore.QSize(16777212, 16777215))
self.pushButton_3.setObjectName(_fromUtf8("pushButton_3"))
self.horizontalLayout_4.addWidget(self.pushButton_3)
and I have another file test.py which has structure like this
test.py
from main import *
class myclass(Ui_MainWindow):
def foo(self):
print("Hello")
def setupUi(self,MainWindow):
pushButton_3.clicked.connect(self.foo) #I want to find correction here
When I Execute test.py .I get this error
Traceback (most recent call last):
File "test.py", line 24, in <module>
ui.setupUi(MainWindow)
File "test.py", line 15, in setupUi
pushButton_3.clicked.connect(self.foo)
NameError: name 'pushButton_3' is not defined
Can Anyone help please??