ZIO.fail not fail - zio

I want learn methods refineXXX of zio library.
For this purpose I write simple code
import zio.ZIOAppDefault
import zio.Unsafe.unsafe
import zio._
import java.sql.SQLException
object Bot extends ZIOAppDefault {
val codeWithExc: ZIO[Any,Throwable,Int] =
ZIO.fail(new SQLException("message of SQL error."))
val MainApp: ZIO[Any, Throwable, Int] = for {
_ <- Console.printLine("Begin")
res <- codeWithExc
_ <- Console.printLine(s" res = $res")
} yield res
def run: URIO[ZIOAppArgs, ExitCode] =
for {
res <- MainApp.exitCode
} yield res
}
unsafe{ implicit u =>
Runtime.default.unsafe.run(Bot.run.provide(ZIOAppArgs.empty))
}
When I run it in IDEA worksheet I see output:
Begin
res0: zio.Exit[Nothing,zio.ExitCode] = Success(ExitCode(1))
and expect fail in res <- codeWithExc and death of the main fiber.

The problem here is that You are mapping ZIO to .exitCode which returns URIO that cannot really fail. Failure will be mapped to success and the only reason to tell that it did actually fail is to verify that ExitCode was not 0. If You change Your code and replace that with something like below, it will look work correctly:
def run = MainApp

Related

scala console error when testing sample IO using zio

