use insta::assert_snapshot;
use monty::MontyRun;
use monty_types::{CompileOptions, MontyObject};
const POINT: &str = r"
from dataclasses import dataclass
import typing
@dataclass
class Point:
x: int
y: int = 5
seen: typing.ClassVar[int] = 0
";
fn eval_str(expr: &str) -> String {
let code = format!("{POINT}\n{expr}\n");
let run = MontyRun::new(code, "test.py", vec![], CompileOptions::default()).expect("code should compile");
match run.run_no_limits(vec![]).expect("code should run") {
MontyObject::String(s) => s,
other => panic!("expected a string, got {other:?}"),
}
}
fn expect_error(expr: &str) -> String {
let code = format!("{POINT}\n{expr}\n");
let run = MontyRun::new(code, "test.py", vec![], CompileOptions::default()).expect("code should compile");
match run.run_no_limits(vec![]) {
Ok(value) => panic!("expected an exception, got {value:?}"),
Err(err) => err.message().map_or_else(|| err.to_string(), ToOwned::to_owned),
}
}
#[test]
fn field_repr_renders_missing_as_a_bare_name() {
assert_snapshot!(
eval_str("repr(Point.__dataclass_fields__['y'])"),
@"Field(name='y',type='int',default=5,default_factory=MISSING,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,doc=None,_field_type=_FIELD)"
);
assert_snapshot!(
eval_str("repr(Point.__dataclass_fields__['x'])"),
@"Field(name='x',type='int',default=MISSING,default_factory=MISSING,init=True,repr=True,hash=None,compare=True,metadata=mappingproxy({}),kw_only=False,doc=None,_field_type=_FIELD)"
);
}
#[test]
fn missing_default_is_not_implemented() {
assert_snapshot!(
expect_error("Point.__dataclass_fields__['x'].default"),
@"Field.default is not yet supported, dataclasses.MISSING is not implemented"
);
}
#[test]
fn unmodelled_field_attributes_are_not_implemented() {
for (attr, missing) in [
("default_factory", "dataclasses.MISSING"),
("metadata", "types.MappingProxyType"),
("_field_type", "dataclasses._FIELD"),
] {
assert_eq!(
expect_error(&format!("Point.__dataclass_fields__['y'].{attr}")),
format!("Field.{attr} is not yet supported, {missing} is not implemented")
);
}
}
#[test]
fn classvars_are_absent_from_the_mapping() {
assert_snapshot!(eval_str("repr(list(Point.__dataclass_fields__))"), @"['x', 'y']");
}