How to specify an example for an object type in api-blueprint - apiblueprint

Is it possible to specify an example value for 'bar' in type Baz in the following data structure?
# Data Structures
## Foo (object)
+ arg0 (number, required) - the arg0
+ arg1 (number, optional) - the arg1
+ arg2: a, b, c (enum, required) - the arg2
## Baz (object)
+ bar (Foo, required)
Thanks in advance
--Ulrich

You should be able to provide an example by specifying each property of the complex object, something like this:
+ bar (Foo, required)
+ Sample
+ (object)
+ arg0: 1
+ arg1: 2

Related

using construct_undefined in ruamel from_yaml

I'm creating a custom yaml tag MyTag. It can contain any given valid yaml - map, scalar, anchor, sequence etc.
How do I implement class MyTag to model this tag so that ruamel parses the contents of a !mytag in exactly the same way as it would parse any given yaml? The MyTag instance just stores whatever the parsed result of the yaml contents is.
The following code works, and the asserts should should demonstrate exactly what it should do and they all pass.
But I'm not sure if it's working for the right reasons. . . Specifically in the from_yaml class method, is using commented_obj = constructor.construct_undefined(node) a recommended way of achieving this, and is consuming 1 and only 1 from the yielded generator correct? It's not just working by accident?
Should I instead be using something like construct_object, or construct_map or. . .? The examples I've been able to find tend to know what type it is constructing, so would either use construct_map or construct_sequence to pick which type of object to construct. In this case I effectively want to piggy-back of the usual/standard ruamel parsing for whatever unknown type there might be in there, and just store it in its own type.
import ruamel.yaml
from ruamel.yaml.comments import CommentedMap, CommentedSeq, TaggedScalar
class MyTag():
yaml_tag = '!mytag'
def __init__(self, value):
self.value = value
#classmethod
def from_yaml(cls, constructor, node):
commented_obj = constructor.construct_undefined(node)
flag = False
for data in commented_obj:
if flag:
raise AssertionError('should only be 1 thing in generator??')
flag = True
return cls(data)
with open('mytag-sample.yaml') as yaml_file:
yaml_parser = ruamel.yaml.YAML()
yaml_parser.register_class(MyTag)
yaml = yaml_parser.load(yaml_file)
custom_tag_with_list = yaml['root'][0]['arb']['k2']
assert type(custom_tag_with_list) is MyTag
assert type(custom_tag_with_list.value) is CommentedSeq
print(custom_tag_with_list.value)
standard_list = yaml['root'][0]['arb']['k3']
assert type(standard_list) is CommentedSeq
assert standard_list == custom_tag_with_list.value
custom_tag_with_map = yaml['root'][1]['arb']
assert type(custom_tag_with_map) is MyTag
assert type(custom_tag_with_map.value) is CommentedMap
print(custom_tag_with_map.value)
standard_map = yaml['root'][1]['arb_no_tag']
assert type(standard_map) is CommentedMap
assert standard_map == custom_tag_with_map.value
custom_tag_scalar = yaml['root'][2]
assert type(custom_tag_scalar) is MyTag
assert type(custom_tag_scalar.value) is TaggedScalar
standard_tag_scalar = yaml['root'][3]
assert type(standard_tag_scalar) is str
assert standard_tag_scalar == str(custom_tag_scalar.value)
And some sample yaml:
root:
- item: blah
arb:
k1: v1
k2: !mytag
- one
- two
- three-k1: three-v1
three-k2: three-v2
three-k3: 123 # arb comment
three-k4:
- a
- b
- True
k3:
- one
- two
- three-k1: three-v1
three-k2: three-v2
three-k3: 123 # arb comment
three-k4:
- a
- b
- True
- item: argh
arb: !mytag
k1: v1
k2: 123
# blah line 1
# blah line 2
k3:
k31: v31
k32:
- False
- string here
- 321
arb_no_tag:
k1: v1
k2: 123
# blah line 1
# blah line 2
k3:
k31: v31
k32:
- False
- string here
- 321
- !mytag plain scalar
- plain scalar
- item: no comment
arb:
- one1
- two2
In YAML you can have anchors and aliases, and it is perfectly fine to have an object be a child of itself (using an alias). If you want to dump the Python data structure data:
data = [1, 2, 4, dict(a=42)]
data[3]['b'] = data
it dumps to:
&id001
- 1
- 2
- 4
- a: 42
b: *id001
and for that anchors and aliases are necessary.
When loading such a construct, ruamel.yaml recurses into the nested data structures, but if the toplevel node has not caused a real object to be constructed to which the anchor can be made a reference, the recursive leaf cannot resolve the alias.
To solve that, a generator is used, except for scalar values. It first creates an empty object, then recurses and updates it values. In code calling the constructor a check is made to see if a generator is returned, and in that case next() is done on the data, and potential self-recursion "resolved".
Because you call construct_undefined(), you always get a generator. Practically that method could return a value if it detects a scalar node (which of course cannot recurse), but it doesn't. If it would, your code could then not load the following YAML document:
!mytag 1
without modifications that test if you get a generator or not, as is done in the code in ruamel.yaml calling the various constructors so it can handle both construct_undefined and e.g. construct_yaml_int (which is not a generator).

