Where to position `import` modules inside an class? - python

I define a class with multiple methods using standard library.
class Dostuff:
def __init__(self):
pass
def read_book(self):
import os
pass
def listen_music(self):
import os.path
pass
def ask_question(self):
import glob
pass
Where is the suitable place inside a class?
The class will be used as a module for repeated application.

It is good custom to place all your imports at the top of your file. There is a style guide on imports in PEP-8.
https://www.python.org/dev/peps/pep-0008/#imports
In your case:
#!/usr/bin/python3
import os
import os.path
import glob
class Dostuff:
def __init__(self):
pass
def read_book(self):
pass
def listen_music(self):
pass
def ask_question(self):
pass

PEP 8 on imports:
Imports are always put at the top of the file, just after any module comments and docstrings, and before module globals and constants.

You misunderstand the scope of import .
Firstly, It's PEP practice to put module on the top,
secondly and most importantly, it's not about best practice,it works that way.
Every time You import any class or function from your file (or module)
import **run ahead always.

Usually the best practice for importing any type of module is to do it at the top of the file you are writing in. So in your case it would look like this:
import os
import glob
class Dostuff:
def __init__(self):
pass
def read_book(self):
pass
def listen_music(self):
pass
def ask_question(self):
pass

Related

How to elegantly mock a class using pytest fixtures?

Let's say I have a fixture to mock a class using monkeypatch.
# conftest.py
#pytest.fixture
def mock_dummyclass(monkeypatch):
def mock_function():
return None
monkeypatch.setattr(dummypackage, "dummyclass", mock_function)
Now, I have to use this fixture in my test so that this class is mocked.
#test_dummy.py
#pytest.mark.usefixtures("mock_dummyclass")
class TestManyDummyMethods:
def test_dummy_one():
import dummypackage # Flag A
def test_dummy_two():
import dummypackage # Flag B
...
def test_dummy_n():
import dummypackage # Flag N
As you can see in the flagged lines, that I'll have to import this module dummypackage inside every function to ensure that the fixture is applied before the module is imported (otherwise the fixture would not be effective).
Importing dummypackage inside the class would work but calling self.dummypackage inside functions doesn't seem very elegant either.
Is there a more elegant way to achieve this?
Comment: The monkeypatch library doesn't seem to be maintained anymore. unittest.mock should probably offer all you need.
I would try to avoid a solution that depends on importing the module as part of your test because that would break if it was imported for another reason (e.g. import other functions).
I am using os as an example as that exists and makes it reproducible.
How best to patch seem to depend on how you import from another module.
Example 1: target_module1.py (importing the join method from os.path):
from os.path import join
def some_method_using_join():
return join('parent', 'child')
This requires us to patch the join method of target_module1.py:
target_module1_test.py:
from unittest.mock import patch, MagicMock
import pytest
from target_module1 import some_method_using_join
#patch('target_module1.join')
def some_test(join_mock: MagicMock):
some_method_using_join()
Example 2: target_module2.py (importing the os module):
import os
def some_method_using_join():
return os.path.join('parent', 'child')
This allows us to patch the join method on os.path:
target_module2_test.py:
from unittest.mock import patch, MagicMock
import pytest
from target_module2 import some_method_using_join
#patch('os.path.join')
def some_test(join_mock: MagicMock):
some_method_using_join()
This assumes that you don't need to patch a class or method that is used at the module level (i.e. while importing).

Importing a module for all methods of an instance in Python3

I encountered a problem whilst importing a module in a Python3 class:
I am importing a module in the __init__ method of my class. It works fine in this method, however is there a way to use this module again in another method? I tried saving the module into a self. variable, still doesn't work.
Of course I could import it again inside the method, but I would rather import the module for all of my methods, since most of them need it.
I'll give you some example code below:
class Example(object)
def __init__(self):
import moduleName as module
module.function() # works perfectly
# Trying to save module for the whole instance:
self.module = module
def method(self):
module.function() # Does not recognize module
self.module.function() # Does not recognize attribute either
I'd be happy if someone could help me with this:)
I don't know if in python we can save a module in a variable. I attempt to declare the import at class level, but the code doesn't work.
I python the function are first-citizen so we can save function in a variable. You should save the function you need in variables when you are in __init__():
import module as mod
mod.function()
self.function = mod.function
After a while...
You can load a module dinamically, but to this you have to import the module importlib. This is the code:
import importlib
class MyClass:
def __init__(self):
self.module = importlib.import_module("module")
self.module.function()
def func(self):
self.module.function()
c = MyClass()
c.func()
There is also the imp module.

