How to pretty print object representation in IPython - ipython

IPython outputs list representation in a pretty way by default:
In [1]: test_list
Out[1]: [<object_1>,
<object_2>,
<object_3>]
I have object like:
class TestObject(object):
def __init__(self):
self._list = [<object_1>, <object_2>, <object_3>]
def __repr__(self):
return self._list.__repr__()
test_object = Test()
And IPython representation of this is:
In [2]: test_list
Out[2]: [<object_1>, <object_2>, <object_3>]
Is there a way to get list's way of the representation for my object?

To get the pretty-printed repr of a list, or any object, call:
from IPython.lib.pretty import pretty
pretty(obj)
If you want your object to have a pretty repr separate from its normal repr (e.g. so it doesn't need IPython to repr() it), you can define a _repr_pretty_(self, cycle=False) method. The cycle parameter will be true if the representation recurses - e.g. if you put a container inside itself.

Related

Shapeless and gremlin scala: How do I return the result of a call to `as`?

So, I am calling this function as (from gremlin-scala):
case class GremlinScala[End, Labels <: HList](traversal: GraphTraversal[_, End]) {
def as(name: String, moreNames: String*)(implicit p: Prepend[Labels, End :: HNil]) =
GremlinScala[End, p.Out](traversal.as(name, moreNames: _*))
}
It is defined here: https://github.com/mpollmeier/gremlin-scala/blob/master/gremlin-scala/src/main/scala/gremlin/scala/GremlinScala.scala#L239
It takes an implicit Prepend argument, which I am not sure I understand. I know that gremlin-scala uses its HList to keep track of which points in the query as is called, so that later when select is called it knows which points in the traversal to return.
This is the key: as appends to that HList. Or prepends apparently, as the case may be.
This works fine in general code, but now I want to write a function that calls as and returns its result. This is where I am stuck: what is the signature of the return value of this function?
Finally, I have added an implicit param to my function, but I fear I have just chased the problem up a level. Here is what I have so far:
case class AsOperation[A, In <: HList](step: String) extends Operation {
def operate(g: GremlinScala[A, In]) (implicit p: Prepend[In, ::[A, HNil]]): GremlinScala[A, p.Out] = {
g.as(step)
}
}
This makes it compile, but I still can't use this function! Whenever I call it, it complains to me that
could not find implicit value for parameter p: shapeless.ops.hlist.Prepend[In,shapeless.::[A,shapeless.HNil]]
How do I write a function that returns the result of as, and what is its signature?
Thanks!
As you explain correctly, the reason we use prepend is to keep the types of the steps labelled with as. It's keeping them in the reverse order since it's easier to process on both sides: for capturing and replaying.
So the implicit p: Prepend[Labels, End :: HNil] is prepending the type at the current step so that we have it captured in the second type parameter (and can use it in later steps, e.g. select).
As far as I can see you're doing exactly the right thing, and it actually works... for me anyway :)
This compiles:
import gremlin.scala._
import shapeless.{HNil, ::}
import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerFactory
def graph = TinkerFactory.createModern.asScala
val gs1: GremlinScala[Vertex, Vertex :: HNil] = graph.V().as("a")
val gs2: GremlinScala[Vertex, Vertex :: HNil] = AsOperation("someLabel").operate(graph.V())

scala, I lose the type information when using pprint

I would expect that toPrettyString1 and toPrettyString2 get the same result, but it seems that toPrettyString1 losses the type information, and pprint.tokenize cannot the fields and print it nicely.
Why is so, and how to solve it?
libraryDependencies += "com.lihaoyi" %% "pprint" % "0.4.1"
case class Entry(id: Int, text: String)
val entry = Entry(1, "hello")
def toPrettyString1[T](o: T) = pprint.tokenize(o).mkString
def toPrettyString2(o: Entry) = pprint.tokenize(o).mkString
println(toPrettyString1(entry)) // I get Entry(1,hello), not what I want
println(toPrettyString2(entry)) // I get Entry(1, "hello"), as expected
The pprint library uses a PPrint type class to determine how a value of a particular type should be printed. If you have a completely unconstrained type T, you'll get a PPrint instance that simply calls toString on the value, which means you won't get quotation marks or the nice escaping pprint provides.
This is really all pprint can reasonably do if it knows nothing about the type, and even that is arguably too much—many type class-based libraries simply do not provide default instances like this even when there is a possible default interpretation of what the type class operations should do.
toPrettyString2 works as expected because you're calling tokenize with a value that's statically typed as Entry, which PPrint can provide a better instance for. If you want this behavior with a generic type, you'll have to add a context bound:
def toPrettyString3[T: pprint.PPrint](o: T) = pprint.tokenize(o).mkString
And then:
scala> println(toPrettyString3(entry))
Entry(1, "hello")
Now you're calling tokenize not with some completely generic T, but specifically with a T that you have a PPrint instance for, and when you call toPrettyString3 with an Entry argument, the library will provide a PPrint instance with the quotation marks, escaping, etc.
The T: pprint.PPrint syntax is just sugar for an implicit argument:
def toPrettyString3[T](o: T)(implicit pp: pprint.PPrint[T]) =
pprint.tokenize(o)(pp).mkString
You didn't define an implicit PPrint[Entry] instance, but the library is able to derive reasonable instances for case classes using a macro. You could also define your own instance if for some reason you wanted different behavior, though, and it would override the derived instance.

How do I get an object's type and pass it along to asInstanceOf in Scala?

I have a Scala class that reads formatting information from a JOSN template file, and data from a different file. The goal is to format as a JSON object specified by the template file. I'm getting the layout working, but now I want to set the type of my output to the type in my template (i.e. if I have a field value as a String in the template, it should be a string in the output, even if it's an integer in the raw data).
Basically, I'm looking for a quick and easy way of doing something like:
output = dataValue.asInstanceOf[templateValue.getClass]
That line gives me an error that type getClass is not a member of Any. But I haven't been able to find any other member or method that gives me an variable type at runtime. Is this possible, and if so, how?
Clarification
I should add, by this point in my code, I know I'm dealing with just a key/value pair. What I'd like is the value's type.
Specifically, given the JSON template below, I want the name to be cast to a String, age to be cast to an integer, and salary to be cast a decimal on output regardless of how it appears in the raw data file (it could be all strings, age and salary could both be ints, etc.). What I was hoping for is a simple cast that didn't require me to do pattern matching to handle each data type specifically.
Example template:
people: [{
name: "value",
age: 0,
salary: 0.00
}]
Type parameters must be known at compile time (type symbols), and templateValue.getClass is just a plain value (of type Class), so it cannot be used as type parameter.
What to do instead - this depends on your goal, which isn't yet clear to me... but it may look like
output = someMethod(dataValue, templateValue.getClass),
and inside that method you may do different computations depending on second argument of type Class.
How do I get an object's type and pass it along to asInstanceOf in Scala?
The method scala.reflect.api.JavaUniverse.typeOf[T] requires it's type argument to be hard-coded by the caller or type-inferred. To type-infer, create a utility method like the following (works for all types, even generics - it counteracts java runtime type arg erasure by augmenting T during compilation with type tag metadata):
// http://www.scala-lang.org/api/current/index.html#scala.reflect.runtime.package
import scala.reflect.runtime.universe._
def getType[T: TypeTag](a: T): Type = typeOf[T]
3 requirements here:
type arg implements TypeTag (but previous implementation via Manifest still available...)
one or more input args are typed T
return type is Type (if you want the result to be used externally to the method)
You can invoke without specifying T (it's type-inferred):
import scala.reflect.runtime.universe._
def getType[T: TypeTag](a: T): Type = typeOf[T]
val ls = List[Int](1,2,3)
println(getType(ls)) // prints List[Int]
However, asInstanceOf will only cast the type to a (binary consistent) type in the hierarchy with no conversion of data or format. i.e. the data must already be in the correct binary format - so that won't solve your problem.
Data Conversion
A few methods convert between Integers and Strings:
// defined in scala.Any:
123.toString // gives "123"
// implicitly defined for java.lang.String via scala.collection.immutable.StringOps:
123.toHexString // gives "7b"
123.toOctalString // gives "173"
"%d".format(123) // also gives "123"
"%5d".format(123) // gives " 123"
"%05d".format(123) // gives "00123"
"%01.2f".format(123.456789) // gives "123.46"
"%01.2f".format(123.456789) // gives "0.46"
// implicitly defined for java.lang.String via scala.collection.immutable.StringOps:
" 123".toInt // gives 123
"00123".toInt // gives 123
"00123.4600".toDouble // gives 123.46
".46".toDouble // gives 0.46
Parsing directly from file to target type (no cast or convert):
Unfortunately, scala doesn't have a method to read the next token in a stream as an integer/float/short/boolean/etc. But you can do this by obtaining a java FileInputStream, wrapping it in a DataInputStream and then calling readInt, readFloat, readShort, readBoolean, etc.
In a type-level context the value-level terms still have a few accessors. The first one and the one you asked for is the type of the value itself (type):
output = dataValue.asInstanceOf[templateValue.type]
if the type of the value has inner members, those become available as well:
class A {
class B {}
}
val a: A = new A
val b: a.B = new a.B
Notice b: a.B.
I must also mention how to access such members without a value-level term:
val b: A#B = new a.B

covariant type T occurs in invariant position

I'm moving my first steps in Scala and I would like to make the following code works:
trait Gene[+T] {
val gene: Array[T]
}
The error that the compiler gives is: covariant type T occurs in invariant position in type => Array[T] of value gene
I know I could do something like:
trait Gene[+T] {
def gene[U >: T]: Array[U]
}
but this doesn't solve the problem because I need a value: pratically what I'm trying to say is "I don't care of the inside type, I know that genes will have a gene field that return its content". (the +T here is because I wanna do something like type Genome = Array[Gene[Any]] and then use it as a wrapper against the single gene classes so I can have a heterogeneous array type)
Is it possible to do it in Scala or I'm simply taking a wrong approach? Would it be better to use a different structure, like a Scala native covariant class?
Thanks in advance!
P.S.: I've also tried with class and abstract class instead than trait but always same results!
EDIT: with kind suggestion by Didier Dupont I came to this code:
package object ga {
class Gene[+T](val gene: Vector[T]){
def apply(idx: Int) = gene(idx)
override def toString() = gene.toString
}
implicit def toGene[T](a: Vector[T]) = new Gene(a)
type Genome = Array[Gene[Any]]
}
package test
import ga._
object Test {
def main(args: Array[String]) {
val g = Vector(1, 3, 4)
val g2 = Vector("a", "b")
val genome1: Genome = Array(g, g2)
println("Genome")
for(gene <- genome1) println(gene.gene)
}
}
So I now think I can put and retrieve data in different types and use them with all type checking goodies!
Array is invariant because you can write in it.
Suppose you do
val typed = new Gene[String]
val untyped : Gene[Any] = typed // covariance would allow that
untyped.gene(0) = new Date(...)
this would crash (the array in your instance is an Array[String] and will not accept a Date). Which is why the compiler prevents that.
From there, it depends very much on what you intend to do with Gene. You could use a covariant type instead of Array (you may consider Vector), but that will prevent user to mutate the content, if this was what you intended. You may also have an Array inside the class, provided it is decladed private [this] (which will make it quite hard to mutate the content too). If you want the client to be allowed to mutate the content of a Gene, it will probably not be possible to make Gene covariant.
The type of gene needs to be covariant in its type parameter. For that to be possible, you have to choose an immutable data structure, for example list. But you can use any data structure from the scala.collection.immutable package.

In py.test, how can I narrow the scope of an xfail mark?

I would like to narrow the scope of the pytest xfail mark. As I currently use it, it marks the entire test function, and any failure in the function is cool.
I would like to narrow that down to a smaller scope, perhaps with a context manager similar to "with pytest.raises (module.Error)". For example:
#pytest.mark.xfail
def test_12345():
first_step()
second_step()
third_step()
This test will xfail if I assert in any of the three methods I call. I would like instead for the test to xfail only if it asserts in second_step(), and not elsewhere. Something like this:
def test_12345():
first_step()
with pytest.something.xfail:
second_step()
third_step()
Is this possible with py.test?
Thanks.
You can define a context manager yourself that does it, like this:
import pytest
class XFailContext:
def __enter__(self):
pass
def __exit__(self, type, val, traceback):
if type is not None:
pytest.xfail(str(val))
xfail = XFailContext()
def step1():
pass
def step2():
0/0
def step3():
pass
def test_hello():
step1()
with xfail:
step2()
step3()
Of course you can also modify the contextmanager to look for specific exceptions.
The only caveat is that you cannot cause an "xpass" outcome, i.e. a special result that the (part of the) test unexpectedly passed.