Entering data into input <Selenium | Watir Ruby>

I would like to enter text in the search engine field of the website. I can select input correctly. However, an error occurs when trying to use:
*undefined method `set 'for # Watir :: Input: 0x000055c93c73b850> *
Code:
sleep 1
advencedSearch = # browser.div (: class => "search")
advencedSearch.a.click ()
sleep 1
productSearch = # browser.div (: class => "filter")
productSearch.input.click ()
productSearch.input (: placeholder => "Name or code").set('hi')```
The Watir::Input is a generic class for all input elements. Typically (always?) you want to work with the type specific classes - eg Watir::TextField. These specific classes are where methods like #set will be available.
Try using #text_field instead of #input:
productSearch.text_field(: placeholder => "Name or code").set('hi')

Mix Request/Response Body and Data Structures

I would like use aglio/api blueprint to create a nice documentation for our new API.
The JSON might be quite big (with lots of optional values), so I'd like to give a proper use case in the body, but also use data structures for the json schema.
However, whenever the schema fits exactly the body, the resulting HTML throws "Hello, world!"s at me, since I didn't fill in the example data - but since I've got a complete and valid example in the body, I wouldn't have expected aglio to create Hello World output.
For reference, that's what I would expect in the resulting htmls body to appear:
{
"a": "i want this to appear",
"b": "in my aglio",
"c": "html file"
}
This is what actually does appear:
{
"a": "Hello, world!",
"b": "Hello, world!",
"c": "Hello, world!",
"d": "Hello, world!"
}
And that's the raw api blueprint:
FORMAT: 1A
# JSON Schema
# Test [/post/something]
## A Test [POST]
+ Request (application/json)
+ Attributes (SomeObject)
+ Body
{
"a": "i want this to appear",
"b": "in my aglio",
"c": "html file"
}
+ Response 200
# Data Structures
## SomeObject (object)
+ a (string) - A
+ b (string) - B
+ c (string) - C
+ d (string, optional) - I'm optional, yet don't want to appear in the html, only the schema
So, first: is that a valid way to do things? Would you recommend a different approach? Is this a bug in aglio, because in apiary it works as I intend it to?
Thanks!
Found the corresponding github issue, looks like nothing's wrong with my description.
https://github.com/danielgtaylor/aglio/issues/221
You can do the following
FORMAT: 1A
# JSON Schema
# Test [/post/something]
JSON Schema Title
## A Test [POST]
+ Request (application/json)
+ Attributes (object)
+ a a-value (string, required) - description about a
+ b b-value (number, required) - description about b
+ c c-value (string, required) - description about c
+ d [a1, a2, a3] (array, optional) - I'm optional
+ Response 200 (application/json)
{
"message": "this works"
}
a a-value (string, required) - description
In above line "a" --> attribute name, "a-value" --> appears in body, "(string, required)" --> for schema generation, "description"--> schema attribute description

sorting a nested list by both members of an element

