Importing a specific function from a module - python-2.7

I have a module called prog1.py which contains a function and other statements, like this:
def func(a,b,c)
...
...
return output
var = input('input')
...
I'm trying to call just the function func from a different module prog2.py like this:
from prog1 import func
N = input('input2')
for i in range(N)
func(x,y,z) # with x,y,z already defined
So when executing prog2.py instead of asking for my input2, it asks for my input from prog1.py. I can move from prog1 import func to my for loop but I don't want it to ask for the other input. Is there a way to call func without using whatever else is in prog1.py?

The top level code of a module is executed upon import and there is no way around this.
If you don't want the line
var = input('input')
to be executed, remove it, put it in a function or guard it with
if __name__ == '__main__'
var = input('input')
(usually at the end of the module).

Related

Java code migration error using com.jayway.jsonpath.JsonPath

I am using Java code and converting the code in ColdFusion. There are some challenges where I am stuck. This is one function I have in Java:
import com.jayway.jsonpath.JsonPath;
import net.minidev.json.JSONArray;
import net.minidev.json.JSONStyle;
private static String getDetails(String instaDetailsElement) {
String jsonResponse = instaDetailsElement.split(" = ")[1];
JSONArray mediaArray = JsonPath.read(jsonResponse, "$.entry_data.PostPage[:1].graphql.shortcode_media");
String returnJsonString = mediaArray.toJSONString(new JSONStyle(JSONStyle.FLAG_IGNORE_NULL));
System.out.println(returnJsonString);
return returnJsonString;
}
These two lines are giving me some trouble:
var mediaArray = JsonPath.read(jsonResponse, "$.entry_data.PostPage[:1].graphql.shortcode_media");
var returnJsonString = mediaArray.toJSONString(new JSONStyle(JSONStyle.FLAG_IGNORE_NULL));
Here is what I attempted so far. I loaded the jar library for JSON path and tried using it like this:
Application.cfc settings
<cfset this.javaSettings = {LoadPaths = ["cfc/jar"], loadColdFusionClassPath = true, reloadOnChange = false}>
CF Code:
public any function getDetails(String instaDetailsElement) {
var jsonResponse = instaDetailsElement.split(" = ")[1];
var JsonPath = Createobject("java","com.jayway.jsonpath.JsonPath");
writedump(application);
var mediaArray = JsonPath.read(jsonResponse, "$.entry_data.PostPage[:1].graphql.shortcode_media");
writedump(mediaArray); abort;
var returnJsonString = mediaArray.toJSONString(new JSONStyle(JSONStyle.FLAG_IGNORE_NULL));
return returnJsonString;
}
I'm able to view the class methods when I dump the JsonPath object (screen shot), but when I try to call JsonPath.read() I get this error:
No matching Method for read(string, string) found for
com.jayway.jsonpath.JsonPath
TL;DR;
No matching method for read(string, string) found for com.jayway.jsonpath.JsonPath
Technically the error message is correct: there is no read() method that accepts two strings (even though that's how it's used in the java code). The method actually expects three arguments:
Pass in an empty array for the 3rd argument:
JsonPath.read(jsonResponse, "$.entry_data.PostPage[:1].graphql.shortcode_media", []);
Explanation:
String jsonResponse = instaDetailsElement.split(" = ")[1];
JsonPath.read(jsonResponse, "$.entry_data.PostPage[:1].graphql.shortcode_media")
If there really is no read(String, String) method, you might wonder why the java code works at all, since that's exactly what it uses. It works due to a special feature of java.
The documentation shows the overloaded read(..) method actually has three parameters, but one of them is special:
read(String json,
String jsonPath,
Predicate... filters)
Notice the ... after the class name (Predicate)? It's a construct called "varargs" (or variable number of arguments):
You can use a construct called varargs to pass an arbitrary number of values to a method. You use varargs when you don't know how many of a
particular type of argument will be passed to the method. It's a
shortcut to creating an array manually ...
To use varargs, you follow the type of the last parameter by an ellipsis (three dots, ...), then a space, and the parameter name. The
method can then be called with any number of that parameter,
including none.
So in java you're allowed to omit the third argument entirely and call read(String, String) with two strings. ColdFusion doesn't support that syntax, because it creates too much ambiguity. So in lieu of omitting the argument, you can pass in an empty array instead:
JsonPath.read(jsonResponse, "$.entry_data.PostPage[:1].graphql.shortcode_media", []);
(Since this has turned into two questions in one thread, I'm separating the second answer out for clarity ...)
var returnJsonString = mediaArray.toJSONString(new JSONStyle(JSONStyle.FLAG_IGNORE_NULL));
As for translating the JSONStyle code, it helps to unpack nested code from the inside out. Then tackle each piece separately:
mediaArray.toJSONString(new JSONStyle( JSONStyle.FLAG_IGNORE_NULL ));
mediaArray.toJSONString( new JSONStyle( JSONStyle.FLAG_IGNORE_NULL ) )
mediaArray.toJSONString( new JSONStyle( JSONStyle.FLAG_IGNORE_NULL ) )
Piece #1
Uses a static field of the JSONStyle class named FLAG_IGNORE_NULL. To access the field, create a reference to that class:
JsonStyle = createObject("java", "net.minidev.json.JSONStyle");
writeDump(JSONStyle.FLAG_IGNORE_NULL);
Piece #2
Creates a brand new instance of the JSONStyle class, using the static field from above. Use createObject() to create the new instance, passing the static field into the psuedo constructor init():
newJsonStyle = createObject("java", "net.minidev.json.JSONStyle").init(JSONStyle.FLAG_IGNORE_NULL);
writeDump( newJsonStyle );
Piece #3
All that's left is calling the JSONArray.toJSONString() method with the JSONStyle object you just created:
result = mediaArray.toJSONString( newJsonStyle );
writeDump(result);

Testing that a plugin function is called in jenkins shared library

I'm trying to write a unit test for a util function in a Jenkins shared library. The util function, calls the Office365Connector plugin in Jenkins.
My util function looks like this:
#!/usr/bin/env groovy
import pe.ui.BuildNotificationSettings
import pe.ui.BuildStates
def call(BuildNotificationSettings options, BuildStates status) {
options.teamsChannelWebhookUrlList.each {
office365ConnectorSend (
status: status.toString(),
webhookUrl: "$it",
color: BuildStates.valueOf(status.toString()).color,
message: "Build ${status.toString()}: ${JOB_NAME} - ${BUILD_DISPLAY_NAME}<br>Pipeline duration: ${currentBuild.durationString}"
)
}
}
The use case that I'm trying to test is that the office365ConnectorSend function is called.
I've tried the following approach:
import com.homeaway.devtools.jenkins.testing.JenkinsPipelineSpecification
import pe.ui.BuildNotificationSettings
import pe.ui.BuildStates
public class _sendTeamsMessageSpec extends JenkinsPipelineSpecification {
def _sendTeamsMessage = null
def setup() {
_sendTeamsMessage = loadPipelineScriptForTest("vars/_sendTeamsMessage.groovy")
def office365ConnectorSend = Mock(office365ConnectorSend)
}
def "returns without sending no build notification settings are passed" () {
given:
def options = new BuildNotificationSettings(
shouldSendNotification: null,
teamsChannelWebhookUrlList: null
)
when:
def result = _sendTeamsMessage(options, null)
then:
0 * explicitlyMockPipelineVariable("office365ConnectorSend")(_)
}
}
running this on Jenkins gives me a java.lang.IllegalStateException:
There is no pipeline variable mock for [office365ConnectorSend]., what am I doing wrong in this approach?
After following this thread, I ended up calling the explicitlyMockPipelineStep function on the office365ConnectorSend plugin function.
This made the function visible in the tests and I was able to resume testing.

How to restore a mock created with jest.mock()?

Apparently mock.mockRestore() does not restore the original implementation of a mock created using jest.mock()
// a.js
export default class A {}
// b.js
import A from './a';
export default class B extends A {}
// test.js
import A from './a';
import B from './b';
jest.mock('./a');
jest.mock('./b');
const b = new B();
test('instanceOf', () => {
A.mockRestore();
B.mockRestore();
expect(b).toBeInstanceOf(A); // fails
});
mockFn.mockRestore only works for a mock function created with jest.spyOn:
const obj = {
func: () => 'original'
}
test('func', () => {
const mock = jest.spyOn(obj, 'func');
mock.mockReturnValue('mocked');
expect(obj.func()).toBe('mocked'); // Success!
mock.mockRestore();
expect(obj.func()).toBe('original'); // Success!
})
jest.spyOn wraps the original function and provides mockRestore as a way to restore the original function.
jest.mock calls work a little differently.
Jest takes over the require system and jest.mock tells Jest that it should return the module mock instead of the actual module whenever it is required.
This means that the module mock doesn't wrap the original module, it completely replaces the original module in the require system. So mockRestore may be defined on mock functions within the module mock, but calling it doesn't restore the original implementation.
jest.mock is typically used when you want to mock an entire module for the whole test.
It is particularly useful when using ES6-style import statements since babel-jest hoists jest.mock calls and they run before anything else in the test file (including any import statements):
import A from './a'; // <= A is already mocked...
jest.mock('./a'); // <= ...because this runs first
test('A', () => {
// ...
}
There isn't an easy way to restore the original module during a test that uses jest.mock since its primary use is to mock a module for an entire test.
If you are trying to use both a mock and the original implementation during the same test there are a few options:
Mock one particular function using jest.spyOn and restore it using mockRestore
Use jest.doMock to avoid the hoisting behavior of jest.mock...just note you also need to use require within the scope that uses jest.doMock instead of using a top-level import
Use jest.requireActual at any time to require the original module
Assuming you cant use spyOn,
you can do something like this:
// test.js
jest.mock('./a');
import A from './a';
A.mockImplementation(params => 'mockVal');
const actualA = jest.requireActual('./a');
test('instanceOf', () => {
A.mockRestore(); // acts like mockReset()
A.mockImplementation((params) => {
return actualA(params);
});
});

MediatorLiveData doesn't work in JUnit tests?

So I've tried using MediatorLiveData for the rather simple use-case of converting an ISO country code (e.g. "US") to a country calling code (e.g. "+1") through the use of libphonenumber. The resulting screen works fine, but seems to fail JUnit tests, even when InstantTaskExecutorRule is used.
Example minimal unit test (in Kotlin) that I believe should pass, but fails instead:
import android.arch.core.executor.testing.InstantTaskExecutorRule
import android.arch.lifecycle.MediatorLiveData
import android.arch.lifecycle.MutableLiveData
import org.junit.Assert.assertEquals
import org.junit.Rule
import org.junit.Test
class MediatorLiveData_metaTest {
#get:Rule
val instantTaskExecutorRule = InstantTaskExecutorRule()
#Test
fun mediatorLiveData_metaTest() {
val sourceInt = MutableLiveData<Int>()
val mediatedStr = MediatorLiveData<String>()
mediatedStr.addSource(sourceInt) {
mediatedStr.value = it.toString()
}
sourceInt.value = 123
assertEquals("123", mediatedStr.value) // says mediatedStr.value is null
}
}
Thanks to Reddit user matejdro; the answer was that like Schrödinger's proverbial cat, MediatorLiveData won't update itself unless observed, so I'd need a mediatedStr.observeForever{} to force it to update itself.

Is there any option to use something similar to mockito argument captor?

we are using gopkg.in/mgo.v2/bson to talk with mongo, and its API populates passed structures instead returning results, for example:
func (p *Pipe) One(result interface{}) error {...
Problems occurs when I want to mock / test code which is using that. I want to both mock this execution and somehow get pupulated value in 'result'.
Currently test has:
query.EXPECT().One(gomock.Any())
So as you can see I dont get any value, I just configure gomock to check that when I run my method then query.One has to be called.
I cannot pass structure like
mystruct := MyStruct{}
query.EXPECT().One(&mystruct)
because mystruct in test code and in real code is different and verifing mock will fail (references are different). Im looking for something similar to mockito's argument captor:
https://static.javadoc.io/org.mockito/mockito-core/2.6.9/org/mockito/ArgumentCaptor.html
This can be achieved via Do.
Copy & Paste of Github example from poy.
var capturedArgs []int
someMock.
EXPECT().
SomeMethod(gomock.Any()).
Do(func(arg int){
capturedArgs = append(capturedArgs, arg)
})
Ref: https://github.com/golang/mock/pull/149
This project can help you: https://github.com/bouk/monkey.
You can replace a function and use a bool variable to check the use.
called := false
monkey.Patch(package.One, func(result interface{}) error {
if result == expected {
called := true
return nil
}
return errors.new("not expected")
})
Dont't forget to restore your original function.
defer monkey.Unpatch(package.One)