@@ -140,12 +140,14 @@ def test_from_pickle(train_data, pickle_file):
140
140
141
141
X , y = train_data
142
142
143
- with mock .patch ('uuid.uuid4' ) as mocked :
144
- mocked .return_value .hex = 'DF74A4B18C9E41A2A34B0053E123AA67'
145
- p = from_pickle (pickle_file ,
146
- func_name = 'predict' ,
147
- input_types = X ,
148
- array_input = True )
143
+ with mock .patch ('sasctl.utils.pymas.core.random_string' ) as mock_rnd_string :
144
+ mock_rnd_string .return_value = 'randomMethodName'
145
+ with mock .patch ('uuid.uuid4' ) as mocked :
146
+ mocked .return_value .hex = 'DF74A4B18C9E41A2A34B0053E123AA67'
147
+ p = from_pickle (pickle_file ,
148
+ func_name = 'predict' ,
149
+ input_types = X ,
150
+ array_input = True )
149
151
150
152
target = """
151
153
package _DF74A4B18C9E41A2A34B0053E123AA6 / overwrite=yes;
@@ -169,7 +171,7 @@ def test_from_pickle(train_data, pickle_file):
169
171
rc = py.appendSrcLine('except Exception as e:');
170
172
rc = py.appendSrcLine(' _compile_error = e');
171
173
rc = py.appendSrcLine('');
172
- rc = py.appendSrcLine('def predict (SepalLength, SepalWidth, PetalLength, PetalWidth):');
174
+ rc = py.appendSrcLine('def _randomMethodName (SepalLength, SepalWidth, PetalLength, PetalWidth):');
173
175
rc = py.appendSrcLine(' "Output: var1, msg"');
174
176
rc = py.appendSrcLine(' result = None');
175
177
rc = py.appendSrcLine(' msg = None');
@@ -219,7 +221,7 @@ def test_from_pickle(train_data, pickle_file):
219
221
220
222
dcl integer rc;
221
223
dcl varchar(4068) msg;
222
- rc = py.useMethod('predict ');
224
+ rc = py.useMethod('_randomMethodName ');
223
225
if rc then return;
224
226
rc = py.setDouble('SepalLength', SepalLength); if rc then return;
225
227
rc = py.setDouble('SepalWidth', SepalWidth); if rc then return;
@@ -251,10 +253,12 @@ def test_from_pickle_2(train_data, pickle_file):
251
253
252
254
X , _ = train_data
253
255
254
- with mock .patch ('uuid.uuid4' ) as mocked :
255
- mocked .return_value .hex = 'DF74A4B18C9E41A2A34B0053E123AA67'
256
- p = from_pickle (pickle_file , func_name = ['predict' , 'predict_proba' ],
257
- input_types = X , array_input = True )
256
+ with mock .patch ('sasctl.utils.pymas.core.random_string' ) as mock_rnd_string :
257
+ mock_rnd_string .side_effect = ['randomMethodName1' , 'randomMethodName2' ]
258
+ with mock .patch ('uuid.uuid4' ) as mocked :
259
+ mocked .return_value .hex = 'DF74A4B18C9E41A2A34B0053E123AA67'
260
+ p = from_pickle (pickle_file , func_name = ['predict' , 'predict_proba' ],
261
+ input_types = X , array_input = True )
258
262
259
263
target = """
260
264
package _DF74A4B18C9E41A2A34B0053E123AA6 / overwrite=yes;
@@ -278,7 +282,7 @@ def test_from_pickle_2(train_data, pickle_file):
278
282
rc = py.appendSrcLine('except Exception as e:');
279
283
rc = py.appendSrcLine(' _compile_error = e');
280
284
rc = py.appendSrcLine('');
281
- rc = py.appendSrcLine('def predict (SepalLength, SepalWidth, PetalLength, PetalWidth):');
285
+ rc = py.appendSrcLine('def _randomMethodName1 (SepalLength, SepalWidth, PetalLength, PetalWidth):');
282
286
rc = py.appendSrcLine(' "Output: var1, msg"');
283
287
rc = py.appendSrcLine(' result = None');
284
288
rc = py.appendSrcLine(' msg = None');
@@ -309,7 +313,7 @@ def test_from_pickle_2(train_data, pickle_file):
309
313
rc = py.appendSrcLine(' result = tuple(None for i in range(1))');
310
314
rc = py.appendSrcLine(' return result + (msg, )');
311
315
rc = py.appendSrcLine('');
312
- rc = py.appendSrcLine('def predict_proba (SepalLength, SepalWidth, PetalLength, PetalWidth):');
316
+ rc = py.appendSrcLine('def _randomMethodName2 (SepalLength, SepalWidth, PetalLength, PetalWidth):');
313
317
rc = py.appendSrcLine(' "Output: P_1, P_2, P_3, msg"');
314
318
rc = py.appendSrcLine(' result = None');
315
319
rc = py.appendSrcLine(' msg = None');
@@ -359,7 +363,7 @@ def test_from_pickle_2(train_data, pickle_file):
359
363
360
364
dcl integer rc;
361
365
dcl varchar(4068) msg;
362
- rc = py.useMethod('predict ');
366
+ rc = py.useMethod('_randomMethodName1 ');
363
367
if rc then return;
364
368
rc = py.setDouble('SepalLength', SepalLength); if rc then return;
365
369
rc = py.setDouble('SepalWidth', SepalWidth); if rc then return;
@@ -383,7 +387,7 @@ def test_from_pickle_2(train_data, pickle_file):
383
387
384
388
dcl integer rc;
385
389
dcl varchar(4068) msg;
386
- rc = py.useMethod('predict_proba ');
390
+ rc = py.useMethod('_randomMethodName2 ');
387
391
if rc then return;
388
392
rc = py.setDouble('SepalLength', SepalLength); if rc then return;
389
393
rc = py.setDouble('SepalWidth', SepalWidth); if rc then return;
@@ -419,11 +423,99 @@ def test_from_pickle_stream(train_data, pickle_stream):
419
423
assert isinstance (p , PyMAS )
420
424
421
425
422
- def test_from_python_file (python_file ):
423
- from sasctl .utils .pymas import PyMAS , from_python_file
426
+ def test_from_python_file (tmpdir ):
427
+ from sasctl .utils .pymas import from_python_file
424
428
425
- p = from_python_file (python_file , func_name = 'predict' )
426
- assert isinstance (p , PyMAS )
429
+ code = """
430
+ def hello_world():
431
+ print('Hello World!')
432
+
433
+ """
434
+
435
+ target = """
436
+ package _DF74A4B18C9E41A2A34B0053E123AA6 / overwrite=yes;
437
+ dcl package pymas py;
438
+ dcl package logger logr('App.tk.MAS');
439
+ dcl varchar(67108864) character set utf8 pycode;
440
+ dcl int revision;
441
+
442
+ method init();
443
+
444
+ dcl integer rc;
445
+ if null(py) then do;
446
+ py = _new_ pymas();
447
+ rc = py.useModule('DF74A4B18C9E41A2A34B0053E123AA67', 1);
448
+ if rc then do;
449
+ rc = py.appendSrcLine('try:');
450
+ rc = py.appendSrcLine(' ');
451
+ rc = py.appendSrcLine(' def hello_world():');
452
+ rc = py.appendSrcLine(' print('Hello World!')');
453
+ rc = py.appendSrcLine(' ');
454
+ rc = py.appendSrcLine(' _compile_error = None');
455
+ rc = py.appendSrcLine('except Exception as e:');
456
+ rc = py.appendSrcLine(' _compile_error = e');
457
+ rc = py.appendSrcLine('');
458
+ rc = py.appendSrcLine('def _randomMethodName():');
459
+ rc = py.appendSrcLine(' "Output: result, msg"');
460
+ rc = py.appendSrcLine(' result = None');
461
+ rc = py.appendSrcLine(' msg = None');
462
+ rc = py.appendSrcLine(' try:');
463
+ rc = py.appendSrcLine(' global _compile_error');
464
+ rc = py.appendSrcLine(' if _compile_error is not None:');
465
+ rc = py.appendSrcLine(' raise _compile_error');
466
+ rc = py.appendSrcLine(' import numpy as np');
467
+ rc = py.appendSrcLine(' import pandas as pd');
468
+ rc = py.appendSrcLine(' result = hello_world()');
469
+ rc = py.appendSrcLine(' result = tuple(result.ravel()) if hasattr(result, "ravel") else tuple(result)');
470
+ rc = py.appendSrcLine(' if len(result) == 0:');
471
+ rc = py.appendSrcLine(' result = tuple(None for i in range(1))');
472
+ rc = py.appendSrcLine(' elif "numpy" in str(type(result[0])):');
473
+ rc = py.appendSrcLine(' result = tuple(np.asscalar(i) for i in result)');
474
+ rc = py.appendSrcLine(' except Exception as e:');
475
+ rc = py.appendSrcLine(' from traceback import format_exc');
476
+ rc = py.appendSrcLine(' msg = str(e) + format_exc()');
477
+ rc = py.appendSrcLine(' if result is None:');
478
+ rc = py.appendSrcLine(' result = tuple(None for i in range(1))');
479
+ rc = py.appendSrcLine(' return result + (msg, )');
480
+ pycode = py.getSource();
481
+ revision = py.publish(pycode, 'DF74A4B18C9E41A2A34B0053E123AA67');
482
+ if revision lt 1 then do;
483
+ logr.log('e', 'py.publish() failed.');
484
+ rc = -1;
485
+ end;
486
+ end;
487
+ end;
488
+ end;
489
+
490
+ method hello_world(
491
+ in_out double result
492
+ );
493
+
494
+ dcl integer rc;
495
+ dcl varchar(4068) msg;
496
+ rc = py.useMethod('_randomMethodName');
497
+ if rc then return;
498
+ rc = py.execute(); if rc then return;
499
+ result = py.getDouble('result');
500
+ msg = py.getString('msg');
501
+ if not null(msg) then logr.log('e', 'Error executing Python function "hello_world": $s', msg);
502
+ end;
503
+
504
+ endpackage;
505
+ """ .lstrip ('\n ' )
506
+
507
+ f = tmpdir .join ('model.py' )
508
+ f .write (code )
509
+
510
+ with mock .patch ('sasctl.utils.pymas.core.random_string' ) as mock_rnd_string :
511
+ mock_rnd_string .return_value = 'randomMethodName'
512
+ with mock .patch ('uuid.uuid4' ) as mocked :
513
+ mocked .return_value .hex = 'DF74A4B18C9E41A2A34B0053E123AA67'
514
+ p = from_python_file (str (f ), 'hello_world' )
515
+
516
+ result = p .score_code ()
517
+
518
+ assert result == target
427
519
428
520
429
521
def test_with_sklearn_pipeline (train_data , sklearn_pipeline ):
0 commit comments