I´m developing a project (Angularjs for the front, FastAPI and MongoDB for the back) about Practical Cases and I've come across the following issue: when I try to use the get method to retreive all the cases the following error appears:
pydantic.error_wrappers.ValidationError: 1 validation error for Case
response -> 0 -> id
str type expected (type=type_error.str)
My data models are as follows:
from typing import Optional, List
from pydantic import BaseModel
class Answer(BaseModel):
id: str
description: str
required: bool
value: int
class SubOption(BaseModel):
id: str
description: str
answer: Answer
class Option(BaseModel):
id: str
description: str
suboption: Optional[List[SubOption]]
answer: Answer
class SubMenu(BaseModel):
id: str
description: str
option: List[Option]
class Menu(BaseModel):
id: str
description: str
submenu: List[SubMenu]
class Case(BaseModel):
id: str
description: str
menu: List[Menu]
The methods:
def practicalCase(case) -> dict:
return{
"id": case["_id"],
"description": case["description"],
"menu": case["menu"]
}
def listCases(entity) -> list:
return [clinicalCase(case) for case in entity]
And the CRUD operations:
#case.get('/cases', response_model=list[Case], tags=["case"])
async def all_cases():
return listCases(ven.local.cases.find())
#case.post('/newcases', response_model=Case, tags=["case"])
async def new_case(case: Case):
case_new = dict(case)
del case_new["id"]
json_compatible_item_data = jsonable_encoder(case_new)
id = ven.local.cases.insert_one(json_compatible_item_data).inserted_id
case = ven.local.cases.find_one({"_id": id})
ven.local.cases.find_one({"_id": id})
I´ve tried many different things, from adjusting the data models using Field(...) to trying to apend the menu dict to the case dict, but to no aveil.
Any kind of help/hint would be welcome. Thanks in advance
This doesn't make any sense:
def practicalCase(case) -> dict:
return{
"id": menu["id"],
"description": menu["description"],
"submenu": menu["submenu"]
}
def listCases(entity) -> list:
return [clinicalCase(case) for case in entity]
The parameter case is never used in practicalCase, but you use variable name menu? The same goes voor listCases(), where you expect a parameter with name entity but are referencing case.
Secondly, this:
class Case(BaseModel):
id: str
description: str
menu: List[Menu]
expects an id of type str, while I am betting that you are using int? It's impossible to tell for sure though.
Related
Trying to store incomming data into mongo using r2d2-mongodb and actix_web.
#[derive(Serialize, Deserialize, Debug)]
struct Weight {
desc: String,
grams: u32,
}
fn store_weights(weights: web::Json<Vec<Weight>>, db: web::Data<Pool<MongodbConnectionManager>>) -> Result<String> {
let conn = db.get().unwrap();
let coll = conn.collection("weights");
for weight in weights.iter() {
coll.insert_one(weight.into(), None).unwrap();
}
Ok(String::from("ok"))
}
I can't seem to understand what/how I need to convert weight into to use with insert_one.
The above code errors into error[E0277]: the trait bound 'bson::ordered::OrderedDocument: std::convert::From<&api::weight::Weight>' is not satisfied
The signature for insert_one is:
pub fn insert_one(
&self,
doc: Document,
options: impl Into<Option<InsertOneOptions>>
) -> Result<InsertOneResult>
Document is bson::Document, an alias for bson::ordered::OrderedDocument.
Your type Weight does not implement the trait Into<Document>, which is required for weight::into(). You could implement it, but a more idiomatic way would be using the Serialize trait with bson::to_bson:
fn store_weights(weights: Vec<Weight>) -> Result<&'static str, Box<dyn std::error::Error>> {
let conn = db.get()?;
let coll = conn.collection("weights");
for weight in weights.iter() {
let document = match bson::to_bson(weight)? {
Document(doc) => doc,
_ => unreachable!(), // Weight should always serialize to a document
};
coll.insert_one(document, None)?;
}
Ok("ok")
}
Notes:
to_bson returns an enum, Bson, which can be Array, Boolean, Document, etc. We use match to make sure it is Document.
I've used ? instead of unwrap, to make use of the Result return type. Make sure the errors are Into<Error> for your Result type.
Returning &'static str instead of allocating a new String for each request.
Solved
For a first ever macro to write this wasnt the easiest. But I learned a lot, much kudo's to Gama11 who pointed me in the right direction, and the coreteam for such a thing of beauty: Haxe.
And I even added some slick doc field strings, so you get nice info during autocompletion.
Main.hx
var e1:Either<String, Int, Bool> = Either3._1('test');
var e2:Either<String, Int, Bool> = Either3._2(1);
var e3:Either<String, Int, Bool> = Either3._3(true);
var error:Either<String, Int, Bool> = Either3._3('Bool expected, but got a String this will give an error');
Either.hx
package;
#:genericBuild(EitherMacro.build())
class Either<Rest> {}
/*#:genericbuild only works on classes, but
can still override the class with an enum. Funky. */
EitherMacro.hx
package;
#if macro
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.Type;
using haxe.macro.Tools;
class EitherMacro {
static var eitherTypes = new Map<Int,Bool>();
static function build():ComplexType {
return switch (Context.getLocalType()) {
case TInst(_.get() => {name: "Either"}, params):
buildEitherEnum(params);
default:
throw false;
}
return macro:Dynamic;
}
static function buildEitherEnum(params:Array<Type>):ComplexType {
var numParams = params.length;
var name='Either$numParams';
if (!eitherTypes.exists(numParams)){
Context.defineType(defineType(name, params));
eitherTypes[numParams] = true;
}
return TPath({pack: [], name: name, params: [for (t in params) TPType(t.toComplexType())]});
}
private static inline function defineType(name:String, params:Array<Type>){
var typeParams:Array<TypeParamDecl> = [];
var typeStrings:Array<String>=[];
var numParams = params.length;
var fields:Array<Field>=[];
for (i in 0...numParams) {
var t=i+1;
typeStrings.push(params[i].toString());
}
var constDocStr=typeStrings.join(',');
for (i in 0...numParams) {
var t=i+1;
var typeString:String=typeStrings[i];
typeParams.push({name:'T$t'});
fields.push(
{
name: '_$t',
pos: Context.currentPos(),
doc: 'from $name<$constDocStr> _$t(v: $typeString)',
kind:FFun({
ret: null,
params: [{name:'T$t'}],
expr: null,
args: [
{
name: 'v',
type: TPath(
{
name:'T$t',
params:[],
pack:[]
}
)
}
]
}
)
}
);
}
var docStr:String="Either represents values which are either of type ";
for(k in 0...typeStrings.length){
if(k!=typeStrings.length-1){
docStr+=typeStrings[k]+" or ";
} else {
docStr+=typeStrings[k]+".";
}
}
return {
pack:[],
name:name,
pos:Context.currentPos(),
doc:docStr,
isExtern: false,
meta:null,
kind:TDEnum,
fields:fields,
params:typeParams
}
}
}
#end
Debugging your macro's the easy way
usage of -D dump=pretty dumps typed AST in dump subdirectory using prettified mode. The output from dump=pretty is almost indistuingishable from regular Haxe code. When errors appear, you find iin the root of the dump directory a file called 'decoding_error.txt'. Its contents might look like this:
{
doc: null
fields: null <- expected value
isExtern: null
kind: null <- expected value
meta: null
name: null <- expected value
pack: null <- expected value
params: null
pos: null <- expected value
}
line 3: expected value
line 5: expected value
line 7: expected value
line 8: expected value
line 10: expected value
This made it much easier for me to debug. But the even better way, is way simple... To debug the easiest way, go to your macrofile (in my case EitherMacro.hx) and do
class EitherMacro{
public static function build(){
var fields=Context.getBuildFields();
var type=Context.getLocalType();
trace(type);
for(f in fields){
trace(f);
}
// your other code
/*
If you use #:build)() instead of #:genericbuild
to debug. Make sure the buildfunction returns
Array<Field> and put at the last line
return Context.getBuildFields();
if you use #:genericbuild you must return
ComplexType, and you can add as the line
return macro:Dynamic; if you have no working return yet.
*/
}
}
the output might look like this:
source/EnumBuilder2.hx:18: TEnum(SomeEnum,[TInst(SomeEnum.T1,[]),TInst(SomeEnum.T2,[]),TInst(SomeEnum.T3,[])])
source/EnumBuilder2.hx:20: {name: _1, doc: null, pos: #pos(source/SomeEnum.hx:4: characters 5-14), access: [], kind: FFun({ret: null, params: [], expr: null, args: [{name: v, opt: false, meta: [], type: TPath(<...>), name_pos: #pos((unknown)), value: null}]}), meta: [], name_pos: #pos(source/SomeEnum.hx:4: characters 5-7)}
source/EnumBuilder2.hx:20: {name: _2, doc: null, pos: #pos(source/SomeEnum.hx:5: characters 5-14), access: [], kind: FFun({ret: null, params: [], expr: null, args: [{name: v, opt: false, meta: [], type: TPath(<...>), name_pos: #pos((unknown)), value: null}]}), meta: [], name_pos: #pos(source/SomeEnum.hx:5: characters 5-7)}
source/EnumBuilder2.hx:20: {name: _3, doc: null, pos: #pos(source/SomeEnum.hx:6: characters 5-14), access: [], kind: FFun({ret: null, params: [], expr: null, args: [{name: v, opt: false, meta: [], type: TPath(<...>), name_pos: #pos((unknown)), value: null}]}), meta: [], name_pos: #pos(source/SomeEnum.hx:6: characters 5-7)}
Another good idea with #:genericbuild(), is to first constructed an enum by hand(or whatever type) and after that trace it using a #:genericbuild, or if you got too much errors using #:build. Then you can copy those trace outputs and try use that code to craft the AST in the macro. This will seriously speedup your development, especially in case of complicated macro's. Almost mindlessly ;-)
Your macro has never run.
Replace your build() function with the following to verify
static function build():ComplexType {
trace('build');
return macro:Dynamic;
}
I suppose #:genericBuild only works for class
1.what I code
class hamburger {
var tomato: String
var patty: String
var bread: String
var number: Int
init(_ tomato: String, _ patty: String, _ bread: String, _ number: Int) {
self.tomato = tomato
self.patty = patty
self.bread = bread
self.number = number
}
init() {
self.tomato = "tomato"
self.patty = "patty"
self.bread = "bread"
self.number = 10
}
}
let sandwich = hamburger("texas" , "iii" , "iii" , 10)
print(hamburger.tomato)
2.error message
Playground execution failed:
error: dotinstall.playground:342:7: error: instance member 'tomato'
cannot be used on type 'hamburger'
print(hamburger.tomato)
^~~~~~~~~ ~~~~~~
3.The sample I followed
enter code here// Class
class User {
let name: String // property
var score: Int
init(name: String, score: Int) {
init(_ name: String, _ score: Int) {
self.name = name
self.score = score
}
init() {
self.name = "bob"
self.score = 30
}
}
//let tom = User(name: "tom", score: 23)
let tom = User("tom", 23)
print(tom.name)
print(tom.score)
let bob = User()
print(bob.name)
print(bob.score)
I have coded like 1 following 3, but I got a error message like 2.
what I did to solve
・anyway follow this sample to be like same
・studied a basic of class syntax, initializer, instance on website
・was looking for a mistypes
・I checked the order of property
I don't why it is not worked even if I just follow the sample code.
please give me tips on the solution.
thanks
You're making a mistake regarding object oriented programming. With hamburger.tomato you try to access the property tomato of the Class Hamburger, not the Object, which is sandwich here. So the solution would be:
print(sandwich.tomato)
In the future, what you might want to do is take a look at styling your code better. Classes(Hamburger) are written starting with an uppercased letter, while the objects, or instances(sandwich), of the Classes are written starting with a lowercased letter.
I see examples of variable initialisation code that can contain any number of statements, for example:
var _globalCounter = 0
let instanceCount: Int = { _globalCounter++ }()
print(instanceCount.dynamicType) // Int
and a full code sample:
struct User {
let name: String
let company: String
let login: String
let password: String
static let database: Dictionary<String, User> = {
var theDatabase = Dictionary<String, User>()
for user in [
User(name: "John Appleseed", company: "Apple", login: "japple", password: "foo"),
User(name: "John Hennessy", company: "Stanford", login: "hennessy", password: "foo"),
User(name: "Bad Guy", company: "Criminals, Inc.", login: "baddie", password: "foo")
] {
theDatabase[user.login] = user
}
return theDatabase
}()
}
What's going on? Is it assignment from a closure like assigning a value from a function call?
These samples are copied form cs 193p fall 2014 class, are these considered to be good practice in terms of complex variable initialisation compared to putting stuff in init?
Please note that here in the second example the variable is static, so effectively this is a thread safe initialisation code?
I'm #learning swift and #confused.
Yes, a closure is just a function. Like any other function, you call it by passing in the arguments inside parentheses. If it is a function that takes no arguments, then you call it with empty parentheses.
let one: Int = { return 1 }()
It's actually as simple as that :)
Sorry about the last thread where I posted this question by accident! Here it is. I received a response from someone (Their response is at bottom of page) and unfortunately it did not work. Thanks in advance!
Create a variable named result and assign it the tuple returned from function greeting. (Note: pass the string "Tom" to the greeting function.)
func greeting() -> (language: String, greeting: String, name: String) {
let language = "English"
let greeting = "Hello"
let name = "Tom"
return (language, greeting, name)
}
var result = greeting()
Error = Your function needs to return a tuple with elements named 'greeting' and 'language'.
Now this solution below tells me that my variable has the wrong value in it, but I can't figure out how to pass it "Tom" to the greeting function because I keep getting an error.
func greeting() -> (language: String, greeting: String) {
let language = "English"
let greeting = "Hello"
return (language, greeting)
}
var result = greeting("Tom")
Response I got in the last thread is below. I still get the error message saying that I need to assign the return value of greeting to result.
func greeting(name:String) -> (language: String, greeting: String) {
let language = "English"
let greeting = "Hello " + name + "!"
return (language, greeting)
}
var result = greeting("Tom").greeting
The task is
Create a variable named result and assign it the tuple returned from function greeting.
What you do in the last block is
var result = greeting("Tom").greeting
what I would expect you to do is
var result = greeting("Tom")