Define Python class in separate file - python-3.x

# File 1
me = MongoEngine(app) # I want to use my instance of MongoEngine to define new classes like the example in File 2
# File 2
class Book(me.Document):
title = StringField(null=False, unique=True)
year_published = IntField(null=True)
How can i pass the instance me.Document as an Object definition when creating my new classes in a new file. It works if i put them in the same file?

I believe that the answer choosen as answer is not fully correct.
It seems that File1.py is your main script which is executed,
and File2.py is a module which contains a class you wish to use in File1.py
Also based on a previous question of the OP I would like to suggest the following structure:
File1.py and File2.py are located in the same direcory
File1.py
import MongoEngine
from File2 import Book
me = MongoEngine(app)
# according to the documentation
# you do need to pass args/values in the following line
my_book = Book(me.Document(*args, **values))
# then do something with my_book
# which is now an instance of the File2.py class Book
File2.py
import MongoEngine
class Book(MongoEngine.Document):
def __init__(self, *args, **kwargs):
super(Book, self).__init__(*args, **kwargs)
# you can add additional code here if needed
def my_additional_function(self):
#do something
return True

In File 2 perform import of the me object:
from file1 import me
class Book(me.Document):
pass
# ...

Just like any Python object in a file, me can be imported. You can do it like so:
import file1
class Book(file1.me.Document):
#Do what you want here!
Hope I have helped!

Related

Is it possible to make a module available as an import from another module?

I'm refactoring some code and have moved around some files. But for backwards compatibility, I would like to make all of my modules keep their old import paths.
my file structure is as follows
--| calcs/
----| __init__.py
----| new_dir
------| new_file1.py
------| new_file2.py
What do I need to do ensure that I can use an import like
import calcs.newfile1.foo
# OR
from calcs.newfile1 import foo
I have tried a few methods of adding the imports to the top level __init__.py file. As is reccommended here
But while this seems to allow an import such as import calcs.newfile1, An import such as import calcs.newfile1.foo raises ModuleNotFoundError: No module named calcs.newfile1
I expect that I need python to recognize calcs.newfile1 as a **module **. At the moment it seems to just be importing it as a class or other object of some sort
The only way i know how to do it is by creating a custom import hook.
Here is the PEP for more information.
If you need some help on how to implement one, i'll suggest you to take a look at the six module,
here
and here
Basically your calcs/__init__.py will become like this:
''' calcs/__init__.py '''
from .new_dir import new_file1, new_file2
import sys
__path__ = []
__package__ = __name__
class CalcsImporter:
def __init__(self, exported_mods):
self.exported_mods = {
f'{__name__}.{key}': value for key, value in exported_mods.items()
}
def find_module(self, fullname, path=None):
if fullname in self.exported_mods:
return self
return None
def load_module(self, fullname):
try:
return sys.modules[fullname]
except KeyError:
pass
try:
mod = self.exported_mods[fullname]
except KeyError:
raise ImportError('Unable to load %r' % fullname)
mod.__loader__ = self
sys.modules[fullname] = mod
return mod
_importer = CalcsImporter({
'new_file1': new_file1,
'new_file2': new_file2,
})
sys.meta_path.append(_importer)
and you should be able to do from calcs.new_file1 import foo

Importing an class and its functionalities from one file to another

I am basically working with python(beginner) on jupyter notebook and stuck on importing a python file into another python file.I am working on an assignment it has 2 files a , b while making a class in file 'a' and importing that file into b to test the function that i have implemented in class of file a but didn't get answer
I tried this line for importing file 'a' in 'b' like this but unable to import
To demonstrate you i created a little sample.
Both files are in the same directory.
# file: a.py
class A:
def printing_method(self):
"""this is the method that prints the output"""
print('Class A said: hello world')
# file: b.py
# import class A from module a
from a import A
class B:
def not_printing_method(self):
"""here we create an instance of the imported class A"""
a_instance = A()
# call the method of class B to print
a_instance.printing_method()
# Create an instance of class B
b_instance = B()
# Call the printing method of class A through the not printing method of class B
b_instance.not_printing_method()

Python - Mock class init that instantiates another class inside

