1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
use crate::context::PuffContext;
use crate::errors::PuffResult;
use crate::program::{Runnable, RunnableCommand};
use std::process::ExitCode;
use clap::{Arg, ArgMatches, Command};
use pyo3::prelude::*;
use pyo3::types::PyDict;
#[derive(Clone)]
pub struct DjangoManagementCommand {}
impl DjangoManagementCommand {
pub fn new() -> Self {
Self {}
}
}
impl RunnableCommand for DjangoManagementCommand {
fn cli_parser(&self) -> Command {
Command::new("django").arg(
Arg::new("arg")
.num_args(1..)
.value_name("ARG")
.help("Arguments to pass to Django."),
)
}
fn make_runnable(&mut self, args: &ArgMatches, context: PuffContext) -> PuffResult<Runnable> {
let subcommand = args.subcommand_name().unwrap_or("django");
let (django_args, python_function) = Python::with_gil(|py| {
let mut django_args = vec![subcommand.into_py(py)];
for arg in args.get_raw("arg").unwrap_or_default() {
django_args.push(arg.into_py(py))
}
let management = py.import("puff.contrib.django.management")?;
let execute_fn = management.getattr("get_management_utility_execute")?;
PyResult::Ok((django_args, execute_fn.into_py(py)))
})?;
let fut = async move {
let res = Python::with_gil(|py| {
context.python_dispatcher().dispatch_blocking(
py,
python_function,
(django_args,),
PyDict::new(py),
)
})?;
let r = res.await??;
let exit_status = Python::with_gil(|py| r.extract::<u8>(py)).unwrap_or_default();
Ok(ExitCode::from(exit_status))
};
Ok(Runnable::new(fut))
}
}