Skip to content

Commit 27b6e3a

Browse files
committed
edits for new Jupyter notebook and updated code files (2026.03)
1 parent ea01611 commit 27b6e3a

6 files changed

Lines changed: 123 additions & 194 deletions

File tree

examples/pzmm_id_code_file_example.ipynb

Lines changed: 53 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,34 @@
77
"source": [
88
"# Creating Python Code Files for SAS Intelligent Decisioning\n",
99
"\n",
10-
"This notebook demonstrates how to use the `CodeFile` class to upload Python code files formatted for SAS Intelligent Decisioning.\n",
10+
"This notebook demonstrates how to use the `CodeFile` class to upload Python code\n",
11+
"files that are properly formatted for use with SAS Intelligent Decisioning.\n",
1112
"\n",
1213
"## Overview\n",
1314
"\n",
15+
"SAS Intelligent Decisioning requires Python code files to follow a specific format.\n",
1416
"\n",
15-
"SAS Intelligent Decisioning (ID) requires Python code files to follow a specific format for detailed specifications on Python code file format requirements for SAS Intelligent Decisioning, see the [Rules For Developing Python Code Files](https://go.documentation.sas.com/doc/en/edmcdc/v_063/edmug/n04vfc1flrz8jsn1o5jblnbgx6i3.htm#n0jrohir6wzvd0n11omfautducm3) documentation.\n",
17+
"Here is a high-level summary of the formatting requirements:\n",
1618
"\n",
17-
"A basic overview:\n",
1819
"- An `execute` function is required\n",
19-
"- An `Output:` docstring listing output variables as first line in the execute function\n",
20-
"- A `DependentPackages:` docstring listing required packages at the top of the file including all non built-in packages needed\n",
20+
"- An `Output:` docstring listing output variables as the first line in the execute function\n",
21+
"- A `DependentPackages:` docstring listing required packages at the top of the file including packages that are needed but are not built-in\n",
2122
"- Must return standard Python data types\n",
2223
"\n",
2324
"\n",
2425
"The `CodeFile` class validates and uploads properly formatted Python code to SAS Viya.\n",
2526
"\n",
27+
"For more information about formating requirements for Python code files, see the [Rules\n",
28+
"For Developing Python Code\n",
29+
"Files](https://documentation.sas.com/?cdcId=edmcdc&cdcVersion=default&docsetId=edmug&docsetTarget=n04vfc1flrz8jsn1o5jblnbgx6i3.htm#n0jrohir6wzvd0n11omfautducm3)\n",
30+
"in _SAS Intelligent Decisioning: User's Guide_.\n",
31+
"\n",
2632
"## Prerequisites\n",
2733
"\n",
28-
"- A SAS Viya environment with Intelligent Decisioning\n",
34+
"- SAS Viya environment with SAS Intelligent Decisioning\n",
2935
"- Appropriate permissions to create files in the target folder\n",
3036
"- sasctl package installed\n",
31-
"- Python code already formatted according to ID requirements"
37+
"- Python code already formatted according to SAS Intelligent Decisioning requirements"
3238
]
3339
},
3440
{
@@ -44,31 +50,14 @@
4450
"execution_count": null,
4551
"id": "e27dcadc",
4652
"metadata": {},
47-
"outputs": [
48-
{
49-
"name": "stderr",
50-
"output_type": "stream",
51-
"text": [
52-
"/Users/sababa/Desktop/repos/python-sasctl/venv3.11/lib/python3.11/site-packages/urllib3/connectionpool.py:1097: InsecureRequestWarning: Unverified HTTPS request is being made to host 'base.ingress-nginx.sababa-dq1-m1.modelmanager.sashq-d.openstack.sas.com'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#tls-warnings\n",
53-
" warnings.warn(\n"
54-
]
55-
},
56-
{
57-
"name": "stdout",
58-
"output_type": "stream",
59-
"text": [
60-
"Connected to https://base.ingress-nginx.sababa-dq1-m1.modelmanager.sashq-d.openstack.sas.com/\n",
61-
"Folder already exists. HTTP Error 409: {\"version\":2,\"httpStatusCode\":409,\"errorCode\":11552,\"message\":\"An item named \\\"ID_python_files\\\" of type \\\"Folder\\\" already exists in the folder \\\"Public\\\".\",\"details\":[\"Existing member: \",\"/folders/folders/3789dfcd-a5a6-4836-85d9-beb5f812baf8\",\"Suggestion: ID_python_files (1)\",\"path: /folders/folders\",\"correlator: 58004f45-b0cb-4737-adb1-1edbfba2040c\"]}\n"
62-
]
63-
}
64-
],
53+
"outputs": [],
6554
"source": [
6655
"from sasctl import Session\n",
6756
"from sasctl.pzmm import CodeFile\n",
6857
"from sasctl.services import folders as folder_service\n",
6958
"\n",
7059
"\n",
71-
"# Replace with your SAS Viya connection details\n",
60+
"# Replace with your SAS Viya connection information\n",
7261
"HOST = 'your-viya-host.com'\n",
7362
"USERNAME = 'your-username'\n",
7463
"PASSWORD = 'your-password'\n",
@@ -90,27 +79,17 @@
9079
"source": [
9180
"## Example 1: Simple Code File\n",
9281
"\n",
93-
"Let's start with a simple example that performs a basic calculation."
82+
"Here is a simple example that performs a basic calculation."
9483
]
9584
},
9685
{
9786
"cell_type": "code",
9887
"execution_count": null,
9988
"id": "fa33286d",
10089
"metadata": {},
101-
"outputs": [
102-
{
103-
"name": "stdout",
104-
"output_type": "stream",
105-
"text": [
106-
"File uploaded successfully!\n",
107-
"File ID: 5169bfbe-4ba4-4998-b9c3-24228add86a7\n",
108-
"File Name: simple_calculator\n"
109-
]
110-
}
111-
],
90+
"outputs": [],
11291
"source": [
113-
"# Define properly formatted ID Python code\n",
92+
"# Define properly formatted Python code\n",
11493
"simple_code = \"\"\"\n",
11594
"def execute(input_value):\n",
11695
" '''Output: score, category'''\n",
@@ -120,14 +99,14 @@
12099
" return score, category\n",
121100
"\"\"\"\n",
122101
"\n",
123-
"# Upload the code file to Viya\n",
102+
"# Upload the code file to SAS Viya\n",
124103
"file_obj = CodeFile.write_id_code_file(\n",
125104
" code=simple_code,\n",
126105
" file_name='simple_calculator.py',\n",
127106
" folder='/Public/ID_python_files'\n",
128107
")\n",
129108
"\n",
130-
"print(f\"File uploaded successfully!\")\n",
109+
"print(f\"The file was uploaded successfully.\")\n",
131110
"print(f\"File ID: {file_obj.id}\")\n",
132111
"print(f\"File Name: {file_obj.name}\")"
133112
]
@@ -139,25 +118,15 @@
139118
"source": [
140119
"## Example 2: Code File with API Call\n",
141120
"\n",
142-
"This example shows how to create a code file that makes an API call to retrieve data."
121+
"Here is an example of how to create a code file that makes an API call to retrieve data."
143122
]
144123
},
145124
{
146125
"cell_type": "code",
147-
"execution_count": 11,
126+
"execution_count": null,
148127
"id": "6608730a",
149128
"metadata": {},
150-
"outputs": [
151-
{
152-
"name": "stdout",
153-
"output_type": "stream",
154-
"text": [
155-
"File uploaded successfully!\n",
156-
"File ID: 7484adcd-3121-4e13-b208-c7b1ef51e444\n",
157-
"File Name: risk_score_api\n"
158-
]
159-
}
160-
],
129+
"outputs": [],
161130
"source": [
162131
"api_code = \"\"\"\n",
163132
"'''DependentPackages: requests'''\n",
@@ -188,9 +157,9 @@
188157
" folder='/Public/ID_python_files'\n",
189158
")\n",
190159
"\n",
191-
"print(f\"File uploaded successfully!\")\n",
160+
"print(f\"The file was uploaded successfully.\")\n",
192161
"print(f\"File ID: {file_obj.id}\")\n",
193-
"print(f\"File Name: {file_obj.name}\")"
162+
"print(f\"File name: {file_obj.name}\")"
194163
]
195164
},
196165
{
@@ -200,23 +169,15 @@
200169
"source": [
201170
"## Example 3: Code with Multiple Dependencies\n",
202171
"\n",
203-
"Specify multiple packages in the DependentPackages docstring."
172+
"Here is an example of specifying multiple packages in the `DependentPackages` docstring."
204173
]
205174
},
206175
{
207176
"cell_type": "code",
208-
"execution_count": 12,
177+
"execution_count": null,
209178
"id": "48f441ff",
210179
"metadata": {},
211-
"outputs": [
212-
{
213-
"name": "stdout",
214-
"output_type": "stream",
215-
"text": [
216-
"File uploaded successfully: data_processor\n"
217-
]
218-
}
219-
],
180+
"outputs": [],
220181
"source": [
221182
"data_processing_code = \"\"\"\n",
222183
"'''DependentPackages: pandas, numpy'''\n",
@@ -234,7 +195,7 @@
234195
" mean_value = float(np.mean(data['values']))\n",
235196
" std_value = float(np.std(data['values']))\n",
236197
" result = 'Pass' if mean_value > threshold else 'Fail'\n",
237-
" \n",
198+
"\n",
238199
" return mean_value, std_value, result\n",
239200
"\"\"\"\n",
240201
"\n",
@@ -245,7 +206,7 @@
245206
" folder='/Public/ID_python_files'\n",
246207
")\n",
247208
"\n",
248-
"print(f\"File uploaded successfully: {file_obj.name}\")"
209+
"print(f\"This file was uploaded successfully: {file_obj.name}\")"
249210
]
250211
},
251212
{
@@ -255,23 +216,15 @@
255216
"source": [
256217
"## Example 4: Reading Code from a File\n",
257218
"\n",
258-
"You can also read Python code from an existing file."
219+
"Here is an example of reading Python code from an existing file."
259220
]
260221
},
261222
{
262223
"cell_type": "code",
263224
"execution_count": null,
264225
"id": "eb8ad79d",
265226
"metadata": {},
266-
"outputs": [
267-
{
268-
"name": "stdout",
269-
"output_type": "stream",
270-
"text": [
271-
"Uploaded code from file: credit_decision\n"
272-
]
273-
}
274-
],
227+
"outputs": [],
275228
"source": [
276229
"from pathlib import Path\n",
277230
"\n",
@@ -298,7 +251,7 @@
298251
"# Clean up\n",
299252
"temp_code_file.unlink()\n",
300253
"\n",
301-
"print(f\"Uploaded code from file: {file_obj.name}\")"
254+
"print(f\"Code uploaded from file: {file_obj.name}\")"
302255
]
303256
},
304257
{
@@ -308,26 +261,15 @@
308261
"source": [
309262
"## Example 5: Code File with No Parameters\n",
310263
"\n",
311-
"You can also create code files that don't require input parameters."
264+
"Here is an example of creating code files that do not require input parameters."
312265
]
313266
},
314267
{
315268
"cell_type": "code",
316269
"execution_count": null,
317270
"id": "460f264f",
318271
"metadata": {},
319-
"outputs": [
320-
{
321-
"name": "stdout",
322-
"output_type": "stream",
323-
"text": [
324-
"WARNING: About to delete existing file: config_info.py\n",
325-
"This may result in loss of sensitive data or configurations.\n",
326-
"Deleted existing file: config_info.py\n",
327-
"Configuration code file created: config_info\n"
328-
]
329-
}
330-
],
272+
"outputs": [],
331273
"source": [
332274
"from sasctl.services import files as file_service\n",
333275
"from sasctl.services import folders as folder_service\n",
@@ -341,12 +283,12 @@
341283
" current_date = datetime.datetime.now().strftime('%Y-%m-%d')\n",
342284
" environment = 'production'\n",
343285
" version = '1.0.0'\n",
344-
" \n",
286+
"\n",
345287
" return current_date, environment, version\n",
346288
"\"\"\"\n",
347289
"\n",
348-
"# Check if file already exists and delete it\n",
349-
"# WARNING: Deleting files may result in loss of important data or configurations.\n",
290+
"# Check if file already exists and delete it.\n",
291+
"# Warning: Deleting files might result in loss of important data or configurations.\n",
350292
"# Ensure you have backups or that the file can be safely removed before proceeding.\n",
351293
"\n",
352294
"file_name = 'config_info.py'\n",
@@ -361,13 +303,13 @@
361303
" params={\"filter\": file_filter}\n",
362304
" )\n",
363305
" if len(existing_file) > 0:\n",
364-
" print(f\"WARNING: About to delete existing file: {file_name}\")\n",
365-
" print(\"This may result in loss of sensitive data or configurations.\")\n",
306+
" print(f\"Warning: You are about to delete this file: {file_name}\")\n",
307+
" print(\"This action might result in loss of sensitive data or configurations.\")\n",
366308
"\n",
367309
" file_service.delete_file({\"id\": existing_file['uri'].split('/')[-1]})\n",
368-
" print(f\"Deleted existing file: {file_name}\")\n",
310+
" print(f\"Deleted file: {file_name}\")\n",
369311
"except Exception as e:\n",
370-
" print(f\"No existing file found: {file_name} {e}\")\n",
312+
" print(f\"This file was not found: {file_name} {e}\")\n",
371313
"\n",
372314
"\n",
373315
"file_obj = CodeFile.write_id_code_file(\n",
@@ -386,24 +328,19 @@
386328
"source": [
387329
"## Example 6: Disable Validation\n",
388330
"\n",
389-
"You can skip pre-upload validation **Note:** The file will still be uploaded even if it has formatting errors - those errors will appear later when you try to use the file in a decision. You can view the codeFile in Intelligent Decisioning and validate it to check."
331+
"Here is an example of skipping pre-upload validation.\n",
332+
"\n",
333+
"**Note:** The file will still be uploaded even if it contains formatting errors.\n",
334+
"The errors appear later when you try to use the file in a decision. You can\n",
335+
"view the code file in SAS Intelligent Decisioning and validate it to check for errors."
390336
]
391337
},
392338
{
393339
"cell_type": "code",
394340
"execution_count": null,
395341
"id": "95855524",
396342
"metadata": {},
397-
"outputs": [
398-
{
399-
"name": "stdout",
400-
"output_type": "stream",
401-
"text": [
402-
"File uploaded without pre-validation: fast_calculator\n",
403-
"Warning: If there are formatting errors, they will appear when you use the file in a decision.\n"
404-
]
405-
}
406-
],
343+
"outputs": [],
407344
"source": [
408345
"fast_code = \"\"\"\n",
409346
"def execute(input_a, input_b):\n",
@@ -413,7 +350,7 @@
413350
"\"\"\"\n",
414351
"\n",
415352
"# Skip pre-upload validation for faster upload\n",
416-
"# File will still be created even if there are formatting errors\n",
353+
"# File is still created when there are formatting errors\n",
417354
"file_obj = CodeFile.write_id_code_file(\n",
418355
" code=fast_code,\n",
419356
" file_name='fast_calculator.py',\n",
@@ -437,18 +374,10 @@
437374
},
438375
{
439376
"cell_type": "code",
440-
"execution_count": 16,
377+
"execution_count": null,
441378
"id": "4a1f6b08",
442379
"metadata": {},
443-
"outputs": [
444-
{
445-
"name": "stdout",
446-
"output_type": "stream",
447-
"text": [
448-
"Session closed\n"
449-
]
450-
}
451-
],
380+
"outputs": [],
452381
"source": [
453382
"# Close the session\n",
454383
"sess.close()\n",
@@ -462,8 +391,8 @@
462391
"source": [
463392
"## Additional Resources\n",
464393
"\n",
465-
"- [SAS Intelligent Decisioning Documentation](https://go.documentation.sas.com/doc/en/edmcdc/v_063/edmug/n04vfc1flrz8jsn1o5jblnbgx6i3.htm)\n",
466-
"- [Rules For Developing Python Code Files](https://go.documentation.sas.com/doc/en/edmcdc/v_063/edmug/n04vfc1flrz8jsn1o5jblnbgx6i3.htm#n0jrohir6wzvd0n11omfautducm3)\n",
394+
"- [SAS Intelligent Decisioning Documentation](https://documentation.sas.com/?cdcId=edmcdc&cdcVersion=default&docsetId=edmug&docsetTarget=n04vfc1flrz8jsn1o5jblnbgx6i3.htm)\n",
395+
"- [Rules For Developing Python Code Files](https://documentation.sas.com/?cdcId=edmcdc&cdcVersion=default&docsetId=edmug&docsetTarget=n04vfc1flrz8jsn1o5jblnbgx6i3.htm#n0jrohir6wzvd0n11omfautducm3)\n",
467396
"- [python-sasctl Documentation](https://sassoftware.github.io/python-sasctl/)"
468397
]
469398
}

src/sasctl/_services/files.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ class Files(Service):
2020
The file can be associated with the URI of another identifiable object
2121
(for example, a parentUri). Every file must have an assigned content type
2222
and name. Files can be retrieved individually by using the file's
23-
identifier or as a list of files by using a parentUri. Each file has its
24-
content stream associated with it. After creation, the metadata that is
23+
identifier or as a list of files by using a parentUri. Each file is
24+
associated with its content stream. After creation, the metadata that is
2525
associated with the file or the actual content can be updated. A single
2626
file can be deleted by using a specific ID. Multiple files can be deleted
2727
by specifying a parentUri. A file can be uploaded via raw request or

0 commit comments

Comments
 (0)