Ternary conditional logic in Karate with undefined variable - nashorn

I have a Karate feature file, let's called it A.feature, that is intended to be re-used by other feature files. By using shared scope, A.feature can use some variables, for instance the country, defined in the calling feature file. I want these parameters to be optional, but with a default value defined in A.feature. To do that I'm using ternary conditional logic, for instance:
* def myCountry = (country ? country : 'us')
However when country is not defined, a
ReferenceError: "country" is not defined
is thrown.
Does anybody have any idea how to resolve that, or if there is a Nashorn or Karate bug ?
If you want the complete stacktrace let me know.

This will work:
* def country = typeof country == 'undefined' ? 'us' : country
EDIT - Karate now has a convenient API to do this:
* def country = karate.get('country', 'us')

A simpler way is to use default values:
* def country = karate.get('country', 'us')

Related

I want to make a dropdown container in my script

I want to create a dropdown container to organize my export variable. Is it possible to create a custom dropdown container in the script?
Like this:
This is another approach to do this. It also requires the script to be tool.
What we need for this approach as a common prefix for the variables you want to group. The advantage is that we don't need _get and _set:
tool
extends Node
var custom_position:Vector2
var custom_rotation_degrees:float
var custom_scale:Vector2
func _get_property_list():
return [
{
name = "Custom",
type = TYPE_NIL,
hint_string = "custom_",
usage = PROPERTY_USAGE_GROUP
},
{
name = "custom_position",
type = TYPE_VECTOR2
},
{
name = "custom_rotation_degrees",
type = TYPE_REAL
},
{
name = "custom_scale",
type = TYPE_VECTOR2
}
]
As you can see we define a category with a name that will appear in the Inspector panel, and the hint_string is the prefix we will use. It is important to put the category before the properties in the array.
See: Adding script categories
Addendum: Using PROPERTY_USAGE_CATEGORY will produce a named header, similar to the one that says "Node2D" on the picture on the question. Use PROPERTY_USAGE_GROUP to make a collapsible group.
Yes, you can do this, but (in my opinion) it is a bit ugly and clutters up your script. You need to mark your script as a tool script and override the _get, _set, and _get_property_list functions.
An example based on your screenshot (not 100% sure this works exactly as-is; I'm also basing it on a recent project where I have since removed it and somewhat reorganized the project/code/node because the slightly nicer UI wasn't worth the additional clutter in the script):
tool
extends Node2D
# Note that these are NOT exported
var actual_position: Vector2
var actual_rotation: float
var actual_scale: Vector2
# Function to enumerate the properties to list in the editor
# - Not actually directly/automatically backed by variables
# - Note the naming pattern - it is {group heading}/{variable}
func _get_property_list():
var props = []
props.append({name="transform/position", type=TYPE_VECTOR2})
props.append({name="transform/rotation deg", type=TYPE_FLOAT}) # might not exist; look at docs to determine appropriate type hints for your properties
props.append({name="transform/scale", type=TYPE_VECTOR2})
return props
# Now the get/set functions to map the names shown in the editor to actual script variables
# Property names as input here will match what is displayed in the editor (what is enumerated in _get_property_list); just get/set the appropriate actual variable based on that
func _get(property: String):
if property == "transform/position":
return actual_position
if property == "transform/rotation deg":
return actual_rotation
if property == "transform/scale":
return actual_scale
func _set(property: String, value):
if property == "transform/position":
actual_position = value
return true
if property == "transform/rotation deg":
actual_rotation = value
return true
if property == "transform/scale":
actual_scale = value
return true
# Not a supported property
return false
Note that this answer is based on Godot 3.4. I'm not sure if a simpler approach is (or will be) available in Godot 4.

How to reference a class from a string which is part of a variable 3.7

I have just read a text file and extracted a string and stored it as a variable. This string also happens to be the name of a class I want to reference in order to use in a function for example. The "which_class" variable is the whichever class was stored in the file
I tried passing the which_class variable in as a parameter to the function. Removing the quotations seems to make it work but I am unsure how to do this.
class needed_for_func_one():
multiplier = 1.23
class needed_for_func_two():
multiplier = 1.15
def random_function(which_class):
print(123 * which_class.multiplier)
PSEUDO CODE
READ FROM FILE STORE STRING AS "which_class"
which_class = "needed_for_func_two"
random_function(which_class)
But this didn't work it just gave me an attribute error
the eval function could help you here.
random_function(eval(whichClass))
However, you should probably rethink whether you really want to it that way or if there is a much cleaner solution.
I think your question is related to this one
How you call the function depends if it is a global function or if it is inside an object.
globals()['call_this_function']() # this is probably what you need
or
getattr(from_this_object, 'call_this_function')()
first, to use a class you need an object of a class.
so if what you read is a name of the class or any other thing it does not matter, just use an if statement to decide what is inside that variable so-called "which_class".
then create an object like :
if which_class=="needed_for_func_one":
newObject = needed_for_func_one()
elseif which_class=="needed_for_func_two":
newObject = needed_for_func_two()
then use the print like :
print(123 * newObject.multiplier )

