Graphql Schema doku displays Input type automatically with Input - graphql-spqr

I have added leangen/graphql-spqr as described in the readme.
Before we had a custom implementation of graphql types like in customtype.types.gql.
After implementation, everything works fine, except the type which are called e.g. OperatorInput, are named in the autogenerated graphql doc like "OperatorInputInput".
I tried to Change it like this in the declaration:
#GraphQLArgument(name = "OperatorInput", description = "Required fields for Operator") OperatorInput operator
But it wasn't applied.
Do you know any workaround?

This is intended. Keep in mind that in GraphQL's type system, input and output types are strictly different. Let's say you have this in Java:
public Book saveBook(Book in) {...}
The Book that is the return type and the Book that is the argument type are 2 different types in GraphQL, and must have unique names. So Input is added automatically to make the names unique.
If you're 100% sure you want to override this, register a custom TypeInfoGenerator via GraphQLSchemaGenerator#withTypeInfoGenerator. You can inherit from DefaultTypeInfoGenerator and override generateInputTypeName. BUT! Do pay attention that if you end up producing the same name for 2 different types, all hell breaks loose. So maybe only drop the suffix Input if the classname already ends with Input and never ever use such classes for output.
Btw #GraphQLArgument sets the name of the argument, not the name of the type of the argument.

Related

How to use Humanize inside #Html,DisplayFor()

How can I display Date Humanizely inside DisplayFor?
I tried like this : #Html.DisplayFor(model =>model.EndDate.Humanize())
but editor shows error like:
an expression tree may not contain a call or invocation that uses
optional arguments
Html.DisplayFor is a templated helper, which just means it returns the value of the model expression using a template. The default template is simply calling ToString() on the property referenced by the model expression. As such, what you pass into it must be a model expression referencing a particular property; you cannot do something like call Humanize on it.
However, you can define your own template. This entails creating a view in Views\Shared\DisplayTemplates, which conforms to one of these naming conventions:
It's named after the type it should be used for, e.g. DateTime.cshtml will be applied to any property that is of type DateTime.
It's named after one of the members of the DataType enum, in which case, it's utilized when that DataType is applied to a particular property, e.g. Date.cshtml will be utilized when you apply the attribute [DataType(DataType.Date)].
It's named whatever you like, but that name is explicitly specified for the property using the UIHint attribute, e.g. if you apply an attribute like [UIHint("MyAwesomeDateTime")] and associated MyAwesomeDateTime.cshtml view will be used.
As such, if you were to create a view like Views\Shared\DisplayTemplates\DateTime.cshtml with the contents:
#model DateTime
#Model.Humanize()
Then, simply calling #Html.DisplayFor(m => m.EndDate) will return the humanized date you're looking for. Since EndDate is a DateTime, DisplayFor will utilize your DateTime.cshtml template, which outputs the model (your DateTime with Humanized chained.
An alternative way to specify a display template is to pass it in directly. This is useful when you have a one-off situation and you don't want the template to apply to everything of a particular type. For example, if you just wanted EndDate humanized, but other dates to display as normal, that could be achieved by doing something like:
#Html.DisplayFor(m => m.EndDate, "HumanizedDate")
You would then of course need an associated HumanizedDate.cshtml. You can also employ UIHint on your property as described above here, if you'd prefer to keep this out of the view, and on your model instead.
All that said, display templates are best utilized when there's complex constructions involved. As Stephen pointed out in the comments below your question, you could easily just do: #Model.EndDate.Humanize(), which not only is more terse and explicit than #Html.DisplayFor(m => m.EndDate), but also doesn't require adding custom views or attributes to your model properties.

What is the name rule of chainer.reporter.report's key?

chainer's document is very good, but I found every page in the document, I didn't found what is name rule of chainer report, How should I control the report name, and log it?
For example, the follow code:
trainer.extend(chainer.training.extensions.PrintReport(
['iteration', 'epoch', 'elapsed_time', 'lr',
'main/loss',
'validation/main/all',
]), trigger=print_interval)
Notice that main/loss and validation/main/all, why is there a main before /loss, How should I control to report loss? Also notice the validation/main/all.same question.
The prefix main is the name of the optimizer (and its target link) used in the updater you are using; StandardUpdater and other built-in updaters use the name main as the default name of the optimizer. If you are using one of the built-in updaters as is, this is always main unless you specify a special name. If you are using a customized updater that uses multiple optimizers, the custom updater assigns names to individual optimizers, which will be used as the prefix of items reported inside of the target link of the optimizer.
The prefix validation is the name of Evaluator extension. When you register an Evaluator with trainer.extend(), you can optionally pass name argument to override this prefix. For example, if you want to use multiple Evaluator objects each of which measures different things, you have to pass different names, which will be used as the prefix in the reported values.
As of the current version (v2.0.2), the naming rule of typical reported values are summarized in the document of chainer.report.

Multiple "default" properties/methods in a VB6 class?