I have a nested list in which I want to sort by the inner and outer elements. I have looked at other solutions on stackoverflow and tried several but none of them work the way I want them to. Below, I've presented four attempts that don't work. The comments for each block of code speak for themselves as to what I'm doing and what I want to accomplish.
from operator import itemgetter
# a representation of my real data to be sorted
list_1 = [['key_e', ['v4eee', 'v1eee', 'v3eee', 'v2eee']], ['key_d', ['v4ddd', 'v1ddd', 'v3ddd', 'v2ddd']], ['key_a', ['v4aaa', 'v1aaa', 'v3aaa', 'v2aaa']], ['key_c', ['v4ccc', 'v1ccc', 'v3ccc', 'v2ccc']], ['key_b', ['v4bbb', 'v1bbb', 'v3bbb', 'v2bbb']]]
"""
# same data as above but formatted for readability
list_1 =
[
['key_e', ['v4eee', 'v1eee', 'v3eee', 'v2eee']],
['key_d', ['v4ddd', 'v1ddd', 'v3ddd', 'v2ddd']],
['key_a', ['v4aaa', 'v1aaa', 'v3aaa', 'v2aaa']],
['key_c', ['v4ccc', 'v1ccc', 'v3ccc', 'v2ccc']],
['key_b', ['v4bbb', 'v1bbb', 'v3bbb', 'v2bbb']]
]
"""
# when running the code, pick 1 of the 4 below sort methods and comment out the other 3
# sort method #1 that doesn't work the way I want it to
list_1.sort(key = lambda x: x[1])
list_1.sort(key = itemgetter(0))
"""
# sort method #2 that doesn't work the way I want it to
list_1 = sorted(list_1, key = lambda x: (x[0], x[1]))
"""
"""
# sort method #3 that doesn't work the way I want it to
list_1.sort(key = itemgetter(1))
list_1.sort(key = itemgetter(0))
"""
"""
# sort method #4 that doesn't work the way I want it to
list_1.sort(key = itemgetter(0, 1))
"""
# print the sorted data
for d in list_1:
print d[0] + ',' + d[1][0] + ',' + d[1][1] + ',' + d[1][2] + ',' + d[1][3] + '\r\n'
"""
# what I get using any of the sort methods
key_a,v4aaa,v1aaa,v3aaa,v2aaa
key_b,v4bbb,v1bbb,v3bbb,v2bbb
key_c,v4ccc,v1ccc,v3ccc,v2ccc
key_d,v4ddd,v1ddd,v3ddd,v2ddd
key_e,v4eee,v1eee,v3eee,v2eee
# what I want
key_a,v1aaa,v2aaa,v3aaa,v4aaa
key_b,v1bbb,v2bbb,v3bbb,v4bbb
key_c,v1ccc,v2ccc,v3ccc,v4ccc
key_d,v1ddd,v2ddd,v3ddd,v4ddd
key_e,v1eee,v2eee,v3eee,v4eee
"""
I think you want the sub-lists to be sorted, and the outer list to be sorted. In which case, do it in two steps:
sorted_inner = [[k, sorted(l)] for k, l in list_1]
sorted_outer = sorted(sorted_inner)
This gives me:
sorted_outer == [['key_a', ['v1aaa', 'v2aaa', 'v3aaa', 'v4aaa']],
['key_b', ['v1bbb', 'v2bbb', 'v3bbb', 'v4bbb']],
['key_c', ['v1ccc', 'v2ccc', 'v3ccc', 'v4ccc']],
['key_d', ['v1ddd', 'v2ddd', 'v3ddd', 'v4ddd']],
['key_e', ['v1eee', 'v2eee', 'v3eee', 'v4eee']]]

How to calculate a formula with undefined variable

I am trying to eval a string with undefined variable. For example: Formula = 2 * 3 + a The result should return a string of 6 + a. Can the eval method do something like that? Or, can you give me some ideas on how to do this?
Update: Thank you for all the inputs. I guess this is not as simple as i thought it would be. Let's say if I don't need to simplify the formula and all i need to do is to replace the variable with value in string?
Example:
a = { "Bob" => 82,
"Jim" => 94,
"Billy" => 58, ........ and more}
How do I convert this string
"2 * 3 + a["Bob"] * b"
to this: "2 * 3 + 82 * b"
Thanks again for your help.
What you are trying to do is complicated, and I don't think it is worth doing it.
You can use some gem to parse the string into a tree of tokens. Then, look for any node under which there is no undefined variable, and replace the node with the calculated value. After doing that, put the tree back to a string.
What about using something like Parslet and making a parsing expression grammar to simplify your expressions? Look at the get started page where you are walked through a simple example in which Parslet reduces integer expressions.
Here is a naïve solution:
str = "+ 1 * 2 - 3 / 2 + b - a"
terms = str.gsub(/^[^+-]+|[+-][^+-]+/).to_a
=> ["+ 1 * 2 ",
"- 3 ",
"+ b ",
"- a"]
numbers, variables = terms.partition { |exp| eval(exp.to_s) rescue false }
=> [["+ 1 * 2 ", "- 3 "],
["+ b ", "- a"]]
numbers.map! { |exp| exp.gsub(/\d+/, &:to_f) }
=> ["+ 1.0 * 2.0 ",
"- 3.0 / 2.0 "]
numbers.map! { |exp| eval(exp) }
=> [2.0, -1.5]
sum = numbers.reduce(:+)
=> "0.5"
result = "#{sum} #{variables.join}"
=> "0.5 + b - a"

Resources