Python typing: how to name a new type? - python-3.7

I wanted to give a name to a dict type, something like:
MyDictType = Dict[int, SomeClass]
and so I found about NewType, but it seems to only accepts runtime types:
the code MyDictType = NewType('MyDictType', Dict[int, SomeClass]
creates the warning Expected type 'Type[_T]', got '_VT' instead
So what is the correct way to do this?
*I'm using Python 3.7 . Please let me know if there's a better solution in newer versions.

You can do
from typing import NewType
MyDictType = NewType("MyDictType", Dict[int, SomeClass])
NewType was added in 3.5.2, but behaviour changed in 3.10. Here're the docs for 3.10: https://docs.python.org/3/library/typing.html#typing.NewType

Related

Strong typed python3.7 - return type and params are not failed

I don't quite understand why this is not failing:
def hello(name: str) -> int:
ending:int = '!!!'
return f'Hello {name} {ending}'
print(hello('John')) # Hello John !!!
And if there is already possibility to strong type python?
The reason is explained in PEP 484 by Guido himself:
It should also be emphasized that Python will remain a dynamically typed language, and the authors have no desire to ever make type hints mandatory, even by convention.
So the answer is NO. Type hints are only hints. They help to indicate what type of data a variable or function should/may contain/returns/etc. It wasn't designed to transform Python into a statically typed language.
As I wrote in comment it is nice to use mypy myproject.py to run it before project/code run. Then you could verify data types structure and correct flow.

Convert Standard.Natural to Ada.Containers.Count_Type

I instanced the Ada.Containers.Vectors generic package like this:
package My_Vectors is new Ada.Containers.Vectors(
Element_Type => My_Type,
Index_Type => Natural);
Say, I have a vector and a Standard.Natural value declared:
Foo_Vector: My_vectors.Vector;
Bar_Natural: Natural := 4;
If I call
Foo_Vector.Set_Length(Bar_Natural);
I get the following error
expected type "Ada.Containers.Count_Type"
found type "Standard.Natural"
Is there a way to cast Bar_Natural to be of Ada.Containers.Count_Type?
Sorry, I was too stupid to actually read all that my error said. I tried converting the Natural using:
Ada.Containers.Vectors.Count_Type(Bar_Natural)
Which makes zero sense!
Reading the error, it is trivial to see that Count_Type is defined in package Ada.Containers.
The correct conversion would therefore be:
Ada.Containers.Count_Type(Bar_Natural);
Giving
Foo_Vector.Set_Length(Ada.Containers.Count_Type(Bar_Natural));

Adding an Appender does not work

I am trying to get an logger and add a specific appender to it. My code is very simple but I am not sure how to get this working.
val loggerInstance = LoggerFactory.getLogger("FOO.class")
var fileAppender = new FileAppender()
// fileAppender .setFile , sietPattern etc..the parameters i want
loggerInstance.addAppender(fileAppender)
I get an error here
Multiple markers at this line
- type mismatch; found : ch.qos.logback.core.FileAppender[Nothing] required:
ch.qos.logback.core.Appender[ch.qos.logback.classic.spi.ILoggingEvent] Note: Nothing <:
ch.qos.logback.classic.spi.ILoggingEvent, but Java-defined trait Appender is invariant in type E. You may wish to investigate a
wildcard type such as `_ <: ch.qos.logback.classic.spi.ILoggingEvent`. (SLS 3.2.10)
- Line breakpoint:loggerchange [line: 76] - addAppender
I have no clue what this error means and how to solve it. Can someone help me?
EDIT :
I tried to do what was told by drexin. I was not able to extend the interface and define the functions . There were only three functions , setName,getName, and doAppend. i am not sure as how to define these functions. Meanwhile i tried something and removed the errors. Please look into the code and let me know if what i am doing makes any sense .
val encoder = new PatternLayoutEncoder()
encoder2.setContext(context)
encoder2.setPattern("%msg%")
fileAppender.setAppend(true)
fileAppender.setContext(context)
fileAppender.setEncoder(encoder2.asInstanceOf[Encoder[Nothing]])
loggerInstance.asInstanceOf[Logger].addAppender(fileAppender
.asInstanceOf[Appender[ILoggingEvent]])
I know using asInstanceOf is not a smart way of coding but for now i want to make this work . When i execute this code i am getting the file in which i want to log but there is no logs inside it. I have checked for level errors , but that's not the case. i believe there is something wrong with encoder/layout. I am not sure how to fix it. Can someone show me how to either extend the class and apply the functions or what is wrong in this new code .
The FileAppender has a type parameter class FileAppender[E], but you instantiate it without providing such a parameter, so scala decides to put Nothing in as type. addAppender expects an appender of type Appender[ILoggingEvent], that is what the error says. What you have to do now, is to either use an existing, or create your own subclass of ILoggingEvent and provide it as type param:
class MyLoggingEvent extends ILoggingEvent {
// implement ALL the methods
}
val fileAppender = new FileAppender[MyLoggingEvent]()
My second approach worked . I am able to see the logs now. I was making the mistake in the pattern. It just a small tweak .
val encoder = new PatternLayoutEncoder()
encoder.setContext(context)
encoder.setPattern("%msg%n")
fileAppender.setAppend(true)
fileAppender.setContext(context)
fileAppender.setEncoder(encoder.asInstanceOf[Encoder[Nothing]])
loggerInstance.asInstanceOf[Logger].addAppender(fileAppender
.asInstanceOf[Appender[ILoggingEvent]])
I will summarize all my efforts towards logging/appending automatically and put it up soon. Hope that will help others too .

Scala manifest and instances

I'm using Jerkson, and I need to check if a given class can be serialized. The java version just needs a class, but jerkson does this:
def canSerialize[A](implicit mf: Manifest[A]) = mapper.canSerialize(mf.erasure)
Given that I have an instance, how can I call this? I pretty much tried
canSerialize[ClassManifest.fromClass(foo)]
But its not working. I wonder why the guys at jerkson could not make it simpler by just making this: canSerialize(Class[_]) ...
Any ideas on how can I invoke this?
Edit:
I fixed this by using:
canSerilialize(Manifest.classType(foo.getClass))
How about this:
canSerialize[Foo]
Compiler can automatically generate manifest for you (if it has enough type information in context)
Since Scala 2.8.0 canSerialize can be written via context bound. See more
If you don't know the class in advance, you can always pass the manifest as a parameter, i.e. this should work: canSerialize( Manifest.classType( foo.getClass ) ).

Create new *package* in a Scala Compiler Plugin

In my quest to generate new code in a Scala compiler plugin, I have now created working classes. The next logical step is to put those classes in a new, non-existing package. In Java, a package is basically a directory name, but in Scala a package seems much more complicated. So far I haven't found/recognized an example where a compiler plugin creates a new package.
At my current level of understanding, I would think that I would need to create first a package symbol with:
parentPackage.newPackage(...)
// ...
and than later create a Tree for the package with PackageDef. But PackageDef doesn't take the symbol as parameter, as one would expect, and searching for:
Scala newPackage PackageDef
returned nothing useful. So it seems that I don't need to do those two steps together. Possibly one is done for my by the compiler, but I don't know which one. So far, what I have looks like this:
val newPkg = parentPackage.newPackage(NoPosition, newTermName(name))
newPkg.moduleClass.setInfo(new PackageClassInfoType(new Scope,
newPkg.moduleClass))
newPkg.setInfo(newPkg.moduleClass.tpe)
parentPackage.info.decls.enter(newPkg)
// ...
val newPkgTree = PackageDef(Ident(newPkg.name), List(ClassDef(...)))
I think my answer to your other question should answer this one as well:
How to add a new Class in a Scala Compiler Plugin?