decorator for initializing dataclass field metadata - python-3.7

using python3.7 dataclass, I am able to write something like:
class Foo:
fuzz: int = field(default=0, metadata={'ns_unit': 'km'})
bazz: str = field(default='', metadata={'ns_prefix': 'xx_', 'ns_other': 1})
Those metadata are used somewhere else. What I would like is to have a way to use decorators to set the metadata, e.g.:
class Foo:
#ns(unit='km')
fuzz: int = 0
#ns(prefix='xx_', other=1)
bazz: str = field(default='')
I is possible to achieve ?

Related

Flutter - Dart - Reflectable package : how to: get class fields type? instantiate object from class/Type? set fields values using Reflectable

I came to know that dart mirrors is disabled in flutter but hope that there might be some alternate way to achieve. Mirrors must not be disabled in flutter, it is an important & must have feature.
import 'package:reflectable/mirrors.dart';
import 'package:reflectable/reflectable.dart';
const reflector = const Reflector();
class Reflector extends Reflectable
{
const Reflector() : super(
invokingCapability,
typingCapability,
reflectedTypeCapability,
);
}
#reflector
class Dictionary
{
String english, myLang;
int index;
}
main() {
test();
}
test()
{
ClassMirror classMirror = reflector.reflectType(Dictionary);
classMirror.declarations.values.forEach((field)
{
VariableMirror variableMirror = field;
/*??????????????????????????????????????????
Now How To Get Field types i.e. String & int
How to instantiate class object
How to set fields values
???????????????????????????????????????????*/
});
}
Runtime object instantiation:
Use the method newInstance from ClassMirror. The first argument is the constructor name. Like you haven't name constructors, simple pass an empty string. The second argument are an array of positional constructor arguments. No constructor, empty array.
Dictionary dic = classMirror.newInstance("", []);
Set fields values:
Use the method invokeSetter from InstanceMirror. The first argument is the field name and the second is the value.
InstanceMirror instanceMirror = reflector.reflect(dic);
instanceMirror.invokeSetter("index", 3);
So far I am able to know field(s) type:
ClassMirror classMirror = reflector.reflectType(Dictionary);
VariableMirror variableMirror = classMirror.declarations["english"] as VariableMirror;
Type type = variableMirror.dynamicReflectedType;
print("field: " + variableMirror.simpleName + " has type: " + type.toString());
Now remaining:
Runtime object instantiation?
How to set fields value of instantiated object?

Unable to print the values of an instance of my model

I know this is a very fundamental question but answer to this will solve many of my doubts.
val new_parent = ParentDetails(intent.extras.getString("name"),
intent.extras.getString("email"),
intent.extras.getString("parent_relation"),
intent.extras.getString("locationdata"))
println(new_parent.tostring())
The code above doesn't print the various fields and their values present in the class.
The ParentDetails is a model I have created with some fields that are initialized. The ParentDetails model:
class ParentDetails {
var parent_id: Int = 0
var parent_name: String = ""
var parent_email: String = ""
var parent_relation: String = ""
var parent_location: String=""
constructor(parent_name: String, parent_email: String, parent_relation: String,parent_location:String) {
this.parent_name = parent_name
this.parent_email = parent_email
this.parent_relation = parent_relation
this.parent_location = parent_location
}
public fun getparentId(): Int {
return parent_id
}
fun ParentDetailsprintme() {
println(parent_name)
println(parent_email)
println(parent_relation)
println(parent_location)
}
}
In fact, it prints null and accessing individual fields, it prints empty string(the way it was initialized).
How do we explain this?
As I understand your problem is that calling println(new_parent.tostring()) does not print what you would like to print in function ParentDetailsprintme.
First of all, you have a typo, the correct call would be new_parent.toString().
Note that it could have been simplified as println(new_parent).
It does not print that you defined in the ParentDetailsprintme method, as the method is not called.
What println(new_parent.toString()) prints, is actually the hashcode of the object, as this is the default behaviour of every object.
To make it work call it like println(new_parent.ParentDetailsprintme()) or override the toString() method for example as:
override fun toString() = "$parent_name $parent_email $parent_relation $parent_location"
then the following
val new_parent = ParentDetails("myName", "myEmail", "myParent_relation", "myLocationdata")
println(new_parent)
should print
myName myEmail myParent_relation myLocationdata
Kotlin's println function simply calls System.out.println(message) under the hood which will call String.valueOf() (e.g. String.valueOf(Object object) for objects, which will call the toString() method of the passed object).
/** Prints the given message and newline to the standard output stream. */
#kotlin.internal.InlineOnly
public inline fun println(message: CharArray) {
System.out.println(message)
}
Update ("Using data class method also works"):
If you make the class to be a data class:
data class ParentDetails(
val parent_id: Int = 0,
val parent_name: String = "",
val parent_email: String = "",
val parent_relation: String = "",
val parent_location: String = ""
)
and then you execute
val new_parent = ParentDetails(0, "myName", "myEmail", "myParent_relation", "myLocationdata")
println(new_parent)
you will receive as result
ParentDetails(parent_id=0, parent_name=myName, parent_email=myEmail, parent_relation=myParent_relation, parent_location=myLocationdata)
This is because data classes override the toString() function:
The compiler automatically derives the following members from all
properties declared in the primary constructor:
equals()/hashCode() pair;
toString() of the form "User(name=John, age=42)";
Did you check that you receive valid data from your intent.extras?
Also I suggest you use data class for your models.
It will look something like this:
data class ParentDetails(
var parent_id: Int = 0,
var parent_name: String = "",
var parent_email: String = "",
var parent_relation: String = "",
var parent_location: String = ""
)
You will be able to use it like this :
val new_parent = ParentDetails(
parent_name = intent.extras.getString("name"),
parent_email = intent.extras.getString("email"),
parent_relation = intent.extras.getString("parent_relation"),
parent_location = intent.extras.getString("locationdata")
)
println(new_parent.tostring())
As already mentioned, you have a typo. toString returns the hashcode of an object unless it's overridden to return something else. Look up the original implementation for more details.
By overriding the toString method, you change what it returns, and through that, what is printed when you print(someClass). DVarga showed that in their answer.
Data classes auto-generate a toString method containing the content of the class. So creating a data class is a shortcut to getting output containing the data.
The reason the method you had didn't work is because you didn't call it. if you call it instead of toString, you would get the data printed.
Also, toString is explicitly called when you print a class. You don't need to call print(someInstance.toString()), print(someInstance) is enough.
And while I'm writing an answer, you don't need to use secondary constructors in Kotlin. Primary constructors would shorten your code significantly, whether it's a data class or not. Also, you should look into naming conventions.

