More advanced filtering system (LHS brackets | RHS colon) in FastAPI - openapi

Is it possible to create a filtering system in FastAPI like:
?something[lte]=120&something2[in]=12,34
or
?something=lte:120&something2=in:12,34
And how to make OpenAPI documentation for it?
Imagine if there are many such endpoints and even more fields? I do not want to describe a set of fields with the same type of Depends classes with a certain logic parse (I don't know how to dynamically pass type annotating for it).
It is also not possible to subclass fastapi.Query and add extra logic to it.
Also there was an idea in the implementation of the f key as a query parameter:
?f=<field_name>:<operator>:<value>&f=<field_name N>:<operator>:<value>
But in this case, the documentation is not complete and you have to fill it in description (it will also be the same for all endpoints). As a result, it will not be clear which fields can be filtered and which operators are used for them.

Related

How to access Method Names from source object in Rule Definition

In our implementation of the Rules Engine we have a test form similar to Rule Test Form on the online demo on "Business Rules Engine Demo". What we would like to do is conditionally show only the Test Fields for the items in use in the rule. We are doing this by grabbing the rule.definition JSON from the ruleeditor then look for the items which we can conditionally create using AngularJS's ng-if directive. This works great with Fields. If the user selects a method, our method of parsing the string is failing. What it appears is the Field Names are stored in the JSON as plain text however the Method Names are not. Is there a way we can configure the control to either A not encrypt the method names or is there a way that we can tap into the encryption to identify if a method is in use in our rule? Thanks in advance.
Methods and actions can have overloads which the Code Effects rule editor supports. Therefore, we can't have multiple menu entries with the same name. Instead, we use a signature hash on all in-rule methods and rule actions regardless of whether it has an overload or not to make them unique on the client.
You need to have either the Full Source or the Editor Source license in order to change the code to either stop that hashing, or tap into the process, or implement it your own way. You don't have that option with any other Code Effects perpetual license.

How to get an OrderedSet of OccurrenceSpecifications from a Lifeline in QVTo?

From the diagram on page 570 of the UML spec I concluded that a Lifeline should have the events property, holding an OrderedSet(OcurrenceSpecification). Unfortunately it is not there, at least in the QVTo implementation that I use.
All I have is the coveredBy property, serving me with an (unordered) Set(InteractionFragment). Since my transformation relies on the correct order of MessageOcurrenceSpecification I somehow need to implement myself what I expected to be implemented by the missing events property.
This is what I have so far:
helper Lifeline::getEvents (): OrderedSet(OccurrenceSpecification) {
return self.coveredBy->selectByKind(OccurrenceSpecification)->sortedBy(true);
}
Obviously sortedBy(true) does not get me far, but I don't know any further. Who can help?
All I could find so far were other people struggling with the same issue years ago, but no solution:
https://www.eclipse.org/forums/index.php/m/1049555/
https://www.eclipse.org/forums/index.php/m/1050025/
https://www.eclipse.org/forums/index.php/m/1095764/
Based on the answer by Vincent combined with input from a colleague of mine I came up with the following solution for QVTo:
-- -----------------------------------------------------------------------------
-- Polyfill for the missing Lifeline::events property
query Lifeline::getEvents (): OrderedSet(OccurrenceSpecification) {
return self.interaction.fragment
->selectByKind(OccurrenceSpecification)
->select(os: OccurrenceSpecification | os.covered->includes(self))
->asOrderedSet();
}
I don't know if it is possible, using directly coveredBy to get an ordered collection. As coveredBy is unordered, if you access it directly by the feature, you will have an unpredictible order and if you try to access it using the eGet(...) stuff, the same result will occur.
However, if I understood correctly, there is a "trick" that could work.
It relies on the assumption that each OccurrenceSpecification instance you need is held by the same Interaction that contains the Lifeline and uses the way EMF stores contained elements. Actually, each contained element is always kind of 'ordered' relatively to its parent (and for each collection so EMF can find elements back when XMI references are expressed using the element position in collections). So, the idea would be to access all the elements contained by the Interaction that owns the lifeline and filter the ones that are contained in coveredBy.
Expression with Acceleo
This is easy to write in MTL/Acceleo. In know you don't use it, but it illustrates what the expression does:
# In Acceleo:
# 'self' is the lifeline instance
self.interaction.eAllContents(OccurrenceSpecification)->select(e | self.coveredBy->includes(e))->asOrderedSet()
with self.interaction we retrieve the Interaction, then we get all the contained elements with eAllContents(...) and we filter the ones that are in the self.coveredBy collection.
But it is way less intuitive in QVT as eAllContents(...) does not exist. Instead you have to gain access to eContents() which is defined on EObject and returns an EList which is transtyped to a Sequence (in QVT,eAllContents() returns a ETreeIterator which is not transtyped by the QVT engine).
So, how to gain access to eContents() in the helper? There is two solutions:
Solution 1: Using the emf.tools library
The emf.tools library give you the ability to use asEObject() which casts your object in a pure EObject and give you more methods to access to (as eClass() for example...etc).
import emf.tools; -- we import the EMF tools library
modeltype UML ...; -- all your metamodel imports and stuffs
...
helper Lifeline::getEvents (): OrderedSet(OccurrenceSpecification) {
return self.interaction.asEObject().eContents()[OccurrenceSpecification]->select(e | self.coveredBy->includes(e))->asOrderedSet();
}
Solution 2: Using oclAstype(...)
If for some reason emf.tools cannot be accessed, you can still cast to an EObject using oclAsType(...).
modeltype UML ...; -- all your metamodel imports and stuffs
modeltype ECORE "strict" uses ecore('http://www.eclipse.org/emf/2002/Ecore'); -- you also register the Ecore metamodel
...
helper Lifeline::getEvents (): OrderedSet(OccurrenceSpecification) {
return self.interaction.oclAsType(EObject).eContents()[OccurrenceSpecification]->select(e | self.coveredBy->includes(e))->asOrderedSet();
}
Limitation
Ok, let's be honest here, this solution seems to work on the quick tests I performed, but I'm not a 100% sure that you will have all the elements you want as this code relies on the strong assumption that every OccurrenceSpecification you need are in the same Interaction as the Liteline instance. If you are sure that all the coveredBy elements you need are in the Interaction (I think they should be), then, that's not the sexiest solution, but it should do the work.
EDIT>
The solution proposed by hielsnoppe is more eleguant than the one I presented here and should be prefered.
You are correct. The Lifeline::events property is clearly shown on the diagram and appears in derived models such as UML.merged.uml.
Unfortunately Eclipse QVTo uses the Ecore projection of the UML metamodel to UML.ecore where unnavigable opposites are pruned. (A recent UML2Ecore enhancement allows the name to be persisted as an EAnnotation.) However once the true property name "events" has been pruned the implicit property name "OccurrenceSpecification" should work.
All associations are navigable in both directions in OCL, so this loss is a bug. (The new Pivot-based Eclipse OCL goes back to the primary UML model in order to avoid UML2Ecore losses. Once Eclipse QVTo migrates to the Pivot OCL you should see the behavior you expected.)

make play-json read the empty string as None for a type of Option[T]

I'm attempting to parse json from the GitHub API with play-json, and encountering a problem with the merge_commit_sha field on Pull Requests (incidentally, I know this field is deprecated, but don't want to discuss that in this parsing problem!). Unfortunately merge_commit_sha field comes back as the empty string in some cases:
"merge_commit_sha": ""
This is how the field is declared in my case class:
merge_commit_sha: Option[ObjectId],
I have an implicit Format[ObjectId], which does not tolerate the empty string, because that's not a valid value for a Git hash id. I'm also using a play-json macro-generated Read[PullRequest], which I'd like to keep on using, in preference to individually declaring reads for every single field on pull requests.
As I've declared the field to be an Option, I'd like "merge_commit_sha": "" to be read as the value None, but this is not what currently happens - a string is present, so the Format[ObjectId] is invoked, and returns a JsFailure.
One thing I tried was declaring an implicit Format[Option[ObjectId]] with the required behaviour, but it didn't seem to get used by the macro-generated Read[PullRequest].
You can define a custom Reads and Writes yourself.
Using Json.format[MyType] uses a Scala macro. You may be able to hook into that. Although, 'extending' a macro for this one case class just seems wrong.
Custom Reads and Writes might be a little 'boilerplate-like' and boring, but they have their upsides.
For example if your json has a bunch of new fields on it, you wont get a JsError when validating or transforming it to a case class. You only take what you need from the JSON and create objects. It also allows for a separation between your internal model and what you're consuming, which in some cases is preferred.
I hope this helps,
Rhys
EDIT
After using some other JSON libs I may have found what you are looking for.
I know the question was asking specifically after Play JSON.
If you're able to move away from Play JSON, Look at spray-json-shapeless specifically JsNullBehaviour and JsNullNotNone REF.