"TypeError: product_show() missing 1 required positional argument: 'Option'"

I have build up a menu with numbers, and my selection variable is Option with type int. 5-Hoodie will show all the stuff with category is Hoodie in my SQL database. I have created a module and I am using the class named LunaPy
Option = int(input("Option: "))
LunaPy.product_show(Option)
I am using SQL library in Python
def product_show(self,Option):
product_dict ={1:"Belt",2:"Blazer",3:"Coat",4:"Dress",5:"Hoodie",6:"Jacket",7:"Jeans",8:"Pants",9:"Shoes",10:"Shorts",11:"Sunglasses",12:"Sweater",13:"SweatShirt",14:"TShirt",15:"Underwear"}
query = "SELECT * FROM LunaPyDataBase WHERE Category = ?"
self.cursor.execute(query,(product_dict[Option],))
I expected the Option variable would return the value to the function so the function can use that to select the category in dictionary. And prints the items in that chosen category.
Change your method to this:
#staticmethod
def product_show(Option):
product_dict ={1:"Belt",2:"Blazer",3:"Coat",4:"Dress",5:"Hoodie",6:"Jacket",7:"Jeans",8:"Pants",9:"Shoes",10:"Shorts",11:"Sunglasses",12:"Sweater",13:"SweatShirt",14:"TShirt",15:"Underwear"}
query = "SELECT * FROM LunaPyDataBase WHERE Category = ?"
self.cursor.execute(query,(product_dict[Option],))
Or do this:
option = int(input("Option: "))
lunaPy = LunaPy()
lunaPy.product_show(option)
The self in your function definition points to the object instance of your LunaPy class. If your method does not require an instance of LunaPy, you can mark it as static... and then you can use it like this Class.method(), but won't be able to use any instance variables or methods of the class.
The other option is to just create the instance and call the method using that.
EDIT:
Didn't notice the self inside the function. The first option won't work, because object instance is required. The second option with lunaPy = LunaPy() should work though.

Groovy - Set your own property of an Integer

I just started to learn Groovy and wondering if you can set your own property for an integer. For example,
def a = 34.5.plus(34.34)
def b = 5.64.minus(3.43)
def c = 12.64.multiply(33.43)
In the above there are certain methods like plus minus and multiply
What should I do if I want to define some of my own methods for integers like that.
I searched Google but couldn't find much about it.
Sure, you can just add methods to the metaClass of Integer.
Here's an example:
Integer.metaClass.zeds = { -> 'z' * delegate }
assert 3.zeds() == 'zzz'
You can also add methods to a single instance of integer should you wish to, ie:
Integer num = 4
num.metaClass.halved = { -> delegate / 2.0 }
assert num.halved() == 2.0
You can also add methods to classes via Extension Methods a good explanation of which can be found over here
It should be noted (as you originally tagged this question as Java) that obviously, Java code will have no knowledge of these things, as it doesn't know about the metaClass
Use groovy meta programming, this allows you to create dynamic method creation atruntime in the class that you want to place in .
bydefault if a method is not found methodmissing exception throws , this is where groovy allows you add method at runtime for more reference use the below comprehensive link
http://groovy-lang.org/metaprogramming.html
If this answer helps , dont forget to click answered.

How to get class field identifier as String in Groovy?

Suppose simple Groovy class (POGO):
class Person { String name; int age }
How to get chosen identifier at runtime? In other words identifier name (like "name" and "age") used in source code by programmer - not value held in variable of this identifier (like "James" and "32").
With result solution (if there is any) it would be possible to write something like this (syntactically wrong pseudo code):
assert new Person().name.identifierAsString == 'name'
assert new Person().age.identifierAsString == 'age'
Please note I'm not trying to get list of field names (like Person.declaredFields), but compile-time safe way to get field identifier as String.
I wrote a lib sometime ago to write type-checked queries. It might be what you are after:
import org.latitude.Latitude
Customer customer = Latitude.forClass Customer
assert customer instanceof Customer
assert customer.name == "name"
I'm not certain what you're trying to accomplish, but you can get all of the declared field names like so:
assert ['name', 'age'] == Person.declaredFields.findAll { !it.synthetic }.collect { it.name }
And otherwise declaredFields is a list of java.lang.reflect.Field that you can use.

Resources