|
| 1 | +# Copyright © 2024, SAS Institute Inc., Cary, NC, USA. All Rights Reserved. |
| 2 | +# SPDX-License-Identifier: Apache-2.0 |
| 3 | + |
| 4 | +class SAS2py: |
| 5 | + """ |
| 6 | + This module provides the interface from the Python process to Proc Python in |
| 7 | + the SAS process. It provides user callable methods for interacting with the |
| 8 | + SAS process it's attached to. |
| 9 | + """ |
| 10 | + |
| 11 | + workpath: str |
| 12 | + """string containing the WORK libref's filesystem path, including the trailing slash.""" |
| 13 | + |
| 14 | + def hideLOG(self, tf: bool) -> None: |
| 15 | + """ |
| 16 | + This methods identifies whether the SAS LOG output for the data transfer methods, sd2df() |
| 17 | + and df2sd() is written or cached to a file. Since it's the Python log, and there's a lot |
| 18 | + of SAS code and messages that those methods generate, the default is to not see all |
| 19 | + of that cluttering up the Python log you're seeing. But, for diagnosing problems, having |
| 20 | + that shown can be helpful. When set to True (default), the contents of the SAS LOG for |
| 21 | + those methods is cached, and you can see it at any time using the printLOG() method, or |
| 22 | + clear the current contents of the cache file using clearLOG(). |
| 23 | +
|
| 24 | + :param tf: boolean default True. Whether to hide the LOG output for data transfer routines |
| 25 | +
|
| 26 | + :return: None |
| 27 | + """ |
| 28 | + |
| 29 | + def printLOG(self, method='SAS') -> None: |
| 30 | + """ |
| 31 | + This methods renders the parts of the SAS LOG output that were hidden from the data |
| 32 | + transfer routines sd2df() and df2sd(), based upon the setting of hideLOG() which |
| 33 | + defaults to True. |
| 34 | +
|
| 35 | + :param method: the default value 'SAS' uses SAS to write the output to the SAS LOG which allows |
| 36 | + for proper coloring of the output in Studio and also shows up before the Python |
| 37 | + output when in 'submit' processing. |
| 38 | + The value 'Python' uses Python to write the output to the Python log, which |
| 39 | + shows up in the SAS LOG without coloring and in the Python output where the method |
| 40 | + was executed, regardless of using 'submit' or 'interactive'. |
| 41 | +
|
| 42 | +
|
| 43 | + :return: None |
| 44 | + """ |
| 45 | + |
| 46 | + def clearLOG(self) -> None: |
| 47 | + """ |
| 48 | + This method will delete all of the currently cached LOG output, if any. Subsequent output |
| 49 | + from data transfer methods will continue to cache their output, if set to hide that output, |
| 50 | + based upon the setting of hideLOG() |
| 51 | +
|
| 52 | + :return: None |
| 53 | + """ |
| 54 | + |
| 55 | + def submit(self, code: str) -> int: |
| 56 | + """ |
| 57 | + This methods submits the code you provide back into the existing SAS session, recursively |
| 58 | + executing it while still within the PROC PYTHON that is running this method. |
| 59 | +
|
| 60 | + :param code: string of SAS code to submit |
| 61 | +
|
| 62 | + :return: None |
| 63 | + """ |
| 64 | + |
| 65 | + def symget(self, name: str) -> str: |
| 66 | + """ |
| 67 | + This methods retrieves the value for the macro variable who's name you provided. It returns |
| 68 | + the string value. If the value represents a numeric type, you can simply cast it to what type |
| 69 | + you like. |
| 70 | +
|
| 71 | + :param name: string of SAS macro variable name |
| 72 | +
|
| 73 | + :return: str |
| 74 | + """ |
| 75 | + |
| 76 | + def symput(self, name: str, val: str) -> int: |
| 77 | + """ |
| 78 | + This methods assigns a macro variable in SAS with the name and value you provide. |
| 79 | +
|
| 80 | + :param name: string of SAS macro variable name |
| 81 | + :param val: value to assign, which will be converted to a string, as that's what macro |
| 82 | + variable in SAS are |
| 83 | +
|
| 84 | + :return: int |
| 85 | + """ |
| 86 | + |
| 87 | + def pyplot(self, plot: object, filename: str = None, filepath: str = None, |
| 88 | + filetype: str='svg', **kwargs) -> None: |
| 89 | + """ |
| 90 | + This methods renders a matplot.pyplot object, or other plot object that supports pyplot's |
| 91 | + savefig() method. It simply calls savefig() writing the plot to one of the supported ODS types |
| 92 | + and submits the SAS code to render that file using ODS. |
| 93 | +
|
| 94 | + :param plot: the plot object; pyplot or equivalent supporting the same savefig() method |
| 95 | + :param filename: name of the file to create, defaults to 'matplot' |
| 96 | + :param filepath: directory path to write the file; defaults to the work library |
| 97 | + :param filetype: file type to create; defaults to 'svg'. This is passed to savefig via format=filetype |
| 98 | + :param kwargs: kwargs passed to the savefig() method |
| 99 | +
|
| 100 | + :return: None |
| 101 | + """ |
| 102 | + |
| 103 | + def renderImage(self, filename: str) -> None: |
| 104 | + """ |
| 105 | + This method renders a plot that has already been written to a file, so you |
| 106 | + can render plots from any plotting object that isn't pyplot or doesn't have the same |
| 107 | + savefig() method as pyplot. You write the plot to a supported ODS file type using that |
| 108 | + objects methods and just call this method to have it rendered. |
| 109 | +
|
| 110 | + :param filename: fully qualified name of the file to render. |
| 111 | +
|
| 112 | + :return: None |
| 113 | + """ |
| 114 | + |
| 115 | + def logMessage(self, message: str, messageType: str = 'NOTE') -> None: |
| 116 | + """ |
| 117 | + Writes a well formed message to the SAS Log |
| 118 | +
|
| 119 | + :param message: {String} - Message that should be written to the SAS log |
| 120 | + :param messageType: {String - default: NOTE} |
| 121 | + - NOTE, writes a Note to the SAS log |
| 122 | + - WARNING, writes a Warning to the SAS log |
| 123 | + - ERROR, writes an Error to the SAS log |
| 124 | +
|
| 125 | + :return: None |
| 126 | +
|
| 127 | + # Example usage |
| 128 | + SAS.logMessage('test') |
| 129 | + SAS.logMessage('testWarn', 'warning') |
| 130 | + SAS.logMessage('testError', 'error') |
| 131 | +
|
| 132 | + """ |
| 133 | + |
| 134 | + def sasdata2dataframe(self, dataset: str, rowsep: str = '\x01', colsep: str = '\x02', |
| 135 | + rowrep: str = ' ', colrep: str = ' ', **kwargs): |
| 136 | + """ |
| 137 | + See the doc for sd2df(). This is just an alias for that method |
| 138 | + """ |
| 139 | + |
| 140 | + def sd2df(self, dataset: str, rowsep: str = '\x01', colsep: str = '\x02', |
| 141 | + rowrep: str = ' ', colrep: str = ' ', **kwargs): |
| 142 | + """ |
| 143 | + This method exports the SAS Data Set to a Pandas DataFrame, returning the DataFrame object. |
| 144 | +
|
| 145 | + :param dataset: the 'libref.table(optional dataset options)' name of the SAS Data Set |
| 146 | +
|
| 147 | + These parameters are not to be used normally. Don't use them without instruction. |
| 148 | +
|
| 149 | + :param rowsep: the row separator character to use; defaults to hex(1) |
| 150 | + :param colsep: the column separator character to use; defaults to hex(2) |
| 151 | + :param rowrep: the char to convert to for any embedded rowsep chars, defaults to ' ' |
| 152 | + :param colrep: the char to convert to for any embedded colsep chars, defaults to ' ' |
| 153 | + :param errors: this is the parameter to decode(errors=) when reading the stream of data into pandas and converting |
| 154 | + from bytes to chars. If the variables in the SAS data set have invalid characters (from truncation or other) |
| 155 | + then you can provide values like 'replace' or 'ignore' to load the invalid data instead of failing. |
| 156 | + :param kwargs: these are for internal use and are generally NOT needed. |
| 157 | +
|
| 158 | + :return: Pandas DataFrame |
| 159 | + """ |
| 160 | + |
| 161 | + def dataframe2sasdata(self, df, dataset: str, |
| 162 | + LF: str = '\x01', CR: str = '\x02', |
| 163 | + colsep: str = '\x03', colrep: str = ' ', |
| 164 | + datetimes: dict={}, outfmts: dict={}, |
| 165 | + labels: dict={}, char_lengths: dict={}, **kwargs): |
| 166 | + """ |
| 167 | + See the doc for df2sd(). This is just an alias for that method |
| 168 | + """ |
| 169 | + |
| 170 | + def df2sd(self, df: 'pandas.DataFrame', dataset: str, |
| 171 | + LF: str = '\x01', CR: str = '\x02', |
| 172 | + colsep: str = '\x03', colrep: str = ' ', |
| 173 | + datetimes: dict={}, outfmts: dict={}, |
| 174 | + labels: dict={}, char_lengths: dict={}, **kwargs) -> int: |
| 175 | + """ |
| 176 | + This method imports a Pandas DataFrame to a SAS Data Set you identify via the `dataset` parameter (libref.table). |
| 177 | +
|
| 178 | + Also note that DataFrame indexes (row label) are not transferred over as columns, as they aren't actually in df.columns. |
| 179 | + You can simply use df.reset_index() before this method and df.set_index() after to have the index be a column which |
| 180 | + is transferred over to the SAS data set. If you want to create a SAS index at the same time, specify that with the |
| 181 | + output dataset options. |
| 182 | +
|
| 183 | + :param df: Pandas DataFrame to import to a SAS Data Set |
| 184 | + :param dataset: the 'libref.table(optional output data set options)' name of the SAS Data Set to create |
| 185 | + :param datetimes: dict with column names as keys and values of 'date' or 'time' to create SAS date or times instead of datetimes |
| 186 | + :param outfmts: dict with column names and SAS formats to assign to the new SAS data set |
| 187 | + :param labels: dict with column names and labels to assign to the new SAS data set |
| 188 | + :param char_lengths: a dictionary containing the names:lengths of all of the character columns. This eliminates |
| 189 | + running the code to calculate the lengths, and goes straight to transferring the data |
| 190 | +
|
| 191 | + These parameters are not to be used normally. Don't use them without instruction. |
| 192 | +
|
| 193 | + :param LF: the character to use for LF when transferring the data; defaults to hex(1) |
| 194 | + :param CR: the character to use for CR when transferring the data; defaults to hex(2) |
| 195 | + :param colsep: the column separator character used for streaming the delimited data to SAS defaults to hex(3) |
| 196 | + :param colrep: the char to convert to for any embedded colsep, LF, CR chars in the data; defaults to ' ' |
| 197 | +
|
| 198 | + :return: int |
| 199 | + """ |
| 200 | + |
| 201 | + def sasfnc(self, *arg) -> str: |
| 202 | + """ |
| 203 | + This method executes the SAS or FCMP function you provide, returning the results. |
| 204 | + The parameters vary based upon the function being called. But the first parameter |
| 205 | + is the name of the function, followed by the required parameters for that function. |
| 206 | +
|
| 207 | + :param arg[1]: name of the SAS function to call |
| 208 | + :param arg[2] to arg[n]: arguments to SAS function |
| 209 | +
|
| 210 | + :return: str |
| 211 | + """ |
0 commit comments