问:
How Do I Make A Pi Pico W Connect To A Network With Wps?
First time using Stack overflow so I'll do my best to explain.

TLDR - HOW DO I MAKE A PI PICO W CONNECT TO A NETWORK WITH WPS?

I'm making a thing, that basically checks whether the value of a particular stock has gone up or down and lights up green or red LED's based on whether the price is up or down. That's all well and good, but to do this it needs to connect to wifi, and being that the thing I'm making has no screen, or keyboard, all we have to accomplish this is the LED's (for the device to communicate with us) and whatever button I put on there.

My plan was to have the device look at a file called "your_wifi_details.txt" for the SSID and pass, and if it finds them, connect - if nothing is there, or if it cannot connect using those details, it is to enter "WPS mode" where the lights will flash, and the user presses the WPS button on their router then presses a button on the device.

Everything is wired up and working perfectly aside from I cannot work out how to get WPS to work on a Pi Pico W. I think I've gotten really close, but i'm getting the error "'CYW43' object has no attribute 'scan_wps'"

(The lines of code are:
# If the button is pressed, scan for WiFi networks that support WPS
if not button.value():
sta_if.scan_wps()

```<code>        # Connect to the first WiFi network that supports WPS
        sta_if.connect_wps()
</code>```

)

Then it goes on to connect to the API's and such to get the stock price and from there everything is good.

Literally everything works, if I manually go into the "your_wifi_details.txt" and put in a correct SSID and password, we're golden, but I can't have users required to download thonny and connect to the device and edit files and yada yada... so I am really hoping this WPS thing can work.

This is the first 'proper' program i've written since starting to learn python so apologies if this is a stupid approach, it's taken a lot or time and confusion to get this far but it's so nearly working, I just need a little help over the finish line so if anyone has faced this problem or can help me toward a solution I'd be super grateful

Here's excerpts from the relevant bits of code that are connected to the problem. There's a lot of "print" debugging commands so I can see in the terminal in Thonny where the program is at and what it's doing, obviously in the final use case there won't be a screen or keyboard so all that stuff will be taken out once development is complete:

```<code>import urequests
import network
import time
import machine

#--------------(Stackoverflow comment)  then further down

#stackoverflow comment:  I don't know why this next line is in bold, it shouldn't be
# Set up the button (connected to pin 15)
button = machine.Pin(15, machine.Pin.IN, machine.Pin.PULL_UP)
print ('pin 15 set as button')

#--------------(Stackoverflow comment)  then further down still

while True:
    print ('enter while true loop')
    # Connect to the WiFi network
    sta_if = network.WLAN(network.STA_IF)
    #print ('firstline passed, sleeping for 10 seconds')

#ignore this, unnecessary now
    #for i in range (0, 20):
     #   time.sleep(0.55)
      #  print ('sleeping...')

    #print ('nap over, trying to continue..')
    sta_if.active(True)
    print ('firing up connection')

    # Read the WiFi SSID and password from the text file
    with open("your_wifi_details.txt", "r") as f:
        ssid = f.readline().strip()
        password = f.readline().strip()
        print ('read your_wifi_details.txt successfully')

    # Try to connect to the WiFi network
    sta_if.connect(ssid, password)
    print ('attempting to connect to wifi')

    # Wait until the device is connected to the WiFi network
    while not sta_if.isconnected():
        # Flash the LEDs to indicate that the device is unable to connect
        print ('connection failed, attempting to flash LEDs')
        green_led.on()
        red_led.on()
        time.sleep(0.5)
        green_led.off()
        red_led.off()
        time.sleep(0.5)

        # Set up the button (connected to pin 0)
        print ('setting up button for WPS')
        button = machine.Pin(15, machine.Pin.IN, machine.Pin.PULL_UP)

        # If the button is pressed, scan for WiFi networks that support WPS
        if not button.value():
            sta_if.scan_wps()

            # Connect to the first WiFi network that supports WPS
            sta_if.connect_wps()

            # Save the WiFi SSID and password to the "your_wifi_details.txt" file
            with open("your_wifi_details.txt", "w") as f:
            f.write(sta_if.config("essid") + "\n")
            f.write(sta_if.config("password") + "\n")
            print ('wifi details written to file')

# Print the WiFi connection status in the terminal so I can see if it worked
print("Connected to WiFi:", sta_if.isconnected())
</code>```

Body:
First time using Stack overflow so I'll do my best to explain.

TLDR - HOW DO I MAKE A PI PICO W CONNECT TO A NETWORK WITH WPS?

I'm making a thing, that basically checks whether the value of a particular stock has gone up or down and lights up green or red LED's based on whether the price is up or down. That's all well and good, but to do this it needs to connect to wifi, and being that the thing I'm making has no screen, or keyboard, all we have to accomplish this is the LED's (for the device to communicate with us) and whatever button I put on there.

My plan was to have the device look at a file called "your_wifi_details.txt" for the SSID and pass, and if it finds them, connect - if nothing is there, or if it cannot connect using those details, it is to enter "WPS mode" where the lights will flash, and the user presses the WPS button on their router then presses a button on the device.

Everything is wired up and working perfectly aside from I cannot work out how to get WPS to work on a Pi Pico W. I think I've gotten really close, but i'm getting the error "'CYW43' object has no attribute 'scan_wps'"

(The lines of code are:
# If the button is pressed, scan for WiFi networks that support WPS
if not button.value():
sta_if.scan_wps()

        # Connect to the first WiFi network that supports WPS
        sta_if.connect_wps()

)

Then it goes on to connect to the API's and such to get the stock price and from there everything is good.

Literally everything works, if I manually go into the "your_wifi_details.txt" and put in a correct SSID and password, we're golden, but I can't have users required to download thonny and connect to the device and edit files and yada yada... so I am really hoping this WPS thing can work.

This is the first 'proper' program i've written since starting to learn python so apologies if this is a stupid approach, it's taken a lot or time and confusion to get this far but it's so nearly working, I just need a little help over the finish line so if anyone has faced this problem or can help me toward a solution I'd be super grateful

Here's excerpts from the relevant bits of code that are connected to the problem. There's a lot of "print" debugging commands so I can see in the terminal in Thonny where the program is at and what it's doing, obviously in the final use case there won't be a screen or keyboard so all that stuff will be taken out once development is complete:

import urequests
import network
import time
import machine

#--------------(Stackoverflow comment)  then further down

#stackoverflow comment:  I don't know why this next line is in bold, it shouldn't be
# Set up the button (connected to pin 15)
button = machine.Pin(15, machine.Pin.IN, machine.Pin.PULL_UP)
print ('pin 15 set as button')

#--------------(Stackoverflow comment)  then further down still

while True:
    print ('enter while true loop')
    # Connect to the WiFi network
    sta_if = network.WLAN(network.STA_IF)
    #print ('firstline passed, sleeping for 10 seconds')

#ignore this, unnecessary now
    #for i in range (0, 20):
     #   time.sleep(0.55)
      #  print ('sleeping...')

    #print ('nap over, trying to continue..')
    sta_if.active(True)
    print ('firing up connection')

    # Read the WiFi SSID and password from the text file
    with open("your_wifi_details.txt", "r") as f:
        ssid = f.readline().strip()
        password = f.readline().strip()
        print ('read your_wifi_details.txt successfully')

    # Try to connect to the WiFi network
    sta_if.connect(ssid, password)
    print ('attempting to connect to wifi')

    # Wait until the device is connected to the WiFi network
    while not sta_if.isconnected():
        # Flash the LEDs to indicate that the device is unable to connect
        print ('connection failed, attempting to flash LEDs')
        green_led.on()
        red_led.on()
        time.sleep(0.5)
        green_led.off()
        red_led.off()
        time.sleep(0.5)

        # Set up the button (connected to pin 0)
        print ('setting up button for WPS')
        button = machine.Pin(15, machine.Pin.IN, machine.Pin.PULL_UP)

        # If the button is pressed, scan for WiFi networks that support WPS
        if not button.value():
            sta_if.scan_wps()

            # Connect to the first WiFi network that supports WPS
            sta_if.connect_wps()

            # Save the WiFi SSID and password to the "your_wifi_details.txt" file
            with open("your_wifi_details.txt", "w") as f:
            f.write(sta_if.config("essid") + "\n")
            f.write(sta_if.config("password") + "\n")
            print ('wifi details written to file')

# Print the WiFi connection status in the terminal so I can see if it worked
print("Connected to WiFi:", sta_if.isconnected())


来源: stackexchange

问:
update a table after inserting a value in the same table using triggers
I'm trying to update the table with some values incremented by 10 in one column when I insert into each values in the same table.

the table looks like this
original table

I want to update the cost column with the value of id multiplied by 10

Final table should look like this
the table i want

I'm adding a trigger to do this but this isn't working

DELIMITER //   Create Trigger cost after INSERT ON myTable FOR EACH ROW   BEGIN  update myTable set cost=id*10; END //

I'm getting this error
insert into myTable(name,cost) values('s',0)  Error Code: 1442. Can't update table 'myTable' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.   0.000 sec

