I want to programmatically get the source code for a given class property (e.g., pandas.DataFrame.iloc). I tried using inspect.findsource(), which works fine for classes and functions. However, it doesn't work for properties.
import pandas
import inspect
type(pandas.DataFrame) # type
inspect.findsource(pandas.DataFrame) # works ok
type(pandas.DataFrame.apply) # function
inspect.findsource(pandas.DataFrame.apply) # works ok
type(pandas.DataFrame.iloc) # property
inspect.findsource(pandas.DataFrame.iloc) # throws exception
TypeError: module, class, method, function, traceback, frame, or code object was expected, got property
Why inspect cannot find source for property? How can I programmatically get the source code (or source file path) for a given property?
Related
In native visual basic within Excel, the expected behavior is
Dim AvayaReport As Object
Dim AvayaServer As Object
...
...
Set ReportInfo = AvayaServer.Reports.Reports("<Report Name>")
AvayaServer.Reports.CreateReport ReportInfo, AvayaReport
After the last line, the CreateReport method mutates AvayaReport to be a report object in this library. However, when I replicate this code within Python, AvayaReport does not get mutated.
import win32com.client
...
AvayaReport = win32com.client.dispatch("ACSREP.cvsReport")
...
ReportInfo = AvayaServer.Reports.Reports(r'<Report Name>")
AvayaServer.Reports.CreateReport(ReportInfo, AvayaReport)
I have tried to compare the behavior between the two environments and with the exception of this issue, the surrounding code is working as intended. However, this COM object has this weird implementation where it requires an empty object to be passed into it's arguments and it changes that object to reflect the created report, but I cannot figure out a way to make this work within Python.
Within VBA, the CreateReport definition is as follows:
Function CreateReport(oRepInfo, oReport, [sTimeZone as String = "default"]) As Boolean
Member of ACSTLG.cvsCatalog
Introduction:
We know that, in python, a function is a class. To some extent, We can look at it as a data type which can be called and return a value. So it is a callable. We also know that Python classes are callables. When they are called, we are actually making objects as their instances.
My implementation: In a current task, I have defined the following class with two methods:
class SomeClass():
def some_method_1():
some_code
def some_method_2():
some_code
self.some_method_1()
some_code
To describe the code above, some_method_2 is using some_method_1 inside it.
Now I am seeking to test some_method_2. In this case, I need to replace some_method_1 with a mock object and specify the mock object to return what I define:
from unittest.mock import Mock
import unittest
class TestSomeClass(unittest.TestCase):
some_object=Some_Class()
some_object.some_method_1 = Mock(return_value=foo)
self.assertEqual(an_expected_value, some_object.some_method_2())
This works totally fine and the script runs without error and the test result is also ok.
A fast Intro about Mypy: Mypy is a python type checking tool which can run and check if the script is written correctly based on variable types. It does this process by some criteria such as type annotations, variable assignments and libraries stub files. This process is done without interpreting and running the code.
What is the Problem?
When I try to check my code with mypy, it gives error for this line:
some_object.some_method_1 = Mock(return_value=foo)
The error indicates that I am not allowed to assign an object to a callable in python. Sometimes mypy does not report real errors and I doubt if this is the case. Especially because I can run my code with no problem.
Now, my question is, have I done my job wrong or just the mypy report is wrong? If I have done wrong, how can I implement the same scenario in a correct manner?
I would like to add a format to export plots in a pyqtgraph application. I've dived in the code looking for a way to do that, but from outside the library source code didn't work. Or at least I couldn't make it work.
Looking how the exporters in the library work, I thought that replicating, for example what the CSVExporter does, would work. In short, a sample code like:
from pyqtgraph.exporters.Exporter import Exporter
class DataFormatExporter(Exporter):
Name = "DataFormat from plot data"
# (...) pure copy of the rest
DataFormatExporter.register()
The only exported that doesn't do this last call to register is the PrintExporter but all the others. This method 'register' is a #classmethod in the Exporter superclass.
But if I test the code, the exception says that the newer class doesn't have the register defined:
AttributeError: type object 'DataFormatExporter' has no attribute 'regiter'
The closest reference to what I'm looking is a post in a pyqtgraph google group and its steps 1 and 2 are just what I've thought should be and what I've tried.
Any hint?
Is possible to mock the declaration import pyarrow.parquet as pq?
I'm trying to mock it as:
#patch("twilio_events.workers.EngineDWH")
#patch("twilio_events.workers.pyarrow")
#patch("twilio_events.workers.s3fs")
def test_process_batch(s3fs, py, e):
pass;
But it throws me an exception Attribute Error....<workspace/myproject/twilio_events/workers.py'> does not have the attribute 'pyarrow'>.
Other mocks are fine, only this one is throwing this exception :(.
Any help?
The target of a patch is the name that needs to be replaced. In this case, if paraquet is imported as pq, you have to replace pq.
Try something like
#patch("twilio_events.workers.pq")
This is explained a bit in the docs:
patch() works by (temporarily) changing the object that a name points to with another one. There can be many names pointing to any individual object, so for patching to work you must ensure that you patch the name used by the system under test.
The basic principle is that you patch where an object is looked up, which is not necessarily the same place as where it is defined.
I am attempting to mock a method and running into issues with mock actually overwriting it.
app/tests/test_file.py <- contains the the unit test, currently using:
#mock.patch('app.method', return_value='foo')
def test(self, thing):
...
do some stuff with app/main/server.py
and get its response, assert a few values
...
assert 'foo' is in return value of some stuff
The method being mocked is being called by another file that server.py is calling.
app/main/server.py <- what the unit test is actually interacting with
app/main/route.py <- where method being mocked is called
app/main/thing.py <- contains method to be mocked
This is with python 2.7 and each package has an init file. The parent folder (app) contains imports for every class and method. I've tried app.method which doesn't give problems, but doesnt work. I've tried thing.method, throws an error. I've tried app.main.thing.method which does nothing.
I've had success in this same test suite mocking an object and one of its methods, but that object is created and used directly in the server.py file. I'm wondering if it's because the method being called is so far down the chain. Mocking is pretty magical to me, especially in Python.
After more digging finally figured it out, will leave it up for any others that have problems (especially since it's not easily Google'able).
As #Gang specified the full path should work, however the module needs to be the module where the method is called, not the module where it is located, as this person points out. . Using #Gang example:
#mock.patch('app.main.route.method')
def test(self, mock_method):
mock_method.return_value = 'foo'
# call and assert