Return type error in eXist-db - exist-db

I have just realized my logger is very active in the case of a function responsible for generating epubs. The problem is it works as expected. Hence I wonder what is going on here.
The error:
java:org.exist.xquery.XPathException, exerr:ERROR The actual return type does not match the sequence type declared in the function's signature: epub-util:render-epub(node()+, xs:string) xs:base64Binary. Expected cardinality: exactly one, got 0.
… epub is properly served to the client.
As for exerr:ERROR, I checked the general log in $EXIST_HOME/webapp/WEB-INF/logs/exist.log. There are no associated errors caught.
The suspected function:
declare function epub-util:render-epub($entries as node()+, $name as xs:string) as xs:base64Binary {
let $zip-file := compression:zip($entries, true())
let $archiveName := $name
return
response:stream-binary($zip-file, 'application/epub+zip', lower-case(replace($archiveName, ' ', '-')) || '.epub')
};
I run eXist on Ubuntu Server 14.04, eXist-db is 3.0.RC1.

response:stream-binary() is a very special function, that in essence directly writes bytes to a servlet output stream , hence it can only be used in the REST interface.
It can only write a byte stream to a HTTP agent, that is e.g. your web browser. It is not possible to store this data in a variable.
I agree that even item() is not a good thing, it should be something like void but that does not exist.
The common use-case it to have this expression as the last function call in a xquery script. A similar construct we use in the JFreechart library.

According to the eXist-db function documentation for response:stream-binary(), this function returns item(), not xs:base64binary. Replacing the return type with item() should fix the error.

Related

How do I return different response in the webflux based on whether the Flux object has elements?