I'm using MySql

ContentLicense: CC BY-SA 4.0


问:
How to fix Plesk running on Google Cloud after running out of storage
I was running into trouble when my plesk server was running out of storage. If so I am not able to login again and services are not starting anymore.

However I tried to free up some storage via the repair page. With not success. Even after updaten the storage at gcloud from 50GB zoo 60GB

Also when executing the resize2fs /dev/sda1 plesk still shows 50GB space.
When executing plesk repair all it is resulting into nothing.

I would be happy to erase some files via ssh but failing to find any plesk file folder at /dev/sda1.

Hopping someone else was running in the same situation and found a solution to make the server run again.


问:
Automatically resizing Font in [Py]Qt[5|6]
I know how to programmatically change QFont, either directly or via Style.

Problem is: is there some way to say "use the largest Font fitting into given space" (and change it when window is manually resized)?

Or should I override resizeEvent() for affected QWidget(s), recompute font, apply, etc, etc?


问:
How to parse build.gradle just like Gradle 7 that supports variable references at end of interpolated strings not enclosed in curly brackets
NOTE: I have replicated this issue on Windows 10 and MacOS 12.6.2. I get the same results with Groovy 4.0.6 and Groovy 4.0.7 (and after updates: 3.0.9).

In order to automate some changes to build.gradle files that are written in Groovy, I'm using the official Apache Groovy parser 4.0.7 (which uses ANTLR 4.11.1) to parse the Groovy build.gradle files. I'm finding that the Groovy parser fails to parse build.gradle files that include variable references at the end of interpolated strings that are not enclosed in curly brackets. However, Gradle 7.5.1 successfully parses the same build.gradle file just fine with the unbracketed variable references at the end of interpolated strings.

To avoid the parser failures I am having to preprocess the build.gradle files to enclose the variable names in curly brackets when located at the end of an interpolated string. However, that adds complications and risks of RegExp pattern errors considering all the various scenarios I have to deal with. To some degree, that involves creating my own mini Groovy parser via RegExp.

Maybe Gradle is preprocessing the build.gradle file? Maybe Gradle 7.5.1 uses a different parser than the official Apache Groovy parser 4.0.7?

I would like to match what Gradle is doing to parse the build.gradle files as closely as possible to avoid these kinds of issues.