What is a 2-dimensional key-value format that Api Blueprint can understand?

I'm developing api documentation for a RESTful search API using Api Blueprint. I would like to be able to pass filters to the API so I can assemble:
filter[filtername1]=filtervalue1
filter[filtername2]=filtervalue2
Per this question, I'm using percent encoded square brackets, but unlike this question, it's not possible for us to describe every possible key name:
How to format hash-based parameters in the URL when creating Blueprint API doc?
I want the key name to be variable, since it could be any field in the source data. Does this work?
## Key-Value-Test [/api/v1/keyvaluetest?term={term}&filter%5B{field_name}%5D={field_value}]
+ term
+ filter_field
+ filter_value
Is there a recommended format for a two-dimensional array like this? It doesn't seem like this would work in Dredd because + filter_field doesn't really match filter[filter_field]
I am afraid that API Blueprint and Apiary does not yet allow these kind of dynamic URL definitions.
API Blueprint and Apiary only allows URI Templates as defined in RFC 6570
The following URI Template is not valid according to that RFC
GET /resource?year={year}&month={month}
You can change the URL to define something like the following:
## Key-Value-Test [/api/v1/keyvaluetest{?term,field_name,field_value}]
+ Parameters
+ term: a
+ field_name: b
+ field_value: c
There are two caveats with this method:
You can only give one field name and field value for the parameters. If you want more field parameters, you have to extend the URL.
You have to change the API url which I don't think you would want to.
Please start a feature request at http://support.apiary.io if you have any.
API Blueprint uses URI Templates standard. There are ways to express and expand arrays (see section 3.2.1), however, it expects "standard URI approach", meaning the URI would be expanded as follows:
/api/v1/keyvaluetest?term=yourterm&filter=filtervalue1&filter=filtervalue2
which is a "standard" way of doing arrays, except the most popular web language popularised your way back in 2000s.
The templates are designed for expansion: give it a bunch of variables and a string, and you'll get a properly-formatted string. As far as I am aware, there is no "wild match" (inserting pattern-match variables at a certain position in string).
The only solution I can think of within the realm of URL templates would be taking advantage of explosion modifier (see composite values):
/api/v1/keyvaluetest{?keys*}
which, given associative array of values [(filter%5Bfiltername1%5D, filtervalue1), (filter%5Bfiltername2%5D, filtervalue2) ] should expand properly.
However, I am not sure how to specify those in MSON as I don't think there is a support for "dynamic keys" and I think most of the tooling wouldn't handle it (yet).
Might be worth asking.

