1use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
18
19#[cfg(feature = "time")]
20use pyo3::{
21 exceptions::PyValueError,
22 types::{PyDate, PyDateTime, PyDelta, PyTime, PyTzInfo},
23};
24
25use pyo3::{
26 types::{
27 PyBool, PyByteArray, PyBytes, PyDict, PyFloat, PyFrozenSet, PyInt, PyList, PySet, PyString,
28 },
29 FromPyObject, IntoPy, Py, PyAny, PyResult, Python,
30};
31
32#[cfg(feature = "complex")]
33mod complex;
35
36#[cfg(feature = "time")]
37use crate::datetime::DateTime;
38#[cfg(feature = "time")]
39use pyo3::{types::PyTuple, ToPyObject};
40#[cfg(feature = "time")]
41use time::{Date, Duration, Month, OffsetDateTime, PrimitiveDateTime, Time, UtcOffset};
42
43#[cfg(feature = "indexmap")]
44mod indexmap;
46
47pub trait PyTryFrom<P>: Sized {
49 fn py_try_from(py: Python, item: &P) -> PyResult<Self>;
55}
56
57impl<P> PyTryFrom<PyAny> for Py<P>
58where
59 Self: for<'a> FromPyObject<'a>,
60{
61 fn py_try_from(_py: Python, item: &PyAny) -> PyResult<Self> {
62 item.extract()
63 }
64}
65
66impl<T, P> PyTryFrom<P> for Box<T>
67where
68 T: PyTryFrom<P>,
69{
70 fn py_try_from(py: Python, item: &P) -> PyResult<Self> {
71 T::py_try_from(py, item).map(Self::new)
72 }
73}
74
75macro_rules! impl_py_try_from_tuple {
77 ($($idx:tt $t:tt $p:tt),+) => {
78 impl<$($t,)+ $($p,)+> PyTryFrom<($($p,)+)> for ($($t,)+)
79 where
80 $($t: PyTryFrom<$p>,)+
81 {
82 fn py_try_from(py: Python, item: &($($p,)+)) -> PyResult<Self> {
83 Ok(($(
84 $t :: py_try_from(py, &item.$idx)?,
85 )+))
86 }
87 }
88 };
89}
90
91impl_py_try_from_tuple!(0 T0 P0);
94impl_py_try_from_tuple!(0 T0 P0, 1 T1 P1);
95impl_py_try_from_tuple!(0 T0 P0, 1 T1 P1, 2 T2 P2);
96impl_py_try_from_tuple!(0 T0 P0, 1 T1 P1, 2 T2 P2, 3 T3 P3);
97impl_py_try_from_tuple!(0 T0 P0, 1 T1 P1, 2 T2 P2, 3 T3 P3, 4 T4 P4);
98impl_py_try_from_tuple!(0 T0 P0, 1 T1 P1, 2 T2 P2, 3 T3 P3, 4 T4 P4, 5 T5 P5);
99impl_py_try_from_tuple!(0 T0 P0, 1 T1 P1, 2 T2 P2, 3 T3 P3, 4 T4 P4, 5 T5 P5, 6 T6 P6);
100impl_py_try_from_tuple!(0 T0 P0, 1 T1 P1, 2 T2 P2, 3 T3 P3, 4 T4 P4, 5 T5 P5, 6 T6 P6, 7 T7 P7);
101impl_py_try_from_tuple!(0 T0 P0, 1 T1 P1, 2 T2 P2, 3 T3 P3, 4 T4 P4, 5 T5 P5, 6 T6 P6, 7 T7 P7, 8 T8 P8);
102impl_py_try_from_tuple!(0 T0 P0, 1 T1 P1, 2 T2 P2, 3 T3 P3, 4 T4 P4, 5 T5 P5, 6 T6 P6, 7 T7 P7, 8 T8 P8, 9 T9 P9);
103impl_py_try_from_tuple!(0 T0 P0, 1 T1 P1, 2 T2 P2, 3 T3 P3, 4 T4 P4, 5 T5 P5, 6 T6 P6, 7 T7 P7, 8 T8 P8, 9 T9 P9, 10 T10 P10);
104impl_py_try_from_tuple!(0 T0 P0, 1 T1 P1, 2 T2 P2, 3 T3 P3, 4 T4 P4, 5 T5 P5, 6 T6 P6, 7 T7 P7, 8 T8 P8, 9 T9 P9, 10 T10 P10, 11 T11 P11);
105
106#[macro_export]
111macro_rules! private_py_try_from_py_pyany_inner {
112 ($item: ident, $py: ident, $py_type: ty) => {{
113 let actual: &$py_type = $item.extract()?;
114 <Self as $crate::PyTryFrom<$py_type>>::py_try_from($py, actual)
115 }};
116}
117
118#[macro_export]
120macro_rules! private_impl_py_try_from_pyany {
121 ($py_type: ty => $rs_type: ty) => {
122 impl $crate::PyTryFrom<$crate::pyo3::PyAny> for $rs_type {
123 fn py_try_from(
124 py: $crate::pyo3::Python,
125 item: &$crate::pyo3::PyAny,
126 ) -> $crate::pyo3::PyResult<Self> {
127 let actual: &$py_type = item.extract()?;
128 <Self as $crate::PyTryFrom<$py_type>>::py_try_from(py, actual)
129 }
130 }
131 };
132}
133
134#[macro_export]
136#[allow(clippy::module_name_repetitions)]
137macro_rules! private_impl_py_try_from {
138 (&$item: ident, $py: ident, $py_type: ty => $rs_type: ty $convert: block) => {
139 #[allow(clippy::use_self)]
140 impl $crate::PyTryFrom<$py_type> for $rs_type {
141 fn py_try_from(
142 $py: $crate::pyo3::Python,
143 $item: &$py_type,
144 ) -> $crate::pyo3::PyResult<Self> {
145 $convert
146 }
147 }
148 };
149}
150pub(crate) use private_impl_py_try_from;
151
152#[macro_export]
155macro_rules! private_impl_py_try_from_with_pyany {
156 (&$item: ident, $py: ident, $py_type: ty => $rs_type: ty $convert: block) => {
157 $crate::private_impl_py_try_from!(&$item, $py, $py_type => $rs_type $convert);
158 $crate::private_impl_py_try_from_pyany!($py_type => $rs_type);
159 };
160}
161pub(crate) use private_impl_py_try_from_with_pyany;
162
163macro_rules! impl_try_from_py_native {
165 ($py_type: ty => $rs_type: ty) => {
166 $crate::private_impl_py_try_from!(&item, py, $crate::pyo3::Py<$py_type> => $rs_type {
167 let item: &$py_type = item.as_ref(py);
168 <Self as $crate::PyTryFrom<$py_type>>::py_try_from(py, item)
169 });
170 }
171}
172pub(crate) use impl_try_from_py_native;
173
174macro_rules! impl_try_from_self_python {
176 ($py_type: ty) => {
177 $crate::private_impl_py_try_from!(&item, py, $py_type => $crate::pyo3::Py<$py_type> {
178 Ok(item.into_py(py))
179 });
180 $crate::private_impl_py_try_from!(&item, _py, $crate::pyo3::Py<$py_type> => $crate::pyo3::Py<$py_type> {
181 Ok(item.clone())
182 });
183 }
184}
185pub(crate) use impl_try_from_self_python;
186
187macro_rules! impl_try_from_self_rust {
189 ($rs_type: ty) => {
190 private_impl_py_try_from!(&item, _py, $rs_type => $rs_type {
191 Ok(item.clone())
192 });
193 }
194}
195
196macro_rules! impl_try_from_primitive {
198 ($py_type: ty => $rs_type: ty) => {
199 private_impl_py_try_from_with_pyany!(&item, _py, $py_type => $rs_type { item.extract() });
200 impl_try_from_py_native!($py_type => $rs_type);
201 };
202}
203
204impl_try_from_primitive!(PyBool => bool);
209impl_try_from_self_python!(PyBool);
210impl_try_from_self_rust!(bool);
211
212impl_try_from_self_python!(PyByteArray);
215impl_try_from_py_native!(PyByteArray => Vec<u8>);
216private_impl_py_try_from!(&item, _py, PyByteArray => Vec<u8> {
217 Ok(item.to_vec())
218});
219
220impl_try_from_py_native!(PyByteArray => Box<[u8]>);
221private_impl_py_try_from!(&item, py, PyByteArray => Box<[u8]> {
222 Vec::<u8>::py_try_from(py, item).map(From::from)
223});
224
225impl_try_from_self_python!(PyBytes);
228impl_try_from_py_native!(PyBytes => Vec<u8>);
229private_impl_py_try_from!(&item, _py, PyBytes => Vec<u8> {
230 Ok(item.as_bytes().to_vec())
231});
232
233impl_try_from_py_native!(PyBytes => Box<[u8]>);
234private_impl_py_try_from!(&item, py, PyBytes => Box<[u8]> {
235 Vec::<u8>::py_try_from(py, item).map(From::from)
236});
237
238#[cfg(feature = "time")]
241impl_try_from_self_python!(PyDate);
242
243#[cfg(feature = "time")]
244impl_try_from_self_rust!(Date);
245#[cfg(feature = "time")]
246impl_try_from_py_native!(PyDate => Date);
247
248#[cfg(feature = "time")]
249private_impl_py_try_from_with_pyany!(&item, py, PyDate => Date {
250 let year = item.getattr("year").map(|any| i32::py_try_from(py, any))??;
251 let month: u8 = item.getattr("month").map(|any| u8::py_try_from(py, any))??; let month: Month = month.try_into()
253 .map_err(|_| {
254 PyValueError::new_err(format!("Expected date month to be within 0-12, got {month}"))
255 })?;
256 let day = item.getattr("day").map(|any| u8::py_try_from(py, any))??; Self::from_calendar_date(year, month, day).map_err(|err| {
259 PyValueError::new_err(format!("Failed to create Date object: {err}"))
260 })
261});
262
263#[cfg(feature = "time")]
266impl_try_from_self_python!(PyDateTime);
267
268#[cfg(feature = "time")]
269impl_try_from_self_rust!(DateTime);
270#[cfg(feature = "time")]
271impl_try_from_py_native!(PyDateTime => DateTime);
272
273#[cfg(feature = "time")]
274private_impl_py_try_from_with_pyany!(&item, py, PyDateTime => DateTime {
275 let date = item.call_method0("date").map(|date| Date::py_try_from(py, date))??;
276 let (time, offset) = item.call_method0("timetz")
277 .map(|time| <(Time, Option<UtcOffset>)>::py_try_from(py, time))??;
278 let datetime = PrimitiveDateTime::new(date, time);
279 let datetime = offset.map_or(Self::Primitive(datetime), |offset| {
280 let datetime = OffsetDateTime::now_utc()
282 .replace_date_time(datetime)
283 .replace_offset(offset);
284 Self::Offset(datetime)
285 });
286
287 Ok(datetime)
288});
289
290#[cfg(feature = "time")]
293impl_try_from_self_python!(PyDelta);
294
295#[cfg(feature = "time")]
296impl_try_from_self_rust!(Duration);
297
298#[cfg(feature = "time")]
299impl_try_from_py_native!(PyDelta => Duration);
300
301#[cfg(feature = "time")]
302private_impl_py_try_from_with_pyany!(&item, _py, PyDelta => Duration {
303 let days: i64 = item.getattr("days")?.extract()?;
304 let seconds: i64 = item.getattr("seconds")?.extract()?;
305 let microseconds: i32 = item.getattr("microseconds")?.extract()?;
306 let nanoseconds = microseconds.checked_mul(1000).ok_or_else(|| {
307 PyValueError::new_err("Could not fit {microseconds} microseconds as nanoseconds into a 32-bit signed integer")
308 })?;
309 let day_seconds = days.checked_mul(24 * 60 * 60).ok_or_else(|| {
310 PyValueError::new_err("Could not fit {days} days as seconds into a 64-bit signed integer")
311 })?;
312 let seconds = seconds.checked_add(day_seconds).ok_or_else(|| {
313 PyValueError::new_err("Could not add {days} days and {seconds} seconds into a 64-bit signed integer")
314 })?;
315 Ok(Self::new(seconds, nanoseconds))
316});
317
318#[cfg(feature = "time")]
319impl_try_from_self_rust!(std::time::Duration);
320#[cfg(feature = "time")]
321impl_try_from_py_native!(PyDelta => std::time::Duration);
322
323#[cfg(feature = "time")]
324private_impl_py_try_from!(&item, _py, PyDelta => std::time::Duration {
325 let days: u64 = item.getattr("days")?.extract()?;
326 let seconds: u64 = item.getattr("seconds")?.extract()?;
327 let microseconds: u32 = item.getattr("microseconds")?.extract()?;
328 let nanoseconds = microseconds.checked_mul(1000).ok_or_else(|| {
329 PyValueError::new_err("Could not fit {microseconds} microseconds as nanoseconds into a 32-bit signed integer")
330 })?;
331 let day_seconds = days.checked_mul(24 * 60 * 60).ok_or_else(|| {
332 PyValueError::new_err("Could not fit {days} days as seconds into a 64-bit signed integer")
333 })?;
334 let seconds = seconds.checked_add(day_seconds).ok_or_else(|| {
335 PyValueError::new_err("Could not add {days} days and {seconds} seconds into a 64-bit signed integer")
336 })?;
337 Ok(Self::new(seconds, nanoseconds))
338});
339
340impl_try_from_self_python!(PyDict);
343
344impl<K1, K2, V1, V2, Hasher> PyTryFrom<HashMap<K1, V1>> for HashMap<K2, V2, Hasher>
345where
346 K2: Eq + std::hash::Hash + PyTryFrom<K1>,
347 V2: PyTryFrom<V1>,
348 Hasher: std::hash::BuildHasher + Default,
349{
350 fn py_try_from(py: Python, item: &HashMap<K1, V1>) -> PyResult<Self> {
351 item.iter()
352 .map(|(key, val)| {
353 let key = K2::py_try_from(py, key)?;
354 let val = V2::py_try_from(py, val)?;
355 Ok((key, val))
356 })
357 .collect()
358 }
359}
360
361impl<K, V, Hasher> PyTryFrom<Py<PyDict>> for HashMap<K, V, Hasher>
362where
363 K: Eq + std::hash::Hash + PyTryFrom<PyAny>,
364 V: PyTryFrom<PyAny>,
365 Hasher: std::hash::BuildHasher + Default,
366{
367 fn py_try_from(py: Python, item: &Py<PyDict>) -> PyResult<Self> {
368 Self::py_try_from(py, item.as_ref(py))
369 }
370}
371
372impl<K, V, Hasher> PyTryFrom<PyDict> for HashMap<K, V, Hasher>
373where
374 K: Eq + std::hash::Hash + PyTryFrom<PyAny>,
375 V: PyTryFrom<PyAny>,
376 Hasher: std::hash::BuildHasher + Default,
377{
378 fn py_try_from(py: Python, item: &PyDict) -> PyResult<Self> {
379 let mut map = Self::with_capacity_and_hasher(item.len(), Hasher::default());
380 for (key, val) in item {
381 let key = K::py_try_from(py, key)?;
382 let val = V::py_try_from(py, val)?;
383 map.insert(key, val);
384 }
385 Ok(map)
386 }
387}
388
389impl<K, V, Hasher> PyTryFrom<PyAny> for HashMap<K, V, Hasher>
390where
391 K: Eq + std::hash::Hash + PyTryFrom<PyAny>,
392 V: PyTryFrom<PyAny>,
393 Hasher: std::hash::BuildHasher + Default,
394{
395 fn py_try_from(py: Python, item: &PyAny) -> PyResult<Self> {
396 let dict: &PyDict = item.downcast()?;
397 Self::py_try_from(py, dict)
398 }
399}
400
401impl<K1, K2, V1, V2> PyTryFrom<BTreeMap<K1, V1>> for BTreeMap<K2, V2>
402where
403 K2: Ord + PyTryFrom<K1>,
404 V2: PyTryFrom<V1>,
405{
406 fn py_try_from(py: Python, item: &BTreeMap<K1, V1>) -> PyResult<Self> {
407 item.iter()
408 .map(|(key, val)| {
409 let key = K2::py_try_from(py, key)?;
410 let val = V2::py_try_from(py, val)?;
411 Ok((key, val))
412 })
413 .collect()
414 }
415}
416
417impl<K, V> PyTryFrom<Py<PyDict>> for BTreeMap<K, V>
418where
419 K: Ord + PyTryFrom<PyAny>,
420 V: PyTryFrom<PyAny>,
421{
422 fn py_try_from(py: Python, item: &Py<PyDict>) -> PyResult<Self> {
423 Self::py_try_from(py, item.as_ref(py))
424 }
425}
426
427impl<K, V> PyTryFrom<PyDict> for BTreeMap<K, V>
428where
429 K: Ord + PyTryFrom<PyAny>,
430 V: PyTryFrom<PyAny>,
431{
432 fn py_try_from(py: Python, item: &PyDict) -> PyResult<Self> {
433 let mut map = Self::new();
434 for (key, val) in item {
435 let key = K::py_try_from(py, key)?;
436 let val = V::py_try_from(py, val)?;
437 map.insert(key, val);
438 }
439 Ok(map)
440 }
441}
442
443impl<K, V> PyTryFrom<PyAny> for BTreeMap<K, V>
444where
445 K: Ord + PyTryFrom<PyAny>,
446 V: PyTryFrom<PyAny>,
447{
448 fn py_try_from(py: Python, item: &PyAny) -> PyResult<Self> {
449 let dict: &PyDict = item.downcast()?;
450 <Self as PyTryFrom<PyDict>>::py_try_from(py, dict)
451 }
452}
453
454impl_try_from_self_python!(PyFloat);
457impl_try_from_self_rust!(f32);
458impl_try_from_self_rust!(f64);
459impl_try_from_primitive!(PyFloat => f32);
460impl_try_from_primitive!(PyFloat => f64);
461
462impl_try_from_self_python!(PyFrozenSet);
465
466impl<T, Hasher> PyTryFrom<Py<PyFrozenSet>> for HashSet<T, Hasher>
467where
468 T: Eq + std::hash::Hash + PyTryFrom<PyAny>,
469 Hasher: std::hash::BuildHasher + Default,
470{
471 fn py_try_from(py: Python, set: &Py<PyFrozenSet>) -> PyResult<Self> {
472 Self::py_try_from(py, set.as_ref(py))
473 }
474}
475
476impl<T, Hasher> PyTryFrom<PyFrozenSet> for HashSet<T, Hasher>
477where
478 T: Eq + std::hash::Hash + PyTryFrom<PyAny>,
479 Hasher: std::hash::BuildHasher + Default,
480{
481 fn py_try_from(py: Python, set: &PyFrozenSet) -> PyResult<Self> {
482 let mut map = Self::with_capacity_and_hasher(set.len(), Hasher::default());
483 for item in set {
484 let item = T::py_try_from(py, item)?;
485 map.insert(item);
486 }
487 Ok(map)
488 }
489}
490
491impl<T> PyTryFrom<Py<PyFrozenSet>> for BTreeSet<T>
492where
493 T: Ord + PyTryFrom<PyAny>,
494{
495 fn py_try_from(py: Python, set: &Py<PyFrozenSet>) -> PyResult<Self> {
496 Self::py_try_from(py, set.as_ref(py))
497 }
498}
499
500impl<T> PyTryFrom<PyFrozenSet> for BTreeSet<T>
501where
502 T: Ord + PyTryFrom<PyAny>,
503{
504 fn py_try_from(py: Python, set: &PyFrozenSet) -> PyResult<Self> {
505 let mut map = Self::new();
506 for item in set {
507 let item = T::py_try_from(py, item)?;
508 map.insert(item);
509 }
510 Ok(map)
511 }
512}
513
514impl_try_from_self_python!(PyInt);
517impl_try_from_self_rust!(i8);
518impl_try_from_self_rust!(i16);
519impl_try_from_self_rust!(i32);
520impl_try_from_self_rust!(i64);
521impl_try_from_self_rust!(i128);
522impl_try_from_self_rust!(isize);
523impl_try_from_self_rust!(u8);
524impl_try_from_self_rust!(u16);
525impl_try_from_self_rust!(u32);
526impl_try_from_self_rust!(u64);
527impl_try_from_self_rust!(u128);
528impl_try_from_self_rust!(usize);
529impl_try_from_primitive!(PyInt => i8);
530impl_try_from_primitive!(PyInt => i16);
531impl_try_from_primitive!(PyInt => i32);
532impl_try_from_primitive!(PyInt => i64);
533impl_try_from_primitive!(PyInt => i128);
534impl_try_from_primitive!(PyInt => isize);
535impl_try_from_primitive!(PyInt => u8);
536impl_try_from_primitive!(PyInt => u16);
537impl_try_from_primitive!(PyInt => u32);
538impl_try_from_primitive!(PyInt => u64);
539impl_try_from_primitive!(PyInt => u128);
540impl_try_from_primitive!(PyInt => usize);
541
542impl_try_from_self_python!(PyList);
545
546impl<P, T> PyTryFrom<Vec<P>> for Vec<T>
547where
548 T: PyTryFrom<P>,
549{
550 fn py_try_from(py: Python, item: &Vec<P>) -> PyResult<Self> {
551 item.iter().map(|item| T::py_try_from(py, item)).collect()
552 }
553}
554
555impl<T> PyTryFrom<Py<PyList>> for Vec<T>
556where
557 T: PyTryFrom<PyAny>,
558{
559 fn py_try_from(py: Python, py_list: &Py<PyList>) -> PyResult<Self> {
560 Self::py_try_from(py, py_list.as_ref(py))
561 }
562}
563
564impl<T> PyTryFrom<PyList> for Vec<T>
565where
566 T: PyTryFrom<PyAny>,
567{
568 fn py_try_from(py: Python, py_list: &PyList) -> PyResult<Self> {
569 let mut list = Self::with_capacity(py_list.len());
570
571 for item in py_list {
572 let item = T::py_try_from(py, item)?;
573 list.push(item);
574 }
575
576 Ok(list)
577 }
578}
579
580impl<T> PyTryFrom<PyAny> for Vec<T>
581where
582 T: PyTryFrom<PyAny>,
583{
584 fn py_try_from(py: Python, item: &PyAny) -> PyResult<Self> {
585 let actual: &PyList = item.downcast()?;
586 Self::py_try_from(py, actual)
587 }
588}
589
590impl<T> PyTryFrom<Py<PyList>> for Box<[T]>
591where
592 T: PyTryFrom<PyAny>,
593{
594 fn py_try_from(py: Python, py_list: &Py<PyList>) -> PyResult<Self> {
595 Self::py_try_from(py, py_list.as_ref(py))
596 }
597}
598
599impl<T> PyTryFrom<PyList> for Box<[T]>
600where
601 T: PyTryFrom<PyAny>,
602{
603 fn py_try_from(py: Python, py_list: &PyList) -> PyResult<Self> {
604 Vec::py_try_from(py, py_list).map(From::from)
605 }
606}
607
608impl<T> PyTryFrom<PyAny> for Box<[T]>
609where
610 T: PyTryFrom<PyAny>,
611{
612 fn py_try_from(py: Python, item: &PyAny) -> PyResult<Self> {
613 let actual: &PyList = item.downcast()?;
614 Self::py_try_from(py, actual)
615 }
616}
617
618impl<T, P> PyTryFrom<Option<P>> for Option<T>
621where
622 T: PyTryFrom<P>,
623{
624 fn py_try_from(py: Python, item: &Option<P>) -> PyResult<Self> {
625 item.as_ref()
626 .map_or_else(|| Ok(None), |item| T::py_try_from(py, item).map(Some))
627 }
628}
629
630impl_try_from_self_python!(PySet);
633
634impl<T, P, Hasher> PyTryFrom<HashSet<P, Hasher>> for HashSet<T, Hasher>
635where
636 T: Eq + std::hash::Hash + PyTryFrom<P>,
637 Hasher: std::hash::BuildHasher + Default,
638{
639 fn py_try_from(py: Python, set: &HashSet<P, Hasher>) -> PyResult<Self> {
640 set.iter().map(|item| T::py_try_from(py, item)).collect()
641 }
642}
643
644impl<T, Hasher> PyTryFrom<Py<PySet>> for HashSet<T, Hasher>
645where
646 T: Eq + std::hash::Hash + PyTryFrom<PyAny>,
647 Hasher: std::hash::BuildHasher + Default,
648{
649 fn py_try_from(py: Python, set: &Py<PySet>) -> PyResult<Self> {
650 Self::py_try_from(py, set.as_ref(py))
651 }
652}
653
654impl<T, Hasher> PyTryFrom<PySet> for HashSet<T, Hasher>
655where
656 T: Eq + std::hash::Hash + PyTryFrom<PyAny>,
657 Hasher: std::hash::BuildHasher + Default,
658{
659 fn py_try_from(py: Python, set: &PySet) -> PyResult<Self> {
660 let mut map = Self::with_capacity_and_hasher(set.len(), Hasher::default());
661 for item in set {
662 let item = T::py_try_from(py, item)?;
663 map.insert(item);
664 }
665 Ok(map)
666 }
667}
668
669impl<T, Hasher> PyTryFrom<PyAny> for HashSet<T, Hasher>
670where
671 T: Eq + std::hash::Hash + PyTryFrom<PyAny>,
672 Hasher: std::hash::BuildHasher + Default,
673{
674 fn py_try_from(py: Python, item: &PyAny) -> PyResult<Self> {
675 let set: &PySet = item.downcast()?;
676 Self::py_try_from(py, set)
677 }
678}
679
680impl<T, P> PyTryFrom<BTreeSet<P>> for BTreeSet<T>
681where
682 T: Ord + PyTryFrom<P>,
683{
684 fn py_try_from(py: Python, set: &BTreeSet<P>) -> PyResult<Self> {
685 set.iter().map(|item| T::py_try_from(py, item)).collect()
686 }
687}
688
689impl<T> PyTryFrom<Py<PySet>> for BTreeSet<T>
690where
691 T: Ord + PyTryFrom<PyAny>,
692{
693 fn py_try_from(py: Python, set: &Py<PySet>) -> PyResult<Self> {
694 Self::py_try_from(py, set.as_ref(py))
695 }
696}
697
698impl<T> PyTryFrom<PySet> for BTreeSet<T>
699where
700 T: Ord + PyTryFrom<PyAny>,
701{
702 fn py_try_from(py: Python, set: &PySet) -> PyResult<Self> {
703 let mut map = Self::new();
704 for item in set {
705 let item = T::py_try_from(py, item)?;
706 map.insert(item);
707 }
708 Ok(map)
709 }
710}
711
712impl<T> PyTryFrom<PyAny> for BTreeSet<T>
713where
714 T: Ord + PyTryFrom<PyAny>,
715{
716 fn py_try_from(py: Python, set: &PyAny) -> PyResult<Self> {
717 let set: &PySet = set.downcast()?;
718 <Self as PyTryFrom<PySet>>::py_try_from(py, set)
719 }
720}
721
722impl_try_from_self_python!(PyString);
725impl_try_from_self_rust!(String);
726impl_try_from_py_native!(PyString => String);
727
728private_impl_py_try_from_with_pyany!(&item, _py, PyString => String {
729 item.to_str().map(ToString::to_string)
730});
731
732#[cfg(feature = "time")]
735impl_try_from_self_python!(PyTime);
736
737#[cfg(feature = "time")]
738impl_try_from_self_rust!((Time, Option<UtcOffset>));
739#[cfg(feature = "time")]
740impl_try_from_py_native!(PyTime => (Time, Option<UtcOffset>));
741
742#[cfg(feature = "time")]
743private_impl_py_try_from_with_pyany!(&item, py, PyTime => (Time, Option<UtcOffset>) {
744 let hour: u8 = item.getattr("hour")?.downcast::<PyInt>()?.extract()?;
745 let minute: u8 = item.getattr("minute")?.downcast::<PyInt>()?.extract()?;
746 let seconds: u8 = item.getattr("second")?.downcast::<PyInt>()?.extract()?;
747 let microseconds: u32 = item.getattr("microsecond")?.downcast::<PyInt>()?.extract()?;
748 let tzinfo: Option<&PyTzInfo> = item.getattr("tzinfo")?.extract()?;
749 let offset = tzinfo.map(|tzinfo| UtcOffset::py_try_from(py, tzinfo)).transpose()?;
750 let timestamp = Time::from_hms_micro(hour, minute, seconds, microseconds).map_err(|err| {
751 PyValueError::new_err(format!("Could not create a Rust Time from {hour}:{minute}:{seconds}.{microseconds}: {err}"))
752 })?;
753 Ok((timestamp, offset))
754});
755
756#[cfg(feature = "time")]
759impl_try_from_self_python!(PyTzInfo);
760
761#[cfg(feature = "time")]
762impl_try_from_self_rust!(UtcOffset);
763#[cfg(feature = "time")]
764impl_try_from_py_native!(PyTzInfo => UtcOffset);
765
766#[cfg(feature = "time")]
767private_impl_py_try_from_with_pyany!(&item, py, PyTzInfo => UtcOffset {
768 let args: Py<PyAny> = (py.None(),).to_object(py);
769 let args: &PyTuple = args.extract(py)?;
770 let duration = item.call_method1("utcoffset", args).map(|any| Duration::py_try_from(py, any))??;
771 let seconds = duration.whole_seconds();
772 let seconds = seconds.try_into().map_err(|_| {
773 PyValueError::new_err(format!("Cannot create a Rust UtcOffset from {seconds} seconds -- too many seconds!"))
774 })?;
775 let offset = Self::from_whole_seconds(seconds).map_err(|_| {
776 PyValueError::new_err(format!("Cannot create a Rust UtcOffset from {seconds} seconds -- too many seconds!"))
777 })?;
778 Ok(offset)
779});
780
781