Is clojure.spec check generating bad input? - testing

Using clojure.spec (org.clojure/clojurescript {:mvn/version "1.10.520"}), I have a function spec that specifies a map for its input.
gen/generate and gen/sample work fine. But calling cljs.spec.test.alpha/check errors with input that should be a map, but is passed a collection (Error: More than one element found in structure). Ie, it looks like the spec system is generating bad input.
Is this a bug with spec?
bar spec
(s/def ::check-run
(s/keys
:req-un
[::action
::check_run
::installation
::organization
::repository
::sender]))
foo.cljs
(s/def ::payload :bar/check-run)
(s/def ::check-run-started (s/keys :req-un [::payload]))
(s/fdef check-run->cijob-created
:args (s/cat :arg ::check-run-started))
(defn check-run->cijob-created [arg])
While the function spec only declares A, the spec system is generating B.
;; A
{:payload {:action "", :check_run {:html_url "", }}, ...}
;; B
[({:payload {:action "", :check_run {:html_url "", }}, ...}})]
workbench
(cljs.spec.test.alpha/check
`foo/check-run->cijob-created
{:clojure.spec.test.check/opts {:num-tests 10}})
[{:spec #object[cljs.spec.alpha.t_cljs$spec$alpha50916],
:clojure.spec.test.check/ret
{:shrunk
{:total-nodes-visited 313, :depth 148, :pass? false, :result #object[Error Error: More than one element found in structure: 0], :result-data #:clojure.test.check.properties{:error #object[Error Error: More than one element found in structure: 0]}, :time-shrinking-ms 11299,
:smallest
[({:payload {:action "", :check_run {:html_url "", }}, ...}})]},
:sym foo/check-run->cijob-created,
:failure #object[Error Error: More than one element found in structure: 0]}]
[1]: https://clojure.org/about/spec

Ok, figured this one out. It was failing due to my use of a specter macro (with navigators). I’m not sure how. But somehow this messes up test.check generators. I’m assuming it’s some kind of strange interplay that’s unworkable with Clojurescript’s macro system.
Anyways, migrating to a simpler get-in fixed the problem.

Related

Proper way to convert Data type of a field in MongoDB

Possible Replication of How to change the type of a field?
I am currently newly learning MongoDB and I am facing problem while converting Data type of field value to another data type.
Below is an example of my document
[
{
"Name of Restaurant": "Briyani Center",
"Address": " 336 & 338, Main Road",
"Location": "XYZQWE",
"PriceFor2": "500.0",
"Dining Rating": "4.3",
"Dining Rating Count": "1500",
},
{
"Name of Restaurant": "Veggie Conner",
"Address": " New 14, Old 11/3Q, Railway Station Road",
"Location": "ABCDEF",
"PriceFor2": "1000.0",
"Dining Rating": "4.4",
}]
Like above I have 12k documents. Notice the datatype of PriceFor2 is a string. I would like to convert the data type to Integer data type.
I have referred many amazing answers given in the above link. But when I try to run the query, I get .save() is not a function error. Please advice what is the problem.
Below is the code I used
db.chennaiData.find().forEach( function(x){ x.priceFor2= new NumberInt(x.priceFor2);
db.chennaiData.save(x);
db.chennaiData.save(x);});
This is the error I am getting..
TypeError: db.chennaiData.save is not a function
From MongoDB's save documentation:
Starting in MongoDB 4.2, the
db.collection.save()
method is deprecated. Use db.collection.insertOne() or db.collection.replaceOne() instead.
Likely you are having a MongoDB with version 4.2+, so the save function is no longer available. Consider migrate to the usage of insertOne and replaceOne as suggested.
For your specific scenario, it is actually preferred to do with a single update as mentioned in another SO answer. It only does one db call(while your approach fetches all documents in the collection to the application level) and performs n db call to save them back.
db.collection.update({},
[
{
$set: {
PriceFor2: {
$toDouble: "$PriceFor2"
}
}
}
],
{
multi: true
})
Mongo Playground

Google Docs API for creating invoice containing table of variable number of rows

I have a template file for my invoice with a table with sample row, but I want to add more rows dynamically based on a given array size, and write the cell values from the array...
Template's photo
I've been struggling for almost 3 days now.
Is there any easy way to accomplish that?
Here's the template file: Link to the Docs file(template)
And here's a few sample arrays of input data to be replaced in the Template file:
[
[
"Sample item 1s",
"Sample Quantity 1",
"Sample price 1",
"Sample total 1"
],
[
"Sample item 2",
"Sample Quantity 2",
"Sample price 2",
"Sample total 2"
],
[
"Sample item 3",
"Sample Quantity 3",
"Sample price 3",
"Sample total 3"
],
]
Now, the length of the parent array can vary depending on the number of items in the invoice, and that's the only problem that I'm struggling with.
And... Yeah, this is a duplicate question, I've found another question on the same topic, but looking at the answers and comments, everyone is commenting that they don't understand the question whereas it looks perfectly clear for me.
Google Docs Invoice template with dynamically items row from Google Sheets
I think the person who asked the question have already quit from it. :(
By the way I am using the API for PHP (Google API Client Library for PHP), and code for replacing dummy text a Google Docs Document by the actual data is given below:
public function replaceTexts(array $replacements, string $document_id) {
# code...
$req = new Docs\BatchUpdateDocumentRequest();
// var_dump($replacements);
// die();
foreach ($replacements as $replacement) {
$target = new Docs\SubstringMatchCriteria();
$target->text = "{{" . $replacement["targetText"] . "}}";
$target->setMatchCase(false);
$req->setRequests([
...$req->getRequests(),
new Docs\Request([
"replaceAllText" => [
"replaceText" => $replacement["newText"],
"containsText" => $target
]
]),
]);
}
return $this->docs_service->documents->batchUpdate(
$document_id,
$req
);
}
A possible solution would be the following
First prep the document by removing every row from the table apart from the title.
Get the full document tree from the Google Docs API.
This would be a simple call with the document id
$doc = $service->documents->get($documentId);
Traverse the document object returned to get to the table and then find the location of the right cell. This could be done by looping through the elements in the body object until one with the right table field is found. Note that this may not necessarily be the first one since in your template, the section with the {{CustomerName}} placeholder is also a table. So you may have to find a table that has the first cell with a text value of "Item".
Add a new row to the table. This is done by creating a request with the shape:
[
'insertTableRow' => [
'tableCellLocation' => [
'rowIndex' => 1,
'columnIndex' => 1,
'tableStartLocation' => [
'index' => 177
]
]
]
]
The tableStartLocation->index element is the paragraph index of the cell to be entered, i.e. body->content[i]->table->startIndex. Send the request.
Repeat steps 2 and 3 to get the updated $doc object, and then access the newly created cell i.e. body->content[i]->table->tableRows[j]->tableCells[k]->content->paragraph->elements[l]->startIndex.
Send a request to update the text content of the cell at the location of the startIndex from 5 above, i.e.
[
'insertText' => [
'location' => [
'index' => 206,
]
],
'text' => 'item_1'
]
]
Repeat step 5 but access the next cell. Note that after each update you need to fetch an updated version of the document object because the indexes change after inserts.
To be honest, this approach is pretty cumbersome, and it's probably more efficient to insert all the data into a spreadsheet and then embed the spreadsheet into your word document. Information on that can be found here How to insert an embedded sheet via Google Docs API?.
As a final note, I created a copy of your template and used the "Try this method" feature in the API documentation to validate my approach so some of the PHP syntax may be a bit off, but I hope you get the general idea.

rasa nlu ner_crf not extracting any entities

I have successfully got my code to detect the correct intent but no entities appear even though I provided some entities in my training data.
data.json:
{ “common_examples”: [
{ “text”:“Hello”,
“intent”:“greeting”,
“entities”:[] },
{ “text”:“Hi”,
“intent”:“greeting”,
“entities”:[] },
{ “text”:“I want a recipe for my lunch”,
“intent”:“get_recipe”,
“entities”:[
{ “start”:22,
“end”: 28,
“value”: “lunch”,
“entity”: “mealtime” }
]
},
{ “text”:“Can you give me a recipe for dinner tonight?”,
“intent”:“get_recipe”,
“entities”:[
{ “start”:29,
“end”:35,
“value”: “dinner”,
“entity”: “mealtime” }
]
},
{ “text”:“I don’t know what to have for lunch”,
“intent”:“get_recipe”,
“entities”:[
{ “start”:31,
“end”: 35,
“value”: “lunch”,
“entity”: “mealtime” }
]
}
},
}
],
"regex_features": [],
"entity_synonyms":[]
}
}
This is just a snippet. I have created 15 examples in total for the get_recipe intent. I just need it to pick out the entity of ‘mealtime’ from the message put to the bot.
My config.yml is as follows:
language: “en”
pipeline:
-name: “nlp_spacy”
-name: “tokenizer_spacy”
-name: “intent_entity_featurizer_regex”
-name: “intent_featurizer_spacy”
-name: “ner_crf”
-name: “ner_synonyms”
-name: “intent_featurizer_count_vectors”
-name: “intent_classifier_tensorflow_embedding”
and this is the code I run to train the bot:
from rasa_nlu.training_data import load_data
from rasa_nlu.model import Trainer
from rasa_nlu import config
from rasa_nlu.model import Interpreter
def train_bot(data_json,config_file,model_dir):
training_data = load_data(data_json)
trainer = Trainer(config.load(config_file))
trainer.train(training_data)
model_directory=trainer.persist(model_dir,fixed_model_name=‘vegabot’)
This runs fine.
And the code I run to predict the intent:
def predict_intent(text):
interpreter = Interpreter.load(‘models/nlu/default/vegabot’)
print(interpreter.parse(text))
Which produces the result:
{‘intent’: {‘name’: ‘get_recipe’, ‘confidence’: 0.9701309204101562}, ‘entities’: [], ‘intent_ranking’: [{‘name’: ‘get_recipe’, ‘confidence’: 0.9701309204101562}, {‘name’: ‘greeting’, ‘confidence’: 0.03588612377643585}], ‘text’: ‘can you find me a recipe for dinner’}
As you can see the intent is correct but entities is blank [] and I can’t figure out why. I don't seem to be getting any errors. Everything runs okay apart from this!
I also ran an evaluation and got:
- intent examples: 12 (2 distinct intents)
- Found intents: ‘greeting’, ‘get_recipe’
- entity examples: 10 (1 distinct entities)
- found entities: ‘mealtime’ which all looks fine.
So obviously it knows to look out for the mealtime entity but why isn't it picking it up from my test messages?
e.g. I need a recipe for lunch, Can you give me a dinner time recipe? etc
I’m using RASA NLU version 0.14.
Any help would be greatly appreciated. Thank you.
The machine learning models in Rasa need a bit of data to train. As correctly suggested in the comments, you have to give the conditional random field a couple of examples, so that it is actually able to generalize. Also make sure to vary the sentences around it, otherwise crf will not generalize to other contexts.

understand azure search charFilters mapping

I create my index with following custom analyzer
"analyzers":[
{
"name":"shinglewhite_analyzer",
"#odata.type":"#Microsoft.Azure.Search.CustomAnalyzer",
"charFilters":[
"map_dash"
],
"tokenizer":"whitespace",
"tokenFilters":[
"shingle"
]
}
],
"charFilters":[
{
"name":"map_dash",
"#odata.type":"#Microsoft.Azure.Search.MappingCharFilter",
"mappings":[ "_=> " ]
}
]
The problem is that word like ice_cream from input will not match query ice cream, it matches icecream though. Can someone help me understand how this works and if I have done something wrong?
Also we'd like query "ice cream" to match "ice cream", "icecream" and "ice and cream" but favor those in order.
in order to map to a space please use the following notation (we'll update the docs to include this information):
{
"name":"map_dash",
"#odata.type":"#Microsoft.Azure.Search.MappingCharFilter",
"mappings":[ "_=>\\u0020" ]
}
Also, by default the shingle token filter separates tokens with a space. If you want to join subsequent tokens into one without a separator you need to customize your filter like in the following example:
{
"name": "my_shingle",
"#odata.type":"#Microsoft.Azure.Search.ShingleTokenFilter",
"tokenSeparator": ""
}
With those two changes for token ice_cream your analyzer will generate: ice, icecream, cream.
I hope that helps

Possible to use angular-datatables with serverside array sourced data instead of object sourced data

I'm trying to use angular-datatables with serverside processing. However, it seems that angular-datatables expects that the data from the server is in object format (object vs array data described) with column names preceding each table datapoint. I'd like to configure angular-datatables to accept array based data since I can't modify my server side output which only outputs data in array format.
I'm configuring Datatables in my javascript like so:
var vm = this;
vm.dtOptions = DTOptionsBuilder.newOptions()
.withOption('ajax', {
url: 'output/ss_results/' + $routeParams.uuid,
type: 'GET'
})
.withDataProp('data')
.withOption('processing', true)
.withOption('serverSide', true);
My data from the server looks like this in array format:
var data = [
[
"Tiger Nixon",
"System Architect",
"$3,120"
],
[
"Garrett Winters",
"Director",
"$5,300"
]
]
But as far as I can tell, angular-datatables is expecting the data in object format like so:
[
{
"name": "Tiger Nixon",
"position": "System Architect",
"extn": "5421"
},
{
"name": "Garrett Winters",
"position": "Director",
"extn": "8422"
}
]
I tried not defining dtColumns or setting it to an empty array like vm.dtColumns = []; but I get an error message when I do that. When I configure dtColumns with a promise to load the column data via ajax I get datatables error #4 because it can't find the column name preceding my table datapoints in the data retrieved from the server.
Is it possible to configure angular-datatables to accept array based data? I can't find anything on the angular-datatables website that indicates it can be configured this way.
Edit: So I removed the .withDataProp('data') which I think was causing the problem. The table works a little better now but it's still broken. After it loads, I get the message No matching records found. Even though right below it it says Showing 1 to 10 of 60,349 entries
Previous1…456…6035Next Does anyone know why this might be?
If you want to use an array of arrays instead of an array of objects, simply refer to the array indexes instead of the object names :
$scope.dtColumns = [
DTColumnBuilder.newColumn(0).withTitle('Name'),
DTColumnBuilder.newColumn(1).withTitle('Position'),
DTColumnBuilder.newColumn(2).withTitle('Office'),
DTColumnBuilder.newColumn(3).withTitle('Start date'),
DTColumnBuilder.newColumn(4).withTitle('Salary')
]
demo using the famous "Tiger Nixon" array loaded via AJAX -> http://plnkr.co/edit/16UoRqF5hvg2YpvAP8J3?p=preview