The following OneCompiler clip (https://onecompiler.com/groovy/3yuaw5jdv) shows both bracketed and unbracketed vars at the end of interpolated strings working for the following source in Groovy 2.7 (note: my program uses Groovy 4.0.7):

```<code>String name = "Joe"
println "Hello, ${name}"
println "Hello, $name "
println "Hello, $name/"
println "Hello, $name" // this fails in Groovy Parser 4.0.7
</code>```

Output:

```<code>#1 Hello, Joe
#2 Hello, Joe
#3 Hello, Joe/
#4 Hello, Joe
</code>```

I can paste the above code into a build.gradle file and run ./gradlew.bat build -x test without errors to get the expected output:

```<code>// build.gradle
plugins {
    id 'java'
}

group 'org.example'
version '1.0-SNAPSHOT'

String name = "Joe"
println "#1 Hello, ${name}"
println "#2 Hello, $name "
println "#3 Hello, $name/"
println "#4 Hello, $name" // this fails in Groovy Parser 4.0.7

repositories {
    mavenCentral()
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
    implementation 'org.apache.groovy:groovy:4.0.7'

}

test {
    useJUnitPlatform()
}
</code>```

Output:

```<code>PS C:\projects\groovy\groovy407> ./gradlew.bat build

> Configure project :
#1 Hello, Joe
#2 Hello, Joe
#3 Hello, Joe/
#4 Hello, Joe

BUILD SUCCESSFUL in 7s
4 actionable tasks: 4 executed
</code>```

However, when I try to parse the above build.gradle file via the Groovy Parser 4.0.7, it can't parse the file and reports parser errors when a variable reference is at the end of an interpolated string and not enclosed in curly brackets.

The following Java class and Java test class demonstrate how the Groovy parser 4.0.7 handles the variable references at the end of interpolated strings not enclosed in curly brackets.

InterpolatedStringParseTester.java:

```<code>package org.example;

import groovyjarjarantlr4.v4.runtime.CharStreams;
import groovyjarjarantlr4.v4.runtime.CommonTokenStream;
import groovyjarjarantlr4.v4.runtime.InputMismatchException;
import org.apache.groovy.parser.antlr4.GroovyLexer;
import org.apache.groovy.parser.antlr4.GroovyParser;

import java.rmi.UnexpectedException;

public class InterpolatedStringParseTester {
    public String upgrade(String contents) throws UnexpectedException{
        try {
            GroovyLexer groovyLexer = new GroovyLexer(CharStreams.fromString(contents));
            CommonTokenStream tokens = new CommonTokenStream(groovyLexer);
            GroovyParser groovyParser = new GroovyParser(tokens);
            GroovyParser.CompilationUnitContext tree = groovyParser.compilationUnit();
            if (tree.exception instanceof InputMismatchException) {
                throw new UnexpectedException("failed to parse contents: ", tree.exception);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new UnexpectedException(e.getLocalizedMessage());
        }
        return "";
    }
}
</code>```

InterpolatedStringParseTesterTest.java:

```<code>package org.example;

import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.rmi.UnexpectedException;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

class InterpolatedStringParseTesterTest {

    String bracketedVarInStrInClass_OK = "class AClass { String x=\"y\" \n" +
            "String a=\"${x}\" }";
    String unbracketedVarInStrInClass_ParserErr = "class AClass { String x=\"y\" \n" +
            "String a=\"$x\" }";
    String closureWithVarInStr_OK = "{ String x-> println \"${x}\" }";

    String closureWithUnbracketedVarInStrFailsParse_ThrowsException = "{ String x-> println \"$x\" }";

    String helloJoe4Ways = "String name = \"Joe\"\n" +
            "println \"#1 Hello, ${name}\"\n" +
            "println \"#2 Hello, $name \"\n" +
            "println \"#3 Hello, $name/\"\n" +
            "println \"#4 Hello, $name\" // this fails in Groovy Parser 4.0.7\n";

    @Test
    void bracketedVarInStrInClassTest_OK() throws UnexpectedException {
        InterpolatedStringParseTester interpolatedStringParseTester = new InterpolatedStringParseTester();
        assertEquals("", interpolatedStringParseTester.upgrade(bracketedVarInStrInClass_OK));
    }

    @Test
    void unbracketedVarInStrInClassTest_NoException_ButParserErr() throws UnexpectedException {
        InterpolatedStringParseTester interpolatedStringParseTester = new InterpolatedStringParseTester();
        assertEquals("", interpolatedStringParseTester.upgrade(unbracketedVarInStrInClass_ParserErr));
        // does not throw an error, but outputs error: line 2:13 mismatched input ' }' expecting {GStringEnd, GStringPart}
    }

    @Test
    void closureWithVarInStrTest_OK() throws UnexpectedException {
        InterpolatedStringParseTester interpolatedStringParseTester = new InterpolatedStringParseTester();
        assertEquals("", interpolatedStringParseTester.upgrade(closureWithVarInStr_OK));
    }
    @Test
    void closureWithUnbracketedVarInStrTest_ThrowsException() throws UnexpectedException {
        InterpolatedStringParseTester interpolatedStringParseTester = new InterpolatedStringParseTester();
        assertThrows(UnexpectedException.class,
                () -> {
                    interpolatedStringParseTester.upgrade(closureWithUnbracketedVarInStrFailsParse_ThrowsException);
        /*
        Throws:
        line 1:21 missing RBRACE at '"$'
        java.rmi.UnexpectedException: failed to parse contents: ; nested exception is:
            groovyjarjarantlr4.v4.runtime.InputMismatchException
        */
        });
    }

    @Test
    void helloJoe4WaysTest_ThrowsInputMismatchException() throws UnexpectedException {
        InterpolatedStringParseTester interpolatedStringParseTester = new InterpolatedStringParseTester();
        assertThrows(UnexpectedException.class,
                () -> {
                    interpolatedStringParseTester.upgrade(helloJoe4Ways);
                });
        /**
         * this results in:
         * line 5:25 token recognition error at: ' // this fails in Groovy Parser 4.0.7\n'
         * line 5:8 mismatched input '"#4 Hello, $' expecting {<EOF>, ';', NL}
         * java.rmi.UnexpectedException: failed to parse contents: ; nested exception is:
         */
    }

    @Test
    void buildGradleParse_ThrowsInputMismatchException() throws IOException {
        InterpolatedStringParseTester interpolatedStringParseTester = new InterpolatedStringParseTester();
        Path path = Paths.get("build.gradle");
        Stream<String> lines = Files.lines(path);
        String buildGradleContents = lines.collect(Collectors.joining("\n"));
        lines.close();
        assertThrows(UnexpectedException.class,
                () -> {
                    interpolatedStringParseTester.upgrade(buildGradleContents);
                });

    }

}
</code>```

UPDATE:
Below is the stderr output along with the stacktrace of the exception that is returned (i.e., returned in the tree.exception field as opposed to being thrown) by GroovyParser.CompilationUnitContext tree = groovyParser.compilationUnit(); in the unit test named helloJoe4WaysTest_ThrowsInputMismatchException:

```<code>line 5:25 token recognition error at: ' // this fails in Groovy Parser 4.0.7\n'
line 5:8 mismatched input '"#4 Hello, $' expecting {<EOF>, ';', NL}
groovyjarjarantlr4.v4.runtime.InputMismatchException
    at groovyjarjarantlr4.v4.runtime.DefaultErrorStrategy.recoverInline(DefaultErrorStrategy.java:492)
    at groovyjarjarantlr4.v4.runtime.Parser.match(Parser.java:213)
    at org.apache.groovy.parser.antlr4.GroovyParser.compilationUnit(GroovyParser.java:368)
    at org.example.InterpolatedStringParseTester.upgrade(InterpolatedStringParseTester.java:18)
    at org.example.InterpolatedStringParseTesterTest.lambda$helloJoe4WaysTest_ThrowsInputMismatchException$1(InterpolatedStringParseTesterTest.java:71)
    at org.junit.jupiter.api.AssertThrows.assertThrows(AssertThrows.java:55)
    at org.junit.jupiter.api.AssertThrows.assertThrows(AssertThrows.java:37)
    at org.junit.jupiter.api.Assertions.assertThrows(Assertions.java:3082)
    at org.example.InterpolatedStringParseTesterTest.helloJoe4WaysTest_ThrowsInputMismatchException(InterpolatedStringParseTesterTest.java:69)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
    at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
    at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
    at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
    at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
    at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:99)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:79)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75)
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
    at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
    at com.sun.proxy.$Proxy2.stop(Unknown Source)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
    at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
    at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133)
    at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
    at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
    at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
</code>```

UPDATE:
On Windows 10, Gradle is using:

Gradle version: 7.4

Groovy version: 3.0.9

On MacOS 12.6.1 Gradle is using:

Gradle version: 7.4

Groovy version: 3.0.9

When I have more time I will try to re-run these tests with the parser that comes with Groovy 3.0.9 and 3.0.10 to match what Gradle is using.

UPDATE:

Since learning that Gradle 7.4 uses Groovy 3.0.9, I have re-run the same tests with Groovy 3.0.9 that result in the same exception when the variable reference is not wrapped in curl brackets and is at the end of a double-quoted interpolated string.

The following is the dependency in build.gradle to make use of the Groovy parse v3.0.9:

```<code>implementation 'org.codehaus.groovy:groovy-all:3.0.9'
</code>```

I created a simple Java project to test Groovy 3.0.9.

Below is the code and output that demonstrates the difference between "with curl brackets" and "without curly brackets" around variable references that appear at the end of interpolated strings:

Main.java:

```<code>package org.example;

import groovyjarjarantlr4.v4.runtime.CharStreams;
import groovyjarjarantlr4.v4.runtime.CommonTokenStream;
import org.apache.groovy.parser.antlr4.GroovyLexer;
import org.apache.groovy.parser.antlr4.GroovyParser;

public class Main {
    public static void main(String[] args) {
        Main main = new Main();
        boolean useBrackets = args.length> 0 && "y".equalsIgnoreCase(args[0]);
        String brackets = "buildscript { def v=\"1.2.3\"; dependencies { classpath { \"grp:pkg:${v}\" } } }";
        String noBrackets = "buildscript { def v=\"1.2.3\"; dependencies { classpath { \"grp:pkg:$v\" } } }";
        String groovyCode = useBrackets ? brackets : noBrackets;
        System.out.println("Groovy code:" + groovyCode);
        main.runVisitor(groovyCode);
    }

    void runVisitor(String buildGradleContents) {
        GroovyLexer groovyLexer = new GroovyLexer(CharStreams.fromString(buildGradleContents));
        CommonTokenStream tokens = new CommonTokenStream(groovyLexer);
        GroovyParser groovyParser = new GroovyParser(tokens);
        GroovyParser.CompilationUnitContext tree = groovyParser.compilationUnit();
        if (tree.exception != null) {
            tree.exception.printStackTrace();
            throw tree.exception;
        }
        TestVisitor testVisitor = new TestVisitor();
        String results = testVisitor.visit(tree);
        System.out.println("results: "+ results);
    }

}
</code>```

TestVisitor.java:

```<code>package org.example;

import groovyjarjarantlr4.v4.runtime.Token;
import org.apache.groovy.parser.antlr4.GroovyParser;
import org.apache.groovy.parser.antlr4.GroovyParserBaseVisitor;

public class TestVisitor extends GroovyParserBaseVisitor<String>{
    public String visitIdentifier(GroovyParser.IdentifierContext ctx) {
        Token startToken = ctx.getStart();
        if (startToken != null) {
            String startTxt = startToken.getText();
        }
        return visitChildren(ctx);
    }
}
</code>```

OUTPUT:

```<code>#1 Hello, Joe
#2 Hello, Joe
#3 Hello, Joe/
#4 Hello, Joe
</code>```0

Body:
NOTE: I have replicated this issue on Windows 10 and MacOS 12.6.2. I get the same results with Groovy 4.0.6 and Groovy 4.0.7 (and after updates: 3.0.9).

In order to automate some changes to build.gradle files that are written in Groovy, I'm using the official Apache Groovy parser 4.0.7 (which uses ANTLR 4.11.1) to parse the Groovy build.gradle files. I'm finding that the Groovy parser fails to parse build.gradle files that include variable references at the end of interpolated strings that are not enclosed in curly brackets. However, Gradle 7.5.1 successfully parses the same build.gradle file just fine with the unbracketed variable references at the end of interpolated strings.

To avoid the parser failures I am having to preprocess the build.gradle files to enclose the variable names in curly brackets when located at the end of an interpolated string. However, that adds complications and risks of RegExp pattern errors considering all the various scenarios I have to deal with. To some degree, that involves creating my own mini Groovy parser via RegExp.

Maybe Gradle is preprocessing the build.gradle file? Maybe Gradle 7.5.1 uses a different parser than the official Apache Groovy parser 4.0.7?

I would like to match what Gradle is doing to parse the build.gradle files as closely as possible to avoid these kinds of issues.

The following OneCompiler clip (https://onecompiler.com/groovy/3yuaw5jdv) shows both bracketed and unbracketed vars at the end of interpolated strings working for the following source in Groovy 2.7 (note: my program uses Groovy 4.0.7):

String name = "Joe"
println "Hello, ${name}"
println "Hello, $name "
println "Hello, $name/"
println "Hello, $name" // this fails in Groovy Parser 4.0.7

Output:

#1 Hello, Joe
#2 Hello, Joe
#3 Hello, Joe/
#4 Hello, Joe

I can paste the above code into a build.gradle file and run ./gradlew.bat build -x test without errors to get the expected output:

// build.gradle
plugins {
    id 'java'
}

group 'org.example'
version '1.0-SNAPSHOT'

String name = "Joe"
println "#1 Hello, ${name}"
println "#2 Hello, $name "
println "#3 Hello, $name/"
println "#4 Hello, $name" // this fails in Groovy Parser 4.0.7

repositories {
    mavenCentral()
}

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
    implementation 'org.apache.groovy:groovy:4.0.7'

}

test {
    useJUnitPlatform()
}

Output:

PS C:\projects\groovy\groovy407> ./gradlew.bat build

> Configure project :
#1 Hello, Joe
#2 Hello, Joe
#3 Hello, Joe/
#4 Hello, Joe

BUILD SUCCESSFUL in 7s
4 actionable tasks: 4 executed

However, when I try to parse the above build.gradle file via the Groovy Parser 4.0.7, it can't parse the file and reports parser errors when a variable reference is at the end of an interpolated string and not enclosed in curly brackets.

The following Java class and Java test class demonstrate how the Groovy parser 4.0.7 handles the variable references at the end of interpolated strings not enclosed in curly brackets.

InterpolatedStringParseTester.java:

package org.example;

import groovyjarjarantlr4.v4.runtime.CharStreams;
import groovyjarjarantlr4.v4.runtime.CommonTokenStream;
import groovyjarjarantlr4.v4.runtime.InputMismatchException;
import org.apache.groovy.parser.antlr4.GroovyLexer;
import org.apache.groovy.parser.antlr4.GroovyParser;

import java.rmi.UnexpectedException;

public class InterpolatedStringParseTester {
    public String upgrade(String contents) throws UnexpectedException{
        try {
            GroovyLexer groovyLexer = new GroovyLexer(CharStreams.fromString(contents));
            CommonTokenStream tokens = new CommonTokenStream(groovyLexer);
            GroovyParser groovyParser = new GroovyParser(tokens);
            GroovyParser.CompilationUnitContext tree = groovyParser.compilationUnit();
            if (tree.exception instanceof InputMismatchException) {
                throw new UnexpectedException("failed to parse contents: ", tree.exception);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new UnexpectedException(e.getLocalizedMessage());
        }
        return "";
    }
}

InterpolatedStringParseTesterTest.java:

package org.example;

import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.rmi.UnexpectedException;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

class InterpolatedStringParseTesterTest {

    String bracketedVarInStrInClass_OK = "class AClass { String x=\"y\" \n" +
            "String a=\"${x}\" }";
    String unbracketedVarInStrInClass_ParserErr = "class AClass { String x=\"y\" \n" +
            "String a=\"$x\" }";
    String closureWithVarInStr_OK = "{ String x-> println \"${x}\" }";

    String closureWithUnbracketedVarInStrFailsParse_ThrowsException = "{ String x-> println \"$x\" }";

    String helloJoe4Ways = "String name = \"Joe\"\n" +
            "println \"#1 Hello, ${name}\"\n" +
            "println \"#2 Hello, $name \"\n" +
            "println \"#3 Hello, $name/\"\n" +
            "println \"#4 Hello, $name\" // this fails in Groovy Parser 4.0.7\n";

    @Test
    void bracketedVarInStrInClassTest_OK() throws UnexpectedException {
        InterpolatedStringParseTester interpolatedStringParseTester = new InterpolatedStringParseTester();
        assertEquals("", interpolatedStringParseTester.upgrade(bracketedVarInStrInClass_OK));
    }

    @Test
    void unbracketedVarInStrInClassTest_NoException_ButParserErr() throws UnexpectedException {
        InterpolatedStringParseTester interpolatedStringParseTester = new InterpolatedStringParseTester();
        assertEquals("", interpolatedStringParseTester.upgrade(unbracketedVarInStrInClass_ParserErr));
        // does not throw an error, but outputs error: line 2:13 mismatched input ' }' expecting {GStringEnd, GStringPart}
    }

    @Test
    void closureWithVarInStrTest_OK() throws UnexpectedException {
        InterpolatedStringParseTester interpolatedStringParseTester = new InterpolatedStringParseTester();
        assertEquals("", interpolatedStringParseTester.upgrade(closureWithVarInStr_OK));
    }
    @Test
    void closureWithUnbracketedVarInStrTest_ThrowsException() throws UnexpectedException {
        InterpolatedStringParseTester interpolatedStringParseTester = new InterpolatedStringParseTester();
        assertThrows(UnexpectedException.class,
                () -> {
                    interpolatedStringParseTester.upgrade(closureWithUnbracketedVarInStrFailsParse_ThrowsException);
        /*
        Throws:
        line 1:21 missing RBRACE at '"$'
        java.rmi.UnexpectedException: failed to parse contents: ; nested exception is:
            groovyjarjarantlr4.v4.runtime.InputMismatchException
        */
        });
    }

    @Test
    void helloJoe4WaysTest_ThrowsInputMismatchException() throws UnexpectedException {
        InterpolatedStringParseTester interpolatedStringParseTester = new InterpolatedStringParseTester();
        assertThrows(UnexpectedException.class,
                () -> {
                    interpolatedStringParseTester.upgrade(helloJoe4Ways);
                });
        /**
         * this results in:
         * line 5:25 token recognition error at: ' // this fails in Groovy Parser 4.0.7\n'
         * line 5:8 mismatched input '"#4 Hello, $' expecting {<EOF>, ';', NL}
         * java.rmi.UnexpectedException: failed to parse contents: ; nested exception is:
         */
    }

    @Test
    void buildGradleParse_ThrowsInputMismatchException() throws IOException {
        InterpolatedStringParseTester interpolatedStringParseTester = new InterpolatedStringParseTester();
        Path path = Paths.get("build.gradle");
        Stream<String> lines = Files.lines(path);
        String buildGradleContents = lines.collect(Collectors.joining("\n"));
        lines.close();
        assertThrows(UnexpectedException.class,
                () -> {
                    interpolatedStringParseTester.upgrade(buildGradleContents);
                });

    }

}

UPDATE:
Below is the stderr output along with the stacktrace of the exception that is returned (i.e., returned in the tree.exception field as opposed to being thrown) by GroovyParser.CompilationUnitContext tree = groovyParser.compilationUnit(); in the unit test named helloJoe4WaysTest_ThrowsInputMismatchException:

line 5:25 token recognition error at: ' // this fails in Groovy Parser 4.0.7\n'
line 5:8 mismatched input '"#4 Hello, $' expecting {<EOF>, ';', NL}
groovyjarjarantlr4.v4.runtime.InputMismatchException
    at groovyjarjarantlr4.v4.runtime.DefaultErrorStrategy.recoverInline(DefaultErrorStrategy.java:492)
    at groovyjarjarantlr4.v4.runtime.Parser.match(Parser.java:213)
    at org.apache.groovy.parser.antlr4.GroovyParser.compilationUnit(GroovyParser.java:368)
    at org.example.InterpolatedStringParseTester.upgrade(InterpolatedStringParseTester.java:18)
    at org.example.InterpolatedStringParseTesterTest.lambda$helloJoe4WaysTest_ThrowsInputMismatchException$1(InterpolatedStringParseTesterTest.java:71)
    at org.junit.jupiter.api.AssertThrows.assertThrows(AssertThrows.java:55)
    at org.junit.jupiter.api.AssertThrows.assertThrows(AssertThrows.java:37)
    at org.junit.jupiter.api.Assertions.assertThrows(Assertions.java:3082)
    at org.example.InterpolatedStringParseTesterTest.helloJoe4WaysTest_ThrowsInputMismatchException(InterpolatedStringParseTesterTest.java:69)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
    at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
    at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
    at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1540)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
    at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
    at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:99)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:79)
    at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75)
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
    at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
    at com.sun.proxy.$Proxy2.stop(Unknown Source)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker$3.run(TestWorker.java:193)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
    at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
    at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133)
    at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
    at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
    at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)