Making a class in Swift 2

How should I correctly create such a class which can be used from any .swift-file of my project and does not need to be initialized with a variable?
I mean that I want not to have to write something like
someVar = myClass()
in each file where I want this class to be usable. I just want this class to have a global public variables and change them from a .swift-file of my project by doing something like
myClass.myVar = value
I'm thinking about making this class a separate file. What's a correct way to do this?
You can create a static property inside a class or struct and call it anywhere. E.g:
//Config.swift
struct Config
{
static var field1 : String = "Field_Value"
static var field2 : String = "Field_Value"
}
You can use the property calling StructName.propertyName.
E.g:
//MyCode.swift
print(Config.field1)
Config.field1 = "New Value"
You can create a new class, make a variable off that class outside any class.
Class Awesome{
}
let awesomeness = Awesome()
you can than use 'awesomeness' as class instance in every other swift file

Postsharp introduce Attributes with Property Arguments

I am trying to achieve attribute introduction like here but my attributes have property arguments like: [Foo(Bar = "Baz")]
How do I correctly pass the arguments? I'm not copying the attributes from something else, so I don't think I can use CustomAttributeData?
You can set properties of your custom attributes by using ObjectConstruction.NamedArguments dictionary.
For example:
public IEnumerable<AspectInstance> ProvideAspects(object targetElement)
{
Type targetType = (Type) targetElement;
var objectConstruction =
new ObjectConstruction(typeof (MyCustomAttribute).GetConstructor(Type.EmptyTypes));
objectConstruction.NamedArguments["Bar"] = "Baz";
var introduceAttributeAspect = new CustomAttributeIntroductionAspect(objectConstruction);
yield return new AspectInstance(targetType, introduceAttributeAspect);
}

Get type of class field with null value in Haxe

Is it possible to get class of field with null value in haxe?
The function "Type.getClass" gets class of value (setted at runtime), but I need to get class defined in a compilation-time.
Function "getClassFields" returns only names of fields, without classes.
For example:
class MyCls
{
public static var i:Int = null;
public static var s:String = null;
}
trace(Type.getClass(MyCls.i)); // show "null", but I need to get Int
trace(Type.getClass(MyCls.s)); // show "null", but I need to get String
And in my situation I can't to change sources of class MyCls.
Thanks.
You can try Runtime Type Information. It's a Haxe feature which allow go get full description of a type in runtime.
http://haxe.org/manual/cr-rtti.html
Since you need to get the types for null fields, you really need to resort to Haxe's Runtime Type Information (RTTI) (as #ReallylUniqueName recomended).
import haxe.rtti.Rtti;
import haxe.rtti.CType;
class Test {
static function main()
{
if (!Rtti.hasRtti(MyCls))
throw "Please add #:rtti to class";
var rtti = Rtti.getRtti(MyCls);
for (sf in rtti.statics)
trace(sf.name, sf.type, CTypeTools.toString(sf.type));
}
}
Now, obviously, there's a catch...
RTTI requires a #:rtti metadata, but you said you cannot change the MyCls class to add it. The solution then is do add it through a macro in your build file. For instance, if you're using a .hxml file, it should then look like:
--interp
--macro addMetadata("#:rtti", "MyCls")
-main Test
With this and your own MyCls definition, the output would look like:
Test.hx:11: i,CAbstract(Int,{ length => 0 }),Int
Test.hx:11: s,CClass(String,{ length => 0 }),String