Hi I've below ZIO ConsoleIO test.
import zio._
import zio.Console
import zio.test.Assertion.equalTo
import zio.test._
object ConsoleIOSpec extends ZIOSpecDefault {
val greet: ZIO[Any, Nothing, Unit] = for {
name <- Console.readLine.orDie
_ <- Console.printLine(s"Hello, $name").orDie
} yield ()
def spec = suite("ExampleSpec")(
test("greet says hello to the user") {
for {
_ <- TestConsole.feedLines("Jack")
_ <- greet
value <- TestConsole.output
} yield assert(value) (equalTo(Vector("Hello, Jack")))
}
)
}
The code is on this github here. When I run the test I get the below error -
ExampleSpec / greet says hello to the user
✗ Vector1("Hello, Jack
") was not equal to Vector1("Hello, Jack")
value did not satisfy equalTo(Vector("Hello, Jack"))
value = Vector1("Hello, Jack
")
at /Users/rnatarajan/Documents/Coding/others/zionomicon/c2-testing/src/test/scala/ConsoleIOSpec.scala:18
Output Produced by Test
| Jack
| Hello, Jack
I've attached the error screenshot -
This is code from zionomicon book section 3.3 Test Implementations Of Standard ZIO Services.
How to fix this issue?
Method "Console.printLine" prints the string in parameter, and a carriage return at the end of it, as you can see with the double quotes in a new line.
To fix the problem, you can replace "Console.printLine" with "Console.print", or take into account the return carriage at the end of the output.

Moto doesn't mock the db properly

What am I doing wrong here?
This is my first time using moto and I'm really confused
conftest.py:
#pytest.fixture(scope='module')
def dynamodb(aws_credentials):
with mock_dynamodb2():
yield boto3.resource('dynamodb', region_name='us-east-1')
#pytest.fixture(scope='module')
def dynamodb_table(dynamodb):
"""Create a DynamoDB surveys table fixture."""
table = dynamodb.create_table(
TableName='MAIN_TABLE',
KeySchema=[
[..]
table.meta.client.get_waiter('table_exists').wait(TableName='MAIN_TABLE')
yield
testfile:
mport json
import boto3
from moto import mock_dynamodb2
#mock_dynamodb2
def test_lambda_handler(get_assets_event, dynamodb, dynamodb_table):
from [...] import lambda_handler
dynamodb = boto3.client('dynamodb')
response = lambda_handler(get_assets_event, "")
data = json.loads(response["body"])
assert response["statusCode"] == 200
assert "message" in response["body"]
assert data["message"] == "hello world"
# assert "location" in data.dict_keys()
But the issue is my lambda is using a helper, which has a dynamodb helper under the hood and that dbhelper starts like this:
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table(os.environ.get('MAIN_TABLE'))
def read_item(key: Dict):
try:
return table.get_item(Key=key)
except ClientError as e:
logging.exception(e)
raise exceptions.DatabaseReadException(f"Error reading from db: {key}") from e
Is that even possible to mock like this?
I feel like when I import the lambda handler it tries to overwrite my mocked db, but can't because obviously there's no os environ variable with the table name.

Display file size in a directory

I am hoping to return and print a dictionary of the files and their file size, what I have written is this;
file_size = {}
for fn in glob.glob('*'):
with os.stat(fn) as f:
file_size[fn] = f.st_size
print (file_size)
But I am getting the AtributeError: enter
To use with statement you need to have the methods __enter__() and __exit__() in the object methods.
That is not the case for os.stat(). Remove the with statement and your problem will be fixed:
import glob, os
file_size = {}
for fn in glob.glob('*'):
f = os.stat(fn)
file_size[fn] = f.st_size
print (file_size)

In Kotlin, how do I read the entire contents of an InputStream into a String?

I recently saw code for reading entire contents of an InputStream into a String in Kotlin, such as:
// input is of type InputStream
val baos = ByteArrayOutputStream()
input.use { it.copyTo(baos) }
val inputAsString = baos.toString()
And also:
val reader = BufferedReader(InputStreamReader(input))
try {
val results = StringBuilder()
while (true) {
val line = reader.readLine()
if (line == null) break
results.append(line)
}
val inputAsString = results.toString()
} finally {
reader.close()
}
And even this that looks smoother since it auto-closes the InputStream:
val inputString = BufferedReader(InputStreamReader(input)).useLines { lines ->
val results = StringBuilder()
lines.forEach { results.append(it) }
results.toString()
}
Or slight variation on that one:
val results = StringBuilder()
BufferedReader(InputStreamReader(input)).forEachLine { results.append(it) }
val resultsAsString = results.toString()
Then this functional fold thingy:
val inputString = input.bufferedReader().useLines { lines ->
lines.fold(StringBuilder()) { buff, line -> buff.append(line) }.toString()
}
Or a bad variation which doesn't close the InputStream:
val inputString = BufferedReader(InputStreamReader(input))
.lineSequence()
.fold(StringBuilder()) { buff, line -> buff.append(line) }
.toString()
But they are all clunky and I keep finding newer and different versions of the same... and some of them never even close the InputStream. What is a non-clunky (idiomatic) way to read the InputStream?
Note: this question is intentionally written and answered by the author (Self-Answered Questions), so that the idiomatic answers to commonly asked Kotlin topics are present in SO.
Kotlin has a specific extension just for this purpose.
The simplest:
val inputAsString = input.bufferedReader().use { it.readText() } // defaults to UTF-8
And in this example, you could decide between bufferedReader() or just reader(). The call to the function Closeable.use() will automatically close the input at the end of the lambda's execution.
Further reading:
If you do this type of thing a lot, you could write this as an extension function:
fun InputStream.readTextAndClose(charset: Charset = Charsets.UTF_8): String {
return this.bufferedReader(charset).use { it.readText() }
}
Which you could then call easily as:
val inputAsString = input.readTextAndClose() // defaults to UTF-8
On a side note, all Kotlin extension functions that require knowing the charset already default to UTF-8, so if you require a different encoding you need to adjust the code above in calls to include encoding for reader(charset) or bufferedReader(charset).
Warning: You might see examples that are shorter:
val inputAsString = input.reader().readText()
But these do not close the stream. Make sure you check the API documentation for all of the IO functions you use to be sure which ones close and which do not. Usually, if they include the word use (such as useLines() or use()) they close the stream after. An exception is that File.readText() differs from Reader.readText() in that the former does not leave anything open and the latter does indeed require an explicit close.
See also: Kotlin IO related extension functions
【Method 1 | Manually Close Stream】
private fun getFileText(uri: Uri):String {
val inputStream = contentResolver.openInputStream(uri)!!
val bytes = inputStream.readBytes() //see below
val text = String(bytes, StandardCharsets.UTF_8) //specify charset
inputStream.close()
return text
}
inputStream.readBytes() requires manually close the stream: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/java.io.-input-stream/read-bytes.html
【Method 2 | Automatically Close Stream】
private fun getFileText(uri: Uri): String {
return contentResolver.openInputStream(uri)!!.bufferedReader().use {it.readText() }
}
You can specify the charset inside bufferedReader(), default is UTF-8:
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/java.io.-input-stream/buffered-reader.html
bufferedReader() is an upgrade version of reader(), it is more versatile:
How exactly does bufferedReader() work in Kotlin?
use() can automatically close the stream when the block is done:
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/use.html
An example that reads contents of an InputStream to a String
import java.io.File
import java.io.InputStream
import java.nio.charset.Charset
fun main(args: Array<String>) {
val file = File("input"+File.separator+"contents.txt")
var ins:InputStream = file.inputStream()
var content = ins.readBytes().toString(Charset.defaultCharset())
println(content)
}
For Reference - Kotlin Read File
Quick solution works well when converting InputStream to string.
val convertedInputStream = String(inputStream.readAllBytes(), StandardCharsets.UTF_8)

Swift get value from UnsafeMutablePointer<Void> using UnsafePointer<String>

I am trying to pass contextInfo of typeUnsafeMutablePointer<Void> to UISaveVideoAtPathToSavedPhotosAlbum and use it in the callback function. For some reason I am unable to access contextInfo as a string using UnsafePointer<String>(x).memory when I am in the callback function.
I am pretty sure it is something simple I am missing but have spent way to many hours trying to figure this out.
Below is some code that I have tried.
The following code works.
var testStr:String = "hello"
takesAMutableVoidPointer(&testStr)
func takesAMutableVoidPointer(x: UnsafeMutablePointer<Void>){
var pStr:String = UnsafePointer<String>(x).memory
println("x = \(x)")
println("pStr = \(pStr)")
}
However the following code does not work.
var testStr:String = "hello"
if UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(filePath){ //the filePath is compatible
println("Compatible")
//UISaveVideoAtPathToSavedPhotosAlbum(filePath, self, nil, nil)
UISaveVideoAtPathToSavedPhotosAlbum(filePath, self, "video:didFinishSavingWithError:contextInfo:", &testStr)
}
else{
println("Not Compatible")
}
func video(video: NSString, didFinishSavingWithError error:NSError, contextInfo:UnsafeMutablePointer<Void>){
var pStr:String = UnsafePointer<String>(contextInfo).memory
println("contextInfo = \(contextInfo)")
println("pStr = \(pStr)")
}
Once I get to the following line:
var pStr:String = UnsafePointer<String>(contextInfo).memory
I keep getting the following error:
Thread 1: EXC_BAD_ACCESS(code=1, address=0x0)
Any help with this would be greatly appreciated.
Thanks.
Update
Rintaro commented that testStr needs to be top level but the following code works.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var testStr:String = "hello"
takesAMutableVoidPointer(&testStr)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func takesAMutableVoidPointer(x: UnsafeMutablePointer<Void>){
var answer = UnsafePointer<String>(x).memory
println("x = \(x)")
println("answer = \(answer)")
}
}
I am trying not to use global variables unless I have to. I may have to but since I am able to execute the above code, it seems as though I do not need to use a global variable.
As discussed in OP comments, testStr has already been freed.
Is there any way to force the retaining of a variable that has been created in a function? Then release it later?
It's not impossible, but I don't know this is the best way to do that.
Anyway, try this with Playground or OS X "Command Line Tool" template:
import Foundation
func foo() {
var str:NSString = "Hello World"
let ptr = UnsafePointer<Void>(Unmanaged<NSString>.passRetained(str).toOpaque())
bar(ptr)
}
func bar(v:UnsafePointer<Void>) {
let at = dispatch_time(
DISPATCH_TIME_NOW,
Int64(2.0 * Double(NSEC_PER_SEC))
)
dispatch_after(at, dispatch_get_main_queue()) {
baz(v)
}
}
func baz(v:UnsafePointer<Void>) {
println("notified")
let str = Unmanaged<NSString>.fromOpaque(COpaquePointer(v)).takeRetainedValue()
println("info: \(str)")
}
foo()
println("started")
dispatch_main()
Unmanaged<NSString>.passRetained(str) increments the retain count.
Unmanaged<NSString>.fromOpaque(...).takeRetainedValue() decrements it, and extract the object.
I think, using pure Swift String is impossible. because String is struct and is allocated in stack memory. Maybe the buffer of it is allocated in heap, but we cannot access it directly.

Resources