UPDATE:
On Windows 10, Gradle is using:

Gradle version: 7.4

Groovy version: 3.0.9

On MacOS 12.6.1 Gradle is using:

Gradle version: 7.4

Groovy version: 3.0.9

When I have more time I will try to re-run these tests with the parser that comes with Groovy 3.0.9 and 3.0.10 to match what Gradle is using.

UPDATE:

Since learning that Gradle 7.4 uses Groovy 3.0.9, I have re-run the same tests with Groovy 3.0.9 that result in the same exception when the variable reference is not wrapped in curl brackets and is at the end of a double-quoted interpolated string.

The following is the dependency in build.gradle to make use of the Groovy parse v3.0.9:

implementation 'org.codehaus.groovy:groovy-all:3.0.9'

I created a simple Java project to test Groovy 3.0.9.

Below is the code and output that demonstrates the difference between "with curl brackets" and "without curly brackets" around variable references that appear at the end of interpolated strings:

Main.java:

package org.example;

import groovyjarjarantlr4.v4.runtime.CharStreams;
import groovyjarjarantlr4.v4.runtime.CommonTokenStream;
import org.apache.groovy.parser.antlr4.GroovyLexer;
import org.apache.groovy.parser.antlr4.GroovyParser;

public class Main {
    public static void main(String[] args) {
        Main main = new Main();
        boolean useBrackets = args.length> 0 && "y".equalsIgnoreCase(args[0]);
        String brackets = "buildscript { def v=\"1.2.3\"; dependencies { classpath { \"grp:pkg:${v}\" } } }";
        String noBrackets = "buildscript { def v=\"1.2.3\"; dependencies { classpath { \"grp:pkg:$v\" } } }";
        String groovyCode = useBrackets ? brackets : noBrackets;
        System.out.println("Groovy code:" + groovyCode);
        main.runVisitor(groovyCode);
    }

    void runVisitor(String buildGradleContents) {
        GroovyLexer groovyLexer = new GroovyLexer(CharStreams.fromString(buildGradleContents));
        CommonTokenStream tokens = new CommonTokenStream(groovyLexer);
        GroovyParser groovyParser = new GroovyParser(tokens);
        GroovyParser.CompilationUnitContext tree = groovyParser.compilationUnit();
        if (tree.exception != null) {
            tree.exception.printStackTrace();
            throw tree.exception;
        }
        TestVisitor testVisitor = new TestVisitor();
        String results = testVisitor.visit(tree);
        System.out.println("results: "+ results);
    }

}

TestVisitor.java:

package org.example;

import groovyjarjarantlr4.v4.runtime.Token;
import org.apache.groovy.parser.antlr4.GroovyParser;
import org.apache.groovy.parser.antlr4.GroovyParserBaseVisitor;

public class TestVisitor extends GroovyParserBaseVisitor<String>{
    public String visitIdentifier(GroovyParser.IdentifierContext ctx) {
        Token startToken = ctx.getStart();
        if (startToken != null) {
            String startTxt = startToken.getText();
        }
        return visitChildren(ctx);
    }
}

OUTPUT:

