Should classes be import when only used for type hints? PEP 560 - type-hinting

What is the benefit of importing from __future__ import annotations? When I understand it right I should stop unnecessary typing import in runtime.
In my example HelloWorld is only needed for typing. But with this code the output always is:
Should this happen?
x = World!
When I remove from hello import HelloWorld the typing help in PyCharm does not longer work (I can understand this, because it does not understand where HelloWorld is from).
from __future__ import annotations
from hello import HelloWorld
if __name__ == '__main__':
def hello(x: str, hello: HelloWorld = None):
if hello is not None:
print('hello.data_01 =', hello.data_01)
print('x =', x)
hello('World!')
hello.py
from dataclasses import dataclass
#dataclass
class HelloWorld:
data_01: str
data_02: str
print("Should this happen?")
So my question is if I still need to do from hello import HelloWorld what benefits do I get from from __future__ import annotations?

The from __future__ import annotations import has one core advantage: it makes using forward references cleaner.
For example, consider this (currently broken) program.
# Error! MyClass has not been defined yet in the global scope
def foo(x: MyClass) -> None:
pass
class MyClass:
# Error! MyClass is not defined yet, in the class scope
def return_copy(self) -> MyClass:
pass
This program will actually crash when you try running it at runtime: you've tried using 'MyClass' before it's actually ever defined. In order to fix this before, you had to either use the type-comment syntax or wrap each 'MyClass' in a string to create a forward reference:
def foo(x: "MyClass") -> None:
pass
class MyClass:
def return_copy(self) -> "MyClass":
pass
Although this works, it feels very janky. Types should be types: we shouldn't need to have to manually convert certain types into strings just to make types play nicely with the Python runtime.
We can fix this by including the from __future__ import annotations import: that line automatically makes all types a string at runtime. This lets us write code that looks like the first example without it crashing: since each type hint is actually a string at runtime, we're no longer referencing something that doesn't exist yet.
And typecheckers like mypy or Pycharm won't care: to them, the type looks the same no matter how Python itself chooses to represent it.
One thing to note is that this import does not, by itself, let us avoid importing things. It simply makes it cleaner when doing so.
For example, consider the following:
from expensive_to_import_module import MyType
def blah(x: MyType) -> None: ...
If expensive_to_import_module does a lot of startup logic, that might mean it takes a non-negligible amount of time to import MyType. This won't really make a difference once the program is actually running, but it does make the time-to-start slower. This can feel particularly bad if you're trying to write short-lived command-line style programs: the act of adding type hints can sometimes make your program feel more sluggish when starting up.
We could fix this by making MyType a string while hiding the import behind an if TYPE_CHECKING guard, like so:
from typing import TYPE_CHECKING
# TYPE_CHECKING is False at runtime, but treated as True by type checkers.
# So the Python interpreters won't do the expensive import, but the type checker
# will still understand where MyType came from!
if TYPE_CHECKING:
from expensive_to_import_module import MyType
# This is a string reference, so we don't attempt to actually use MyType
# at runtime.
def blah(x: "MyType") -> None: ...
This works, but again looks clunky. Why should we need to add quotes around the last type? The annotations future import makes the syntax for doing this a little smoother:
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from expensive_to_import_module import MyType
# Hooray, no more quotes!
def blah(x: MyType) -> None: ...
Depending on your point-of-view, this may not seem like a huge win. But it does help make using type hints much more ergonomic, makes them feel more "integrated" into Python, and (once these become enabled by default) removes a common stumbling block newcomers to PEP 484 tend to trip over.

Related

Can pureconfig use camel case config