How to mock external module calls and test code in the class body

I want to store static information in a class, shared by all the instances. The information is something obtained by using another module, I only want to do this once, eg. let's say that this is what I have in mymodule.py:
import os
MyClass:
bus = os.environ.get('DBUS_SESSION_BUS_ADDRESS', None)
def __init__(self):
pass
How can I test this code and mock os.environ.get to make sure that the call is made correctly?
Since the execution happens at the time of the first import, I would need to reload the module in the test, but even so, I can't have os.environ.get mocked at the right time:
import unittest
from unittest import patch, MagicMock
import importlib
import mymodule
class TestMyClass(unittest.TestCase):
#patch('mymodule.os.environ', spec=['get'])
def test_class_init_patch(self, mock_env):
# Too early - the reload overrides the mock
importlib.reload(mymodule)
mock_env.get.assert_called_once_with('DBUS_SESSION_BUS_ADDRESS', None)
def test_class_init_mock(self):
importlib.reload(mymodule)
# Too late - the class body already executed
mymodule.MyClass.os.environ = MagickMock()
I have managed to come up with two alternatives, that make this testable:
Move the class initialization code into a class method and call it from the class body. I can test this class method in my unit test.
Move the class initialization into the __init__ method, guarded by a flag stored in a class variable so that it is only initialized once on the first instantiation.
While both of these should work just fine, it just feels more clean and straightforward to leave this in the class body if possible.
I have managed to figure out how to do this the right way (I hope)!
If you have imported only the module and not the class, function into your code's namespace, eg.:
like this: import os
and not like this: from os import geteuid
You can do this in your test to patch the os module directly:
import os
import unittest
from unittest import patch
import importlib
import mymodule
class TestMyClass(unittest.TestCase):
#patch('os.environ.get')
def test_class_init_patch(self, mock_env_get):
importlib.reload(mymodule)
mock_env_get.assert_called_once_with('DBUS_SESSION_BUS_ADDRESS', None)
This is described in the official documentation as well:
However, consider the alternative scenario where instead of from a import SomeClass module b does import a and some_function uses a.SomeClass. Both of these import forms are common. In this case the class we want to patch is being looked up in the module and so we have to patch a.SomeClass instead:
More details in the official documentation.
This way the module is being patched directly and reloading your own module doesn't affect the patching.
Once the test has run, the patching of the module is undone as usual, however, keep in mind, that the state of your class remains the same way as it was initialized while the external module was patched, so you might need to reload the module again before you run your other tests.
The easiest way to make sure, that you reclaim your "normal" class state, is to reload the module in your TestCase object's setUp method, eg.:
def setUp(self):
importlib.reload(mymodule)

What is the right way to import modules inside my class

I am new to python and I'm trying to add math module inside my class but I don't know what is the right way adding it
import math
class myClass():
#some code
or
class myClass():
import math
#some code
What is the right way the first or the second one?
Anything declared inside a class definition becomes a class variable, a module included, so by importing math within a class definition, it becomes a class variable that is accessible only via the class object or the instance object, so:
class myClass:
import math
def __init__(self, value):
self.value = value
def sqrt(self):
return math.sqrt(self.value)
print(myClass(4).sqrt())
would result in:
NameError: name 'math' is not defined
but changing the sqrt method to:
def sqrt(self):
return self.math.sqrt(self.value)
would properly output:
2.0
That said, there is usually no good reasons to import modules as class variables. In the vast majority of cases modules are imported outside the class, as global variables.

Correct way to import a class from a package in Python

I have a class like this in package a:
class A:
#staticmethod
def method(param1, param2):
...
return something
And in a python file:
from a import A
print(A.A.method(p1,p2))
What is wrong in my definitions? I think isn't correct to call a static method by `Class.Class.method'.
Screenshots with errors:
[EDIT after question was updated with picture]
So your top-level app is called a you can see this in the picture just under "Information" on the left in the picture. Then you have a module called A, which you can see the file A.py just under the folder a. This module A has the class called A
so when you do from a import A you are importing the file A.py
That file has a class A() which has def method(p1, p2)
You say A.A.method() is working... and that would be correct
It now becomes
from a import A
print(A.A.method(p1,p2)
Alternatively
import a
print(a.A.A.method(p1,p2)
Or
from a.A import A
print(A.method(p1, p2)
My advice: start using some more descriptive names, not a for top
level package and A for module and A for class

Categories

Resources