# WITH curly brackets
PS C:\projects\research\gradle-tooling> java -jar .\build\libs\gradle-tooling-1.0-SNAPSHOT.jar y
Groovy code:buildscript { def v="1.2.3"; dependencies { classpath { "grp:pkg:${v}" } } }
results: null
# WITHOUT curly brackets
PS C:\projects\research\gradle-tooling> java -jar .\build\libs\gradle-tooling-1.0-SNAPSHOT.jar n
Groovy code:buildscript { def v="1.2.3"; dependencies { classpath { "grp:pkg:$v" } } }
line 1:12 mismatched input '{' expecting {<EOF>, StringLiteral, GStringBegin, 'as', 'in', 'trait', 'var', IntegerLiteral, FloatingPointLiteral, BooleanLiteral, 'null', ';', Capitalized
Identifier, Identifier, NL}
groovyjarjarantlr4.v4.runtime.InputMismatchException
        at groovyjarjarantlr4.v4.runtime.DefaultErrorStrategy.recoverInline(DefaultErrorStrategy.java:492)
        at groovyjarjarantlr4.v4.runtime.Parser.match(Parser.java:213)
        at org.apache.groovy.parser.antlr4.GroovyParser.compilationUnit(GroovyParser.java:362)
        at org.example.Main.runVisitor(Main.java:28)
        at org.example.Main.main(Main.java:21)
Exception in thread "main" groovyjarjarantlr4.v4.runtime.InputMismatchException
        at groovyjarjarantlr4.v4.runtime.DefaultErrorStrategy.recoverInline(DefaultErrorStrategy.java:492)
        at groovyjarjarantlr4.v4.runtime.Parser.match(Parser.java:213)
        at org.apache.groovy.parser.antlr4.GroovyParser.compilationUnit(GroovyParser.java:362)
        at org.example.Main.runVisitor(Main.java:28)
        at org.example.Main.main(Main.java:21)


问:
Getting a file path error when attempting to delete old directory information, and create new directory information in Laravel
Creating a forum site.

I want to alow users to edit their forum posts. Including in the forum in a image that acts as the front cover to their post.

Users can edit all information within the post, but the second they attempt to change the image of their featured image (front cover), I get an error message. Everything else is functional (luckily).

Error Message: Can't write image data to path (C:\xampp\htdocs\my-forum-site\storage\app/public/images/post_images/thumbnail/thumb_1673199816_testing.png)

```<code>public function updatePost(Request $request){
        if( $request->hasFile('featured_image') ){
            $request->validate([
                'post_title'=>'required|unique:posts,post_title,'.$request->post_id,
                'post_content'=>'required',
                'post_category'=>'required|exists:sub_categories,id',
                'featured_image'=>'mimes:jpeg,jpg,png|max:1024',
            ]);

            $path = "images/post_images/";
            $file = $request->file('featured_image');
            $filename = $file->getClientOriginalName();
            $new_filename = time().'_'.$filename;

            $upload = Storage::disk('public')->put($path.$new_filename, (string) file_get_contents($file));

            $post_thumbnails_path = $path.'thumbnails';
            if( !Storage::disk('public')->exists($post_thumbnails_path) ){
                Storage::disk('public')->makeDirectory($post_thumbnails_path, 0755, true, true);
            }

            Image::make( storage_path('app/public/'.$path.$new_filename) )
                ->fit(200,200)
                ->save(storage_path('app/public/'.$path.'thumbnail/'.'thumb_'.$new_filename) );

            Image::make( storage_path('app/public/'.$path.$new_filename) )
                ->fit(500,350)
                ->save( storage_path('app/public/'.$path.'thumbnails/'.'resized_'.$new_filename) );

        //deletes old post featured image from directory.
        if( $upload ){
            $old_post_image = Post::find($request->post_id)->featured_image;

            if( $old_post_image != null && Storage::disk('public')->exists($path.$old_post_image) ){
                Storage::disk('public')->delete($path.$old_post_image);

                if( Storage::disk('public')->exists($path.'thumbnails/resized_'.$old_post_image) ){
                    Storage::disk('public')->delete($path.'thumbnails/resized_'.$old_post_image);
                }

                if( Storage::disk('public')->exists($path.'thumbnails/thumb_'.$old_post_image) ){
                    Storage::disk('public')->delete($path.'thumbnails/thumb_'.$old_post_image);
                }
            }

            //replacing the old data with new data in our database.
            $post = Post::find($request->post_id);
            $post->category_id = $request->post_category;
            $post->post_title = $request->post_title;
            $post->post_slug = null;
            $post->post_content = $request->post_content;
            $post->featured_image = $new_filename;
            $saved = $post->save();

            if( $saved ){
                return response()->json(['code'=>1,'msg'=>'Post Has Successfully Updated!']);
            }else{
                return response()->json(['code'=>3,'msg'=>'Something went wrong for updating post.']);
            }

        }else{
            return response()->json(['code'=>3,'msg'=>'Error in uploading new featured image.']);
        }

        }else{
            $request->validate([
                'post_title'=>'required|unique:posts,post_title,'.$request->post_id,
                'post_content'=>'required',
                'post_category'=>'required|exists:sub_categories,id'
            ]);

            $post = Post::find($request->post_id);
            $post->category_id = $request->post_category;
            $post->post_slug = null;
            $post->post_content = $request->post_content;
            $post->post_title = $request->post_title;
            $saved = $post->save();

            if($saved){
                return response()->json(['code'=>1, 'msg'=>'Post has been successfully updated!']);
            }else{
                return response()->json(['code'=>3, 'msg'=>'Something Went Wrong While Updating Post!']);
            }
        }
    }
</code>```

Body:
Creating a forum site.

I want to alow users to edit their forum posts. Including in the forum in a image that acts as the front cover to their post.

Users can edit all information within the post, but the second they attempt to change the image of their featured image (front cover), I get an error message. Everything else is functional (luckily).

Error Message: Can't write image data to path (C:\xampp\htdocs\my-forum-site\storage\app/public/images/post_images/thumbnail/thumb_1673199816_testing.png)

public function updatePost(Request $request){
        if( $request->hasFile('featured_image') ){
            $request->validate([
                'post_title'=>'required|unique:posts,post_title,'.$request->post_id,
                'post_content'=>'required',
                'post_category'=>'required|exists:sub_categories,id',
                'featured_image'=>'mimes:jpeg,jpg,png|max:1024',
            ]);

            $path = "images/post_images/";
            $file = $request->file('featured_image');
            $filename = $file->getClientOriginalName();
            $new_filename = time().'_'.$filename;

            $upload = Storage::disk('public')->put($path.$new_filename, (string) file_get_contents($file));

            $post_thumbnails_path = $path.'thumbnails';
            if( !Storage::disk('public')->exists($post_thumbnails_path) ){
                Storage::disk('public')->makeDirectory($post_thumbnails_path, 0755, true, true);
            }

            Image::make( storage_path('app/public/'.$path.$new_filename) )
                ->fit(200,200)
                ->save(storage_path('app/public/'.$path.'thumbnail/'.'thumb_'.$new_filename) );

            Image::make( storage_path('app/public/'.$path.$new_filename) )
                ->fit(500,350)
                ->save( storage_path('app/public/'.$path.'thumbnails/'.'resized_'.$new_filename) );

        //deletes old post featured image from directory.
        if( $upload ){
            $old_post_image = Post::find($request->post_id)->featured_image;

            if( $old_post_image != null && Storage::disk('public')->exists($path.$old_post_image) ){
                Storage::disk('public')->delete($path.$old_post_image);

                if( Storage::disk('public')->exists($path.'thumbnails/resized_'.$old_post_image) ){
                    Storage::disk('public')->delete($path.'thumbnails/resized_'.$old_post_image);
                }

                if( Storage::disk('public')->exists($path.'thumbnails/thumb_'.$old_post_image) ){
                    Storage::disk('public')->delete($path.'thumbnails/thumb_'.$old_post_image);
                }
            }

            //replacing the old data with new data in our database.
            $post = Post::find($request->post_id);
            $post->category_id = $request->post_category;
            $post->post_title = $request->post_title;
            $post->post_slug = null;
            $post->post_content = $request->post_content;
            $post->featured_image = $new_filename;
            $saved = $post->save();

            if( $saved ){
                return response()->json(['code'=>1,'msg'=>'Post Has Successfully Updated!']);
            }else{
                return response()->json(['code'=>3,'msg'=>'Something went wrong for updating post.']);
            }

        }else{
            return response()->json(['code'=>3,'msg'=>'Error in uploading new featured image.']);
        }

        }else{
            $request->validate([
                'post_title'=>'required|unique:posts,post_title,'.$request->post_id,
                'post_content'=>'required',
                'post_category'=>'required|exists:sub_categories,id'
            ]);

            $post = Post::find($request->post_id);
            $post->category_id = $request->post_category;
            $post->post_slug = null;
            $post->post_content = $request->post_content;
            $post->post_title = $request->post_title;
            $saved = $post->save();

            if($saved){
                return response()->json(['code'=>1, 'msg'=>'Post has been successfully updated!']);
            }else{
                return response()->json(['code'=>3, 'msg'=>'Something Went Wrong While Updating Post!']);
            }
        }
    }


问:
Get array with file urls after multiple file upload to Firebase Storage
How can I get an array of URLs returned by getDownloadURL() after uploading multiple files to Firebase Storage with Angularfire?