I'm using pureconfig pureconfig lib with pureconfig-yaml module. Everything works like a charm, my only problem is that I have to convert the property names from camel case to kebab case.
Painful examples from real world:
case class Config(log4JPath: String, registryURL: String, HOUR_FORMAT: String)
Yaml:
log-4-j-path: /conf/log4j.properties
registry-url: http://foo.com
hour-_-format: dd-mm-yy
I don't want to maintain 2 different case types and think about how to convert from one to the other, I would love to have pure copy&paste scala class -> yaml config solution. Is there a chance I could achieve camel case on both sides ?
Edit:
I've created a wrapper around pureconfig lib, which does some config overriding by environment variables. Client should use the wrapper in following manner:
val conf: Config = ConfigLoader(file).load[Config]
However this is not sufficient and the client needs to provide 2 imports:
// to find implicit reader
import pureconfig.generic.auto._
// to use Camelcase - as suggested from the answer
import ConfigLoader.productHint
It would be great if the wrapper (ConfigLoader) could deal with the imports and they would not be left on client's responsibility.
Moreover the imports are identified as "Unused" by IntelliJ IDE and when "optimize imports" is triggered or "Optimize imports on the fly" is enabled the imports are auto-erased. According to this thread (accepted answer is not working for me), we can solve this with "Mark import as always used...", however this is not an ideal solution because other team members will have to do the same for every project or we should commit .idea to VCS (which I'd like to avoid).
I'm attaching screenshot of my test (dependency pureconfig.generic.auto._ have already been marked as allways used):
Yes you can. Take a look to the documentation - field-mappings.
import pureconfig._
import pureconfig.generic.auto._
import pureconfig.generic.ProductHint
// Case classes should be final ;)
final case class Config(log4JPath: String, registryURL: String, HOUR_FORMAT: String)
val yaml =
"""log4JPath: /conf/log4j.properties
|registryURL: http://foo.com
|HOUR_FORMAT: dd-mm-yy""".stripMargin
implicit val indentityHint: ProductHint[Conf] =
ProductHint[Conf](new ConfigFieldMapping {
def apply(fieldName: String) = fieldName // Basically the identity.
})
loadYaml[Config](yaml)
// res: ConfigReader.Result[Config] = Right(Config("/conf/log4j.properties", "http://foo.com", "dd-mm-yy"))
(Note, this was tested in ammonite, using pureconfig 0.11.0).

How do I figure out the right partial imports to use for scalaz 7? [duplicate]

I am using scalaz7 in a project and sometimes I run into issues with imports. The simplest way get started is
import scalaz._
import Scalaz._
but sometimes this can lead to conflicts. What I have been doing until now the following slightly painful process:
work out a minimal example that needs the same imports as my actual code
copy that example in a separate project
compile it with the option -Xprint:typer to find out how the code looks after implicit resolution
import the needed implicits in the original project.
Although this works, I would like to streamline it. I see that scalaz7 has much more fine-grained imports, but I do not fully understand how they are organized. For instance, I see one can do
import scalaz.std.option._
import scalaz.std.AllInstances._
import scalaz.std.AllFunctions._
import scalaz.syntax.monad._
import scalaz.syntax.all._
import scalaz.syntax.std.boolean._
import scalaz.syntax.std.all._
and so on.
How are these sub-imports organized?
As an example, say I want to work with validations. What would I need, for instance to inject validation implicits and make the following compile?
3.fail[String]
What about making ValidationNEL[A, B] an instance of Applicative?
This blog post explains the package structure and imports a la carte in scalaz7 in detail: http://eed3si9n.com/learning-scalaz-day13
For your specific examples, for 3.failure[String] you'd need:
import scalaz.syntax.validation._
Validation already has a method ap:
scala> "hello".successNel[Int] ap ((s: String) => "x"+s).successNel[Int]
res1: scalaz.Validation[scalaz.NonEmptyList[Int],java.lang.String] = Success(xhello)
To get the <*> operator, you need this import:
import scalaz.syntax.applicative._
Then you can do:
"hello".successNel[Int] <*> ((s: String) => "x"+s).successNel[Int]

Scala JSR 223 importing types/classes

The following example fails because the definition for Stuff can't be found:
package com.example
import javax.script.ScriptEngineManager
object Driver5 extends App {
case class Stuff(s: String, d: Double)
val e = new ScriptEngineManager().getEngineByName("scala")
println(e.eval("""import Driver5.Stuff; Stuff("Hello", 3.14)"""))
}
I'm unable to find any import statement that allows me to use my own classes inside of the eval statement. Am I doing something wrong? How does one import classes to be used during eval?
EDIT: Clarified example code to elicit more direct answers.
The Scripting engine does not know the context. It surely can't access all the local variables and imports in the script, since they are not available in the classfiles. (Well, variable names may be optionally available as a debug information, but it is virtually impossible to use them for this purpose.)
I am not sure if there is a special API for that. Imports are different across various languages, so bringing an API that should fit them all can be difficult.
You should be able to add the imports to the eval-ed String. I am not sure if there is a better way to do this.

Scala-IDE or Scala strange import behavior

I am working on a small Scala project. I have the following issue with 'import':
If, at the top of one of my files, I import two thing with these commands:
import main.Main._
import main.game.Game
^^^^
it gives me the following error message at the underlined 'main' word: "missing arguments for method main in object Main; follow this method with `_' if you want to treat it as a partially applied function" which is quite strange especially that it is just an import statement. And naturally no actual importing occures. At first I thought about semicolon inference quirks again but it is not the case. If I swap the two lines and write like this:
import main.game.Game
import main.Main._
then everythinng is fine.
Could anyone shed some light on that? Is it something special about Scala?
Presumably you have a main method in object Main. So after import main.Main._ main refers to this method instead of the main package. You could avoid it in several ways:
Change import order, as in the question.
Don't import the main method, as Daniel C. Sobral's answer suggests.
Explicitly say you want the top-level main package:
import _root_.main.game.Game
Following the normal Java package naming convention should avoid this problem in most cases, as you are unlikely to have members (or subpackages) called com or org (though net could be a problem).
You do have a method named main inside main.Main, don't you? Well, since you imported it, it has now shadowed the package by the name main. You can try this to confirm:
import main.Main.{main => _, _}
import main.game.Game
This will exclude main from being imported.

How should I organize implicits in my Scala application?

Having written a few scala tools, I'm trying to come to grips with the best way to arrange my code - particularly implicits. I have 2 goals:
Sometimes, I want to be able to import just the implicits I ask for.
Othertimes, I want to just import everything.
To avoid duplicating the implicits, I've come up with this structure (similar to the way scalaz is arranged):
case class StringW(s : String) {
def contrived = s + "?"
}
trait StringWImplicits {
implicit def To(s : String) = StringW(s)
implicit def From(sw : StringW) = sw.s
}
object StringW extends StringWImplicits
// Elsewhere on Monkey Island
object World extends StringWImplicits with ListWImplicits with MoreImplicits
This allows me to just
import StringW._ // Selective import
or (in most cases)
import World._. // Import everything
How does everyone else do it?
I think that implicit conversions are dangerous if you don't know where they are coming from. In my case, I put my implicits in a Conversions class and import it as close to the use as possible
def someMethod(d: Date) ; Unit {
import mydate.Conversions._
val tz = TimeZone.getDefault
val timeOfDay = d.getTimeOfDay(tz) //implicit used here
...
}
I'm not sure I like "inheriting" implicits from various traits for the same reason it was considered bad Java practice to implement an interface so you could use its constants directly (static imports are preferred instead).
I usually had implicit conversions in an object which clearly signals that what it is imported is an implicit conversion.
For example, if I have a class com.foo.bar.FilthyRichString, the implicit conversions would go into com.foo.bar.implicit.FilthyRichStringImplicit. I know the names are a bit long, but that's why we have IDEs (and Scala IDE support is getting better). The way I do this is that I feel it is important that all the implicit conversions can be clearly viewed in a 10 second code review. I could look at the following code:
// other imports
import com.foo.bar.FilthyRichString
import com.foo.bar.util.Logger
import com.foo.bar.util.FileIO
import com.foo.bar.implicits.FilthyRichStringImplicit._
import com.foo.bar.implicits.MyListImplicit._
// other implicits
and at a glance see all the implicit conversions that are active in this source file. They would also be all gathered together, if you use the convention that imports are grouped by packages, with a new line between different packages.
Along the lines of the same argument, I wouldn't like a catch-all object that holds all of the implicit conversions. In a big project, would you really use all of the implicit conversions in all your source files? I think that doing that means very tight coupling between different parts of your code.
Also, a catch-all object is not very good for documentation. In the case of explicitly writing all the implicit conversions used in a file, one can just look at your import statements and straight away jump to the documentation of the implicit class. In the case of a catch-all object, one would have to look at that object (which in a big project might be huge) and then search for the implicit conversion they are after.
I agree with oxbow_lakes that having implicit conversion in traits is bad because of the temptation of inheriting from it, which is, as he said, bad practice. Along those lines, I would make the objects holding the implicit conversions final just to avoid the temptation altogether. His idea of importing them as close to the use as possible is very nice as well, if implicit conversions are just used sparingly in the code.
-- Flaviu Cipcigan