AppleScript application support: 'duplicate' command fails

I am trying to support the 'duplicate' command. It works fine for duplicating the top class:
tell application "SpellAnalysis" to duplicate level 1
This, however, crashes:
tell application "SpellAnalysis" to duplicate (get unit 1 of (get level 1))
I have provided index specifiers for both classes, where the outer container for 'unit' is 'level'. Oddly, I can specify a property of the unit class like this:
tell application "SpellAnalysis" to (get general rule of unit 1 of (get level 1))
The culprit seems to be that the 'objectsByEvaluatingSpecifier' always returns a null value when used within NSCloneCommand subclass, as well as the unit class' objectSpecifier method, where its needed.
I was finally able to support AppleScript 'duplicate' command. Although the normal way to support the command is by sub-classing 'NSCloneCommand', with this method, your direct parameter results in a specifier that specifies the containing object and not the direct object--as a special provision of the 'NSCloneCommand'. I suppose this is meant to facilitate the case when you would be duplicating an object belonging to a document, where the document class provides the means for creating new constituent objects. Unfortunately, in my case, my constituent objects take part in their own duplication and need to know their specifiers to do so. The solution was to support the 'duplicate' command by the optional technique of creating a custom 'duplicate' command within my application's suite that entailed subclassing the more general 'NSScriptCommand'. This alternative avoids any redirection of the specifier returned from the 'directParameter' method of the 'NSScriptCommand' class. I was able to work from there to derive all the child class-objects for cloning.