I am trying the following, I try to use Promise.all(uploads) but without success:

```<code>uploadFiles(event: any) {

    const fileList = event.target.files;
    const uploads: any[] = [];

    this.fotosPolaroid.forEach( (item: File) => {

      const file = item;
      const filePath = `nombreModelo/${file.name}`;
      const fileRef = this.storage.ref(filePath);
      const task = this.storage.upload(filePath, file);

      this.uploadPercent = task.percentageChanges();

      task.snapshotChanges().pipe(
        finalize( () => {
          return fileRef.getDownloadURL().subscribe( urlImage => {
            console.log(urlImage);
            uploads.push(urlImage)
          })
        })
      )
      .subscribe();
    });

    return Promise.all(uploads)
    .then( response => {
      console.log(response);
    })
    .catch( error => {
      console.log(error);
    });

  }
</code>```

The images are uploaded to Firebase Storage, but I am not able to generate an array with these URLs, this is what I get in the console:

Body:
How can I get an array of URLs returned by getDownloadURL() after uploading multiple files to Firebase Storage with Angularfire?

I am trying the following, I try to use Promise.all(uploads) but without success:

uploadFiles(event: any) {

    const fileList = event.target.files;
    const uploads: any[] = [];

    this.fotosPolaroid.forEach( (item: File) => {

      const file = item;
      const filePath = `nombreModelo/${file.name}`;
      const fileRef = this.storage.ref(filePath);
      const task = this.storage.upload(filePath, file);

      this.uploadPercent = task.percentageChanges();

      task.snapshotChanges().pipe(
        finalize( () => {
          return fileRef.getDownloadURL().subscribe( urlImage => {
            console.log(urlImage);
            uploads.push(urlImage)
          })
        })
      )
      .subscribe();
    });

    return Promise.all(uploads)
    .then( response => {
      console.log(response);
    })
    .catch( error => {
      console.log(error);
    });

  }

The images are uploaded to Firebase Storage, but I am not able to generate an array with these URLs, this is what I get in the console:


问:
AdonisJs: create migration for existent database schema
I have an existent Postgresql database schema which I wrote in SQL. It initializes extensions, enum types, and defines many tables with foreign keys, constraints, indexes, etc.
Now I wish to build an AdonisJs app around that database. I would like new developers to be able to set up an empty database with the same schema, without having to run the SQL command in psql themselves.

I do not want to write all the schema using the Adonis schema builder DSL because there are many tables and it would take a lot of time to translate.

In ruby on Rails, the schema would be kept updated in the db/schema.rb file and new developers would spin up their dev environment using rails db:schema:load. What is the equivalent in AdonisJS?

The current way I'm doing it is by creating a migration that basically runs the raw SQL query. But I'm convinced there should be a cleaner way. Or even a way to get this SQL file away from my migration.

import Database from '@ioc:Adonis/Lucid/Database'
import BaseSchema from '@ioc:Adonis/Lucid/Schema'

export default class extends BaseSchema {
  public async up () {
    const schemaSql = this.initialSchema()
    console.log(schemaSql)

    await Database.rawQuery(schemaSql)
  }

  public async down () {
  }

  public initialSchema() {
    const fs = require('fs');
    const path = require('path');
    var data = fs.readFileSync(path.resolve(__dirname, './../initial_schema.sql'));
    return data.toString();
  }
}
```
<p>and then inside  <code>database/initial_schema.sql</code> I have:</p>
<pre class="lang-sql prettyprint-override"><code>CREATE EXTENSION IF NOT EXISTS citext;
CREATE EXTENSION IF NOT EXISTS pgcrypto;
CREATE EXTENSION IF NOT EXISTS btree_gist;

DROP TYPE IF EXISTS nivel_formacion;

CREATE TYPE nivel_formacion AS ENUM ('secundaria', 'grado', 'maestria', 'doctorado');

CREATE TABLE "foobar" (
  "id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  "name" varchar NOT NULL,
  "created_at" timestamp NOT NULL,
  "updated_at" timestamp NOT NULL
);

-- ...etc etc etc..
</code>```

Body:
I have an existent Postgresql database schema which I wrote in SQL. It initializes extensions, enum types, and defines many tables with foreign keys, constraints, indexes, etc.
Now I wish to build an AdonisJs app around that database. I would like new developers to be able to set up an empty database with the same schema, without having to run the SQL command in psql themselves.

I do not want to write all the schema using the Adonis schema builder DSL because there are many tables and it would take a lot of time to translate.

In ruby on Rails, the schema would be kept updated in the db/schema.rb file and new developers would spin up their dev environment using rails db:schema:load. What is the equivalent in AdonisJS?

The current way I'm doing it is by creating a migration that basically runs the raw SQL query. But I'm convinced there should be a cleaner way. Or even a way to get this SQL file away from my migration.

import Database from '@ioc:Adonis/Lucid/Database'
import BaseSchema from '@ioc:Adonis/Lucid/Schema'

export default class extends BaseSchema {
  public async up () {
    const schemaSql = this.initialSchema()
    console.log(schemaSql)

    await Database.rawQuery(schemaSql)
  }

  public async down () {
  }

  public initialSchema() {
    const fs = require('fs');
    const path = require('path');
    var data = fs.readFileSync(path.resolve(__dirname, './../initial_schema.sql'));
    return data.toString();
  }
}

and then inside  database/initial_schema.sql I have:

CREATE EXTENSION IF NOT EXISTS citext;
CREATE EXTENSION IF NOT EXISTS pgcrypto;
CREATE EXTENSION IF NOT EXISTS btree_gist;

DROP TYPE IF EXISTS nivel_formacion;

CREATE TYPE nivel_formacion AS ENUM ('secundaria', 'grado', 'maestria', 'doctorado');

CREATE TABLE "foobar" (
  "id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
  "name" varchar NOT NULL,
  "created_at" timestamp NOT NULL,
  "updated_at" timestamp NOT NULL
);

-- ...etc etc etc..


问:
How to show previous div after user get error message and prompted to insert field again
I have a specific situation and I'll give my best to explain it.

On page I have a select field, inside it I have two choice for user, that looks like this:

```<code><select id="payment_type" name="payment_type">
    <option>Select a payment type...</option>
    <option value="Income">Income</option>
    <option value="Expense">Expense</option>
</select>
</code>```

Now I have a JS code that show form for income or expense, depends which one user has selected:

```<code>$('#payment_type').on('change', function() {
var val = $(this).val();
$('#Income').hide();
$('#Expense').hide();
$('#' + val).show();
});
</code>```

So if user has selected Income from dropdown list I will show him this form:

```<code> <form action="#" id="Income" class="hidden" th:action="@{/api/transaction/saveIncome/{walletId} (walletId=${id})}"
      th:object="${transaction}" method="POST">

    <label for="amountIncome" class="col-form-label">Amount</label> <input
        type="text" th:field="*{amount}" class="form-control"
        id="amountIncome" placeholder="amount"> <span
        th:if="${#fields.hasErrors('amount')}" th:errors="*{amount}"
        class="text-danger"></span>
    <input type="text" th:field="*{note}" placeholder="Enter note" class="form-control mb-4 col-4">
    <input type="date" th:field="*{date}" class="form-control mb-4 col-4">

    <select th:field="${transaction.incomeCategories}">
        <option value="0">Select income category</option>
        <option
                th:each="incomeCategories : ${incomeCategories}"
                th:value="${incomeCategories}"
                th:text="${incomeCategories.displayName}"
        ></option>
    </select>
    <button type="submit" class="btn btn-info col-2"> Save Wallet</button>
</form>
</code>```

Now, If the user entered wrong value for amount I will provide him error, and that works fine. But what is the problem, I will provide you a use case:

Here user pick the transaction type:

Now, user has selected Income for example, and I provide him form for Income:

Now, If user for field amount insert -1 I will provide him an error, but I'm redirected to this page again:

And when I select again Income only then I can see the error:

While I want to display him immediately form that he picked from list. So if he choose Income but made error on form, display him again Income form without having to choose again from dropdown menu.

The only solution so far that I have on my mind is to create a totally separated HTML pages with form, but I think that there is for sure a way to solve this on another way without that.

I give my best to explain problem and added picture for better understanding, for anything else I'm here to explain or to provide more information. Thank you and also sorry for my bad English.

Body:
I have a specific situation and I'll give my best to explain it.

On page I have a select field, inside it I have two choice for user, that looks like this:

<select id="payment_type" name="payment_type">
    <option>Select a payment type...</option>
    <option value="Income">Income</option>
    <option value="Expense">Expense</option>
</select>

Now I have a JS code that show form for income or expense, depends which one user has selected:

$('#payment_type').on('change', function() {
var val = $(this).val();
$('#Income').hide();
$('#Expense').hide();
$('#' + val).show();
});