I am trying to make a replacement VB6 class for the Scripting.Dictionary class from SCRRUN.DLL. Scripting.Dictionary has (among other things) a "Keys" method that returns an array of keys, and a read/write "Item" property that returns the item associated with a key. I am confused about this, because both of them seem to be defaults for the class. That is:
For Each X In MyDict
Is equivalent to:
For Each X In MyDict.Keys
Which to me implies that "Keys" is the default operation for the class, but:
MyDict("MyKey") = "MyValue"
MsgBox MyDict("MyKey")
Is equivalent to:
MyDict.Item("MyKey") = "MyValue"
MsgBox MyDict.Item("MyKey")
Which to me implies that "Item" is the default operation for the class.
I've never before created a VB6 class that had a default operation, so upon realizing this, I thought perhaps I could define multiple default operations as long as they all have different signatures, which they do: Keys is nullary, the Item getter takes a Variant, and the Item setter takes two Variants. But this doesn't seem to be allowed: When I use "Tools/Procedure Attributes" to set the Keys function to be the default, and then I use it to set the Item property to be the default, the IDE complains that a default has already been set.
So I think I'm misunderstanding something fundamental here. What is going on in the Scripting.Dictionary object that makes it able to act as if "Keys" is the default in some contexts, but as if "Item" is the default in others? And whatever it is, can I accomplish the same thing in VB6?
OK, answering my own question: I haven't tried this yet, but I gather that "Item" should be made the default, and that I should add an entirely new function called "NewEnum" that looks something like the following (slightly modified from an example in Francesco Balena's "Programming Microsoft Visual Basic 6.0" book):
Public Function NewEnum() As IUnknown
Set NewEnum = m_Keys.[_NewEnum]
End Function
(where "m_Keys" is a Collection containing the keys), and then use Tools/Procedure Attributes to hide NewEnum and to set its ProcID to -4.
What you are observing is the difference between the default member and a collection enumerator. A COM object (including VB6 classes) can have both.
You can identify the default property of a class by looking in the Object Browser for the tiny blue globe or the words "default member of" in the description (see Contents of the Object Browser). The Object Browser will not identify an enumerator method, but if you look at the class's interface definition using OLE View or TypeLib Browser (free but registration required) it's DispId will be 0xfffffffc or -4.
In your own class, you can mark the default property by setting the Procedure ID to "(default)" in the Procedure Attributes dialog (see Making a Property or Method the Default). You already listed the steps for setting up the collection enumerator in your own answer, but you can find this listed as well in the Programmer's Guide topic Creating Your Own Collection Class: The House of Bricks.
Scripting.Dictionary has a dirty secret:
It does not handle enumeration at all, it returns big ugly Variant arrays and your For Each loops iterate over those.
This is one of the reasons why a Dictionary can actually be far less efficient than a standard VB6 Collection.

maps as anonymous struct members

I was stumbling over some behavior in go which I cannot make sense of completely and explainations of any kind would be wellcome:
type Test struct{
Name string // or other metadata to be stored along the core map element
map[string]string
}
The above code will fail to compile with an unexpected map error.
Which is probably because struct Field delarations must be types, however I fail to appriciate why map[string]string is not a type.
Changing it to
type Embedded map[string]string
type Test struct{
Name string
Embedded
}
get's arround the compiler error, but still Test["someKey"] raises the compiler error
invalid operation: Test["someKey"] (index of type Test).
Of course adressing the anoymous field directly with Test.Embedded["someKey"] works,
but my questions are:
Why are literal map declarations valid as types in non-anonymous field declarations but not valid in anonymous fields
Why does indexing the containing type not work? Why can't it work?
Thanks for clarifications.
Anonymous fields must be named types only. You're perhaps somewhat confusing Type, LiteralType and TypeName.
Referring to an anonymous field is presribed by the specs to be done always by its type name. Thus Test.Embedded[key] is the only legal form. Here you might be confusing the embedded field methods, which are inherited from embedded fields w/o need to use the field name and the field value, which must use it.

Setting field defaults on programmatically created Dexterity items

I have a Dexterity content type based on plone.directives.form.Schema which has a number of form hints for assigning defaults:
#form.default_value(field=ITrial['start_on'])
def default_start_on(data):
return datetime.now()
Some of the defaults are more complex, passing back objects that are themselves instances of Dexterity types. These objects are essential for the main type's setup, which is triggered by various events.
I'm now in the process of testing. Ideally, I'd like to be able to use something like:
item = createContentInContainer(folder, 'ctcc.model.trial', 'item')
That is, I'd like the defaults to be picked up by the item without having to be manually passed into the constructor.
If I was using zope.schema I could use FieldProperty to set up proxies to the schema fields. Is there something equivalent for Dexterity, or perhaps a function for pushing an object through form creation?
Solution: I ended up going with David's option #1, intercepting ObjectCreatedEvent.
#grok.subscribe(ITrial, IObjectCreatedEvent)
def create_trial(trial, event):
if getattr(trial, 'start_on', None) is None:
trial.start_on = default_start_on(None)
It stills feels like I'm replicating part of form behaviour, but at least it's using the same functions that are providing the form defaults.
As you've discovered, the #form.default_value decorator is respected by z3c.form forms, but not when items are created in other ways. You have several options:
Write a handler for the ObjectCreatedEvent for your content type which sets up the necessary default values. This is the simplest approach to implement, but may not work if there are other handlers of this event that need the values in place.
Create your own subclass of Dexterity's generic Item class, and use it instead of Item as the basis for your content type. Then you can customize the __init__ method to set whatever you want. This would require migration of existing content items though, if you already have some.
This is a more complicated option. Replace the factory utility used to construct the content type. createContentInContainer ends up looking for an IFactory utility with a name equal to the factory attribute of the content type's FTI. The default implementation is in plone.dexterity.factory but you could replace it with a different one that does more.

Resources