From 6a527ad2afe48a3978510ae95b4752bfd7ceb836 Mon Sep 17 00:00:00 2001 From: Ishan Bhanuka Date: Fri, 22 Nov 2024 02:55:17 +0530 Subject: [PATCH 01/15] Wip: parquet catalog --- nautilus_core/Cargo.lock | 1 + nautilus_core/adapters/src/tardis/replay.rs | 4 +- nautilus_core/persistence/Cargo.toml | 1 + .../persistence/src/backend/catalog.rs | 191 ++++++++++++++++++ nautilus_core/persistence/src/backend/mod.rs | 1 + nautilus_core/serialization/src/parquet.rs | 17 +- 6 files changed, 210 insertions(+), 5 deletions(-) create mode 100644 nautilus_core/persistence/src/backend/catalog.rs diff --git a/nautilus_core/Cargo.lock b/nautilus_core/Cargo.lock index b753c1c8aa41..8893e0bb4e92 100644 --- a/nautilus_core/Cargo.lock +++ b/nautilus_core/Cargo.lock @@ -3188,6 +3188,7 @@ dependencies = [ "criterion", "datafusion", "futures", + "itertools 0.13.0", "log", "nautilus-core", "nautilus-model", diff --git a/nautilus_core/adapters/src/tardis/replay.rs b/nautilus_core/adapters/src/tardis/replay.rs index a226fb4dee44..2b246ea535dd 100644 --- a/nautilus_core/adapters/src/tardis/replay.rs +++ b/nautilus_core/adapters/src/tardis/replay.rs @@ -430,7 +430,7 @@ fn batch_and_write_bars(bars: Vec, bar_type: &BarType, date: NaiveDate, pat }; let filepath = path.join(parquet_filepath_bars(bar_type, date)); - match write_batch_to_parquet(&batch, &filepath, None) { + match write_batch_to_parquet(batch, &filepath, None) { Ok(()) => tracing::info!("File written: {}", filepath.display()), Err(e) => tracing::error!("Error writing {}: {e:?}", filepath.display()), } @@ -463,7 +463,7 @@ fn write_batch( path: &Path, ) { let filepath = path.join(parquet_filepath(typename, instrument_id, date)); - match write_batch_to_parquet(&batch, &filepath, None) { + match write_batch_to_parquet(batch, &filepath, None) { Ok(()) => tracing::info!("File written: {}", filepath.display()), Err(e) => tracing::error!("Error writing {}: {e:?}", filepath.display()), } diff --git a/nautilus_core/persistence/Cargo.toml b/nautilus_core/persistence/Cargo.toml index 45243957e0c5..f5bff2587700 100644 --- a/nautilus_core/persistence/Cargo.toml +++ b/nautilus_core/persistence/Cargo.toml @@ -25,6 +25,7 @@ thiserror = { workspace = true } binary-heap-plus = "0.5.0" compare = "0.1.0" datafusion = { version = "43.0.0", default-features = false, features = ["compression", "regex_expressions", "unicode_expressions", "pyarrow"] } +itertools.workspace = true [dev-dependencies] nautilus-test-kit = { path = "../test_kit" } diff --git a/nautilus_core/persistence/src/backend/catalog.rs b/nautilus_core/persistence/src/backend/catalog.rs new file mode 100644 index 000000000000..689da3a62aa0 --- /dev/null +++ b/nautilus_core/persistence/src/backend/catalog.rs @@ -0,0 +1,191 @@ +use itertools::Itertools; +use log::info; +use nautilus_serialization::arrow::{ + bars_to_arrow_record_batch_bytes, order_book_deltas_to_arrow_record_batch_bytes, + order_book_depth10_to_arrow_record_batch_bytes, quote_ticks_to_arrow_record_batch_bytes, + trade_ticks_to_arrow_record_batch_bytes, +}; +use std::path::PathBuf; + +use datafusion::arrow::record_batch::RecordBatch; +use nautilus_model::data::{Data, GetTsInit}; +use nautilus_serialization::arrow::EncodingError; +use nautilus_serialization::parquet::write_batches_to_parquet; + +pub struct ParquetCatalog { + base_path: PathBuf, + batch_size: usize, +} + +impl ParquetCatalog { + pub fn new(base_path: PathBuf, batch_size: Option) -> Self { + Self { + base_path, + batch_size: batch_size.unwrap_or(5000), + } + } + + fn make_path(&self, type_name: &str, instrument_id: Option<&str>) -> PathBuf { + let mut path = self.base_path.join("data").join(type_name.to_lowercase()); + + if let Some(id) = instrument_id { + path = path.join(id); + } + + std::fs::create_dir_all(&path).expect("Failed to create directory"); + let file_path = path.join("data.parquet"); + info!("Created directory path: {:?}", file_path); + file_path + } + + fn check_ascending_timestamps(data: &[T], type_name: &str) { + assert!( + data.windows(2).all(|w| w[0].ts_init() <= w[1].ts_init()), + "{} timestamps must be in ascending order", + type_name + ); + } + + fn write_batch_to_parquet(batch: RecordBatch, path: PathBuf, type_name: &str) { + info!("Writing {} data to {:?}", type_name, path); + write_batches_to_parquet(&[batch], &path, None) + .expect(&format!("Failed to write {} to parquet", type_name)); + } + + fn write_data( + &self, + items: Vec, + extract_fn: F, + to_batch_fn: fn(Vec) -> Result, + type_name: &str, + instrument_id: &str, + ) where + F: Fn(Data) -> Option, + T: GetTsInit, + { + let data: Vec = items.into_iter().filter_map(extract_fn).collect(); + + ParquetCatalog::check_ascending_timestamps(&data, type_name); + + let path = self.make_path(type_name, Some(instrument_id)); + info!( + "Processing {} data in chunks of {} to {:?}", + type_name, self.batch_size, path + ); + + // Convert all chunks to record batches first + let batches: Vec = data + .into_iter() + .chunks(self.batch_size) + .into_iter() + .map(|chunk| match to_batch_fn(chunk.collect()) { + Ok(batch) => batch, + Err(e) => { + panic!( + "Failed to convert {} chunk to record batch: {:?}", + type_name, e + ) + } + }) + .collect(); + + // Write all batches to parquet file + info!( + "Writing {} batches of {} data to {:?}", + batches.len(), + type_name, + path + ); + write_batches_to_parquet(&batches, &path, None) + .expect(&format!("Failed to write {} to parquet", type_name)); + } + + pub fn write_data_enum(&self, data: Vec) { + // Group data by variant + let grouped_data = data.into_iter().chunk_by(|d| std::mem::discriminant(d)); + + for (_, group) in grouped_data.into_iter() { + let items: Vec<_> = group.collect(); + if items.is_empty() { + continue; + } + + // Match on the first item to determine the variant type + match items[0] { + Data::Delta(ref delta) => { + self.write_data( + items, + |d| { + if let Data::Delta(d) = d { + Some(d) + } else { + None + } + }, + order_book_deltas_to_arrow_record_batch_bytes, + "OrderBookDelta", + &delta.instrument_id.to_string(), + ); + } + Data::Depth10(depth) => { + self.write_data( + items, + |d| { + if let Data::Depth10(d) = d { + Some(d) + } else { + None + } + }, + order_book_depth10_to_arrow_record_batch_bytes, + "OrderBookDepth10", + &depth.instrument_id.to_string(), + ); + } + Data::Quote(quote) => { + self.write_data( + items, + |d| { + if let Data::Quote(d) = d { + Some(d) + } else { + None + } + }, + quote_ticks_to_arrow_record_batch_bytes, + "QuoteTick", + "e.instrument_id.to_string(), + ); + } + Data::Trade(trade) => { + self.write_data( + items, + |d| { + if let Data::Trade(d) = d { + Some(d) + } else { + None + } + }, + trade_ticks_to_arrow_record_batch_bytes, + "TradeTick", + &trade.instrument_id.to_string(), + ); + } + Data::Bar(bar) => { + self.write_data( + items, + |d| if let Data::Bar(d) = d { Some(d) } else { None }, + bars_to_arrow_record_batch_bytes, + "Bar", + &bar.bar_type.to_string(), + ); + } + Data::Deltas(_) => { + // Handle OrderBookDeltas_API if needed + continue; + } + } + } + } +} diff --git a/nautilus_core/persistence/src/backend/mod.rs b/nautilus_core/persistence/src/backend/mod.rs index 10062490b8d6..1bb9e176bc3e 100644 --- a/nautilus_core/persistence/src/backend/mod.rs +++ b/nautilus_core/persistence/src/backend/mod.rs @@ -17,3 +17,4 @@ pub mod kmerge_batch; pub mod session; +pub mod catalog; diff --git a/nautilus_core/serialization/src/parquet.rs b/nautilus_core/serialization/src/parquet.rs index 36697491b87e..56eaf23d6d57 100644 --- a/nautilus_core/serialization/src/parquet.rs +++ b/nautilus_core/serialization/src/parquet.rs @@ -20,7 +20,16 @@ use parquet::{arrow::ArrowWriter, basic::ZstdLevel, file::properties::WriterProp /// Writes a `RecordBatch` to a Parquet file at the specified `filepath`, with optional compression. pub fn write_batch_to_parquet( - batch: &RecordBatch, + batch: RecordBatch, + filepath: &Path, + compression: Option, +) -> Result<(), Box> { + write_batches_to_parquet(&[batch], filepath, compression) +} + +/// Writes a `RecordBatch` to a Parquet file at the specified `filepath`, with optional compression. +pub fn write_batches_to_parquet( + batches: &[RecordBatch], filepath: &Path, compression: Option, ) -> Result<(), Box> { @@ -37,8 +46,10 @@ pub fn write_batch_to_parquet( .set_compression(compression.unwrap_or(default_compression)) .build(); - let mut writer = ArrowWriter::try_new(file, batch.schema(), Some(writer_props))?; - writer.write(batch)?; + let mut writer = ArrowWriter::try_new(file, batches[0].schema(), Some(writer_props))?; + for batch in batches { + writer.write(batch)?; + } writer.close()?; Ok(()) From 65e99b929a6c21d6d852a0f562ddc83793cae9eb Mon Sep 17 00:00:00 2001 From: Ishan Bhanuka Date: Sat, 23 Nov 2024 22:18:08 +0530 Subject: [PATCH 02/15] Refactor data types for generic catalog writing --- nautilus_core/model/src/data/bar.rs | 4 + nautilus_core/model/src/data/delta.rs | 23 +++ nautilus_core/model/src/data/depth.rs | 8 + nautilus_core/model/src/data/quote.rs | 8 + nautilus_core/model/src/data/trade.rs | 8 + .../persistence/src/backend/catalog.rs | 158 ++++++------------ nautilus_core/serialization/src/arrow/bar.rs | 4 + .../serialization/src/arrow/delta.rs | 4 + .../serialization/src/arrow/depth.rs | 4 + nautilus_core/serialization/src/arrow/mod.rs | 50 +----- .../serialization/src/arrow/quote.rs | 4 + .../serialization/src/arrow/trade.rs | 4 + 12 files changed, 127 insertions(+), 152 deletions(-) diff --git a/nautilus_core/model/src/data/bar.rs b/nautilus_core/model/src/data/bar.rs index 1a433a25fa0e..fbbcc96e8f8c 100644 --- a/nautilus_core/model/src/data/bar.rs +++ b/nautilus_core/model/src/data/bar.rs @@ -585,6 +585,10 @@ impl Bar { self.bar_type.instrument_id() } + pub fn metadata(&self) -> HashMap { + Self::get_metadata(&self.bar_type, self.open.precision, self.volume.precision) + } + /// Returns the metadata for the type, for use with serialization formats. #[must_use] pub fn get_metadata( diff --git a/nautilus_core/model/src/data/delta.rs b/nautilus_core/model/src/data/delta.rs index de0ba43edd6a..5dcbdc01c920 100644 --- a/nautilus_core/model/src/data/delta.rs +++ b/nautilus_core/model/src/data/delta.rs @@ -103,6 +103,29 @@ impl OrderBookDelta { } } + pub fn metadata(&self) -> HashMap { + // TODO: handle second delta check differently + // Check if price and size precision are both zero + // if price_precision == 0 && size_precision == 0 { + // // If both are zero, try the second delta if available + // if data.len() > 1 { + // let second = &data[1]; + // price_precision = second.order.price.precision; + // size_precision = second.order.size.precision; + // } else { + // // If there is no second delta, use zero precision + // price_precision = 0; + // size_precision = 0; + // } + // } + + Self::get_metadata( + &self.instrument_id, + self.order.price.precision, + self.order.size.precision, + ) + } + /// Returns the metadata for the type, for use with serialization formats. #[must_use] pub fn get_metadata( diff --git a/nautilus_core/model/src/data/depth.rs b/nautilus_core/model/src/data/depth.rs index 16f9e927042f..3bda5cc71e32 100644 --- a/nautilus_core/model/src/data/depth.rs +++ b/nautilus_core/model/src/data/depth.rs @@ -94,6 +94,14 @@ impl OrderBookDepth10 { } } + pub fn metadata(&self) -> HashMap { + Self::get_metadata( + &self.instrument_id, + self.bids[0].price.precision, + self.bids[0].size.precision, + ) + } + /// Returns the metadata for the type, for use with serialization formats. #[must_use] pub fn get_metadata( diff --git a/nautilus_core/model/src/data/quote.rs b/nautilus_core/model/src/data/quote.rs index a9c0c0f968c3..98b74201e3a6 100644 --- a/nautilus_core/model/src/data/quote.rs +++ b/nautilus_core/model/src/data/quote.rs @@ -130,6 +130,14 @@ impl QuoteTick { }) } + pub fn metadata(&self) -> HashMap { + Self::get_metadata( + &self.instrument_id, + self.bid_price.precision, + self.bid_size.precision, + ) + } + /// Returns the metadata for the type, for use with serialization formats. #[must_use] pub fn get_metadata( diff --git a/nautilus_core/model/src/data/trade.rs b/nautilus_core/model/src/data/trade.rs index 627825bded42..bf3c528855d3 100644 --- a/nautilus_core/model/src/data/trade.rs +++ b/nautilus_core/model/src/data/trade.rs @@ -82,6 +82,14 @@ impl TradeTick { } } + pub fn metadata(&self) -> HashMap { + Self::get_metadata( + &self.instrument_id, + self.price.precision, + self.size.precision, + ) + } + /// Returns the metadata for the type, for use with serialization formats. #[must_use] pub fn get_metadata( diff --git a/nautilus_core/persistence/src/backend/catalog.rs b/nautilus_core/persistence/src/backend/catalog.rs index 689da3a62aa0..8738318f5a86 100644 --- a/nautilus_core/persistence/src/backend/catalog.rs +++ b/nautilus_core/persistence/src/backend/catalog.rs @@ -1,15 +1,15 @@ use itertools::Itertools; use log::info; -use nautilus_serialization::arrow::{ - bars_to_arrow_record_batch_bytes, order_book_deltas_to_arrow_record_batch_bytes, - order_book_depth10_to_arrow_record_batch_bytes, quote_ticks_to_arrow_record_batch_bytes, - trade_ticks_to_arrow_record_batch_bytes, -}; +use nautilus_model::data::bar::Bar; +use nautilus_model::data::delta::OrderBookDelta; +use nautilus_model::data::depth::OrderBookDepth10; +use nautilus_model::data::quote::QuoteTick; +use nautilus_model::data::trade::TradeTick; +use nautilus_serialization::arrow::EncodeToRecordBatch; use std::path::PathBuf; use datafusion::arrow::record_batch::RecordBatch; use nautilus_model::data::{Data, GetTsInit}; -use nautilus_serialization::arrow::EncodingError; use nautilus_serialization::parquet::write_batches_to_parquet; pub struct ParquetCatalog { @@ -46,46 +46,40 @@ impl ParquetCatalog { ); } - fn write_batch_to_parquet(batch: RecordBatch, path: PathBuf, type_name: &str) { + pub fn write_batch_to_parquet(batch: RecordBatch, path: PathBuf, type_name: &str) { info!("Writing {} data to {:?}", type_name, path); write_batches_to_parquet(&[batch], &path, None) - .expect(&format!("Failed to write {} to parquet", type_name)); + .unwrap_or_else(|_| panic!("Failed to write {} to parquet", type_name)); } - fn write_data( - &self, - items: Vec, - extract_fn: F, - to_batch_fn: fn(Vec) -> Result, - type_name: &str, - instrument_id: &str, - ) where - F: Fn(Data) -> Option, - T: GetTsInit, + fn write_data(&self, data: Vec, type_name: &str) + where + T: GetTsInit + EncodeToRecordBatch, { - let data: Vec = items.into_iter().filter_map(extract_fn).collect(); - ParquetCatalog::check_ascending_timestamps(&data, type_name); - let path = self.make_path(type_name, Some(instrument_id)); + // TODO: use instrument id + let path = self.make_path(type_name, None); info!( "Processing {} data in chunks of {} to {:?}", type_name, self.batch_size, path ); + // TODO: get instrument id from batch metadata // Convert all chunks to record batches first let batches: Vec = data .into_iter() .chunks(self.batch_size) .into_iter() - .map(|chunk| match to_batch_fn(chunk.collect()) { - Ok(batch) => batch, - Err(e) => { - panic!( - "Failed to convert {} chunk to record batch: {:?}", - type_name, e - ) - } + .map(|chunk| { + // Take first element and extract metadata + // SAFETY: Unwrap safe as already checked that `data` not empty + let data = chunk.collect_vec(); + let first = data + .first() + .expect("Encode to record batch expects non-empty chunk"); + let metadata = first.metadata(); + T::encode_batch(&metadata, &data).expect("Expected to encode batch") }) .collect(); @@ -97,95 +91,41 @@ impl ParquetCatalog { path ); write_batches_to_parquet(&batches, &path, None) - .expect(&format!("Failed to write {} to parquet", type_name)); + .unwrap_or_else(|_| panic!("Failed to write {} to parquet", type_name)); } pub fn write_data_enum(&self, data: Vec) { - // Group data by variant - let grouped_data = data.into_iter().chunk_by(|d| std::mem::discriminant(d)); - - for (_, group) in grouped_data.into_iter() { - let items: Vec<_> = group.collect(); - if items.is_empty() { - continue; - } - - // Match on the first item to determine the variant type - match items[0] { - Data::Delta(ref delta) => { - self.write_data( - items, - |d| { - if let Data::Delta(d) = d { - Some(d) - } else { - None - } - }, - order_book_deltas_to_arrow_record_batch_bytes, - "OrderBookDelta", - &delta.instrument_id.to_string(), - ); - } - Data::Depth10(depth) => { - self.write_data( - items, - |d| { - if let Data::Depth10(d) = d { - Some(d) - } else { - None - } - }, - order_book_depth10_to_arrow_record_batch_bytes, - "OrderBookDepth10", - &depth.instrument_id.to_string(), - ); + let mut delta: Vec = Vec::new(); + let mut depth10: Vec = Vec::new(); + let mut quote: Vec = Vec::new(); + let mut trade: Vec = Vec::new(); + let mut bar: Vec = Vec::new(); + + for d in data.iter().cloned() { + match d { + Data::Delta(d) => { + delta.push(d); } - Data::Quote(quote) => { - self.write_data( - items, - |d| { - if let Data::Quote(d) = d { - Some(d) - } else { - None - } - }, - quote_ticks_to_arrow_record_batch_bytes, - "QuoteTick", - "e.instrument_id.to_string(), - ); + Data::Depth10(d) => { + depth10.push(d); } - Data::Trade(trade) => { - self.write_data( - items, - |d| { - if let Data::Trade(d) = d { - Some(d) - } else { - None - } - }, - trade_ticks_to_arrow_record_batch_bytes, - "TradeTick", - &trade.instrument_id.to_string(), - ); + Data::Quote(d) => { + quote.push(d); } - Data::Bar(bar) => { - self.write_data( - items, - |d| if let Data::Bar(d) = d { Some(d) } else { None }, - bars_to_arrow_record_batch_bytes, - "Bar", - &bar.bar_type.to_string(), - ); + Data::Trade(d) => { + trade.push(d); } - Data::Deltas(_) => { - // Handle OrderBookDeltas_API if needed - continue; + Data::Bar(d) => { + bar.push(d); } + Data::Deltas(_) => continue, } } + + self.write_data(delta, "OrderBookDelta"); + self.write_data(depth10, "OrderBookDepth10"); + self.write_data(quote, "QuoteTick"); + self.write_data(trade, "TradeTick"); + self.write_data(bar, "Bar"); } } diff --git a/nautilus_core/serialization/src/arrow/bar.rs b/nautilus_core/serialization/src/arrow/bar.rs index 76f0c18d05aa..f21ce8b4c3b8 100644 --- a/nautilus_core/serialization/src/arrow/bar.rs +++ b/nautilus_core/serialization/src/arrow/bar.rs @@ -117,6 +117,10 @@ impl EncodeToRecordBatch for Bar { ], ) } + + fn metadata(&self) -> HashMap { + self.metadata() + } } impl DecodeFromRecordBatch for Bar { diff --git a/nautilus_core/serialization/src/arrow/delta.rs b/nautilus_core/serialization/src/arrow/delta.rs index 40ec9a93d676..9e97db817145 100644 --- a/nautilus_core/serialization/src/arrow/delta.rs +++ b/nautilus_core/serialization/src/arrow/delta.rs @@ -131,6 +131,10 @@ impl EncodeToRecordBatch for OrderBookDelta { ], ) } + + fn metadata(&self) -> HashMap { + self.metadata() + } } impl DecodeFromRecordBatch for OrderBookDelta { diff --git a/nautilus_core/serialization/src/arrow/depth.rs b/nautilus_core/serialization/src/arrow/depth.rs index 198475b21da2..f2c191fd3056 100644 --- a/nautilus_core/serialization/src/arrow/depth.rs +++ b/nautilus_core/serialization/src/arrow/depth.rs @@ -223,6 +223,10 @@ impl EncodeToRecordBatch for OrderBookDepth10 { RecordBatch::try_new(Self::get_schema(Some(metadata.clone())).into(), columns) } + + fn metadata(&self) -> HashMap { + self.metadata() + } } impl DecodeFromRecordBatch for OrderBookDepth10 { diff --git a/nautilus_core/serialization/src/arrow/mod.rs b/nautilus_core/serialization/src/arrow/mod.rs index 21f34eb15314..184a975d60a1 100644 --- a/nautilus_core/serialization/src/arrow/mod.rs +++ b/nautilus_core/serialization/src/arrow/mod.rs @@ -95,6 +95,8 @@ where metadata: &HashMap, data: &[Self], ) -> Result; + + fn metadata(&self) -> HashMap; } pub trait DecodeFromRecordBatch @@ -162,25 +164,7 @@ pub fn order_book_deltas_to_arrow_record_batch_bytes( // Take first element and extract metadata // SAFETY: Unwrap safe as already checked that `data` not empty let first = data.first().unwrap(); - let mut price_precision = first.order.price.precision; - let mut size_precision = first.order.size.precision; - - // Check if price and size precision are both zero - if price_precision == 0 && size_precision == 0 { - // If both are zero, try the second delta if available - if data.len() > 1 { - let second = &data[1]; - price_precision = second.order.price.precision; - size_precision = second.order.size.precision; - } else { - // If there is no second delta, use zero precision - price_precision = 0; - size_precision = 0; - } - } - - let metadata = - OrderBookDelta::get_metadata(&first.instrument_id, price_precision, size_precision); + let metadata = first.metadata(); OrderBookDelta::encode_batch(&metadata, &data).map_err(EncodingError::ArrowError) } @@ -194,12 +178,7 @@ pub fn order_book_depth10_to_arrow_record_batch_bytes( // Take first element and extract metadata // SAFETY: Unwrap safe as already checked that `data` not empty let first = data.first().unwrap(); - let metadata = OrderBookDepth10::get_metadata( - &first.instrument_id, - first.bids[0].price.precision, - first.bids[0].size.precision, - ); - + let metadata = first.metadata(); OrderBookDepth10::encode_batch(&metadata, &data).map_err(EncodingError::ArrowError) } @@ -213,12 +192,7 @@ pub fn quote_ticks_to_arrow_record_batch_bytes( // Take first element and extract metadata // SAFETY: Unwrap safe as already checked that `data` not empty let first = data.first().unwrap(); - let metadata = QuoteTick::get_metadata( - &first.instrument_id, - first.bid_price.precision, - first.bid_size.precision, - ); - + let metadata = first.metadata(); QuoteTick::encode_batch(&metadata, &data).map_err(EncodingError::ArrowError) } @@ -232,12 +206,7 @@ pub fn trade_ticks_to_arrow_record_batch_bytes( // Take first element and extract metadata // SAFETY: Unwrap safe as already checked that `data` not empty let first = data.first().unwrap(); - let metadata = TradeTick::get_metadata( - &first.instrument_id, - first.price.precision, - first.size.precision, - ); - + let metadata = first.metadata(); TradeTick::encode_batch(&metadata, &data).map_err(EncodingError::ArrowError) } @@ -249,11 +218,6 @@ pub fn bars_to_arrow_record_batch_bytes(data: Vec) -> Result HashMap { + self.metadata() + } } impl DecodeFromRecordBatch for QuoteTick { diff --git a/nautilus_core/serialization/src/arrow/trade.rs b/nautilus_core/serialization/src/arrow/trade.rs index b90178c5162f..10aaddd32385 100644 --- a/nautilus_core/serialization/src/arrow/trade.rs +++ b/nautilus_core/serialization/src/arrow/trade.rs @@ -116,6 +116,10 @@ impl EncodeToRecordBatch for TradeTick { ], ) } + + fn metadata(&self) -> HashMap { + self.metadata() + } } impl DecodeFromRecordBatch for TradeTick { From 25f50332bfc0cc99e13efab473416bae978d9a11 Mon Sep 17 00:00:00 2001 From: Ishan Bhanuka Date: Sun, 24 Nov 2024 10:41:59 +0530 Subject: [PATCH 03/15] Simplify schema metadata logic --- nautilus_core/model/src/data/bar.rs | 4 -- nautilus_core/model/src/data/delta.rs | 23 ------- nautilus_core/model/src/data/depth.rs | 8 --- nautilus_core/model/src/data/quote.rs | 8 --- nautilus_core/model/src/data/trade.rs | 8 --- .../persistence/src/backend/catalog.rs | 63 +++++++++---------- nautilus_core/persistence/src/backend/mod.rs | 2 +- nautilus_core/serialization/src/arrow/bar.rs | 2 +- .../serialization/src/arrow/delta.rs | 21 ++++++- .../serialization/src/arrow/depth.rs | 6 +- nautilus_core/serialization/src/arrow/mod.rs | 6 ++ .../serialization/src/arrow/quote.rs | 6 +- .../serialization/src/arrow/trade.rs | 6 +- 13 files changed, 71 insertions(+), 92 deletions(-) diff --git a/nautilus_core/model/src/data/bar.rs b/nautilus_core/model/src/data/bar.rs index fbbcc96e8f8c..1a433a25fa0e 100644 --- a/nautilus_core/model/src/data/bar.rs +++ b/nautilus_core/model/src/data/bar.rs @@ -585,10 +585,6 @@ impl Bar { self.bar_type.instrument_id() } - pub fn metadata(&self) -> HashMap { - Self::get_metadata(&self.bar_type, self.open.precision, self.volume.precision) - } - /// Returns the metadata for the type, for use with serialization formats. #[must_use] pub fn get_metadata( diff --git a/nautilus_core/model/src/data/delta.rs b/nautilus_core/model/src/data/delta.rs index 5dcbdc01c920..de0ba43edd6a 100644 --- a/nautilus_core/model/src/data/delta.rs +++ b/nautilus_core/model/src/data/delta.rs @@ -103,29 +103,6 @@ impl OrderBookDelta { } } - pub fn metadata(&self) -> HashMap { - // TODO: handle second delta check differently - // Check if price and size precision are both zero - // if price_precision == 0 && size_precision == 0 { - // // If both are zero, try the second delta if available - // if data.len() > 1 { - // let second = &data[1]; - // price_precision = second.order.price.precision; - // size_precision = second.order.size.precision; - // } else { - // // If there is no second delta, use zero precision - // price_precision = 0; - // size_precision = 0; - // } - // } - - Self::get_metadata( - &self.instrument_id, - self.order.price.precision, - self.order.size.precision, - ) - } - /// Returns the metadata for the type, for use with serialization formats. #[must_use] pub fn get_metadata( diff --git a/nautilus_core/model/src/data/depth.rs b/nautilus_core/model/src/data/depth.rs index 3bda5cc71e32..16f9e927042f 100644 --- a/nautilus_core/model/src/data/depth.rs +++ b/nautilus_core/model/src/data/depth.rs @@ -94,14 +94,6 @@ impl OrderBookDepth10 { } } - pub fn metadata(&self) -> HashMap { - Self::get_metadata( - &self.instrument_id, - self.bids[0].price.precision, - self.bids[0].size.precision, - ) - } - /// Returns the metadata for the type, for use with serialization formats. #[must_use] pub fn get_metadata( diff --git a/nautilus_core/model/src/data/quote.rs b/nautilus_core/model/src/data/quote.rs index 98b74201e3a6..a9c0c0f968c3 100644 --- a/nautilus_core/model/src/data/quote.rs +++ b/nautilus_core/model/src/data/quote.rs @@ -130,14 +130,6 @@ impl QuoteTick { }) } - pub fn metadata(&self) -> HashMap { - Self::get_metadata( - &self.instrument_id, - self.bid_price.precision, - self.bid_size.precision, - ) - } - /// Returns the metadata for the type, for use with serialization formats. #[must_use] pub fn get_metadata( diff --git a/nautilus_core/model/src/data/trade.rs b/nautilus_core/model/src/data/trade.rs index bf3c528855d3..627825bded42 100644 --- a/nautilus_core/model/src/data/trade.rs +++ b/nautilus_core/model/src/data/trade.rs @@ -82,14 +82,6 @@ impl TradeTick { } } - pub fn metadata(&self) -> HashMap { - Self::get_metadata( - &self.instrument_id, - self.price.precision, - self.size.precision, - ) - } - /// Returns the metadata for the type, for use with serialization formats. #[must_use] pub fn get_metadata( diff --git a/nautilus_core/persistence/src/backend/catalog.rs b/nautilus_core/persistence/src/backend/catalog.rs index 8738318f5a86..a6a286606f71 100644 --- a/nautilus_core/persistence/src/backend/catalog.rs +++ b/nautilus_core/persistence/src/backend/catalog.rs @@ -25,7 +25,7 @@ impl ParquetCatalog { } } - fn make_path(&self, type_name: &str, instrument_id: Option<&str>) -> PathBuf { + fn make_path(&self, type_name: &str, instrument_id: Option<&String>) -> PathBuf { let mut path = self.base_path.join("data").join(type_name.to_lowercase()); if let Some(id) = instrument_id { @@ -46,52 +46,45 @@ impl ParquetCatalog { ); } - pub fn write_batch_to_parquet(batch: RecordBatch, path: PathBuf, type_name: &str) { - info!("Writing {} data to {:?}", type_name, path); - write_batches_to_parquet(&[batch], &path, None) - .unwrap_or_else(|_| panic!("Failed to write {} to parquet", type_name)); - } - - fn write_data(&self, data: Vec, type_name: &str) + pub fn data_to_record_batches(&self, data: Vec) -> Vec where T: GetTsInit + EncodeToRecordBatch, { - ParquetCatalog::check_ascending_timestamps(&data, type_name); - - // TODO: use instrument id - let path = self.make_path(type_name, None); - info!( - "Processing {} data in chunks of {} to {:?}", - type_name, self.batch_size, path - ); - - // TODO: get instrument id from batch metadata - // Convert all chunks to record batches first - let batches: Vec = data - .into_iter() + data.into_iter() .chunks(self.batch_size) .into_iter() .map(|chunk| { // Take first element and extract metadata // SAFETY: Unwrap safe as already checked that `data` not empty let data = chunk.collect_vec(); - let first = data - .first() - .expect("Encode to record batch expects non-empty chunk"); - let metadata = first.metadata(); + let metadata = EncodeToRecordBatch::chunk_metadata(&data); T::encode_batch(&metadata, &data).expect("Expected to encode batch") }) - .collect(); + .collect() + } - // Write all batches to parquet file - info!( - "Writing {} batches of {} data to {:?}", - batches.len(), - type_name, - path - ); - write_batches_to_parquet(&batches, &path, None) - .unwrap_or_else(|_| panic!("Failed to write {} to parquet", type_name)); + fn write_data(&self, data: Vec, type_name: &str) + where + T: GetTsInit + EncodeToRecordBatch, + { + ParquetCatalog::check_ascending_timestamps(&data, type_name); + + let batches = self.data_to_record_batches(data); + if let Some(batch) = batches.first() { + let schema = batch.schema(); + let instrument_id = schema.metadata.get("instrument_id"); + let path = self.make_path(type_name, instrument_id); + + // Write all batches to parquet file + info!( + "Writing {} batches of {} data to {:?}", + batches.len(), + type_name, + path + ); + write_batches_to_parquet(&batches, &path, None) + .unwrap_or_else(|_| panic!("Failed to write {} to parquet", type_name)); + } } pub fn write_data_enum(&self, data: Vec) { diff --git a/nautilus_core/persistence/src/backend/mod.rs b/nautilus_core/persistence/src/backend/mod.rs index 1bb9e176bc3e..8e7024675cd8 100644 --- a/nautilus_core/persistence/src/backend/mod.rs +++ b/nautilus_core/persistence/src/backend/mod.rs @@ -15,6 +15,6 @@ //! Provides an Apache Parquet backend powered by [DataFusion](https://arrow.apache.org/datafusion). +pub mod catalog; pub mod kmerge_batch; pub mod session; -pub mod catalog; diff --git a/nautilus_core/serialization/src/arrow/bar.rs b/nautilus_core/serialization/src/arrow/bar.rs index f21ce8b4c3b8..fff278bdb62f 100644 --- a/nautilus_core/serialization/src/arrow/bar.rs +++ b/nautilus_core/serialization/src/arrow/bar.rs @@ -119,7 +119,7 @@ impl EncodeToRecordBatch for Bar { } fn metadata(&self) -> HashMap { - self.metadata() + Bar::get_metadata(&self.bar_type, self.open.precision, self.volume.precision) } } diff --git a/nautilus_core/serialization/src/arrow/delta.rs b/nautilus_core/serialization/src/arrow/delta.rs index 9e97db817145..931fc7e5f9e4 100644 --- a/nautilus_core/serialization/src/arrow/delta.rs +++ b/nautilus_core/serialization/src/arrow/delta.rs @@ -133,7 +133,26 @@ impl EncodeToRecordBatch for OrderBookDelta { } fn metadata(&self) -> HashMap { - self.metadata() + OrderBookDelta::get_metadata( + &self.instrument_id, + self.order.price.precision, + self.order.size.precision, + ) + } + + fn chunk_metadata(chunk: &[Self]) -> HashMap { + let metadata = chunk + .first() + .map(EncodeToRecordBatch::metadata) + .expect("Chunk should have alteast one element to encode"); + + // If first element precision metadata is 0, try using metadata of second element + metadata + .get("price_precision") + .zip(metadata.get("size_precision")) + .filter(|(p, s)| *p == "0" && *s == "0") + .and_then(|_| chunk.get(2).map(EncodeToRecordBatch::metadata)) + .unwrap_or(metadata) } } diff --git a/nautilus_core/serialization/src/arrow/depth.rs b/nautilus_core/serialization/src/arrow/depth.rs index f2c191fd3056..edcf69e91664 100644 --- a/nautilus_core/serialization/src/arrow/depth.rs +++ b/nautilus_core/serialization/src/arrow/depth.rs @@ -225,7 +225,11 @@ impl EncodeToRecordBatch for OrderBookDepth10 { } fn metadata(&self) -> HashMap { - self.metadata() + OrderBookDepth10::get_metadata( + &self.instrument_id, + self.bids[0].price.precision, + self.bids[0].size.precision, + ) } } diff --git a/nautilus_core/serialization/src/arrow/mod.rs b/nautilus_core/serialization/src/arrow/mod.rs index 184a975d60a1..54caaf1d3ea9 100644 --- a/nautilus_core/serialization/src/arrow/mod.rs +++ b/nautilus_core/serialization/src/arrow/mod.rs @@ -97,6 +97,12 @@ where ) -> Result; fn metadata(&self) -> HashMap; + fn chunk_metadata(chunk: &[Self]) -> HashMap { + chunk + .first() + .map(|elem| elem.metadata()) + .expect("Chunk must have atleast one element to encode") + } } pub trait DecodeFromRecordBatch diff --git a/nautilus_core/serialization/src/arrow/quote.rs b/nautilus_core/serialization/src/arrow/quote.rs index 732d4948ebf6..f1640d0a6523 100644 --- a/nautilus_core/serialization/src/arrow/quote.rs +++ b/nautilus_core/serialization/src/arrow/quote.rs @@ -117,7 +117,11 @@ impl EncodeToRecordBatch for QuoteTick { } fn metadata(&self) -> HashMap { - self.metadata() + QuoteTick::get_metadata( + &self.instrument_id, + self.bid_price.precision, + self.bid_size.precision, + ) } } diff --git a/nautilus_core/serialization/src/arrow/trade.rs b/nautilus_core/serialization/src/arrow/trade.rs index 10aaddd32385..31b1ed4c119d 100644 --- a/nautilus_core/serialization/src/arrow/trade.rs +++ b/nautilus_core/serialization/src/arrow/trade.rs @@ -118,7 +118,11 @@ impl EncodeToRecordBatch for TradeTick { } fn metadata(&self) -> HashMap { - self.metadata() + TradeTick::get_metadata( + &self.instrument_id, + self.price.precision, + self.size.precision, + ) } } From 64a971d7f898af8f2a7787e0a8de36d583e86f6b Mon Sep 17 00:00:00 2001 From: Ishan Bhanuka Date: Sun, 24 Nov 2024 14:08:28 +0530 Subject: [PATCH 04/15] Add pyo3 bindings for catalog --- nautilus_core/persistence/src/backend/catalog.rs | 2 +- nautilus_core/persistence/src/python/mod.rs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/nautilus_core/persistence/src/backend/catalog.rs b/nautilus_core/persistence/src/backend/catalog.rs index a6a286606f71..986e3f3a7f0b 100644 --- a/nautilus_core/persistence/src/backend/catalog.rs +++ b/nautilus_core/persistence/src/backend/catalog.rs @@ -63,7 +63,7 @@ impl ParquetCatalog { .collect() } - fn write_data(&self, data: Vec, type_name: &str) + pub fn write_data(&self, data: Vec, type_name: &str) where T: GetTsInit + EncodeToRecordBatch, { diff --git a/nautilus_core/persistence/src/python/mod.rs b/nautilus_core/persistence/src/python/mod.rs index 0f1130af8d4a..03bb4e530023 100644 --- a/nautilus_core/persistence/src/python/mod.rs +++ b/nautilus_core/persistence/src/python/mod.rs @@ -16,6 +16,7 @@ //! Python bindings from `pyo3`. pub mod backend; +pub mod catalog; pub mod wranglers; use pyo3::prelude::*; @@ -26,6 +27,7 @@ pub fn persistence(_: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_class::()?; m.add_class::()?; m.add_class::()?; + m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; From 80e60a28f23def28aab726b907069c99cdfc9a90 Mon Sep 17 00:00:00 2001 From: Ishan Bhanuka Date: Sun, 24 Nov 2024 20:45:32 +0530 Subject: [PATCH 05/15] Add query function to catalog --- nautilus_core/Cargo.lock | 1 + nautilus_core/persistence/Cargo.toml | 1 + .../persistence/src/backend/catalog.rs | 59 +++++++++++++++---- .../persistence/src/backend/session.rs | 40 ++++++++++++- .../persistence/src/python/catalog.rs | 51 ++++++++++++++++ nautilus_core/persistence/src/python/mod.rs | 2 +- 6 files changed, 142 insertions(+), 12 deletions(-) create mode 100644 nautilus_core/persistence/src/python/catalog.rs diff --git a/nautilus_core/Cargo.lock b/nautilus_core/Cargo.lock index 8893e0bb4e92..e8d1cbbb3126 100644 --- a/nautilus_core/Cargo.lock +++ b/nautilus_core/Cargo.lock @@ -3188,6 +3188,7 @@ dependencies = [ "criterion", "datafusion", "futures", + "heck 0.5.0", "itertools 0.13.0", "log", "nautilus-core", diff --git a/nautilus_core/persistence/Cargo.toml b/nautilus_core/persistence/Cargo.toml index f5bff2587700..dd856d57d2a5 100644 --- a/nautilus_core/persistence/Cargo.toml +++ b/nautilus_core/persistence/Cargo.toml @@ -26,6 +26,7 @@ binary-heap-plus = "0.5.0" compare = "0.1.0" datafusion = { version = "43.0.0", default-features = false, features = ["compression", "regex_expressions", "unicode_expressions", "pyarrow"] } itertools.workspace = true +heck.workspace = true [dev-dependencies] nautilus-test-kit = { path = "../test_kit" } diff --git a/nautilus_core/persistence/src/backend/catalog.rs b/nautilus_core/persistence/src/backend/catalog.rs index 986e3f3a7f0b..f615c79fe95c 100644 --- a/nautilus_core/persistence/src/backend/catalog.rs +++ b/nautilus_core/persistence/src/backend/catalog.rs @@ -1,27 +1,35 @@ use itertools::Itertools; use log::info; +use nautilus_core::nanos::UnixNanos; use nautilus_model::data::bar::Bar; use nautilus_model::data::delta::OrderBookDelta; use nautilus_model::data::depth::OrderBookDepth10; use nautilus_model::data::quote::QuoteTick; use nautilus_model::data::trade::TradeTick; -use nautilus_serialization::arrow::EncodeToRecordBatch; +use nautilus_serialization::arrow::{DecodeDataFromRecordBatch, EncodeToRecordBatch}; use std::path::PathBuf; use datafusion::arrow::record_batch::RecordBatch; +use datafusion::error::Result; +use heck::ToSnakeCase; use nautilus_model::data::{Data, GetTsInit}; use nautilus_serialization::parquet::write_batches_to_parquet; -pub struct ParquetCatalog { +use super::session::{self, build_query, DataBackendSession, QueryResult}; + +pub struct ParquetDataCatalog { base_path: PathBuf, batch_size: usize, + session: DataBackendSession, } -impl ParquetCatalog { +impl ParquetDataCatalog { pub fn new(base_path: PathBuf, batch_size: Option) -> Self { + let batch_size = batch_size.unwrap_or(5000); Self { base_path, - batch_size: batch_size.unwrap_or(5000), + batch_size, + session: session::DataBackendSession::new(batch_size), } } @@ -67,7 +75,7 @@ impl ParquetCatalog { where T: GetTsInit + EncodeToRecordBatch, { - ParquetCatalog::check_ascending_timestamps(&data, type_name); + ParquetDataCatalog::check_ascending_timestamps(&data, type_name); let batches = self.data_to_record_batches(data); if let Some(batch) = batches.first() { @@ -87,6 +95,37 @@ impl ParquetCatalog { } } + /// Query data loaded in the catalog + pub fn query( + &mut self, + // use instrument_ids or bar_types to query specific subset of the data + instrument_ids: Vec, + start: Option, + end: Option, + where_clause: Option<&str>, + ) -> Result + where + T: DecodeDataFromRecordBatch, + { + let mut paths = Vec::new(); + for instrument_id in instrument_ids.iter() { + paths.push(self.make_path("TODO", Some(instrument_id))); + } + + // If no specific instrument_id is selected query all files for the data type + if paths.is_empty() { + paths.push(self.make_path("TODO", None)); + } + + for path in paths.iter() { + let path = path.to_str().unwrap(); + let query = build_query(path, start, end, where_clause); + self.session.add_file::(path, path, Some(&query))?; + } + + Ok(self.session.get_query_result()) + } + pub fn write_data_enum(&self, data: Vec) { let mut delta: Vec = Vec::new(); let mut depth10: Vec = Vec::new(); @@ -115,10 +154,10 @@ impl ParquetCatalog { } } - self.write_data(delta, "OrderBookDelta"); - self.write_data(depth10, "OrderBookDepth10"); - self.write_data(quote, "QuoteTick"); - self.write_data(trade, "TradeTick"); - self.write_data(bar, "Bar"); + self.write_data(delta, &"OrderBookDelta".to_snake_case()); + self.write_data(depth10, &"OrderBookDepth10".to_snake_case()); + self.write_data(quote, &"QuoteTick".to_snake_case()); + self.write_data(trade, &"TradeTick".to_snake_case()); + self.write_data(bar, &"Bar".to_snake_case()); } } diff --git a/nautilus_core/persistence/src/backend/session.rs b/nautilus_core/persistence/src/backend/session.rs index f8ab32b2dbe1..a69446ce5810 100644 --- a/nautilus_core/persistence/src/backend/session.rs +++ b/nautilus_core/persistence/src/backend/session.rs @@ -20,7 +20,7 @@ use datafusion::{ error::Result, logical_expr::expr::Sort, physical_plan::SendableRecordBatchStream, prelude::*, }; use futures::StreamExt; -use nautilus_core::ffi::cvec::CVec; +use nautilus_core::{ffi::cvec::CVec, nanos::UnixNanos}; use nautilus_model::data::{Data, GetTsInit}; use nautilus_serialization::arrow::{ DataStreamingError, DecodeDataFromRecordBatch, EncodeToRecordBatch, WriteStream, @@ -176,6 +176,44 @@ impl DataBackendSession { // Note: Intended to be used on a single Python thread unsafe impl Send for DataBackendSession {} +pub fn build_query( + table: &str, + start: Option, + end: Option, + where_clause: Option<&str>, +) -> String { + let mut conditions = Vec::new(); + + // Add where clause if provided + if let Some(clause) = where_clause { + conditions.push(clause.to_string()); + } + + // Add start condition if provided + if let Some(start_ts) = start { + conditions.push(format!("ts_init >= {}", start_ts)); + } + + // Add end condition if provided + if let Some(end_ts) = end { + conditions.push(format!("ts_init <= {}", end_ts)); + } + + // Build base query + let mut query = format!("SELECT * FROM {}", table); + + // Add WHERE clause if there are conditions + if !conditions.is_empty() { + query.push_str(" WHERE "); + query.push_str(&conditions.join(" AND ")); + } + + // Add ORDER BY clause + query.push_str(" ORDER BY ts_init"); + + query +} + #[cfg_attr( feature = "python", pyo3::pyclass(module = "nautilus_trader.core.nautilus_pyo3.persistence") diff --git a/nautilus_core/persistence/src/python/catalog.rs b/nautilus_core/persistence/src/python/catalog.rs new file mode 100644 index 000000000000..e4e43826eb97 --- /dev/null +++ b/nautilus_core/persistence/src/python/catalog.rs @@ -0,0 +1,51 @@ +use std::path::PathBuf; + +use nautilus_model::data::bar::Bar; +use nautilus_model::data::delta::OrderBookDelta; +use nautilus_model::data::depth::OrderBookDepth10; +use nautilus_model::data::quote::QuoteTick; +use nautilus_model::data::trade::TradeTick; +use pyo3::prelude::*; + +use crate::backend::catalog::ParquetDataCatalog; + +/// A catalog for writing data to Parquet files. +#[pyclass(name = "ParquetCatalogV2")] +pub struct PyParquetDataCatalogV2 { + inner: ParquetDataCatalog, +} + +#[pymethods] +impl PyParquetDataCatalogV2 { + /// Create a new ParquetCatalog with the given base path and optional batch size. + #[new] + #[pyo3(signature = (base_path, batch_size=None))] + pub fn new(base_path: String, batch_size: Option) -> Self { + Self { + inner: ParquetDataCatalog::new(PathBuf::from(base_path), batch_size), + } + } + + // TODO: Cannot pass mixed data across pyo3 as a single type + // pub fn write_data(mut slf: PyRefMut<'_, Self>, data_type: NautilusDataType, data: Vec) {} + + pub fn write_quote_ticks(&self, data: Vec) { + self.inner.write_data(data, "quote_tick"); + } + + pub fn write_trade_ticks(&self, data: Vec) { + self.inner.write_data(data, "trade_tick"); + } + + pub fn write_order_book_deltas(&self, data: Vec) { + self.inner.write_data(data, "order_book_delta"); + } + + pub fn write_bars(&self, data: Vec) { + self.inner.write_data(data, "bar"); + } + + pub fn write_order_book_depths(&self, data: Vec) { + self.inner.write_data(data, "order_book_depth"); + } +} diff --git a/nautilus_core/persistence/src/python/mod.rs b/nautilus_core/persistence/src/python/mod.rs index 03bb4e530023..e996dc6f781e 100644 --- a/nautilus_core/persistence/src/python/mod.rs +++ b/nautilus_core/persistence/src/python/mod.rs @@ -27,7 +27,7 @@ pub fn persistence(_: Python<'_>, m: &Bound<'_, PyModule>) -> PyResult<()> { m.add_class::()?; m.add_class::()?; m.add_class::()?; - m.add_class::()?; + m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; From 8c1e2cb989c69c7df5a3dd979bda67de957b188f Mon Sep 17 00:00:00 2001 From: Ishan Bhanuka Date: Mon, 9 Dec 2024 11:29:11 +0530 Subject: [PATCH 06/15] Add persist to json function and round trip test --- nautilus_core/Cargo.lock | 434 +++++++++--------- nautilus_core/model/src/data/deltas.rs | 5 +- nautilus_core/model/src/data/mod.rs | 30 +- nautilus_core/persistence/Cargo.toml | 4 + .../persistence/src/backend/catalog.rs | 42 +- .../persistence/src/python/catalog.rs | 10 +- .../persistence/tests/test_catalog.rs | 58 ++- 7 files changed, 354 insertions(+), 229 deletions(-) diff --git a/nautilus_core/Cargo.lock b/nautilus_core/Cargo.lock index 59ce231be754..d06f7995e0f8 100644 --- a/nautilus_core/Cargo.lock +++ b/nautilus_core/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 4 +version = 3 [[package]] name = "addr2line" @@ -68,9 +68,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.21" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" [[package]] name = "android-tzdata" @@ -162,9 +162,9 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "arrow" -version = "53.3.0" +version = "53.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c91839b07e474b3995035fd8ac33ee54f9c9ccbbb1ea33d9909c71bffdf1259d" +checksum = "4caf25cdc4a985f91df42ed9e9308e1adbcd341a31a72605c697033fcef163e3" dependencies = [ "arrow-arith", "arrow-array", @@ -184,9 +184,9 @@ dependencies = [ [[package]] name = "arrow-arith" -version = "53.3.0" +version = "53.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "855c57c4efd26722b044dcd3e348252560e3e0333087fb9f6479dc0bf744054f" +checksum = "91f2dfd1a7ec0aca967dfaa616096aec49779adc8eccec005e2f5e4111b1192a" dependencies = [ "arrow-array", "arrow-buffer", @@ -199,9 +199,9 @@ dependencies = [ [[package]] name = "arrow-array" -version = "53.3.0" +version = "53.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd03279cea46569acf9295f6224fbc370c5df184b4d2ecfe97ccb131d5615a7f" +checksum = "d39387ca628be747394890a6e47f138ceac1aa912eab64f02519fed24b637af8" dependencies = [ "ahash 0.8.11", "arrow-buffer", @@ -210,15 +210,15 @@ dependencies = [ "chrono", "chrono-tz", "half", - "hashbrown 0.15.2", + "hashbrown 0.14.5", "num", ] [[package]] name = "arrow-buffer" -version = "53.3.0" +version = "53.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e4a9b9b1d6d7117f6138e13bc4dd5daa7f94e671b70e8c9c4dc37b4f5ecfc16" +checksum = "9e51e05228852ffe3eb391ce7178a0f97d2cf80cc6ef91d3c4a6b3cb688049ec" dependencies = [ "bytes", "half", @@ -227,9 +227,9 @@ dependencies = [ [[package]] name = "arrow-cast" -version = "53.3.0" +version = "53.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc70e39916e60c5b7af7a8e2719e3ae589326039e1e863675a008bee5ffe90fd" +checksum = "d09aea56ec9fa267f3f3f6cdab67d8a9974cbba90b3aa38c8fe9d0bb071bd8c1" dependencies = [ "arrow-array", "arrow-buffer", @@ -248,9 +248,9 @@ dependencies = [ [[package]] name = "arrow-csv" -version = "53.3.0" +version = "53.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "789b2af43c1049b03a8d088ff6b2257cdcea1756cd76b174b1f2600356771b97" +checksum = "c07b5232be87d115fde73e32f2ca7f1b353bff1b44ac422d3c6fc6ae38f11f0d" dependencies = [ "arrow-array", "arrow-buffer", @@ -267,9 +267,9 @@ dependencies = [ [[package]] name = "arrow-data" -version = "53.3.0" +version = "53.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4e75edf21ffd53744a9b8e3ed11101f610e7ceb1a29860432824f1834a1f623" +checksum = "b98ae0af50890b494cebd7d6b04b35e896205c1d1df7b29a6272c5d0d0249ef5" dependencies = [ "arrow-buffer", "arrow-schema", @@ -279,9 +279,9 @@ dependencies = [ [[package]] name = "arrow-ipc" -version = "53.3.0" +version = "53.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d186a909dece9160bf8312f5124d797884f608ef5435a36d9d608e0b2a9bcbf8" +checksum = "0ed91bdeaff5a1c00d28d8f73466bcb64d32bbd7093b5a30156b4b9f4dba3eee" dependencies = [ "arrow-array", "arrow-buffer", @@ -294,9 +294,9 @@ dependencies = [ [[package]] name = "arrow-json" -version = "53.3.0" +version = "53.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b66ff2fedc1222942d0bd2fd391cb14a85baa3857be95c9373179bd616753b85" +checksum = "0471f51260a5309307e5d409c9dc70aede1cd9cf1d4ff0f0a1e8e1a2dd0e0d3c" dependencies = [ "arrow-array", "arrow-buffer", @@ -314,9 +314,9 @@ dependencies = [ [[package]] name = "arrow-ord" -version = "53.3.0" +version = "53.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ece7b5bc1180e6d82d1a60e1688c199829e8842e38497563c3ab6ea813e527fd" +checksum = "2883d7035e0b600fb4c30ce1e50e66e53d8656aa729f2bfa4b51d359cf3ded52" dependencies = [ "arrow-array", "arrow-buffer", @@ -329,9 +329,9 @@ dependencies = [ [[package]] name = "arrow-row" -version = "53.3.0" +version = "53.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "745c114c8f0e8ce211c83389270de6fbe96a9088a7b32c2a041258a443fe83ff" +checksum = "552907e8e587a6fde4f8843fd7a27a576a260f65dab6c065741ea79f633fc5be" dependencies = [ "ahash 0.8.11", "arrow-array", @@ -343,18 +343,18 @@ dependencies = [ [[package]] name = "arrow-schema" -version = "53.3.0" +version = "53.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b95513080e728e4cec37f1ff5af4f12c9688d47795d17cda80b6ec2cf74d4678" +checksum = "539ada65246b949bd99ffa0881a9a15a4a529448af1a07a9838dd78617dafab1" dependencies = [ "bitflags 2.6.0", ] [[package]] name = "arrow-select" -version = "53.3.0" +version = "53.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e415279094ea70323c032c6e739c48ad8d80e78a09bef7117b8718ad5bf3722" +checksum = "6259e566b752da6dceab91766ed8b2e67bf6270eb9ad8a6e07a33c1bede2b125" dependencies = [ "ahash 0.8.11", "arrow-array", @@ -366,9 +366,9 @@ dependencies = [ [[package]] name = "arrow-string" -version = "53.3.0" +version = "53.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d956cae7002eb8d83a27dbd34daaea1cf5b75852f0b84deb4d93a276e92bbf" +checksum = "f3179ccbd18ebf04277a095ba7321b93fd1f774f18816bd5f6b3ce2f594edb6c" dependencies = [ "arrow-array", "arrow-buffer", @@ -383,9 +383,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.18" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df895a515f70646414f4b45c0b79082783b80552b373a68283012928df56f522" +checksum = "0cb8f1d480b0ea3783ab015936d2a55c87e219676f0c0b7dec61494043f21857" dependencies = [ "bzip2", "flate2", @@ -418,7 +418,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] @@ -429,7 +429,7 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] @@ -455,20 +455,21 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "aws-lc-rs" -version = "1.11.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f47bb8cc16b669d267eeccf585aea077d0882f4777b1c1f740217885d6e6e5a3" +checksum = "fe7c2840b66236045acd2607d5866e274380afd87ef99d6226e961e2cb47df45" dependencies = [ "aws-lc-sys", + "mirai-annotations", "paste", "zeroize", ] [[package]] name = "aws-lc-sys" -version = "0.23.1" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2101df3813227bbaaaa0b04cd61c534c7954b22bd68d399b440be937dc63ff7" +checksum = "ad3a619a9de81e1d7de1f1186dcba4506ed661a0e483d84410fdef0ee87b2f96" dependencies = [ "bindgen", "cc", @@ -505,7 +506,7 @@ dependencies = [ "serde_json", "serde_path_to_error", "serde_urlencoded", - "sync_wrapper 1.0.2", + "sync_wrapper 1.0.1", "tokio", "tower", "tower-layer", @@ -528,7 +529,7 @@ dependencies = [ "mime", "pin-project-lite", "rustversion", - "sync_wrapper 1.0.2", + "sync_wrapper 1.0.1", "tower-layer", "tower-service", "tracing", @@ -598,7 +599,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.90", + "syn 2.0.87", "which", ] @@ -673,7 +674,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] @@ -787,16 +788,16 @@ dependencies = [ "quote", "serde", "serde_json", - "syn 2.0.90", + "syn 2.0.87", "tempfile", "toml", ] [[package]] name = "cc" -version = "1.2.2" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f34d93e62b03caf570cccc334cbc6c2fceca82f39211051345108adcba3eebdc" +checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" dependencies = [ "jobserver", "libc", @@ -929,7 +930,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] @@ -940,9 +941,9 @@ checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "cmake" -version = "0.1.52" +version = "0.1.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c682c223677e0e5b6b7f63a64b9351844c3f1b1678a68b7ee617e30fb082620e" +checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a" dependencies = [ "cc", ] @@ -1039,16 +1040,6 @@ dependencies = [ "libc", ] -[[package]] -name = "core-foundation" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -1057,9 +1048,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.16" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" +checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6" dependencies = [ "libc", ] @@ -1216,7 +1207,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] @@ -1227,7 +1218,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] @@ -1663,7 +1654,7 @@ dependencies = [ "json-writer", "num_enum", "serde", - "thiserror 2.0.4", + "thiserror 2.0.5", "time", "tokio", "zstd", @@ -1678,7 +1669,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] @@ -1720,7 +1711,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] @@ -1730,9 +1721,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.90", + "syn 2.0.87", ] +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + [[package]] name = "digest" version = "0.10.7" @@ -1753,7 +1750,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] @@ -1804,12 +1801,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.10" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -2007,7 +2004,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] @@ -2130,9 +2127,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.2" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" [[package]] name = "hashlink" @@ -2469,7 +2466,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] @@ -2512,7 +2509,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", - "hashbrown 0.15.2", + "hashbrown 0.15.1", "serde", ] @@ -2607,11 +2604,10 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.74" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a865e038f7f6ed956f788f0d7d60c541fff74c7bd74272c5d4cf15c63743e705" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ - "once_cell", "wasm-bindgen", ] @@ -2642,9 +2638,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "lexical-core" -version = "1.0.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06d7a061b7feb8a4b233a4d90280d13e0965c4e0181566e9ad61af98e210ca9d" +checksum = "0431c65b318a590c1de6b8fd6e72798c92291d27762d94c9e6c37ed7a73d8458" dependencies = [ "lexical-parse-float", "lexical-parse-integer", @@ -2655,9 +2651,9 @@ dependencies = [ [[package]] name = "lexical-parse-float" -version = "1.0.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0029bdee2a94a6c4393a86f7e6921c90f234218fa4f2154bc001c92bc51e8bf5" +checksum = "eb17a4bdb9b418051aa59d41d65b1c9be5affab314a872e5ad7f06231fb3b4e0" dependencies = [ "lexical-parse-integer", "lexical-util", @@ -2666,9 +2662,9 @@ dependencies = [ [[package]] name = "lexical-parse-integer" -version = "1.0.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "440a2398a08def518ff962b69e7146246c53bad8090e2b75d95fd5a469338958" +checksum = "5df98f4a4ab53bf8b175b363a34c7af608fe31f93cc1fb1bf07130622ca4ef61" dependencies = [ "lexical-util", "static_assertions", @@ -2676,18 +2672,18 @@ dependencies = [ [[package]] name = "lexical-util" -version = "1.0.4" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3100209587e35b13881068ce5a41241b112e0500b4d847ba16be172829c112ff" +checksum = "85314db53332e5c192b6bca611fb10c114a80d1b831ddac0af1e9be1b9232ca0" dependencies = [ "static_assertions", ] [[package]] name = "lexical-write-float" -version = "1.0.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27adf08e2f91ff44ab54bbac0c4579303f0865730870f91b58c044df821f114c" +checksum = "6e7c3ad4e37db81c1cbe7cf34610340adc09c322871972f74877a712abc6c809" dependencies = [ "lexical-util", "lexical-write-integer", @@ -2696,9 +2692,9 @@ dependencies = [ [[package]] name = "lexical-write-integer" -version = "1.0.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b4e5d27d742da13f013765f849efc0c4b6173e0e64404546475eb5ee0931e2c" +checksum = "eb89e9f6958b83258afa3deed90b5de9ef68eef090ad5086c791cd2345610162" dependencies = [ "lexical-util", "static_assertions", @@ -2712,9 +2708,9 @@ checksum = "09d6582e104315a817dff97f75133544b2e094ee22447d2acf4a74e189ba06fc" [[package]] name = "libloading" -version = "0.8.6" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", "windows-targets 0.52.6", @@ -2745,9 +2741,9 @@ checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "litemap" -version = "0.7.4" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" +checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" [[package]] name = "lock_api" @@ -2852,15 +2848,22 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ + "hermit-abi 0.3.9", "libc", "wasi", "windows-sys 0.52.0", ] +[[package]] +name = "mirai-annotations" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1" + [[package]] name = "native-tls" version = "0.2.12" @@ -2873,7 +2876,7 @@ dependencies = [ "openssl-probe", "openssl-sys", "schannel", - "security-framework 2.11.1", + "security-framework", "security-framework-sys", "tempfile", ] @@ -2918,7 +2921,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "strum", - "thiserror 2.0.4", + "thiserror 2.0.5", "thousands", "time", "tokio", @@ -3051,7 +3054,7 @@ dependencies = [ "ring", "rstest", "rustls", - "rustls-native-certs 0.8.1", + "rustls-native-certs 0.8.0", "tracing", ] @@ -3071,7 +3074,7 @@ dependencies = [ "pyo3", "pyo3-async-runtimes", "rstest", - "thiserror 2.0.4", + "thiserror 2.0.5", "tokio", "ustr", ] @@ -3094,7 +3097,7 @@ dependencies = [ "rust_decimal_macros", "serde", "strum", - "thiserror 2.0.4", + "thiserror 2.0.5", ] [[package]] @@ -3167,7 +3170,7 @@ dependencies = [ "serde_json", "strum", "tabled", - "thiserror 2.0.4", + "thiserror 2.0.5", "thousands", "ustr", ] @@ -3192,7 +3195,7 @@ dependencies = [ "rstest", "rustls", "serde_json", - "thiserror 2.0.4", + "thiserror 2.0.5", "tokio", "tokio-rustls", "tokio-tungstenite", @@ -3217,13 +3220,17 @@ dependencies = [ "nautilus-model", "nautilus-serialization", "nautilus-test-kit", + "pretty_assertions", "procfs", "pyo3", "quickcheck", "quickcheck_macros", "rand", "rstest", - "thiserror 2.0.4", + "serde", + "serde_json", + "tempfile", + "thiserror 2.0.5", "tokio", ] @@ -3248,7 +3255,7 @@ dependencies = [ "serde", "serde_json", "strum", - "thiserror 2.0.4", + "thiserror 2.0.5", "ustr", "uuid", ] @@ -3287,7 +3294,7 @@ dependencies = [ "pyo3-async-runtimes", "rstest", "rust_decimal", - "thiserror 2.0.4", + "thiserror 2.0.5", "ustr", ] @@ -3303,7 +3310,7 @@ dependencies = [ "parquet", "pyo3", "rstest", - "thiserror 2.0.4", + "thiserror 2.0.5", ] [[package]] @@ -3485,7 +3492,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] @@ -3562,7 +3569,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] @@ -3640,9 +3647,9 @@ dependencies = [ [[package]] name = "parquet" -version = "53.3.0" +version = "53.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b449890367085eb65d7d3321540abc3d7babbd179ce31df0016e90719114191" +checksum = "dea02606ba6f5e856561d8d507dba8bac060aefca2a6c0f1aa1d361fed91ff3e" dependencies = [ "ahash 0.8.11", "arrow-array", @@ -3659,7 +3666,7 @@ dependencies = [ "flate2", "futures", "half", - "hashbrown 0.15.2", + "hashbrown 0.14.5", "lz4_flex", "num", "num-bigint", @@ -3831,9 +3838,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.10.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" [[package]] name = "powerfmt" @@ -3850,6 +3857,16 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "pretty_assertions" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d" +dependencies = [ + "diff", + "yansi", +] + [[package]] name = "prettyplease" version = "0.2.25" @@ -3857,7 +3874,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" dependencies = [ "proc-macro2", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] @@ -3888,14 +3905,14 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] name = "proc-macro2" -version = "1.0.92" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] @@ -4008,7 +4025,7 @@ checksum = "22c26fd8e9fc19f53f0c1e00bf61471de6789f7eb263056f7f944a9cceb5823e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] @@ -4040,7 +4057,7 @@ dependencies = [ "proc-macro2", "pyo3-macros-backend", "quote", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] @@ -4053,7 +4070,7 @@ dependencies = [ "proc-macro2", "pyo3-build-config", "quote", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] @@ -4291,7 +4308,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "sync_wrapper 1.0.2", + "sync_wrapper 1.0.1", "system-configuration", "tokio", "tokio-native-tls", @@ -4373,9 +4390,9 @@ dependencies = [ [[package]] name = "rsa" -version = "0.9.7" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47c75d7c5c6b673e58bf54d8544a9f432e3a925b0e80f7cd3602ab5c50c55519" +checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" dependencies = [ "const-oid", "digest", @@ -4417,7 +4434,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.90", + "syn 2.0.87", "unicode-ident", ] @@ -4507,19 +4524,20 @@ dependencies = [ "rustls-pemfile", "rustls-pki-types", "schannel", - "security-framework 2.11.1", + "security-framework", ] [[package]] name = "rustls-native-certs" -version = "0.8.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +checksum = "fcaf18a4f2be7326cd874a5fa579fae794320a0f388d365dca7e480e55f83f8a" dependencies = [ "openssl-probe", + "rustls-pemfile", "rustls-pki-types", "schannel", - "security-framework 3.0.1", + "security-framework", ] [[package]] @@ -4610,20 +4628,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ "bitflags 2.6.0", - "core-foundation 0.9.4", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework" -version = "3.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1415a607e92bec364ea2cf9264646dcce0f91e6d65281bd6f2819cca3bf39c8" -dependencies = [ - "bitflags 2.6.0", - "core-foundation 0.10.0", + "core-foundation", "core-foundation-sys", "libc", "security-framework-sys", @@ -4668,7 +4673,7 @@ checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] @@ -4836,7 +4841,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] @@ -4847,9 +4852,9 @@ checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" [[package]] name = "socket2" -version = "0.5.8" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", "windows-sys 0.52.0", @@ -4902,7 +4907,7 @@ checksum = "01b2e185515564f15375f593fb966b5718bc624ba77fe49fa4616ad619690554" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] @@ -4967,7 +4972,7 @@ dependencies = [ "quote", "sqlx-core", "sqlx-macros-core", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] @@ -4990,7 +4995,7 @@ dependencies = [ "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", - "syn 2.0.90", + "syn 2.0.87", "tempfile", "tokio", "url", @@ -5147,7 +5152,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] @@ -5169,9 +5174,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.90" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", @@ -5186,9 +5191,9 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "sync_wrapper" -version = "1.0.2" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" dependencies = [ "futures-core", ] @@ -5201,7 +5206,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] @@ -5225,7 +5230,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ "bitflags 2.6.0", - "core-foundation 0.9.4", + "core-foundation", "system-configuration-sys", ] @@ -5298,11 +5303,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.4" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f49a1853cf82743e3b7950f77e0f4d622ca36cf4317cba00c767838bac8d490" +checksum = "643caef17e3128658ff44d85923ef2d28af81bb71e0d67bbfe1d76f19a73e053" dependencies = [ - "thiserror-impl 2.0.4", + "thiserror-impl 2.0.5", ] [[package]] @@ -5313,18 +5318,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] name = "thiserror-impl" -version = "2.0.4" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8381894bb3efe0c4acac3ded651301ceee58a15d47c2e34885ed1908ad667061" +checksum = "995d0bbc9995d1f19d28b7215a9352b0fc3cd3a2d2ec95c2cadc485cdedbcdde" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] @@ -5457,7 +5462,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] @@ -5482,9 +5487,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.17" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" dependencies = [ "futures-core", "pin-project-lite", @@ -5500,7 +5505,7 @@ dependencies = [ "futures-util", "log", "rustls", - "rustls-native-certs 0.8.1", + "rustls-native-certs 0.8.0", "rustls-pki-types", "tokio", "tokio-rustls", @@ -5509,9 +5514,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.13" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", @@ -5602,7 +5607,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] @@ -5662,7 +5667,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568" dependencies = [ "quote", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] @@ -5718,7 +5723,7 @@ checksum = "560b82d656506509d43abe30e0ba64c56b1953ab3d4fe7ba5902747a7a3cedd5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] @@ -5741,9 +5746,9 @@ checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" -version = "1.0.14" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-normalization" @@ -5792,9 +5797,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.4" +version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +checksum = "8d157f1b96d14500ffdc1f10ba712e780825526c03d9a49b4d0324b0d9113ada" dependencies = [ "form_urlencoded", "idna", @@ -5920,9 +5925,9 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.97" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d15e63b4482863c109d70a7b8706c1e364eb6ea449b201a76c5b89cedcec2d5c" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if", "once_cell", @@ -5931,37 +5936,36 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.97" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d36ef12e3aaca16ddd3f67922bc63e48e953f126de60bd33ccc0101ef9998cd" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.87", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.47" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dfaf8f50e5f293737ee323940c7d8b08a66a95a419223d9f41610ca08b0833d" +checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" dependencies = [ "cfg-if", "js-sys", - "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.97" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "705440e08b42d3e4b36de7d66c944be628d579796b8090bfa3471478a2260051" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5969,22 +5973,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.97" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98c9ae5a76e46f4deecd0f0255cc223cfa18dc9b261213b8aa0c7b36f61b3f1d" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.87", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.97" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ee99da9c5ba11bd675621338ef6fa52296b76b83305e9b6e5c77d4c286d6d49" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "wasm-streams" @@ -6001,9 +6005,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.74" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a98bc3c33f0fe7e59ad7cd041b89034fa82a7c2d4365ca538dda6cdaf513863c" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" dependencies = [ "js-sys", "wasm-bindgen", @@ -6011,9 +6015,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.26.7" +version = "0.26.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e" +checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" dependencies = [ "rustls-pki-types", ] @@ -6110,7 +6114,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] @@ -6121,7 +6125,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] @@ -6350,11 +6354,17 @@ dependencies = [ "lzma-sys", ] +[[package]] +name = "yansi" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" + [[package]] name = "yoke" -version = "0.7.5" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" dependencies = [ "serde", "stable_deref_trait", @@ -6364,13 +6374,13 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.5" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.87", "synstructure", ] @@ -6392,27 +6402,27 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] name = "zerofrom" -version = "0.1.5" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.5" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.87", "synstructure", ] @@ -6441,7 +6451,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.90", + "syn 2.0.87", ] [[package]] diff --git a/nautilus_core/model/src/data/deltas.rs b/nautilus_core/model/src/data/deltas.rs index 65f4d59f9d43..5ebaf5ae72ef 100644 --- a/nautilus_core/model/src/data/deltas.rs +++ b/nautilus_core/model/src/data/deltas.rs @@ -28,11 +28,12 @@ use nautilus_core::{ use super::{delta::OrderBookDelta, GetTsInit}; use crate::identifiers::InstrumentId; +use serde::{Deserialize, Serialize}; /// Represents a grouped batch of `OrderBookDelta` updates for an `OrderBook`. /// /// This type cannot be `repr(C)` due to the `deltas` vec. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Serialize, Deserialize)] #[cfg_attr( feature = "python", pyo3::pyclass(module = "nautilus_trader.core.nautilus_pyo3.model") @@ -137,7 +138,7 @@ impl GetTsInit for OrderBookDeltas { /// dereferenced to `OrderBookDeltas`, providing access to `OrderBookDeltas`'s methods without /// having to manually access the underlying `OrderBookDeltas` instance. #[repr(C)] -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[allow(non_camel_case_types)] pub struct OrderBookDeltas_API(Box); diff --git a/nautilus_core/model/src/data/mod.rs b/nautilus_core/model/src/data/mod.rs index 8538012948ff..aa18c88a1d99 100644 --- a/nautilus_core/model/src/data/mod.rs +++ b/nautilus_core/model/src/data/mod.rs @@ -55,7 +55,7 @@ use crate::{ /// Not recommended for storing large amounts of data, as the largest variant is significantly /// larger (10x) than the smallest. #[repr(C)] -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[allow(clippy::large_enum_variant)] pub enum Data { Delta(OrderBookDelta), @@ -66,6 +66,34 @@ pub enum Data { Bar(Bar), } +macro_rules! impl_try_from_data { + ($variant:ident, $type:ty) => { + impl TryFrom for $type { + type Error = (); + + fn try_from(value: Data) -> Result { + match value { + Data::$variant(x) => Ok(x), + _ => Err(()), + } + } + } + }; +} + +impl_try_from_data!(Delta, OrderBookDelta); +impl_try_from_data!(Deltas, OrderBookDeltas_API); +impl_try_from_data!(Depth10, OrderBookDepth10); +impl_try_from_data!(Quote, QuoteTick); +impl_try_from_data!(Trade, TradeTick); +impl_try_from_data!(Bar, Bar); + +pub fn to_variant>(data: Vec) -> Vec { + data.into_iter() + .filter_map(|d| T::try_from(d).ok()) + .collect() +} + impl Data { /// Returns the instrument ID for the data. pub fn instrument_id(&self) -> InstrumentId { diff --git a/nautilus_core/persistence/Cargo.toml b/nautilus_core/persistence/Cargo.toml index dd856d57d2a5..d3ffbf67aad3 100644 --- a/nautilus_core/persistence/Cargo.toml +++ b/nautilus_core/persistence/Cargo.toml @@ -27,6 +27,8 @@ compare = "0.1.0" datafusion = { version = "43.0.0", default-features = false, features = ["compression", "regex_expressions", "unicode_expressions", "pyarrow"] } itertools.workspace = true heck.workspace = true +serde_json.workspace = true +serde.workspace = true [dev-dependencies] nautilus-test-kit = { path = "../test_kit" } @@ -34,6 +36,8 @@ criterion = { workspace = true } rstest = { workspace = true } quickcheck = "1" quickcheck_macros = "1" +tempfile.workspace = true +pretty_assertions = "1.4.1" [target.'cfg(target_os = "linux")'.dependencies] procfs = "0.17.0" diff --git a/nautilus_core/persistence/src/backend/catalog.rs b/nautilus_core/persistence/src/backend/catalog.rs index f615c79fe95c..fbac24bda619 100644 --- a/nautilus_core/persistence/src/backend/catalog.rs +++ b/nautilus_core/persistence/src/backend/catalog.rs @@ -7,6 +7,7 @@ use nautilus_model::data::depth::OrderBookDepth10; use nautilus_model::data::quote::QuoteTick; use nautilus_model::data::trade::TradeTick; use nautilus_serialization::arrow::{DecodeDataFromRecordBatch, EncodeToRecordBatch}; +use serde::Serialize; use std::path::PathBuf; use datafusion::arrow::record_batch::RecordBatch; @@ -71,17 +72,42 @@ impl ParquetDataCatalog { .collect() } - pub fn write_data(&self, data: Vec, type_name: &str) + pub fn write_to_json(&self, data: Vec) + where + T: GetTsInit + Serialize, + { + let type_name = std::any::type_name::().to_snake_case(); + ParquetDataCatalog::check_ascending_timestamps(&data, &type_name); + + let path = self.make_path(&type_name, None); + let json_path = path.with_extension("json"); + + info!( + "Writing {} records of {} data to {:?}", + data.len(), + type_name, + json_path + ); + + let file = std::fs::File::create(&json_path) + .unwrap_or_else(|_| panic!("Failed to create JSON file at {:?}", json_path)); + + serde_json::to_writer(file, &data) + .unwrap_or_else(|_| panic!("Failed to write {} to JSON", type_name)); + } + + pub fn write_data(&self, data: Vec) where T: GetTsInit + EncodeToRecordBatch, { - ParquetDataCatalog::check_ascending_timestamps(&data, type_name); + let type_name = std::any::type_name::().to_snake_case(); + ParquetDataCatalog::check_ascending_timestamps(&data, &type_name); let batches = self.data_to_record_batches(data); if let Some(batch) = batches.first() { let schema = batch.schema(); let instrument_id = schema.metadata.get("instrument_id"); - let path = self.make_path(type_name, instrument_id); + let path = self.make_path(&type_name, instrument_id); // Write all batches to parquet file info!( @@ -154,10 +180,10 @@ impl ParquetDataCatalog { } } - self.write_data(delta, &"OrderBookDelta".to_snake_case()); - self.write_data(depth10, &"OrderBookDepth10".to_snake_case()); - self.write_data(quote, &"QuoteTick".to_snake_case()); - self.write_data(trade, &"TradeTick".to_snake_case()); - self.write_data(bar, &"Bar".to_snake_case()); + self.write_data(delta); + self.write_data(depth10); + self.write_data(quote); + self.write_data(trade); + self.write_data(bar); } } diff --git a/nautilus_core/persistence/src/python/catalog.rs b/nautilus_core/persistence/src/python/catalog.rs index e4e43826eb97..ffc0c9fc5dd3 100644 --- a/nautilus_core/persistence/src/python/catalog.rs +++ b/nautilus_core/persistence/src/python/catalog.rs @@ -30,22 +30,22 @@ impl PyParquetDataCatalogV2 { // pub fn write_data(mut slf: PyRefMut<'_, Self>, data_type: NautilusDataType, data: Vec) {} pub fn write_quote_ticks(&self, data: Vec) { - self.inner.write_data(data, "quote_tick"); + self.inner.write_data(data); } pub fn write_trade_ticks(&self, data: Vec) { - self.inner.write_data(data, "trade_tick"); + self.inner.write_data(data); } pub fn write_order_book_deltas(&self, data: Vec) { - self.inner.write_data(data, "order_book_delta"); + self.inner.write_data(data); } pub fn write_bars(&self, data: Vec) { - self.inner.write_data(data, "bar"); + self.inner.write_data(data); } pub fn write_order_book_depths(&self, data: Vec) { - self.inner.write_data(data, "order_book_depth"); + self.inner.write_data(data); } } diff --git a/nautilus_core/persistence/tests/test_catalog.rs b/nautilus_core/persistence/tests/test_catalog.rs index 9265d827ee57..b6a87451b04b 100644 --- a/nautilus_core/persistence/tests/test_catalog.rs +++ b/nautilus_core/persistence/tests/test_catalog.rs @@ -16,8 +16,9 @@ use nautilus_core::ffi::cvec::CVec; use nautilus_model::data::{ bar::Bar, delta::OrderBookDelta, is_monotonically_increasing_by_init, quote::QuoteTick, - trade::TradeTick, Data, + to_variant, trade::TradeTick, Data, }; +use nautilus_persistence::backend::catalog::ParquetDataCatalog; use nautilus_persistence::{ backend::session::{DataBackendSession, DataQueryResult, QueryResult}, python::backend::session::NautilusDataType, @@ -27,6 +28,9 @@ use nautilus_test_kit::common::get_test_data_file_path; use procfs::{self, process::Process}; use pyo3::{prelude::*, types::PyCapsule}; use rstest::rstest; +use serde_json; +use std::path::PathBuf; +use tempfile; /// Memory leak test /// @@ -320,3 +324,55 @@ fn test_bar_query() { assert_eq!(ticks.len(), expected_length); assert!(is_monotonically_increasing_by_init(&ticks)); } + +#[rstest] +fn test_catalog_serialization_json_round_trip() { + use pretty_assertions::assert_eq; + + // Setup + // let temp_dir = tempfile::tempdir().unwrap(); + let temp_dir = PathBuf::from("."); + let catalog = ParquetDataCatalog::new(temp_dir.clone(), Some(1000)); + + // Read original data from parquet + let file_path = get_test_data_file_path("nautilus/quotes.parquet"); + let mut session = DataBackendSession::new(1000); + session + .add_file::("test_data", file_path.as_str(), None) + .unwrap(); + let query_result: QueryResult = session.get_query_result(); + let original_data: Vec = query_result.collect(); + let original_data_variants: Vec = to_variant(original_data); + + // Write to JSON using catalog + catalog.write_to_json(original_data_variants.clone()); + + // Read back from JSON + let json_path = temp_dir.join("data/nautilus_model_data_quote_quote_tick/data.json"); + dbg!(&json_path); + let json_str = std::fs::read_to_string(json_path).unwrap(); + let loaded_data_variants: Vec = serde_json::from_str(&json_str).unwrap(); + + // Compare + assert_eq!(original_data_variants.len(), loaded_data_variants.len()); + for (orig, loaded) in original_data_variants + .iter() + .zip(loaded_data_variants.iter()) + { + dbg!(&orig.bid_size); + dbg!(&orig.bid_size.raw); + dbg!(&orig.bid_size.precision); + dbg!(&loaded.bid_size); + dbg!(&loaded.bid_size.raw); + dbg!(&loaded.bid_size.precision); + assert_eq!(orig.instrument_id, loaded.instrument_id); + assert_eq!(orig.bid_price, loaded.bid_price); + assert_eq!(orig.ask_price, loaded.ask_price); + assert_eq!(orig.bid_size.raw, loaded.bid_size.raw); + assert_eq!(orig.bid_size.precision, loaded.bid_size.precision); + assert_eq!(orig.ask_size.raw, loaded.ask_size.raw); + assert_eq!(orig.ask_size.precision, loaded.ask_size.precision); + assert_eq!(orig.ts_event, loaded.ts_event); + assert_eq!(orig.ts_init, loaded.ts_init); + } +} From f49136de586d002e1b6a6e5228733d5ea38a12a4 Mon Sep 17 00:00:00 2001 From: Ishan Bhanuka Date: Mon, 16 Dec 2024 20:50:59 +0530 Subject: [PATCH 07/15] Fix quotes data and add round trip tests --- .../persistence/tests/test_catalog.rs | 93 +++++++++++++----- tests/test_data/nautilus/quotes.parquet | Bin 470645 -> 205415 bytes 2 files changed, 67 insertions(+), 26 deletions(-) diff --git a/nautilus_core/persistence/tests/test_catalog.rs b/nautilus_core/persistence/tests/test_catalog.rs index b6a87451b04b..35c0a00384a6 100644 --- a/nautilus_core/persistence/tests/test_catalog.rs +++ b/nautilus_core/persistence/tests/test_catalog.rs @@ -23,14 +23,14 @@ use nautilus_persistence::{ backend::session::{DataBackendSession, DataQueryResult, QueryResult}, python::backend::session::NautilusDataType, }; +use nautilus_serialization::arrow::ArrowSchemaProvider; use nautilus_test_kit::common::get_test_data_file_path; #[cfg(target_os = "linux")] use procfs::{self, process::Process}; use pyo3::{prelude::*, types::PyCapsule}; use rstest::rstest; -use serde_json; +use std::io::Write; use std::path::PathBuf; -use tempfile; /// Memory leak test /// @@ -330,49 +330,90 @@ fn test_catalog_serialization_json_round_trip() { use pretty_assertions::assert_eq; // Setup - // let temp_dir = tempfile::tempdir().unwrap(); let temp_dir = PathBuf::from("."); let catalog = ParquetDataCatalog::new(temp_dir.clone(), Some(1000)); // Read original data from parquet let file_path = get_test_data_file_path("nautilus/quotes.parquet"); + // let file_path = "test.parquet"; let mut session = DataBackendSession::new(1000); session .add_file::("test_data", file_path.as_str(), None) .unwrap(); let query_result: QueryResult = session.get_query_result(); - let original_data: Vec = query_result.collect(); - let original_data_variants: Vec = to_variant(original_data); + let quote_ticks: Vec = query_result.collect(); + let quote_ticks: Vec = to_variant(quote_ticks); // Write to JSON using catalog - catalog.write_to_json(original_data_variants.clone()); + catalog.write_to_json(quote_ticks.clone()); // Read back from JSON let json_path = temp_dir.join("data/nautilus_model_data_quote_quote_tick/data.json"); - dbg!(&json_path); let json_str = std::fs::read_to_string(json_path).unwrap(); let loaded_data_variants: Vec = serde_json::from_str(&json_str).unwrap(); // Compare - assert_eq!(original_data_variants.len(), loaded_data_variants.len()); - for (orig, loaded) in original_data_variants - .iter() - .zip(loaded_data_variants.iter()) + assert_eq!(quote_ticks.len(), loaded_data_variants.len()); + for (orig, loaded) in quote_ticks.iter().zip(loaded_data_variants.iter()) { + assert_eq!(orig, loaded); + } +} + +#[rstest] +fn fix_parquet_data_quantity_values() { + use datafusion::parquet::arrow::ArrowWriter; + use nautilus_model::types::quantity::Quantity; + use nautilus_serialization::arrow::EncodeToRecordBatch; + use pretty_assertions::assert_eq; + use std::collections::HashMap; + + // Read original data from parquet + let file_path = get_test_data_file_path("nautilus/quotes.parquet"); + let mut session = DataBackendSession::new(1000); + session + .add_file::("test_data", file_path.as_str(), None) + .unwrap(); + let query_result: QueryResult = session.get_query_result(); + let quote_ticks: Vec = query_result.collect(); + let mut quote_ticks: Vec = to_variant(quote_ticks); + + // fix bid and ask size + for data in quote_ticks.iter_mut() { + data.bid_size = Quantity::new(data.bid_size.raw as f64, data.bid_size.precision); + data.ask_size = Quantity::new(data.ask_size.raw as f64, data.ask_size.precision); + } + + let metadata = HashMap::from([ + ("price_precision".to_string(), "5".to_string()), + ("size_precision".to_string(), "0".to_string()), + ("instrument_id".to_string(), "EUR/USD.SIM".to_string()), + ]); + let schema = QuoteTick::get_schema(Some(metadata.clone())); + + // Write the record batch to a buffer + let file_path = PathBuf::from("test.parquet"); + let mut file = std::fs::File::create(&file_path).unwrap(); { - dbg!(&orig.bid_size); - dbg!(&orig.bid_size.raw); - dbg!(&orig.bid_size.precision); - dbg!(&loaded.bid_size); - dbg!(&loaded.bid_size.raw); - dbg!(&loaded.bid_size.precision); - assert_eq!(orig.instrument_id, loaded.instrument_id); - assert_eq!(orig.bid_price, loaded.bid_price); - assert_eq!(orig.ask_price, loaded.ask_price); - assert_eq!(orig.bid_size.raw, loaded.bid_size.raw); - assert_eq!(orig.bid_size.precision, loaded.bid_size.precision); - assert_eq!(orig.ask_size.raw, loaded.ask_size.raw); - assert_eq!(orig.ask_size.precision, loaded.ask_size.precision); - assert_eq!(orig.ts_event, loaded.ts_event); - assert_eq!(orig.ts_init, loaded.ts_init); + let mut writer = ArrowWriter::try_new(&mut file, schema.into(), None).unwrap(); + for chunk in quote_ticks.chunks(1000) { + let batch = QuoteTick::encode_batch(&metadata, chunk).unwrap(); + writer.write(&batch).unwrap(); + } + writer.close().unwrap(); + } + + let mut session = DataBackendSession::new(1000); + session + .add_file::("test_data", file_path.to_str().unwrap(), None) + .unwrap(); + let query_result: QueryResult = session.get_query_result(); + let ticks: Vec = query_result.collect(); + let ticks_variants: Vec = to_variant(ticks); + + assert_eq!(quote_ticks.len(), ticks_variants.len()); + dbg!("e_ticks[0]); + dbg!(&ticks_variants[0]); + for (orig, loaded) in quote_ticks.iter().zip(ticks_variants.iter()) { + assert_eq!(orig, loaded) } } diff --git a/tests/test_data/nautilus/quotes.parquet b/tests/test_data/nautilus/quotes.parquet index 395792a2b6a4ef33bc7085d29cd6d51793cd25a6..0f02ac8b9d891e0cd45c817e6d491b9c1e7e2677 100644 GIT binary patch delta 52726 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� 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 P+D+vG)6d>+z90P$ga&BB From da6de61d8474566b73f319daae5d48e2099777a5 Mon Sep 17 00:00:00 2001 From: Ishan Bhanuka Date: Mon, 16 Dec 2024 21:14:17 +0530 Subject: [PATCH 08/15] Clean up tests --- .../persistence/src/backend/catalog.rs | 5 ++- .../persistence/tests/test_catalog.rs | 33 +++++++------------ 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/nautilus_core/persistence/src/backend/catalog.rs b/nautilus_core/persistence/src/backend/catalog.rs index fbac24bda619..a21cdde83c17 100644 --- a/nautilus_core/persistence/src/backend/catalog.rs +++ b/nautilus_core/persistence/src/backend/catalog.rs @@ -34,6 +34,7 @@ impl ParquetDataCatalog { } } + // TODO: fix path creation fn make_path(&self, type_name: &str, instrument_id: Option<&String>) -> PathBuf { let mut path = self.base_path.join("data").join(type_name.to_lowercase()); @@ -72,7 +73,7 @@ impl ParquetDataCatalog { .collect() } - pub fn write_to_json(&self, data: Vec) + pub fn write_to_json(&self, data: Vec) -> PathBuf where T: GetTsInit + Serialize, { @@ -94,6 +95,8 @@ impl ParquetDataCatalog { serde_json::to_writer(file, &data) .unwrap_or_else(|_| panic!("Failed to write {} to JSON", type_name)); + + json_path } pub fn write_data(&self, data: Vec) diff --git a/nautilus_core/persistence/tests/test_catalog.rs b/nautilus_core/persistence/tests/test_catalog.rs index 35c0a00384a6..68bb5cf9cda5 100644 --- a/nautilus_core/persistence/tests/test_catalog.rs +++ b/nautilus_core/persistence/tests/test_catalog.rs @@ -29,7 +29,6 @@ use nautilus_test_kit::common::get_test_data_file_path; use procfs::{self, process::Process}; use pyo3::{prelude::*, types::PyCapsule}; use rstest::rstest; -use std::io::Write; use std::path::PathBuf; /// Memory leak test @@ -330,8 +329,8 @@ fn test_catalog_serialization_json_round_trip() { use pretty_assertions::assert_eq; // Setup - let temp_dir = PathBuf::from("."); - let catalog = ParquetDataCatalog::new(temp_dir.clone(), Some(1000)); + let temp_dir = tempfile::tempdir().unwrap(); + let catalog = ParquetDataCatalog::new(temp_dir.path().to_path_buf(), Some(1000)); // Read original data from parquet let file_path = get_test_data_file_path("nautilus/quotes.parquet"); @@ -345,10 +344,9 @@ fn test_catalog_serialization_json_round_trip() { let quote_ticks: Vec = to_variant(quote_ticks); // Write to JSON using catalog - catalog.write_to_json(quote_ticks.clone()); + let json_path = catalog.write_to_json(quote_ticks.clone()); // Read back from JSON - let json_path = temp_dir.join("data/nautilus_model_data_quote_quote_tick/data.json"); let json_str = std::fs::read_to_string(json_path).unwrap(); let loaded_data_variants: Vec = serde_json::from_str(&json_str).unwrap(); @@ -360,9 +358,8 @@ fn test_catalog_serialization_json_round_trip() { } #[rstest] -fn fix_parquet_data_quantity_values() { +fn test_datafusion_parquet_round_trip() { use datafusion::parquet::arrow::ArrowWriter; - use nautilus_model::types::quantity::Quantity; use nautilus_serialization::arrow::EncodeToRecordBatch; use pretty_assertions::assert_eq; use std::collections::HashMap; @@ -375,13 +372,7 @@ fn fix_parquet_data_quantity_values() { .unwrap(); let query_result: QueryResult = session.get_query_result(); let quote_ticks: Vec = query_result.collect(); - let mut quote_ticks: Vec = to_variant(quote_ticks); - - // fix bid and ask size - for data in quote_ticks.iter_mut() { - data.bid_size = Quantity::new(data.bid_size.raw as f64, data.bid_size.precision); - data.ask_size = Quantity::new(data.ask_size.raw as f64, data.ask_size.precision); - } + let quote_ticks: Vec = to_variant(quote_ticks); let metadata = HashMap::from([ ("price_precision".to_string(), "5".to_string()), @@ -390,11 +381,12 @@ fn fix_parquet_data_quantity_values() { ]); let schema = QuoteTick::get_schema(Some(metadata.clone())); - // Write the record batch to a buffer - let file_path = PathBuf::from("test.parquet"); - let mut file = std::fs::File::create(&file_path).unwrap(); + // Write the record batches to a parquet file + let temp_dir = tempfile::tempdir().unwrap(); + let temp_file_path = temp_dir.path().join("test.parquet"); + let mut temp_file = std::fs::File::create(&temp_file_path).unwrap(); { - let mut writer = ArrowWriter::try_new(&mut file, schema.into(), None).unwrap(); + let mut writer = ArrowWriter::try_new(&mut temp_file, schema.into(), None).unwrap(); for chunk in quote_ticks.chunks(1000) { let batch = QuoteTick::encode_batch(&metadata, chunk).unwrap(); writer.write(&batch).unwrap(); @@ -402,17 +394,16 @@ fn fix_parquet_data_quantity_values() { writer.close().unwrap(); } + // Read back from parquet let mut session = DataBackendSession::new(1000); session - .add_file::("test_data", file_path.to_str().unwrap(), None) + .add_file::("test_data", temp_file_path.to_str().unwrap(), None) .unwrap(); let query_result: QueryResult = session.get_query_result(); let ticks: Vec = query_result.collect(); let ticks_variants: Vec = to_variant(ticks); assert_eq!(quote_ticks.len(), ticks_variants.len()); - dbg!("e_ticks[0]); - dbg!(&ticks_variants[0]); for (orig, loaded) in quote_ticks.iter().zip(ticks_variants.iter()) { assert_eq!(orig, loaded) } From 6ae67410ba90ac39f612deaf3a09a3c41b6cf163 Mon Sep 17 00:00:00 2001 From: Ishan Bhanuka Date: Mon, 16 Dec 2024 21:16:54 +0530 Subject: [PATCH 09/15] Add todo --- nautilus_core/persistence/src/backend/catalog.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/nautilus_core/persistence/src/backend/catalog.rs b/nautilus_core/persistence/src/backend/catalog.rs index a21cdde83c17..6dc94339a81c 100644 --- a/nautilus_core/persistence/src/backend/catalog.rs +++ b/nautilus_core/persistence/src/backend/catalog.rs @@ -119,6 +119,7 @@ impl ParquetDataCatalog { type_name, path ); + // TODO: Set writer to property to limit max row group size write_batches_to_parquet(&batches, &path, None) .unwrap_or_else(|_| panic!("Failed to write {} to parquet", type_name)); } From 6c3834afbe7840b1b195d44097773fb109eb1f9d Mon Sep 17 00:00:00 2001 From: Ishan Bhanuka Date: Tue, 17 Dec 2024 18:22:38 +0530 Subject: [PATCH 10/15] Add max_row_group_size option to parquet writer --- nautilus_core/persistence/src/backend/catalog.rs | 14 +++++++------- nautilus_core/persistence/src/python/catalog.rs | 10 +++++----- nautilus_core/serialization/src/parquet.rs | 4 +++- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/nautilus_core/persistence/src/backend/catalog.rs b/nautilus_core/persistence/src/backend/catalog.rs index 6dc94339a81c..c6716c357cab 100644 --- a/nautilus_core/persistence/src/backend/catalog.rs +++ b/nautilus_core/persistence/src/backend/catalog.rs @@ -99,7 +99,7 @@ impl ParquetDataCatalog { json_path } - pub fn write_data(&self, data: Vec) + pub fn write_to_parquet(&self, data: Vec) where T: GetTsInit + EncodeToRecordBatch, { @@ -120,7 +120,7 @@ impl ParquetDataCatalog { path ); // TODO: Set writer to property to limit max row group size - write_batches_to_parquet(&batches, &path, None) + write_batches_to_parquet(&batches, &path, None, Some(5000)) .unwrap_or_else(|_| panic!("Failed to write {} to parquet", type_name)); } } @@ -184,10 +184,10 @@ impl ParquetDataCatalog { } } - self.write_data(delta); - self.write_data(depth10); - self.write_data(quote); - self.write_data(trade); - self.write_data(bar); + self.write_to_parquet(delta); + self.write_to_parquet(depth10); + self.write_to_parquet(quote); + self.write_to_parquet(trade); + self.write_to_parquet(bar); } } diff --git a/nautilus_core/persistence/src/python/catalog.rs b/nautilus_core/persistence/src/python/catalog.rs index ffc0c9fc5dd3..74636fbeaf44 100644 --- a/nautilus_core/persistence/src/python/catalog.rs +++ b/nautilus_core/persistence/src/python/catalog.rs @@ -30,22 +30,22 @@ impl PyParquetDataCatalogV2 { // pub fn write_data(mut slf: PyRefMut<'_, Self>, data_type: NautilusDataType, data: Vec) {} pub fn write_quote_ticks(&self, data: Vec) { - self.inner.write_data(data); + self.inner.write_to_parquet(data); } pub fn write_trade_ticks(&self, data: Vec) { - self.inner.write_data(data); + self.inner.write_to_parquet(data); } pub fn write_order_book_deltas(&self, data: Vec) { - self.inner.write_data(data); + self.inner.write_to_parquet(data); } pub fn write_bars(&self, data: Vec) { - self.inner.write_data(data); + self.inner.write_to_parquet(data); } pub fn write_order_book_depths(&self, data: Vec) { - self.inner.write_data(data); + self.inner.write_to_parquet(data); } } diff --git a/nautilus_core/serialization/src/parquet.rs b/nautilus_core/serialization/src/parquet.rs index 56eaf23d6d57..05e6859938ad 100644 --- a/nautilus_core/serialization/src/parquet.rs +++ b/nautilus_core/serialization/src/parquet.rs @@ -24,7 +24,7 @@ pub fn write_batch_to_parquet( filepath: &Path, compression: Option, ) -> Result<(), Box> { - write_batches_to_parquet(&[batch], filepath, compression) + write_batches_to_parquet(&[batch], filepath, compression, None) } /// Writes a `RecordBatch` to a Parquet file at the specified `filepath`, with optional compression. @@ -32,6 +32,7 @@ pub fn write_batches_to_parquet( batches: &[RecordBatch], filepath: &Path, compression: Option, + max_row_group_size: Option, ) -> Result<(), Box> { // Ensure the parent directory exists if let Some(parent) = filepath.parent() { @@ -44,6 +45,7 @@ pub fn write_batches_to_parquet( let default_compression = parquet::basic::Compression::ZSTD(ZstdLevel::default()); let writer_props = WriterProperties::builder() .set_compression(compression.unwrap_or(default_compression)) + .set_max_row_group_size(max_row_group_size.unwrap_or(5000)) .build(); let mut writer = ArrowWriter::try_new(file, batches[0].schema(), Some(writer_props))?; From d65a98c6d5caca49a60b0ef2ebbf173e859b82be Mon Sep 17 00:00:00 2001 From: Ishan Bhanuka Date: Tue, 17 Dec 2024 19:11:37 +0530 Subject: [PATCH 11/15] Fix row group size in quotes test data --- .../persistence/tests/test_catalog.rs | 15 ++++++++++++--- tests/test_data/nautilus/quotes.parquet | Bin 205415 -> 132969 bytes 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/nautilus_core/persistence/tests/test_catalog.rs b/nautilus_core/persistence/tests/test_catalog.rs index 68bb5cf9cda5..a22cea5d4630 100644 --- a/nautilus_core/persistence/tests/test_catalog.rs +++ b/nautilus_core/persistence/tests/test_catalog.rs @@ -29,7 +29,6 @@ use nautilus_test_kit::common::get_test_data_file_path; use procfs::{self, process::Process}; use pyo3::{prelude::*, types::PyCapsule}; use rstest::rstest; -use std::path::PathBuf; /// Memory leak test /// @@ -359,7 +358,11 @@ fn test_catalog_serialization_json_round_trip() { #[rstest] fn test_datafusion_parquet_round_trip() { - use datafusion::parquet::arrow::ArrowWriter; + use datafusion::parquet::{ + arrow::ArrowWriter, + basic::{Compression, ZstdLevel}, + file::properties::WriterProperties, + }; use nautilus_serialization::arrow::EncodeToRecordBatch; use pretty_assertions::assert_eq; use std::collections::HashMap; @@ -386,7 +389,13 @@ fn test_datafusion_parquet_round_trip() { let temp_file_path = temp_dir.path().join("test.parquet"); let mut temp_file = std::fs::File::create(&temp_file_path).unwrap(); { - let mut writer = ArrowWriter::try_new(&mut temp_file, schema.into(), None).unwrap(); + let writer_props = WriterProperties::builder() + .set_compression(Compression::ZSTD(ZstdLevel::default())) + .set_max_row_group_size(1000) + .build(); + + let mut writer = + ArrowWriter::try_new(&mut temp_file, schema.into(), Some(writer_props)).unwrap(); for chunk in quote_ticks.chunks(1000) { let batch = QuoteTick::encode_batch(&metadata, chunk).unwrap(); writer.write(&batch).unwrap(); diff --git a/tests/test_data/nautilus/quotes.parquet b/tests/test_data/nautilus/quotes.parquet index 0f02ac8b9d891e0cd45c817e6d491b9c1e7e2677..9501e35da98bd1bd8da1bf0bef48f268d0dc3402 100644 GIT binary patch literal 132969 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 literal 205415 zcmb^aeLPo7_s5UxPAW=5!jX_lk|a5jBuSDaNm5CYgd|D2Q;H->k|aqIk|aq|Nsc2) z?vjwok?y3Dqx(AF*V;4h>-YG5zW;vDqwDds)}B3k_UxHiYt}3-+nIKg=C-I?3hDjL(PG3wqUyjMZ6c74{mJhCXviq$!WcZDk(FD*C|1Mn`PSZE zuk8BsJ&d>Y8LO8u+8$-)bS)SU>$3V?3YmOqCzEfdGCuEStiI3qQL#yQu9z94>S0FR zd`1`TX5qSRKSt?wOmF&>(RUHk2L~~pzRP$xnelemQ{n!@GK|mb8C?cH7xcRE&)D-d z7^^R`>(cX>e948$AAd5c`Z2vrVvBHJa0jFBUyP^! zHmlF}6{GJI)~>@LjHk~t20Jres$r}i*(%ig+=B7;SEm2y&1C5tjAF5js%?zA1OE~3 zGo8d}>&STcU&hl)ZNhci0M1H4(@VO~ zz<$Dy%F-i-mhZKTw%3jeH+L(bhou-nq*eUW%GhLr#i^mADuxMp~rQJohy` z8R=fHSv9u$vIkkIsIria!MX|u`=N-bg5*BG0%x7!k}v-eYJTBY5NLerU}_y6 zpn`Vi1nLZrD(mir*O!*)+j~AJ zna0q$=8Dng1d?h4{7nR!ssf)|6=s_7B?xq%N zIodAVO)J{!tPDNKl5TKHbV#j#dqpqHdQ9Ctd#8AZb201I4BTg~CbQ05G1BT>bOxS4 z-&p8S^c}iF?T97sUUOmSg)<3*5Z!cSzqwjGeHMK@PrY_OUJRgXW}}AUUb-Dc_L<>U zd^xjG=vQ=TvMqXYFFL!_^^K#ps`OpgH+GW@qpBS{yj(U1v>Yid} zP3b>&(OfyP*FgllB!;HlD{ZS*gCyx?<0 zscXT?cka2kJwYlhq0)VJ;?S_%5gQGa9~?KIgZ|;b}VdHB(rzPUW-nd^) ztaQkg+cHggaJau#?0xs{Z`OM8cT?*!^#5_c-r{pEq0v1zeq&gPP|LNFRxhK3!E5y& z1(d1h4%lH5QZ~0M2#b+mcF`OxV=`irJG)Xvr+v0mv!;hMv3Jw?85zx;>z7*-dL-}R0xAV zT6u1N%h5CqF!PRBOje96b;@znmyeX!-vx6LXsozSzr7aaqwi`6t2V}dyt!JUO8tHG8a9=aG+)FRvzI$$?mqEgO&6q|vNEoYb26#Cr_2R2u=6>@s!PliCNtI)0 z#YkI}VLvd|EbXD^l!SUux{z7#p68ThkWlHF+vMetP><3V3^MVpF$EH`+%xOFrYwV0 z?};Jrli$=CfC}@Pv=*b5lxh!Jfs=vn2Q89n*8cnLph-&AT7AVGCMomJO^$a)do(_! zn`=esugl^Nt{-gO(1?C8i`vI5|B@*%C!0t2#Z`>{ zBv{{Wn95W1^-;BU94f{47G9!xf_y|f-3X;$fuqi`h*F>2cprnpQoo`n6Ng8X;+oE} z3P_m6u%EY9WH)rcj6!Pb+HRbL!P66TbH##VxIM>N#~}BOzxwrN)LrVIzf}7e>YlOm z!xwrWs-d~&tUa6_=%^D%0~?@g%g|t;IlHVImEt`$K5aKv84}U+%}q}w3Qr0&S(@Dt zBQ!K1qQz}G918Luw1-BtlN0cWnkH+q*b#-h=^b^3SKwPO(>_KY>an*$0^pea3f*8b zQs^7w3qvZ}x-L1=gIDF4s|j$_K33NDZM*SE)V^w~AW`k~EW9ec|0T4lqQo`FSX;iL z`&%GNzG_>QL$!?d+wH6qH;DO95--U6(v=XTOU=|n*>l=n7__COUC0%I-a+;inYqKJ5S>_)jl0o21^G< z{}qhP%=-QMP;17l+w2r?p&^rDt`=#XX_s-uiIgx|S$LE4^;UUK84g;hR>jWB6NZkH z8;Fr^lR4}yYOukRHUr}yqJ}I~`xXn6LwX&gL`Q8otVhYVV`NEbqcWyXI?cIc8~HKg z(udI{o3Rg}$g)0H4x#b%b%u+_SWAi(MFhF8TRMx@3rqKaLPDJHq}u}K4Kp^2@B!B zMp~%D<_p%E8Ex_aqAgMuk{^M$5*j+b?jHM!Z?D*;;Y#-CX&hp`&Lf0p|4PQ=cV|{|E>xY4s(v_-uKM$yc&! z32b{<2`vudAv0Amp|Hp%RgH-$54w5kK4zKQ^ivBkICd7TSnwIE!i>g=!xLIubCO`3 z+x;$|x`1K5)fh#{UNkQF9P`WVvNM*Z_MJskq|#~k?0U|ej?wSrVyG8iE3X_MfcDY>cG6ZK+_!4D=Mt?JLY~AZXnO0 ztb`UYp`@cqc7rg1Az?nM91H7NwZl5W=e?>e|DOd(vUZPY^f!vPImd=cTFe_aqxgmC_F9Q{8Fetz zsWusl-X68WqVJRyP>AW-+zIpGp8Ied4X!j9yFS%pV%}gGke;XXz)cTkEe6XXY#`i- zO$Gj%w6_R1*C7*H;0%{86=qURSa@kvrfm|;^cp|GR@JD z!(1nhUfate+4jv*r%LziRb7GBI&qb2HWhdo0FxW74Pq+YFUJ$yF2{Rm5*pFDHLq#F zrqrzWM>DdkUQG##v`J|IZmvkFdEFBf3FCmh-%Yx98BK{Pch`%rG=R-F*hbd*-J}FB zodnqGMzpbfwO+h4^~L4*`)DyWoQiY>Qpweyk55;LDE+4kh${QXx9|_2u+p|k+q6|8 z%20B?JCv6kjpd^nVdK5Xh)hw8L?b-(;e;2~`{dL5Qm^1Mg}xCpbU?jNo)hrwW1zE1 zTvhwOXm?mc+rNR%HrXX`RGoFw>RNk@5>?Xb+AvIQqDneGPQ9@rssWO*PFz{XhoF-x zQ4OtKfy(f;-h3+fB{;QwV1Ik!lV9~}6KoG!vq?~Pc7J^v*Afn`u&-xl3mia zaVw-cVIfK@YugBaF07%$_v;T<+mBy=w{`1z4)w{WhIa?;Sb;Zz^=j^PC~Wb}o0in@ zs@o@j8m3Yg>^T+Qij|?EqwDLJACYB6&lG&ekbY-TSD;`epZOZz7@XbEx*_o9;OvrT zfkI)t53`^@e@Nk)?{AhX3YzbUJsqkHQXloVbs(cu*=FW&1_PtXn(G^cCBPxewj zmHyk=_AF?NQKU^~jfXIAs4wyH8(w2=Mn`->P~7z z_qQ9(iCa))%TxArCv+|b$1)BwJnQm=q5j4nZXP6kqezRidQW_Y2W@zVpOI*i;2Lyv z1>MBL)InbgjqjlcEh(&je`5t6TmNnQ)5I-gUa1S{>C_W+->$Z-lC(4M6`3U(sg^YIubg z#$t%R%tOP`jk)pnRdO5YY3{jY?>L!B~Gumo&r{%QTgBGiEu9h@4qSjii&t5`ltS_2GPtfykJoZMo)7WVRbqxIU{R$l|*zJNlf91m<{3jY|K zkNp#&xz*S32_$mPeZpuzyX>8OM2qX>M4te9-s4W;v5xQL3rk(4r>@F*`~j1EXTeIr z?JZha6;_H}8cbN*&>TlK@+^bkFCW9LMb7UrbNup~?_X`MKcL?f?Qo&fbIR&02kd4?2T=kYdyo_0B-!+CwN}F|GE{l@xOBVy(zT=m^W@UbECi?hdVSXrxGW$Kl}B%^VQUP#ID z;OmyXW(;gtfjO+_8kkhII2-H%X)%E9z~HHPAv6H*hTUS!T{oF{dkh!#N{_Q6)?r_X z9cILA0Dj!;lxT}ZYU|3>BLj?8$a8bYHGEu;3m6$ED>0&c4V8Vunp*>|{o%7@ynIAn z6Gjx76bulI6T}*{ZD0uQ=4DF^)!KXquV#m`_?pCxiy8$a7c1rTJiGjxfV25@N55i`DYF&#T z_Ec!I&twEA;O@W&!1LTm0pPXhd11yj^s4U@)yOGjG z>_-pH8I75SVe#rnBR0&Kn&@5Tx2Pq~Lr3EK2wsfVy4mWH7L(;8XJg@D`&bNE3Icmz z6tBXzmUnu)0yPq8qJJ(I`jlV&B9{-NmK@Ai38DSw%_!Ln2=ljL-`=b;FBg-sV81>JPY zYFIx_8CCuha80Or{SVm5W-QlDx2|R*P=m3O-T9eG0m8M;OUElUC~5q<+NvV?!PY^9H+y=ucdQyIw-2AZ;Tz(@k&deHFpV!Pu3yV{S%o9J4Q?jQUyMNbcLiRWxs5VjyW9*C zyz$6a-NMjczgdwy;*K6c>X@P^OuH*ieD-0dEo}YRT*OYhrlb4&c6crw_&OFT+;^_Q zhZfu!dbMnPXsWXcedDadUooa^HF^OTmr;y>oZbJ8*PBk+k2>l-F$5Y}u&Oc307D?J z=|TX;WM-pQo>i6|mICZ)u+trDFW7BF-1nKK+F|3KXvaccKL7K}E;ztqX4qr6W7OBv z5@MGLi5B&T8T#0LV6q8|t>xKI9%tnuXRBv9UXWWaeAdD1OX?5IUQKImq<#v5 zg;;aR)qsTgudl+Ffr#1YvdOgvvBo=Q)(1=@!;9H*Qi`IP*PL=3v>ycs*0|Hxpk)H$ zQa(A(@4r<1@+){e@e9_@{CJ!EOgxp8*{n+8}JBHL?3OL0C%&<{@N+m>#ya zC7&*tsK7nw+K$caJOnMw)hNK5LrU8HqQ^$dP>;bbg`1w%9Vkqr5^R?g3o3|%E?&yb8yllawFqa_DZo-m^dbeUvY}J!Ep+ms%S0}qA26e4qa!D^?!WKIxKfo8-W_56^qysg5E;2 z-JG(lDa68#f86x49L~j}p|OaNp&GO>rd*$1XDE(baMrfal1}B4hoo=9aiW4`s9m!C zSQh%y0*)kmXq~W{y{N`spQK_J_`b6-Yz$S`Kzq0=EIkfQFGLiZMEeG z&Bps`$PDQBA6%EOKh0^fAr$3Gz);DdWh64B*w+i^sc;><6eGnkbP*k#vlWHOs+S&H>a8iD0WO zJJ6))zvnaHYKLUw+90~7A@j4WjjZ>9y=25?!~6c%W%%_+*zZ=~*CPl2n)P4xjDLp! zkiH9>Q7B82cNzXWWJl4+J*Gd0id+5#=?C5vFZG>nz`7n*Qv6{C4gXe1LvX{h4|ps) z?ja?=Mpe&o&9O9A`CrxKTH!w73GA_h!+s}IWxv>cq(l*!{{5&OuhF@G?P+x}RFEDt z-~h%UDau0r3)GO|kLypz;9_FPySY6C|E%S{_7d`LMEM6|JfB09FCxlE5apSO@-S3+ zo`xu&L6r9($`=vkX^8S1M0qlzycJPCizwejlo#{Ayc(XjBg*3u<66N`b@^nOb zH=;ZnQT~l6FGrMTBg*>_)c|)RnB2m7PC~rub=f(Wrd>B!_%m2+!5#`B< z@@hnRH@A5njwr9?|K`Vt@?k`IGP*n;MwG82%8L=@&$z65CFIHY?q?L`(TMVIMEPQ( z{4`O%nkauwl&>brpAqG$iSpJ&`ER1U8c|*w@@jqu;otwws}Z$BK|(YGSYFN4;9yfR z1sGxGN%zsiMV!3bpuAkI7SJ&?U=W?4kLbRgFkaK&w z3=Id{gjD-V8;(8HXK{wKo%Fc=*vmW|I^A5-;*INdbDL<(y_7nmDA`Xz$ljr57Jm#h zmX%zrG6X3zWGF&+uOdKlQBWZ1e?Y{&wF}pV{9W=9t)U`7Xjtni?C4`HQft!f&L8#6 zvxB9sw~D=Y79kt0Tp-h0D|YT0yZFWKg7Usr43uyl$gvPCy0`s^%C=KuO+xz^40VRX`O45zIy^b%QUdIWJdkRa(^sk3J;l!3Kaf5 zrAHQ*R%O_ae-xUxkbD#^+yJYOl3DiJy>?$}l#uAX$Mn)DX-6D##oFPpOm2OuRjR}J z#a1a+>+DX%ddAkCwL3A#B4(?H1GzYJv+NY-dzRRFJ1QMROV{ZeD5{K5n9yeg-@PjK z%dE7>Tb1Fc{pf91wXsTYuOa=ki$hau&#GhzrccFwh~|hsnU$fbu338bdX13NlAD(| z)XV;agZph6uf9@Yed<*W9TD0}Y4mc`jt$OhOm|dz6k6JpZlGQ7jz+1(zS#OqiEy%vu6+kLMs8-mKvy!Y4~d+IJ%y)@{q+jUdZ;m0d`BX}|2u$} zLPUI;rKX<5ttU4aDt`_&Q63yu*n%TH?0=F+s@3$z(s+ACcK?LY z6yc?qtL0hgrTPPR6|Gz_R#qI!8jrq;k>+ZX=E{o4{N)07ymz?inS~0tR+JyP1SO~s4MQiJ@Vrmyp6f)$2sqM?V6!F^lKlP-7{2cEPvubB>fJa z@vJkHHmu1An12hpwIW-A&P@QSKK;Xm&(PhL1ym;ttU;Yj(J zyGmDgIZDb$6eAEp5lV_HAiS`;3&948CPE6KA_zUqZMQ3M){32nWzxCnoXuMOw?~`K zEliuN7-^JZvzCt16A?jE+-#AEYovVe1`tK>QtC1$8)2EM^YDk#+ltN;)uQJD)+$k@ z>N3K%Mo`8et~SD0Ji;P*p+{et-9?BbV4@g4shs++)Q(%N)vvmxHs&i0o=On}jQz|v z{)NjAmPM2XxIZtrC+-`wfeYpJRH;eKwt617za-R-Tn z)bwgZCytkGNU7K8gL7qnqvfiqLU73DYIAvjUcC0D=F&iWZMk_^^aptEIdNL^(!;*7 zCr;ZT1!D-7l?=xfUSkIJbt_D~;1Gi8zuZ)F&};u*@zz(-@5WD2XTJcnRTV|>psO*6 zJ3STxe3yf@Rb$F~??Rh22leeeN&6TYdSS_5^`7%J@bYRiX~`m`-Bx3*W5Z)Q-7X`c z^tPtV!@g4%&bQCR>z+v0#H*hngfrA@O^Lqkx@B6U4R)8kjpDVXCGO(!ro#`H_rClG z+Dj$tozS86o@&wQPFaiB*E?l7WiQFhJ7H-*tlm7&Gs|IExcQWs^YIZq)$kxFh3D1d z!(ChNzXG*S(-BTo_k>EhEXku2I1=@+p5a;FYSe0=HLS%X32&Mg9q;YXYtq@ z1GDdREDn?#n7w4xLPza^7w??8Bz6Vs60N6B!DKchvB=(T_v+V_D16WUt>^U7ZL2iirc&3u=j)hy01@n#$mN3{O6;TSK4O6VDDs75OjE7cvNNv%E$za1M)+)m; z!Gc|@Qv_f@qgqWRPf`R+JRan)5OmR$LLzhFy-q1-$oT`fABDRVDh$_TD9huLx&&Po;Z_j2D~7 zcrP^EDho~te5fnp7iYI3COPopo8<$oZ*z@2~p(Ck3#ga zqvzhO%S#0-HaJuOzW=BndTvq^L$H-smJI7-w$X4b`QjTfEf#CZSHKaZVSqdhdvtl} zC%B;op{0Lca#Wd!SrtI3S8b(~xiv4#AuGHuI{A|;GMvJY$CcA!quJaEDJo1jSP~Xr zW9^Bd^c}RO%oIMVprj8+9~|AD=afm)_p~b>OY6+AhkXJ1;PC1kG9O_Y;yz?^(@3m0 zKXby;HUo=5bUK!zy?Ivi1!*DXEfyv#%v*=`^q^q_(06o=K8U8wBTr0i&Gc|{Oju!L zSqV>|A(eCExOG~{8y6!5Yw}l;uFopd!5D8Ob`)01P z^&pc-u_PIw#)Bg3u9N5qmZ_Iv52Gw!Orj(WGJOpD1y2GEREa1SBANRHAV+DH5Z5er zo#ZGfj;b#yXp8SFR*n9uuDH)sZ78$7)%5bk&k5J(b^l;ZDCh@%X=l@qTG65n=nrS9=T?{VCq19y5$@p9kcPdfKNy4KtiQ0(Fh z|H~(S*~??)PxO*jp%%#*NmU;g!EmBZ95*46^y6gZ!81^2_Xu~rq^h-FN9;5y0W#_h z@|qx#E9gF~$qPp?=dL!&My+#2WDog=I626mK%YD1%q1Z3jwzM2wrb3#iWh#x%XO~} zdcTK){mAGldYX+q>7C^(KgInVy{r7i2LViiyF=G1UQR})U3T5;+;7McYJ9iJC=$sz z@4DlWoP(6pgdG;SHERt{RN{2(Rc_-!9233n9)W8(`i3&063MAvCMk7qdYoDU@>{&o zIjF4T-=M4&z~-RD6=`s>$f7hr390dQ?ueT(H21H@zFq zp>eHix|@F*6t%7~ydgQUq@w*x^G}_k%2)rtstt-NH*^;|Bf8k0|Lxb#genjHCYKI|q*Z$5ycN)g#Z`Rt8!>od+_Mi`My$|@d-ihj z_w6|9M#FJ_NS@#Jo%ET${i28De*0;V@XWpY$1k0tijNcN3L7w7%FNoFuLM^rfTcNNf9+0!fVBk9s3) zLeV7Lr-PT;@@+ZZ&28c}@`0Y~JZ|o{4Zy(NRJ?pc{*Tdd6>gut%+o|=6Gzzm#vs8c z|9z*NHXo?WS5Fv!ZidK}IU-!sj45)%kU>M0SFT%u8Zg+O`wV~gE2wD2#B1>13Rir< zX9z-~{qd3$sb^6OzP{nNdGtKtyV2(xj1I;x_E_Va z3YB4Y8=|8yB=k;7h6z<$|EA2y;gU~HN>+Iy~St0K;hY2mz^>W5>ESj#oYG}nxt z>ju{vDFhmN;W&scdyzxSlZDzs4_PeAYSHio|83w(Uo8n*(B_+k{-nihz5B{C! zWJm8~Y$F_3A)H=1;25yri8kfIDT*mu+Hg0 zeNiV|=ev-sueM=pKquH(XO|ufgPp54CwE-NArtF|(=fs0d~z*(tOL(Gu+Y&9Nh6+< zmERjEKlLqe9=xT5?v>h7*a}o*A@rG=B<$HRd9m0~<|Yl(8Q3Ue=VzX>5C$$}4(y7# zS_BLf&b;~OvwB;ZX$jQE#_L5+pf+Cnw9wb)sx`P_AJT3Wus5T~ zjkRW!%$xc#UYDTbWezxdb9+63R-A??VP?6X{A__pGA4V@(4-( zXg~@T2}V<48h6ilKIH35gtVgS6_huhR(0N78D#1_71 zJFAlx#aA6Yp|?(DBmFh#7R3*q`j`mM+kR8!uwYVQb@j3Jd>&;fD<2^Y8F4@`x7hUw zzwU&cR^Q({XFT)W56eYSh#OKHN=EqvDm@L&Z}ko=lnTRkR@fV_%zg!BiPHN}`UX!f zV6IS(0;MX*Ox|3egt5>rj10`wTxT5$X_P=&QR$caL>uG8U030P0TpTTI+oDxf}K`> zgjTKx+Yoder5r-)U8Wo#e2$#F<2L!&wjp=C0v<4SLs#42X~Vf{FAbce9VNKYD)8b~ zZM~r|@hWyos0@2R7i|6z+d>QnKH?ky-7Pv-o3UGr*FKF2aGf@BuU(9e4@M}*MK{rA zc=a24P#PW!oskFG9-N7Fr51 z0rGWrn
Yo@AQ{mGwsCbdQBd+4=hZ+sC%fj;7YK2x7aVFZU_1cw#2_>x53-TX1M zP-+7uGf)hQK)p_jF;2CHNc5G7yyJ2ykcMX)bAZ}%#P8QePO)VVBNzJ zn=L4oFk-V!svYuxV=Yo1q)&c(Q0SO9z(R^M*m%!thl@Bj%`U^=Glt@`NF&zqHptLN z$rPKk$y%|boNp9slZw?v3mJd4v_2v*@d{y$y1)L(Ij)Im^^XwpD1Fcs_)b~a?^qA3 z`wM58#sP=Q9^`DotSnuPS$S?s9(=WmcKn8eZv!kxIo1O>J+N-{wc&`tti=>9*BvhT z(yy3I-unRZ&VG)Dsre8`4g;*xJeWLk>>zPF=&KhmIfm>3%mNuenC3W`W>~QV@*7~_ z@vAt<{(*zi-MHNV!0+dfy8a zXohD=>#Ob&J40dm3@>;atiuMN2|JA@_eGiY_-0vT`jY3TW9(5a^XVhFDqb1j4MTXz zKzZ(I>&=#8+GH z8#m}BR|@VkeMuT1c+ zSo4Vt2qqn7@9x`4h|4~O!9uXM)wf`&&oTO)uqLF$wENPmFKh`lL4GwX+*AaNX;~E( z;4tY~yYibq8vI2LzYzV*MR(Jb}UsO^*m|G=*R zt->;%k6Lb!-4zz7TdmTk`5)d>%R0Po_L}%>BV_4y}g%FvWO4R+fnxHFKo7IK;Vh`kvlJ1K*BF=|s z>zqe{h}Z+Aa5XPP22;cZS~La$446ekd}6Ii5uH)mjRP$&oDZ!pp{F0i5z-|@JZOD2 zPy(8814#oU_KL%CL&-;>vpo!vErO##!Tz8t4G%@{FHS$Kb#`F5;GNN?f4NRtU8=p- za+|aY3N_oL&BKR@wTi24mz^|QZK$P&O8BgQqOWZ?Nt>r}q}*ID-cj>N_-r$zt$+G< z(gygKP(4P*XopF5MMuwd_#cHFZ63{GW}MC+*Vij`JHh zS|!~4pP`FT^&IQyK;_=yWus*O?AJTll>Gw#aqDwre*bEdJ%BOU&><_)54E&oy~K>} z_{73U-9gLgTF;+5Ft;@}eLsoJcNBrLqQn3CUY+=cSF>=3kTw6^Sr6U@x`!~V;xD}% zYl17@_x@Yk!=&z5Nqi&&$UW2rfeI@ww~CVb6?XCEfe?YK|4 z!BS&bxSLSRFDQjN*+OG(msB@ec+k5q^0=XKf%dkFr>;5g$cHS-MsN3?2mSi#`*xe8x;HTcb^xPguAA#c zTfZJwp+a#tq_;@R;g8C&zbPYT8YJC~GdY}rOUOz5-xF}rRRsyrPr?bf82$Z;|Iezq zoiacU|FahUss;U>o0+HY_dKm>mn+)$cy25BiF20X;9`;kIOixa`CHOl*EZ<4wvAr* z61?xf>^X7Dro{yxz)P;n+CGA#bUv$efzh82I}tx~Za?sM4aqVQjOLtWoZmTzM)K>N z8Jx52S4n-s{aZK>E@pBu=R^l4-{<^1XYJH(l((77cyMU%O(b`Z-xSdU{u@5aAHceL? z08Zt+#`)Tx=^ey3MbmXX-KV<-f~9#QMoEI#c1|jn2EX<8_LKpe`!M?TWfZ^P{~YP# zkDX~Hij9BlI1Kz%Bvno9o;`P?9JqbO_3+`~{7)am6u^rMZ|4%D>=;#E^k|KMtRS{_ zmJ%pEu6B|#I5PO;&C%e*%>EZN!E^l|uNVUk8^E~t$(tuykljxlFw+K8K0Eague7+& zoe17NAk{btJidKcpUI%k(Y;Djh$}`eAzod@m^Niny&>ei28_qW?o0m(xwRK#nQ8iP zW5_Zd!^Ee9+c^K>bpL3RW&*v3<*_7d@bX;7iD%vI=0i5z5m;>t9x*!{xEP!`i!rdi z= zHBv8v{@z+u+2Gx-HNH9E?N5w3iZv@PLw>=j+P?k-$*BR!Lvz7^K*kKt12c{1ll~)T zm>HAJXE6?vYS>TL7d_ng7x4k-js_-coR$>30)4ObY14>i`es{*e>rEZ$pib0woE2E zU)!N@72I9GSg{~CisU2(n+l?BW{6on7_nJpCvl!hK><;22IED}R!&({rnlf6B4OV{ z<&y?5#ths7`YxFXMd09I#%3p($#or>A#R&n-8VX^^d&6wD#cPMva9AotYv0I&x4Qv_bwoRGx z9&-P7#^U8$#JV7-Xvi27A8`&C&E#{MjDyB7ns9F9Txc3%-;Mk7IhAKJc{is;{k00Z ze(2<){{MoBy5T#CeI_v`a8`1P=`sCe&f}a*Hm%wB1^2z?oN6pqOtL5E)ahL2yk0lO z@GGt-Bvx-Cc8!vh`wqVEIA=?2&%O2aH|Uzjc$Bk@Q)c^8{r_-%Hs=-*cQE~V&LKOQ z{P!-#Sr-3pp!?R(WmG+W&$?G#yWBp``~RN!kK{=`jB~d?I^75IZq8iJmz+5}*!4Ef ze=RmXq4G=TFdpO_I9O7lFZ9zn&v1GTVfrhN&n=?s*U!w1BC4h^{*lVKhx3=$lY4Z1 zwKwBb!!6?dASZIJ{gcV^Vlrl=&+Nr0-J8+04_Ja&h!ILZwk$GDl({?l+T(r1OvZzHyHDuprmCFi{TOx_;O%W zeXY_T_kHG!uw(K^PW44h-l7=dMCE2FF&_AXvHy!dj*&izvu`_-<6koV#~HtEk(30= zg$)VcOYHkd{WkGH17m3;qsxUUCX&#{aGv&flp+PW-#W&l!*@)UhCJokxXxkVF5@+a z$RrQpy{kd@|xf!{iUX3 zK%1=LfjVILpx0UxL5*nj`?{oGcB}s+Fqd<;+R|AhU*TM-&g8#1zi?`4FugNp6z3hz z9?mhNSve<8w-4Prss1?5dz^At4_zm{C1((47Uy%$glnwangYhZg2#QP`^N2NEavRy zT)Kzp4{{c9e&QS*!mc}V9^j0UUFofddf$BYEY=4T4xKif0zTlJ9K~dJ&UnuIobnFS z{HgqQ&Q{JjOPD^uk?{%VGqp$ARDPu8%u@#7#N_?Q%t7n&?!B`?1(VA+tic?OTha@_ zyeq!{E&>Y`FW+$iC*G~UwH7>mz4^5VSPUnp15yyTUJ9rPcjPnrZj_W0J zNk3-qihabToJE{noJ;nx>lO>X-4@CvRVD64`GcHYoZ+XLzH^yxpHN(P`j{F-{CjEV zh6CVbC&o|e`!h*)yLMA80_^O6^uL3k?xCvFhrrdGd)-=9jzDhwB7cl{@^(%Qv5NCT zZvKxL$U}G9O+5-0TXy;pmur9f`xqF-*}1JMuUhj%zbO#rcfy6LicoA-~&YbUX{R3ufFc>pSEkXkWJ|$pNrt~)A z;h!&;l!B_(H}%WFoZ*hXM8Bt>GKrV}`u$%y=zKzYXC+;aluv&Ej(YNLZ#7tbJo0S~ z=;S(9vlfh5&A9FI@7@m~cc%26P!F!{X&TT#a+vgPVyLpkS3zE{T;B+JQ%qP%6Zn3? z*l|z5`&ZU|c?~|e%J@*$==>YVf66gdJblPjR z`G^MCS#|cjCTO{)Y19~S8|Sr%+0tVnpXiV)Ar8NM={NCX+zq?&q_=I-m;_dGwlvE9 ztp~Yw;gaYnV5Z`y`$VG)W6TXesf&yUY##pl6Y@>Yn)7Eb8A1MH+B9YwxODRKg~s5p z6JzF>f}IJBp?Swwnn4bgStm0K3`;*1PW-)k#s_n7;TM1R*jvy z@1XO~Nv`9ZVm@2h7V@@+pcrCjVdyJ6aM2CM$u}93&F<{ChrZY8BhwaxUgf{WIe@jC zve*0AFM-?{aw>|rVPKQ)Qj*u6ZzC@9V08HY%*l!L^R7;HCcQOdl<|#K%ONkX?Rrd% z=3G+8VDWmiDoaPWx9N^p84;~CEWhnVcm8SF42h{`D}VU$_Q7|7Ye>7;r$kIEew z#rTo)wHlM>t218a)P3vPMdc@SFdpG_e#hiHoJE~Xo_^(*whPMF<}psa%BY{uc%O6W z?&BU*u84E7?1N_{@8>M!93{u}i#Yo{@laZYa_cxBaQ13p`a_)EoSILW{uXB!r^7R* z59eHeuFn#x_Y`N}G$udboSe?&c+TIPlQNjzjkBC{j_;`>RNvYMKC@lH|2U6VG5Hs# zYc-Saa;~gl@)1ty;{$fn{ZBZD#4~voX9lO)38v5Be9kGC!1O_!S)Ait&)%SVqdDE& znB4iLaq?>D7ky>)d;M&=8|0Bs+QZg>`#6UhT{Uute1x-h^{8=cA**QJa3hY;X6!8L zY9@K_;xUUnz$wai4iPIk_5NV;an4_ylT?`g80Qbpn2}5`{nGg!)f2$k%sKNF({JK5 zdClZOTTrf=RBub4wKV4r7kmh6X#>j>A6g=8gyhP-M^3XE$1KG zm_Cp5HD~a4rf=s|*ums^oI5#lICab??4bIObN=GoGMni$Ii)R_Jc~1(^V}S!*E;)a zq9^LP!#OsU$&sA5Ij4IaUr*&yIK91@T+3|elz_V&f}aFoVx$9>#I4Bah7vh z{O$UMp0}0r0;fzF)6eG2p5FErOTOq7H0f}oIf~qoSA+V=ii(wmNR_`=S+>s=c)cpoaZ<T|C2L`vxalQ`^t8z{}rd=2PV(wRQSl`s6vlXn^8_`PoL$)W%7SM zB)%WcXs^H+6cSv%75Xer*XOp|gCO7KjA>=Ebb3cV>6Wy zW-xgtXB+2N@f)60&+`6^C7fd=m>kJ@n^SWD)2DHcu68&__b=f*!1;kQtcG2`&N;G{ z$@@6pa@y80{VUG66J4!T@5BVgSk4J2nS6w^lv68_>F;owx*hyuJMK^AoW6$1DV#p; zOs?Z}SODPvBg5#q~Sg_b$ytV;7iSRVNb+%1t<1N(|z>aJ$iX zH{@BP&VL}z=`bI^2W)y`wKxPk^`+2zAET*$eX^DSrAq5+X~y;JGzUE=I^ zlfDt4(xt{3L>tcDLH^rFUd!n%dHxg0$((1-JX?1V^0XAj4V)i-XDdfSzxY4K(Xs6@ zBu8*2j8PhN2(n*So(1tSr&L(SO_KlSG`9);M)G-1sTYO5QIJzP`(JdpK(e{%LG{Dn z7S6qc#;hcH=cD2i#M%bNRi~UEksQnUozo?W>2*E742{P1BkLJA>m8X-@)OQkg_ZA* zKpy7rV}BI1;B+$?aG2!Owf;L}!JJ7$t`ql6X3XPs|C!N4`U*~UHMtkZAUnLv9vKG~ zawccm?mG^-Yg5N<;u3$x2+l6fC7YT47N@as=uax&&xCP3XDz4U45qIVA7vPia{B!l zCrL2IaZVh-3U1$ia9-W z4{Dx(tZenmrBjf5Zkr5D0>>3InyL)BN%AJnbDWKw zGe)xOg`B>YL7AsfzMgaATqbKv%e^A~pZ%1Eo&o({X|6d7HgFohW^!0=@oCaeHvcj_ z6)bPmjv_Xtl-(ni^*X-e9JsPK;}Om;oLYUD{xIhqPN{o(1$3VuXDa8Q3a0nvtmm9| zpXrl1#VeWY#i@L>@?Wa&3g?JeCLiSd#CdXshi)3m^p3AS26i0=a#X3 zyy(6soHNHU`OJ7m)lZ3Obp728!#3i=n~Zxo-*PUv#q?J==NB>gGUuw$I+b+XU&gsI zjLGBnGalmnmoqq=>0fgGwDobK`&TbyEa&{esbk0VM>)T7u3W_QrJT}=1CCKW0i5Za zLzI}_j5D2ch%(bRac=s9$&H*#UZm7eeK$GP+nIcWQ~f2A!#O{2-VbcF%)ou!r_HCH z2R)J*9~`k-l?nM}4CAwlgA%VaY;Y;njV*)foD-OR3!B=@h^^tcFKYhW}uRh&Zd zNzUF$OrFAdg0qry@@aNGp7TEEf1GZ~?D{>sQ%}iTh}o;!;^8tdd7NAJH0Q8 z*(m>dGUI%G#*$yr4x}IZoAD55G3S{7n7)Y9_;2kaRQ?QSJ*QC_)7No|-(|8P=X%aQ ze5h9=`4&OFZ7ob$)9>z6s(IbGk!1=Ia^IVXHz@)6FjoXbBly;B!s z5$C{bdN=6)4V?9y(+Ze=KuF~my6($a&uO%m=}&Wt?_=_M&RR|tYmdn}xIdrs+5GmT zJjhzI!Og@goMSTb?5;v?a(B3v4;sCTURnUQ>@KS&-jMw@=Q{ZCNn8l=&lbic&c08X zypFTiGbS5wUOuN+ME5DAF=k{ij`6MhPI`Mk#_OD&Rf$=J&=;+))3^a@xG|1e!`N5b z$A$DKIrS$n`2^>GocDB?e&R$%-LDcS>Avu9jAw4AG>|M&%;?S8yM)PWIV(A{510(Q ziSlw0jQ#8zZAf0vS4Tdo}fpce*>_@sT-^|#`Y4L=~Pg)q4p3NR#gmSkyC#N#` z`#DCJG{#a+Gasw9R6d<^<_0GFb2f6$@MZe5oDH03HZuK4!}c>&&pu8?BPQ?SZ0EF^ z#`F_<2S26qM>t3KVe&!FBF@o$nOvJ*6t8FjNxC2UVD61<0uYc;jxfC4P%@|?u zY};MPU7XQJvUSQK|Hb)*GcbnfFD|$8r0X4H+f#{6pLVqptuCm}sQ^0%b$ug_l4Nv! z7%}BO$2kkziqekNLFDylvN zW1=+uAAz?VinEChOBma3OQbeI9$w7o#aY8S^$yd|RJ2WejdJGio`!t{&vVW`-h1yC z$Xhu(ztkFhgEt(X)D^}>Po5t54taCRXTATxL#d4F%7(vt)g#{bvi8s3U@)iY zh&)em$evEo8wY^ZoSnn<8U{k{zOdG25V$s=_W|O&AJfN6fp$L`hnGEeC%Ki=Wa;3i zBnSBK`aA^mIq~*|G+0x*xNayYRr&Y(Kfv1Yamgy6Uf5duk>GL83gyHKl6S7$TB`=m zH{GW>8obP@Fq6siI4^O^nK8ZQEXD{<$$_e_biWhlv_VYPdUQRJ^q)DmH86SQsl|PHmh@gfN8_(I;k`I*e=|9cb3@FsK4WmbjdS6c=pd3OzaM{< zsIhm|gt4HJ^-m9?_wz~5i5}ZT6V0_Q(uyv+G@lEh8Y57lD~;B4j`Jelcd za{7Ef^OedcbA}vxykR`#H=J_ngI|%njq@VsbIwc+c0K>uMe7MD7m_}AKXGXW<6OTN zB_u~mC{EJ>KXLljUI`#sua41s&D&0r$9*5UW+Eti=lW@4f#b*Fy5MKEh(*NUE4S|v zzjN+;GQMCE&3YA(AnP^ACIPy`=wtXu9usp!@ZY<7mie zSQ$lSlvPniR*8zF5-O|GP(-372@NSUkcw19p|Z*d4P=BADpXWA4U*E(Ucc))*Y*4B z`FOpr&(|O4KIh!$ew_PpGhR$4vBqPDl;NJtW_G9i!j^bL2C$;}W`_E(I~0)D*q0%X zHsL-ul+0mYuqIZUv+(kxeE*R#6m)SvyHox$cKP~8TW7$%g8j|&`#D` zgF2sG{Xt50Cft9q9v`U}eI^T8!IErye7BaZXI-z+E*UoWFy3dg7untWX&+_xvKH^V z*oMsfofgpT+ZGm~!vo0m7CoP_o7nZ1)MwZx_JruZ$(Hc$A!{r~eV-j9PCbqFW*b@k zp>$7V z$&;*L4YfY&$tJQZW6K)xyE<0qD0MEo-PKimHryrL$XV<~_9;7J8Qm?}ZEPDmUiGUL z{+!dSi5hj(c=9HDXacq9`{=#+-i%FQjr(X%X45}VcYY+@i?mAdyQA!P_FM_=t*p%6 z>Yw;7F^m-4N3LZP*pap?4d%eRovh#j>XWR%LTWvB9cwu9w?BS&niZ0z{wPOoyQupH z?=vrvX{>lAwLja!j^9$RY6b73*i7?v?%0wu$pUuj5TR4JC$LE()P|zuIx$k~w4szW zyeq9r5u6KtVwYA^N3wnFK9$Y+`0g!hr%GMOj#s00W=mPo-k~4xySDeFc^|n^Ch(aJ z?7}0-4XoocDTR5kt6$1qj2>nqx6F;f{=i<}N}X%^vL5#!GqQs%o=&}NaOe^*jKFF zPueF`jPb?q(%GSv)SKAzY%6P4MfZp7n1dx3@cUlY;ShBZt9Y1tFPr1M_!Yj78T(=E z0#HnuyrV+O_C&hjp2bSNrM~};d{&?qk9Ube(vrQvKAY=0d?DN|ZAcx-uQu4n*cx_{ z6zxCQ3TbK$8PbhC!p?1v4#%I9!|r)Xy(dHK7VZV?s0-9e#w(5NU>7zejoBpD(2Vw? zfxoxlyB_wzz2mvq-6wT>(fNsF9^1uwuBxA~2=4dTiQ4N{V+(#0OhWZpf$!9ND^5MZ zT_DnMq&>Lt5ShX@v*saY<_>UAV`oZizKWgBu9TwI@U>j;2)l$oIg4##?WR3DkN3T7 zA^V2iZAAAJ6LPFjU5B3hLvx@d(tgP0{2K;U(+sQuHroDV3Dc&CCPpS6QK(@>ckB^h(K-?4)w)qpZY%{5|+?8~c-;7(sh1Tg857mqpTj zd=weQrrR&Pi9c_s1G$N9Wz8IEPhs5^dw$^iqwEiMxf1OfV@Owa`s*77 z!7lISJFD@A`bzE?fBbIlWip5DWJg}1J)4!zqu#;Z3o6OP?*(^~p6p%rL@@1jtjw&% z-T2;`4Pvv|?X&6rj5V>MKFf|6@j=B2zTd`Xux;!x3A%4#AG33P%3AO{<+|tyXK+qE z8OT0oXWgZJ<}s}*e3!Y=8C~dv+A5J@!=B=1xdF9XMo!C9HW-XZ- zqjm=OMz^xZsQxliSj|;tHFO($tnZ5*_D@!|IQk%VB>SZE*N!#N<}b+NExMnu)rPF| z@&K2Jk=I$H`-10jKYTbvbRGDa9e;${nZ3#0i>7^Q47uLfYz}^Rnr&qDU1)!+@@O~S z?NrG^c9a^m;MJi&@IIAI9Q?A`3wp~CGL4-sLha9rQSW7E#2+ul z`-TKEnSHcYIAQj&D9QT8c$rrwl7WifuZUV=x&R)40bYP2F1I@Xo zaX-ZhYEeIlkhj|c`_jCy>03dk9b zofjkg2%V&2ws0SKlD*4Lw9POJhu!kx_7CUiG80=)4o;KCSHaG0+1dLKI`c>~nqkabO2qdc%Feap+I1+D+5S28z51%Bz0^P>8vm!dQN8Vb{g7>xxa{RmE%5>-!X|=oz zP(+42Q+CJV5_HF6!4mZJQc`ZrsV~?g#*xl1bwmrGZ?e(mAsQvn%e>ymUIXQ#9S2_r zSJ`ZOR1W@K^WsAVcw%yhb|u)=qZC^OE`Cc632_vuhW2G2u!iM2BWht^ly6{M2bQ#* zRlfu3r<<-p|N6Ejp)WR)bNxu+hIIRS*p1nf?oVs6lfFpKybI>t%-V@|v9_huxsR2O zHNbu>wYU*&SO4PQ1cuLi@wF9v%ij7UQ2P{mXl3HSXJ9Ma_ipfKY?b%qQub8O-W4xk z7kW$HoaZR{5;`DFwF(`PP6n{)d5OZ^un&~*DM82f_wVQfAC(>{M4iGlKcS}k$yC{3*iW%$3QwE+p;Ot7qo`k;kqh_=yLA%jRC|Ct z58EQnSkVdL>>pwLxv)7pUXCeTA10yJiWeU9Xg;|@C3(Bs_Sd!zf=680Ty zzmo2Q4mi8ag?CX7{m0NluQi6+fL^(k*61|xW4}-zc14~3N?Yiotkxas6>K#-E4J|z zzPrGByLHc61ihrB=o@NYk(uTU7P7l4sq<&AIOGZY)JJgxy}(Ac_3yt=*gvz=_V|GJ zbI9|_nVB1)&wExnZUUWkRz#yOdjEad44S+nhrB0!*$3?YKH4u8p48m}?tgSN9*5VYPzGJzFxtX#Sic29O|ew=79^a{-yU#1L09CKq>3I+=W1FI7&tbn*uG=32UY%}|d=&JNoUe2Olrkw2j|WeWt8_mJ z{x;GNJOx^rkSPNj^RY*}C$BpV3JK01cNYA$Lh&J*s#P>R1sw9(ejd7kHR`9<-hbd0 z?ml)Ze^I$nH;qz3-`3?x=Rh?%leBd3>&&#c4A4q1^X3Im=Rf-encxm#lM9!@?EH>t z`Ji-q*Qx?^^?{l~wA?A^D%w_iv>41ex26H@^#3PX01W!cZ^ONXUGKJYM-6o1GV=S= z%l-H9=lFMdKLFkGDmJx%VG?m_t+=1BJ%y%>kce#qr3`oOYR8VVo%$5qaEwf5Ph7t` z?iuWV*oL8p|2~IKQW!Mz1vqdNnJc#^s|(s%o(y6KbdG+5doSy@)!w}u`f|0pSr2&K zX?Z?+S@}mFs;^3#UeJr_g?4Tn-TM(tjlVkK6ZlH$bIoT^QsT#_e(;UanvO4EgE843 zuNU_f`jUG?11hnS?7o?_=Nq*6@yi0gK)X-7^Ux|*(ycb*AM}%%&A$a(;a?Xo^S46a zm5$wogTQMK_Ww5+R4zQKCjxp&cQ_0K2Y!CNOCG!!KKeWA+|_$g0h}6p)L0RezV=sL z2@DELSc8tSnG`qyTvYC*I2Ei;{`AxcbTv?4Yz)f&yA_Ro-}hJ76kIQ6{J;zp@ZA5& z0<_doo@5C+sj5580uT4zI*P{YB%QPZw;tR$-x{=b5{*C?`F|g}5R9I^|N9cKf;AUc z)>{hwT0UW$3-01c$*$n_=0a z{{%tLzdveZ2v{+tw+5X$@cWo3@KAlMEBfN=pScIYdEdyGD`#>JL2Krb(X4;+xH(5* zPfj5Rr;_m-uJ6Wu!uVxfaiB;^?DAuvn#H|;$3e~HGgsjE$jUsL@=zllJU5lxphq^; zik!vWCHh=DD(yN$E&*KaMoJeCzk_W$^1tAd;4pczWm~RJBD6>VY065Ay-vry@&2wC zsKEm=k(FwuzO?Jy^Axy0V^{B{{*ylZUMlR#7f2<)iz4Ts3)zzPkAKsl-<>~boB_T_ zBj=`*s|B7oXTko9T`5SdHh^?uYgkW(d7E~bGFi+$@Wg4 zn1=7h%pmu%0|(c1;J%&}5~fxfLhfVVvK>vU6mP=&@ri$&(4r-0ZkB>hPUOe}U;i@b zcZH<=RkDOF-zAcT_mRT07u*8VSIG!gfX^o7nxcu_b}5yhz#H<{mA6l^2jr6x1*GN9 zaQQ0ObwkKnc5*27?I%m>@jkJQjAb?3snwp6apyh?SHru18xLBdCxvd6{IA(O38O!? zuup&dU|Joh;VY7h8XKH@i<&6p&bSLEvsRX)Cf$S1WF==&2e3!}T|3$U_xr~_iZ+6+ zD-O;y*;P5zb7sb$#CNV1y z*mFR{1K5+<2dt47?MZBy+(o$-c=wjo*t+8m_A)kxef7X5q!sq+Q?H6q@6+UV*YGiq zp%*(d2P#p2=$g`w z@0N6v*ICQFyRu!d`|R*^K<~5l8+?Piq2~&m>qlp-+>-tVJkLJwzo66uofq-^7&>Q^ z%+R;s=Ny|bbp7^MrD(ADD8pXRdMGL7{q_y^dc$zFcVO~_gA3n-9s#SgKY%jLQ=X&t z>phoz1dCW}y#cY3eFFa!PoMf3obuwrxPI{GX`B6DKx>^{e^JjV}9ItgTiY`*bnBs?Gtzee_q!7W;p;Hr$s79-u{X$-F4!^KrnsB-LZo}-&vk+=n07d z@u<_W=|;lftQ|IoM8N45uWC@sRt0lW@B%yh5p_Cy=rOffazPNj8(cGXy%@Ob4(ahB z%1Inr+Uu^$aB$htX_6zb)qEq+U1xF}r9dfXyAo;errO&t=!zL`!(_p%U%xlY;hvs4 zU=*mDK}NFPe$!{*-ozFgKi+};r(AlpB4|@V8eCDBqXccdvtT!>-?mS040vbSk}h<& z5!pE4qw-kjo=EM=aiC)q8Rt7qP8B-T;DH0Wc-X6^3E*Czf-rT^z|gJ?{jI*FM+21j z_(4q*JeL&{r3Ieeu6-LF5J;9K#vIm%j;#8<(*PWD@I(=s%r+dMwjFzSvLWo3S$$<{ zJL_pm(_k-T)fzXK8bL>~AK4{Mw4WYfS8WP+!vRY^n1RA8$EQvQec1bK;h5V)%weC? zwQ?4k$x3unr@kS_=Kc=FdpIi=bmAJeZreKFnPBcYp^NCq^JJ0F=~viA8^|8k&X;;G z+s*3U-4Jg9?|*)N6mAJRly1I-USo~IhyBG)Vh8P~uCc#hGz-6D-5sc_SfRj}xVdmw z7b$;f4^C=y9qRxJ-zRmyR}XW9Zd`hz91U8qmr+`y5Vsd6j9s{NbqpxzeJx~svht#dQbF^|YF*4{wDbq(xS1PhL% z-`)1j^#IQ-h}ygs6p|mGg9fpiMYSKVgO(pkj%%)#_Jr0+hF_TkdbkP|dVzK9S~u!? zR!Q~rN4$rzJ?zMfk7B)XXM0$?OSCIwlA)~k^kJet@cuqKXa==6+r%z3r@c+&!fbp$ zOqATpwz1}7v13mVJbp`Y13P1K!hzOM0yy?N}3 zx=mn3kM7{j;9P5=Vlb?t^aTR^XJ%dl;rX$5(4jI?0@bmUml{>t2J z>>k!Gk2*A;9AUI?VIbT~PAnGM0gjDl%gR1r%e~fm9t3(`u2$Fyy3G0=gO;*(v#H;) z_H(FzE#Gi41l~QmVYVz3d}0`?z6T8WFy`=HFmlVI#0apDUA&dLgw?3Z-W~<_dD8n9 z9|EskDyc_(HZ2}<7;Ivr+E4w7ftGGanQ#=8o4EN28c>$8C=L{fv^<3FXFZex2Ofj| z!=I(AAe_0N{*oK)DiCuzM! zm%7#4od@4tN|~4r9ypV+Gy{CkIwVm)U>B{mJc{?rE^}{O0K*E8w`YS#ck9aKfHP#) z9YJ-U3En|X(@qV}1s}4;>D0;W)4>~x@ophZ`rQ-$f-M=JqH`Gx`nKr>ni`qmas`|m zMIK{+u`3VKemXciEDzoZg^(|;=aylwY!5Na2jf_&r_|@q$#2HJ_&hl#jeP8zpN)I_ zy|9%9U|IvY^!S+5*paNt3F-*;&CSTDLbz+psn#w6(>3nzDghI&3x7w;1YiEW0R}J6 zzkCxkTUgRo3cj-=EiKCil|x^v`IUAHTv$t*h&{@xf)>~l-T9>+V|*hOlDqsQp+o8{Kht;jZ|-HMap=+w=5E zBj`6L`%n{ja7>w4GbsAn#R~Ofe+kvEXodb#zcvvyj1z1{A4doaKE`+6Qj6QbAwHyj z-3#G%XzM%VU-^=kPoYh>N1k{Fii?*Gdk(I8=wgGK{jQq!AEl-S7$&HXD=K1q$k@wRD4V_nMCMft>A3zmi0{sdKD6ujr}^Ysog<$W-j-m8A;8V0no9t|4Gsd{ewAI5UBC_3iyTn%6j0Q_twWHKg z>}pr{aJ<*DlijF|-yi#fdonwykJ_6R`apfTSjR{a-pO7gL-*dR7mcjwTgVwoe)d{jf0WJZgNEOk&sVvhKj$!sf+jW$?XB zh!fgYsoJdyx?8(Pj0Yp;k+)=iRbp!l66~7*zWOm(UITnxan=#td(bo*?PfI{Tkl|N zUr7(q1f_#5O3=P`$qicIZa?dnsDM9NH6X-Q8@gr?xvpOB1omBa%3bPs_77VgpLZYM zMfz6R>3~x=lE#dSIWMb(cQqr2azL0Q|@<)u4`K zwLb(e$9oK`{E=E`rlZL;*at7GaxezZunSe)k6;UoC)affd@+Ge*k<5k3W|&Ryg-ki zIqPBuPDmn!*P0&3E@Q{9qdv%fViSM+51kJ01pkn3mEv=;Z?O}qsI66>{=$81k>utX zUe$jQKk|i|Io$u-lJ^J=sf;MF0A;JlU^cQ*;QMUYZ?Gy& z)CbtyRR$a9zNtWp%wJG(DeP*;16qy3N%sb>0k6gy5zRG zp!9$j>Na4uqT@_ka7_36o#^+v05b>B{SMg~D;bDAulCEJlmEn41qeGj~o9&>i%Ua)E$Ik}+a zHMTqaA97*fLsorYR>eN(L+qpYPUCQBu>|rQ8?!Qa8}2{Z*j3c>t4S42_+?RWk6@kq zue`%9WmUgW*OblI*bn>3$nG`hpY9^r17On?2M08I$NR%*1v@E-`a8R9C*N81VCv3u z&cPAzU6sL+epKCve8ujJTag|Kdk6dLICa$ta-aG!r6{=fu(F!e&sq6TlU?xc{+ayS zPb!CdG~s^r09g=0-mw!HdJy)6(TUdRKlY#^wN#gW815l#>vr#7*g}s@vJZjNl3U)O zXV`&fslC_+_KlCf+F^M2Z((p?H25-ezIF^~lSOKJzK@B8zQsOU@bgt1bo)Z`(>9NX z$Dlv2_5OPtbXrH=WQ)A0U+E4uJ^}ZXspQrSt3fBB$#cF z@crKNq_s)F;#BA$_BA_2NHPZZ1Xgzd^>McJZe~5+zuqGcH;`i!tcIL}-Md@y)p=0p z4Y`heWzb)q4*NVqGK77>76=~sgZCM6m0L1E<G?Y++>PF#g|fg-{Citv4-Y&ojgME*N<!}aqVXlrTMm&zhsl$y=D7E# z@gB_%?>+DsTgS%v;59Jw>EQv_LAhsSCu{wjIx9_M2Hu^1{2O%>yva6<@fIzG)*nlD z_}p};f>yC;Y^nk6u1lQ01D1H{C)@{bO>KOLX8&0~;sJQ)_8?pIYE1He^qi|n1)8DU z@)sTU&d>NE*dp9%-vYYMz3KcIEN5M8s6Vl<{57nfz+L%doIx9?x@z(!G~nx+H)uP% zVWq~rm(UN`F!joC>{lA(^YzJxx}Z<~Z64SS3j8DA3AFsL9c%r}aW||Z@3Q+8tQ31- zf6Fc!MIGR&`1397)4j<%TjNaopcjhN<)K~dnv885K0~(-wi??H?yux-|IeU7X1zWY$I2+ zld9fUbY1t>p(iNpIFnyw4WJ$MdBa4lU5{s*&|kp0s>FqzaNJcnVi-dbQfxiGVAvIh_*&tz%AN<<&Fmnv&u^zf zcMLo{K@SXRR9}sbY$9{m74a2kaIa)F6R4wE|C7`MzaL$s5ARCKCLKaOl>W^y0P9$( zan$eHlFl2#-fryYG!5KhLOx-ggv8=-zrm^upgzDh52SwjWVECyyz^@#A8oXcz;3Bi zHZ=p6+$FEEeei3Ir^7z{tX_#Z7?(;)tZ(>&?XI_8cP3cPPN_}Gz)oRjFKZrS0o}RY zcGYZ9^1nk9twFsZKSs?3e~XY)TpGUHK##2)`F;U7{NQDcg zbbHW8d-)5r-LbaG0nAuJcE0&*?FjuPM6V1D4kb@L8Mt{dv|t;V;Ah-}{f{+VZ7#hO z+VSRy+i2R3%i7MMfJ9d+8olzyE?2NI_vo@^;QN1G#w$SCy~^;9I42{-G5NqE8F^RfIYMK^#wHK z9obd5`xW-gU8BeOf-|oCU9<_*%?-M_4g7R&cXt4oGka1>5SX6&*KsGPx;`NqjbwdF zHf{)kUgACS&o1znOTy7`&`(*f0sWyu{u*igV?Xo`S+c(4q22*#+l-BV=xf&Y0`+C~ zB|G;b?T5FDX5xEyv-4f(uErGF>5oK_8Qjd>#bt^IZ`J!ZjMF2 z%ou+Z+#B&pBp&RwJi0Lf>{$({k* zhLYoI<^?A~4;?>RCmGzzUM*Ubj;&Zs8qPRmodRusyXH+Qn8vCdUafWxI*L_RPB?|# zU3gFGJSZ_TsT%G5eo-Lv*S@cP= z5L9&_BUxdELkn;XkvDkXy8oXalW;rdgITdkJ#|ysU6rJ zd+&{|0MBI<2GoEe{)_U^jqHEyoK3Xbp1gjx7VaIaO#Z}@JJ9b+&;7m!PVE~0wgIeT zH%)tey9rwVc;SxwV8{vbQ{b(851~iTS|-{IE^Ce5jeZF?l6VB#zuz^u9o)wju|6W7 zl%BzEAWEKM1;wZz_Ws%QAKaaVH%4`W3q;6ezEj`zK+l?XPyH<@s`b#m7xZJBS!stE zGvC4PuJmLlx+iydKYI2uxzljou|DVy)@mAc7CY34+MG>eBLrSI;&&qkkZbC8iGP5u zW7GTJ{=}a6g*?OB-v~GO2z%?WWm2EPXNEO`{ow1DzA<0HBSW8regog#-tp=?XkSCl zTv!;uDBEXqRu-%kxn3*} zPSBl@p#XONEPsJsF+0?@K!_xEG=L19ZeWJ;gTv? z&no!+**_jy-Z;Jjtzkz*`6jDF8`z7qqo>#@-P0X3pfxW)K8zk=PoH?zsRbQVYS*L< z#=X2&IuX3h3J#x;Jqh|@iksSGaBwPFS#w)T2YRCXnGd?)QT99gGwZ>+DX{OJDe@d$ z?6%{Z9(aJg#*SM?d(C*6srvYHCXhe-a(uDfKaj(cmi#q@&eA!!bsG3dIX1}%eBP_w zhOU*4uQdki*(oyAwVOP5n!vu;Y(NpJGx*GB^he{g$)@0nCUVyIR7ErBPIlkK@C7rW zw|_hRbv9UgbJ~0Tnga>jh`9*Br2Wf^Lr>pRywr!WYehU0Wdb z{Cv<&kepGY-GRM6?)K;f;KAjqoY19qo_iL80`dcHqS8~hv@8Nke-D$i2cxSm%ttF& zjoZ{NHDq4QtO&fPCTl=*`v=?5PDS4<=dM|U~jr3 zZGo1puqj3p#6McE2Yp+j!qD+W*~`fN%gJ6=Z^EjTct0fX8MOi2|3c_CI@N7f ztREQp=fk`$;1jdE_5t9~Mxi=%pUUI3KyX0M=1x@Qg0yuIcqwFjbqJ^&N{%}hlOGBl z&MrPr{ejg>r`r3IfqK!?Uj&)WyetjGyRMX!e%g@YSesTIOiblzKt&joCF6qkw@5J@u4$t?QI^w8WM zo%7)J8rQk$pmHr4!S=C^b+lh&-z^XKL>n)oTn}yAKZV8>84IMpQVK*9BwOBb9yd3>u8G79% zDgnLZO0G~I-;AB1N>;xw8*v%>N|CEAYPiDFFD92rULKl+4ro&JlaRt zk`dC{|L~oo3@JI194z`K z5$c(Z^=oiXWBr?`b?=k2JcQcuevuu%mRd*Wv}``?BXr4$-whqG)oglVh0YReLee|4H!=QnMWnP z_?_irGLQX}yjZ;w_PArN_Elipim!)Iv+LF7)u71@(!lQbRqUsWNEf*ipRvnWTY2iH z7rK*g!+tGbT^bq`NM^Iz=0csgSF)35QU}fmT~H6ZggLqA_n7><(B^;0os}hh*ojxm zcoFr$aitJ*WRpto7=r_^H4$!qMiG|OCk_aJ`mlV&jV zoBW{`a94SL4LYWRv}bz{E*#hj`$fl|8ECuGz97`7pyU&3veDJ)F}Qu&*Q4mJdM&Xh zpvuJGH_$t!y83OPQB=JjdVTS_Ow>nFs2jCAZx-h2=hi37aj8KY_Bw&-&3|wv*jqLc4+~8OlZs4Al7y@B7%z z_oRHV?>3Nm6JILzLz_$@(^>J!)TeLBAIG~~1^I9B!l7UA=PesAN>gZeOycWJ2-t+^+I(1YEn&eWfXQK zo2^ZqS$16L2kese^?_)z;<^G8_hscu=N06kD)Zr>=-i(Na4x`i#t z4Ou%H?qz4gq7}ixf{QJcK$+UU5cF#u>2`n>DR&_~Ph4%=yk9BmV{jZwY8N9Ct2XS$Y(CfIxOS2MaPkxV#6I<7q~p#}TdrKe1^!68oMZbQe}Og>ym8S5ZFhzpN9{t$0(OnnnESZDX7eRVhE9RDktF+`IL^hkYA0>d z`@*mx=(mhi&U`9v3B8|PJ|w#o z`-ceG+*>R)2Rg2g6xr1miT!>LxnVCk(I&DQ_b3@PAuF)=f=eKJZ{4qF)?n&Soh5U@ zvR|axtvfN;!j)uUsLwYW=+V2#-E0>tC7t3s5AJ7KiA|fv*+Ne<9=Z(G_>pyMKIq2Y zVlRcfS-lYUQ4^y-F9HkL#@9N|4$wDutZhU;vT8xpJ@uwpi}C$ka!OolH+DSxhh2S~ z_F8uG32M3Jn^c#;d$$$jEmmGpDsn08q3qMwSykAUUE~G!*kx-$C)gckg=|L$wdVDq z<7*7UmxHBjk@Fj`)zC^VWEkr-`B&Fk*sm^G+p-Q+TuSa?Wu2&ZvXyTW=X=6Cqh4|Y zd!MzxY7l{U?cGh4=m={c0WWYHo0(ynhaDMj@pL`7B!P4|NtUn!Ry~#ThWkFYhmBlK zyRr6mN4(ojBvmGnG6$`NePG|VxMz*k59 z1;YNEb<5N=*#WI+?tTR=WZ$qee+$U%gguRY%ufG9`#DzRFZF4*v?kF3znc?na0I>2 zE{mZKct6-881|=ZMj!S052WZv(vKZmbT$~@7nP8ndrXV5Cx?;8*hbsde%$rvlYR@x zF|wO%6eu1wQ#59EQ&LL$9`>A>OVnQI_LG{^!$6JGcE;H`Myh!kJckq5x_6?cSLwX12{lz_HW3l={(Abas%-XFgwLb)V0h_Juau{26 zA{oI7_xIQ0euj;R(42V~`nhA(PIT5{(rdJP5w@NpX|_Yh`v|n=`9$Yv@D@A6$KV+D zWdR@Y81N+v;Xa9S*7dZoA6yBTT@D%b09qn_puRV zIJ;ofQ`MueUt`3#K)3!QC)^eocM|$#bfOz-6GQHv(DVR%*L&~biQp@C;r)Qs zr=gdfl1xG!)@D6HpY2xqoCI#$L$@RkyuuB~7H(2E%)Mg^&Io9#uG5u6{SImYTqOP24ka!OE4U$bQXy-F;$@8Gh zb25w7OdGracTeF~fizGvUVJ;coK;VtKEz&Jot}sHEDuss+oBKq2>XR?EeMXzfZZWj zt{xp5LJqXf6TSdlDz(586@Ahjg0_|R-@gQIDI?q1q&F+dGhu(8`|~%dokzy9BX%5{ zmIeD(wv9~-qFsC^SeL_xcBk!;p(+tjJ!+qop{~5X9yaVDv z=zTUOIr!)m=p%v)=H!9mHQl>Wg*x(>MzLN#wCO@sl>%`0sM6(VQS*w*La_Q@-Ic50 zt{RW`XpXAE*&@*WePcVCzIU)=F(@8J-kyK<2==T6q|`{$JJ_o;{VhtsUu;kowdNM_ z5Zo_qB~t^)2h-DwahDLa_=47pk-iVxb*@3%H2Q`#~O3q~0+qwem%tDWk=!w}eSsa`LtV2f;$02A`^7$r z=x?iq7KGt?2dt9)5!pI;*TX70Q14+6<*um1`}oUb6#J1~c7^u0JAMwj1Ml7j zk&AYcSJ{GK>H@1{Gx43?Fr8rZBr7nSI-a!{L2aMv(U0%;u|2HaIob=^(dVi6uw87e zkAO}+eE;7D(#n@iG)VNu-A>3L9W7u-4WM4Y=CKFvHg@7W;W%%lyPyx7usvW?1GGRO zIhBoPms&_>{Cr_vtAX8gM% z)dcT{3grFIME0~GwL;DOg?RtCd~Y?{rmiG(ADpQ{T9h~hV&A+*S}uzCfGsVjs{H`p zE0ATQ$e_-f>u~>%o%4eFB^&jMJIgs0-`QuA2Lk$^Vc*zJssxgWtgHDEg@QAiGU+Sg*$j<7z zYxsWeZL*tPP(!_&?P6_fX}|Mc|6&V#_m^GMNBx^!`GNX2tNoEWmK|Qy_zJ(@!ltuN z*y$y77r93IvS(SPJ>KJ5;rlRFdM~vVD-lNRypP;xJ9rtsU%G%4T1d{9gMW+~?2G<0 zd5B(RD=)PSe+2E8NtUzYv#6z}i|@z#cJ>)-IfM2Lwr(bM(2(?7`2Ih3wg~klHcym# z$Niaq@!fOw^aE<;W^z9}@Kn3eV|b_Q8L$;S<3%>H3w0zf<6gij=u(HWCY4s|PvD-+ zzHx%TJr8=7E2-FbWn>%l9(G z?_@hzt8&`KZjpm3$Y3SOe0=|SEcv9sO6w(b#LmvOsG@}2GqiwJkfh$lzG9Od`(Jj! zJMYD06Pw?y;nofNo;RdOZsiH=mYpjepdV)a9QFo`m`%QCJFTc!3_E6n_uK#PaO$KH z}7b%1{GdAw^GkY`v6L+a#Z-ADW2 z-n*RqG=6Ubc8NM!^ifgl19Z?Qa#Kms9PC+P4tvlqtoefXH?Z?rg@x2Z6(WA%p2Dhj zs_1{j@5PU(d;*^gCF9Okp2QCDT+xEM>i?AZ43@FGV(TigmmMWsKkRvgRUc`##pqU%zxTbU8bI6ZK}3#-F%9VyBx@{~F|N zpa^@cFgf$ypiS6w8^|0sypejAhshhfdrWLmRRXmpk>|hqxnocHMz*lN->Iw1#7^N| zyPS++zp-w&_?|COJqF$d_+QZ)2fp1fIbIE1}Nu%Gn&!3u8We3(Fd%NJ#{i`xKH&6#Trn%8uMq32l} z(VJ28@SWG;>9(Nezls9XOgVFeJvgVRV?R3fne8?QaO!h%+?GA>ux$nxt#JhHo9vU( zVpjh?btWtMfSYYheAkBWFP*@N8Q5q>!>*3I~QHj^!ts&*nYR1 z>d$-|=w%hX=eawn4qV{LU$th0ugnNC!yAE`0AQ{dMG(Vu|1-tuD6=!sL>y0?H*6Xv_ zdhnz-sWauU6}G{LNm<_DUv_6vZ8vs5E3|iwst@$n>4PFSfH!8460X})HbM_qk$8sw zxjJXDA9$#UblcMrja|-OyJQ>c553!L&sQ{Zu;P?W;M@mSH=tE(-n~Ruc#xIsowd|S zItRvXhWj90(#!hCw5`yimih&42Y0b|l*F!L`&w-~9|*qi>o~dtwDu>nS?y^%8*n!@ zCU@VxJSPZx!9DUaJF zP0B;Reoi>M3v}xz1H&8Sc0=#nPv)@s*~Y?qV4t5uuG`UUfqf>3tlMUv6AoQ({;mi8 zDtci2e(>!>y==k^ej+K?|?u*$2VQ!b{4B!3`&`Zi@zA zAGwhn0}6&#)Ww3Ps~VJ!fu2#uLyv=B9hXW<^l zF45>nN`XH5Ij9Xyxjs@h6)fC$*&fvkCwth(`>7`^vOSFVp>kcdXkgapndiWUnnTWM z;Q46vW9SjribgawDGh$? z3og5sgI`&bMbwi5M%&ziJ&yg!=9>Q>O?MjB1OD}KytGI}X+^ZEP)b=MC0c}#rG%17 zN_!$w$&wV65n6;on+O#tp=1e#hze;@*^)@8Z1*|;bM6Ooy{`A?e1FY6nz^#gl|8u2 z%_jXfsBXFiUCSDIQj1NwegXGQZ(L{H1%+1(4u){K>?{2veyLnH5RJdQ2V*$b=G(2^~<=Q zWNX;z!)Q-sr%O>kWp}?=@fAP!ja~VY`X#&R6?O6HZtZ$_S8u45jv7xVPqX_4Z#Cim zm319Jy}bUJV*~7^X@1G*Mo;nQsGrB)*)3qY^`RrJp!h=4j}?_YYy2K|{fUZpA3@39 z!h`>FXSe<*=*?_@mZM51^r39Bm%VQ&Dbfx5`?Vq8&>hZXJ3HTnT2@C+_Z!?p*cR5s zeDB=vuvf6YLsfTUiw+~b*(dCf(<}P%E-^he;0L&otz#Xl%HQLj`jFh^-0SocT1o3r z3L3$FWZ#XWU1wDConE;AyzppdA2>XC!&Wqnt(Yp_*bl8UjZ_VO+x7?AjxAy5Zum6x zAMD1S;#uz1ie%47zp} zd6%7F$~`#w9^TEL8VC!4Cu+!N#~#hXesqGYOeLMxZwSHtH#=Kaaecp2ZJA2{j!UJ zQqYO4X!^AZY3Lo5nuRjpT_;B!S@4cCIY+D41AFMV_;j>15~<} zP3-!~erK_h*(!F@6x!FZiR^C{{@A|%ea__Hpm+HBPR-5FM}Xf;a;!&!g4aoRcIl9v z;}l_+F!&@t8k`t^?E$*bHk_4&<4j_KHH4O z%_HrFHoww=K9H2NbRsD8B68&BBJ`EIdB&GM{*cw9n%vn$}9Ub!a2Rd+%X8BA|X0y&GV^Fr{ z&j}My^S03aS-5xlUNHr2H|5yR!FId2%M2`GZ%$lr1G`<9oZZ*nhn>aF>Zg{E85Lj- z``%9-Y8K#>1Ol6+RQ;eQ1geI+7^HZZ)_X75FB4h%Dij;jqMwf)Vvg|VV7vk z^0$R9WEC~3cd}zlFGj6^dj$KDwV6%(s5#_L_Endi!YX*5^Oe*p`nn7|j+JO}n6n!C z5UcQp`Xc*ZE469P&oF$KZld!Y6`w`=vCr5irnINdCi`k!ydB_utiFMgBk1|-;VLw` z*tcvA_@U{=c_+}Yx~YCGxacXl^yoGjXXtUq$pfs!I$0as$GDNXz4I%urTfSax7r7| zK)<_9=HDS*FL!9W!d}v7H)@i;zqt^V|8?TaW}c?;keA1wROk&4`?wF15cC*(d3yZMTq)3r^n;vY7QyscKU>oat z`0Gkv=wIyOkUzQp(Ajg6KA<-(NX?TT#{!^FoFXrK3DskJe>DjX1fR0=zfrqhXlmR9 z`vcZ0Xxqrm(7EisE!3)8$td`&Gq zmG+ygW*T)jJL6!7{ucP0xd>FC2kuh&57(o2FOywi z9;dKRXVm-`3D&UzncS@Dj6q_1;hxD3F{18$WD<^hLh_5N=!jDDGg080GV&H%t|aRa z4SV3*3yEkw`}{ri%n#%lR`cTg8hm#mkMtZmDsmrmH9K_}^>KE9B=xHL%Qx{|8LRPv z+Hq>+rv0$rVr7rmX~sZbZPyl#1C`#A?iPOvu^+Ned^|D^Kr2obYC$az)g1Z{eCg!- z7_HM7H25HBtV#N_wd_nS+E24(B__M@z2bH99qXzvY)U-rKSq$U;Wk34(9(f+I%%lU zR}b{UBaLR%rkd1zLKc^6i=V=G%UyP&i+pR6(?Kai-{)u?`>^V?bq4ghhve5JlPK&1 zKZY7*g85PA`Do;@9m}%8PwZ$Z>e;VG9>6_|9ee8X1MGe57uNPP?SeiwqG#~y2}XvY z9qi^x@&?`kQe!!fd)o#bv_g!c(|WV}ki%?B=IqOzAq z9=Qg-XBQSyFWGUq8h6Es4r@!nvzHPDZ-P>n$rbc@pXgjzZodRBp|S~VG{EqiOR$>E34S~lcIg%^*pFOMJ>c70s< z1bPSC&hC8kWy@38m*(s*K=rn0bfGS@Z;r3QK6damn!rkSxnF$_9Z)>r2RbQ7Ot}tJ zstz1l4^F=wZ1@6fyF(_fxNre`l=A!zw6?QN<0Y7TIot(3dWBrQW8?|!IJSpfDq|!2 z3ids0F{>oYJ3FA^qYb`W*hChvu9G5d*KGL!C- z!gjOpUBcrp+tA;vb2atwr2U1sZ(*BLsAE@XD>lL|KBi&?>d%TPQ44)^K7@PmYxnC- zpm6$tKGc(a%zpPfKDin8RsQ6_>4yH;-fYA}pLf`8uBX?ufG*=rj-q=N&2PT}HAa)t zAu?N9p%sSC|BObyY#Y}G8lDPwLuHQaInWLsb5gEE+k0&1yahX!YJ5i{mXU%ZZ|c2+ z-gEv(7P?~V!B*5hguKBT&CynR4|@%pKcr$6wt@s1#GH8$aMTnstbrc9`^JtJ$eXXn({ma5z5gBYdvQLuOki z*f92T(`WF5e953MpuGZlomCw{9mN_p+gjke6Rc1R^)Yt98*1xgKXSgpyZjU6=nV(o zVyE44PVNTxtLj^S1HZBMYSbO-q;_Z3UcBGB;(iMqS48GpAD__!J$4}}?lyGU59k0^ zYCW|DyOq83%j^NZn_J!}@)Nvuo7B2P#<7EAf@kAhQu#s=dXa5q!&GSBrb;%m7HZTv z?COv6dhqirFSY6Rf@y`M$Q9C)wb>Ewh4+K=M`ocZ3&MzDUM2c)-17B6`!@Zt8)j%!w zn)G37*w^Xqck%s%Oj6PCxba`;b|J%H^k<^a7gTQanS%mN@b_cW^BTnjp^fs%2L)O~fBFj#fNb^)qkv%egDy@Xt< zsPPy33aj2$HeCcdnssZZ?%(?3BJNJXWH0-$_O7ca?4#~g#SR1&G>)5!f!d43bO(X) ztoVr2p4fiub5^+4tXdrQu%gB45};f$c_HGX6SmAA@}Tve6l{ToN-e(7``u!Sr8MVX_QsCIas{hda?Aiqb#D+spuqJ>0zfIG^aaVq7d`24F)tj9t z11{_%!}`g@TV^%5|6yHkQ{Q7J-l49v51tRdIa9V`CHY%LCK9`5LHH&)@VoTLi|DDq zk1q1yb5?1_o)g%6*mp+M)-%Zh5#^V7U-;yztO8iTO1gZB!46_yx>6_gjTIgN`;4-( zS?Jqxa@j4iA!c<5?j9WzCXNIZ^6zdyx3hWd=mOf~*dF#pm~#fc*RlNFj2>b)Sy7Li zM`}wZDvpBtQz_E&)g*iDX$|DR^r}PH>oUlVNl&jULeF#Y=|gQNh)o#{KF}u3ErJ&+ zK`Z;T87YHX1VmIom^EQ1vVYiFVYFwk>gJ6jjp1Fysq+ufq@IYJS)lPXrMKw%v&fgT~Qw!R=GXR(9g=tt)Xq%CGWCYo3E}}!-e(Vs(cZ`Itnrref%j5J2QEZ|*sX3n=koRdN_; zfAae?beYe8lH0+(tmxzk*4WjjY&bM z=L_V3vb zyYYVWcvo&Dxan8v+P&aQ_VRD)QGduCYyqo(d(|;~-^;q+rMCKXXI~WTO}l;xMuSz> z3C8FR*-63ZcR5n9x$+WrehVp^v;GUV>&#>B`#|AA(@vus*hlR4>L-o3PtiMda6c$M zi8N-H_0D{V`vA4JSHe^cixL|Mn#87^4x-(C_Oa z$`636-N@~KFjnt(3ne|F{otJ1OBoMsFY+^!9b*UFN{5 zj0{kD$J)o4;K2pI#IwL&*3p{!78_PRv-S+!k63K9xdh4xN*7)RWu00*3b98;Jh}o# z4BOXR1Pa!wPc8=Y(@Oo&^^?E9MFppjnST$cUWM*DbSD`VIYL&m!47Mmsga_>eFoUxvBa1`ANBC z68o2RJ5T%dIo{*0!#hgN@6uOIiEL)YnEXwUcEv}N~^4qh@pk@1`f0cuG>{p$?1x{E=PP;PR`8M>fBJv&ER!r@( zSFn!<37Xu6ma9n#Mnl*Z*6HZf%ecq0KUw*8Prl%;A2YM50u+xWl|K!MzXxsU zZ)NZRJjV_Xpx(;9X3aLz-Y{@`4!-YBDp08eqgE{6TLsptbd{sa-$(yNKe3G+)K2;8 zGakZzhg}_3x*5Bi{m!o1PJ1c)VeYED|Gj&4K7Eu`~Q=Z)K|js5=eU zzQXqwGsy8qoaFa4fMps+gKebg?TA+WLPk0wv+lF3DJhHkIJnpKOh&o55 z?D-5T3VVW)+IA`v|K!zd>Qs0=+-rivDE@f5GFw$VEB*V+EVx*EzEvj|$iffZlqHY+{qvrR>N3 zvhLIh)ct_yHX-ou{H!KnaP`LFk3_(mtXl6vzk$$h`*y!Yt5~=F)M*#JW=p_+Qfg)o zdcJMpMk!FXo!rg7XSL72&&B&s*5LxR#@5{*aF1cTS^HqxZ?HqXqot+cox8&UV;OYO z5qDWIC)aJH960PeX?lUoV3UIc?C|a@KJ_8`jP)K&Ej)y@eO@gl4|kgrUgqd!c0wxk zLH6}Y>eU{iJMi7g4dnX&0(=#q1NFyfDT2~}id@kdE2HH`gB_o5#G*2VEAOLicA~pg zz!8nJ)z!f5Y%5z=zHsYU*z0267oZlgDKBmY_mG6!w=BUH)+&+u=J@^@b77b6IUIyaekWT?b@Q<=mXV$Bj;2{bD-}#> zKr6OY%g+NX)--r60I#*nODqJ(yd#bB@~yD7Ll#D$6D;1BqJxL+{)PUmA3bdm7+R_3 zycqn}9kbxlQE&*ddofGNlF7oake-j}19yKbbe z1S58ndd+c5S3#d+hqq9tvr*aO;_&{NRSLX)A3Ktj-9){Q{lXf$J@~d7-d$sRC%Wl6 zKp*<`&lB}7Kbnb-ik24eY8%JHq`xdvd9Y*Gg>Z*Mm#ffQuT*0=8}7 zmRu*;10P9!Kn;3B>(+t=eWX{pytFfP$}O_+<1RrL=nw4b?L}L$Z;x@)Uyl|XJ%dj2 zF&gFpCb5<5BwyNpvr0FlK5c+^d)OlOY$@#yk>@l$;l3e?9HRK<1olSOE>B+03;G&6 zaBKb&Y@H$R@1cj-qM_7dhLIy`cL{sLy@Y-7ud^H5>rJ1fA1KgDj`o`J-XGeAEo3db z{G&I*{&r8MKp?noeg5*zpmhJcO4M3?+0`KM)swz?!JzH&!+X$h0yjX4URGm<7-vi*->@AM!11eFOO&#_V) zsV6^vwL1mw$u3gA&`;~gwQi)wt(M$luur#>AA1}OTR}>M?~*)765pvvkItP6H?Q+-gJ*vlTz6wSSVsZmb!367EgoGlyk>YrdH-KnGuc z6^ZUQm)FVyw+_j7MbEMu>#b9<>sj#^)S5oKkm`c9wCz* zqD=8_aLxW3s%#VInFHqCeGGr#4SauCK^C!_Yb>{3ggvA`Z+#xv!p{9gE%loWVpH!} zpTc({cgf?drL0pQ3yODRQ( zK4(3@s_v}YL%dw?BEpYmB+{%?51_Me&9Rt{$8K2 zU|4qQpKoBS$1Fx{P(|RbMqk3OwaO=ICzHL5GQ9j7&`Qm ztD7Wvfqlcy?W8@IZDt)W{Y}I7v6so^Wt&^2p-1P3NXUYhEGB*(0b2MZH;n{M4JVHp z1)8i$9i#}Rv*J$Fe(W>0b1m(*r$Z!_;Cirs3z}*s*nvv(=!*PxOYOe(cJ>_jJ{v|FJ2p&vt7-uh}I23zZ2X7l@l~)P%ms zemb%F19n5d#W5|=;j*jmMDRcM2kTf!`z=;gX0nPdyc^i`$N_cB+>nIc3KV{Z&YqDv zOb^UrGmNMQ&m=7$J&VM96`N8`ZIkR*j=P|n_+NBATg5&pe|d2d?9*?Nscf&dYUUK! z^?RoW^nW<%PU#wMCVzneoYG9wGvlG^g2v*G^YpUxk2+JCN_=73LF(=G!| zGw2Bs8&06RHv8Q(2gPTJ3tNExtjwT{S=a~NH+Q45cPuh2L77z{igUphcJ6BGtLk$0 zxOcKq#(VweL3_+1*AG%Xhh6&Q+BPS?c*{~p_H^LBaehS+StPG_fkj54m5v7jxhXt8T+R|@>kSHkla>f zptAzHi48jZ$OAik&4zST#e8$`N^o{vj^8R!@t^FP)!z}SPh@BS*u`!?r88s`bjxY7t1_t{JE41r?KbeJzN14JSRn5A zatEj|n5;XVzGNr#$=w$-c7tQ)FK9u(Z!CNq0h&LJ+_eXM<$kRXl?>Mz9t8%muhC@IJjB)tNE(y{770JvfsPR&ce9SkLcO@(Vs(#F zzbo^7n+>~MIq5WJR`MC>{T(l!p<|p!rJVz>xsv}T6u!bv)Fy*^Y~*vHmwhLTSjV!C zrMUmQ=24mlUW^p_g=RgoGcN)YYsm`+nm@5ECzI*FZ|WCAYsUXPgC-s#4L?^nT!r4( z`Y^Ht9GK%#j*7`#yiyAKutnMJ6U(4|k9OGK1ie$pr)=(RySe4CKUdT2M>XchzrO{l zWxAx?2JP6-r8dfy&@!hTHa!Hz5?oF^!gtpn#ykca&({=IgZgzQ8Bf5`_2e+mO^Q#U zhkB8l*gb#G9KyYWoiC8{zYeW5e~f!oe3N($IOz~MSW9*ncI0^*wdY{_5S3cgX>!c% zTJY^bhb?vB?szigjsEf%(1NYx=A4HIuwSu(XQ{={kry|4RN~!P{KTA>VA!wI-mkz- zs>4<{fFIb!YSd%Y$pOt5%3j00db`867Vva9X|#hJI`8LY+_$oJGyXKafff}>8r2HQ z^c}Zo1Gllw>;>%|LGNL|YW_9uBPf6R=Ijn|J}a9}E$`|# z+{IpI$Ni-J0Nb6eF>DaL3o&$vL|X-a-b8z9#Y`o@TP?po%Yb3e2aJ#d->?}cjxWa^ zoJ#t$&)Fq+#LVR3p2JGsr4C{n)?NNR67H*%?OYVWGPZrVL(FLCHfi!=fcC60&|3z& z6r!sh{r-yPJSHWp$<1s|uY0o++{YN1zf%PxSib>Hs%p?8!sMCvAA`n1KOI*QrUkyR z(f1w)`Yt6;vZBkVz1it)?ydN4!-WA#<3R}v!vu6AYn3K8Zvu1+d+sE4#Wa&L+|B>i z|3W{p9+iR9w4v7?9vX;#ycX=N1GZi#n<8Y6W6z2tGub|y3-!1=Eg^5SvlZscOoTo5 zT=;%;>(-GK=xg?axQ&S}wB_@U!Ds<{QNKi64|<*YO}j~;#jb;c^uZAkWH{?IqGAW` zx7j((&eyPg)*pAA3_fN59uTvh0`2-Ad7qtlkb2lylUsOCXO%X}q)mfv>03N|I;b4C zrwCnPr7^|`d~nPCgE45eZ@^d+@H{KCpV};jEQ=+*?T)X-ckkGRE2wo;43FVH=l#<< zv}^9^eX~H}*Y$#?peHM2c;*uJ-l*_{bHGk^X*9KEsdKp{>={E0Q?0;%hXYOLgCPz> zL(wze%)X%-R~siT0F@WXWTL_6+w84D>Dt9}7lJc3?74xyoUGiBj{bLb$|6wq;Foh~ zI6F*3LwzysU1d(F|5s9}Xmtv<^sXPZ=qSCBHFjWjz>gOz!F!=TijJU87`fLk&~goQ zQ)1&}C(t5^tYb5_eT;I3eQ*dFz|IV%UhDlO-v#bkKID2o@*%rt>i*Ao&zMFIF(mEU zCvA6wy@XA^XZ+M1`Y)SspL*Z}GL=oQq+T9hFW~|2M;#^=zh;+V7qI8An*GL}TSDft z($}b)So7=DwGoZeHo$wMJ>;JeG8eE_-<)}w@g^!3oX@3?#R6xkNuWS+2s5P z+if%16-3%@Axqued;Q>EsvDlR2^@c>%xeqyA6w3v`mfHy-7)#@k*#3aQPQ|C!73Qq zyKGVfs=lwP6rCSSzO!}z^}l`0fN9%c-^bc2Q|E*}{eXK+mT`RuDC1Wz9SS}%3|x%f zYfo6P8`OJCy0Z7#N(=YDc%S}7A}$iVka}r!G$@ls2D6SQsk1#6uf%)Q26A+bbjd;J z-Ry#+=YL>dWDQcN?;j%zb=!R6;a>MCqUI17Xk{CD7<@FJv~S$^2fL1)q3!%K0XmHx zs6%~xA}ORx9{Bl7HWA+0HVpJk2CHsL-$()HN1g9OFR-%F)FEs$dtgkP|1o&?<=ysk zsOSfBasG(+*wzK)h8GdF$DuP`k`1p&&r?dnPr&|?Rjt}5kP02eHmxb!f<55d_s{6C z9x{wgiJGuJ4R#;zX;)8y9rp(MoCf7J>y^^MIaehT(Z1HLdosZ1ZKO*(c|7?1Z`>6< zE@@hC=TppEw3tV`f~wtphEZtvPw+z(k!D=P%8tjOc(0|T!>2fJj~7lDmzc+cy_ z#n5eOg4Si=?~~;7Q{;W8Q+YRG_th}&L}y1zq?Ln*;v?SN0RzSE=H3Gb40C>+uCq7Cd)7`vn$?;}XX z=F%AKU99}sRrjz%*_;z=yWc{0=p}4;2dee!WuOLj+i!mY-PwaHsC(IU_S7<$7H#Q- zciUL69Ut4ujCrJi&i7$M zp?mhZAB)k*$e&6VrwKrQ9T)tgICs6e|Hrevstvz`vQp#iGPe7HRh+{b=ll|{QgkB2?+arF2J z;HB3BJ`=&;=_%Q$UBJ{f^covs_(Vw;`U7iaM4ihz4)9)$_Xk3xt}xlp#*0wfSBWO# zJA(;z^YlPdZ8C!$H2QVmB-qE~4evmoTUfd1gKE=S_x71-;9NVBTlLX)9` z*jMbJHO1R-xBBX}W;%GD?dYbCUOZE32JBtzB856@?8~gDzLncd=s$PE8qfz7WY~WS z3dYc8s|uE(+3e8O)Pd}4N9tATiw@wsZg$03>LW$FMNMGOEhe{LCEM6}CDa$#Npj1J z@qPK5&poJSD;dlB=S1txg1wd%$fa)IqVA1* z#N0rO$KH;j-VjY5$?H*H4)?L<~t{r{;#? zKJzsBT|hxE7P`DD-wV}zNS;2jFbjK3BDtFtSo8i3?h))AXX?nF(W~NM-+Qg-2)g7t zx#$LYnH^P1oj*F->Hxg+e5)3LR%4r)k%Ipj&?s-W_CrvIi<@ zcXe`G91r(S4T1e=R7AD$A#ih0t@~kcE> zdkkC38W-jJ;^z&D$x3$8Rq6!xH|tzNdj*@bYhez4UUD}X!nUxM5wthAj&@9fcaAwl zN$6?u=mp7O^syV|XcudHoH~lV+#k33DBMT>B6qOyx5wq-9%t{Ql>**ox2g8KVq1?T zBMWt3VSi%Hv!{q0hYk#^Hbq~svo=xJv&NgLPqE4~y+ZN*9=3z6H=%vBm}n8+GiuVl zp@-aSJx_q@lL9i)7*^q<)Q~jj1#BKWvV-9| zS!6S7kxi{RaJTv?xW}@2F3ak$-IWgd&UKoQ0ls~G_!OG$`(Q*S zc;SagNfxN{lZtM$iyrFg(Ow3Lmi9sC|!??k3r0hqx4VpTqe3S5TWyF`8_nkDvG;RtJ^**%e1-sx%zO zeXuI&&l;&wFS;Zpdjsx8f%)4?L5~>=3(*;u;&zsUw|sTq-2%%eR9oKxwY13>J)Tk6 zCf~_)cF+&%y>I>V@4~(EJ$c7+wp#_X_FU45H5=NHhWn7JP|^F~tMgH-D#3Z(>zp5f zYwP?kSA!Wvp@V9`h0X7NqJwXLTTlzuu`};bm$O=Tsbg7@3hFHf_(5-ApF?9>8zvFNo-V<5foz$P%<-4ehS*6|7 zY3%t0x}ErWX=~Dw4VQhORS!FSXYoH5$dP%hoIJH)6gX1|1Y$$Dg4@AFXX z;C`}^Rk3y8p27=DaevHC5utVyC5JwK*N^uq)--w7)JEtGcJNW^0Jg$q^hUhL zx{}M?$da;7^(NRGm2T9b=E`JuSlqs5=SQj@5`@~64AS+zlXklu~YK{=(;t^6}7WaOGQhE-gt@b8%F-Cx0m|} z-R>P1i!SgXTiK=e*O+#|euceSNgd#D_zLbuYe-Qo-EY{{?5gYQJU>B~u_h7!GO*JY z9c@8H7n8;#ri|`{R(tc<9(~YC9&RK1S?65O!+2LePwu=xIs}PS<8EV`Huy7WIGfZQ zY%~{phsWT4^esEqliJRU{ArLmr3>!kCzFnBIXm*NX#n0st>qVe1>dj*gNh2ep)a^c zt^WpEdytFu)J|c)iuJ$Q3l^^!{0A+UJ?GL7o;uU=0zDejsq+UE@3`KKew`b4=r7pq z-?#H0xZ?5s$pUTg^9IT5{89VyN8h0dwj#BH-~z=osR3XfD>s@tlFQwYz3riCw}9FWogq6k4tAN-?_4BFcLp zSX6tx6}|s;;_pG=x^7bC+Wl$b(0kb>*Qtd@9{u>goxRFVZkwzz7{5+CIrrRSXY6O} zsV$zzu@wiW$qWH6vzc9IJ%&OL`9dBlvP{Q*wm5XuFmS1y{0j75YhFD1Aa!Z4Bv^Lm z`dcYb<1TqaEiQRDwA5HKh&{td@8fCV{wA4e01Y zx8yXzQ%lx`YJn0X|6M`foSUpW4z$W8bJ^kNsV!LJIi8vLZqg8uH)sMoUV?h#v((Y! zVP7)YzZ$*5?wUd^z53OS39!o+pAFCkYvn@Kb-=muWViy^nv<7;yM+5vL0z!x*WRtD zpW3(edf*IoGNUW@6t-HSRwEk4Dqo>KzvI@3Nw5c0C;!j~YuU&e>Kks4eGFi4w11vB z88lx>o?$hW{cCWKVaKXaH?o?>Ege(gzKShl1B630r@>y!PI@BeitXiU{SxgjQ;anP z58WjDSnYD^c(!0n=d9`Q&Pa)D{kS&-`^#MWi8DaybgdS&A%mQgNqQQtu{VM}S};h! z6zm+=@)=z=p1d)EwCoNUKO6S5tob+U99FW2x@PN@$~o{ZHJH37(K*KqTA}37Qw#9t zx#ZuL;DKDShh24^dZy{)z`1ZAcQRGO3Y6b4!v$5nCoVe=eDrm*(0p)>T+3I~L7psU z_ld2GvVlFP`tL2&HQ`YGN_?M0&fS+hU^TS*e)8oDza|H0)0boh``RbN&Jp&%Q%&Ph zk?Ew1(5r{oN7#F8@`KHT*1#@)MA8CXFy8VSsum^Z=LDLyzg1ZaX0sA+sqN}MEpUdt z#9Q?injRmU=K>lZB2Tk}4paNHU99;V*SK}?KH}Wp`{=oY;$z&w!>ck@qR$=3SWVL- z*c#2v{T|?ccGtO(sT-h6Cta!Y1d9*u-RA}7*{j|~4{kiv=mV~sIdP;f=q-BR7TqUC z3JfCM*u{3K`u=dg#LDduR|$YtX?$6Oj?dgYY$LdQ=GjPeFWbp3Gp2pda>dk5a3A@8 ziQH!J{QF0{feilM9w8 z9Rl^|?M*WJ-jHn;5dxW%pJBnfqLiCxF@PhtbJ0iO`G2kOk}rCFsy0ku>WLJ>k8ju$4=Rsd>mZ%PvtpU#GX04!ukZXkY?;Hw0==cbqUk2kqUM?wbp~WIs*sj?IT&I)l8z9!)4W zEr4BiscYsXFqCa!6_(R}d&vC!etkyr12`y-rYk>J{*5X--NJXcK8shhAo- z;a_RR(7|s>pR~fRtI*Ro+^QU_a&z48YtXNW?t14yAGYd#4#MzQ|P^lCbAFM z&*FdEZoqzYF!_)*7($)Qu6mxNT#8@s?uq$j;LZy2EgO7~TKYbD^}p$n_)g^@dH2hp z={KP#d?hdJnspI-cLdpX?Bcy!&_$_ag~tNn+t7RC3cJxxcIg4?VEZK#@4(*3ny;kZ z!oFtBSJ5uHnhaw1iS}NvfX_D#A|0#a`>_A8PEV<)9@m+25B5AZAN~j4_n|MXd~_7m zSKd&ICb1Sfr$;}44v_H^s00seoK=9TJ{q>Z3haMOuB|3jV=h)c#QXal+aG~@S&gv5 z@7VKSMP@$+-59aiIShac|q{*f2hRSzQ1;=cN@$~*KMd;8nh%D(Uyx@aXSuexMfEA&=1GC`f(HI~%+)UgrovFtbYY+>Yi+>dV5 zlxYWd&MIGw3RVBSi%vWmKj1BRm$h=!F~P3CEHvspc;gCrZN~{a>^D}^<58pRK^7mt z8g^q~`VQ<|qib59!BqoRtV1^mk)PRR!qi3VtmK$i_%5BTV^!B`%6Gwj#hJY9LXL7J z|7w>n#k)a|LmYZ6G)ea>C}?5eg|4wADCz;<>_UHc+z)ss8+p=qZ{ zgUXJrKcVH~BQK$58rLTDf@j#Fn$(-v{aVy&Q@9tjIvnf+ z$KCa4{{{N7%PXi=BH`4 z_kSyyEC+3L)y^LcUKH~Vm0v=Ju`(ANj>^LxWEL-_0ICepS%@x3bGeP?vF+@FleFiv zZ&^2wKmYK3C9AiAI)R<&Nqv*e)lV`S0q>;^NOkK$%SS<v7;sHp}^I-gsyU z7xFHv=Sn?(pF`RNxc|p~XW!;m#A)N#IrXqe2aG*Uj-M)|HxWA9kd&=5%)+)^>pMml ztX{IoN)Mc)I4lBH^K4(M4@!HH;*K5r450s8Ll$2vF`f(^`dr&?D%iq~t)t%0ik+x9 zi1%dnTPk(a2A7ApuV3x)a~jz5>`eI#(Ce7_Uv!54w#`PM?do>dnP3Uqyvt^(F|@yI zWuEIHfG zr5d|rC7IfhICnO5(DsKn(BPvcb!Ol>)*^-atInoH=CFS+J97tJeUmI>gUhKuCY6|3 z!QCdA>?+mJp9d{J=4Tr!@a~}Ue9+m_r3TeWFuZ6D9%B1hw+X(Q3t`u|cKQS=yw~I< zy77g~mBrvs&-oK=aF4&NxCE3xOb&9gvBwt3)tIsjRN8XWAB`IF^BpSl=eLwC7_`T* zzz+0YT=NC1-P+QY(2Uv_w-5Ba*N4pwCCB-|LnnEC(cx&^GxjaIDo@$9n@F@ z=1O}Atpy)$G%Q572>a?dgRfah5o-Nvu?@JZC7n)3XSkGDuLsjuHCJkZXbmHG*ca_1 zFTDNHi7oq%oX^(Q|CZkXd)y0B{v{d4zG2e@Jw!d>-GRj8VW`9!!(w#B_?jN{I{W0i zkDeE_U*zd5v?7XBS9~$X8#<^ha249XE;~H(qc3zZTkz(~U4LkWR&tw{w#P>3?FJR6 z(fN}}>wCXP20{-|sQI}GJj#A)_A%HDt=>YeV6U@7O-$b6eG~hFHJL@b-QX80L2%z! z6X=K!72ZNVXUlxY*NGk{7YN5 z=&+!yq^zi{sNz%sEwTT9p&&Lpt?GN@6ZkQ2DFFe2q2U6i0?GnI1cXfm*9s^Kh?x#Z z6VMhIVk*=uFjGL%R9IQiT0q8BWUZisfP$%LnxMCUqUpe9!B7EZQ!(WMF#_tQgVqi> zCZJ_1o;Ki|fVS!2<^k6P^h}2+3snhBHkDW_)F5DJIy6n_lfX>VVa-Cn1x!sPm4$~0 znwv_k6;>3qG98{KtSxA5D%~tRQ_#j#Mp?vKaJi}MS`i09dsDeIk^f`p-2a*^*f@-e zin<{xD(Z$iZ|H`osHhw6e0+9bj4|NZ`GF1H5ET`598^@)4N_o$V}ht zTIOA3p>GK;^DQc+BT&ozi^}Lo-SWVqa(c3Bd1R4|zBRZ!x~Q6tLdC%r*U-_rIK<*w zI>r@8UTmjhgK^Zw^>iF+1+ch*j@PXK7dO%gt`(NWPC7BT!nW8&C!to_7rW^xx|Pnw z9{M)dO7CJXeS2`FZ*do$j9TSi+)bzGRs|OK&{JKjB8z?W9l=%6#eMWN6b!bcpT1KE zLo6Af?{dM&OZ@cRK^S$(5Ir3Q2bK)e_vql@k`ek|7u>QWK;IXH+m;0B8K`*sk`R5r zF5bB$Oh4d?_b!Rh4+i6XOJ?a*)N22dIXX?ZIc?~T?yn^7=sl|pvERJ*r+u?Y$AiBTLZ=>F}SWZmRJOX7hGeDMKSoOwf0yX zL!evhj3qIIuC?A+GD8$x>x)fe0H}5T*mQeUMmd=o&5@Ac( zj4WLuVkw^?cO{aS0*vfnB6X>Zp+Kz%mMR!Iy7k~v6+`J-Z&?a5a)aw_OLYttYJ+_# z#K_Zaa4t17@?9IeOD&9o;0E8)QU-|H=wDjKQ0q1ZmXs4%bW~TaFcDBi(y7> zwl8xtiglZv%RG$3uFc+MUdEB&X5X?dh6T07zpR^K)olqZ>tU3*wnUcs7)OI!qRaXi zr6>e!c|YTr4uM!cz&P$gkeB-zCxQs-@*zeU3JEM9W}MU^!Q~^2Q!b=sd4O>`h_o#a zGRjfO_T?eQ8C|k-d6;q5mF!&}VVnyl`mA(&T! zXj>eLS&PEh<8aKYI*c=p#JuLhc;m>->p_e!E{$nNVf}IGOot8|h|6Hsxv-HqD)UAV z8;zqg>rpt^3O4hm4u@F5XWnw*$SVNm?I4c2LdI-B;s3uAGN01n!4)dz(=NPa1;~6R zh_|iKF&j|?`wEEptd8JZVP-z(B6wF=n9m0Zz7?fRCyMA_QO0c25d$mAnRi^o$O;?t zg&;AyqMGSKkzgxpn9Vv8Vr4C}#YG~ov@=_SB)a_zLh5Uh`bJ8du&YXG&&4#TlN(d}}=NUTp?ySy+m>$Bi4A1saKNA3Rqv79xi z+Z}*qupYQ}M_^Re=fT}k7@akQN{7MOtS@xw2soehr7N8b2UuSP)2VP7YZ$c$fGb#E z>-Kr$sJ(VL#QILR*9kYXzIW~Q!Y!;Hf_r`NQdR)9&krwS zjq3IV;N`4`u6+@>jrC)2Uld-=3ZgP#@inY5T?Qh)mNo9mAjjKT6Tu8>d_60K+7HAx zuqJi;!T3hjlxx2w-pQH{?zhFeSYgxwd%TvVIO8@WpqrBB+D@ z_-@vW?qDFkhxOQXFcR-${SrJFjqhX4qNuRd{j6VgRK)55)^9E7oXNVBaDvgT2l_SGTQ-?~ia>M-jcSEhG$g!OMQ)3>^6 zmK8-E@~@s_E$9vfR?oAZxDG{DM_K;`4@FnUuw&44SVAm&k)Do7h+{8qrjrw3>?LD# zYC-}#7R>+>64^`j3@{;yy{wsGNkFidk1=csD0Up0X-~khSLm6}1QL5?Gt-+uX0IA! z`V!LEFf_}bkj{qdS%HKMc6>7{l0apz9%Drl=^=uqk0IY3bI~vWa5?+gcZ!gcjP@y4fjup>wT=y{%d3UF&6U z9~1i4cCpE5k$-JBo1zy5*7mSdn?;eeKK70=QFLt|I}HuM*7dV@>H);M0rswDfV|Gn z-aQ6T*A21L(PCiTFnf<)46Ykt?`;-a)&BRDL3RdOVqX_x@7GJ5>%!~<%@Xgr z2>ale#J6siO+`!n>*m-ry)>|Ho}Jk&jjW5Z4~tZ-`v<#LQ%VFqch{QM!vsp$? zgmGA7GHPN1hmFnx5)(NbeHNIQ#Njq)SrQQ(-dL6`5yj!7<@Q7zN1&HG6G_B1$N79@fNu+Y5W7*L}I!A_9z}B-lS$YLxJ)a|QR*=^N zoa`|Lb-j$EK<5DK6`UM>4!B;$Q8wpT)`Ohfu^iia9Y=*$+SfyzJiXGn-pt8wR(jW4 zI0a)$-}+Jxh|cw|FXO27xqWW9}}9m|cbujc5`D%ge^j$W@qY^dcJnpNZt zc8+mOMcq)(fzWxth6YZdJ`dc`$SG>hvutp3Ok;Vr4K9uuop0aZ<`nDmof|xy!_E2L z4PMTXv3%c#E{+9V;NQ^AvFZx~8+te;%>|JSKF-mxg6M`mPAM9MZS3b9(}ReO1DxZ{ zAbF#ob7BmnZXDv2q1C{~Va`dt8r(R-In}JTYz%NtkEv}NgPd}-#=bGcIiuG&H&%r? zXPY(NjS1|0UZY|niPr`Ap>J82$ z68BoO!J9U9&NgMCINXGe(o>+9~#PBKszY`>ejm zxyj6ZuDQs&$-;eptjM>ilK=3{u zJ7zIQFPqEANPzd%SQ!;5;|-%v0!Rh#YyC+Osp5UpeA0ph zdEbtmv>|o85%eiL65@TQKjlQ4dEYmm@**v~AI47kkfpo;`m`Te#v9e24j{{U51UU% zkT%|rW2d9YYF-ds4oj}#jp@q~$+f)k=5lhfoi{O7PED@oh0te!rD3Weri7JP4@DB9y{wx?&3wz=lsdtyczwuKynZ7 zar3!IvXA%6*tuwOA8!_IgKh2S{i?Siwhr)qYqpWM`gy;P*{EBGcys6qVCyjN4}Ar= zb%gh4bA@GVfcMu}g>7q9kT;L6v~LaZ{?=DIw}yHDG*^1JMtJ{@RrAA_lep_nUSn_Dh>(H8!e@ykARDIbBk z;zyV9k%lV)bU8n{7H7CZy-_~-?i}CWek6-g)y7*+w zbw8$?Pcd8%V0!qeE!QI$AAiUA^(dx~pN6r+u>Jg<20H>fz~9wkCu9Bm-Q#vDc8H&j zaRAt1{vLw^#E$Uywm2-<0Ds@O!-fs=Gca{_Y>2<#Q0K&k`3G9+yx0i;;CP)6JIkkH zZuqfte461#06WjmY`GD^M)`-vZ$z;%0y?H1hKm(24D|?HoPgOJ(h)WW1TW(r#2mx>WrVWP@@G-aSIGjLWxaGu=1j3eEUL08<8o%Ykr3nDc zZ9gtuAU50%;4%b~mfH~=RUjR|9mUZFGE4&u&lY4E8W4ECK;F_o#sh-v@dhehCQx9W z0`Lk!j^QZ~uM#L*p0eOULGJidHoQ)t!aQxqLxMcR(@wlukl*sO7jF?1j6dzemkL14 zGk$!TKy7#?fG-zlTAqpEZ36B1Gf{lCK!<6B5o!c_LnDGvD=@S)k_mQ!alDaAs24z( zX8}TkpwRFvNN5xkwLEJfI0dHhXKe(Rz>Im$PH+o~4bM3V9>L+3=ez{3;K=xMK0=qk zf_dIg=oVNF&j$!Sf|8c!BLtt|==k$dLZ6@%v3%9a-*#HgTZ{DmknMp%t;!AP;f^9C1!6eqmU;v$n^!i(cB zDk(u&gJ}jxiNZ^UW{{L5yxh`kAt8iU#+z*Yf*wtAr(a~IgwAZ#<-1-CT{+gt8hwmF3z<9BV_TtW}#Mf*0l@UG!S=QfY<#g-Sn z+q}Y;#$WVp>k@h~FZs813p))j1-A7F@3p)X+2#|zJpNL2Tc5BC!jeDuvhlJgjPGI}6@O48cxP3(UMoXtuzg;5zvbn~_NegP@t339V?=$JE*Lph z^q!#$L5>r>-_k`U!$cp9cTvd+qJGRP069_gq2U#foFw|F5 zVY*=yw&)8(H-f?!ec94YrU0U^#=EH$nP?dEIzUl~zBarLQdFXET3)wMK+(73uiGd( z(Fo=ZI|UMbXL!R&F^j%$dBaPwh<+G=DP^Kj!ElL`DCNzZ=~V1H@qaU}>?yB4ZySEe=@R+DA@<0ZS(OsA&m6EcQJhEfH91 zd=E@Z0+zMDXGuc<%O~EmrJ;a0?ECh#|L1AO_nm1ZU}fw3-ZV0>YT|ugS{eYue&A0_ z2jIpJ0%;jQeCr31G%B!q;)7@!9Z10T!*;TPHO79#PCl@u_#wDc1#D>j(6SQ*HcotK+o=PRupilXLck{DN6wvQU~}t7-kla;%fv^%ouvQ* z`>}s#8Gtl?9N1Y7B)5JX*=Yl|PJA5QSq-4D1F&5+0NOZ!*i{Q)S_jCx>;QIRfV!(5 zz+pcDb~ONa<0s&*Mu5=ziDj1)AWnQ@+vNgC*iY@d+(3%)Q|B%Zu&wn|?=CN}ed1H! zt}cL#{mj3s8=x3J3+(CvQd>WZ?D7FSCO(Vq>I2fSe%S7QV5iZK*gXL3YW0(M`+?mP ze(LTaARRjh>>dX87ze@KBf#F)LCfv{uy10}wmS%9U?13bhk*UY2hQDL;6UpG@9qe2 zaN>b)_bfoge(v8r2hfb42X@Z`nXR8kc1M9j6Q4(S$B60JAy|5>m|+}3q{oSwtwZE= zn3y#&L`_c+v$04{>F@e43LNz85i!jg^<^CrHqrK7}r?3ea*oLFG|(wR;Y3tPYR zrjx~@i7$QWX<`8Tl|MaQEH-`>NY4;UTEB{i?vaTV*sp;-3UQ9{YjBTBtZe<-vIi9BPJC_KqZ6yJ-`Mv+;ymLw&OK&v ze(N{hJr;4n#5cY@rD72Kt$$CMSZ(|^u%}$CY5g{`$0pWJd>h?UE!JU2V0&xCdgBOU zZ>`wSIzrxS7aJ!=sC(nQC!seon^06Y?}Daw$~*#W52iWb&HFQ z-#hnu#D`nI_wMzIk4${;+uJ3!V1MxM?G{^&KLqynh)Y_3i0t)=k52p$-PAFXz$6zZg4B!zNey-k$Vil2GLC^6Ns`O0W0nkrgTn$HXJs0hh#s{mFj7ExBv_$$7vdd9n2;?*XsmrHP+>2f8F)?9cuK-I7k@&w&Fy zl6$Q`M-KQTFHig&JZ?``79*judnRx6wI4kjCfAJrj zlk^&Y2^^f4+;9CQaxf}+cjA}m!5C>Db{0mBmA+@3MNs3U@3+p9sW9mW6SGumg0vs| zD?m+@erWs^q$Wu}YW>whMMyuM_|-;5Ne8gM*{L|`C&u5LRFd@5*5ABTvh=fw-+a_G zsUQ2hpPDWmH2xl-W=J2j{vM%HrJqmy9;MQyL)bYOjV=AcIESF|rC+wrk^gVi{c2*4 zN|Q;4v3~$Gh4gFVA0SO7{igK~3k{ThJMo8&rjw3f|FqK}>37CIoiwxb`_@0bG>i0y zi9da`QfUDDm!DQ99X0+Hpp{D>w*D2N*`z;C{1v5DOM}>XSZ0lM%s7w8td)+p&XY6k z(us+AYG%DOg#8=HY>-YG{{}M~rBkhcTQZ%}>50E>nJ#G<`;R@-Eq!GC$C>Go{?z)9 zH`6QqdEy^mW|uUA{nww_EuAs`8_4XDK5qRtlIfHFGVyOTv#L)zi;cn#^-F&>MiGYw zq`$RB$%p*X-zTEfLqpOz>;iCTSo()?0X#G!{j+t!aws7EYhuB6C@7uBKCvGPN&hxJ zaUKdw|7m^VJrt4tJMqMKXjU4<{^vh5CtWc97dSL8ebV}0Lou=#TnwBZ zD_aD`An9?k#qJmi9VS~6ilNaHWU;tKVtS%%DYQsUPm(QjFS61RvgM&g6?Bv=4!77r z$H`Vei<{^q*-H1~PC8k(Dzvzlo+g9gmJHIq4j1{oe&p=LJ92<{bDrc*`?t*BtSWF*{5 z2h%M}fmSv#J+f`?m7PqlYIPid#L%nv>C>)uXI=S*CmS3@a)-6k5H&ipiqm z65#CEEC!T-WXEMO-3b&nEQ=LNps^FO*tj)fc48I>TBBwsWpUkWtZYOUFSMqDjmqNV z);id@ECIB(iA~B9y4QBH$yuV%+Fo{A7Jyqf$WG4^L+eJ_8Ceqdx*0Y#OB!0Yz@}%( zaEWjZJ1YxHL~{69a(5zy17u}~5@{S+mIAk4%u!_JK9azpDYIJztq zZi9mZW#vH|nmFdHeD{VIJPI;Eby>W(P%hHB6E^w-| zbhsoqw%P6<1C#%H0Wrpj^IvU!t z!0pQ_#UbFl{;XpV0?8Z5I_^eLc>b&tAq0*0f366J6!V6&PC`gEZzSuK8)@YQvQCGP z6}(_pIWF133uT>wlACzpth4UqPF^JITqwDhH=AX{Z5`yzWmQ01M|tyEmF}%Gyl7Tc zXzKzmMqZ6W!TGWB^AHNjkCR_;qbPis{9*`2<0r^#aA+|mf`pKTU4OVF&r?atDMRHa7Y1Pe#?!c2mtx*5RN90$s2HZu|Oez3c{-eD*4lHyj1|op9$eB z1Uh*mj^GeL@@FAJlfW#0&Q0hPSme)#2)%+*xf4em6qL!EAmXT?Tz>A>DQaP(yxpB*6*}b|p_B@t zOYXsKa|qq?yU?~Kp-29rdt0Z_D}O1ptykD3_u{q>3cKZ<(DqSbkNlo{`;5>he>t>$ zLD(nn!ja*ke)%g987Uf&zv?DaM1J{eAu>%gB=5#i#G+yO>kvgP8j-)@rdUM*`I{k1 zg(xWR!KFGxA^BTSYLh4|f7_kfDT>J738nUmX5~KIjzQ6!ycgOrDw>zyckh@HMdj~? zb}Wcuvioppa3D7OJtz$c#AUzlPNM*@><>a|G$0|nAGcEsBxZjI?NkFv*&n%gS^-4% z$Dy4S04jR`x6AQ=^VKKNt|ow#{i%CbCqT~rEVQc^NXz!)b`JvS*@MvTQ6MAxfqVB1 zK+XO^5vPYqPqvG=H zhwgndVq5l)p?wSD>g*sc11_n_9)mKFlG^NXcLqgb&z=Zn&?NQQA>4kkq#=6}+OL*0 zW>2~ITP4oy>CpZPi7PvdJK&JGvmZeRnk1g=pWFvJCEo0xLkD^#RbAN;+`&OfclHc) za8%Nh{n&kQM&ir(w9Apqr#>A*}pgCWSUQ~j z2Sig#N3#EP)2z}!_Fo}dg*2EwkIQsOL)m{rnN8Ag_CM~-PH80j-%w_+bT&JRJ2WVr z%U*yEjY{XUpSTarNTb>Rg$^x9V-zuXI$Rd3SX4+y%HkA@+vpS-OtEB=PLm}lV(|>I zEK#wvkfD|(DVDV{tTKdR`6Q!4hEl}gnGP9Fv7(UKBqJ$SwlOI9#v%INZPVz6x1B)WcGrBo+HC6;5qD^tU?7cho2*FQ&4h%oa{*jEk~B4 zz~_i_6gfGCIqDo$jR$ zzFpZmX{P1ZE8X~Faejlct*}^~->7VFE4Jo4l^v7C75Ofu2Y=X+?^fO|JlvG; zQNGxAxHI3Yd};DvK{JTjW!qrBI4WG3IIe0lQ7LVlmJ3vYoJ^ebN} zv>*!xl&`i~CHp2Mgwuy@f|d3+9#g+m6l@M3wJO9$hGi$?e0J z!ok?w_X?Z+PzgNeBx79LZBNx2`j9kYUn+>a-ZRe-46 z0sL_Xh|B$?@OTqQ%KfzMcqd5C{cQ4hFPN6=$DbGk({l$4PmF>YxewY-%z)I~&nHhT zfb`rUd>LHL&i$gW45{Yle%V$=Q3JVOO_tHrvfN?(NwHdy`*q<-wOWJY&$)p zw&ngfd3r%zog2iL!!ORYTRBBz&z+bor)lbQL-;ddO+)Tv;Tg52F?Xu% zj8)^zot`{Xp{a7^hVf?|8h7ra!m~{pPwr1`XFE0C+@B}U_G-FvBlvTJn(o}0!gHgV zp4`W6=Vmm%++QZoEol03XYn?;wm@D*b1aPA+4 z6>9BB?w@THR&5~nugQuEZ7_EpU+K_>a{n%@Y|@5v|7ol2)JAguoviHD&gMq(RfF2O z+=arbQSE&0leVfEZ8Z14$*Kiyj4Fmu4cEo078O+^b#bc2?bQ?=OtoaHnx;!o#S+eo zb&0B_Md#JJB-OI^^Hv=~wS4M)g$|{PBV2IkaH=+dcJCHdksYosMbx@(DX7@ zBH@x)uTZTox}?^tR2$kaS@oc5<8A&ahz>dRHh?N?^>Hr3XtD+~H+6^c*`H`J)mMYTvntqRj#OEK70*r{5Y zp*6C^7w>X4hWYgD7w`Ik@AG?w>lwm zo@nY;FO-%C5N;1b>3QO!+oMoMo}~Tu3`EV7PTgLB=y@_i1HAD6--bmE$U=UeyuE=^ z2;^l?HP8xWc?!Z);zC7UPSI29LRFr!{V8i9n3p^CR7IgKPepjzQ3&Pb6+PWlXwJ)T zf4Z~Kl2! zs?9UBH&Tl1dB&+mT2Xx-M0i$Q)R0$L^sKt5sxhyq{aI^~GtV^jY(DoO#^wy+np4XKkvkplV%#qD5;lDU^4n=uVRgrN`Im~C)#jx9%k9lpGa~=W zRC9$Hm0wF}ahP%WSBqMj%%uEl?Jb>Va{l$HmR@sOzMarIXim>}6t#|;GxF=&TW8GF z{2NoP3ubzLJ;4nxX6N55awCiR`M28Llwu(N_LQ4eEX!{ow26xq`A-$Ksf$(lPq(*O zi^2S7rrIisb@`2ic1JOk|7=lvQ?WV!x%T$XVoUz>Q|-OQrTI=m$6#?;ep6A$XmNS| zo%W8IVq5+TQymM%)%h-h2Y$FFzq!bRJY1XK((a)gw&%A_d1#00^WB8I;=}*1L@2te zKHQk!-hS75*qPrkb+_WME8jzS(Q(+Ff4Atxro*267u#R#JnYSXY3jw^!(I7a!b^jP zyYoAXUK%~zlYg)MrJ2LN{FkR*S~%R7-$n4kkM!riQshM*8OVRN-Ag&*&wp*oOFJ@@ z-%aQg9~sVny{J=tWF-HM_D<`OK>nLkofSud`8|Ytjw7M`w~FpH9SP^Z-F~n0NF@KA zse8RgX7hc7mj{o`<@Xl7JbGk4|9<<+Ge@HN?@qnEa3rRnkI)6T#1_0))P=Of6};cx zMX|sNKA7sFSrQ8R39pDPi3J}Py`r`x6@1kGiq(QB_;~7-3Ja=Wfbgorf-Cr>=+!0* zso>N0S351_g3qR2?X{#8_zABKTG9&!i(VVGWE4DTe{IG>E%sBjR@a@#=6;@rr2;mKf z6)O0y=#3_;x#0WuH#)7Bf*+>d=(Uy>1PE^qTFVMXi{2cymKQv1e{;raEBJBh%>`?9 zL6Fb`FR3XQE9ya()E11l_fSgg1rt*}w34d&f)L>?aY;kLWYJsdlE#9m_P4Ah&VuQw zw<=0p1!2P5juLmlqoTK)N<0NWwZGk2;w|`j>h0c=u7U{Roxzgsf|;UsMoW4M9=E?U zQ{pT5W$K-UlD>jjf)9SQzu?y*AM)rx!Efz8%29v8?^8b7(V>DlLa+GfaKRr%z3QVQ z1%I~pT8{<_{+jBoI2tUNC){@&4Hf)dbie6nxZt1m`<+K41^-Un?>#zO5GA}jcyz8{ zq3GSwqw@t%+TWcy8ZG#5>fME-F<=a_4_+DzE;98YOXI-B9etEi7`SA*k5-xh#uDEX zmnMQsP4B5olfY#i?^#O`;PUDBDoRmc9PxceDGpp=dcUcZ1g`9Ozq6DKu9|+ow=@le z5kD9#O$Xto4@OHf!1#_2W=g5x>gf*_O6gz%u^)bn4X!cuBaiXHwH^JGV*t2rx}SDT z1|||e6dzN7>rEf3kEy^79Uoecf#AmJ4=ax8z$D^Fj$;tG$@EdvF*CTi{NK?L#R!DD40()97@v2rlE?A>CYC9_kn3dKm0^LxYOiEo)`dk zb@(YK{NV0sKkdX2m`)rNpBM)BmxtgVqxPaNqP`#fc!8L44pi5d!y{9yFZ@ zg9kbube@QS2d5wOo|pxx#Lov$%z-r1=c6a)!OV`&XHG=HL(`uxoQP4=i9_(RST(~m zge;3wGdqSTWiT~sdWcq*pk@=l5SJyYIi@evWl3so#~0Qzgqk<~MMW7(%_n~8D8s1* zrZ1byNNQonmz`x~wP^aw-m)|`K>TX3EL|-&eKlH^p_X)fHB&}aOQ*kDD5I-o#9{bJ zwmQo+j6BI#%R7cCCjoW#^f2wDOsyb(Ek3DG=a{}$pH!)p9ba2dg6iDquPaXK)GFdP zj+2l&&-6{xNwYe?}uom2<=q88X|rtKGmQuG<~N&)u=A&_|AIDsWwf2 zS8>XvHWR;hoN}v+P2V@2@~97YeBXJ>t3ERQeebC*wT1Y@;Hhr4)%3&YsUCGn#}6~7 zeCngqKP;T;Q__37!+iqk=LIq{+6bVz;1^swo4SbetRVdv?H`rP!x-qW*c8}Y}%({t(y(~qO4 z=hc-RKhB(vs;j1dTsR%0sU`;D<*}OcrXaFBPII9nNGXSDE=~t&|V0pU6 zVVW2%&(PF$Ow5#1H8-Xw7Ru?GdSVEEhON123L($%HMcrKlrwALMy6>XPKwVc zG*6i()n`1 zJ$R-}(`1?+{l6mmPRI1j8Jp&X>FI?t)fyKu3_n|=X*PwCXKOVr9bw8@yQXzIOgmez zaT6bj&o*e8GZ%9?gp#KXsnLMBeZivnr`BZ_}sAOb<>Rc+=%9ljv4E@facBVnTm5kO%L(0<6KDdmg#ZRxv=K# zj>nznBAR!mANQV{)%b|N44#|Q^qPJdJvXnp-|@@Lxv1vd>0cJk#c2D8vv6Ci_C3=q z(iW$EzhjnSgK0mQo~79mwEe_i#kNH4ho)cEwj}LG9lu&_2<^wyzgE~#+5zHk4jWGU ziRrf{8%g_V$8ViBvi7s--+FCnT0imkL0h_Z(DeJLEkpaD^)`@{5~y%nX}0P(NEiZbn}>95g>a_z&8zh)|I+8?L? zTBxY1)&`05@X8wPm}wqaS*soIn5R_QwG-3xw90yIi1@d-vOzm(`deMusGaKg+gj<= zPEY?`QR&i#iT^k%-P%W{f0`;i+Mhc9>8$i>f1duQx3WtcA^tm9*{z*1{X1IOqkY`* z?@Xmn`^)sd3zdD^Sz;7k)vx{46h&4IXn*U7QmXvg->0Lrsv+$haY0-)to_5ZpspIx z{@Jl$tqN%Wn*RTsLG3*8iK8l{{oC}UsVc1fr{hUyRYd#m^poDIS#6Z~-(c08cER-D zXw|&-NymRPRZ;DK)Bi10#pq&4G4a*0x<%%g@_AhPvODL^y3L+t_s&~%Tf)ok zpD)!RNXs9bFVi8-%O9RE*Cl(FKR$2MZ4EDfa=u!JBE`jDsL`R#amg2Ibr?@v>IJ(F z8;;AoP_M(0R!A;1=RI*pf={<2yz0q?K3y6K7Jso{x6=$uzBr)U z<$51xm9+Z7#W@|#y!zqAd0nPw_2Y|C-J$U6Cl_P%bW%cmO{|__ zPDrka(=$B@sWmV?E1Zy7lb~ml)<|j+^&ImWO-+)X>seD$gV6KBYbt9{dOm4wT@6kz zFt5E+L(&U9Ywy*N^`h|F`!#8LfVA#GO}bueUiYvjLoe~Hdt5`+OT+7))X?=ZQeyli zwm!?8n0$$^mwOUZF9G`OaAM{qnO;F!FS(@9=a|=PE~)fN&-#)}pguRezVebzuOe-z zy9DX;%p2}pGVAj_8}41Q=nKLd?q4d^gQSfQE|uxk=8X?8Rh8>Co{f($+4S1*#wVAm z^*T~g{N)y6>0%**w9h_p#^xj|oO-lVzQs4wztD!J^`o5Gta zFT3<+(&oC$Zhf(N^PS5c{bA4MdzZcXBjL^WFL&uJq%99Fck8X@Ee|jE=u13X9$)t9 zkA}BAx!k8OB_ZOk^y`nA5y@8u^v6Aj)GL1di7+Db%8Dl`DN>pDJ-umQ9jG>x@im#0|oHwJAYvT+TJgC%KnBig=m06o$s3D;xwTXsHX0)a@ z$#B_&E~!Nru7uH*wJ1X^2~$^#Gh8)e?$nYD*F2bewPeHfFy?-3n!!%OKB!GMILz3G zwHbyw5B6~_)o>$>eNsy|)RS=WSJ{S}W?b@BzTuV!mwFX2+z#V1ugVM!B)sIR!tj(C zuequ+Jng}kTm=o!gz=SEb%sU~q3$YVc-Bm~bJc8k&O^9&)na%)Ot^ow)Zio$A6zXn zG?|GHua+C`c!-a$+6*s*iBGOp8(bt({IwcGvze59t=7=uA*Eik8(PDp%xm=qHz`GO zt-;V{PSIRzG_-qCO0GE#9pRM9Yc7L_w5{%%+i=&s?anoi;YH83d)K^%m%`ibU+Xe> zN!uS>>o#p?>gDYfo;$ncgq_0ILM;cZXqz3UOf zJK@y(*Jlkr(vAn$=M25(9S^V18}55{JiZ<^yc^!}XkaGJa>? zd&glme(%|P&tWnC5Z-&=VJ$TVNc$c*%8aAteGeVw#)qDLj~zDSkKuh!9M#4kDI>nF z#yDoqNUp0jj(ajv>+Hsfa7Jcby)i`EFR5!VPMY^?>Kctxp8X|tPUCcVe`TG^7$zO4 zt8*J4nGf8l^B8~f9Jp8KHU1nvaKEn07$F^eP}gmoF&}(b*JFI_IrzBFXZ$66@JU^t zah61lztL~})l5ykF<|`7LruNmH~t=`X5JVw&XH)68^gvw%rwo75#yg8TFH%o@vktg z@V>tmrs#q{L*IB4-*dTKrF{|YX8W_nXlH`&mdVs`RPKD72OJM|_2t$W1IyeWecQ#g{F3TS;XM{`pJ zZMe%Rxd}oWA8{&g>Y$_)Zrx1?+EmQFbJGlMzRSIL(*kXI#JzvB6hfr%9^5R0kj1=* zH_M^qyS&FYZP3<7yeBuSAyf)K{#FfyF6JlSs)aCj`Kh<;5cUy2^Hx2COA$zJH9+`c zf#y~tM7S#`x#fh2j|7#sTo5TmSa-_}r4$SA-10!%?h5bS@_hQ|(YGxfBRj~(nbC);XT>@YX8cUC5`;%;-*mMw{ua+~M5Y)!1J+x+Zh zzOnGF^uIqmK|n%4;Q#-ygwlggE!*nh54vH^x$wY@RF-TdoQRs?VEfb81*gE9{tAd3B6N~EfGe}W$&`T z*pWy1&Staomb-|3g70^*;VY=i+3B{_HS9NYcfHT>eu*U+K2m5a_UFl4!@h!Fj+mKz zL;Wp1zJqqVNk_XHL6HXd18eNbbat==SQRSv zOcRXXBPpx}PKym5ql2zdSczV7Av1L}AL~O0>yq&THR1-)ZGz<8*;z71&=MY!gN(u5 z>??MC?~+Ut*gY&xq$~pSEXnB^>#Y|<>+juJX9Y&jiQKsYoNh+$d|XuekiO6rmK z+6O&|g?{szT-ZTgVx4kN4?Yg}sXLA4qWgw!xrSay&75%poTU9c8-2&>I9kNVLFXv9 zH==((?i~>iZfQGUkN`Sdl;4KN&9EPJ3N$&UUX9vDlJk|EXD33BS#*C|61b;vP+c;( zt@eOXI+%A#ekYopY=`vXM ziM%XVza|g*H9Nk;>m>G>?WafPgWGqK*=(q((PG?t*+X-v=bDj2#hMP|-R9Be+vr1f zZxi*z)L{YzunT%+&P3;E&)I?AcD(3T2ns7(oJJjs_R3xX_Z5@(m*yYCPLW-5AGJDv zV9r%AY@2)ly3nM!7?qwy=CEz7)NI=4vm*vC|BCNZM9G+;+>IYKieUGCOuBeZ%)<83 zENw^kYmtTQj9+#N#juC{Cdd3Cm#~HG(4t?#CGc)D>$LxP8Fp5n#MDx7co5lQFQL_l z?LeBce(W=LevkP%e0PEMJFr*r5%i+Pva3;jnf!QENS5rJc6wY3^y2Ac5Uc!irXB8s zf03fjdsRE38IaHN2VK=kOW*=Do z8NR#9jy0v;$IgFTbRX{#i8dl%z$A?$0jRJhd5V3&3e2Egi;ZVjZgo5O9lq;i^^63{ zu{W@K#@uX4qmKR$xSvX@+luxn4wL=`e*AFO3hl_h`QtC>T1dvScUg%&cG~~oK9Ak; z|L&#z96KU_`c5EeHvh{;{Lagg93OvgkzgbI#dvJZmy`dnHNTRUd!D2UL+@kr**EOv zy>xG9zs%pD`%3w!aM!hP}}`+=2re)R?K!R&i> zvJ34|?6ygJH3q@E;cDbIcKIh6Z`?12EN(~J*fEEw->?f0Q|~##?^q|RPI(dd?i(9s zP2I~*u%X@|cfcOsnT;Vs$B`nh$DP1Eg&ojAo$!YI$0qEy5gQEe4vjbxj1G7*p$rXe zA}gPf&KGn{hQS`grg}U{7lR(?Nyf_T)e?u+DN^f}1OtuSBBVj{qcgo^z&Y=S%FBXv z4`sH^{Z?C<*{7fygy-&NGC49+&Q8KnYV(zcte3NE=QvvV4FWN4@QbZ}zS zgc=Rp9d3$fg8A$|B|9_h0@i5)^=Ir+?h z-+lLEL%BA1Dk4>12YkqC9iv{)Ca^W^DBGES_uU(tzCKvR!>IwC?Bgr_rT1=08URZ<0dRdzJ@4OFz5%H4s!x zx7G{-XZUn`qmz0k4c`wsuo3Luk_t=QRfE?YMD5s8wvSzTknZ!B{w(|7yOi3bV0a(S z_OVA&Y43K}Bpd>F``$DD=pDQ6jiF$kJ^5+E;q%z*if$-{f!!jp|H46yh}zT$a4j3W zu1!7~`q}qUC(y*Q%k^k2dm;bo?-=Nj0oHo4V7W#27IgKLpLb4x$Jp-OwdwKDAz#Ed zo&vuP+kYqtbPywBJQhi2Lc7~p8)tzDY|mAtUhI8~R=H<`a*N52r>4z458V}L7=ID8 z4kGtSZ5ojS-Mw~xS1u?qWld}W=z^wJSiUV0Pjaf zWjzEHTf2hmz`FRO@9RN(*GVc3V9Z)_civy2N6_8r1ExL(-M==AHenwU--m{bo&V#1 z?KSrCGw7``hbo%Ek4q=1wSqMTp5HschgZl)QikW=K^sVu_g_5fz)pBq725}jU0z#< zZecz0sgL{r9r_7&iQQzkUdrar(AoDMb)wR3vzq^c=Pd>pi9CY;`Ok33`oW;m!&%SK z+Jt6VQBeCNDPz7bYbbP&u+nfbQ2pYq?XsZQ&eeJ7q5gOqIk4NobI=&@gzA7fXh~Z} z=2);ZXqn4+@L7RY^hB_`HshQMXyMkZs0!|8i^ArKPl7)ALAnB!$-DFy?Tx!`JsEea z=82l%1NQkd={qx^8>R_>!j8V^7NcrhnK@Hm>NBE1?XMfuVxE2 zuu>($%U42oA4ooiZXD9AVTbL0t{t`UAZ>rWw7187;T1hc+!v9@jIO(^hF;y!_Y{p{ zS2j|YCx%O{fxRg_+QbPoK1!ysA`#R+Y>@3#e|#sql9aF`ce2k}`|(wU_%2kD>}5NZ zs25Kl^H`1du6_7^>IX8Kb?l4^*H}eq+HF|jR*x|*@XnKc$O=BEJ%atrs=T26Cfmo_zNGyK>vdLmCH`(QJ0O$# zA*+=|oxuKOHM417$5ylEo06mP_uL=)&T|F-vGKLk{j6&pbrtJWPaVyQ$BXX6?_1ds z3Djn6Haq7e?b+;qtn?|`{n?A`WY>)A_`C4uoczyq>&Wi!&$QOUZu5iO()n`rI%tK~ zjzezXL3X6!6~pz=(QLz7MKyP5dG+h-(9u)K?$W*%?BEruHXfkP*jo|k19rwZ>Ug%F z)s(0G1pAwfQJ`J?jpIH1o$YK3YxaFZk);OQ`@&3`K`29ilJv(kU?S*V78?=Y^4pw$A^+Gm)z06LVJ9RJqemvXH?wCjW zc~*QrwHcemo;9akJ)?j62Kb#@?4&c)N7*vg*gM_}-=(uYKGY4YzAtqWtGkgpk(JZc z%Ea#%u^sGQJ=!hw$sE@DuxPM1y#H*KQHpkZNk8=kZM?}V0t=UJ#C@sal+B>E6}f-5 zs_ho&PIiU%)S#`i`XP>j;)wG+j+3d&2{uzGo`!-QzG26wykEUHd zhAdSSAjy0iv!;YRs9l*A;KL%ajfWNa^ zgsfmE4W>TIma!_Lv}dx)b+%{m`;}}c+ru8Jr+W#j&_I2Vea~7o(*Bl>JK5KUzdQXD zd7Pb^NFB{qvg%2+-(qL43m>-!zCXhnyHTgJzVQEug7-$&*`0dCG*vs?x3O7l3u`)^ z?wRan4eBP=NR#>z`|d}1EdJiupX5IF@-OO9ze!6rhn;fEu@1kBVjU}}kFoZ*so%1T zDyj3>4pt-l`_R4cJ15vb?9ZdLJ4KM+*+sM?Px#6E-P^Th2M2$ zdQ1!ivuYb9fia_k+!?3sxKelfPf{IS7uuX`78! zzb%go0kfXnEk6W4@$J_?3>s}D(^v)Fct70F-+%A{?f<0Td<1m;Ovc@4ln#ZK5Aj`w zE@Ok)_v}R*(W7|p9+Odp&g(E45C)F9^lTQogcb7l+l}qc`V2ew3HvmgmiE#!9C~It zxsmPpn>+R>>?{6}%Evomu*29>s$+&mKyT?QoR2lUP-M95a8M@Ms3}gG)mD^~)$r>4j{K5AFO-L`cfz_Wyd+i`a z{RDWYEkbGzCga%YqSUc$Yu&Z2_};IcY-%8l8p$Q6Y;*Bmz+O(I9+gDqvJP&2@9|wZ z>!A^@auRy%f_{@kuzRMkXA;;|r~e@`fHiVkQ7j@oSZE`;s*9s_AL91 zouxqcYwRWq|MRKv{xQ4Rl6s1`^jq8w296n-25xz);+6q6u|}QLhw{r)ao3vrUFHl} z{cOrHv^o9mJ@l?%{NA&mlMorrerMH%X^&)Yv10dT6ytYW*fZ?V`?POjAG0%SXg|#k zdO+>Xj*Wfr1%I!A9etcSoc+WmuJO>wgm*$tWDUE{nYx;t?m`{Q?wBO(jo-DhrfSq_ zlgaU)k}~n$bzQ$5U3P;EX5X_*Z_-}CE-t0cV_iZT<+I@XyR6e8YPG{;1p9>zIzsy! z_K%gXJ$}D-8ClK#W~W)x9?Sk@oor~YWX0t~PvGxtXS3K5V`!hlX0ap2(%#H&9Y_6) zUHLk_9)Ir!JE4R6Iy>PF^%1s*t=aj^A{)N@oH|$U9O!YHd>FmJZ z-($@^9ADz^|Htm~q|V+zZuBA_v(_`d%jLrRPAzh=Hd)ahWsCcyzhnek&Z_>Sy_7Y& zGbI||r?HP&!@IOMvV*Fq^;s`gxSIBGwv-(bdG`VS?qgOYirR-wWj93Ap2XI&LNT=K zunX*6MK8hc<+9Qa)VtX>R?3lfbGA>pe=dGEQH9*k7P6h}VpY25u^p`I$G9N;zKWgN zLmkcjU|09jZr?|ivO|hyT*vP>vX9xB#k7kac<>$Xo7l&!VKD8f?4X0xUTgy^zsN)D zGJJoPeYvazzb?mR`4aYE}M6DMk#(Ln@MJ8ld78@{K9?t7P5rxu1&gl4ffKtjT5hf6W5W7 zZsdR|zRtKOvf5LrPqP2md(&v2KAqI~F*p&wJMxoED@$*}9$ZfPutF8o?(73LH`GM( z2E3OJBL^;jwglUYtz+G6X}`~&SV=7icd-%*)aTgd@zhQQ*@8FWT_t<0kb1D? z%bmD)uwD}W1=#hht|av-HlSIm7w@B5$ToI%+aw)vK$!eXU{&kjg&Lk_@ zIlc?r@qHF+x{=zCea6n(M0*C?#HMYgT|vJi4S(k#D`!X@$ab&`X3{=YDCh;gk7kvH zsl(Y)R(SyJ+VXwh%Hh4zp7QKl;INH%8!Nz)PeR)&L50s`nC{EnRnUEGRCMmNYUtbS zcXnqC?K!I#Y{2`6NgZd<=1+lb=zXo0^YPO&qZxllI>-K z&oo2Jl#||UJ*#(%c2ha4q)vD@x9i2BUho_{FJ374JM=EL`+I}#59n+8TN8hRiUp)i z>xn%%*Zfy z*pTtA_`N+lb11d?laeIdzp=ZUsGX8mJj1=)qgP4=4E7}NZ6Mdp2(!Z7`;T%sTF+Yj zr7mPQ#yAM8!o8hcrW)mst@Uy86?9^-%hXAr;i5ktsLy|z|Dhh|YR0I6g^hYc)WOA% z$UOFi=HMH+kDNhnXIt3eTC|(8zQ59b;QQ0;frzIYCqutur6&x3i@lr8VgF;#Po(?R zmpO~3!n*@mmWNThY|?Ve>k90ngXLyU13$5w8Va^!&uAol+}?L%tNl`Nn+{6dDoI6) zSM|zhfZvqDY|x;BvU}(+_F(JeVom6ZfpM8LK)r{W?dY!f8hI`7Keo!%-5&et6rmHS zX_=mwHt5G@vdyemIo-FgO{~!^+BdR~*})aGr?T>)4Ho$OQ;(7A-GNNM2)K2Rz+^yJaAm%eJ#K&9~;@y+C~Udvr!i zma;DB#%iB6bHT1*H8ZI{Z+el4yWM88%3#-1?CFN&FLvro>L0>VQhIQ&7(niHetidf zsw?Tt#;|YK(w?LqD5MYX#LEhHp&_A53(;5d2d5Z-GWjLx=vf~J(V5^=c7fivx!5s+ zQ9)?IgUQ#?;_I4kjKI#D0=CWbIfSkmHn;+99ZrrLK^|b&Y)9IC;Tr7{!IlwtpU0kK_Z^~rjMeLEya%zh7Yg>wfo|Qtv$6^L9jhZo_fxFwBLy$~y~vc3v*={c6|er+ z>{oWu2HG9iGIphQ@3^_}-T8l^cIXRM?T+$sZ1=n5Nmj6mT8H&uPq8l1Wp()7Jys)z z`Vza-!C}}uxQ}!s=d$P6=dAc@x|^}v*%nr1;x}{rog{XqGIf{=d6PY=NW%ud8NW+ng=DDvWXbL4G~eOf^gMZ%9d?0wGy8;9@vE6=4)4R* z3$xvwu_a8&LRM?AP$KRLY>Ftg-VoA#C^-#Cq|&mXGA@9&)4ft``en7a2wRu*+Xa$}NO_()pYfXapPT zXBmav%U<6`eaYx`4eq;*$u_pwgnIR$z`={~_e98O_Ho_lxwsFmCug$0tof;eK)laP zBnP=Ky@u`0KGb~w4SUg#;2Dd-KsKKp{gd`Qwu6=ZMZ0Q+f-ioT$%@^k-ol;U80HgG@7 znvUFh6+4r4k)&4hHQTTp_K};(xokaarT^j#-Vd->*mvwc1G=ZpB*zQwYQy(EHIn02 zfH@CIsan#Xy}+uU$XSK&jRuQ_CBlO zO8aqEX7cM={B95XihVhS_VTIZurC2aZQ#SfZ?n#CseiI-I{D73y`#>%q_7#kv%E~^ zvai@td9>%SQu);W?8Dt97w~(*J){TwfQ{Qr`#n~A?ut%)Z^7CG8X-<8b z6<FunNB4&StSK?C_Cv_hX;2mfmGg@H?e@kw@&n`8DJ&_9Z*_0qv&8Cs*RTv+S@F z)SKBStWg~8an5%H?BRVs>*_+iRL#W*_X2jbI<fVElp%KI5wRerSmiZJCYUBrH+oy z(p&?3nxmNyYPFg)Ihf<%1U=VuX}L4FgMG!C&!PP?D`Q42^9cSp5_q5Zgsf$?o2Vym zD9Ocp6#Jc(nz7;o?#HxA&p$mXuFwg0LS503RitS(nI5H_jC-A9*)vpUH7TO(AiWm4 zg+1Q$)e8F;JFz%296OY4e)Zdb9rWyWve-}a6SneTcTYFab|`tBHE0k#gL_0o+7Nf} zGpllp+K#=+K8&PYD~jA;XFMOjOJeI-9edh8OnABv?^YAZE9@9$YQd{wKk=@`o*MM} zu_v_OVDc<$B1*lPJ;Nr}1&rJP@4GT1kNJQhS!6NW#ad_6F0^U#eSGK6%5J6BpLu7H zFYH$bxXeLg2a>VEIVdoe3tPkn%$6@Q`_?>-4+D%;2ko}&E?du5&GSA0Ll zjg))mePR=IRDnnXTIidlw*^#Oo8z(-v|)=`U3JSO+!I;B$<)n9MqBy8zA``9WE;53 zU%?-pb7N=s9HC z>}Kb7_M+MB@blD;B6miF!(PtLe(1aqyYRvDtC3*GiJhO(g>mG;$vGRMpoNbFjEe?y zGJ14k!8W$^hVzmW(4Sc4o7C6XL#5O&Lw+B@cVFJzH;MyQ-;$;5v~=&Zc-S{+r;Sbk zn{>%pdgK|_%Ta9bNx0Xu^R7KF!Ja0U<8um}9Mhwp3`ViNj-h_oe)Vuqwr?aYH<2Q> znbtM18?q;zpI2k2e3dYL0OsGkxCed9E-IzI^i2MEE$qkBi|f$VNnbbDgCVBv-gUj6w@(dt0XDHc-Ge@3Pxwf#WE0;XaB7EL=mU9k;c|)B&^yjftVG2#$sKHF z{wa}8*awXCE=r4cW7Pq-@6b)vWNe^(hTs$Uk7vcNa|6JZ`MQe+fgUYh73lHZvU`VsYh5PR z4+AImFa9nC=G3*ejRj5ICG5t5OU{0D8V}~P@|o1Z?0fc!qQ>M2@a}HYJ_rz z)4|7TWb~(*`>{_g9j2oJ3Rsa6%Se%rMIW_b*E#UfO&iQveB?AbVbsLu=+P^6C-gy~ ztK^pTJ5**u54PE%HV^DsPWqp)(XfD4bpGgt9%4(_Zr0j`?gJ0o*;~T9Fq<#O(W7tF z#1?>_mu_32`ooU@M!i|5dpa(Qpkvs{_oZ=9?uJf=%lJW9^qga zTOTQtf&E(P-k~V)s>#gM7|>f{v3wjTIkRY3JeZ_-+xaB;$3SOSB4|F7OdC*FfIZeZ z)jbIm5?ri!8vN}v?h%?kxoAWhIQX;mLez&f_(DD9(BWISds|KTi^`6uS+goBs_d0bL)|-azd)?%8n@bh@`ly%dz$@U#6Ec+#8H(~DK8fR-Gc zy0sFNdOZ8t9k7O?e6d}MSBD5*Kug1Q^y^D3+X6@VwefiELJ^rfdC$K~QbJb^1V&u)O78wT9%Ec{y{gJKK>)v1pj{Voc%!v%xl|sWgvL1@z8&RK&2}& z+M=MRRGZCkaKPs`L8HNQA!C1_c5l1R$$?tYF^1znscU~H$%DIt6V{;$3#RQ-1(%h3 zj?)6~q<(sC06OSST44yv{JRy2{y6wo(+J!!)UeSQ6!19oX%1+np)}15Ts3jhs<~i9 z*R2>dUL)nCIk+u+<6;ZYV%3l%=(5c}#Fm1Q^A7#61uNLu!<4k)FXfPaGdf|rJ?_I& zQXRnSkFQubg9d*T^<2PYcI?$#iLTHoMda9rmlQpr=dSF!wE-My?KyoTsH`x+3;i%@ z_r)!swHjH>2CGvGeUW~L_q*4oM(qImk_|d`fwS*qH2Q;2*=t4T`gcPwZWuEv0IZnN zRfTE|_@NL69<7OXK-<6dTZV%RzmrjU$+<_N)$_?nc5|xY{216%)5t;TWW3MyeYmTt ztbQ8{ik3vLISwk%dHC-HsGgdf7Y9C_@klKm%+Mlzw8`3P(bKrwM`pC5QVz3Z6Tr2O zq*U>U``AXK{@Z&J96p+Svi*|ADQM9hq!BAM^i3x2bqzu7sBR;9ij{m!eLg7TWg6UH zuxs~G_h*iHm=1etHYva9oM;C06}F_c?{6k__nC0REU^77X_-l`6==4*2>Wl=MUYxq zm|VqHu^w^@x8%Zmfia{{PS87S?_tXlFM+yGJ~W{>*lFn@l9!>C1y|ld!`M$%eS&$= zrPbubd*mwi20JG<+!)_^d~)nXtFM2boDaI(An&s6OQxpdZn2bni)ojP&{LgOX}3XvcjWK956`iM3&-fOQW3u3Znk zzT@s&w1&03;5wlJI+r!SNPU5I&841i8h;YsIm{t5%t%8I;UkT(r?QQ#fhX-LY_RM( z*(dPs1FN>p|33C=Hj3?NToBL%`<=v&V$>^%-02Xa@CKm|;H5f;o%np#J?tMF>72nx*lGjZwP zXdy;QdVP3@y+JQTxf@JX4PW{Zblc%Nr5BWbJmV#5y}`q_4=iFWw1uOwD?g@x{{;3I zn`nIoXS8Q4egS_aEjaWQw9p9pi+ao;AFz{^LMDBOy=)@cc;#9OcH{gHJpxbRzb~tQ zHxmXGCzDE{cfVmvy^YHr0A~6>7(Wp7o$KL<#*Gw?M^_y;F%SXg`Y$*t3YyI6s6x$} z{73Gk@&< za;dT7zy%egZl2tHd1%8uh5JyQmV?>~;C+4Dx9C0tvQD^9X*~4%&?&bS!R29OtgpW8 zMCd@>MjLd+@Q!*_@PKz=@FY-I&#DalGs*V78aT4AS6Lm*xEK{S8BE$aE;u+mt_V$KYmZSc8vkIr9_*J{9VKcj3w?Qg*srk4bz4gfpu^Zc*0!GZ zByp=dMsU{?w(T_rMO;+UO+at9fxV(|ckpc3=f8ECi(X(yc2cLmBgbF*6NvW^cIfW7 zYuK7C?!Knrr3|5S=%_Pfk#|xDc99SHp0)C&KEQUenh$*9=fL}4pPz=9fi|UEZ=u&% zgOK5Wu~XQAhp4Npvkm6rcdWAwbtNmbD=O9!?vq5zUt5FI>Kw+~fFcc~=8rqWmqXXB zj4MZXtRf{9XY^xhE0I&`pN6l5PInzXU=_GBeAg#5E--McJ!s+@w#gA3rJgS90#+W{ zdLQ+gBc-_(+}327g(^HHgIQ}`Ifr$y=Lr^`Kz}$Mv~&ZLmxOIy4+@P|$whawTZc?} z<_?zu<{d=`tTmizGp|Bdm8P9JNursI#0XY z1u~HJG8sO^8{Rjt17}ftvGwfI*|fKaX3xX-!-tUD*cNv7P}+AtHrt2q+SnwYHBX`aS;Xr%KJdMXeV~#r7`yMi_(o7-@xeuCw9NR!Xu^w<3e?W8 z*KiY#1L@`?hW~?2pIC-P;0Iyw@DG6|}SvDn>7{GM3cN5=mch zcW>3x@B=-|&4RasMit~a1u4B9(4pf=>paUG?DwoyK6PLLDQ<9Z=`OgJ#H|qW2gk>= zWo5nCvTr88+zonMz9Y8>w4eJY3N2-==23UE*7K=gL-dSF*pLOXTw?(`=g+x zYSUC>K-sBVo6#L*S<7NU(NMFa=poike%FBG(EV&_r{rvGf%oL5VY@_9pu7JCXr_WT z0)hW?nIIX=3RaEw!Mi&&;^De%apgMm89HF?S2f^d?9!rH9DI(=o0vdHO!<=WuFi7 zDaQL85pvT*k+0Yi@o5^D!QJ1tw4>>vS@wD0^f2-``eBEy%&W^7$ZOd0wv)f3 zvR%%;HDCZcw3~VpYrH^H@d4b&{b;&W3$B0vytxkCG(YEPJs7S~HuNz#JHXwZSdAUxSzba zT;&t^k98}hE-EK=4)?g=-EKu_5?ad6xnytk8G6{<$h+u&!zT-W0i|=Bu73v~3FajH z1g}_DBMp{%FibSf z0@eMKxkU(cwcDvI43=N9c#0le6tHvvIA27ea3J{At;c;3XuqCp(F{$;etEl8P6R9u za1I&_w#3)R4*^XRNSkk`7Y>E?&!2O780b|<$^|^{!uBxVIY|smWQ8oK53}PfskcZ- zuETemS}&%cgC68p4+n3?Eg3ih49PDYHxl$quQZncPi2tCdcSXCpVcRa8jvH8-`^|= z`^h!yFQPM?$nDN#;5ZRUY1q4)GIx#wjjAuE$$*b11+0(-ORweEpgWemGaC*1j0p}z zty4);%M_iA>!BemhjdVC%2IJtJ%r!FbzV52+V{@*Khx_M9 za@>TS(-ff}UAcG$HM~luu0Tonhy8$^@qjv>?Pts5^BeG8sBfi}2B@`>G`xIzr51GFPNNv~ z?=IG?=^^$%u`NTi!5&A8w>sdeN$pCyU?00ujXIQ_(z|yJ-lJHhK57lqkVqg8p$_3GKbCx%sgZP{tX3KI+|U8|(aucE!<4fLcJW|a z=!K?ap-$LVA-QX^E0O%TaZTQD9>?qqKcTtTicK(5&L%^3pR65fsBM4MT zaC^89EMnzPQr~9VPEijjue-h<-bpE(-gp44R3xVtK6!)f4F3nYVDJ$;X~4ybgV0CW zr}3{0L!gHykQr>0%iis{|6-$EsYkCRC#cKj;r$3}_a(0zyOf>ymAa~IvDzWnPlk4` zL;E|6WDbM%c{Vm^r2oeVw1SkEsgM1cz~lIk8GqoSd2u`ibV>WGDIT}po1?)K<7^yl?ne@}p`+{v44ktcPB z<{-m3xTk56+p^3Do`ja2e&FmWFg5e`=44PZi|m{tAejn1?AysD=w^0GxlSl{6x(CI zd2$-`atpGAb(0w8j=OX7*)+70O>d$8ua(^SoP5qYWSG9d_Xp097BhFONQd6dzF}tw zNkrkEz-kIppI}QLT&ThOw})gzEjd2Hd~gQrUY+AQ&VWMiNO!hF_e*&u>|5y^2-O2kqL) zo2=2f>FaS%V@1wWFZ8IpUjX}PPxAKffo6r!YJbQG_6r-{PkYzPk#Sey-7e9+2aE81 zolH5ZUQhl@%=?4wokVUAFH$Li_B%=nMUW?1b;XZKc#mX9bRB+%t+Bu^{2F-Sd4%wF zQ1%7+inVx2eetZ?EWEG!`ESfk@FrWU;5DQaT4y}j=6%zq5_-a%y80^6>iWo}`(TNu zPC^5CORMe?n$y2Qyb-*AcinEUt;dxy5NJ}zntUqd&t!IN%>V0WmIFE^wf zeG7f^@8bcTpuj(}Tj0t6dU^Gx*|_W7BOkB_<;=&uhy4S)Yz*}dk8!^~z;5D2-rp8$ z)C0X#^j<#tmR*;%-RCoO(;)NlU%*2ZZx4P2yV>iN)J1mV`f*=yr91Z;B zH7(lx&UM0RMj)13=HFMOLDq)3sF@LqT&H zwUxubdv|Kz3x5 zg2P`>Th?YFb-C084Qbd%ul+ep1`J?D)=^8X_@^riyVS_k#L?j3R>P<0p8;p@$blVk zEyiO&X?dBKW5M-#i)_b%DuNTV6u{Q8u?rQ!sj0PHN??J`z;zSA=daIyRt7WtTFj<{ z+S|w))_&TaYz^2;S@olf95tbDvAz@bH)20#2O59=patDFAVO6e45*v579CYj=CV%l z70I~YX4Mm@BiYR-sR#UsS*8Q;O3J1kMcw58&C&($v670^-7P6+^k8o_+_Xv`^qWaG zv#W%L#^Qd1oghqon0-8e`g!wM2_ty7sfB#H(fSDXlY2@=#-Qy3@*3N7sN%E<>?2NV zm&^uZ)5(z=YQJJTYj4mr1@Evks#CJC)7W{dA1lm(ezjqd>pW26zoSzvK<&Xl$5?`Y zM9CTUwLca>kH0)7fG)NQM@ z?|8tT?m#Lj)e3q-AOG=Rpf~u7b^b|ht+dG32lfkHZ?e&VZu0GweI3}QL1Ptt!C85K zmu&$xFYUg$9sHEBuX6{OJ8xRrZZI?b@A5t1#0?3NXejGlve731+SY4Se-QZFJ|QLq z+@z#ki~gKI{vKuc^ANPZ3|Z6mNc%AKqO6UZ&^PR&Z0gJGYu54{?Gf9CT)_9v#%JE5 zL3Pb*j^OvK*w1;3L!q~@P3-+!{~g9%vx1b&>}m~%Uby*?>`_qC_2`@k&}=PP=|*m! zGARJ}=d9UO>MVBnH0rJFGj_pr+N;=A-)0Si`kd} z_5^R-o(Nt$NGgVqA*{^OA$fQ&wIUlXG_Om7zA@~)OfuLaMk-b<+?xU|rZQF|72L*N zEn1d|J+7G4n|0J84SM$7s(0z&Synk>t#Sr*7^|d|kci!R<)P#maO9|zJ80LBb8=ar z^-prxFS4&TCmI5!L8K7Q-%~>!uO@K zre6kK%E|9z#b06T&EH*@2PU$W&6mvcq33RVa}$kP_DSLjIMId-WkuwUF2TLKX==e$ zFml7%$wk-#32CT}AUU*3>jie)vWS7bGBt)gZE3# z$f?Qm9Irzs{*xYY1H4mxX#tuNwJ-$LP~F#$HnHdaQ(RjLJ>%l_WOU+V)uUzLl*C(A zsD=CL0p)m)tonqyMv+x)<%GYUw_xAW6@LbO%7zqcwPCv*csRBK%*eX3qY4z=yeuEx z$o|L9-$MJMlh;pI!@Z4_E|^+!AG*6V+OgSwctH=i~gIt_0T#euJ|{A0deG~ zUAG=Sf*w0}^^nKl>Za&@=+_W~kxxPEk3oZ4!GmlO>n-|8{srv1L&!u{a47YouKq3m z!QD<|W7sQji72_+SF8Iy^j!UilRkh$CO@+70ynXbSt*-YrroeR%Qx>q_g@7>e_=P?7E1Aq%-w4s| zgS~0^YRS*w3%x4AFW{TkzER)6V`9yL-@)#?{vAI+>nhT8>6MUQ&`;T2LsxeFhJMK& zYv@z`1AUAA%1&ye{V2QY5w%is_*#5FDTNgO?Kr9*+N<*WGSuSeh+l#&@Xr(D=WP}O z^%cpo1(%$Jq5n?1o<9&AQ`V`g_OJDu}Km-kbTWA8f`E^ z3idp&nQh^?A7+--_vEpIA zsgs~}twmeWM0Q4}iH#bx`sHU4=rJ}auH)5Y=%`Yw`YB-S>uaS`!Mm*B2-Tcv(2vp_ zm8XM)(#hLZcO^BTr;bkU)dXYMAMCG-jqWpG-)AcN5?$fw|6LnA%wA&^SJPglBCVx^ zzoSb2>dE!RcJ3vIr`Z10gTAN{zD*zeq!gWE0KV*+(t@s+imx^VYuFjm)YV%&_RNHR zg|ToEsxc_}Gy1bmf4ULqR8P+Rkv`5C`W1U{YRD2(=$+q_zRd%xZ|cvO51I}iF~S0z zJ}F3b0XR;Ly{A4y&nyNV1<6@eQ`)dM#NHjd1Pou} zx(Z!s<*|P$C@@<1CMu=n_hcDZ`e(R=H5hp(dofzUs@xz8dG7ht5+V zAMZACbAui`(ytY5)O&evJ?N!RdKi#)!v2HYVXwb0H3uzoT2PE84C}Ml0Qx=&3r1BO z?<#wP^H!6G){tGSwyLWO-j9y<2=f6CwF})vwH)V0ZvsR6dl&kF&BhO`cYtDbLif;v z6P}&j1q#34`U;(pEoHGAJRhKPCje9mBo#BF3Id@+*cE4}ds*#FY8l@tz4*>^Gr7}X zZhSDbl;F!oR4i6%;XzQ^DK`Wiay`%>1l-6<-k_G;H9qAK?1`+$Zt5v>t~KNC+tj=4 zFu2c4r5b&uTRz|jSS;W;8q7wB8tXBMJJ=W^%DXwp$vs*roRxXTa-K4wjjqQZ;#m?O~VSqx~BD zZgo@{zJGVYJt-Ts(n>cu503b2?2n$Pep-k|M{eyyrJ~4l4#THjfEIToy^3DE#I9q# zWOAb~VzVB8f%9^pBTeM?p}Q(qC|v?CNA|8puiJ+upywS(Cnc4~*jW?FJ0Hu$FGJ@Q zIV?gK?fZ5J?PHJZr&c;Z4qOmbf%gsUN7iN`?c$5bBT`fT;k)J1q{Jw4gbaBm%Vm2W z+&5;Ek6FWW)X%s6xs3N6#&O+fE4y;=47GgdKK8aKwP{_=I^55)o9n4H8_2nCLalf| z$BtM}t)Y=5QvkcTCOP$oo(=Y-TMZHDo(l36d+|24L?yX{ea<=_^|^=Nm9wf5)Zy&^ z(RAPOK>u4D$0MUe5=sLVp%5ymkQJ#&sU#ysLdeQWMv_QVi&Qj3LzD<5l2XyoKqay& zEe#cE+;e{C+`pcW*ZXt6-GA=m@w@$gT|eht)Dp`Eh!ntGCOhqNLlJgfR8TjnIDfEq zA$V^4yJ^Lsd4k7@Qc&JE=w}(2#fq<^?w&q)N;&Lxf~VJ^`u$1GmEmKrLvQXrpMpwX zo%;m6p3p8?0j^9Wr;HrA6&*m?BJN(^@8=#29mqe_zIaxrlU-JNON| zoV6N3UE8LkRR#N%P>)k+L^ye#)i4%p#l4c%GNBGPie69yyOc2*`&;qSJ!s=UcE)mmu{nqH%MFd!*&~?df3k_d1r(+Dr|{BXB3otMfLq0?Vo{R(|_zm zV`|g~JqMLEf0v@wWjeYqz!^z3{^-@E9_LUWdBL~n!c4=&mtY|~)u*8nJB>9F9Bj}8 z9eOW26!qP2mX8{R*93KdBhvL;UxPJ&MP=WBwGItc=z6QBFK@vgY}SD2W$&OR29np$ zs!M%>UbsWg{WF-mlYDLWCccC-m*ch-N^A1 zS0!O@W6x_)pDRBg*bDnm+nR7RL*AnR6;&X8Sz$%$iQmGe{DJqJGHE|__`dNU`!&M< z&Squ4eNPvFt|;040xi2jF59X;To5{J(Jfo_LGA(J{$Q}Dp0^N~=uHMsesl^uY4`Ev z!l2q-a+HJNe(VM8CDzK3_6ux#Z1!dmxSP9~6t*@i!}ez9%QgMNu4H>y^%1n|2A|In zh4+7~r}5lQY?*=W$^$^j=;Kb3pg^|7{2`!xP_MhzL zAxn*Ap!@re|Aqz!kjsP}*UCaqIN>V0FKW$bcrQN|w_6?*5m;)b0LtF!ib8+fC7r6t&HJ{M;Jz=n@6i}=Xvl%VW5G4X zI`h!V+dl8dfo*rl$laoTp`R$rO=5qo(&weE){7I;^~ zc73E?@`)^AZM&%bWy_~dfP0Hs>Pi#A4~P1mqJe2->S1!pngdemupe7?SYHDiU{79% z7M-XGy*q}C*+iauS>K4eR1?{d6(~0edQLVu^fY;f{T(Q=1m9m7X757Ph0LnaJ?u}` zNtkve5z;&*%v1~R&ajoK)DsVp6|8C+^$u3kRXPg4Tgl#H&91j;Yr}q;9dv^_fX&_( z<%92~N#wGnBeJoR6)v@*4+=URbU>?(aR<ra-_4}vyluB|Pm&!kI0yW2+94dh@6p#} z37+_+Z8sMz?;{N>s`p@vR+5F$K0oI{kB%WXv2R#und9r`!}~E-Dll-Y74-C(63*y^ z-kb_+(21>J&qj5+*}y(ZbN9DJU;+E^wf6GG(APGsd5C^t$45}Vt1-w~iud=($@}Wx zVyCcwShoYT-(j^5Qp>FfRJMbACl|7U9U(8hZ5iy*?910VH?hs$kf+)G7c2$rVP8Bu zDhw5_&+kH2ZcmF}0hX~v%R9Z?pcNd*IM!aP@68(6FWarD^8n?Sk+JM>d+LpB<@+>i zPq>@$f%Ih`v9_0|CE~lrrrJt$h^0?IFEE5Xmu--by)DJ`%&8;Aqc-7Pf4xq>P|%aT&szW8d=~fUf8+&rc)z&+cHhs5Ps8B-5v%uw zI=o}ozi`-_S*LRo^*2Dv8?U^G7P6hJ$?tx08(}}iK4WM7q5UK~@Gtcdw(NG=V*Jix z_q1K;Bi4Bjb?7G%(@5A~ve{kKnV(6qFQh*^rs!BC-WQdSp0NhS*jjPqe)geNeK+p9 z)};ReQgL{ob`8Lo~G4;hb93TD#3M27LZIG7dHRL)NpYH|5H4 z|HrPrMIEQq8Mq1dckD?+hosHWjfW=AiUTJcA$PGuR^JTAz092)zlKa=RSoKYZiV-q zY&SbQCF@KA?6PCq=5GTpyp7z74(}v$-;v&t`G0Xg?pLg~9h~V;eq$H9mf7xry?{Nh z;jj~1S(8j;MZ3H2;C_@%Oq^)46S{fH&5h{nrKH#Bl||T7y01*?`yy@NgDmX(k1Iqu{{4bv{{UF>(Zz94dU zHtdTdu_fIIEdI{RVMp>x<+%&3e1zPmfrLqvb z_3!S*%V5lH_fKf9^0Z?`;L1-A8_}%IB1?)v@i?-|`q(b)*$YVNVFuOMZs!6_OTa!h zB8Ph7dhsaS&jynxLdnOovWjt+5;Ogd)(j%oJ!#aw0&V-0%uNsV!Ctv$Xf~SeMJg1( zjVpz&YhE054V3MzOezP*-E^r!$HEV4xDF~TC*QokTY!D8(EST~&`o?(C3u(BT1~y5 ztztFZX^-C?>UR_FKd=iFb6#VQ7(+&}?d;sKwCA$nZ|97=1@}$t>`v;_tmHfD+pdWp zZ^K<5+mP7(;tuqnZR81dT@v+UR>5}H@VjvLj+I|b9n0>>bGeJ}Di_Ek_6zHLk@oi+ zehF8@-TMe~(MIwzTM$WIFlWCB-c22>9f=-d`$rfxdcy7D31NgXF=v!_|f z6ST*%+5av|*TTI-zx@A9V~+?>kGySdgYREfY`%rQP*V_m1e#1BO-mMsV_&;Mnk`EF zj4dOltnnD{N0Q~E$cWZ!9=N|^E!wEt*`yBcoaHC*&h|W+5Zc{@T^dFzg_CKlqw%hh zPvCu~2{}q^q8;{kadOtv%01Yb?4Ua8<7`1X{A<|Yy+RlMbuXaNZ><>gBrEoZ`YUVy zmwMShvh~*8D|o-TihRp1xJ|u@eZyMap}qQ(?wLCH?k~H#i~2Xa>N9l}tMP?8nUySh z*n!`#XS3Mn?5q-cA9#ga#~x!9V!g-K!}oEl%x3C2tW+HJ@-5^RD-mbBU$%f0v>~nK z;K!)JzUY*WFO$%! zvl73dRYqjb>h6}8&^|XS_cej`J6s;3Hap4vAGJ0&L%T$~|3bxI>gK!x1K7AGYAJtj zt7Ih|@@Z;1?ydU|K9Nt6v^peBM zO$6HDeIwh#&bdzepbAp>1{tX^^b+1b8$&)Xn4{hfow%`e4Jt1s*Mt_ZBZpGQupMm1 zlJ535aOb_0tYt5~o#6Bq_SjBxU|!`x?7EFEkI~Pwe+}*g6V1s_Z0j6qm%;nz;d|Bp zm84D|LJCWf-s~w~_dj^QYTv{6@4z`O-m34xQQtF;qEoNxKSwna>tsKGH(8H`0gJHj zv6B~3N9LIbeT3ce0{M#FATjhZ?yuM{-mPArpzVCfE_SUib*OG+CcdjrBagDCdej-t zZ})b=`-c_eSC!2VuuIg)qA&7;K0`-*B?C)}EU;(CEsjOMv&IWPm119FN7_(Jj7;ps z{Wz=Ks-*h`zZc)7^c8$ALGC+Nc?dhy)1?k|)cqy(4J>D4lJ8bxJMSec*ziw>Lc3wN z`9j9B{fcz+ai2FpeD@D9Vjwv&-9+>!^fs?XQ`A>GH0nPmljHZy(dmIbiM_@e*th!N zew=;1oI1*ZG#VF~jqfK}=faDMz0kF+-eu~PSZhbz|FAcPZGMEUJ)9H{T)gEMw7S8k zax{GwDPu&2v**~fv}-|qaJR?Oz5ib@YaS_@qW|h2^jeEnKf#yq-=jHX1bd!c{(Sfw zd>4E{da#Qcsb4*imlA^a2M3F+P_GnHFqQORl~*oK!1u)eyP+~e1X?eWJj&|Lc4@?Y z{NP{1MZqrC$M^1C?8WOyA3b-G0npO@`kA7E0%SewQ++5B_x`IMcB3k`bqZo&61!MF zzybT`>p=(51$n1x(TON$?F@(oXF)sQWYSJ?RrXhky#l z$bR0HC$K9fyELO}Q^=ic)>P{3+xzUK;Jr9mD;X_vxO)$kRdydZ6wG0D##0M^{x=)< z`|Q*&)TfFL#o#VfLVjl*u2B1L*1d}F-do5=>>I0xKXGrjChb~<{iLBk&#D_M14ca_ zl!_WFwFVCZo7NZE%7LpyKHWiYvwfn}V=nDmJ_`0NtW$t)*=XqNtV$qtkp9D8xHqt~ z45<5ry{E~;o-9h5+!qeSp8J5zW#b=G&vw`E#CLbiI%Ne=eG-}Z!+$0ApbSuxHO8-{8MRRWTDrteUm!A`z3a%YD#|(Y?>P@yTxT%FK zIg~J14_Yyev}I!tQ@>%Yj!<7@-&vj$n+4z5%q6d|X+!2%;C^S_@Lp8QkKE7h^QZP! zFIr&??+@8&8q`C#B}kdTZo$s)f49*L`U0zUceUJX=&EaLP0c~aMH$8DV|Ioubp|_Q zF?BjSdZhk$ypLtyvI|Dhp3jaPP2Jf3RNDgXO*=@5*W~>3{yw;iH@t9|13Lb*m}?0d z-)@ORGue4!*OKPro!8D;R^Y^cHwsY0ap#8Ef)+(BThTF1Rw0YQDb3{A^|2qZ=ZO@p zUINrcJz@A#=)r5q_3SJU>N>VtTWK-gIp~lE zJ*7Lb{VVM6qEFdTJHH9rLC3H{N)sZnz1SIrE4s1M*|#t6v@U~Q&_ounqnfEVu?1|u zQ>zv1;ohAs6Vk24Ru(3=v0ZGaDDA5EABZo9yY1}w2h@5gYb|k~v@ztcBY2WEh@|$3 zCLgh}7E%p(_l7lJoG{V_T4V`X>eD-U6|{BDoetFD{L>k$!7|o9m--s3oJU<6<{ylA zG8;%E(?J)oGuc6A)c))-b81ELQy=io=J*RYcTo2PS@`$tur<&z`&xFO9qhXm8}DG7 zU$NTgfo^$o84X$(`we}@iZ7xLV8_bIYk9(ZP3XrKbWAuI&k7kQ$a}%QQbK7tx}v^x zA9}~@+n}}JA#YN9^3FNf(>_ni@dp308;kC|#qMSWH?LOqf&MW|c$+U+YD7voh8*{U zmQ<2zLjPR0Sn3b%C?cI=TXth#XRn;KiVlF@WElGc-6kSGIS`!t__8m0bM?n|)Ww~w zWUJRur)wvS34(WF9n#CPcX}}NsAc{UVPFhftuW{^_PRMCnc-lYf6Lwtpk)Agp4FJX z@d54zGs#W&E?7iBFSt)$V23@R-hRL;7T?8Jy(vZOSOZt;nD3)?H^Tm!jru`tcPLgyr;}gVWizO+vM2lR z3&lH~yOZ+KAKy}s#eh!TWO)1oxlPa;x01Q+rSmgIV_~<>B|SDgHN`#}LEa6q&5ehy zG5+`t{UMg1vK4&)WSlG7aH|{2b2Cfej_Jf{DGbIjyKbAbTM4Oh9-j_1_uxr^M%NKzMp%?mD ztV#io1dwk1H#T4|NWEZ_3SMI0u#;C>CE@P6icEGTdst^T>eTO>1P{So4ZB*PclHrz z3qi7f_uq9#p{KD^zf&J#4NFtc;QI-7;5BMLcB$=yvFY$WL)?FB2AIw!45sd4CkcdH zI0oBph>ev5d49=|$l_zAFZ%LQ9>YCQRleYTZab&=Ihe3y`Wa|aF28EtYB zd~kcm@>5{uZngdBF2@@W(GxkTIoY7L$4u!n-~slh_R|H}>N?~ews|tO_axgZ=iz;Z z7Mac(_I&t(yTOu~!!ChyhrEa=0F9pqUq)qTTC6Pu{q)I54Xb^Zp+l~38dL-tZcWX< z3Z7mxwF@1$;DY0I@CU2EhZ3xLRp4Fr(wg*F*y_KYEV~V!VkP>h^D6!J;_k3Z>;dX)pDA_+ zT;f2=76+GNN5u^3McY}oP1Ie@ug>0u-DUM?>l!ek;=@1GBzlMYeel3MwPR?p%#B7= zQI@>SPHl9SdjR_gx76Z?U_85Fn^1Nww4I;2%>dF&qtBHp2;Zx&V6fnIOP zjJywm_0S?0$oza#DPrp^+*g>7+ko27AxqhHgG&o=KgK?0XGqeX&d!jce#CBmw(JXj z_l;ftoccMt{sndMiLV+BaMv(h?IdbAgFL||3EXJL{R`_RNWG-tiE|_DWf^{{Xy970 zr>LLjR+AR+q}AU2ZJ?Mn>Box5o;7?6`{YTZ?cRYydJ6aa=cccdKR^ewzp|XieuUne zP4=*NrVkPR3j5oY5#P|5Rb&S{&y`wMbC}jQc#mLPSl8KG=X{5~id{E&+-7VMNz#X{ zWyMb{`-SfkGj;_000Y^2*14wQE$->}$kLaqK(x%>>#tN2T8Ef%l)e z_YHc%q2XR(Xa-v~O|0n`w5A?8F8p=-A80%F3OmQ^!{C3g8?GhCdy{rmSFhuK>a%KI zzb5$o-4{}_sNy~L(^k#r0^puD()!G8SwZOFS%0^qD~-rothzDxpw!#=KKs!Wq5j~} z$K;d4_l>acA0?~PNtZQV5xDn^Tj~xW-=hF;uCgUp!38*U?)4dJTFKJ`XDQE@@kbdbWF8sp$vG- z#aUApyt#@rRqOG@9{er&Bw7}6-+VZD*UW1ZI{4U(sdC_YcFk13v)HL@4XdL|`)c+e z`(LK_9suZ}bs6eFU}JIl7;m20KWV|TYv8=v_ZiFYSw zX?{n=j7UHB30rGSd%6kP``FdT3GR1Ho}%asuI;<$fF>5ND_;S2Ha|P>0#1L}+^`Z{ z@QAcMv_WPS^n@eiE>>c->_XfX+{v7tc~#iby=3Q&4nbGwH zS`F3(Zcj#KgewNRg9fXUucD#uu=}X#a^1%A?yR5xPZPu3}&_Uo)_2K85V=AQSHL*YAR zr}%Z~Hnx-<=S=%nR!C0uNf_KcX}K;L4yq5-{EMDUcMaYEX0Q2^hu-uc7ggPJi-0a< zr|$Gj$Nt9_&KoEk32iQO(ilC%et0!&BX)z4q*fHT;?e9==>Es#8TSqH(a=q z>7RVO+t11=rgULvvJI@^7}{OlPgdUo?@|}NW(-(zciJu`PfkDl7U1-01wc<*lTxy!l-XuZn7L3=<$RnniWV-3`3 zKf#t?nH7uoqf5y*tec#qZZhmYMv$`63;U--O9$C$W}y0CJki|yDzDIm4@uQpvbaJ+ z>^R;naovP2Sob*fBq%j~-BWZYd#~n%RVMW6d*qjtSqa#?ehk(>1zt>;eG!e9j9Huw zeqiOLs7+ps+=Y7b_XLjic+688 z$pM`>>gRqmneAaG$kRTkeNQdE2e5VQl<+FcbFd4Wy2hbJcaDrd56bMFz6xzpTi1Yw zOd!R+4v@)(c9YnkaRHR@oY#y7vuSIo`+1Z1S*yt%BQL_;1vY*v^||ryXXnE%H|)#0 zOW?3qNoUaHGb*pq`mPy z4_MvD)YlH3-iYr?X{6I(vVzs|m|cYL>NjP)uYke3a!;YM1ta%g1>dsPh182;3LfG< zdXm%1GVtuBg96t;ZPc2-3RiopmjA4BNqOYW*Dg2zJ{u zN%^RDs7e>=YI1$zW9-9wUZMxsAzdCNPoV>f1%IGAX9kR^2NfR%4Q>EuREAG~2DaZM z4=&5i#U3?g-g~s}W4p?8FsC5e6+LvBbc`8!6niJz&DzQ=lzjpF7PgpGl;xcjY<#y6 z@2s22eAeyMmhHIrv6Hf>kFwLUsmJJF>E8%<@oX{sfn8)k??Z&_jPUNjgU=h#-|VV~ z)I(E}3ULo*U!_s+Sf(+$33f4ss%5A@J3x`T|GQOtaW8)9QQ8a&ofPav*Rl`T?|w(7 zzJlGspA?-j-5=YBjl1Xj2D{zu#EKTsb>gf;=+@D*D_cPoc~Uw;CbSJ&Zt%QMX#Df` z3GLwYFIAI>5s&W2(`P?xm)$!S}W*-_f|mq`=7Q+Hat@od1!9E(_b!hT2Dv z*I0d14aK*xKV~nAS2+r%^?PMf<73TMe7|wo;|4mRh`eZZWM((?cxzJ3eemKR&;hK}8ftSkjJ?@sb{FsF zR5S_y1aDN5YB$N9?4a%8Cip&NOl}dH$F{MNV`<+oj(o+MD^Z_e9pBCE#_yM3YS-!k zGYU!J%j8;iVNA3)zVDegG7C+cPyQHM(2DISP3q{6sqMvgx1_RPV8|quK6J1aX~M2& zpRp+wj)8q}S9OD&yW>X=_LOCNI#D?Vjq$(1D0ZVFbqgClhPs)x>b$iQ?@Qm2_b#nE zj6J!4w3%~I`VX|RCAo7hd1}aH8{8wL$QCx}Ma?$c8`$HG)B|3UzU*W6D+@9EbJ|9R}m3rzzAp!F}3ck{_P8^UMfp4~9_Co1ub z3}n~(M6VNsUDjnwN`LV0#4%6MyR(|$@^E(vCwtg?b+_C^U>|k6W``&!r*g!20H|RzKx-hF%!-XTu@>8peaZ^e znLQMPJ+jC~SppnZOy^+_W^xr?{F&?xo-E1ysMPPUtU7P%@D?=>xcze4x2>n*8A&LuU592`9g-XBSk z7B6({vGp3sef4JhRUe=$58l-vXPbvxD?*R)ZPyFaoLM`@{^kYp+^tRxg%Oc<3=$jnFTvagoJlVm{%cX8* zKZZ2C!@EtPdB;ZvuD`Xy_;kvfTe$=x1;0!l8%n;vnE2{`ZS^tRqrC( zV{J6mp=HjNjM4ySog+`M19Pa?u}|29;HAs({(#ZvWK_$TJjG_1P>*{wUQ83-rEjWF zodo6%6O_^hGlrA$O^2Y2DExf!)JYP^-}TWck=~DcINQY9?>YYvccY>aWtL#smP@}-Lo1tUbHNj=(^|N}4 zR_z?^%W}wDtXgo1@;tcT!Ilj8oQ9n-kX+$ezFma@LD19cr>f6N|zLw)*!L;&ux=4NkEn||%qPN4O@s6`>30tS<`Msp*Q-iDnZQz$mH97-?4M= zl4<)6=&XXyzalWk6>N$>?1;`xmOknZMh6~V;R6;L=^a9=MIJpxbwtV4>>YOB0NQ)m zO^!sxP41*-tiySI0oFeNrzR z3l<*@G(la`Neu_-tj*AMPGr`r1(sW&#aqZgwx0cawsSMSUq8~76A!NMD_gl0e9jj9 zrXKZ&jA8TH$(0U=@xF)kxJ7OG;pVmk*qdYf1QNj-s{@AUHCdf-^!qSU;8pb{?29d= z?3p#6vE2*~du#)R2I`$az1aI~)Wg~)+;z2&?@0p1bVx&XagV`0+y#}guWScB*?a8# zq31hxz^)}rX0YG0+njd7o_LxZJM(u51@m*$@LuMv8CT8V>Q{bNYePUT)59@42 zeS?jxFsM5X@B7UI7hVEo1f&ZKKv|bI&qC}`arZBSagy75ia>!n<*CKs#f&mPbj{T7 zuTcSA^3>m5<4T~r_TEfIh4+&W*>Ic0sX6B0INTOI)hy~ zih5{kS_s~mvuD}tHrj*Q$p&^-2lWXy_1v_J_`OaJnZo{M-OtlrYU(qg6z;~Ek>3Z2 zx?_J8C+#K3RZos(;C_qMcuGB?j@-pQtEaX*YS4)Hx6{c<8KkXe{qSqB$E_t*rvxs> zE@SPdQkSwyy3_}fO-0J!PHQh|>G0A7`#dY{NFB~Lv6ofDBJs|mD5o1WFCi<2M`e{m z%l=C2s{n7>JDk4(sxK$?E>B!l2_0KRzG2&osa<1k9>(`7_Q61bS+}5vJx&WpBiI(! z<_a#?C{mKpK+hO-JrP&6x%_L`5>Nr8`{F(a>`xs96L0CI*fhEng!C{C>nJJ z@4u$xkF5q1mMz&@1J;f0sz8^#P5g^~V4L1kyIfSBc@OrRtYc(ZFm?s|opp$!y^QUg z<8a}>yBE9E?!*1SbvM&dKlTYb(~tHxwkCl3bden5NY1K4k-l4dKb z?_g)MliaBHu@h};zdeNaFKpss>gLftTD7n*?iBGxWh4WaKLT%_$a;uQJW1yGnu(&If$&zp@?8JGkHRBY4D3`yje1A#KYiu!^lnqRz6Nb{+S$(Y3!(?~5Yq zyFi(UW4Y+9*#_@X4Rdl2`;+yypgnC4Ibv|V%4fKbW+RV_AH{BCz4T0Fzd#$V%IW_V zl>OGa0X4W9S%`|3k{RriYt-k;NV~0aU-8bYM_F7^fxGEoUi={T=r}6fxqC9 zK61gCU*iQ{!Jl(x-yQ0=P!KxoFxkwetWHb9y+CVP73#4|WJ7=O@4T#LA`dcNH{PzsdoAUCsbS&j2=bMXBq>y%5a z61KS$_wDRg);^r}YwTd3L}_Wb^KjZ_D1$E8?;#7G$#EY!43s=i8t0OkY-&h9JA7X! zHtinzg!LIjEhJ7Zefn^~aCl#M)O$8sz^bQH?_pmaqjvNZiNU+&UgVnH0qf+TgC;Ae zjRvLv6uF@@mnROB2j73XwgZ(ZTz&^_w-ebs797!JqO1f)v2AR9g>~3?*z32y%}335 zkk2dbnrT%<=HtiHAvJ7xd!2mk5PEjAh2OD2JC7&o4=#M>s@{u zfO)~B)-vyfM$pm$jh-f;r=+6duy#?ULYNb^+;J2?kZ5D#6-^iWppppqmxHpuNGU>X_ zw$Lfc0WnL!+VP~wr$JY-kA5LX7oGZvturk2%u;aQaB@V8)NAbhXU~nb1Anp3In)(w z;QBev_&)gQ@FB~gE6`K1*V31Rahpl)S37MTpwF>GTc}U63E2~N;`=97 zF{ttmc04P)o_ZVmnVs%__nRZ!U1fVFxobH=@9q1y7WJt(bP64{L$?+E$j0xaR@g;O zv3n@*4DY+`N!zjB%dw?j4k}v#E@&e2*>=&;92eMw?n`x|Q+hVmuLSdZN$-l`(yO4; zZjgoVVg+2GJ6Xr5qA=`A1^3Bo(ELNEQ5|1>Nl!3^t!8!B(f*rNye9R*3+}eCMeNx! z+MVLhsjh{0uLM$jbn8*r9CrAPK{L8He!REYpZmB>r}r}{_Y9z+_XNPWdND&P1j3RG6K-Wv`2Ouu$^ z6F4+sU&3Zk@a<~-IMC52qj3vZ$!c8-Dc%Ylkhifd0W{q$d~z2UbSC8L9&qT+*dhDC zwaewL&cXC1~;m$Ay@s6#HV^-hJmM)p9oa2EEY7;+!`#4@85ck{XAS$60=>M*v6wU|%4 z<4}EtL-3uxG})5vzaM*(|Dak_CV)K0N(E9+eehy)8oZ~vO7)>1R+B5;NtGKdIfr4N zVK;pI5ioKYDG?njeH41Og}e>wk@Zm^9TZuYV2IxEBZFrsg=1%FPB@VPPU^nVgzjUj zeo$-tBqgt{7DUdd*fVNX z-`HW}T9ozq7x^_vV~({EZG$2;L$9IR85IBY7#&O3bVMgF^qv_C@x>uc3>KS7^Nf7d+W} z3N`p5RMrWap378z4{EQm*!BT5_at{tZn=qF`71);BdBL@bqW2d^rj2FG0T3yXK>tr zZ)T|RA+;;$DRxjA_432yHFo{#8$a+)>{pNP7ceqA{m(bBT=3)QUT~Zc`L*BL#6Qr& z&QoPYTi~z%kAq(g1kJQ9_KJb0S+AYLECxYu{NUz31k7by**PC+&tYG&&X@jX;QfvQ za!Gk`n>4ii#Rv&m@RIqYFC##6-_+)jpz-vnqeg+VR-_Lc4W4AhT&VrnC+x?Sv@bmo zF+>sWBTGN1jRo7-RdHKaV^^^nTd0%S)Oc#$tz;UjwqRTaez%hyU+-+91TA*7XCvyz zF8_O5OBwnfo7VPZvkLTz^x}Wk&L2m>JJwZ)orb}vrS!||0^&kV%;{KC(e6L~C9#St% z^{c>Lz+LPwx`wS`Yb&1T>A*hY2AR(GXpB3h3;X2mt1alcgs=9~z<(E==jef%`Q)b) zZUNJw7oQ~M@7{Nr0e$Q1j0H2nv!+AT4L~z9Quc4&ZbRsLo2|Y^;Npd(o$-!?#?Ws} z$pvO)K6|CEVz3FkKl`Wo2i4o{w%!!1WsSS0sG32m$9Ww^V}t!}&j!Ve#DvU2e^zE- zrV;iYkKnJU>`n7b3sA-(V)Puag`ML_U7|e99`}!Ig5g&GxzL_QV+4$1a&?FNF7t*RH->49b;}mgVIB zjm`^~!tVE6v%eiU`vo~-`riWVpZ!w5puPg+hMFmw%b=UtkbU<(v7=XbokYjZ4(?eF zn$(~1a{x#GlU?BmZejzB{c2sI4-XWRa06BQB=uH{r(BH0_H1_t)Wj*Cf9uKA@czdDrsQhjq}^(h+KYVCZw%)o6To{Kf#V zi;X(2DZU=M7S~cN}#v3-HX2hik|VTKnKX=T`mKC*`n-@ zN#)S%4!yU(4*H~#kJy|_yEzrGKUGrwg{sU;etQE{I^~*H3EHur$`+2PhL$G+Z~FtV>HOouhv4M;S(&wtgPW7dwART>o&HntHiDh3jS{tjGAZ~fxBMl% zKa6tP&;p)_CiP>;!E=8W;2y@>&HU5c3N0d>GO7)f={;iJ4sKvyvAG&CA#Y(Xnf+zw zJ8<}k>n88Pd93V7>fwG)k+>h+U*-J)9PIO~vkMej&|&x$lw50P*9~4Y@qF?VlvY}= z_6uCO`d*qqEBwA(dcC?3cxm12CKUdG?NVWI^!Mm!5ipi5U?=>feHZ)nq>AJ~xQm$X z6pywE{Jf5K*9|b10B^MX{v-oNJ{24>3~XgHj~-cqJt&>@XP>f*ZVoUT4)15!A-AYQ z*v8cbzemEm!x%f)(O@~-G1O_hJaoG>nHQj8qyQZ%>RO08-2eRrJ@bGZ@{kN>&-8e_ zQiOK}{n>BEfpM&#VDmU7Xkj7p^xJnK)e;fMH53FZ(ke&wg%6)@_(05nE zS80N6rDSuQ%n@v(c=8n6yD+x_cb7$EC2Jx#Pi7MAJI+NXpr|SJQaMz{@pde zN*CH~H+hGhw1--9{Hz=Jev(xTl*!P8Zt1l#nE{U3xupnQW~ri}58l1u(P;=;ZWA0o z3p~%tBvG4fC(Cz`K6Xb|;@un8dKtCm*y)FHH+}o49_^ZQVw({t^s+&~7+lNtpMLrh z_SS^xJ*MDC);5vaqHI-#1?-vP)6*@%fBS-r=YbJUgEyk5znOhQRZ5yB%?HOUkU52h zpKrIf0;TJ0=2(L>y|!FKpHCh03zh#@qPqZ;-Shbz8qG?os3_au-c{~``hOu6iyYIi zrDK28p`)}%KDGn11AaVP4&L7AJK7o4j3l@E1zD_sZa&yF)de(9A?w-94et_G!9FO0 z3}6j5Qm^#+e9;x&)qKe{e&juN%e16V_@1dpiccr)I&`AkVZXwr-Zp&X0sWUfaEDs- zE}71rtfpR)+#ulz_oMcaqrYUAW9PHyOU!;_&$&Y8u+mqlo7vf=)OB%9dR}m^zlHoW zLM9h`TigY0j1)iK(oJl`eZ`w%ZOaxGc%WxS>@>_>{q zJ<+Mfq_y>rX6%b>X^Z-@b%obq%e_Ov-E0MG?C+R`yL0NT{b6AFA=0q-fMqzePq|JUs=TeH44t=we6!S}@4sC^ zP;Ue5+t{UJsLyPC)QS7{EW?HfP{yx8dLvjnJ;(;V-Em<4W>EVz>Bin+tIa+B;`@xx z5{#kR^Py`II@9f8h# zPBy+E*B)0KdKC8O?6{h3{nDWm*ya`Gq1b}ozJEd`yU9p4EkS)v2JF5*dL_rf_qRoT zPk_T!8x&81rX>;w(cZSOEt%lccG9(jJQ9BXH}0c7FR5gK*QVIGqAsdSw`YSJy1J^+ zVUPMoodq|tt!(1Mu!LOLJ+$WP=YfqnBhu^#N!G#*PvMzyd*z;l9^Gue=bnv?Pz56b-rz9qyXlPy{xy(cLd?ilN&x1gy%z-^a+O$H_Y`$1hxm zeVvNoN7N)bjbGG(?<2_3ugbP#$FjrEI^4$I$eua6^6P8p z_u2=%-hfKKv@_8uc2SidKo54$GU^_7wLP`Wr3IlM;cf%#9n*OcJ9HDdTt;!?CuoUx z+Sy;gAXd7dx($2i#x;sx!Em;TecE49vj_IZ+tZ%@2A!+&;Rme4-+=BU)JJ5$$7FHu(B^@# zTmK?wMK6dM1RcQEvp$<>uVsBKJFno~%(>(g&F_+fp}UiAR-h-At^A9|jOm*p2^w|o z4@OV2^{mr7+AG+@(gLf8z@3nP?Jy~@>!5+~P_R-Xa3dOgF-KkooF*0Z5S2Sn954(# zw`xfadS0#TEh;;K+`ztK=S-wMoNZ?Jeoa&!4&U{%dB!h&<)Me0kddscDfI@nd~(}C z1-P@HLYA@iQ>kY;E{Ioz_ZsES>*(b1q-(Llj4{v&vBm4roMBz>QH$ZEV{qBgvCtlc zX_?BP(IfF|Dxk7VXXONN8~d3ZBhvM0BJ2krBu-QZFTL#NI|=-KGA$dm3z*i9US;E^ z*D7j3ce0lH)H$rPppPTI-|bIo36a0pWMOLi8j*u|H$}aEt~O|_L1wZ86b^*I~vZcEL^q*Uijp*GfGIF<^oFTNCL;hkkn;q;(9mKwLrgl(X zunX_LvdhL(?=RXcG7I*cVlt|PY-i_Qq0VJ>hAk<^`-;|2-Kc6Cxr6mTlc;S3dmY;^ zhq@zF*$4M{otw4B;0HEBsk+Yux?((;`N3V!6uO?(EbbSCJtZdXJSw({R6H$m#0=VE zK)uau@Y>^mr2kxl;T_a9gD{r`VFN>V36zi{IGtmH&0 zNu6?j|9qX_zlsy5b54X4A!JU3M(ku*h@Cjq$=FVtUz^McvxeD;-V-t>JJkuB)BI}l zW2gB(U!T|O`^PTV%kBPnb}s(fWmA_+-@>i>5pjEd3xxyP^{lT6Hqt;^#fP1B`AgW8 zo}w%WcnCGp9l;BQg zC0Svus5$o*PgH@%HM|$Y?m&%dM4Gbvz;1XyaHA+k4fNFpY=r%GXK<4SXp=NNf}I%3 zVC4fJq5cqZ`BVYu_%Vnd?&SO6p1AZ=!yyNpNGA4a>epOAn{AY z)FqfsJ?Nj#^*M~dA;T`}QXuBdrL(X^)u&5}fxk~pYJ?Tw5JLkq{#g$CkJIjtOMnMC z6NX_45iOZ3fr9~O^{ap%k3i%WZjUMj-GW+>I8_F>0h83c26zJ%*WK=c`{Q9pb~zAN z_0+u)s3RXZSOIJj1$?|2s2JVw=N8~HUd798z;~!s6JnFMgI2lE6vOI{i|nwX(x<<} zW@c@lQU#opyo>!Y@LW>xnO(rVWW>OS4!Q+&G3qVU`;FWRc&9cY{v8mTQUm&`>&yz+ zgbu`}1EMeBo_YvzJ8Hn9r+x5Vh5Az=(mRIY7VH80PG{=@SXmpQ_!8o`s8cQ@eI{-f z?^Ez@`D0=gY$xibhW0=9f}YrjxDoXc>f$D3r`(*?y$`(Ghx!Kf(_fI?u((LFAKVAy z13rPRuIkMB47hIny`{Cl$r#M~mCAJ<`>v-@f0o?g+R~{ui+lb$|Qx)9}70Z*k)1z;@J+2=5JW zLuAAq-_3dmw-1$dV$P^~&}-Lr(qJE;&M!l{8#QMg(v7G%>IyUb{$tcp!!ku6OsL5 z6k`AJGpifGyOu8yJ*eyxNGFWmPHF`A8r0Kz#eKMA42W4j5O+6$j;&~aZU?U9E}qd0 zeB4vp2zz4X%}K|B-~2P`;upZ=H;DUD*I%;z1MhCs@apW;6QI|icBAI(LiUaFdnNEa z{`7I&N#G?^;u)kn&mxLHqHE#%S=87~NRwIaL-4+9+=e@_&rwwoNI$SU1Yd$Zw;9on zy2HfX0q?|Bh}EdU8GS#%y9qUOF4A3-|B7k>d)5@hW2nopNRN3^Erahl;Y0Jk1~#Hz z+&`=L8_*M_ot)D^O?md5Gr;Gls*OlLWZo-<_x#Y+4%o}6)%U`l!ku#TIPom-AnL!U z_`l2n--6wAF@_5JMaW;V=Yg~_h&iE%t5LuGwOR?^C*MJ=L>)klvJ&^g_g>Vll>E`H zprhZvX25=pdZ~TSX1I6#g!t3m>EFYx**4320hsvvhlAe(Yfv+CJNXwuht0aT)(Nz{ zE&T>I$br=#$^uv8Tjz)>IJ_5`LB$Hw}86)rQdb}n_JCe?f^xeCvRZG z+FuLr0q>(ye?s~yYT`AdYfwjBM|#7)Jv-sA>p@M)oBku*2T}c~h55+-4)y8+q(>9l z|AXIqQ7c;Ct-BApA9d3Oq8v#4`o z9)SA+RB{f|%Yr-Q@Gicyd=IP}mHzptoBy}hBVI*)IWwF78+dm(1=0KVt{Lu)?-3uN z;=f(r_YmyZ^N43rXKx-q)eZLCp59K_^~cSa9^gaNwO=6JjhcG`>3gVmSI6++_a$o) zr)Hhm4)>I7#P4ztmj{V1!~1R2Iirv+3Pv1z`^kIw?n0#<-j?wQbTew$5u{h6Uf0L1 zf$ud2L}d};#VdoP-@*Q9+NJxjEF9viiaonMpxZVheiP9?q8D_adr=PTgdRj=^Sg4m ze@2~k9O-wcrl6ZM`oKMN6yj0Toi5{2cu%^8IOgz&Mz~j@cA@^EJMswLC54DT>Jg_K z5byncTh$NlrZo2O?fZZNAxi2j0VeK`ceRi+bIK?1Q!D zaZkWIQsS8%u)9%vUPD*mju=8biz@sZ>F3TT!|+|%h8VtU+q|cs+fEH8`~ftSR~ul} zY~nH4%VRJ72D^J4;)m|M=s!UZnD*4b3QG|CQRP1`qCErqdDQQJL3*{e_B_02FG37X zob?*+PSgc$#^pZHS5R}SJ~YE^6Cde?4VED0Oqvrn2%6Y;I}i3|KVq#H@jYr`%kog>o z5VxYPeTek`OzZ!G?{iBKZ==pxiS+Tz@kv489ySjV3UCy`eIXDr<0hv8ZYyfC3+dlb zX@8&obQHKBM^!taU*Nuo8YJJw2nJ2`p1%P55xd$n8rXWTtsnO1moxoifW}vdc<0Y^ zLqYFEm9-%qIQht*|F@%lkDBgHj}L=CX8@7wxLpW$7i!~%<@Io5!)%cl;J2v9pMO<6 z7BuDs;%BWKJKS9o^OSKwd31~h_D28d{jfKW$=^l*ul&^Zcswxv8sa75p2HJBk0&Fp zM?Hy};7hy<-%kqO?VJeA$o+6S5@Tyvd+VsQ*KC)yV&a_pelg z8B>7c)rg;?j?f^z1T|%I9vKVX9YpFCd(?%mR#SlYqRpgaAU6haODtmlm#066_wc3i5wn2L|J_**yNdXF zNeVEFgxLJNrV(!9cZrW+t5I?1k^Z{!$4RrnzPj`9KdHcbs5|Z;eW~bnNgCK6<=s7$ z4rJvco{;JyI$3hL@0bHZG(-$R}Kzi0#8D-6(YuM-mu4VxUTsREgZ(R1)@!7{M2#3i`cC=zUl`!sv5kl~!Uq{l z(6JXk`;`rR<2dZ+06%R(970|2HPTet?X_HRpWbjRo(GIsmZgU!+z5^018==t7bpNO zitc?0tBpatin=?*SSNo zdrF$s1z`U#gSH=b)I3Ce;KL5M51`&aJ$!TBm_=X@JrKc$6((_`7ia7hZb zxf(bx4Kb=+hTR4F_iKo(>xe?1GjuoDrw$@kp*}|q`KqAw6L4RNIutyUXaSu+8c{y; z@c0_gt*BFHA-x^-4^(jqvY$hJg1TikvJar9yiF6qpLYWHK++bq;1p)im*oKe{Y}2yqu%)Q?Pze#oa_hhzH6C#j>f-XpX;!emK|OZ=yT@?X%-MOk z9;o<$zYE)nda_mn9R(ejQ1c^fxA^VpW55^v$MY+KSyNLGRLs)|C)}997!WGMI z!X8Tv3T^}jr6Ddyy^T6D9odWKAa3y=rNi$BP%YQzRlr@pzpE8CnjD(a1azV*u%hb`|%^A@0EX4DuM-E=4odtW8+;IFH(2UxP z8mmP1OHK2(e+TZX?1){cLQ~fzc)vd)G~+z**UMji-U^iNVBd%R7Ih-{SK0;88y_Q< z*uH!IJ?Oa&h};i58ZUx=^1|YB0)t*59{)Zeqz&{LS-}?Al-Rf5!yZDtiTYRQf8I-A zKN5!6ftrRv`Y`H(yLGtB@aJ7SD!2mNdL8jG>c$&LPy8A2`@Qpa!0+(;5U;%$Gw%n` zGhQNovu*w*igZSO@|+uBKaF|@`~vTvL7&UN zbp$pQx9lEl9V&b4yj?dzuZ~<5@C)$MHS^EH5^jxK;sUVlg)zJm9KwfHBnuTk4yzdZaKX!`e-yRdlg zn;#zn6E`GhyMb3w6~o2u9?*+_4vc*S4BvZH0UJl^x(O>q#gdUuy)cIHJJ=7Q4x_IB z9@(dSY_EXtTTvgQwx$Tf`@r7%et-x2Fz>s6Va54~F$CG%e$eGa#DgTnZDhnm-?KIF zy$1C)>Q~?G_!{1itVxI*0B)UsRRSB>`Q{qz%p?0pJ_cSxpuI{&ccA^gsc zdLNabONe<6_Va~^-|7*k7!d!XT$RK3v?1*tSgW~i)=S_BcG?QqMI6NasP9l0bCJCr zwQB6G zdP}%);y=Iv)T#Fe#BdWDDtE)$nh?`|c~<@gboBlm=U|!f&KYlkCsD^HAYF#~Ng~q3 z>4+a*sh7gX?*njtHWSt#Ug$(D5Z@U z0Dqpp5KB(HY#s@EQf@+AAdqF;9~K1cL z83y*OFP?3Nty{I@d)VWv5iy5ep1^>{zfbGX*9@0FPuG)x(CYsQfGv zxB)eB&Xn75_huj-n2RV{yrV4&>}OC@;_>g`evkUe>x=2pptHYMm%?roTb{ti$Pg<~ zBfrrei2?h1=Kk@qKs+W{1S_=Z+hI?m4xkDfko^qmW7MMJ;SccpUrBD!ZBls-=+dYiKf~fqUZmv$f2Y1Y z533n%c@1k0K}HUZTHgux#eBqL&kk|v zpx1BixCFcLNbY?m(1FVS9O;+IWnvcC|GskaC)kBQAYMV;copeC>n<{R;4VFk`22Ew zDj#&r)Hhz(fG7KK0$?FWe+M@CVCE?Z_!;VZ)S?+H6GUK-cQze`4ceLe8|<0~k>@4A zH_HVxrSQK0TdWKiQ;Rreu{00vfR^|<3gEO2Ka|2&W8OT0jU4umR{__5oOxCaG)eCK z1-oj}$|MbNO@GJ|*aa<34X~UIxjnE$U1Rs=0slRE@)uZsuKHswaNLjk;uis1CKdI+Xv+B(prUPKLQ8|v8H+{f^}4D|tO?tEldhdscr z2lw4~))v5K9~*lZ)_!f{&J957b;RBaTTYjQUR*hO5cb7dT+BznHTjekX5f8P2LAeS zxW6DEE_5%&YzDmt^;uTtWw`&LY*SQsJ5*#=ymn0d7tcpG)jbfk}INr2%0I{f0F%{5?;Dc(0{FR%hN zDj=$^Y9#y*C91V{L{vmna8xihBOo#4|G$V0q1#-4Kl&f|JMZxU0RdyT1keI-0hoXw z+6Y|$HXwvH(iT7oz|aCc0n~s9S`cmo6c9-pr5m9Qh@}PFMwkMyw9%ds<^UWm1UJ$W zK%$M&jkE?N(n4(`9RUtS!(NK&6fI1o{JLvIf+<5;qDOp`=CWMrlXn(V}gmOe3_k7|$s42pugJ z7i<|}q)pNVTSpYrCfkA?BTTd@o?z#QQW_RF+BKq#7N;BS9#Kx4Y8&kvVWv&v@(c*1mOe3wd1kV`r zNE1q=Q#1-L%r){HEm;@l9@$EpX$$j>bkb&d z!u%tz&{A+1Okg{0whn_0yg^H~VJLwvTABw#4eX?)lj+4=ocn))MHY&C`vw20o=_*~U5oeY9-PSZCl18WlIr6*xr8(T#HlzNO{b#`yyM zwE3QK{=fh_4Htn43Zm0>5!j#*I>Q!03Bu5so(O7C1f7K&4+TZi*}C!CpjbM`Hr^D3 zrE@*w%|SRi4>!RQM56O`6Rbgrbb)PxBZxv5dL}r7Qs@wFqAMt!F49eO2W8U5wu!zV zDqZ54=ntaNrMO7UC>C9&i^PuN(dD*C$|#7g@I+EaN$E;l6f{anSLvd(qw?r#Ta;;( zmag$cnMdj9dAMlHC?h>z7i}F?OkZG&c8oI77kZ+dqe|&oT#Rc}8NEOk;~rH`Uu28% zjWW|0dt&^fD(O00EGD>$UZ{)323OPdwpdEAg>LY~QiJ!>jkrlra4o$^H%S{@M_*!_ zWD2&@mwG0dgKhL;++<6zoxV&r*&2L;zT7t15$vF^@Jx0FpQ4*^Q(VF4=q0)-?%-DX zO4}4)u#>*ZGsPc#gKN^#Z}Loaj($NmYCmHYAp@!-hA7U>Q3-cykDjQH>*5LP(5VI)XJMk+IuGaD-48pLht)kQ9amM|6dx zGir21cSt5h5? z2^j};WbK$d#z7m|G)BufBhOgZDIEx|X&%sA#r@QxM&?-iQE)g4A&1keGQbH|^CQl+YbT7k> zn+}E6GMaVMwV`#4@DMxZI&<0&$#TF2c zwoJ-c3$x#oNgcbF>BY^1#?~?ibn~=h>zI#i^Gsu{%qO0C=CL;BQ(Ts1teyFXF3URh z1oKZ@mSe1g`OK5$9D9oC!)3e1o?{N`vfX1_nSa@`ePf->=bmi;*elEzI4WjbJM*QE ziXC@@`N~G6jB_zxd#KcLoy;Lz4m7Td`L`}dJFc7gk1fYE&dq$|$uW=fFyG>GE#th* zce-5bxTnnbwp_=u$ zGb|A#)|f(uH6oD}+Q4u`P*`ET3}-|N3xj96BGOsmg-mxuCTna1(-%Qyjq7FlBWSD$ zJPR|P#TsA8!j9*$CN!`p<000>UKVw{log3*L*tdKs6w`Od>$*hfo&SEWySQe&Es{f zSUkrv-pHC%$gz$uW=(G3IL4b;Q+heh@ue&*p6eQ4#)>QCy2qEZrZ#YWx2`mqy~Xwf`c`qSKyp*ibcT-T@%i+k_(0I39YP|4MN`pCu>%( z&_Ce{D+Lc>CbqL?7ed&HH(03+5M`o^mDUSUCw8*Z@gitq7i&(TNIS8cmC+zFO?0#7 z_KM6CJ*-T;*fP<}npY^cPJGJBY7jdn`dHb$V&}vcEGk~&nmEMDDU`S;zGdY$NPH9h ztogkX|HJ?`4KKw+2C?adQfy=ho6#VpL}J*?UMV#)g3ZFqpvXuzyHKW$jAe5gWTr?g zo7*chN8;E#yxbB=V)F~-*2qM*ph514q_Bm(a%W@;8^SAGk?Cwvp~4-R$rd*#e34YP zq*vjOq_L%VB_@i+mK7?oQ9QQ1K}m^%*os~yHA>1>;#E+TlC3IKX`}Mk>IRi5O3T*t zs?1S3b{<}Bi88YD3)R-BV)lXtwIj;JUf8R4MwPO)c#SKnj9pNuaYvQ27d2>nQD*ky zUX4GhlC8t%VWO+pg@t+8=xVmUA&(MmVHy)XdAm2zrYf0XD=&UV2wV(Uf!_45$#~F=w0B9KE*cS7rLU)u}caUx}#g!D;pO2 zqMhtjy$k)(SJI)1alqxY%oZwbYnSb{W0^is@pnD=g5)bhFnt z6qsV%>86fSnh zyk&20SnP}Ov$ymv_QwQpD)Bl@Y!GK_p$;1x!r9iKqr_r3+k17?*a%J)z7UFy}V)7#bP--dkf96I8HTQZ;2&wb`|Qav5B1B4SGi`h4V?T-Wi+1vEU7^*mO=! zp}`%S$=TCj@WoO&pY|I3u{6$Jyb&{r#o1SA#7^RI_BR+QlOWD#y+-OJDW?`+1Wi(M z4ipw?C*^StHWZmAX*q{_i_DXBoI3mx%OoS`aN!c`q+-sIh9!qEGr5Y>P*{weT+L~0D5gxdaGH9Hsgw6| z?D%ES6ACr4%fN`(tk@6&t~A$FGL4k=&mOS8K7c+-nW1O;{}Vdhcp87RSATUt__NxIY)J zv0@XsHyhSCuoUhuy=$D<6s`-u)`d;yb`-94V>7w88rJ%-RPOEGwSFv(+lep3#Id;l zD=fpt@wmS>lu_a!?w#H;YMhkYg-m0SGDjpnH~ z?o<3nmZ^5`AB7)Tr=H;c+3=BLs)PHi_ao=jQ(PZ@lWXcZ?qK02_taMIUk#glQ=Q!B zy_@_~uW(=B&6sKJ+?R!B?6e!)R}E&$G#B@EubDcnlRJd3fTneE|1PZ1PV46W(@ec!OzG0n&Qw|BF1+6%59zr{6eh&x=k#XapU z_rHcMzG;5$hu$szX#uH?I-)6-n@1$E`^67Y;R?x80AU@gfLS7(9zNUSEa9^LP^)t0;JgH?gmZikI>t2_HjvB`-?< zu@;}li*EebgxB(7`aU+}b-Y-@4h!DMo21`i#TWA?H|}uYO}r_6JDm7Z9+t4vg)ig9 z>36#E<-DnlJAHUFZ(83@KfaQOBUEDuRXn`D8cV3=5gMy01PhPYS4}1C<&g-xAVMvV ztly<2)bZjQcbN!QUP9k4Gr`77B9KA6cUEd?AuEvMetdK zeGn;<&(`nLl4ALs#(gFdme1|mXC~qJJi>kpiNxpY_ghJcd_m)W2Z_QL_U(6)Quq+z zGZ!hHFVcVJCS~%)ji32QRKBF|Ge3#OmlA3*WENkhuf>vie0gIng$(f(eYI4wl&>Tl zfXGU|N`F90&f}{a517bWzNYVhnXKdI5e{0&Mt;8jpp{(AU(k5aK{oLh_8oMROZi&D zAs4xfU!XtaCYSRUH6HSj&HTlEhy3J9zK&3biLc@p>g%xa)qH(p9VOnvH}us}yKNf z7YmLw9(PPP2|n*T?wnpKuoAv-O)nGF>%VYMFBcqb{K7ZgEI8Kpg@1abz(zQMNvaYw z=ucpiss)XWCn!l4K~vueYSLbTop2ILsueWrPim9u1jidsnv$%7FZxcJlWc+$gfA^g zcEL&gm)4{cf-f7tbR;nI-(6{v0-$C;YYX93>eN-sw9>O_mC~2;V}(5j%1VYVc&Por`H zf`J12uTWDWpdjK8P)Z~;%J73WB^C;9`oWZfg+}-PU{1k7A;hbe6!85t!&PfaA{5$m z)saGh!uqc|Q&J!d@kdumIuvgB(VdbBjcxkTmqLZc_5bKkp+OPEcFb%RG~UpToy~(L zG__M^L(s(jcIs>?6iNIEnyrMQ3_odS=Rwg;KbdB0p_u-k%(Hb+Eb*FUwh@|SxMrPQ z3{7sj=9q1Qru1KP&Mt+p#OtovWl)^qx_fpxG_~ovZ?+kl)_>hUyAr|?Z(vfZAiUuQ zHnkceG~J-2S|DQo4QlFMh(!DuO09*+hM%>mbx?fM&!$u>l+gdPIn@Rw5^q{k?a*|? zO>622D5>eDBh>-T=)dVqJq1ySzqnG*LCJ<++^Mb5%%)#_sZMBC|1bX3D^Lp2g-L6N zW*c1Cv>Q-rlZ%q(g3|h3)U-}0o!9}TbwP6s9on>RD5I&vl;(!!_IH@mJWwX_mL<&# z%`@DxragtSnr=DLd{B1(Eoa&bh)TTeN*jW547c5BZ=u|#+rBhEG{670KP^B+BX(la zgG6*gCpJAq#AxcIq+>+P{!VIogos7_ACw*`VjKRaO^+3En*L`>$BMZ9|1+oKL_FfJ zmUNPcZ}`=ko+uJD{pv`kh=l#WI@41`5b=&HJzXR++;OL8io{KKeCbq?r2mdTohFhJ zyD)QDBAKBJJBKHdH+50wKq5td7j=$Qq$J*j<|suf!(Hv1JdwKTu4#@|r0KtFo}&}x z5${>%7)AMpd)7I{q6JO&9CJ*fh5h%Ob4o>8;(gbgGEsryzI#r&Xi?LB-yE}OasPe) zoJx_7*p11k5)~S{u^H7OeN#6j!y+>DcT+R=ij2euP)4n&$nZd$Q72l`^uUy16)o+5 zV9v0Kiiy8jGVG#dhTp6iCq&Deesg3vL@WA#b7q_pnTQWv8RtYLhKKHqR?*6)hrSG_ zXjT71f5sJ2DbbCY+b&vdaAW6gxglE9mo86@6n@L)4T#M_!YluV3xd%uU886mDB_ClGF;*Slz z+RRw-j;3ByCRV(&zt^0J6IT=aESV(nE<>L+Gf}*|sn3x~5r5L(=gdqITZsLx%ye;$ zq2HaEDc;l6@5`i$Kke`LXVS!biC)Y+mUy4Ri=D?4?{D%_=0W1m`n}Y7QgJPD0Gg*1 zA21AP=jDkHHVv5OX~l>72h8(y;yU7E%RHm_u;H4|TiS$wSjiGNO{>PbpazaZ~?OYSvz{ zo%jcoRV!{b{GrXN6CZE-!<1zef6@PkIm;$KLHyH_Wfz|`{AtZPA^x)IPe+zR{8j&- z&a6{n2l1IJ>zug7@XVdnD*n3ZnJ>#J{-*z#KkJJ46w!ytZWo_6_^{bG#Alj(lx&yy zY`>41-6=jt9E7sF#NQeQwb|X`@0tcp*>3Uq{y}rLN8C#M%aZLCUoiY-&3-EWzUePV zwoiPq|1W3u3$c^<+?72fZZkZ0XTKF+YI^R=_KPp~Klf(`NUjiHV5mWo9}F+B)DX$l zrWX_{M)G6-3o122(oTE{Q6nWk8D46sv65>|FHKaeLYrXdRWt-5#mhp0JHNf+^NC`T!|YxrB6lP9^?^tUNTE4knQw>d{A=_dYT$uUYE z82+*56ia?<`p1!Dl05AH$C*^t=8nH@+OR?UI)UKX(2N$*U$mWxh-Dy5CQo-zga)4ny<1B!3%*we!0r|1=Go=DQ_t z`iIT)J(9P?|19&pl6Qvxtn;5r-Z%Z{nD3MP+y9?){tJnp_`x-QNHT2r;GX|h@?X;j z-+aI1L;nZ=`~YbHDIlB{BpqQ4h@*u_N7@6DX&7msHz0==Aq^sp5YZx~ql_a8XtB~@ z`-l=6Ryx`{qJoB#hLA?q&`8oT#*y{3L}{pfWDAWV4fBp{qoqhOq`(eZx-{Gv*h9;d zjgWKq(QY>k72fa)hXB^!_ zFPBcWj~=9(rPI8lhv}7494RE6Q6S zFzTf7_Aw<4t2Dtorh;LUCXzyH7+QM*1XLv)~7^kEZQdkG$oHW@O z*28F(&a{UOGMv&`-mqcD6=@0y6V7ax&NgD=m^Y-Uc1$wUB~9~Ua+sacbW*s8*(IH0 z3@>1IOEc`@B}}(;t~b1b>5*oV#?~;s(s{hA}PbRlVCbJ=#!W)^xmdcc*C=pvJ zQyHTQ*m*LwJ*tGQm1(?D6>Oa>j}%?QHp=pi(e>`H=#6e;m&&xHm=1QC ztiTx4!!DOCvd0Xv&9cSbm|=FMOh<|h=TylGjj?f@YMI_1o6NDu4Bprr&R&_3G)cs% zl@%E$6>#cgOYD25(#i*CQ(@O|9X2WgCrC>$y*5AK9n2aDB2(-l=We z7cw(xS_gMXR$-jh!+k5;Y@asB^~<(+rwwxh@UZfoUVH@)C$A&tS z-^MSMTS*BW{4#mHF`%_5+z*NE;?~H%O^9;5T3WY)q|( z5*0V?sVxvi@ryUL4N6hCNNF8Vx}w9F)&pfKZrRfYA*$lGH*FZADLP5%;Ubpef5!AU z5l``}Jv~_jDeidFb3{@_7io@2q*UBB&M6S(Del?ll!&y7``$SfBAud}lu;uxDjpa! z>P5wh-|QJJB9r2wH=|8ds&JF$c8JOpJ;u2`qH@I}``kg1S@FAf?y#s*;UQ&)i>nm9 z#>_ZzwW80SnJl&_`n{Ps;=KwlX`V=2s~9lOD-hQy9^2=Yh^>kz-gy;bo8l=ct43^B z{9(+h7oSl4Y0qjAI~32nS#9DirxZR?c8B#L_W6Snzv6>;{;(uK z89=6mOM{dnifD1t5aq~bTCx={4NF$U%WV%QisT@^AFObG6gPZ9kQmk_H0KGzr zQ-+WkHByptOcA4Any3tIX0%8t%CG@On>0mB{gTW{)&eIkuTOD5WaL4KRnL zG-U*t6)s~b#}~2UWIW}BW>&HcQcfIT<;bMUNHSX_Q!1m1*afmYWpp#UM5a~746rL? zI%O=GQzJ7fClzt(WyQ+L&72mQ3H&@Kr%hI>#FDukvNB~{5w}NHuAJJ;9h8}s(+0T1 zvPvb6%nO%SDe*cPM8J2-@VQloYbCLw-(~TqNv~w<>2g3kT&+<*WhW zu>6WLg$#u&+Lg15pg6@1Wok2&tZ*sQ2A~{8r!t)^5-GZrbBaU-if&~_v#3PjR?Zy| zRVX~lOtQE};Z@En64xu9Dzlo!EefA9dqCW#c%h_{B^`<(WloW#NAXsf+bkJW_?7bq zB*TgT6^$$nR|cu*MbbEBh>FoHO;%!5%mHbRGD5{7%S6gZ6}w1Qpo~>eqDWsXX!Qj%37l~ScDQWdE3RO)6`iAt-|45%tp zI#nK7U86Fp@{823=~voJgRc?q8g1?wXtYXz2>Rvqvk~|8lP&@z@j$I3zeC?xI;6fswi6Aqj{^^ z+`M>D<5z7NSUju=P*;+5;dw#otwp-Hyb$%aW?ga~M!kJNmy;Kvt|AwT@*>qA7Zn!d z#j1BS7nbB<)jJ0YEAnvaYO=m2kEGsJq_59QRPS!qx8zaOpA6{R@>0|mvY{g{U0qXT z=*i1e?`bv+=26w34j6{>XzIOWV|YGGy|2g^m(Nr0Z#E|9L+Z~4j5+yIbuGC_l&@4D zC@Lz*&r=_4E-J~_st*kmRpjf`b>t;A`9}5Oq9yhD#p)x?OIq?x>dyz3wB?tot>mR0 z`DN<*qNP3gSF^-hx04dHga+Jf+}@GQE}XYYIS3Caqnw5(u3o%(q5vXTW>^%n!nDi+w(C&TZ&fnENE4K-MnIOfm8j>z>47oSJbD-rtpRB>eEH0xP>>=XPQmP z3tj571E!pXo$7Ps64Amg^|wVO1q-{?-!+$%EOe{S50q3a^r&0OD{B^d)fb9Z)-Qaj z{=Ru-%R-;};=szbg)h`j@~V!7L+ZAoRXq#esxLLK8eHgCUmjRByf8p>gOn z7GA*8{I94iu7IccwYe<00MgtUD9b63YP!hlLnaL# znr`y?ngXNdLDBm9f?~~Y&FfnVOqz!S>)Q%SHE!~Tj)F2xPtk^+f^yBH<_&`dX3g&d z8-@!iH6C(#_@XLJZ&7*NqH0ZFb9wS2i>7~|JZI5fjhDPpw5V1yP_(gNQJv;-^Tv`z zR?U-vjTMWw*fdYcAJr_fYyK$usD9B2&7aL5wJdUIo(+7|w&;|`N8Z%2=$vM-Xj9Lk zR?T0{n+6v-HO~h&4KKQ)c|kUZFK*YoEHcL}zM*;5Y))S6(!3rp=Pd5j43R5Di@P*` z7gZE2?$-R%Tv4*vt$8z0QL)&gc}w10v)HS7SG2i)@l(zF=FKgOeVTsR(bS^QS>U-Op1#eU6)fi1&}1M&jmE5mg`c_Wro#_2-xMjo$B)?xAjA6Mq+ zBJzUbw~BO;d83wWEzrg01s~s9qQmBme!R6phsz6z-&Ug|<&9agtzMUy7kYeKi;j{P z_IO*HE+r2W|Nr{B_PEIA_usCp&?Hn^nuPYuiKcCLTiVs6cC*{kBx^C3bIzPw=bWjT zX}Vu$YPZ{Tndyp937I)j2_aNM2u(r=m5`YeO+pBj-%Pvvb^CsQpVyqv>+{^-pXYhz z&-0v8D;go;QKhqJq{Pcy>Oi9;7uiZT&=`p~P{zaJBo|XOsDmSnaNf2P*;boGmC<7liNUk;;gm|sw8k<3c*Gqzd zDly(H*+o^sc#8xuSE=zhC6R#1NGwPWP^LD5lN>agdWa>-jW*K|u_B2A>a4`7 zL`2oi5^IuZbDe`&m)vBl+aTPeF+e?!beG0b^?cGpddOTaBt4~vZS^A3TN(#6h)Eym z%~S(S`b&?P8`NZg^r)>tM+Qmbfkq=4EImdwwvnLp7IR|{87jTi);L6lOA~-5D;Xgb zQ%$pEq%_goc{k2v{+ z^iJv?I9VdS%Y2VI8Is;@yGNIdN+rO(#$-||rS5G@W~4Iny*ZK%bznE&4 zCR6vrRB?-xGT*PJTBWq@ejU{zWq=2aRHsx)J`(}c*MvA%c`hH+89t)ZGNPO36<5@9vNc7WwpSgRwhDb zq#m7RB4sA?qYfrYR%d&3gNc#V1D!l&oUDQBl7)IWX-^1V&w_h zJ=9~cQX;$8{Fqt^$?mf~rcU47KgG(_K?l8p)8Sg04y)1O!hFv@>2}5N6f4+rB?Q+jTNQT%Q}HBaf)*! z0@Velw8+fnE_F()%wp@(rF6(x;BjM0r>u*5ye);5J#K!yC#75VgzfR6ls;KE@Psv` zU)DoCF`F_V>oq^&NEwtpX?tQLWkl8obn{Y2WlvGv{M0eo)8=kr>bUF~Tem26Qq~Xj zh*PIz&r&^b>a^@RbB{W8M)tg|N0&M;8vuHZsSC0fsNS|zPWGa?wf1P>?R{6`{Fh8YM1<2pDJ*86x$;W`FjjCYzTh!BSDp3Bm`RN{2sQew< z(?hCo`8e>5RTUw(QqRn)BIOh2XB?_1`Mb7fHdHb4NuZynj+4Jf_4C#7^7qaCLUn@t z16#jHog|+Eo)xQ4$Umf>h1C-IN9JeMYDoUE?OB}~l}`iD8P%lx6Y9A(H6#Dj{9KP( zCI8I!+>lx;p8=k?s4Rwip9vI+h%H&^A1AL7^{-t?9 zsHv5IWg8G_itFVIzzbqcv;1r71z6J}x0zp1Yg*-Y+Y35PhnxdmG-^8Ki`0v48dm;| z`NbYhxBOe%i$j_|`4aGwRnsqbP%q7D2IR};mmHcw`FFOLHZ&vh6=0B;HY)#~8sw*q z$$u~p3e(2rKiURGX_N9*U`U)cCI5*Ug43quKbwctX*2R)Y(u)VdHEVJY)o5_|4I$F zrE&7#%)>otOY+}s!$WB+@^#>4Yuc)OgL-*3ZB4#ue%X<>F8{;!@K3hvgNuHUK)${)$c;1bGNvHEM&Q z^XXUHv>*DkikT3l@oGyX$-Fl@)x{e zOedk8^c!vI40O5Wjh=KBbcOwmp>!=2Ab8W7o(1vgH)qrHpg_x;j`SkvO8c7|=_OE* zV2qbh2354+RU}5@$3+yXd#zj1~y6yrs@)g#`AubQv8G zD0thL(FujnZ?|Qz(6yGgdosGA>+Ek2W%NOzf_JPL{g9A;XEtL13bVZ9$QXon+uzy9 z7=gkCN$dYDF2D??4 zIS)k&CXAU2&;fd)Et7)|S|)ljm!KQ%6GNFRP?X?ZYvw8>qTij(T!W%5?>aKqp_}aQ zZe+T_F@i~6mOC6vPx7-o;6s*4VU{O+*gh%B@`mFC?}@W~;G609;4FXmh~+(XRsej| z{+=!?2#y!LZ_EmYkJ0b9Wr6T5miK$ILg8EO?+;~#!wG^9tXUDTnEqfkD-uq$eBj86 zf^V~bu#pu5Ckdu_*>Ujg^b|ik9zJfF5@sjBci5*y*-7vT!H44P6Y!n%hj6w8zRU8V zIvaxTwtuM0Mq!EIBV#rROX-i=vKd%r`KTvb1WI}3*Ck7u*vV9N4| zI;Rz;?Vsp!I$%cdsWGP$R??rg<*;yy<|Gb4O0n^ZYyyVcj=R^hdNT*;?T+oa>MlZqz zEr{8&s4i$lEcQiRK?lMLzA+YbB3<-1Z3QgyxaFIkf^Osq`!_=ceMq<9TWdi-(nEhc zTQGq1TE2A@3?fh3zuhPpLHYzsyuwlBDSC-tIEFlJSrQhGBhT2EM1_+`zrZ0boI;+Z z9dO|^@|?w?E}TK0w>xx&^T>c;*;u%Myg)Cv6>`XnmgSzpCFCXh@=)OlGAQ`YTDXb~ z(cjG$t|7yg?;M5e$jkQcHVWMoBZ3uPk-Op*dWB!)p?KA@A}sP$yk=h!6?rR01>cK{ zd=#(K-@`@ziZ?9ZtBV2@Z`!}t6$L5A1V0#yf)#JkKeQErinlF4^c00E-m(8MR1~fl z7yM`~icnbTA7_gq6%&>p9Ys-!ckMrJ6vZee1*<$=oZ>xtm9L9eyl+_*>Jk(m*jGim zB*m2AC$a8?;zRl;SSL|@Wcf+0gA^azf70nt#kAmOqmER3LjT;RV-%lSe(uq!6rb6D z9@1$QGlE~Nx-7*k{mZN_Pcdit#i1)wd~W|`Lswj)m=~<^^ks@K=rz9Hp!m|VCe+s| zzOt{0^!17b!LMR{v*K&|S6JVouvvap>su9e`>#5Ehk_IQX4H2o7U|#G^sM3=%WpmU zZpF9u--h&kiY3ACR(-$1LH|ChA5bh?es|~x72nx^-_VaJRs`$3;!(x-^g6$IO!0$d zU06J>_|d*DDxOrV3O2;WQ;MJH4Y+t(@v~(^T|A@s#qPv8uUHdo8jBYcztWp+#hl_d z%VtmUlHzy!=1}p9VqNfuwRlyrLH{vZyr$T+{NX5GSNviBW24v&bpzeJO5D+Hj9Xxd z2fCeg3oG$N&*9vnOT1Bca9d)D4|*=M4Jq+Qcd*+uB?0Jp+%|nl5b6PLHe zOF;Ajc6)D0D0(5ceYhkX^#sqED2YIM%sF!fqnEJmVJ8#NOF8%GlS!x#cy8j!6R0n9E^<>s27u>HoXkS`%z1Ms^Uy%{yycTc=#|`gn zR2g~|;}LkufL_gdgq^BIui-qRPt~Kr;Q5KCn$ca%`N*jj6kyNSoN7e{-1+)b9ViH1 zU^>-_hAW9VMiGpuwR-N$)GmrkM)ATP0W3f<4}kkV=NdX}dtok4Hlc>2yUVZdMJ@h2E5!<(TORU%iAkhEQP(ix1t+MSUb$SkjumrP zZdSVCC18-3!5u%z1O*yA@KbD1n86b-<$|IO-gp^!RieQMFK4bo4E}fpdzHozfLC%? z=?y`+0leB|2*#_JtJ@7AUd>+JYY4?_xT}W^;dm{0&4eKWH!|1E86t5Ld(E;T3a{g? z*)+u9^H1P4~d# zE`1e>w}61Dip1|{fc7c|e}Dygt5o=d957s^#altaL{%2v#t7!B^6++6uv}GyKg0<( zt4i<=5cH}p!yjhAz-j~j2n&W)*W!b?_#cPuV(Sb*=u{NyYVNuYlo}*@NV$BiRym5hq-R9dI0ZbuUoDj#GmA@ z+pHeJ`@m4Ino;~ICN!{S41byp4XYW)pW#BIYbNo2P?%UVg+I#(k(z1zIaa8tnZcju zg!-C!d;knH)hysIFk$UA9R4C3)?2fLzr=+N*R0@!;O>cfqPB0!Ngn4-u7CMc$?kZTN_He!|ffe4JXFIeG|12gq7JhR~t!8u=|#4 zqlkC8eVes0#3UHuWsD=8-L*r?VLGvEyq#w=o%xna(jN6fJ| zEE|i6&$$~mjU~i980lpyBfelF15F0vOExmhR7-rtMMj(Ii3RXLqN$nqnmK@&S_m6^ zKx1kp?A!spse|CagCc)v5xv1#6Nn#ZgCDu(5KQSVtZkqU+ z6=~{bh+jC7zHXja1EWoK3&gKXbbB2~{KiK2)-4ggbJ4?fE5tf@(?s1WvBBIlSGPuN zvNtW)trLH6H*MCrk!~R|UiI$eHf2m;y$89yD<-Vo)A_w>tjgokT|b~IPzj;Twp^yc}Z7XSVIDN>0(@TLlWr|a&uzC z3DQ@2GtwX-{km?}G(hBKi#O{VP|`o-h^c`jcPfvxH!$SoT}OHwROA(lM}`};WI)K# ziH0nauRJ=}kVgh~9bIlHBClLLy4g@d28G0XHI|WADdPhh4dm5b@nMa%xsKVDXr~v4aFdZZS1>k|D}l+8bH&+OAuA8@tKt7H=7D z>?1=%Zk=fCCxyye=Nbpdu&!H|8wbhVi??nzj*#IY30_U30VAB}6w<{s6X`I}* zm=N7GNk)W-6Pu>U{Yo*?G)-RLCDt^}kT)!f^-c3+WJsc^X@NYTOl)uB$b(&py-iEx zjf;uHO)F$n$ZZo%tE5PI+g#Hc8Qpc;a??6_)8cKLO>W6CAxU1%?#Z#rq`+p6C|1A#i zd)(W1Lgz&3wll!*)3$BCGlge}FYn*(i=R2KJn-lF#g{Mi{jF^K8A&VWcb0NSEQc}~7kqx=io&pFIuXTVMs;1=NPzH`6Z4)2|RLF4P@lKZU~ zw;teeZ@|O(8sXXM{aI2!=NycGb6s;V{Hj;{ef|CJb@=;6yZtT5f3A2Y$Z*XzKj#BD za}2B*w>jgSZ3BOgv%TSp^Kb4}oJX8-F87=ISDgQ(?o1fdHb2ugz*#%sx%;^q)M-n~bKYmQUc-COvNy7a{^tha65 zFVjV1u5HWc^d+uKx?%V3JQp+e&aK_GF|O^9(uIG^lZ$lT(zTKCiBA9fwPb8;s!P6= zi9hpuc#A&f^ttRem+l-S+J|KdMR{3pJ% z_OXYLxYQF0{(isHcy4itq>{u8S0A|g!9_cR-FYTd(wP=Lc7}F=I9+7dA@ Date: Tue, 17 Dec 2024 23:29:25 +0530 Subject: [PATCH 12/15] Fix quotes tick data test --- tests/unit_tests/persistence/test_backend.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit_tests/persistence/test_backend.py b/tests/unit_tests/persistence/test_backend.py index abd6cd85d092..563eda393356 100644 --- a/tests/unit_tests/persistence/test_backend.py +++ b/tests/unit_tests/persistence/test_backend.py @@ -56,7 +56,7 @@ def test_backend_session_quotes() -> None: # Assert assert len(ticks) == 9_500 - assert str(ticks[-1]) == "EUR/USD.SIM,1.12130,1.12132,0,0,1577919652000000125" + assert str(ticks[-1]) == "EUR/USD.SIM,1.12130,1.12132,100000,100000,1577919652000000125" is_ascending = all(ticks[i].ts_init <= ticks[i].ts_init for i in range(len(ticks) - 1)) assert is_ascending From 2c85502dddabcf4be97d444a5dbb9abf19be6801 Mon Sep 17 00:00:00 2001 From: Ishan Bhanuka Date: Thu, 19 Dec 2024 02:01:47 +0530 Subject: [PATCH 13/15] Simplify orderbook delta metadata --- nautilus_core/serialization/src/arrow/delta.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/nautilus_core/serialization/src/arrow/delta.rs b/nautilus_core/serialization/src/arrow/delta.rs index 931fc7e5f9e4..94cc95b0c2b4 100644 --- a/nautilus_core/serialization/src/arrow/delta.rs +++ b/nautilus_core/serialization/src/arrow/delta.rs @@ -141,18 +141,17 @@ impl EncodeToRecordBatch for OrderBookDelta { } fn chunk_metadata(chunk: &[Self]) -> HashMap { - let metadata = chunk + let delta = chunk .first() - .map(EncodeToRecordBatch::metadata) .expect("Chunk should have alteast one element to encode"); - // If first element precision metadata is 0, try using metadata of second element - metadata - .get("price_precision") - .zip(metadata.get("size_precision")) - .filter(|(p, s)| *p == "0" && *s == "0") - .and_then(|_| chunk.get(2).map(EncodeToRecordBatch::metadata)) - .unwrap_or(metadata) + if delta.order.price.precision == 0 && delta.order.size.precision == 0 { + if let Some(delta) = chunk.get(2) { + return EncodeToRecordBatch::metadata(delta); + } + } + + EncodeToRecordBatch::metadata(delta) } } From 6cb413f226d583c379293d3a6868d346caa70b47 Mon Sep 17 00:00:00 2001 From: Ishan Bhanuka Date: Thu, 19 Dec 2024 02:32:58 +0530 Subject: [PATCH 14/15] Fix chunk metadata usage for order book delta --- nautilus_core/serialization/src/arrow/delta.rs | 5 ++++- nautilus_core/serialization/src/arrow/mod.rs | 6 ++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/nautilus_core/serialization/src/arrow/delta.rs b/nautilus_core/serialization/src/arrow/delta.rs index 94cc95b0c2b4..f25a1e80e59f 100644 --- a/nautilus_core/serialization/src/arrow/delta.rs +++ b/nautilus_core/serialization/src/arrow/delta.rs @@ -140,13 +140,16 @@ impl EncodeToRecordBatch for OrderBookDelta { ) } + /// Extract metadata from first two deltas + /// + /// Use the second delta if the first one has 0 precision fn chunk_metadata(chunk: &[Self]) -> HashMap { let delta = chunk .first() .expect("Chunk should have alteast one element to encode"); if delta.order.price.precision == 0 && delta.order.size.precision == 0 { - if let Some(delta) = chunk.get(2) { + if let Some(delta) = chunk.get(1) { return EncodeToRecordBatch::metadata(delta); } } diff --git a/nautilus_core/serialization/src/arrow/mod.rs b/nautilus_core/serialization/src/arrow/mod.rs index 54caaf1d3ea9..9a1ff4f857c4 100644 --- a/nautilus_core/serialization/src/arrow/mod.rs +++ b/nautilus_core/serialization/src/arrow/mod.rs @@ -167,10 +167,8 @@ pub fn order_book_deltas_to_arrow_record_batch_bytes( return Err(EncodingError::EmptyData); } - // Take first element and extract metadata - // SAFETY: Unwrap safe as already checked that `data` not empty - let first = data.first().unwrap(); - let metadata = first.metadata(); + // Extract metadata from chunk + let metadata = OrderBookDelta::chunk_metadata(&data); OrderBookDelta::encode_batch(&metadata, &data).map_err(EncodingError::ArrowError) } From 6d26af98afbb2bdd4eed858ed23f2f184893eafd Mon Sep 17 00:00:00 2001 From: Chris Sellers Date: Thu, 19 Dec 2024 09:00:04 +1100 Subject: [PATCH 15/15] Update lock files --- nautilus_core/Cargo.lock | 74 +++--- nautilus_core/persistence/Cargo.toml | 8 +- poetry.lock | 374 +++++++++++++-------------- 3 files changed, 228 insertions(+), 228 deletions(-) diff --git a/nautilus_core/Cargo.lock b/nautilus_core/Cargo.lock index c1bffc47bc5d..e40855df36dc 100644 --- a/nautilus_core/Cargo.lock +++ b/nautilus_core/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "addr2line" @@ -455,9 +455,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "aws-lc-rs" -version = "1.11.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f47bb8cc16b669d267eeccf585aea077d0882f4777b1c1f740217885d6e6e5a3" +checksum = "f409eb70b561706bf8abba8ca9c112729c481595893fd06a2dd9af8ed8441148" dependencies = [ "aws-lc-sys", "paste", @@ -466,9 +466,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.23.1" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2101df3813227bbaaaa0b04cd61c534c7954b22bd68d399b440be937dc63ff7" +checksum = "8478a5c29ead3f3be14aff8a202ad965cf7da6856860041bfca271becf8ba48b" dependencies = [ "bindgen", "cc", @@ -1669,7 +1669,7 @@ dependencies = [ "json-writer", "num_enum", "serde", - "thiserror 2.0.7", + "thiserror 2.0.8", "time", "tokio", "zstd", @@ -2205,11 +2205,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.9" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2266,9 +2266,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97818827ef4f364230e16705d4706e2897df2bb60617d6ca15d598025a3c481f" +checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0" dependencies = [ "bytes", "futures-channel", @@ -2287,9 +2287,9 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.3" +version = "0.27.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +checksum = "f6884a48c6826ec44f524c7456b163cebe9e55a18d7b5e307cb4f100371cc767" dependencies = [ "futures-util", "http", @@ -2875,9 +2875,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +checksum = "4ffbe83022cedc1d264172192511ae958937694cd57ce297164951b8b3568394" dependencies = [ "adler2", ] @@ -3050,7 +3050,7 @@ dependencies = [ "pyo3", "pyo3-async-runtimes", "rstest", - "thiserror 2.0.7", + "thiserror 2.0.8", "tokio", "ustr", ] @@ -3076,7 +3076,7 @@ dependencies = [ "serde", "serde_json", "strum", - "thiserror 2.0.7", + "thiserror 2.0.8", "time", "tokio", "tracing", @@ -3102,7 +3102,7 @@ dependencies = [ "rust_decimal_macros", "serde", "strum", - "thiserror 2.0.7", + "thiserror 2.0.8", ] [[package]] @@ -3175,7 +3175,7 @@ dependencies = [ "serde_json", "strum", "tabled", - "thiserror 2.0.7", + "thiserror 2.0.8", "thousands", "ustr", ] @@ -3200,7 +3200,7 @@ dependencies = [ "rstest", "rustls", "serde_json", - "thiserror 2.0.7", + "thiserror 2.0.8", "tokio", "tokio-rustls", "tokio-tungstenite", @@ -3235,7 +3235,7 @@ dependencies = [ "serde", "serde_json", "tempfile", - "thiserror 2.0.7", + "thiserror 2.0.8", "tokio", ] @@ -3260,7 +3260,7 @@ dependencies = [ "serde", "serde_json", "strum", - "thiserror 2.0.7", + "thiserror 2.0.8", "ustr", "uuid", ] @@ -3300,7 +3300,7 @@ dependencies = [ "pyo3-async-runtimes", "rstest", "rust_decimal", - "thiserror 2.0.7", + "thiserror 2.0.8", "ustr", ] @@ -3316,7 +3316,7 @@ dependencies = [ "parquet", "pyo3", "rstest", - "thiserror 2.0.7", + "thiserror 2.0.8", ] [[package]] @@ -3346,7 +3346,7 @@ dependencies = [ "serde", "serde_json", "strum", - "thiserror 2.0.7", + "thiserror 2.0.8", "thousands", "tokio", "tokio-tungstenite", @@ -4581,7 +4581,7 @@ dependencies = [ "openssl-probe", "rustls-pki-types", "schannel", - "security-framework 3.0.1", + "security-framework 3.1.0", ] [[package]] @@ -4708,9 +4708,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "3.0.1" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1415a607e92bec364ea2cf9264646dcce0f91e6d65281bd6f2819cca3bf39c8" +checksum = "81d3f8c9bfcc3cbb6b0179eb57042d75b1582bdc65c3cb95f3fa999509c03cbc" dependencies = [ "bitflags 2.6.0", "core-foundation 0.10.0", @@ -4721,9 +4721,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.12.1" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2" +checksum = "1863fd3768cd83c56a7f60faa4dc0d403f1b6df0a38c3c25f44b7894e45370d5" dependencies = [ "core-foundation-sys", "libc", @@ -5382,11 +5382,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.7" +version = "2.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93605438cbd668185516ab499d589afb7ee1859ea3d5fc8f6b0755e1c7443767" +checksum = "08f5383f3e0071702bf93ab5ee99b52d26936be9dedd9413067cbdcddcb6141a" dependencies = [ - "thiserror-impl 2.0.7", + "thiserror-impl 2.0.8", ] [[package]] @@ -5402,9 +5402,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.7" +version = "2.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d8749b4531af2117677a5fcd12b1348a3fe2b81e36e61ffeac5c4aa3273e36" +checksum = "f2f357fcec90b3caef6623a099691be676d033b40a058ac95d2a6ade6fa0c943" dependencies = [ "proc-macro2", "quote", @@ -5819,9 +5819,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicode-bidi" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" diff --git a/nautilus_core/persistence/Cargo.toml b/nautilus_core/persistence/Cargo.toml index d3ffbf67aad3..cccb431f047e 100644 --- a/nautilus_core/persistence/Cargo.toml +++ b/nautilus_core/persistence/Cargo.toml @@ -17,18 +17,18 @@ nautilus-serialization = { path = "../serialization" } anyhow = { workspace = true } futures = { workspace = true } +heck = { workspace = true } +itertools = { workspace = true } log = { workspace = true } pyo3 = { workspace = true, optional = true } rand = { workspace = true } +serde_json = { workspace = true } +serde = { workspace = true } tokio = { workspace = true } thiserror = { workspace = true } binary-heap-plus = "0.5.0" compare = "0.1.0" datafusion = { version = "43.0.0", default-features = false, features = ["compression", "regex_expressions", "unicode_expressions", "pyarrow"] } -itertools.workspace = true -heck.workspace = true -serde_json.workspace = true -serde.workspace = true [dev-dependencies] nautilus-test-kit = { path = "../test_kit" } diff --git a/poetry.lock b/poetry.lock index 5cad93a33833..7c2b78b409ce 100644 --- a/poetry.lock +++ b/poetry.lock @@ -13,87 +13,87 @@ files = [ [[package]] name = "aiohttp" -version = "3.11.10" +version = "3.11.11" description = "Async http client/server framework (asyncio)" optional = false python-versions = ">=3.9" files = [ - {file = "aiohttp-3.11.10-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cbad88a61fa743c5d283ad501b01c153820734118b65aee2bd7dbb735475ce0d"}, - {file = "aiohttp-3.11.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:80886dac673ceaef499de2f393fc80bb4481a129e6cb29e624a12e3296cc088f"}, - {file = "aiohttp-3.11.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:61b9bae80ed1f338c42f57c16918853dc51775fb5cb61da70d590de14d8b5fb4"}, - {file = "aiohttp-3.11.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9e2e576caec5c6a6b93f41626c9c02fc87cd91538b81a3670b2e04452a63def6"}, - {file = "aiohttp-3.11.10-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:02c13415b5732fb6ee7ff64583a5e6ed1c57aa68f17d2bda79c04888dfdc2769"}, - {file = "aiohttp-3.11.10-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4cfce37f31f20800a6a6620ce2cdd6737b82e42e06e6e9bd1b36f546feb3c44f"}, - {file = "aiohttp-3.11.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3bbbfff4c679c64e6e23cb213f57cc2c9165c9a65d63717108a644eb5a7398df"}, - {file = "aiohttp-3.11.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49c7dbbc1a559ae14fc48387a115b7d4bbc84b4a2c3b9299c31696953c2a5219"}, - {file = "aiohttp-3.11.10-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:68386d78743e6570f054fe7949d6cb37ef2b672b4d3405ce91fafa996f7d9b4d"}, - {file = "aiohttp-3.11.10-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:9ef405356ba989fb57f84cac66f7b0260772836191ccefbb987f414bcd2979d9"}, - {file = "aiohttp-3.11.10-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:5d6958671b296febe7f5f859bea581a21c1d05430d1bbdcf2b393599b1cdce77"}, - {file = "aiohttp-3.11.10-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:99b7920e7165be5a9e9a3a7f1b680f06f68ff0d0328ff4079e5163990d046767"}, - {file = "aiohttp-3.11.10-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0dc49f42422163efb7e6f1df2636fe3db72713f6cd94688e339dbe33fe06d61d"}, - {file = "aiohttp-3.11.10-cp310-cp310-win32.whl", hash = "sha256:40d1c7a7f750b5648642586ba7206999650208dbe5afbcc5284bcec6579c9b91"}, - {file = "aiohttp-3.11.10-cp310-cp310-win_amd64.whl", hash = "sha256:68ff6f48b51bd78ea92b31079817aff539f6c8fc80b6b8d6ca347d7c02384e33"}, - {file = "aiohttp-3.11.10-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:77c4aa15a89847b9891abf97f3d4048f3c2d667e00f8a623c89ad2dccee6771b"}, - {file = "aiohttp-3.11.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:909af95a72cedbefe5596f0bdf3055740f96c1a4baa0dd11fd74ca4de0b4e3f1"}, - {file = "aiohttp-3.11.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:386fbe79863eb564e9f3615b959e28b222259da0c48fd1be5929ac838bc65683"}, - {file = "aiohttp-3.11.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3de34936eb1a647aa919655ff8d38b618e9f6b7f250cc19a57a4bf7fd2062b6d"}, - {file = "aiohttp-3.11.10-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0c9527819b29cd2b9f52033e7fb9ff08073df49b4799c89cb5754624ecd98299"}, - {file = "aiohttp-3.11.10-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65a96e3e03300b41f261bbfd40dfdbf1c301e87eab7cd61c054b1f2e7c89b9e8"}, - {file = "aiohttp-3.11.10-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98f5635f7b74bcd4f6f72fcd85bea2154b323a9f05226a80bc7398d0c90763b0"}, - {file = "aiohttp-3.11.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:03b6002e20938fc6ee0918c81d9e776bebccc84690e2b03ed132331cca065ee5"}, - {file = "aiohttp-3.11.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6362cc6c23c08d18ddbf0e8c4d5159b5df74fea1a5278ff4f2c79aed3f4e9f46"}, - {file = "aiohttp-3.11.10-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:3691ed7726fef54e928fe26344d930c0c8575bc968c3e239c2e1a04bd8cf7838"}, - {file = "aiohttp-3.11.10-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:31d5093d3acd02b31c649d3a69bb072d539d4c7659b87caa4f6d2bcf57c2fa2b"}, - {file = "aiohttp-3.11.10-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:8b3cf2dc0f0690a33f2d2b2cb15db87a65f1c609f53c37e226f84edb08d10f52"}, - {file = "aiohttp-3.11.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:fbbaea811a2bba171197b08eea288b9402faa2bab2ba0858eecdd0a4105753a3"}, - {file = "aiohttp-3.11.10-cp311-cp311-win32.whl", hash = "sha256:4b2c7ac59c5698a7a8207ba72d9e9c15b0fc484a560be0788b31312c2c5504e4"}, - {file = "aiohttp-3.11.10-cp311-cp311-win_amd64.whl", hash = "sha256:974d3a2cce5fcfa32f06b13ccc8f20c6ad9c51802bb7f829eae8a1845c4019ec"}, - {file = "aiohttp-3.11.10-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:b78f053a7ecfc35f0451d961dacdc671f4bcbc2f58241a7c820e9d82559844cf"}, - {file = "aiohttp-3.11.10-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ab7485222db0959a87fbe8125e233b5a6f01f4400785b36e8a7878170d8c3138"}, - {file = "aiohttp-3.11.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cf14627232dfa8730453752e9cdc210966490992234d77ff90bc8dc0dce361d5"}, - {file = "aiohttp-3.11.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:076bc454a7e6fd646bc82ea7f98296be0b1219b5e3ef8a488afbdd8e81fbac50"}, - {file = "aiohttp-3.11.10-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:482cafb7dc886bebeb6c9ba7925e03591a62ab34298ee70d3dd47ba966370d2c"}, - {file = "aiohttp-3.11.10-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bf3d1a519a324af764a46da4115bdbd566b3c73fb793ffb97f9111dbc684fc4d"}, - {file = "aiohttp-3.11.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24213ba85a419103e641e55c27dc7ff03536c4873470c2478cce3311ba1eee7b"}, - {file = "aiohttp-3.11.10-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b99acd4730ad1b196bfb03ee0803e4adac371ae8efa7e1cbc820200fc5ded109"}, - {file = "aiohttp-3.11.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:14cdb5a9570be5a04eec2ace174a48ae85833c2aadc86de68f55541f66ce42ab"}, - {file = "aiohttp-3.11.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:7e97d622cb083e86f18317282084bc9fbf261801b0192c34fe4b1febd9f7ae69"}, - {file = "aiohttp-3.11.10-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:012f176945af138abc10c4a48743327a92b4ca9adc7a0e078077cdb5dbab7be0"}, - {file = "aiohttp-3.11.10-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:44224d815853962f48fe124748227773acd9686eba6dc102578defd6fc99e8d9"}, - {file = "aiohttp-3.11.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c87bf31b7fdab94ae3adbe4a48e711bfc5f89d21cf4c197e75561def39e223bc"}, - {file = "aiohttp-3.11.10-cp312-cp312-win32.whl", hash = "sha256:06a8e2ee1cbac16fe61e51e0b0c269400e781b13bcfc33f5425912391a542985"}, - {file = "aiohttp-3.11.10-cp312-cp312-win_amd64.whl", hash = "sha256:be2b516f56ea883a3e14dda17059716593526e10fb6303189aaf5503937db408"}, - {file = "aiohttp-3.11.10-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8cc5203b817b748adccb07f36390feb730b1bc5f56683445bfe924fc270b8816"}, - {file = "aiohttp-3.11.10-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5ef359ebc6949e3a34c65ce20230fae70920714367c63afd80ea0c2702902ccf"}, - {file = "aiohttp-3.11.10-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9bca390cb247dbfaec3c664326e034ef23882c3f3bfa5fbf0b56cad0320aaca5"}, - {file = "aiohttp-3.11.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:811f23b3351ca532af598405db1093f018edf81368e689d1b508c57dcc6b6a32"}, - {file = "aiohttp-3.11.10-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddf5f7d877615f6a1e75971bfa5ac88609af3b74796ff3e06879e8422729fd01"}, - {file = "aiohttp-3.11.10-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6ab29b8a0beb6f8eaf1e5049252cfe74adbaafd39ba91e10f18caeb0e99ffb34"}, - {file = "aiohttp-3.11.10-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c49a76c1038c2dd116fa443eba26bbb8e6c37e924e2513574856de3b6516be99"}, - {file = "aiohttp-3.11.10-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7f3dc0e330575f5b134918976a645e79adf333c0a1439dcf6899a80776c9ab39"}, - {file = "aiohttp-3.11.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:efb15a17a12497685304b2d976cb4939e55137df7b09fa53f1b6a023f01fcb4e"}, - {file = "aiohttp-3.11.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:db1d0b28fcb7f1d35600150c3e4b490775251dea70f894bf15c678fdd84eda6a"}, - {file = "aiohttp-3.11.10-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:15fccaf62a4889527539ecb86834084ecf6e9ea70588efde86e8bc775e0e7542"}, - {file = "aiohttp-3.11.10-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:593c114a2221444f30749cc5e5f4012488f56bd14de2af44fe23e1e9894a9c60"}, - {file = "aiohttp-3.11.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7852bbcb4d0d2f0c4d583f40c3bc750ee033265d80598d0f9cb6f372baa6b836"}, - {file = "aiohttp-3.11.10-cp313-cp313-win32.whl", hash = "sha256:65e55ca7debae8faaffee0ebb4b47a51b4075f01e9b641c31e554fd376595c6c"}, - {file = "aiohttp-3.11.10-cp313-cp313-win_amd64.whl", hash = "sha256:beb39a6d60a709ae3fb3516a1581777e7e8b76933bb88c8f4420d875bb0267c6"}, - {file = "aiohttp-3.11.10-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0580f2e12de2138f34debcd5d88894786453a76e98febaf3e8fe5db62d01c9bf"}, - {file = "aiohttp-3.11.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a55d2ad345684e7c3dd2c20d2f9572e9e1d5446d57200ff630e6ede7612e307f"}, - {file = "aiohttp-3.11.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:04814571cb72d65a6899db6099e377ed00710bf2e3eafd2985166f2918beaf59"}, - {file = "aiohttp-3.11.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e44a9a3c053b90c6f09b1bb4edd880959f5328cf63052503f892c41ea786d99f"}, - {file = "aiohttp-3.11.10-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:502a1464ccbc800b4b1995b302efaf426e8763fadf185e933c2931df7db9a199"}, - {file = "aiohttp-3.11.10-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:613e5169f8ae77b1933e42e418a95931fb4867b2991fc311430b15901ed67079"}, - {file = "aiohttp-3.11.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4cca22a61b7fe45da8fc73c3443150c3608750bbe27641fc7558ec5117b27fdf"}, - {file = "aiohttp-3.11.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:86a5dfcc39309470bd7b68c591d84056d195428d5d2e0b5ccadfbaf25b026ebc"}, - {file = "aiohttp-3.11.10-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:77ae58586930ee6b2b6f696c82cf8e78c8016ec4795c53e36718365f6959dc82"}, - {file = "aiohttp-3.11.10-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:78153314f26d5abef3239b4a9af20c229c6f3ecb97d4c1c01b22c4f87669820c"}, - {file = "aiohttp-3.11.10-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:98283b94cc0e11c73acaf1c9698dea80c830ca476492c0fe2622bd931f34b487"}, - {file = "aiohttp-3.11.10-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:53bf2097e05c2accc166c142a2090e4c6fd86581bde3fd9b2d3f9e93dda66ac1"}, - {file = "aiohttp-3.11.10-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c5532f0441fc09c119e1dca18fbc0687e64fbeb45aa4d6a87211ceaee50a74c4"}, - {file = "aiohttp-3.11.10-cp39-cp39-win32.whl", hash = "sha256:47ad15a65fb41c570cd0ad9a9ff8012489e68176e7207ec7b82a0940dddfd8be"}, - {file = "aiohttp-3.11.10-cp39-cp39-win_amd64.whl", hash = "sha256:c6b9e6d7e41656d78e37ce754813fa44b455c3d0d0dced2a047def7dc5570b74"}, - {file = "aiohttp-3.11.10.tar.gz", hash = "sha256:b1fc6b45010a8d0ff9e88f9f2418c6fd408c99c211257334aff41597ebece42e"}, + {file = "aiohttp-3.11.11-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a60804bff28662cbcf340a4d61598891f12eea3a66af48ecfdc975ceec21e3c8"}, + {file = "aiohttp-3.11.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4b4fa1cb5f270fb3eab079536b764ad740bb749ce69a94d4ec30ceee1b5940d5"}, + {file = "aiohttp-3.11.11-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:731468f555656767cda219ab42e033355fe48c85fbe3ba83a349631541715ba2"}, + {file = "aiohttp-3.11.11-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb23d8bb86282b342481cad4370ea0853a39e4a32a0042bb52ca6bdde132df43"}, + {file = "aiohttp-3.11.11-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f047569d655f81cb70ea5be942ee5d4421b6219c3f05d131f64088c73bb0917f"}, + {file = "aiohttp-3.11.11-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd7659baae9ccf94ae5fe8bfaa2c7bc2e94d24611528395ce88d009107e00c6d"}, + {file = "aiohttp-3.11.11-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af01e42ad87ae24932138f154105e88da13ce7d202a6de93fafdafb2883a00ef"}, + {file = "aiohttp-3.11.11-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5854be2f3e5a729800bac57a8d76af464e160f19676ab6aea74bde18ad19d438"}, + {file = "aiohttp-3.11.11-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6526e5fb4e14f4bbf30411216780c9967c20c5a55f2f51d3abd6de68320cc2f3"}, + {file = "aiohttp-3.11.11-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:85992ee30a31835fc482468637b3e5bd085fa8fe9392ba0bdcbdc1ef5e9e3c55"}, + {file = "aiohttp-3.11.11-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:88a12ad8ccf325a8a5ed80e6d7c3bdc247d66175afedbe104ee2aaca72960d8e"}, + {file = "aiohttp-3.11.11-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:0a6d3fbf2232e3a08c41eca81ae4f1dff3d8f1a30bae415ebe0af2d2458b8a33"}, + {file = "aiohttp-3.11.11-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:84a585799c58b795573c7fa9b84c455adf3e1d72f19a2bf498b54a95ae0d194c"}, + {file = "aiohttp-3.11.11-cp310-cp310-win32.whl", hash = "sha256:bfde76a8f430cf5c5584553adf9926534352251d379dcb266ad2b93c54a29745"}, + {file = "aiohttp-3.11.11-cp310-cp310-win_amd64.whl", hash = "sha256:0fd82b8e9c383af11d2b26f27a478640b6b83d669440c0a71481f7c865a51da9"}, + {file = "aiohttp-3.11.11-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ba74ec819177af1ef7f59063c6d35a214a8fde6f987f7661f4f0eecc468a8f76"}, + {file = "aiohttp-3.11.11-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4af57160800b7a815f3fe0eba9b46bf28aafc195555f1824555fa2cfab6c1538"}, + {file = "aiohttp-3.11.11-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ffa336210cf9cd8ed117011085817d00abe4c08f99968deef0013ea283547204"}, + {file = "aiohttp-3.11.11-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81b8fe282183e4a3c7a1b72f5ade1094ed1c6345a8f153506d114af5bf8accd9"}, + {file = "aiohttp-3.11.11-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3af41686ccec6a0f2bdc66686dc0f403c41ac2089f80e2214a0f82d001052c03"}, + {file = "aiohttp-3.11.11-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:70d1f9dde0e5dd9e292a6d4d00058737052b01f3532f69c0c65818dac26dc287"}, + {file = "aiohttp-3.11.11-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:249cc6912405917344192b9f9ea5cd5b139d49e0d2f5c7f70bdfaf6b4dbf3a2e"}, + {file = "aiohttp-3.11.11-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0eb98d90b6690827dcc84c246811feeb4e1eea683c0eac6caed7549be9c84665"}, + {file = "aiohttp-3.11.11-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ec82bf1fda6cecce7f7b915f9196601a1bd1a3079796b76d16ae4cce6d0ef89b"}, + {file = "aiohttp-3.11.11-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9fd46ce0845cfe28f108888b3ab17abff84ff695e01e73657eec3f96d72eef34"}, + {file = "aiohttp-3.11.11-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:bd176afcf8f5d2aed50c3647d4925d0db0579d96f75a31e77cbaf67d8a87742d"}, + {file = "aiohttp-3.11.11-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:ec2aa89305006fba9ffb98970db6c8221541be7bee4c1d027421d6f6df7d1ce2"}, + {file = "aiohttp-3.11.11-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:92cde43018a2e17d48bb09c79e4d4cb0e236de5063ce897a5e40ac7cb4878773"}, + {file = "aiohttp-3.11.11-cp311-cp311-win32.whl", hash = "sha256:aba807f9569455cba566882c8938f1a549f205ee43c27b126e5450dc9f83cc62"}, + {file = "aiohttp-3.11.11-cp311-cp311-win_amd64.whl", hash = "sha256:ae545f31489548c87b0cced5755cfe5a5308d00407000e72c4fa30b19c3220ac"}, + {file = "aiohttp-3.11.11-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e595c591a48bbc295ebf47cb91aebf9bd32f3ff76749ecf282ea7f9f6bb73886"}, + {file = "aiohttp-3.11.11-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:3ea1b59dc06396b0b424740a10a0a63974c725b1c64736ff788a3689d36c02d2"}, + {file = "aiohttp-3.11.11-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8811f3f098a78ffa16e0ea36dffd577eb031aea797cbdba81be039a4169e242c"}, + {file = "aiohttp-3.11.11-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd7227b87a355ce1f4bf83bfae4399b1f5bb42e0259cb9405824bd03d2f4336a"}, + {file = "aiohttp-3.11.11-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d40f9da8cabbf295d3a9dae1295c69975b86d941bc20f0a087f0477fa0a66231"}, + {file = "aiohttp-3.11.11-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ffb3dc385f6bb1568aa974fe65da84723210e5d9707e360e9ecb51f59406cd2e"}, + {file = "aiohttp-3.11.11-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8f5f7515f3552d899c61202d99dcb17d6e3b0de777900405611cd747cecd1b8"}, + {file = "aiohttp-3.11.11-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3499c7ffbfd9c6a3d8d6a2b01c26639da7e43d47c7b4f788016226b1e711caa8"}, + {file = "aiohttp-3.11.11-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8e2bf8029dbf0810c7bfbc3e594b51c4cc9101fbffb583a3923aea184724203c"}, + {file = "aiohttp-3.11.11-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:b6212a60e5c482ef90f2d788835387070a88d52cf6241d3916733c9176d39eab"}, + {file = "aiohttp-3.11.11-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:d119fafe7b634dbfa25a8c597718e69a930e4847f0b88e172744be24515140da"}, + {file = "aiohttp-3.11.11-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:6fba278063559acc730abf49845d0e9a9e1ba74f85f0ee6efd5803f08b285853"}, + {file = "aiohttp-3.11.11-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:92fc484e34b733704ad77210c7957679c5c3877bd1e6b6d74b185e9320cc716e"}, + {file = "aiohttp-3.11.11-cp312-cp312-win32.whl", hash = "sha256:9f5b3c1ed63c8fa937a920b6c1bec78b74ee09593b3f5b979ab2ae5ef60d7600"}, + {file = "aiohttp-3.11.11-cp312-cp312-win_amd64.whl", hash = "sha256:1e69966ea6ef0c14ee53ef7a3d68b564cc408121ea56c0caa2dc918c1b2f553d"}, + {file = "aiohttp-3.11.11-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:541d823548ab69d13d23730a06f97460f4238ad2e5ed966aaf850d7c369782d9"}, + {file = "aiohttp-3.11.11-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:929f3ed33743a49ab127c58c3e0a827de0664bfcda566108989a14068f820194"}, + {file = "aiohttp-3.11.11-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0882c2820fd0132240edbb4a51eb8ceb6eef8181db9ad5291ab3332e0d71df5f"}, + {file = "aiohttp-3.11.11-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b63de12e44935d5aca7ed7ed98a255a11e5cb47f83a9fded7a5e41c40277d104"}, + {file = "aiohttp-3.11.11-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa54f8ef31d23c506910c21163f22b124facb573bff73930735cf9fe38bf7dff"}, + {file = "aiohttp-3.11.11-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a344d5dc18074e3872777b62f5f7d584ae4344cd6006c17ba12103759d407af3"}, + {file = "aiohttp-3.11.11-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b7fb429ab1aafa1f48578eb315ca45bd46e9c37de11fe45c7f5f4138091e2f1"}, + {file = "aiohttp-3.11.11-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c341c7d868750e31961d6d8e60ff040fb9d3d3a46d77fd85e1ab8e76c3e9a5c4"}, + {file = "aiohttp-3.11.11-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ed9ee95614a71e87f1a70bc81603f6c6760128b140bc4030abe6abaa988f1c3d"}, + {file = "aiohttp-3.11.11-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:de8d38f1c2810fa2a4f1d995a2e9c70bb8737b18da04ac2afbf3971f65781d87"}, + {file = "aiohttp-3.11.11-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:a9b7371665d4f00deb8f32208c7c5e652059b0fda41cf6dbcac6114a041f1cc2"}, + {file = "aiohttp-3.11.11-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:620598717fce1b3bd14dd09947ea53e1ad510317c85dda2c9c65b622edc96b12"}, + {file = "aiohttp-3.11.11-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bf8d9bfee991d8acc72d060d53860f356e07a50f0e0d09a8dfedea1c554dd0d5"}, + {file = "aiohttp-3.11.11-cp313-cp313-win32.whl", hash = "sha256:9d73ee3725b7a737ad86c2eac5c57a4a97793d9f442599bea5ec67ac9f4bdc3d"}, + {file = "aiohttp-3.11.11-cp313-cp313-win_amd64.whl", hash = "sha256:c7a06301c2fb096bdb0bd25fe2011531c1453b9f2c163c8031600ec73af1cc99"}, + {file = "aiohttp-3.11.11-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3e23419d832d969f659c208557de4a123e30a10d26e1e14b73431d3c13444c2e"}, + {file = "aiohttp-3.11.11-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:21fef42317cf02e05d3b09c028712e1d73a9606f02467fd803f7c1f39cc59add"}, + {file = "aiohttp-3.11.11-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1f21bb8d0235fc10c09ce1d11ffbd40fc50d3f08a89e4cf3a0c503dc2562247a"}, + {file = "aiohttp-3.11.11-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1642eceeaa5ab6c9b6dfeaaa626ae314d808188ab23ae196a34c9d97efb68350"}, + {file = "aiohttp-3.11.11-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2170816e34e10f2fd120f603e951630f8a112e1be3b60963a1f159f5699059a6"}, + {file = "aiohttp-3.11.11-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8be8508d110d93061197fd2d6a74f7401f73b6d12f8822bbcd6d74f2b55d71b1"}, + {file = "aiohttp-3.11.11-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4eed954b161e6b9b65f6be446ed448ed3921763cc432053ceb606f89d793927e"}, + {file = "aiohttp-3.11.11-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6c9af134da4bc9b3bd3e6a70072509f295d10ee60c697826225b60b9959acdd"}, + {file = "aiohttp-3.11.11-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:44167fc6a763d534a6908bdb2592269b4bf30a03239bcb1654781adf5e49caf1"}, + {file = "aiohttp-3.11.11-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:479b8c6ebd12aedfe64563b85920525d05d394b85f166b7873c8bde6da612f9c"}, + {file = "aiohttp-3.11.11-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:10b4ff0ad793d98605958089fabfa350e8e62bd5d40aa65cdc69d6785859f94e"}, + {file = "aiohttp-3.11.11-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:b540bd67cfb54e6f0865ceccd9979687210d7ed1a1cc8c01f8e67e2f1e883d28"}, + {file = "aiohttp-3.11.11-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1dac54e8ce2ed83b1f6b1a54005c87dfed139cf3f777fdc8afc76e7841101226"}, + {file = "aiohttp-3.11.11-cp39-cp39-win32.whl", hash = "sha256:568c1236b2fde93b7720f95a890741854c1200fba4a3471ff48b2934d2d93fd3"}, + {file = "aiohttp-3.11.11-cp39-cp39-win_amd64.whl", hash = "sha256:943a8b052e54dfd6439fd7989f67fc6a7f2138d0a2cf0a7de5f18aa4fe7eb3b1"}, + {file = "aiohttp-3.11.11.tar.gz", hash = "sha256:bb49c7f1e6ebf3821a42d81d494f538107610c3a705987f53068546b0e90303e"}, ] [package.dependencies] @@ -168,19 +168,19 @@ files = [ [[package]] name = "attrs" -version = "24.2.0" +version = "24.3.0" description = "Classes Without Boilerplate" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2"}, - {file = "attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346"}, + {file = "attrs-24.3.0-py3-none-any.whl", hash = "sha256:ac96cd038792094f438ad1f6ff80837353805ac950cd2aa0e0625ef19850c308"}, + {file = "attrs-24.3.0.tar.gz", hash = "sha256:8f5c07333d543103541ba7be0e2ce16eeee8130cb0b3f9238ab904ce1e85baff"}, ] [package.extras] benchmark = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins", "pytest-xdist[psutil]"] cov = ["cloudpickle", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] -dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] +dev = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier (<24.7)"] tests = ["cloudpickle", "hypothesis", "mypy (>=1.11.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] @@ -2931,18 +2931,18 @@ files = [ [[package]] name = "pydantic" -version = "2.10.3" +version = "2.10.4" description = "Data validation using Python type hints" optional = true python-versions = ">=3.8" files = [ - {file = "pydantic-2.10.3-py3-none-any.whl", hash = "sha256:be04d85bbc7b65651c5f8e6b9976ed9c6f41782a55524cef079a34a0bb82144d"}, - {file = "pydantic-2.10.3.tar.gz", hash = "sha256:cb5ac360ce894ceacd69c403187900a02c4b20b693a9dd1d643e1effab9eadf9"}, + {file = "pydantic-2.10.4-py3-none-any.whl", hash = "sha256:597e135ea68be3a37552fb524bc7d0d66dcf93d395acd93a00682f1efcb8ee3d"}, + {file = "pydantic-2.10.4.tar.gz", hash = "sha256:82f12e9723da6de4fe2ba888b5971157b3be7ad914267dea8f05f82b28254f06"}, ] [package.dependencies] annotated-types = ">=0.6.0" -pydantic-core = "2.27.1" +pydantic-core = "2.27.2" typing-extensions = ">=4.12.2" [package.extras] @@ -2951,111 +2951,111 @@ timezone = ["tzdata"] [[package]] name = "pydantic-core" -version = "2.27.1" +version = "2.27.2" description = "Core functionality for Pydantic validation and serialization" optional = true python-versions = ">=3.8" files = [ - {file = "pydantic_core-2.27.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:71a5e35c75c021aaf400ac048dacc855f000bdfed91614b4a726f7432f1f3d6a"}, - {file = "pydantic_core-2.27.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f82d068a2d6ecfc6e054726080af69a6764a10015467d7d7b9f66d6ed5afa23b"}, - {file = "pydantic_core-2.27.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:121ceb0e822f79163dd4699e4c54f5ad38b157084d97b34de8b232bcaad70278"}, - {file = "pydantic_core-2.27.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4603137322c18eaf2e06a4495f426aa8d8388940f3c457e7548145011bb68e05"}, - {file = "pydantic_core-2.27.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a33cd6ad9017bbeaa9ed78a2e0752c5e250eafb9534f308e7a5f7849b0b1bfb4"}, - {file = "pydantic_core-2.27.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15cc53a3179ba0fcefe1e3ae50beb2784dede4003ad2dfd24f81bba4b23a454f"}, - {file = "pydantic_core-2.27.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45d9c5eb9273aa50999ad6adc6be5e0ecea7e09dbd0d31bd0c65a55a2592ca08"}, - {file = "pydantic_core-2.27.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8bf7b66ce12a2ac52d16f776b31d16d91033150266eb796967a7e4621707e4f6"}, - {file = "pydantic_core-2.27.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:655d7dd86f26cb15ce8a431036f66ce0318648f8853d709b4167786ec2fa4807"}, - {file = "pydantic_core-2.27.1-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:5556470f1a2157031e676f776c2bc20acd34c1990ca5f7e56f1ebf938b9ab57c"}, - {file = "pydantic_core-2.27.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f69ed81ab24d5a3bd93861c8c4436f54afdf8e8cc421562b0c7504cf3be58206"}, - {file = "pydantic_core-2.27.1-cp310-none-win32.whl", hash = "sha256:f5a823165e6d04ccea61a9f0576f345f8ce40ed533013580e087bd4d7442b52c"}, - {file = "pydantic_core-2.27.1-cp310-none-win_amd64.whl", hash = "sha256:57866a76e0b3823e0b56692d1a0bf722bffb324839bb5b7226a7dbd6c9a40b17"}, - {file = "pydantic_core-2.27.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:ac3b20653bdbe160febbea8aa6c079d3df19310d50ac314911ed8cc4eb7f8cb8"}, - {file = "pydantic_core-2.27.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a5a8e19d7c707c4cadb8c18f5f60c843052ae83c20fa7d44f41594c644a1d330"}, - {file = "pydantic_core-2.27.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7f7059ca8d64fea7f238994c97d91f75965216bcbe5f695bb44f354893f11d52"}, - {file = "pydantic_core-2.27.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bed0f8a0eeea9fb72937ba118f9db0cb7e90773462af7962d382445f3005e5a4"}, - {file = "pydantic_core-2.27.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a3cb37038123447cf0f3ea4c74751f6a9d7afef0eb71aa07bf5f652b5e6a132c"}, - {file = "pydantic_core-2.27.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:84286494f6c5d05243456e04223d5a9417d7f443c3b76065e75001beb26f88de"}, - {file = "pydantic_core-2.27.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:acc07b2cfc5b835444b44a9956846b578d27beeacd4b52e45489e93276241025"}, - {file = "pydantic_core-2.27.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4fefee876e07a6e9aad7a8c8c9f85b0cdbe7df52b8a9552307b09050f7512c7e"}, - {file = "pydantic_core-2.27.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:258c57abf1188926c774a4c94dd29237e77eda19462e5bb901d88adcab6af919"}, - {file = "pydantic_core-2.27.1-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:35c14ac45fcfdf7167ca76cc80b2001205a8d5d16d80524e13508371fb8cdd9c"}, - {file = "pydantic_core-2.27.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d1b26e1dff225c31897696cab7d4f0a315d4c0d9e8666dbffdb28216f3b17fdc"}, - {file = "pydantic_core-2.27.1-cp311-none-win32.whl", hash = "sha256:2cdf7d86886bc6982354862204ae3b2f7f96f21a3eb0ba5ca0ac42c7b38598b9"}, - {file = "pydantic_core-2.27.1-cp311-none-win_amd64.whl", hash = "sha256:3af385b0cee8df3746c3f406f38bcbfdc9041b5c2d5ce3e5fc6637256e60bbc5"}, - {file = "pydantic_core-2.27.1-cp311-none-win_arm64.whl", hash = "sha256:81f2ec23ddc1b476ff96563f2e8d723830b06dceae348ce02914a37cb4e74b89"}, - {file = "pydantic_core-2.27.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9cbd94fc661d2bab2bc702cddd2d3370bbdcc4cd0f8f57488a81bcce90c7a54f"}, - {file = "pydantic_core-2.27.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5f8c4718cd44ec1580e180cb739713ecda2bdee1341084c1467802a417fe0f02"}, - {file = "pydantic_core-2.27.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:15aae984e46de8d376df515f00450d1522077254ef6b7ce189b38ecee7c9677c"}, - {file = "pydantic_core-2.27.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1ba5e3963344ff25fc8c40da90f44b0afca8cfd89d12964feb79ac1411a260ac"}, - {file = "pydantic_core-2.27.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:992cea5f4f3b29d6b4f7f1726ed8ee46c8331c6b4eed6db5b40134c6fe1768bb"}, - {file = "pydantic_core-2.27.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0325336f348dbee6550d129b1627cb8f5351a9dc91aad141ffb96d4937bd9529"}, - {file = "pydantic_core-2.27.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7597c07fbd11515f654d6ece3d0e4e5093edc30a436c63142d9a4b8e22f19c35"}, - {file = "pydantic_core-2.27.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3bbd5d8cc692616d5ef6fbbbd50dbec142c7e6ad9beb66b78a96e9c16729b089"}, - {file = "pydantic_core-2.27.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:dc61505e73298a84a2f317255fcc72b710b72980f3a1f670447a21efc88f8381"}, - {file = "pydantic_core-2.27.1-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:e1f735dc43da318cad19b4173dd1ffce1d84aafd6c9b782b3abc04a0d5a6f5bb"}, - {file = "pydantic_core-2.27.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f4e5658dbffe8843a0f12366a4c2d1c316dbe09bb4dfbdc9d2d9cd6031de8aae"}, - {file = "pydantic_core-2.27.1-cp312-none-win32.whl", hash = "sha256:672ebbe820bb37988c4d136eca2652ee114992d5d41c7e4858cdd90ea94ffe5c"}, - {file = "pydantic_core-2.27.1-cp312-none-win_amd64.whl", hash = "sha256:66ff044fd0bb1768688aecbe28b6190f6e799349221fb0de0e6f4048eca14c16"}, - {file = "pydantic_core-2.27.1-cp312-none-win_arm64.whl", hash = "sha256:9a3b0793b1bbfd4146304e23d90045f2a9b5fd5823aa682665fbdaf2a6c28f3e"}, - {file = "pydantic_core-2.27.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:f216dbce0e60e4d03e0c4353c7023b202d95cbaeff12e5fd2e82ea0a66905073"}, - {file = "pydantic_core-2.27.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a2e02889071850bbfd36b56fd6bc98945e23670773bc7a76657e90e6b6603c08"}, - {file = "pydantic_core-2.27.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42b0e23f119b2b456d07ca91b307ae167cc3f6c846a7b169fca5326e32fdc6cf"}, - {file = "pydantic_core-2.27.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:764be71193f87d460a03f1f7385a82e226639732214b402f9aa61f0d025f0737"}, - {file = "pydantic_core-2.27.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1c00666a3bd2f84920a4e94434f5974d7bbc57e461318d6bb34ce9cdbbc1f6b2"}, - {file = "pydantic_core-2.27.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3ccaa88b24eebc0f849ce0a4d09e8a408ec5a94afff395eb69baf868f5183107"}, - {file = "pydantic_core-2.27.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c65af9088ac534313e1963443d0ec360bb2b9cba6c2909478d22c2e363d98a51"}, - {file = "pydantic_core-2.27.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:206b5cf6f0c513baffaeae7bd817717140770c74528f3e4c3e1cec7871ddd61a"}, - {file = "pydantic_core-2.27.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:062f60e512fc7fff8b8a9d680ff0ddaaef0193dba9fa83e679c0c5f5fbd018bc"}, - {file = "pydantic_core-2.27.1-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:a0697803ed7d4af5e4c1adf1670af078f8fcab7a86350e969f454daf598c4960"}, - {file = "pydantic_core-2.27.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:58ca98a950171f3151c603aeea9303ef6c235f692fe555e883591103da709b23"}, - {file = "pydantic_core-2.27.1-cp313-none-win32.whl", hash = "sha256:8065914ff79f7eab1599bd80406681f0ad08f8e47c880f17b416c9f8f7a26d05"}, - {file = "pydantic_core-2.27.1-cp313-none-win_amd64.whl", hash = "sha256:ba630d5e3db74c79300d9a5bdaaf6200172b107f263c98a0539eeecb857b2337"}, - {file = "pydantic_core-2.27.1-cp313-none-win_arm64.whl", hash = "sha256:45cf8588c066860b623cd11c4ba687f8d7175d5f7ef65f7129df8a394c502de5"}, - {file = "pydantic_core-2.27.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:5897bec80a09b4084aee23f9b73a9477a46c3304ad1d2d07acca19723fb1de62"}, - {file = "pydantic_core-2.27.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d0165ab2914379bd56908c02294ed8405c252250668ebcb438a55494c69f44ab"}, - {file = "pydantic_core-2.27.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6b9af86e1d8e4cfc82c2022bfaa6f459381a50b94a29e95dcdda8442d6d83864"}, - {file = "pydantic_core-2.27.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f6c8a66741c5f5447e047ab0ba7a1c61d1e95580d64bce852e3df1f895c4067"}, - {file = "pydantic_core-2.27.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9a42d6a8156ff78981f8aa56eb6394114e0dedb217cf8b729f438f643608cbcd"}, - {file = "pydantic_core-2.27.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:64c65f40b4cd8b0e049a8edde07e38b476da7e3aaebe63287c899d2cff253fa5"}, - {file = "pydantic_core-2.27.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdcf339322a3fae5cbd504edcefddd5a50d9ee00d968696846f089b4432cf78"}, - {file = "pydantic_core-2.27.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bf99c8404f008750c846cb4ac4667b798a9f7de673ff719d705d9b2d6de49c5f"}, - {file = "pydantic_core-2.27.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8f1edcea27918d748c7e5e4d917297b2a0ab80cad10f86631e488b7cddf76a36"}, - {file = "pydantic_core-2.27.1-cp38-cp38-musllinux_1_1_armv7l.whl", hash = "sha256:159cac0a3d096f79ab6a44d77a961917219707e2a130739c64d4dd46281f5c2a"}, - {file = "pydantic_core-2.27.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:029d9757eb621cc6e1848fa0b0310310de7301057f623985698ed7ebb014391b"}, - {file = "pydantic_core-2.27.1-cp38-none-win32.whl", hash = "sha256:a28af0695a45f7060e6f9b7092558a928a28553366519f64083c63a44f70e618"}, - {file = "pydantic_core-2.27.1-cp38-none-win_amd64.whl", hash = "sha256:2d4567c850905d5eaaed2f7a404e61012a51caf288292e016360aa2b96ff38d4"}, - {file = "pydantic_core-2.27.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:e9386266798d64eeb19dd3677051f5705bf873e98e15897ddb7d76f477131967"}, - {file = "pydantic_core-2.27.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4228b5b646caa73f119b1ae756216b59cc6e2267201c27d3912b592c5e323b60"}, - {file = "pydantic_core-2.27.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b3dfe500de26c52abe0477dde16192ac39c98f05bf2d80e76102d394bd13854"}, - {file = "pydantic_core-2.27.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:aee66be87825cdf72ac64cb03ad4c15ffef4143dbf5c113f64a5ff4f81477bf9"}, - {file = "pydantic_core-2.27.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b748c44bb9f53031c8cbc99a8a061bc181c1000c60a30f55393b6e9c45cc5bd"}, - {file = "pydantic_core-2.27.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ca038c7f6a0afd0b2448941b6ef9d5e1949e999f9e5517692eb6da58e9d44be"}, - {file = "pydantic_core-2.27.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e0bd57539da59a3e4671b90a502da9a28c72322a4f17866ba3ac63a82c4498e"}, - {file = "pydantic_core-2.27.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ac6c2c45c847bbf8f91930d88716a0fb924b51e0c6dad329b793d670ec5db792"}, - {file = "pydantic_core-2.27.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b94d4ba43739bbe8b0ce4262bcc3b7b9f31459ad120fb595627eaeb7f9b9ca01"}, - {file = "pydantic_core-2.27.1-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:00e6424f4b26fe82d44577b4c842d7df97c20be6439e8e685d0d715feceb9fb9"}, - {file = "pydantic_core-2.27.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:38de0a70160dd97540335b7ad3a74571b24f1dc3ed33f815f0880682e6880131"}, - {file = "pydantic_core-2.27.1-cp39-none-win32.whl", hash = "sha256:7ccebf51efc61634f6c2344da73e366c75e735960b5654b63d7e6f69a5885fa3"}, - {file = "pydantic_core-2.27.1-cp39-none-win_amd64.whl", hash = "sha256:a57847b090d7892f123726202b7daa20df6694cbd583b67a592e856bff603d6c"}, - {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3fa80ac2bd5856580e242dbc202db873c60a01b20309c8319b5c5986fbe53ce6"}, - {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d950caa237bb1954f1b8c9227b5065ba6875ac9771bb8ec790d956a699b78676"}, - {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0e4216e64d203e39c62df627aa882f02a2438d18a5f21d7f721621f7a5d3611d"}, - {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02a3d637bd387c41d46b002f0e49c52642281edacd2740e5a42f7017feea3f2c"}, - {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:161c27ccce13b6b0c8689418da3885d3220ed2eae2ea5e9b2f7f3d48f1d52c27"}, - {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:19910754e4cc9c63bc1c7f6d73aa1cfee82f42007e407c0f413695c2f7ed777f"}, - {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:e173486019cc283dc9778315fa29a363579372fe67045e971e89b6365cc035ed"}, - {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:af52d26579b308921b73b956153066481f064875140ccd1dfd4e77db89dbb12f"}, - {file = "pydantic_core-2.27.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:981fb88516bd1ae8b0cbbd2034678a39dedc98752f264ac9bc5839d3923fa04c"}, - {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5fde892e6c697ce3e30c61b239330fc5d569a71fefd4eb6512fc6caec9dd9e2f"}, - {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:816f5aa087094099fff7edabb5e01cc370eb21aa1a1d44fe2d2aefdfb5599b31"}, - {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c10c309e18e443ddb108f0ef64e8729363adbfd92d6d57beec680f6261556f3"}, - {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98476c98b02c8e9b2eec76ac4156fd006628b1b2d0ef27e548ffa978393fd154"}, - {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c3027001c28434e7ca5a6e1e527487051136aa81803ac812be51802150d880dd"}, - {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:7699b1df36a48169cdebda7ab5a2bac265204003f153b4bd17276153d997670a"}, - {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:1c39b07d90be6b48968ddc8c19e7585052088fd7ec8d568bb31ff64c70ae3c97"}, - {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:46ccfe3032b3915586e469d4972973f893c0a2bb65669194a5bdea9bacc088c2"}, - {file = "pydantic_core-2.27.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:62ba45e21cf6571d7f716d903b5b7b6d2617e2d5d67c0923dc47b9d41369f840"}, - {file = "pydantic_core-2.27.1.tar.gz", hash = "sha256:62a763352879b84aa31058fc931884055fd75089cccbd9d58bb6afd01141b235"}, + {file = "pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa"}, + {file = "pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a"}, + {file = "pydantic_core-2.27.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236"}, + {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962"}, + {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9"}, + {file = "pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af"}, + {file = "pydantic_core-2.27.2-cp310-cp310-win32.whl", hash = "sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4"}, + {file = "pydantic_core-2.27.2-cp310-cp310-win_amd64.whl", hash = "sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31"}, + {file = "pydantic_core-2.27.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc"}, + {file = "pydantic_core-2.27.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048"}, + {file = "pydantic_core-2.27.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d"}, + {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b"}, + {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474"}, + {file = "pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6"}, + {file = "pydantic_core-2.27.2-cp311-cp311-win32.whl", hash = "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c"}, + {file = "pydantic_core-2.27.2-cp311-cp311-win_amd64.whl", hash = "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc"}, + {file = "pydantic_core-2.27.2-cp311-cp311-win_arm64.whl", hash = "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4"}, + {file = "pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0"}, + {file = "pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2"}, + {file = "pydantic_core-2.27.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4"}, + {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3"}, + {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4"}, + {file = "pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57"}, + {file = "pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc"}, + {file = "pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9"}, + {file = "pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b"}, + {file = "pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b"}, + {file = "pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e"}, + {file = "pydantic_core-2.27.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4"}, + {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27"}, + {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee"}, + {file = "pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1"}, + {file = "pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130"}, + {file = "pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee"}, + {file = "pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b"}, + {file = "pydantic_core-2.27.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d3e8d504bdd3f10835468f29008d72fc8359d95c9c415ce6e767203db6127506"}, + {file = "pydantic_core-2.27.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:521eb9b7f036c9b6187f0b47318ab0d7ca14bd87f776240b90b21c1f4f149320"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:85210c4d99a0114f5a9481b44560d7d1e35e32cc5634c656bc48e590b669b145"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d716e2e30c6f140d7560ef1538953a5cd1a87264c737643d481f2779fc247fe1"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f66d89ba397d92f840f8654756196d93804278457b5fbede59598a1f9f90b228"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:669e193c1c576a58f132e3158f9dfa9662969edb1a250c54d8fa52590045f046"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdbe7629b996647b99c01b37f11170a57ae675375b14b8c13b8518b8320ced5"}, + {file = "pydantic_core-2.27.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d262606bf386a5ba0b0af3b97f37c83d7011439e3dc1a9298f21efb292e42f1a"}, + {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:cabb9bcb7e0d97f74df8646f34fc76fbf793b7f6dc2438517d7a9e50eee4f14d"}, + {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_armv7l.whl", hash = "sha256:d2d63f1215638d28221f664596b1ccb3944f6e25dd18cd3b86b0a4c408d5ebb9"}, + {file = "pydantic_core-2.27.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bca101c00bff0adb45a833f8451b9105d9df18accb8743b08107d7ada14bd7da"}, + {file = "pydantic_core-2.27.2-cp38-cp38-win32.whl", hash = "sha256:f6f8e111843bbb0dee4cb6594cdc73e79b3329b526037ec242a3e49012495b3b"}, + {file = "pydantic_core-2.27.2-cp38-cp38-win_amd64.whl", hash = "sha256:fd1aea04935a508f62e0d0ef1f5ae968774a32afc306fb8545e06f5ff5cdf3ad"}, + {file = "pydantic_core-2.27.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:c10eb4f1659290b523af58fa7cffb452a61ad6ae5613404519aee4bfbf1df993"}, + {file = "pydantic_core-2.27.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ef592d4bad47296fb11f96cd7dc898b92e795032b4894dfb4076cfccd43a9308"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c61709a844acc6bf0b7dce7daae75195a10aac96a596ea1b776996414791ede4"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42c5f762659e47fdb7b16956c71598292f60a03aa92f8b6351504359dbdba6cf"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4c9775e339e42e79ec99c441d9730fccf07414af63eac2f0e48e08fd38a64d76"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:57762139821c31847cfb2df63c12f725788bd9f04bc2fb392790959b8f70f118"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d1e85068e818c73e048fe28cfc769040bb1f475524f4745a5dc621f75ac7630"}, + {file = "pydantic_core-2.27.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:097830ed52fd9e427942ff3b9bc17fab52913b2f50f2880dc4a5611446606a54"}, + {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:044a50963a614ecfae59bb1eaf7ea7efc4bc62f49ed594e18fa1e5d953c40e9f"}, + {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:4e0b4220ba5b40d727c7f879eac379b822eee5d8fff418e9d3381ee45b3b0362"}, + {file = "pydantic_core-2.27.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5e4f4bb20d75e9325cc9696c6802657b58bc1dbbe3022f32cc2b2b632c3fbb96"}, + {file = "pydantic_core-2.27.2-cp39-cp39-win32.whl", hash = "sha256:cca63613e90d001b9f2f9a9ceb276c308bfa2a43fafb75c8031c4f66039e8c6e"}, + {file = "pydantic_core-2.27.2-cp39-cp39-win_amd64.whl", hash = "sha256:77d1bca19b0f7021b3a982e6f903dcd5b2b06076def36a652e3907f596e29f67"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9"}, + {file = "pydantic_core-2.27.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c33939a82924da9ed65dab5a65d427205a73181d8098e79b6b426bdf8ad4e656"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:00bad2484fa6bda1e216e7345a798bd37c68fb2d97558edd584942aa41b7d278"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c817e2b40aba42bac6f457498dacabc568c3b7a986fc9ba7c8d9d260b71485fb"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:251136cdad0cb722e93732cb45ca5299fb56e1344a833640bf93b2803f8d1bfd"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d2088237af596f0a524d3afc39ab3b036e8adb054ee57cbb1dcf8e09da5b29cc"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d4041c0b966a84b4ae7a09832eb691a35aec90910cd2dbe7a208de59be77965b"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:8083d4e875ebe0b864ffef72a4304827015cff328a1be6e22cc850753bfb122b"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f141ee28a0ad2123b6611b6ceff018039df17f32ada8b534e6aa039545a3efb2"}, + {file = "pydantic_core-2.27.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7d0c8399fcc1848491f00e0314bd59fb34a9c008761bcb422a057670c3f65e35"}, + {file = "pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39"}, ] [package.dependencies]