I know there is a function named "hasElements" on a Flux object. But it behaves a bit strange!
Flux<RoomBO> rooms=serverRequest.bodyToMono(PageBO.class).flatMapMany(roomRepository::getRooms);
return rooms.hasElements().flatMap(aBool -> aBool?ServerResponse.ok().body(rooms,RoomBO.class):ServerResponse.badRequest().build());
return ServerResponse.ok().body(rooms,RoomBO.class)
The second return statement can return the right things I need when the flux object is not empty,but the first return statement only returns a empty array,which likes "[]" in json.I don't know why this could happen!I use the same data to test.The only difference is that I call the hasElements function in the first situation.But I need to return badRequest when the flux object is empty. And the hasElements function seems to make my flux object empty,though I know it doesn't do this actually.
well, finally I decide to call switchIfEmpty(Mono.error()) to throw an error and then I deal with the special error globally(Sometimes it's not suitable to use onErrorReturn or onErrorResume). I think this can avoid the collect operation in memory when meets big data. But it's still not a good solution for the global error handler can be hard to maintain. I'd expect someone to give a better solution.
In your example you are transforming class Flux to class RoomBO, it is one of the reasons, why you get an empty array.
If you need to return the processed list of rooms, then, I think, collectList should be your choice. https://projectreactor.io/docs/core/release/api/reactor/core/publisher/Flux.html#collectList--
Flux<RoomBO> roomsFlux = serverRequest.bodyToMono(PageBO.class)
.flatMapMany(roomRepository::getRooms);
return rooms
.collectList()
.flatMap(rooms -> !rooms.isEmpty() ? ServerResponse.ok().bodyValue(rooms) : ServerResponse.badRequest().build());

How to use a certain set of values for typing in Python

I need to specify a certain set of values as the expected return type for my function. Let's say there was defined some class called Scene which has attribute name which is supposed to be a string which may end only with "1K", "2K" or "4K". Now I want to write a function which takes this class as an argument and returns the last 2 characters of its name as a string. Is there a way to specify this function return type like a set of exact string values using built-in modules in Python 3.7.7? Something like this:
def scene_resolution(sc : Scene): -> any value in {'1K', '2K', '4K'}: # return type?
res = sc.name[-2:]
assert res in {'1K', '2K', '4K'}
return res
I know about using Literal from typing_extensions, but unfortunately it works only with Python 3.8 and higher, and the API of the soft I'm dealing with uses Python 3.7.7. I've also tried to make something with enum.Enum but could not make it work properly.
Do you have any suggestions?
UPD. The only way I found so far is to define some function that returns the set I need and use its name as expected return type. Not sure whether it is correct way and a good practice, but at least it works.

linter err113: do not define dynamic errors, use wrapped static errors instead

I am using err113 as part of golangci-lint.
It is complaining about ...
foo_test.go:55:61: err113: do not define dynamic errors, use wrapped static errors instead: "errors.New(\"repo gave err\")" (goerr113)
repoMock.EXPECT().Save(gomock.Eq(&foooBarBar)).Return(nil, errors.New("repo gave err")),
^
foo_test.go:22:42: err113: do not define dynamic errors, use wrapped static errors instead: "errors.New(\"oops\")" (goerr113)
repoMock.EXPECT().FindAll().Return(nil, errors.New("oops"))
^
What is best way to fix this ?
Quoting https://github.com/Djarvur/go-err113
Also, any call of errors.New() and fmt.Errorf() methods are reported
except the calls used to initialise package-level variables and the
fmt.Errorf() calls wrapping the other errors.
I am trying to get a idiomatic example for this.
Declare a package-level variables as suggested:
var repoGaveErr = errors.New("repo gave err")
func someFunc() {
repoMock.EXPECT().Save(gomock.Eq(&foooBarBar)).Return(nil, repoGaveErr)
}
Every call to errors.New allocates a new unique error value. The application creates a single value representing the error by declaring the package-level variable.
There are two motivations for the single value:
The application can compare values for equality to check for a specific error condition.
Reduce memory allocations (although probably not a big deal in practice)
The value io.EOF is a canonical example.
Since GO 1.13 you can define a new error type, wrap it and use it.
for example, if you want to return an "operation not permitted" + the operation.
you need to implement something like
var OperationNotPermit = errors.New("operation not permitted")
func OperationNotFoundError(op string) error {
return fmt.Errorf("OperationNotPermit %w : %s", OperationNotPermit, op)
}
then in your code, when you want to return the error,
return nil, OperationNotFoundError(Op)
Let's back to question case:
first, define the custom error and the wapper
var repoError = errors.New("repositoryError")
func RepositoryError(msg string) error {
return fmt.Errorf("%w: %s", repoError,msg)
}
then in your code,
repoMock.EXPECT().Save(gomock.Eq(&foooBarBar)).Return(nil, RepositoryError("YOUR CUSTOM ERROR MESSAGE"))
Since it hasn't been said before, you probably don't need to define package level errors for tests. Given the idea is to wrap errors so they can be compared and unwrapped in the caller, returning a dynamic error in a test is fine as long as the purposes of your test are served.

Golang error control on parameters when calling a function with reflection

I'm trying to call a function using reflection based on it's name.
I first recover the function with
f := reflect.ValueOf(s).MethodByName(name)
I do error control on the function name by checking if "f" is valid with
if !f.IsValid() {
return errors.New("There is no function with that name")
}
And finally I perform the call with
f.Call(inputs)
My challenge is that inputs depends on the user, and sometimes they can put too many parameters, too little or invalid types.
IE:
2019/01/04 16:47:54 http: panic serving [::1]:53662: reflect: Call using string as type int
How can I control that the inputs are valid before performing the call?
Maybe there is a way to recover the expected inputs in my method and check them against the provided ones?

Function parameter error - Missing Argument Label Anomaly - SWIFT

I have a strange issue (which I can overcome however I would like to get a proper understanding of my error).
I have a small random number generator function which I use often:
func ranNum(low: Int, high:Int) -> UInt32 {
var result = arc4random_uniform(UInt32((high+1)-low)) + low
return result
}
When I use this in XCode playgrounds it works just fine if I pass in something like:
ranNum(1, 10)
However, in a regular Swift file it generates the error message : Missing argument label 'hi:' in call. Now I can overcome this by calling the function this way:
ranNum(1, hi:10)
Apart from it just being a little harder to read, it just isn't making sense why it works in Playgrounds but also why it requires only the 2nd argument label and not both. Any help as to what I am not understandinh would be greatly appreciated.
That's called external parameter name, and by default:
global functions: don't have implicit external names
class/struct methods: external names are automatically defined for all parameters after the first
initializers: external names are automatically defined for all parameters
If not explicitly specified, external names take the same name as the local parameter.
You can override that by prefixing a local parameter name with _. In your case:
func ranNum(low: Int, _ high:Int) -> UInt32 {
...
}
You mentioned that in playground calling the function works without any external parameter name - I may argue that:
in playground you have that function as a global function
in other tests, that function is a class/struct method
Am I right?

Resources