Skip to content

Commit

Permalink
append Raises line to function docstrings as appropriate
Browse files Browse the repository at this point in the history
If the WIT representation of a function returns `result<A,B>`, then we generate
a Python function that returns `A` and raises `Err(B)`.  Since there's currently
no way of representing the `Err(B)` part in the function's signature, we do the
next best thing: put it in the docstring.

Fixes #53

Signed-off-by: Joel Dice <joel.dice@fermyon.com>
  • Loading branch information
dicej committed Jan 12, 2024
1 parent d7eadf2 commit 56e6090
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 23 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

68 changes: 46 additions & 22 deletions src/summary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ struct FunctionCode {
static_method: &'static str,
return_type: String,
result_count: usize,
error: Option<String>,
}

pub struct Summary<'a> {
Expand Down Expand Up @@ -751,9 +752,9 @@ impl<'a> Summary<'a> {

let result_types = function.results.types().collect::<Vec<_>>();

let (return_statement, return_type) =
let (return_statement, return_type, error) =
if let wit_parser::FunctionKind::Constructor(_) = function.wit_kind {
("return".to_owned(), "None".to_owned())
("return".to_owned(), "None".to_owned(), None)
} else {
let indent = if let wit_parser::FunctionKind::Freestanding = function.wit_kind {
""
Expand All @@ -762,18 +763,29 @@ impl<'a> Summary<'a> {
};

match result_types.as_slice() {
[] => ("return".to_owned(), "None".to_owned()),
[] => ("return".to_owned(), "None".to_owned(), None),
[ty] => match special_return(*ty) {
SpecialReturn::Result(result) => (
format!(
"if isinstance(result[0], Err):
SpecialReturn::Result(result) => {
let error = if let Some(ty) = result.err {
Some(type_name(ty))
} else {
Some("None".into())
};

(
format!(
"if isinstance(result[0], Err):
{indent} raise result[0]
{indent} else:
{indent} return result[0].value"
),
result.ok.map(type_name).unwrap_or_else(|| "None".into()),
),
SpecialReturn::None => ("return result[0]".to_owned(), type_name(*ty)),
),
result.ok.map(type_name).unwrap_or_else(|| "None".into()),
error,
)
}
SpecialReturn::None => {
("return result[0]".to_owned(), type_name(*ty), None)
}
},
_ => (
"return result".to_owned(),
Expand All @@ -785,6 +797,7 @@ impl<'a> Summary<'a> {
.collect::<Vec<_>>()
.join(", ")
),
None,
),
}
};
Expand All @@ -805,6 +818,7 @@ impl<'a> Summary<'a> {
static_method,
return_type: format!(" -> {return_type}"),
result_count,
error,
}
}

Expand Down Expand Up @@ -949,7 +963,14 @@ impl<'a> Summary<'a> {
},
}

let docstring = |docs: Option<&str>, indent_level| {
let docstring = |docs: Option<&str>, indent_level, error: Option<&str>| {
let docs = match (docs, error.map(|e| format!("Raises: Err({e})"))) {
(Some(docs), Some(error_docs)) => Some(format!("{docs}\n\n{error_docs}")),
(Some(docs), None) => Some(docs.to_owned()),
(None, Some(error_docs)) => Some(error_docs),
(None, None) => None,
};

if let Some(docs) = docs {
let newline = '\n';
let indent = (0..indent_level)
Expand Down Expand Up @@ -1000,7 +1021,7 @@ impl<'a> Summary<'a> {
fields = "pass".to_owned()
}

let docs = docstring(docs, 1);
let docs = docstring(docs, 1, None);

format!(
"
Expand Down Expand Up @@ -1078,7 +1099,7 @@ class {name}:
.collect::<Vec<_>>()
.join("\n ");

let docs = docstring(ty.docs.contents.as_deref(), 1);
let docs = docstring(ty.docs.contents.as_deref(), 1, None);

Code::Shared(format!(
"
Expand All @@ -1102,7 +1123,7 @@ class {camel}(Enum):
flags
};

let docs = docstring(ty.docs.contents.as_deref(), 1);
let docs = docstring(ty.docs.contents.as_deref(), 1, None);

Code::Shared(format!(
"
Expand All @@ -1114,7 +1135,7 @@ class {camel}(Flag):
TypeDefKind::Resource => {
let camel = camel();

let docs = docstring(ty.docs.contents.as_deref(), 1);
let docs = docstring(ty.docs.contents.as_deref(), 1, None);

let empty = &ResourceInfo::default();

Expand All @@ -1134,9 +1155,10 @@ class {camel}(Flag):
return_statement,
static_method,
result_count,
error,
} = self.function_code(function, &mut names, &seen, Some(id));

let docs = docstring(function.docs, 2);
let docs = docstring(function.docs, 2, error.as_deref());

if let wit_parser::FunctionKind::Constructor(_) = function.wit_kind {
if stub_runtime_calls {
Expand Down Expand Up @@ -1246,10 +1268,11 @@ class {camel}:
params,
return_type,
static_method,
error,
..
} = self.function_code(function, &mut names, &seen, Some(id));

let docs = docstring(function.docs, 2);
let docs = docstring(function.docs, 2, error.as_deref());

format!(
"{static_method}
Expand Down Expand Up @@ -1393,12 +1416,13 @@ class {camel}(Protocol):
return_type,
return_statement,
result_count,
error,
..
} = self.function_code(function, &mut names, &seen, None);

match function.kind {
FunctionKind::Import => {
let docs = docstring(function.docs, 1);
let docs = docstring(function.docs, 1, error.as_deref());

let code = if stub_runtime_calls {
format!(
Expand Down Expand Up @@ -1440,7 +1464,7 @@ def {snake}({params}){return_type}:
format!("self, {params}")
};

let docs = docstring(function.docs, 2);
let docs = docstring(function.docs, 2, error.as_deref());

let code = format!(
"
Expand Down Expand Up @@ -1531,7 +1555,7 @@ Result = Union[Ok[T], Err[E]]
.map(|&interface| import("..", interface))
.collect::<Vec<_>>()
.join("\n");
let docs = docstring(code.docs, 0);
let docs = docstring(code.docs, 0, None);

let imports = if stub_runtime_calls {
imports
Expand Down Expand Up @@ -1567,7 +1591,7 @@ from ..types import Result, Ok, Err, Some
.map(|interface| import("..", interface))
.collect::<Vec<_>>()
.join("\n");
let docs = docstring(code.docs, 0);
let docs = docstring(code.docs, 0, None);

write!(
file,
Expand Down Expand Up @@ -1637,7 +1661,7 @@ from ..types import Result, Ok, Err, Some
.map(|&interface| import(".", interface))
.collect::<Vec<_>>()
.join("\n");
let docs = docstring(world_exports.docs, 0);
let docs = docstring(world_exports.docs, 0, None);

let imports = if stub_runtime_calls {
imports
Expand Down

0 comments on commit 56e6090

Please sign in to comment.