I'm trying new Swift 5.5 await async features and I get that compilation error when I try this in a Playground:
let task1 = Task {
// ...
}
'Task' cannot be constructed because it has no accessible initializers
I got the example from https://www.hackingwithswift.com/articles/233/whats-new-in-swift-5-5
Any idea?
It looks like the current syntax is async { ... } instead of Task { ... } with the intention that the Task syntax is to be used in some future build.
Related
Suppose we need to execute some code when a function finishes, no matter how.
Example:
void myFunc() async {
await myLock.acquire();
if(...) {
myLock.release();
return;
}
...
myLock.release();
}
Many languages have features that allow to achieve this in a more elegant way than just manually calling myLock.release() before every return statement (For example defer in Go). Is something like that also possible in Dart?
Dart does not have RAII. You instead would need to use try-finally.
(Dart did recently (in 2.17) add Finalizers, but those would fire when objects are garbage collected, which might happen at some non-deterministic time, if ever.)
And just for the record, an example of using try/finally:
void myFunc() async {
await myLock.acquire();
try {
if(...) {
return;
}
...
} finally {
myLock.release();
}
}
You'd want to start the try after allocating the resource, so that you don't try to release if allocation throws.
Is something like this possible, i.e. using the JobDSL API from a class outside the main DSL script?
//main_jobdsl_script.groovy:
new JobCreator().createJob()
//JobCreator.groovy:
job("new-job") {
steps {
batchFile("Hello World")
}
}
When running it I get the error
13:03:18 ERROR: No signature of method: JobCreator.job() is applicable for argument types:
(org.codehaus.groovy.runtime.GStringImpl, StartJobCreator$_createJob_closure1)
values: ["new-job", de.dbh.jobcreation.StartJobCreator$_createStartJob_closure1#374d293]
I want to avoid that the main-script gets too big and cluttered and rather divide the code into several scripts / classes.
Yes, it is possible. The current script has access to all API methods, so you need to pass it to the custom class.
//main_jobdsl_script.groovy:
new JobCreator(this).createJob()
//JobCreator.groovy:
class JobCreator {
private final Object context
JobCreator(Object context) {
this.context = context
}
void createJob() {
context.job('new-job') {
steps {
batchFile('Hello World')
}
}
}
}
Currently I'm trying to register findFiles step.
My set up is as follows:
src/
test/
groovy/
TestJavaLib.groovy
vars/
javaLib.groovy
javaApp.jenkinsfile
Inside TestJavaApp.groovy I have:
...
import com.lesfurets.jenkins.unit.RegressionTest
import com.lesfurets.jenkins.unit.BasePipelineTest
class TestJavaLibraryPipeline extends BasePipelineTest implements RegressionTest {
// Some overridden setUp() which loads shared libs
// and registers methods referenced in javaLib.groovy
void registerPipelineMethods() {
...
def fileList = [new File("testFile1"), new File("testFile2")]
helper.registerAllowedMethod('findFiles', { f -> return fileList })
...
}
}
and my javaLib.groovy contains this currently failing part:
...
def pomFiles = findFiles glob: "target/publish/**/${JOB_BASE_NAME}*.pom"
if (pomFiles.length < 1) { // Fails with java.lang.NullPointerException: Cannot get property 'length' on null object
error("no pom file found")
}
...
I have tried multiple closures returning various objects, but everytime I get NPE.
Question is - how to correctly register "findFiles" method?
N.B. That I'm very new to mocking and closures in groovy.
Looking at the source code and examples on GitHub, I see a few overloads of the method (here):
void registerAllowedMethod(String name, List<Class> args = [], Closure closure)
void registerAllowedMethod(MethodSignature methodSignature, Closure closure)
void registerAllowedMethod(MethodSignature methodSignature, Function callback)
void registerAllowedMethod(MethodSignature methodSignature, Consumer callback)
It doesn't look like you are registering the right signature with your call. I'm actually surprised you aren't getting a MissingMethodException with your current call pattern.
You need to add the rest of the method signature during registration. The findFiles method is taking a Map of parameters (glob: "target/publish/**/${JOB_BASE_NAME}*.pom" is a map literal in Groovy). One way to register that type would be like this:
helper.registerAllowedMethod('findFiles', [Map.class], { f -> return fileList })
I also faced the same issue. However, I was able to mock the findFiles() method using the following method signature:
helper.registerAllowedMethod(method('findFiles', Map.class), {map ->
return [['path':'testPath/test.zip']]
})
So I found a way on how to mock findFiles when I needed length property:
helper.registerAllowedMethod('findFiles', [Map.class], { [length: findFilesLength ?: 1] })
This also allows to change findFilesLength variable in tests to test different conditions in pipeline like the one in my OP.
I'm using grails 2.1.1 and I getting the message "No signature of method: ClassA.save() is applicable for argument types: () values: []" when trying to save an object in production environment.
This is the code:
def method(campId, userId){
ClassA cbl = new ClassA()
cbl.userId = userId
cbl.campId = campId
cbl.save(flush:true)
}
This code works fine in development but when I execute the code in production I have this problem.
A couple of things to look out for
You say it works in dev but not in production so the first starting point of any investigation is what is the difference between both. Meaning do a show create table class_a on both product/development environments.
It maybe something has changed and it has some required value that is no longer provided
Step 2:
It is obviously not saving so you need to see if any errors are thrown
def method(campId, userId){
if (campId && userId) {
try {
ClassA cbl = new ClassA()
cbl.userId = userId
cbl.campId = campId
if (!cbl.save(flush:true)) {
//println cbl.errors
//log.info "${cbl.errors}"
}
}catch (Exception e) {
//println "E really happended $e"
}
}else {
println "oh my ... a certain value has not been provided"
}
}
You see in above code an if statement to ensure both values provided since you are setting without checking, the try catch was last alternative to try but the if it saves println error is the next thing to try
Finally there are many ways to save a class just in case as Anton suggest you have some other inbuild functions in ClassA when it comes to saving and new ClassA() may cause an issue maybe since you are missing
ClassA() {
super()
}
or something then I would lastly try this as a test
ClassA cbl = new ClassA(userId:userId,campId:campId)?.save(flush:true)
Same logic applied differently
How can I access ant tasks from my build.gradle.kts script? In particular, I am interested in the ant.patch task.
Can I extend it, like so?
task("patchSources", Patch::class) {
Can I invoke it from other task, like this?
task("patchSources") {
doLast {
ant.patch(...)
}
}
I know how to do it in Groovy: How do I apply a patch file in Gradle?
AntBuilder extends from Groovy's AntBuilder. You can translate the dynamic method invocations from groovy like ant.patch() to Kotlin by using invokeMethod and providing the desired task as the first argument and the properties to bind as a map in the second argument.
For example, for your Patch use case (available properties documentation) the Kotlin could look like this:
val patchSources by tasks.creating {
doLast {
ant.invokeMethod("patch", mapOf(
"patchfile" to patchFile,
"dir" to configDir,
"strip" to 1
))
}
}
This works for me:
import org.apache.tools.ant.taskdefs.Patch
val patchConfigTask = task("patchConfig") {
dependsOn(unzipTask)
doLast {
val resources = projectDir.resolve("src/main/resources")
val patchFile = resources.resolve("config.patch")
Patch().apply {
setPatchfile(patchFile)
setDir(buildDir.resolve("config/"))
setStrip(1) // gets rid of the a/ b/ prefixes
execute()
}
}
}
I am not sure if it's the one-right-way-to-do-it.