@@ -19,18 +19,10 @@ use crate::data::{
1919 serialize:: { serialize_macaddr, serialize_power, serialize_temperature} ,
2020} ;
2121
22- #[ cfg_attr( feature = "python" , derive( asic_rs_pydantic:: PyPydanticTaggedUnion ) ) ]
23- #[ cfg_attr(
24- feature = "python" ,
25- pydantic( discriminator = "type" , value = "value" , ref = "asic_rs.TuningTarget" )
26- ) ]
2722#[ derive( Debug , Clone , PartialEq , Serialize , Deserialize ) ]
2823pub enum TuningTarget {
29- #[ cfg_attr( feature = "python" , pydantic( tag = "power" ) ) ]
3024 Power ( Power ) ,
31- #[ cfg_attr( feature = "python" , pydantic( tag = "hashrate" ) ) ]
3225 HashRate ( HashRate ) ,
33- #[ cfg_attr( feature = "python" , pydantic( tag = "mode" ) ) ]
3426 MiningMode ( MiningMode ) ,
3527}
3628
@@ -124,3 +116,218 @@ pub struct MinerData {
124116 /// The current pools configured on the miner
125117 pub pools : Vec < PoolGroupData > ,
126118}
119+
120+ #[ cfg( feature = "python" ) ]
121+ pub use python_tuning_target:: { TuningTargetHashRate , TuningTargetMode , TuningTargetPower } ;
122+
123+ #[ cfg( feature = "python" ) ]
124+ mod python_tuning_target {
125+ use asic_rs_pydantic:: {
126+ PyPydanticType , PydanticSchemaMode , get_required_field, literal_schema,
127+ pydantic_typed_dict_schema, tagged_union_schema, union_schema,
128+ } ;
129+ use measurements:: Power ;
130+ use pyo3:: { exceptions:: PyValueError , prelude:: * , types:: PyAnyMethods } ;
131+
132+ use super :: { HashRate , MiningMode , TuningTarget } ;
133+
134+ #[ pyclass( from_py_object, module = "asic_rs" ) ]
135+ #[ derive( Debug , Clone ) ]
136+ pub struct TuningTargetPower {
137+ pub watts : f64 ,
138+ }
139+
140+ #[ pymethods]
141+ impl TuningTargetPower {
142+ #[ getter]
143+ fn watts ( & self ) -> f64 {
144+ self . watts
145+ }
146+ }
147+
148+ #[ pyclass( from_py_object, module = "asic_rs" ) ]
149+ #[ derive( Debug , Clone ) ]
150+ pub struct TuningTargetHashRate {
151+ pub hashrate : HashRate ,
152+ }
153+
154+ #[ pymethods]
155+ impl TuningTargetHashRate {
156+ #[ getter]
157+ fn hashrate ( & self ) -> HashRate {
158+ self . hashrate . clone ( )
159+ }
160+ }
161+
162+ #[ pyclass( from_py_object, module = "asic_rs" ) ]
163+ #[ derive( Debug , Clone ) ]
164+ pub struct TuningTargetMode {
165+ pub mode : MiningMode ,
166+ }
167+
168+ #[ pymethods]
169+ impl TuningTargetMode {
170+ #[ getter]
171+ fn mode ( & self ) -> MiningMode {
172+ self . mode
173+ }
174+ }
175+
176+ impl < ' py > pyo3:: IntoPyObject < ' py > for TuningTarget {
177+ type Target = pyo3:: PyAny ;
178+ type Output = pyo3:: Bound < ' py , pyo3:: PyAny > ;
179+ type Error = pyo3:: PyErr ;
180+
181+ const OUTPUT_TYPE : pyo3:: inspect:: PyStaticExpr = {
182+ use pyo3:: type_hint_union;
183+ type_hint_union ! (
184+ <TuningTargetPower as pyo3:: PyTypeInfo >:: TYPE_HINT ,
185+ <TuningTargetHashRate as pyo3:: PyTypeInfo >:: TYPE_HINT ,
186+ <TuningTargetMode as pyo3:: PyTypeInfo >:: TYPE_HINT
187+ )
188+ } ;
189+
190+ fn into_pyobject ( self , py : pyo3:: Python < ' py > ) -> Result < Self :: Output , Self :: Error > {
191+ match self {
192+ TuningTarget :: Power ( p) => TuningTargetPower {
193+ watts : p. as_watts ( ) ,
194+ }
195+ . into_pyobject ( py)
196+ . map ( pyo3:: Bound :: into_any) ,
197+ TuningTarget :: HashRate ( hr) => TuningTargetHashRate { hashrate : hr }
198+ . into_pyobject ( py)
199+ . map ( pyo3:: Bound :: into_any) ,
200+ TuningTarget :: MiningMode ( m) => TuningTargetMode { mode : m }
201+ . into_pyobject ( py)
202+ . map ( pyo3:: Bound :: into_any) ,
203+ }
204+ }
205+ }
206+
207+ impl PyPydanticType for TuningTarget {
208+ fn pydantic_schema < ' py > (
209+ core_schema : & Bound < ' py , PyAny > ,
210+ mode : PydanticSchemaMode ,
211+ ) -> PyResult < Bound < ' py , PyAny > > {
212+ let power_schema = pydantic_typed_dict_schema ! ( core_schema, "asic_rs.TuningTargetPower" , {
213+ "type" => required( literal_schema( core_schema, & [ "power" ] ) ?) ,
214+ "value" => required( <Power as PyPydanticType >:: pydantic_schema( core_schema, mode) ?) ,
215+ } ) ?;
216+ let hashrate_schema = pydantic_typed_dict_schema ! ( core_schema, "asic_rs.TuningTargetHashRate" , {
217+ "type" => required( literal_schema( core_schema, & [ "hashrate" ] ) ?) ,
218+ "value" => required( <HashRate as PyPydanticType >:: pydantic_schema( core_schema, mode) ?) ,
219+ } ) ?;
220+ let mode_schema = pydantic_typed_dict_schema ! ( core_schema, "asic_rs.TuningTargetMode" , {
221+ "type" => required( literal_schema( core_schema, & [ "mode" ] ) ?) ,
222+ "value" => required( <MiningMode as PyPydanticType >:: pydantic_schema( core_schema, mode) ?) ,
223+ } ) ?;
224+ let tagged_union = tagged_union_schema (
225+ core_schema,
226+ [
227+ ( "power" , power_schema) ,
228+ ( "hashrate" , hashrate_schema) ,
229+ ( "mode" , mode_schema) ,
230+ ] ,
231+ "type" ,
232+ Some ( "asic_rs.TuningTarget" ) ,
233+ ) ?;
234+ if mode == PydanticSchemaMode :: Serialization {
235+ return Ok ( tagged_union) ;
236+ }
237+ let power_instance = core_schema. call_method1 (
238+ "is_instance_schema" ,
239+ ( core_schema. py ( ) . get_type :: < TuningTargetPower > ( ) , ) ,
240+ ) ?;
241+ let hashrate_instance = core_schema. call_method1 (
242+ "is_instance_schema" ,
243+ ( core_schema. py ( ) . get_type :: < TuningTargetHashRate > ( ) , ) ,
244+ ) ?;
245+ let mode_instance = core_schema. call_method1 (
246+ "is_instance_schema" ,
247+ ( core_schema. py ( ) . get_type :: < TuningTargetMode > ( ) , ) ,
248+ ) ?;
249+ union_schema (
250+ core_schema,
251+ [
252+ power_instance,
253+ hashrate_instance,
254+ mode_instance,
255+ tagged_union,
256+ ] ,
257+ )
258+ }
259+
260+ fn from_pydantic ( value : & Bound < ' _ , PyAny > ) -> PyResult < Self > {
261+ if let Ok ( p) = value. extract :: < PyRef < ' _ , TuningTargetPower > > ( ) {
262+ return Ok ( TuningTarget :: Power ( Power :: from_watts ( p. watts ) ) ) ;
263+ }
264+ if let Ok ( hr) = value. extract :: < PyRef < ' _ , TuningTargetHashRate > > ( ) {
265+ return Ok ( TuningTarget :: HashRate ( hr. hashrate . clone ( ) ) ) ;
266+ }
267+ if let Ok ( m) = value. extract :: < PyRef < ' _ , TuningTargetMode > > ( ) {
268+ return Ok ( TuningTarget :: MiningMode ( m. mode ) ) ;
269+ }
270+ let type_str: String = get_required_field ( value, "type" ) ?. extract ( ) ?;
271+ let v = get_required_field ( value, "value" ) ?;
272+ match type_str. as_str ( ) {
273+ "power" => Ok ( TuningTarget :: Power (
274+ <Power as PyPydanticType >:: from_pydantic ( & v) ?,
275+ ) ) ,
276+ "hashrate" => Ok ( TuningTarget :: HashRate (
277+ <HashRate as PyPydanticType >:: from_pydantic ( & v) ?,
278+ ) ) ,
279+ "mode" => Ok ( TuningTarget :: MiningMode (
280+ <MiningMode as PyPydanticType >:: from_pydantic ( & v) ?,
281+ ) ) ,
282+ _ => Err ( PyValueError :: new_err ( format ! (
283+ "Unknown TuningTarget type '{type_str}', expected 'power', 'hashrate', or 'mode'"
284+ ) ) ) ,
285+ }
286+ }
287+
288+ fn to_pydantic_data ( & self , py : Python < ' _ > ) -> PyResult < Py < PyAny > > {
289+ use pyo3:: types:: { PyDict , PyDictMethods } ;
290+ let dict = PyDict :: new ( py) ;
291+ match self {
292+ TuningTarget :: Power ( p) => {
293+ dict. set_item ( "type" , "power" ) ?;
294+ dict. set_item ( "value" , <Power as PyPydanticType >:: to_pydantic_data ( p, py) ?) ?;
295+ }
296+ TuningTarget :: HashRate ( hr) => {
297+ dict. set_item ( "type" , "hashrate" ) ?;
298+ dict. set_item (
299+ "value" ,
300+ <HashRate as PyPydanticType >:: to_pydantic_data ( hr, py) ?,
301+ ) ?;
302+ }
303+ TuningTarget :: MiningMode ( m) => {
304+ dict. set_item ( "type" , "mode" ) ?;
305+ dict. set_item (
306+ "value" ,
307+ <MiningMode as PyPydanticType >:: to_pydantic_data ( m, py) ?,
308+ ) ?;
309+ }
310+ }
311+ Ok ( dict. into_any ( ) . unbind ( ) )
312+ }
313+
314+ fn to_pydantic_repr_value ( & self , py : Python < ' _ > ) -> PyResult < Py < PyAny > > {
315+ use pyo3:: IntoPyObject as _;
316+ match self {
317+ TuningTarget :: Power ( p) => TuningTargetPower {
318+ watts : p. as_watts ( ) ,
319+ }
320+ . into_pyobject ( py)
321+ . map ( |b| b. into_any ( ) . unbind ( ) ) ,
322+ TuningTarget :: HashRate ( hr) => TuningTargetHashRate {
323+ hashrate : hr. clone ( ) ,
324+ }
325+ . into_pyobject ( py)
326+ . map ( |b| b. into_any ( ) . unbind ( ) ) ,
327+ TuningTarget :: MiningMode ( m) => TuningTargetMode { mode : * m }
328+ . into_pyobject ( py)
329+ . map ( |b| b. into_any ( ) . unbind ( ) ) ,
330+ }
331+ }
332+ }
333+ }
0 commit comments