I have the following python file board.py:
def __init__(self, language):
self.foo = Foo(language)
self.words = Aux(self.foo)
And I'm creating this test_file:
#classmethod
def setUpClass(cls):
super().setUpClass()
cls.board = Board('pt')
def test_total_time(self):
self.board.total_time(True)
#some assert
But I'm getting a FileNotFoundError because Aux.___init____() calls a self.foo.method() that opens a file and reads from it.
Is there a way to mock self.foo.method(), or the class Aux?
You will want to patch the module. If you give me the name of the test file and the class you are testing. I can finish this answer for you.
In the test file:
import unittest
def BoardTestCase(unittest.TestCase):
#classmethod
def setUpClass(cls):
super().setUpClass()
cls.aux_mock = unittest.mock.patch('file_undertest.Aux')
cls.board = Board('pt')
def test_total_time(self):
self.board.total_time(True)
#some assert
I would suggest using pytest instead of the standard library unittest. Your tests will be written as functions meaning you can reuse the Board class only when needed to. You can set more robust fixtures (Board class test cases) and the mocker extension is more intuitive if you spend the 15 minutes to wrap your head around it.

How to mock readlines() in Python unit tests

I am trying to write a unit test to a class init that reads from a file using readlines:
class Foo:
def __init__(self, filename):
with open(filename, "r") as fp:
self.data = fp.readlines()
with sanity checks etc. included.
Now I am trying to create a mock object that would allow me to test what happens here.
I try something like this:
TEST_DATA = "foo\nbar\nxyzzy\n"
with patch("my.data.class.open", mock_open(read_data=TEST_DATA), create=True)
f = Foo("somefilename")
self.assertEqual(.....)
The problem is, when I peek into f.data, there is only one element:
["foo\nbar\nxyzzy\n"]
Which means whatever happened, did not get split into lines but was treated as one line. How do I force linefeeds to happen in the mock data?
This will not work with a class name
with patch("mymodule.class_name.open",
But this will work by mocking the builtin directly, builtins.open for python3
#mock.patch("__builtin__.open", new_callable=mock.mock_open, read_data=TEST_DATA)
def test_open3(self, mock_open):
...
or this without class by mocking the module method
def test_open(self):
with patch("mymodule.open", mock.mock_open(read_data=TEST_DATA), create=True):
...
#Gang's answer pointed me to the right direction but it's not a complete working solution. I have added few details here which makes it a working code without any tinkering.
# file_read.py
def read_from_file():
# Do other things here
filename = "file_with_data"
with open(filename, "r") as f:
l = f.readline()
return l
# test_file_read.py
from file_read import read_from_file
from unittest import mock
import builtins
##mock.patch.object(builtins, "open", new_callable=mock.mock_open, read_data="blah")
def test_file_read(mock_file_open):
output = read_from_file()
expected_output = "blah"
assert output == expected_output

How to import a variable that is in a class, from one file to another?

File 1
#file1
from tkinter import *
class UI:
def __init__(self):
self.main_window = Tk()
sam = 'TestWord'
import file2
def run(self):
self.main_window.mainloop()
def main():
ui = UI()
ui.run()
main()
File 2
#file2
from file1 import sam
print(sam)
Output
from file1 import sam
builtins.ImportError: cannot import name 'sam'
How can I import sam when it is in a class? I know how to do this without the class present. Also, this code opens two GUI's which must be part of the problem, but I'm completely lost at this point. Do both variables have to be self.sam? So, self.sam = 'TestWord' and import self.sam. I have tried this and it didn't work, however, I might be missing a detail here. Any help will be appreciated.
problem is import file2 will not run the code for you. It happens only on python REPL.
you could do something like below,
File1:
from tkinter import *
class UI:
def __init__(self):
self.main_window = Tk()
sam = 'TestWord'
from file2 import foo
foo(sam)
def run(self):
self.main_window.mainloop()
def main():
ui = UI()
ui.run()
main()
File2:
def foo(sam):
print(sam)
So your main() doesn't run when you import file1, only when you run file1 use
if __name__ == '__main__':
main()
Additionally you can't access sam inside the class, this isn't a matter of files in this case, to access it from outside the class you either need to make it global, or use self.sam = ... and have an instance of your class.
Even better is to have file2 contain methods that use the sam value which you import into your file1.
Without seeing your actual use case I can't provide any other methods of achieving what you want, but you really should not make it global to access from another file.

Resources