So if user has selected Income from dropdown list I will show him this form:

 <form action="#" id="Income" class="hidden" th:action="@{/api/transaction/saveIncome/{walletId} (walletId=${id})}"
      th:object="${transaction}" method="POST">

    Amount <input
        type="text" th:field="*{amount}" class="form-control"
        id="amountIncome" placeholder="amount">
    <input type="text" th:field="*{note}" placeholder="Enter note" class="form-control mb-4 col-4">
    <input type="date" th:field="*{date}" class="form-control mb-4 col-4">

    <select th:field="${transaction.incomeCategories}">
        <option value="0">Select income category</option>
        <option
                th:each="incomeCategories : ${incomeCategories}"
                th:value="${incomeCategories}"
                th:text="${incomeCategories.displayName}"
        ></option>
    </select>
    <button type="submit" class="btn btn-info col-2"> Save Wallet</button>
</form>

Now, If the user entered wrong value for amount I will provide him error, and that works fine. But what is the problem, I will provide you a use case:

Here user pick the transaction type:

Now, user has selected Income for example, and I provide him form for Income:

Now, If user for field amount insert -1 I will provide him an error, but I'm redirected to this page again:

And when I select again Income only then I can see the error:

While I want to display him immediately form that he picked from list. So if he choose Income but made error on form, display him again Income form without having to choose again from dropdown menu.

The only solution so far that I have on my mind is to create a totally separated HTML pages with form, but I think that there is for sure a way to solve this on another way without that.

I give my best to explain problem and added picture for better understanding, for anything else I'm here to explain or to provide more information. Thank you and also sorry for my bad English.


问:
Script not recognizing Instance Script
I have 3 projects. 1 works but I want to refactor and use an asset from Unity store.
2nd project is the asset only with my mission system modified/merged to work with the asset and it works fine. Awesome.

So the 3rd project is the one I need to work, it is my original project with the asset imported in.
The issue I am having is the mission system, for some reason the ApplicationManager instance is not being seen inside the itempickup used like "ApplicationManager.instance" BUT it works in the 2nd project, they are literal copy/paste and no idea why it is not seen?

