From da22d877a578eb22d0fcb32ff4baa7d2f63c49a2 Mon Sep 17 00:00:00 2001 From: Michael Huang Date: Thu, 12 Oct 2023 01:56:25 -0400 Subject: [PATCH] only import enum module once --- src/input/input_python.rs | 7 +++++-- src/input/shared.rs | 16 +++++++++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/input/input_python.rs b/src/input/input_python.rs index 6e5d1eb3c..e2471409a 100644 --- a/src/input/input_python.rs +++ b/src/input/input_python.rs @@ -21,7 +21,10 @@ use super::datetime::{ float_as_duration, float_as_time, int_as_datetime, int_as_duration, int_as_time, EitherDate, EitherDateTime, EitherTime, }; -use super::shared::{decimal_as_int, float_as_int, int_as_bool, map_json_err, str_as_bool, str_as_float, str_as_int}; +use super::shared::{ + decimal_as_int, float_as_int, get_enum_meta_object, int_as_bool, map_json_err, str_as_bool, str_as_float, + str_as_int, +}; use super::{ py_string_str, BorrowInput, EitherBytes, EitherFloat, EitherInt, EitherString, EitherTimedelta, GenericArguments, GenericIterable, GenericIterator, GenericMapping, Input, JsonInput, PyArgs, @@ -765,7 +768,7 @@ fn maybe_as_string(v: &PyAny, unicode_error: ErrorType) -> ValResult(v: &'a PyAny) -> Option<&'a PyAny> { let py = v.py(); - let enum_meta_object = py.import("enum").unwrap().getattr("EnumMeta").unwrap().to_object(py); + let enum_meta_object = get_enum_meta_object(py); let meta_type = v.get_type().get_type(); if meta_type.is(&enum_meta_object) { v.getattr(intern!(py, "value")).ok() diff --git a/src/input/shared.rs b/src/input/shared.rs index 1a8e2b61c..509137d2e 100644 --- a/src/input/shared.rs +++ b/src/input/shared.rs @@ -1,11 +1,25 @@ use num_bigint::BigInt; -use pyo3::{intern, PyAny, Python}; +use pyo3::sync::GILOnceCell; +use pyo3::{intern, Py, PyAny, Python, ToPyObject}; use crate::errors::{ErrorType, ErrorTypeDefaults, ValError, ValResult}; use super::parse_json::{JsonArray, JsonInput}; use super::{EitherFloat, EitherInt, Input}; +static ENUM_META_OBJECT: GILOnceCell> = GILOnceCell::new(); + +pub fn get_enum_meta_object(py: Python) -> Py { + ENUM_META_OBJECT + .get_or_init(py, || { + py.import("enum") + .and_then(|decimal_module| decimal_module.getattr("EnumMeta")) + .unwrap() + .to_object(py) + }) + .clone() +} + pub fn map_json_err<'a>(input: &'a impl Input<'a>, error: serde_json::Error) -> ValError<'a> { ValError::new( ErrorType::JsonInvalid {