Python 3.7 nested dataclass mypy type check error - typechecking

#dataclass
class A:
one: int = 0
two: str = ""
#nested_dataclass
class B:
three: A
four: str
#nested_dataclass
class C:
five: B
six: str
obj = C(five={"three":{"one": 23, "two":"narf"}, "four": "zort"}, six="fnord")
print(obj.five.three.two)
This code is correct according to functionality I guess. But, when I run mypy src --ignore-missing-imports, I get the following error:
run.py:50: error: Unexpected keyword argument "five" for "C"
run.py:50: error: Unexpected keyword argument "six" for "C"
Would be lot helpful if someone would help me overcome this. Thanks

Mypy has no idea what a nested_dataclass is -- it doesn't appear to be a decorator that's a standard part of the dataclasses module.
Consequently, mypy won't be able to understand whatever special logic is happening when you try instantiating C. As far as mypy is concerned, C is a regular old class -- and has no constructor.
The two possible solutions you have are to:
Just use #dataclass and drop whatever custom logic you're using.
Write a plugin for mypy that can understand the #nested_dataclass decorator. You can get some examples of what this looks like by looking at the dataclasses plugin that comes baked into mypy.

Related

Dialyzer does not catch errors on returned functions

Background
While playing around with dialyzer, typespecs and currying, I was able to create an example of a false positive in dialyzer.
For the purposes of this MWE, I am using diallyxir (versions included) because it makes my life easier. The author of dialyxir confirmed this was not a problem on their side, so that possibility is excluded for now.
Environment
$ elixir -v
Erlang/OTP 24 [erts-12.2.1] [source] [64-bit] [smp:12:12] [ds:12:12:10] [async-threads:1] [jit]
Elixir 1.13.2 (compiled with Erlang/OTP 24)
Which version of Dialyxir are you using? (cat mix.lock | grep dialyxir):
"dialyxir": {:hex, :dialyxir, "1.1.0", "c5aab0d6e71e5522e77beff7ba9e08f8e02bad90dfbeffae60eaf0cb47e29488", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "07ea8e49c45f15264ebe6d5b93799d4dd56a44036cf42d0ad9c960bc266c0b9a"},
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
Current behavior
Given the following code sample:
defmodule PracticingCurrying do
#spec greater_than(integer()) :: (integer() -> String.t())
def greater_than(min) do
fn number -> number > min end
end
end
Which clearly has a wrong typing, I get a success message:
$ mix dialyzer
Compiling 1 file (.ex)
Generated grokking_fp app
Finding suitable PLTs
Checking PLT...
[:compiler, :currying, :elixir, :gradient, :gradualizer, :kernel, :logger, :stdlib, :syntax_tools]
Looking up modules in dialyxir_erlang-24.2.1_elixir-1.13.2_deps-dev.plt
Finding applications for dialyxir_erlang-24.2.1_elixir-1.13.2_deps-dev.plt
Finding modules for dialyxir_erlang-24.2.1_elixir-1.13.2_deps-dev.plt
Checking 518 modules in dialyxir_erlang-24.2.1_elixir-1.13.2_deps-dev.plt
Adding 44 modules to dialyxir_erlang-24.2.1_elixir-1.13.2_deps-dev.plt
done in 0m24.18s
No :ignore_warnings opt specified in mix.exs and default does not exist.
Starting Dialyzer
[
check_plt: false,
init_plt: '/home/user/Workplace/fl4m3/grokking_fp/_build/dev/dialyxir_erlang-24.2.1_elixir-1.13.2_deps-dev.plt',
files: ['/home/user/Workplace/fl4m3/grokking_fp/_build/dev/lib/grokking_fp/ebin/Elixir.ImmutableValues.beam',
'/home/user/Workplace/fl4m3/grokking_fp/_build/dev/lib/grokking_fp/ebin/Elixir.PracticingCurrying.beam',
'/home/user/Workplace/fl4m3/grokking_fp/_build/dev/lib/grokking_fp/ebin/Elixir.TipCalculator.beam'],
warnings: [:unknown]
]
Total errors: 0, Skipped: 0, Unnecessary Skips: 0
done in 0m1.02s
done (passed successfully)
Expected behavior
I expected dialyzer to tell me the correct spec is #spec greater_than(integer()) :: (integer() -> bool()).
As a side note (and comparison, if you will) gradient does pick up the error.
I know that comparing these tools is like comparing oranges and apples, but I think it is still worth mentioning.
Questions
Is dialyzer not intended to catch this type of error?
If it should catch the error, what can possibly be failing? (is it my example that is incorrect, or something inside dialyzer?)
I personally find it hard to believe this could be a bug in Dialyzer, the tool has been used rather extensively by a lot of people for me to be the first to discover this error. However, I cannot explain what is happening.
Help is appreciated.
Dialyzer is pretty optimistic in its analysis and ignores some categories of errors.
This article provides some advanced explanations about its approach and limitations.
In the particular case of anonymous functions, dialyzer seems to perform a very minimal check
when they are being declared: it will ignore both the types of its arguments and return type, e.g.
the following doesn't lead any error even if is clearly wrong:
# no error
#spec add(integer()) :: (String.t() -> String.t())
def add(x) do
fn y -> x + y end
end
It will however point out a mismatch in arity, e.g.
# invalid_contract
# The #spec for the function does not match the success typing of the function.
#spec add2(integer()) :: (integer(), integer() -> integer())
def add2(x) do
fn y -> x + y end
end
Dialyzer might be able to detect a type conflict when trying to use the anonymous function,
but this isn't guaranteed (see article above), and the error message might not be helpful:
# Function main/0 has no local return.
def main do
positive? = greater_than(0)
positive?.(2)
end
We don't know what is the problem exactly, not even the line causing the error. But at least we know there is one and can debug it.
In the following example, the error is a bit more informative (using :lists.map/2 instead of Enum.map/2 because
dialyzer doesn't understand the enumerable protocol):
# Function main2/0 has no local return.
def main2 do
positive? = greater_than(0)
# The function call will not succeed.
# :lists.map(_positive? :: (integer() -> none()), [-2 | 0 | 1, ...])
# will never return since the success typing arguments are
# ((_ -> any()), [any()])
:lists.map(positive?, [1, 0, -2])
end
This tells us that dialyzer inferred the return type of greater_than/1 to be (integer() -> none()).
none is described in the article above as:
This is a special type that means that no term or type is valid.
Usually, when Dialyzer boils down the possible return values of a function to none(), it means the function should crash.
It is synonymous with "this stuff won't work."
So dialyzer knows that this function cannot be called successfully, but doesn't consider it to be a type clash until actually called, so it will allow the declaration (in the same way you can perfectly create a function that just raises).
Disclaimer: I couldn't find an official explanation regarding how dialyzer handles anonymous
functions in detail, so the explanations above are based on my observations and interpretation

How to set value to the child map in the father map in kotlin?

as title, I have the code:
val description= mutableMapOf(
"father2" to "123",
"father" to mutableMapOf<String,String>())
description["father"]["child"] = "child value"
if i try this: description["father"]["child"]="child value"
I will get the error:
Unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
public inline operator fun <K, V> MutableMap<String!, String!>.set(key: String!, value: String!): Unit defined in kotlin.collections
public inline operator fun kotlin.text.StringBuilder /* = java.lang.StringBuilder */.set(index: Int, value: Char): Unit defined in kotlin.text
how can i do?
This is about typing (or lack of it).
The description map is created from two pairs, one from a String to a String, and the other from a String to a MutableMap<String, String>.  The keys are both String, so Kotlin will infer String for the type of key.  But what about the values?  They're two completely unrelated types, with no common superclass except Any.  So the type of description is inferred to be MutableMap<String, Any>.  (You can check that in e.g. the REPL.)
So, when you pull out a value, what can the compiler tell about it?  Almost nothing.  It's an Any, so the only thing you can be sure of is that it's not null.
That's why the compiler isn't treating that pulled-out value like a map; as far as it knows, it might not be a map!  (We know — but only because we can see what the map was initialised with, and that it's not modified since then, nor is the reference shared with any other objects or threads that could modify it.  But that's a relatively rare circumstance.)
Kotlin is a strongly-typed language, which means the compiler tracks the type of everything, and tries very hard not to let you do anything that could cause a runtime error.  Your code, if it compiled, would risk a ClassCastException any time the data didn't exactly match what you expected, which is hardly a route to good programs.
So, what can you do?
The safest thing would be to change your program so that you don't have any maps with unknown types of values.  Obviously, that depends on what your program is doing, so we can't make useful suggestions here.  But if your description were a MutableMap<String, MutableMap<String, String>>, then the compiler would know exactly what type everything was, and your intended code would compile and run fine.
The other main alternative would be to check what the value is before trying to treat it like a map.  One way to do this uses the as? safe-cast operator.  That checks whether a value is of a given type; if so, it's cast to that type; otherwise, it returns null.  You can then use the .? safe-call operator to call a method only if the value isn't null.  Putting that together:
(description["father"] as? MutableMap<String, String>)?.put("child", "child value")
If the value is as you expect, that will work fine; if not, it will do nothing and continue.
That's rather long-winded, but it will compile and run safely.  Alternatively, you could do the same thing in a more explicit way like this:
val child = description["father"]
if (child is MutableMap<String, String>))
child["child"] = "child value"
(Within the if, the compiler knows the type of child, and uses a a ‘smart cast’ to allow the putter call.)
That's even more long-winded, of course.  But that's what you get from trying to work against the type system :-)
(Oh, and by the way, I think the usual terminology for recursive data structures is ‘parent’ and ‘child’; I've not seen ‘father’ used that way before.)
Try this:
description["father"]?.put("child", "child value")
My current solution:
val description:MutableMap<String,Any> = mutableMapOf(
"father" to "123"
)
val father2 = mutableMapOf<String,String>()
father2.put("child", "child value")
description["father2"]=father2
You can try this:
val description = mutableMapOf<String?,MutableMap<String,String>?>
("father" to mutableMapOf<String,String>())
description.get("father")?.put("Key","Value")
println(description) // {father={Key=Value}}

What language is used by bosun?

From their quickstart guide I got this following sample
alert cpu.is.too.high {
template = test
$metric = q("sum:rate{counter,,1}:os.cpu{host=your-system-here}", "1h", "")
$avgcpu = avg($metric)
crit = $avgcpu > 80
warn = $avgcpu > 60
}
I would guess it's a perlish DSL. What is the name of this language?
We just call it "Bosun's expression language" and is documented at http://bosun.org/expressions.html. As you said it is a custom DSL. It currently has the following qualities
It is not imperative. The language itself actually lacks true variables, the "$foo" are just text replacement
It is functional
It is well typed (functions accept and return specific types. Since the DSL is for alerting, we believe it is important to catch as many errors at possible at parse time.)
The guts implementation of the parser and lexer is based on that guts of text/template. A map function that takes an expression to operator on every X item in a series for an entire seriesSet is in the works, so the language is still a bit in the works. But I don't think we will be change the underlying design choices mentioned above (except maybe actually use real variables instead of text replacement at some point.)

Compiling Code - error CS1056 '`'

I am trying to compile a code using my own compiler (CodeDOM), but on codes like this:
390. sealed class FunctorComparer`1 {
421. public System.Array+FunctorComparer`1[T] () {}
448. abstract public interface IEnumerator`1 {
... (1676 matches) ...
i am getting this error:
c:\Users\[Username]\AppData\Local\Temp\0z4zag32.0.cs(390,29) : error CS1056: Unexpected character '`'
what am I missing?
[EDIT (1, "16:25", "4 May")]
the code i m trying to compile is not written by me. I don't know what that
character stands for, learning it. But i found that on this site
http://submain.com/ghostdoc/samples/PowerCollections/HTML/html/75549028.htm
it is being used, and it is strange the CodeDOM doesnt parse it.
The backticks should be removed from the code. This is what the error code is hinting at.
They were likely added due to an overzealous escaping on the part of the system you're getting this code sample from.
The name of any member (field, property, method, class) can not contain the character
'`'
If you are reading details from
System.Reflection
It will add this character, i m not sure it s need, may be because it is overidding a virtual member x times. like
System.Threading.Tasks.Task`1[System.Threading.Tasks.VoidTaskResult] //1 time
System.Threading.Tasks.Task`6[System.Threading.Tasks.VoidTaskResult] //6 times
Just taking the first part of the declaration is complete, and contains all the informations the computer needs to do the work.
from
System.Threading.Tasks.Task`1[System.Threading.Tasks.VoidTaskResult]
to
System.Threading.Tasks.Task

R cannot declare setClass with inheritance

removeClass("A")
setClass('A',representation=representation(a="numeric"))
setMethod('initialize','A', function(.Object,...,a){
.Object#a=a
.Object
})
ok up to here
removeClass("B")
setClass('B',representation=representation(b="numeric"),contains="A")
This code fails on the definition of class "B" , without I had any chance to add an initialize method for "B", and without I even create any object
Error in .local(.Object, ...) : argument "a" is missing, with no default
It does not fail if I add a default value for the a parameter in initialize.A method
Can anyone explain why ?
"why" is a tricky question, with the answer being "because" it's implemented that way. If you're asking what needs to be done to avoid this, the answer is to either (a) provide a default value to the argument a in the constructor or (b) avoid using an initialize method. There is some discussion here. The implicit contract is that new("A") succeeds,

Resources