error CS0103: The name 'ApplicationManager' does not exist in the current context
EDIT:
It seems only the assets scripts are not seeing the ApplicationManager, I tested with my other scripts and they see it just fine, not sure what to look at to get them to work in this project since they work in the 2nd project fine.
EDIT 2: So it seems it simething about how he made the asset. If I move the AppMan to HIS folder labeled PickUp (for items) it now sees the script. How the &(* do I remove or fix that restriction?? Never seen it before. Once I move it to that folder all my other scripts now lose the reference.
Application manager:

```<code> public class ApplicationManager : MonoBehaviour
    {
private static ApplicationManager _Instance = null;

        public static ApplicationManager instance
        {
            get
            {
                // If we don't have an instance yet find it in the scene hierarchy
                if (_Instance == null)
                {
                    _Instance = (ApplicationManager)FindObjectOfType(typeof(ApplicationManager));
                }

                // Return the instance
                return _Instance;
            }
        }
    }
</code>```

And the Itempickup:

```<code>public abstract class ItemPickupBase : Interactable
    {
        [SerializeField]
        protected List<GameState> _setOnCollect = new List<GameState>();

protected void PickUpItem(ICharacter character, IItem item, bool playPickUpSound = true)
        {
            if (item == null)
            {
                Debug.LogError("Item Instance is null, can't pick up anything.");
                return;
            }

            int addedCount = 0;
            int originalCount = item.StackCount;

            string rejectReason = string.Empty;

            if (m_AddType == AddType.AddToMatchingContainer)
            {
                var containers = character.Inventory.GetContainersWithTag(item.Definition.Tag);
                foreach (var container in containers)
                {
                    if (container.GetAllowedCount(item, item.StackCount, out rejectReason) > 0)
                        addedCount += container.AddItem(item);

                    if (addedCount == originalCount)
                        break;
                }

                if (originalCount > 1)
                    item.StackCount = originalCount - addedCount;
            }

            if (addedCount != originalCount)
            {
                var containers = character.Inventory.Containers;
                foreach (var container in containers)
                {
                    if (container.GetAllowedCount(item, item.StackCount, out rejectReason) > 0)
                        addedCount += container.AddItem(item);

                    if (addedCount == originalCount)
                        break;
                }
            }

            if (addedCount > 0)
            {
                string pickupUpMessage = $"Pickup up {item.Name}";

                if (addedCount > 1)
                    pickupUpMessage += $" x {addedCount}";

                MessageDisplayerUI.PushMessage(pickupUpMessage, item.Definition.Icon);

                if (playPickUpSound)
                    m_PickUpSound.Play2D(1f, SelectionType.Random);

                if (addedCount >= originalCount)

                     if (ApplicationManager.instance && _setOnCollect.Count > 0)
                     {

                         foreach (GameState state in _setOnCollect)
                         {
                             ApplicationManager.instance.SetGameState(state.Key, state.Value);
                         }
                     }

                Destroy(gameObject);
            }
            else
            {
                MessageDisplayerUI.PushMessage(rejectReason != string.Empty ? rejectReason : "Inventory Full", Color.red);
            }
        }
}
</code>```

Not sure what to try since this is almost a literal copy/paste from the original and it is not working. The only difference I can see is the ItemPickup in the 2nd project is a public class and the one I am having issues with is a public abstract class.
But when I try to access the ApplicationManager in another script it still does not see it so I figured that was not the issue.

Title: Script not recognizing Instance Script

Body:
I have 3 projects. 1 works but I want to refactor and use an asset from Unity store.
2nd project is the asset only with my mission system modified/merged to work with the asset and it works fine. Awesome.

So the 3rd project is the one I need to work, it is my original project with the asset imported in.
The issue I am having is the mission system, for some reason the ApplicationManager instance is not being seen inside the itempickup used like "ApplicationManager.instance" BUT it works in the 2nd project, they are literal copy/paste and no idea why it is not seen?

error CS0103: The name 'ApplicationManager' does not exist in the current context
EDIT:
It seems only the assets scripts are not seeing the ApplicationManager, I tested with my other scripts and they see it just fine, not sure what to look at to get them to work in this project since they work in the 2nd project fine.
EDIT 2: So it seems it simething about how he made the asset. If I move the AppMan to HIS folder labeled PickUp (for items) it now sees the script. How the &(* do I remove or fix that restriction?? Never seen it before. Once I move it to that folder all my other scripts now lose the reference.
Application manager:

 public class ApplicationManager : MonoBehaviour
    {
private static ApplicationManager _Instance = null;

        public static ApplicationManager instance
        {
            get
            {
                // If we don't have an instance yet find it in the scene hierarchy
                if (_Instance == null)
                {
                    _Instance = (ApplicationManager)FindObjectOfType(typeof(ApplicationManager));
                }

                // Return the instance
                return _Instance;
            }
        }
    }

And the Itempickup:

public abstract class ItemPickupBase : Interactable
    {
        [SerializeField]
        protected List<GameState> _setOnCollect = new List<GameState>();

protected void PickUpItem(ICharacter character, IItem item, bool playPickUpSound = true)
        {
            if (item == null)
            {
                Debug.LogError("Item Instance is null, can't pick up anything.");
                return;
            }

            int addedCount = 0;
            int originalCount = item.StackCount;

            string rejectReason = string.Empty;

            if (m_AddType == AddType.AddToMatchingContainer)
            {
                var containers = character.Inventory.GetContainersWithTag(item.Definition.Tag);
                foreach (var container in containers)
                {
                    if (container.GetAllowedCount(item, item.StackCount, out rejectReason) > 0)
                        addedCount += container.AddItem(item);

                    if (addedCount == originalCount)
                        break;
                }

                if (originalCount > 1)
                    item.StackCount = originalCount - addedCount;
            }

            if (addedCount != originalCount)
            {
                var containers = character.Inventory.Containers;
                foreach (var container in containers)
                {
                    if (container.GetAllowedCount(item, item.StackCount, out rejectReason) > 0)
                        addedCount += container.AddItem(item);

                    if (addedCount == originalCount)
                        break;
                }
            }

            if (addedCount > 0)
            {
                string pickupUpMessage = $"Pickup up {item.Name}";

                if (addedCount > 1)
                    pickupUpMessage += $" x {addedCount}";

                MessageDisplayerUI.PushMessage(pickupUpMessage, item.Definition.Icon);

                if (playPickUpSound)
                    m_PickUpSound.Play2D(1f, SelectionType.Random);

                if (addedCount >= originalCount)

                     if (ApplicationManager.instance && _setOnCollect.Count > 0)
                     {

                         foreach (GameState state in _setOnCollect)
                         {
                             ApplicationManager.instance.SetGameState(state.Key, state.Value);
                         }
                     }

                Destroy(gameObject);
            }
            else
            {
                MessageDisplayerUI.PushMessage(rejectReason != string.Empty ? rejectReason : "Inventory Full", Color.red);
            }
        }
}

Not sure what to try since this is almost a literal copy/paste from the original and it is not working. The only difference I can see is the ItemPickup in the 2nd project is a public class and the one I am having issues with is a public abstract class.
But when I try to access the ApplicationManager in another script it still does not see it so I figured that was not the issue.


问:
How to get the user's information who mentioned a page on Facebook?
I have successfully setup a Facebook App which provides Business Page management.

The goal is to get notified when a Facebook user mentions the said Page and identify who.

Setting up the webhook, for every mention I receive this kind of payload:

{
   "entry":[
      {
         "id":"105569338984024",
         "time":1673197963,
         "changes":[
            {
               "value":{
                  "message":"BusinessPage I mention you",
                  "post_id":"5882266138421716_3303976449916555",
                  "created_time":1673137958,
                  "item":"post",
                  "verb":"add"
               },
               "field":"mention"
            }
         ]
      }
   ],
   "object":"page"
}
```

Contrary to messaging or comments, I do not receive any information about the user who created this mention.

How should I get the user info? Or perhaps I did not setup the webhook properly?

Body:
I have successfully setup a Facebook App which provides Business Page management.

The goal is to get notified when a Facebook user mentions the said Page and identify who.

Setting up the webhook, for every mention I receive this kind of payload:

{
   "entry":[
      {
         "id":"105569338984024",
         "time":1673197963,
         "changes":[
            {
               "value":{
                  "message":"BusinessPage I mention you",
                  "post_id":"5882266138421716_3303976449916555",
                  "created_time":1673137958,
                  "item":"post",
                  "verb":"add"
               },
               "field":"mention"
            }
         ]
      }
   ],
   "object":"page"
}

Contrary to messaging or comments, I do not receive any information about the user who created this mention.

How should I get the user info? Or perhaps I did not setup the webhook properly?


问:
xlwings addin installation error messages on macOS using Rosetta
After upgrading to Rosetta and reinstalling python and anaconda, xlwings install addin generates the error messages below. There is also an error in the Excel addin "Traceback (most recent call last): File "", line 1, in  ImportError: No module named xlwings.utils"

```<code>$>xlwings addin install

xlwings version: 0.27.15
Traceback (most recent call last):
  File "/Users/phil/opt/anaconda3/lib/python3.9/site-packages/aeosa/appscript/reference.py", line 482, in __call__
    return self.AS_appdata.target().event(self._code, params, atts, codecs=self.AS_appdata).send(timeout, sendflags)
  File "/Users/phil/opt/anaconda3/lib/python3.9/site-packages/aeosa/aem/aemsend.py", line 92, in send
    raise EventError(errornum, errormsg, eventresult)
aem.aemsend.EventError: Command failed: Parameter error. (-50)

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/phil/opt/anaconda3/bin/xlwings", line 11, in <module>
    sys.exit(main())
  File "/Users/phil/opt/anaconda3/lib/python3.9/site-packages/xlwings/cli.py", line 1081, in main
    args.func(args)
  File "/Users/phil/opt/anaconda3/lib/python3.9/site-packages/xlwings/cli.py", line 44, in addin_install
    _addin_install(addin_source_path)
  File "/Users/phil/opt/anaconda3/lib/python3.9/site-packages/xlwings/cli.py", line 54, in _addin_install
    app.books[addin_name].close()
  File "/Users/phil/opt/anaconda3/lib/python3.9/site-packages/xlwings/main.py", line 1079, in close
    self.impl.close()
  File "/Users/phil/opt/anaconda3/lib/python3.9/site-packages/xlwings/_xlmac.py", line 464, in close
    self.xl.close(saving=kw.no)
  File "/Users/phil/opt/anaconda3/lib/python3.9/site-packages/aeosa/appscript/reference.py", line 518, in __call__
    raise CommandError(self, (args, kargs), e, self.AS_appdata) from e
appscript.reference.CommandError: Command failed:
        OSERROR: -50
        MESSAGE: Parameter error.
        COMMAND: app(pid=18444).workbooks['xlwings.xlam'].close(saving=k.no)
</code>```

The addin and xlwings were working before the upgrade to Rosetta. The SampleCall macro was running as expected.

Body:
After upgrading to Rosetta and reinstalling python and anaconda, xlwings install addin generates the error messages below. There is also an error in the Excel addin "Traceback (most recent call last): File "", line 1, in  ImportError: No module named xlwings.utils"

$>xlwings addin install

xlwings version: 0.27.15
Traceback (most recent call last):
  File "/Users/phil/opt/anaconda3/lib/python3.9/site-packages/aeosa/appscript/reference.py", line 482, in __call__
    return self.AS_appdata.target().event(self._code, params, atts, codecs=self.AS_appdata).send(timeout, sendflags)
  File "/Users/phil/opt/anaconda3/lib/python3.9/site-packages/aeosa/aem/aemsend.py", line 92, in send
    raise EventError(errornum, errormsg, eventresult)
aem.aemsend.EventError: Command failed: Parameter error. (-50)

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/phil/opt/anaconda3/bin/xlwings", line 11, in <module>
    sys.exit(main())
  File "/Users/phil/opt/anaconda3/lib/python3.9/site-packages/xlwings/cli.py", line 1081, in main
    args.func(args)
  File "/Users/phil/opt/anaconda3/lib/python3.9/site-packages/xlwings/cli.py", line 44, in addin_install
    _addin_install(addin_source_path)
  File "/Users/phil/opt/anaconda3/lib/python3.9/site-packages/xlwings/cli.py", line 54, in _addin_install
    app.books[addin_name].close()
  File "/Users/phil/opt/anaconda3/lib/python3.9/site-packages/xlwings/main.py", line 1079, in close
    self.impl.close()
  File "/Users/phil/opt/anaconda3/lib/python3.9/site-packages/xlwings/_xlmac.py", line 464, in close
    self.xl.close(saving=kw.no)
  File "/Users/phil/opt/anaconda3/lib/python3.9/site-packages/aeosa/appscript/reference.py", line 518, in __call__
    raise CommandError(self, (args, kargs), e, self.AS_appdata) from e
appscript.reference.CommandError: Command failed:
        OSERROR: -50
        MESSAGE: Parameter error.
        COMMAND: app(pid=18444).workbooks['xlwings.xlam'].close(saving=k.no)

The addin and xlwings were working before the upgrade to Rosetta. The SampleCall macro was running as expected.


问:
How can I access a private google calendar via an iframe?
I used an iframe for two of my google calendars in a Django website on my NAS in the past. That stopped working as I found out yesterday. When I use the link for a public calendar like Holidays in my country, there is no problem, but as soon as I use the embed link from the google calendar settings it will give me the following error:

"403. That's an error.

We're sorry, but you do not have access to this page. That’s all we know."

But it is so strange. In the Google calendar settings right above the section with the embed code there is the public URL for the corresponding calendar. And it is the same. Just without the <iframe src=" etc. part around it. When I take this URL and paste it into the browser address bar, it works. If I put it in an iframe element in a tiny html file on my computer and open that, again I get the 403. So for whatever reason the link does not work when included in an iframe.

As a browser I used FF 108, but it also does not work in Chromium.

Do you have any suggestion how to solve this or advice what changed with regards to Google's policy? As far as I know this has nothing to do with login credentials because I am testing this on my computer and every other google-related page also recognizes me.

Best regards
Martin


问:
How to ignore the effect of leap year when using Temporal.Duration?
I am trying to compare the duration of x and the duration of a year in second, to find out how many times I need to repeat an action annually.

I get the seconds of a year like this:

const now = Temporal.Now.zonedDateTimeISO('Europe/London')

Temporal.Duration.from("P1Y").total({ relativeTo: now, unit: "seconds"}) //31536000
```
<p>And I get the duration of <code>x</code> like that as well, but when <code>x</code> is <code>P2Y</code>, I get an extra <code>86400</code>, as next year(2024) is a leap year, which we have 29/2</p>
<pre class="lang-js prettyprint-override"><code>Temporal.Duration.from("P2Y").total({ relativeTo: now, unit: "seconds"}) //63158400, instead of 6307200
</code>```

I want to ignore Leap Year in the duration(I know the result will be incorrect, but I want a more theoretical result), how can I do that?

Body:
I am trying to compare the duration of x and the duration of a year in second, to find out how many times I need to repeat an action annually.

I get the seconds of a year like this:

const now = Temporal.Now.zonedDateTimeISO('Europe/London')

Temporal.Duration.from("P1Y").total({ relativeTo: now, unit: "seconds"}) //31536000

And I get the duration of x like that as well, but when x is P2Y, I get an extra 86400, as next year(2024) is a leap year, which we have 29/2

Temporal.Duration.from("P2Y").total({ relativeTo: now, unit: "seconds"}) //63158400, instead of 6307200

I want to ignore Leap Year in the duration(I know the result will be incorrect, but I want a more theoretical result), how can I do that?


问:
3D bounded voronoi/delaunay
I'm searching for an open-source code computing the 3D voronoi/delaunay of a point cloud bounded by a generic volume.

I'm currently coding mostly on python using scipy to generate the diagrams, but 3D bounding is not supported. Mathworks community has a pair of codes such as this with a bounded cuboid and this with a convex polytope, but I would prefer faster languages since point clouds I'm working with are quite large.

Thanks,
ic

Title: 3D bounded voronoi/delaunay