mirror of
https://github.com/yabwon/SAS_PACKAGES.git
synced 2026-01-06 06:40:06 +00:00
SAS Packages Framework, version 20230207
SAS Packages Framework, version 20230207
News:
- "Additional Content" feature added to the framework.
Changes in the framework related to the new feature:
- new macro `%loadPackageAddCnt()`,
- modifications in the `%generatePackage()` macro,
- new parameter in `%loadPackage()` and `%installPackage()` macros,
- new code added in loading test.
Fixes:
- IML Modules loader utility macro rewritten,
- bug fixes.
Documentation:
- documentation updated,
- spelling fixes.
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
when empty the "packages" value is used */
|
||||
)/secure
|
||||
/*** HELP END ***/
|
||||
des = 'Macro to list directories pointed by "packages" fileref, version 20230112. Run %extendPackagesFileref(HELP) for help info.'
|
||||
des = 'Macro to list directories pointed by "packages" fileref, version 20230207. Run %extendPackagesFileref(HELP) for help info.'
|
||||
;
|
||||
|
||||
%if %QUPCASE(&packages.) = HELP %then
|
||||
@@ -22,7 +22,7 @@ des = 'Macro to list directories pointed by "packages" fileref, version 20230112
|
||||
%put ### This is short help information for the `extendPackagesFileref` macro #;
|
||||
%put #-----------------------------------------------------------------------------------------#;;
|
||||
%put # #;
|
||||
%put # Macro to list directories pointed by 'packages' fileref, version `20230112` #;
|
||||
%put # Macro to list directories pointed by 'packages' fileref, version `20230207` #;
|
||||
%put # #;
|
||||
%put # A SAS package is a zip file containing a group #;
|
||||
%put # of SAS codes (macros, functions, data steps generating #;
|
||||
@@ -102,4 +102,3 @@ filename packages list;
|
||||
|
||||
*/
|
||||
|
||||
/**/
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
default value 1 means "delete tests work" */
|
||||
)/ secure minoperator
|
||||
/*** HELP END ***/
|
||||
des = 'Macro to generate SAS packages, version 20230112. Run %generatePackage() for help info.'
|
||||
des = 'Macro to generate SAS packages, version 20230207. Run %generatePackage() for help info.'
|
||||
;
|
||||
%if (%superq(filesLocation) = ) OR (%qupcase(&filesLocation.) = HELP) %then
|
||||
%do;
|
||||
@@ -38,7 +38,7 @@ des = 'Macro to generate SAS packages, version 20230112. Run %generatePackage()
|
||||
%put ### This is short help information for the `generatePackage` macro #;
|
||||
%put #-------------------------------------------------------------------------------#;
|
||||
%put # #;
|
||||
%put # Macro to generate SAS packages, version `20230112` #;
|
||||
%put # Macro to generate SAS packages, version `20230207` #;
|
||||
%put # #;
|
||||
%put # A SAS package is a zip file containing a group #;
|
||||
%put # of SAS codes (macros, functions, data steps generating #;
|
||||
@@ -96,7 +96,7 @@ des = 'Macro to generate SAS packages, version 20230112. Run %generatePackage()
|
||||
%end;
|
||||
|
||||
%put --- generatePackage START ---;
|
||||
%local zipReferrence filesWithCodes _DESCR_ _LIC_ _DUMMY_ _RC_ _PackageFileref_;
|
||||
%local zipReferrence filesWithCodes _DESCR_ _LIC_ _DUMMY_ _RC_ _PackageFileref_ additionalContent;
|
||||
%let zipReferrence = _%sysfunc(datetime(), hex6.)_;
|
||||
%let filesWithCodes = WORK._%sysfunc(datetime(), hex16.)_;
|
||||
%let _DESCR_ = _%sysfunc(datetime(), hex6.)d;
|
||||
@@ -491,6 +491,15 @@ DESCRIPTION END:
|
||||
|
|
||||
+-...
|
||||
|
|
||||
+-998_addcnt [additional content for the package, can be only one!, content of this
|
||||
| | directory is copied "as is"]
|
||||
| |
|
||||
| +-arbitrary_file1 [an arbitrary file ]
|
||||
| |
|
||||
| +-subdirectory_with_files [an arbitrary directory with some files inside]
|
||||
| |
|
||||
| +-...
|
||||
|
|
||||
+-999_test [tests executed during package generation, XCMD options must be turned-on]
|
||||
| |
|
||||
| +-test1.sas [a file with a code for test1]
|
||||
@@ -553,7 +562,9 @@ data &filesWithCodes.;
|
||||
('LIBNAME' 'MACRO' /*'MACROS'*/ 'DATA'
|
||||
'FUNCTION' /*'FUNCTIONS'*/ 'FORMAT' /*'FORMATS'*/
|
||||
'IMLMODULE' 'PROTO' 'EXEC' 'CLEAN'
|
||||
'LAZYDATA' 'TEST' 'CASLUDF'))
|
||||
'LAZYDATA' 'TEST' 'CASLUDF'
|
||||
'ADDCNT'
|
||||
))
|
||||
then
|
||||
do;
|
||||
put "WARNING: Type " type 'is not yet supported.' /
|
||||
@@ -561,30 +572,53 @@ data &filesWithCodes.;
|
||||
"WARNING- No content from it will be used to generate the package." / " ";
|
||||
goto ignoreFolder;
|
||||
end;
|
||||
|
||||
/* if it is a directory then read its content */
|
||||
if fileId then
|
||||
do j = 1 to dnum(fileId); drop j;
|
||||
file = dread(fileId, j);
|
||||
if file NE lowcase(file) then
|
||||
do;
|
||||
put 'ERROR: File with code should be named ONLY with low case letters.';
|
||||
put 'ERROR- Current value is: ' file;
|
||||
lowcase_name = lowcase(file);
|
||||
put 'ERROR- Try to use: ' lowcase_name;
|
||||
put;
|
||||
_abort_ + 1;
|
||||
end;
|
||||
fileshort = substr(file, 1, length(file) - 4); /* filename.sas -> filename */
|
||||
|
||||
if strip(reverse(file)) in: ('sas.') then output; /* ignore not ".sas" files */
|
||||
else
|
||||
do;
|
||||
put "WARNING: Only *.sas files are supported." /
|
||||
"WARNING- The file: " file "will be ignored." /
|
||||
"WARNING- ";
|
||||
end;
|
||||
end;
|
||||
/* if it is a directory then read its content... */
|
||||
if fileId then
|
||||
do;
|
||||
/* ...but! do not use files from "additional content" directory */
|
||||
if NOT (upcase(type) =: 'ADDCNT') then
|
||||
do j = 1 to dnum(fileId); drop j;
|
||||
file = dread(fileId, j);
|
||||
if file NE lowcase(file) then
|
||||
do;
|
||||
put 'ERROR: File with code should be named ONLY with low case letters.';
|
||||
put 'ERROR- Current value is: ' file;
|
||||
lowcase_name = lowcase(file);
|
||||
put 'ERROR- Try to use: ' lowcase_name;
|
||||
put;
|
||||
_abort_ + 1;
|
||||
end;
|
||||
fileshort = substr(file, 1, length(file) - 4); /* filename.sas -> filename */
|
||||
|
||||
if strip(reverse(file)) in: ('sas.') then output; /* ignore not ".sas" files */
|
||||
else
|
||||
do;
|
||||
put "WARNING: Only *.sas files are supported." /
|
||||
"WARNING- The file: " file "will be ignored." /
|
||||
"WARNING- ";
|
||||
end;
|
||||
end;
|
||||
else
|
||||
do;
|
||||
file = "additionalcontent";
|
||||
fileshort = file;
|
||||
additionalContent+1;
|
||||
if additionalContent > 1 then
|
||||
do;
|
||||
put "WARNING: Only ONE directory with additional content is allowed!" /
|
||||
"WARNING- Store all additional content in a single directory." /
|
||||
"WARNING- The directory: " folder "will be ignored." /
|
||||
"WARNING- ";
|
||||
end;
|
||||
else
|
||||
do;
|
||||
/*output;*/
|
||||
put "NOTE: Additional content located in " folder;
|
||||
call symputX('additionalContent', folder, "L");
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
ignoreFolder: ;
|
||||
rc = dclose(fileId);
|
||||
@@ -680,6 +714,55 @@ data _null_;
|
||||
end;
|
||||
run;
|
||||
|
||||
%if %superq(additionalContent) NE %then
|
||||
%do;
|
||||
/* code inspired by Kurt Bremser's "Talking to Your Host" article */
|
||||
/* https://communities.sas.com/t5/SAS-User-Groups-Library/WUSS-Presentation-Talking-to-Your-Host/ta-p/838344 */
|
||||
/* WUSS 2022 */
|
||||
|
||||
data &filesWithCodes.addCnt;
|
||||
run;
|
||||
|
||||
data &filesWithCodes.addCnt;
|
||||
length root dname $ 2048 filename $ 256 dir level 8;
|
||||
root = "&filesLocation./&additionalContent.";
|
||||
retain filename dname ' ' level 0 dir 1;
|
||||
label
|
||||
filename = "file"
|
||||
dname = "folder"
|
||||
;
|
||||
run;
|
||||
|
||||
data &filesWithCodes.addCnt;
|
||||
modify &filesWithCodes.addCnt;
|
||||
rc1=filename('tmp',catx('/',root,dname,filename));
|
||||
rc2=dopen('tmp');
|
||||
dir = 1 & rc2;
|
||||
if dir then
|
||||
do;
|
||||
dname=catx('/',dname,filename);
|
||||
filename=' ';
|
||||
end;
|
||||
replace;
|
||||
|
||||
if dir;
|
||||
|
||||
level=level+1;
|
||||
|
||||
do i=1 to dnum(rc2);
|
||||
filename=dread(rc2,i);
|
||||
output;
|
||||
end;
|
||||
rc3=dclose(rc2);
|
||||
run;
|
||||
|
||||
proc sort data=&filesWithCodes.addCnt(where=(filename is not null));
|
||||
by root dname filename;
|
||||
run;
|
||||
%end;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
proc contents data = &filesWithCodes.;
|
||||
run;
|
||||
@@ -699,9 +782,31 @@ title6 "MD5 hashed fileref of package lowcase name: &_PackageFileref_.";
|
||||
%end;
|
||||
|
||||
|
||||
proc print data = &filesWithCodes.(drop=base folderRef fileRef rc folderid _abort_ fileId);
|
||||
proc print data = &filesWithCodes.(drop=base folderRef fileRef rc folderid _abort_ fileId additionalContent);
|
||||
run;
|
||||
title;
|
||||
|
||||
%if %superq(additionalContent) NE %then
|
||||
%do;
|
||||
data _null_;
|
||||
if not nobs then
|
||||
do;
|
||||
put "WARNING: Directory with additional content is empty.";
|
||||
put "WARNING- Additional content will not be generated.";
|
||||
call symputX("additionalContent", "", "L");
|
||||
end;
|
||||
stop;
|
||||
set &filesWithCodes.addCnt nobs=nobs;
|
||||
run;
|
||||
title2 "Package additional content:";
|
||||
proc print
|
||||
data=&filesWithCodes.addCnt(drop=root dir level)
|
||||
label
|
||||
;
|
||||
run;
|
||||
%end;
|
||||
|
||||
title;
|
||||
options ¬esSourceOptions.;
|
||||
|
||||
|
||||
@@ -1146,7 +1251,7 @@ data _null_;
|
||||
|
||||
set &filesWithCodes. end = EOF nobs=NOBS;
|
||||
by TYPE notsorted;
|
||||
if (upcase(type) in: ('CLEAN' 'LAZYDATA' 'TEST' 'CASLUDF'))
|
||||
if (upcase(type) in: ('CLEAN' 'LAZYDATA' 'TEST' 'CASLUDF' 'ADDCNT'))
|
||||
then continue; /* CASLUDF type will go in the next loop */
|
||||
/* cleaning files are only included in unload.sas */
|
||||
/* lazy data are only loaded on demand
|
||||
@@ -1158,7 +1263,7 @@ data _null_;
|
||||
('LIBNAME' 'MACRO' /*'MACROS'*/ 'DATA'
|
||||
'FUNCTION' /*'FUNCTIONS'*/ 'FORMAT' /*'FORMATS'*/
|
||||
'IMLMODULE' 'PROTO' 'EXEC' 'CLEAN'
|
||||
'LAZYDATA' 'TEST'))
|
||||
'LAZYDATA' 'TEST' 'ADDCNT'))
|
||||
then
|
||||
do;
|
||||
putlog 'WARNING: Type ' type 'is not yet supported.';
|
||||
@@ -1283,23 +1388,48 @@ data _null_;
|
||||
/* FOOTERS for IML, FCMP, and PROTO - end */
|
||||
|
||||
/* add the link to the functions dataset, only for the first occurrence */
|
||||
if 1 = isFunction and (upcase(type)=:'FUNCTION') then
|
||||
/*if 1 = isFunction and (upcase(type)=:'FUNCTION') then
|
||||
do;
|
||||
put "options APPEND=(cmplib = work.%lowcase(&packageName.fcmp));"/;
|
||||
end;*/
|
||||
if 1 = FIRST.type and (upcase(type)=:'FUNCTION') then
|
||||
do;
|
||||
put '%sysfunc(ifc(0<' /
|
||||
' %sysfunc(findw((%sysfunc(getoption(cmplib)))' /
|
||||
" ,work.%lowcase(&packageName.fcmp),""'( )'"",RIO))" /
|
||||
',,%str(options' " APPEND=(cmplib = work.%lowcase(&packageName.fcmp));)" /
|
||||
'))' ;
|
||||
end;
|
||||
|
||||
/* add the link to the proto functions dataset, only for the first occurrence */
|
||||
if 1 = isProto and (upcase(type)=:'PROTO') then
|
||||
/*if 1 = isProto and (upcase(type)=:'PROTO') then
|
||||
do;
|
||||
put "options APPEND=(cmplib = work.%lowcase(&packageName.proto));"/;
|
||||
end;*/
|
||||
if 1 = FIRST.type and (upcase(type)=:'PROTO') then
|
||||
do;
|
||||
put '%sysfunc(ifc(0<' /
|
||||
' %sysfunc(findw((%sysfunc(getoption(cmplib)))' /
|
||||
" ,work.%lowcase(&packageName.proto),""'( )'"",RIO))" /
|
||||
',,%str(options' " APPEND=(cmplib = work.%lowcase(&packageName.proto));)" /
|
||||
'))' ;
|
||||
end;
|
||||
|
||||
/* add the link to the formats catalog, only for the first occurrence */
|
||||
if 1 = isFormat and (upcase(type)=:'FORMAT') then
|
||||
/*if 1 = isFormat and (upcase(type)=:'FORMAT') then
|
||||
do;
|
||||
put "options INSERT=(fmtsearch = work.%lowcase(&packageName.format));"/;
|
||||
end;*/
|
||||
if 1 = FIRST.type and (upcase(type)=:'FORMAT') then
|
||||
do;
|
||||
put '%sysfunc(ifc(0<' /
|
||||
' %sysfunc(findw((%sysfunc(getoption(fmtsearch)))' /
|
||||
" ,work.%lowcase(&packageName.format),""'( )'"",RIO))" /
|
||||
',,%str(options' " INSERT=(fmtsearch = work.%lowcase(&packageName.format));)" /
|
||||
'))' ;
|
||||
end;
|
||||
|
||||
|
||||
end; /* loopOverTypes - start */
|
||||
|
||||
/* this is a header for CASLudf macro */
|
||||
@@ -1333,7 +1463,7 @@ data _null_;
|
||||
' !! '' %put %str( )when set to the value of `HELP` (upcase letters!) displays this help message.;''' /
|
||||
|
||||
' !! '' %put - `depList` [technical] contains the list of dependencies required by the package.;''' /
|
||||
' !! '' %put %str( )for _this_ instance of the macro the default value is: `';
|
||||
' !! '' %put %str( )for _this_ instance of the macro the default value is: `' @;
|
||||
%if %superq(packageReqPackages) ne %then
|
||||
%do;
|
||||
do i = 1 to countw(packageReqPackages, ",", "Q");
|
||||
@@ -1343,7 +1473,7 @@ data _null_;
|
||||
%end;
|
||||
put +(-1) '`.;''' /
|
||||
' !! '' %put The macro generated: '' !! put(dtCASLudf, E8601DT19.-L) !! ";"' /
|
||||
' !! '' %put with the SAS Packages Framework version 20230112.;''' /
|
||||
' !! '' %put with the SAS Packages Framework version 20230207.;''' /
|
||||
' !! '' %put ****************************************************************************;''' /
|
||||
' !! '' %GOTO theEndOfTheMacro;''' /
|
||||
' !! '' %end;''' ;
|
||||
@@ -1476,9 +1606,9 @@ data _null_;
|
||||
put '%if (%str(*)=%superq(cherryPick)) or 0 < &cherryPick_IML_ALL. %then %do;';
|
||||
|
||||
/* this "text wrapper" was added to get datetime generated when macro is compiled */
|
||||
put "data _null_; dtIML=datetime(); IML='"; /* wrapper start */
|
||||
put "data _null_; dtIML=datetime(); IML="; /* wrapper start */
|
||||
|
||||
put '%macro ' " &packageName.IML(list=1,err=ERROR,resetIMLstorage=1,depList=" ;
|
||||
put '''%macro ' " &packageName.IML(list=1,err=ERROR,resetIMLstorage=1,depList=" ;
|
||||
%if %superq(packageReqPackages) ne %then
|
||||
%do;
|
||||
length reqPackage $ 32;
|
||||
@@ -1488,25 +1618,25 @@ data _null_;
|
||||
end;
|
||||
put ;
|
||||
%end;
|
||||
put ")/ des = ""IML Modules loader for &packageName. package""; " /
|
||||
' %if HELP = %superq(list) %then ' /
|
||||
' %do; ' /
|
||||
' %put ****************************************************************************; ' /
|
||||
' %put This is help for the `' "&packageName.IML" '` macro; ' /
|
||||
' %put Parameters (optional) are the following:; ' /
|
||||
put "' !! ')/ des = ""IML Modules loader for &packageName. package""; ' !!" /
|
||||
''' %if HELP = %superq(list) %then '' !!' /
|
||||
''' %do; '' !!' /
|
||||
''' %put ****************************************************************************; '' !!' /
|
||||
''' %put This is help for the `' "&packageName.IML" '` macro; '' !!' /
|
||||
''' %put Parameters (optional) are the following:; '' !!' /
|
||||
|
||||
' %put - `list` indicates if the list of loaded moduls should be displayed,; ' /
|
||||
' %put %str( )when set to the value of `1` (the default) runs `SHOW MODULES%str(;)`,; ' /
|
||||
' %put %str( )when set to the value of `HELP` (upcase letters!) displays this help message.;' /
|
||||
''' %put - `list` indicates if the list of loaded moduls should be displayed,; '' !!' /
|
||||
''' %put %str( )when set to the value of `1` (the default) runs `SHOW MODULES%str(;)`,; '' !!' /
|
||||
''' %put %str( )when set to the value of `HELP` (upcase letters!) displays this help message.;'' !!' /
|
||||
|
||||
' %put - `resetIMLstorage` indicates if to reset default moduls storage,; ' /
|
||||
' %put %str( )when set to `1` (the default) runs `RESET STORAGE = WORK.IMLSTOR%str(;)`.; ' /
|
||||
''' %put - `resetIMLstorage` indicates if to reset default moduls storage,; '' !!' /
|
||||
''' %put %str( )when set to `1` (the default) runs `RESET STORAGE = WORK.IMLSTOR%str(;)`.; '' !!' /
|
||||
|
||||
' %put - `err` [technical] indicates message type in case of missing modules catalog,; ' /
|
||||
' %put %str( )when set to the value of `ERROR` (the default) prints Error message.; ' /
|
||||
''' %put - `err` [technical] indicates message type in case of missing modules catalog,; '' !!' /
|
||||
''' %put %str( )when set to the value of `ERROR` (the default) prints Error message.; '' !!' /
|
||||
|
||||
' %put - `depList` [technical] contains the list of dependencies required by the package.; ' /
|
||||
' %put %str( )for _this_ instance of the macro the default value is: `';
|
||||
''' %put - `depList` [technical] contains the list of dependencies required by the package.; '' !!' /
|
||||
''' %put %str( )for _this_ instance of the macro the default value is: `' @;
|
||||
%if %superq(packageReqPackages) ne %then
|
||||
%do;
|
||||
do i = 1 to countw(packageReqPackages, ",", "Q");
|
||||
@@ -1514,50 +1644,50 @@ data _null_;
|
||||
put reqPackage @;
|
||||
end;
|
||||
%end;
|
||||
put +(-1) '`.;' /
|
||||
' %put The macro generated: ''' " !! put(dtIML, E8601DT19.-L) !! " '''; ' /
|
||||
' %put with the SAS Packages Framework version 20230112.; ' /
|
||||
' %put ****************************************************************************; ' /
|
||||
' %GOTO theEndOfTheMacro; ' /
|
||||
' %end; ' /
|
||||
put +(-1) '`.; '' !!' /
|
||||
''' %put The macro generated: ''' " !! put(dtIML, E8601DT19.-L) !! " '''; '' !!' /
|
||||
''' %put with the SAS Packages Framework version 20230207.; '' !! ' /
|
||||
''' %put ****************************************************************************; '' !! ' /
|
||||
''' %GOTO theEndOfTheMacro; '' !! ' /
|
||||
''' %end; '' !! ' /
|
||||
|
||||
' %local localSYSmacroName localPackageName i depListNm; ' /
|
||||
' %let localSYSmacroName = &sysmacroname.; ' /
|
||||
' %let localSYSmacroName = %LOWCASE(&localSYSmacroName.); ' /
|
||||
' %let localPackageName = %substr(&localSYSmacroName.,1,%eval(%length(&localSYSmacroName.)-3));' /
|
||||
' ' /
|
||||
' %if %superq(depList) ne %then ' /
|
||||
' %do; ' /
|
||||
' %do i = 1 %to %sysfunc(countw(&depList.,%str( ))); ' /
|
||||
' %let depListNm = %scan(&depList.,&i.,%str( )); ' /
|
||||
' %if %SYSMACEXIST(&depListNm.IML) %then ' /
|
||||
' %do; ' /
|
||||
' %&depListNm.IML(list=0,err=&err.,resetIMLstorage=0) ' /
|
||||
' %end; ' /
|
||||
' %end; ' /
|
||||
' %end; ' /
|
||||
' %if %sysfunc(CEXIST(WORK.&localSYSmacroName.)) %then ' /
|
||||
' %do; ' /
|
||||
' %put NOTE: Loading IML Modules from package &localPackageName.; ' /
|
||||
' RESET STORAGE = WORK.&localSYSmacroName.; ' /
|
||||
' LOAD MODULE = _all_; ' /
|
||||
' %end; ' /
|
||||
' %else ' /
|
||||
' %do; ' /
|
||||
' %put %superq(err): IML Modules not provided; ' /
|
||||
' %let list = 0; ' /
|
||||
' %end; ' /
|
||||
' %if 1 = %superq(list) %then ' /
|
||||
' %do; ' /
|
||||
' SHOW MODULES; ' /
|
||||
' %end; ' /
|
||||
' %if 1 = %superq(resetIMLstorage) %then ' /
|
||||
' %do; ' /
|
||||
' RESET STORAGE = WORK.IMLSTOR; ' /
|
||||
' %end; ' /
|
||||
'%theEndOfTheMacro: %mend; ' ;
|
||||
''' %local localSYSmacroName localPackageName i depListNm; '' !! ' /
|
||||
''' %let localSYSmacroName = &sysmacroname.; '' !! ' /
|
||||
''' %let localSYSmacroName = %LOWCASE(&localSYSmacroName.); '' !! ' /
|
||||
''' %let localPackageName = %substr(&localSYSmacroName.,1,%eval(%length(&localSYSmacroName.)-3));'' !!' /
|
||||
|
||||
put "'; rc = resolve(IML); run;"; /* wrapper end */
|
||||
''' %if %superq(depList) ne %then '' !!' /
|
||||
''' %do; '' !!' /
|
||||
''' %do i = 1 %to %sysfunc(countw(&depList.,%str( ))); '' !!' /
|
||||
''' %let depListNm = %scan(&depList.,&i.,%str( )); '' !!' /
|
||||
''' %if %SYSMACEXIST(&depListNm.IML) %then '' !!' /
|
||||
''' %do; '' !!' /
|
||||
''' %&depListNm.IML(list=0,err=&err.,resetIMLstorage=0) '' !!' /
|
||||
''' %end; '' !!' /
|
||||
''' %end; '' !!' /
|
||||
''' %end; '' !!' /
|
||||
''' %if %sysfunc(CEXIST(WORK.&localSYSmacroName.)) %then '' !!' /
|
||||
''' %do; '' !!' /
|
||||
''' %put NOTE: Loading IML Modules from package &localPackageName.; '' !!' /
|
||||
''' RESET STORAGE = WORK.&localSYSmacroName.; '' !!' /
|
||||
''' LOAD MODULE = _all_; '' !!' /
|
||||
''' %end; '' !!' /
|
||||
''' %else '' !!' /
|
||||
''' %do; '' !!' /
|
||||
''' %put %superq(err): IML Modules not provided; '' !!' /
|
||||
''' %let list = 0; '' !!' /
|
||||
''' %end; '' !!' /
|
||||
''' %if 1 = %superq(list) %then '' !!' /
|
||||
''' %do; '' !!' /
|
||||
''' SHOW MODULES; '' !!' /
|
||||
''' %end; '' !!' /
|
||||
''' %if 1 = %superq(resetIMLstorage) %then '' !!' /
|
||||
''' %do; '' !!' /
|
||||
''' RESET STORAGE = WORK.IMLSTOR; '' !!' /
|
||||
''' %end; '' !!' /
|
||||
'''%theEndOfTheMacro: %mend; '' ' ;
|
||||
|
||||
put "; rc = resolve(IML); run;"; /* wrapper end */
|
||||
|
||||
put '%put NOTE: Macro named:; ';
|
||||
put '%put %nrstr( %%)' "&packageName." 'IML(); ';
|
||||
@@ -2036,7 +2166,7 @@ data _null_;
|
||||
put " stop; ";
|
||||
put "run; ";
|
||||
|
||||
/* cleanup */
|
||||
/* clean-up */
|
||||
put "proc delete data = WORK._last_; ";
|
||||
put "run; ";
|
||||
put 'options ls = &ls_tmp. ps = &ps_tmp. ¬es_tmp. &source_tmp.; ' /;
|
||||
@@ -2124,7 +2254,15 @@ data _null_;
|
||||
put ' end ; ';
|
||||
%end;
|
||||
|
||||
put 'put "***"; put "* SAS package generated by generatePackage, version 20230112 *"; put "***";';
|
||||
|
||||
%if %superq(additionalContent) NE %then
|
||||
%do;
|
||||
put 'put ;' / 'put @3 ''Package contains additional content, run: %loadPackageAddCnt(' "&packageName." ') to load it'';';
|
||||
put "put @3 'or look for the %lowcase(&packageName.)_AdditionalContent directory in the Packages fileref';";
|
||||
put "put @3 'localization (only if additional content was deployed during the installation process).';" / "put ;";
|
||||
%end;
|
||||
|
||||
put 'put "***"; put "* SAS package generated by generatePackage, version 20230207 *"; put "***";';
|
||||
|
||||
put 'run; ' /;
|
||||
|
||||
@@ -2247,7 +2385,7 @@ data _null_;
|
||||
if NOBS = 0 then stop;
|
||||
|
||||
set &filesWithCodes. nobs = NOBS end = EOF;
|
||||
if (upcase(type) not in: ('TEST')); /* test files are not to be copied */
|
||||
if (upcase(type) not in: ('TEST' 'ADDCNT')); /* test files and additional content are not to be copied */
|
||||
|
||||
call execute(cat ('filename _SPFIN_ "', catx('/', base, folder, file), '";'));
|
||||
call execute(cats("filename _SPFOUT_ ZIP '", base, "/%lowcase(&packageName.).zip' member='_", folder, ".", file, "';") );
|
||||
@@ -2322,6 +2460,95 @@ data _null_;
|
||||
end;
|
||||
run;
|
||||
|
||||
|
||||
/* Additional Content */
|
||||
/* check if a file with additional content exists in the Work library */
|
||||
filename _SPFOUT_ "%sysfunc(pathname(work,L))/addcnt.zip";
|
||||
%if %sysfunc(fexist(_SPFOUT_)) %then
|
||||
%do;
|
||||
%if %sysfunc(fdelete(_SPFOUT_)) NE 0 %then
|
||||
%do;
|
||||
%put ERROR: Additional content for package not generated!;
|
||||
%put ERROR- Delete "%sysfunc(pathname(work,L))/addcnt.zip" file;
|
||||
%put ERROR- and try again.;
|
||||
%let additionalContent=;
|
||||
%end;
|
||||
%end;
|
||||
filename _SPFOUT_ clear;
|
||||
|
||||
%if %superq(additionalContent) NE %then
|
||||
%do;
|
||||
|
||||
%put ;
|
||||
%put Status of additional content for the package:;
|
||||
/* create "addcnt.zip" file for Additional Content */
|
||||
data _null_;
|
||||
set &filesWithCodes.addCnt;
|
||||
if dir=0;
|
||||
|
||||
rc1=filename("_SPFIN_" , catx('/',root,dname,filename), "disk", "lrecl=1 recfm=n");
|
||||
rc1txt=sysmsg();
|
||||
rc2=filename("_SPFOUT_", "%sysfunc(pathname(work,L))/addcnt.zip", "ZIP"
|
||||
,"lrecl=1 recfm=n member='" !! catx('/',dname,filename) !! "'");
|
||||
rc2txt=sysmsg();
|
||||
|
||||
do _N_ = 1 to 10;
|
||||
rc3=fcopy("_SPFIN_","_SPFOUT_");
|
||||
rc3txt=sysmsg();
|
||||
if fexist("_SPFOUT_") then leave;
|
||||
else sleeprc=sleep(0.25,1);
|
||||
end;
|
||||
|
||||
rc4=fexist("_SPFOUT_");
|
||||
rc4txt=sysmsg();
|
||||
|
||||
if rc4 = 0 then
|
||||
do;
|
||||
call symputX("createPackageContentStatus",1,"L");
|
||||
put "ERROR:" @;
|
||||
end;
|
||||
put "AddCnt: " dname +(-1) "/" filename /
|
||||
"Try=" _N_ "Return codes:" /
|
||||
(rc:) (=);
|
||||
|
||||
rc1=filename("_SPFIN_");
|
||||
rc2=filename("_SPFOUT_");
|
||||
run;
|
||||
|
||||
/* inserting addcnt.zip into the package file */
|
||||
%put ;
|
||||
%put Status of inserting "addcnt.zip" into the package file:;
|
||||
data _null_;
|
||||
rc1=filename("_SPFIN_" , "%sysfunc(pathname(work,L))/addcnt.zip", "disk", "lrecl=1 recfm=n");
|
||||
rc1txt=sysmsg();
|
||||
rc2=filename("_SPFOUT_", pathname("&zipReferrence.","F"), "ZIP", "lrecl=1 recfm=n member='addcnt.zip'");
|
||||
rc2txt=sysmsg();
|
||||
|
||||
do _N_ = 1 to 10;
|
||||
rc3=fcopy("_SPFIN_","_SPFOUT_");
|
||||
rc3txt=sysmsg();
|
||||
if fexist("_SPFOUT_") then leave;
|
||||
else sleeprc=sleep(0.25,1);
|
||||
end;
|
||||
|
||||
rc4=fexist("_SPFOUT_");
|
||||
rc4txt=sysmsg();
|
||||
|
||||
if rc4 then
|
||||
rc5=fdelete("_SPFIN_");
|
||||
else
|
||||
do;
|
||||
call symputX("createPackageContentStatus",1,"L");
|
||||
put "ERROR:" @;
|
||||
end;
|
||||
put "File addcnt.zip, Try=" _N_ "Return codes:" /
|
||||
(rc:) (=);
|
||||
|
||||
rc1=filename("_SPFIN_");
|
||||
rc2=filename("_SPFOUT_");
|
||||
run;
|
||||
%end;
|
||||
|
||||
options notes source;
|
||||
%put NOTE-;
|
||||
%put NOTE-######################################################;
|
||||
@@ -2444,6 +2671,10 @@ run;
|
||||
put @n '%unloadPackage'"(&packageName.,";
|
||||
put @n " path=&filesLocation.) " /;
|
||||
|
||||
/* additional content */
|
||||
put @n '%loadPackageAddCnt'"(&packageName.,";
|
||||
put @n " path=&filesLocation.) " /;
|
||||
|
||||
put ;
|
||||
put '***************************************************';
|
||||
run;
|
||||
@@ -2661,6 +2892,10 @@ data _null_;
|
||||
put '%unloadPackage'"(&packageName.,";
|
||||
put " path=&filesLocation.) " /;
|
||||
|
||||
/* additional content */
|
||||
put '%loadPackageAddCnt'"(&packageName.,";
|
||||
put " path=&filesLocation.) " /;
|
||||
|
||||
put "filename packages '&filesLocation.';" /
|
||||
'%listPackages() ' /;
|
||||
|
||||
@@ -2909,6 +3144,11 @@ options "elenmax_tmp.;
|
||||
|
||||
proc sql;
|
||||
drop table &filesWithCodes.;
|
||||
|
||||
%if %sysfunc(exist(&filesWithCodes.addCnt)) %then
|
||||
%do;
|
||||
drop table &filesWithCodes.addCnt;
|
||||
%end;
|
||||
quit;
|
||||
|
||||
/* turn on the original value of the note about quoted string length */
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
*/
|
||||
)/secure
|
||||
/*** HELP END ***/
|
||||
des = 'Macro to get help about SAS package, version 20230112. Run %helpPackage() for help info.'
|
||||
des = 'Macro to get help about SAS package, version 20230207. Run %helpPackage() for help info.'
|
||||
;
|
||||
%if (%superq(packageName) = ) OR (%qupcase(&packageName.) = HELP) %then
|
||||
%do;
|
||||
@@ -39,7 +39,7 @@ des = 'Macro to get help about SAS package, version 20230112. Run %helpPackage()
|
||||
%put ### This is short help information for the `helpPackage` macro #;
|
||||
%put #-------------------------------------------------------------------------------#;
|
||||
%put # #;
|
||||
%put # Macro to get help about SAS packages, version `20230112` #;
|
||||
%put # Macro to get help about SAS packages, version `20230207` #;
|
||||
%put # #;
|
||||
%put # A SAS package is a zip file containing a group #;
|
||||
%put # of SAS codes (macros, functions, data steps generating #;
|
||||
@@ -169,7 +169,7 @@ TODO:
|
||||
- add MD5(&packageName.) value hash instead "package" word in filenames [DONE]
|
||||
*/
|
||||
|
||||
/* Macros to install SAS packages, version 20230112 */
|
||||
/* Macros to install SAS packages, version 20230207 */
|
||||
/* A SAS package is a zip file containing a group of files
|
||||
with SAS code (macros, functions, data steps generating
|
||||
data, etc.) wrapped up together and %INCLUDEed by
|
||||
|
||||
@@ -10,11 +10,13 @@
|
||||
, URLuser = /* user name for the password protected URLs */
|
||||
, URLpass = /* password for the password protected URLs */
|
||||
, URLoptions = /* options for the `sourcePath` URLs */
|
||||
, loadAddCnt=0 /* should the additional content be loaded?
|
||||
default is 0 - means No, 1 means Yes */
|
||||
)
|
||||
/secure
|
||||
minoperator
|
||||
/*** HELP END ***/
|
||||
des = 'Macro to install SAS package, version 20230112. Run %%installPackage() for help info.'
|
||||
des = 'Macro to install SAS package, version 20230207. Run %%installPackage() for help info.'
|
||||
;
|
||||
%if (%superq(packagesNames) = ) OR (%qupcase(&packagesNames.) = HELP) %then
|
||||
%do;
|
||||
@@ -29,7 +31,7 @@ des = 'Macro to install SAS package, version 20230112. Run %%installPackage() fo
|
||||
%put ### This is short help information for the `installPackage` macro #;
|
||||
%put #--------------------------------------------------------------------------------------------#;;
|
||||
%put # #;
|
||||
%put # Macro to install SAS packages, version `20230112` #;
|
||||
%put # Macro to install SAS packages, version `20230207` #;
|
||||
%put # #;
|
||||
%put # A SAS package is a zip file containing a group #;
|
||||
%put # of SAS codes (macros, functions, data steps generating #;
|
||||
@@ -86,6 +88,13 @@ des = 'Macro to install SAS package, version 20230112. Run %%installPackage() fo
|
||||
%put # - `URLoptions=` Options for the `sourcePath` URLs filename. Consult the SAS #;
|
||||
%put # documentation for the further details. #;
|
||||
%put # #;
|
||||
%put # - `loadAddCnt=` *Optional.* A package zip may contain additional #;
|
||||
%put # content. The option indicates if it should be loaded #;
|
||||
%put # Default value of zero (`0`) means "No", one (`1`) #;
|
||||
%put # means "Yes". Content is extracted into the **packages** fileref #;
|
||||
%put # directory in `<packageName>_AdditionalContent` folder. #;
|
||||
%put # For other locations use `%nrstr(%%loadPackageAddCnt())` macro. #;
|
||||
%put # #;
|
||||
%put #--------------------------------------------------------------------------------------------#;
|
||||
%put # #;
|
||||
%put # Visit: `https://github.com/yabwon/SAS_PACKAGES/tree/main/SPF/Documentation` #;
|
||||
@@ -286,6 +295,8 @@ des = 'Macro to install SAS package, version 20230112. Run %%installPackage() fo
|
||||
filename out list;
|
||||
*/
|
||||
/* copy the file byte-by-byte */
|
||||
%local installationRC;
|
||||
%let installationRC=1;
|
||||
data _null_;
|
||||
length filein 8 out_path in_path $ 4096;
|
||||
out_path = pathname ("&out");
|
||||
@@ -323,7 +334,7 @@ des = 'Macro to install SAS package, version 20230112. Run %%installPackage() fo
|
||||
if symgetn("replace")=1 then
|
||||
do;
|
||||
put @2 "The following file will be replaced during "
|
||||
/ @2 "instalation of the &packageName. package: "
|
||||
/ @2 "installation of the &packageName. package: "
|
||||
/ @5 out_path;
|
||||
rc = FDELETE("&out");
|
||||
rc = FCOPY("&in", "&out");
|
||||
@@ -337,10 +348,24 @@ des = 'Macro to install SAS package, version 20230112. Run %%installPackage() fo
|
||||
end;
|
||||
|
||||
put @2 "Done with return code " rc= "(zero = success)";
|
||||
call symputX("installationRC", rc, "L");
|
||||
run;
|
||||
|
||||
filename &in clear;
|
||||
filename &out clear;
|
||||
|
||||
%if 1 = &loadAddCnt.
|
||||
AND 0 = &installationRC.
|
||||
AND NOT (%upcase(&packageName.) in (SPFINIT SASPACKAGEFRAMEWORK SASPACKAGESFRAMEWORK))
|
||||
%then
|
||||
%do;
|
||||
%put; %put - Additional content loading - Start -;
|
||||
%loadPackageAddCnt(&packageName.
|
||||
,path=&firstPackagesPath.
|
||||
,target=&firstPackagesPath.
|
||||
)
|
||||
%put - Additional content loading - End -;
|
||||
%end;
|
||||
%put *** %lowcase(&packageName.) end *******************************************;
|
||||
/*-++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-*/
|
||||
%end;
|
||||
@@ -458,7 +483,7 @@ des = 'Macro to install SAS package, version 20230112. Run %%installPackage() fo
|
||||
|
||||
/* Macro to list SAS packages in packages folder.
|
||||
|
||||
Version 20230112
|
||||
Version 20230207
|
||||
|
||||
A SAS package is a zip file containing a group
|
||||
of SAS codes (macros, functions, data steps generating
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/*+listPackages+*/
|
||||
|
||||
%macro listPackages()/secure PARMBUFF
|
||||
des = 'Macro to list SAS packages from `packages` fileref, type %listPackages(HELP) for help, version 20230112.'
|
||||
des = 'Macro to list SAS packages from `packages` fileref, type %listPackages(HELP) for help, version 20230207.'
|
||||
;
|
||||
%if %QUPCASE(&SYSPBUFF.) = %str(%(HELP%)) %then
|
||||
%do;
|
||||
@@ -16,7 +16,7 @@ des = 'Macro to list SAS packages from `packages` fileref, type %listPackages(HE
|
||||
%put ### This is short help information for the `listPackages` macro #;
|
||||
%put #-----------------------------------------------------------------------------------------#;;
|
||||
%put # #;
|
||||
%put # Macro to list available SAS packages, version `20230112` #;
|
||||
%put # Macro to list available SAS packages, version `20230207` #;
|
||||
%put # #;
|
||||
%put # A SAS package is a zip file containing a group #;
|
||||
%put # of SAS codes (macros, functions, data steps generating #;
|
||||
@@ -166,7 +166,7 @@ options ls = &ls_tmp. ps = &ps_tmp. ¬es_tmp. &source_tmp.;
|
||||
|
||||
/* Macro to generate SAS packages.
|
||||
|
||||
Version 20230112
|
||||
Version 20230207
|
||||
|
||||
A SAS package is a zip file containing a group
|
||||
of SAS codes (macros, functions, data steps generating
|
||||
|
||||
@@ -29,9 +29,11 @@
|
||||
to be loaded into the session, default value "*" means
|
||||
"load all elements of the package"
|
||||
*/
|
||||
, loadAddCnt=0 /* should the additional content be loaded?
|
||||
default is 0 - means No, 1 means Yes */
|
||||
)/secure
|
||||
/*** HELP END ***/
|
||||
des = 'Macro to load SAS package, version 20230112. Run %loadPackage() for help info.'
|
||||
des = 'Macro to load SAS package, version 20230207. Run %loadPackage() for help info.'
|
||||
minoperator
|
||||
;
|
||||
%if (%superq(packageName) = ) OR (%qupcase(&packageName.) = HELP) %then
|
||||
@@ -47,7 +49,7 @@ minoperator
|
||||
%put ### This is short help information for the `loadPackage` macro #;
|
||||
%put #-------------------------------------------------------------------------------#;
|
||||
%put # #;
|
||||
%put # Macro to *load* SAS packages, version `20230112` #;
|
||||
%put # Macro to *load* SAS packages, version `20230207` #;
|
||||
%put # #;
|
||||
%put # A SAS package is a zip file containing a group #;
|
||||
%put # of SAS codes (macros, functions, data steps generating #;
|
||||
@@ -96,6 +98,13 @@ minoperator
|
||||
%put # Default value of an asterisk (*) means: #;
|
||||
%put # "load all elements of the package". #;
|
||||
%put # #;
|
||||
%put # - `loadAddCnt=` *Optional.* A package zip may contain additional #;
|
||||
%put # content. The option indicates if it should be loaded #;
|
||||
%put # Default value of zero (`0`) means "No", one (`1`) #;
|
||||
%put # means "Yes". Content is extracted into the **Work** #;
|
||||
%put # directory in `<packageName>_AdditionalContent` folder. #;
|
||||
%put # For other locations use `%nrstr(%%loadPackageAddCnt())` macro. #;
|
||||
%put # #;
|
||||
%put #-------------------------------------------------------------------------------#;
|
||||
%put # #;
|
||||
%put # Visit: `https://github.com/yabwon/SAS_PACKAGES/tree/main/SPF/Documentation` #;
|
||||
@@ -187,6 +196,11 @@ minoperator
|
||||
%let cherryPick=*;
|
||||
%end;
|
||||
|
||||
%if %superq(loadAddCnt) NE 1 %then
|
||||
%do;
|
||||
%let loadAddCnt = 0;
|
||||
%end;
|
||||
|
||||
filename &_PackageFileref_. &ZIP.
|
||||
/* put location of package myPackageFile.zip here */
|
||||
"&path./%lowcase(&packageName.).&zip." %unquote(&options.)
|
||||
@@ -224,13 +238,20 @@ minoperator
|
||||
%if %bquote(&packageEncoding.) NE %then &packageEncoding. ;
|
||||
%else utf8 ;
|
||||
;
|
||||
%if %bquote(&lazyData.) = %then
|
||||
%if %superq(lazyData) = %then
|
||||
%do;
|
||||
%local tempLoad_minoperator;
|
||||
%let tempLoad_minoperator = %sysfunc(getoption(minoperator));
|
||||
options minoperator; /* MinOperator option is required for cherryPicking to work */
|
||||
%include &_PackageFileref_.(load.sas) / &source2.;
|
||||
options &tempLoad_minoperator.;
|
||||
%if 1 = &loadAddCnt. %then
|
||||
%do;
|
||||
%put; %put - Additional content loading - Start -;
|
||||
%loadPackageAddCnt(&packageName.,
|
||||
path=&path.)
|
||||
%put - Additional content loading - End -;
|
||||
%end;
|
||||
%end;
|
||||
%else
|
||||
%do;
|
||||
|
||||
365
SPF/Macros/loadpackageaddcnt.sas
Normal file
365
SPF/Macros/loadpackageaddcnt.sas
Normal file
@@ -0,0 +1,365 @@
|
||||
/*+loadPackageAddCnt+*/
|
||||
/*** HELP START ***/
|
||||
|
||||
%macro loadPackageAddCnt(
|
||||
packageName /* name of a package,
|
||||
e.g. myPackage,
|
||||
required and not null */
|
||||
, path = %sysfunc(pathname(packages)) /* location of a package,
|
||||
by default it looks for
|
||||
location of "packages" fileref */
|
||||
, target = %sysfunc(pathname(WORK)) /* a path in which the directory with
|
||||
additional content will be generated,
|
||||
name of directory created is set to
|
||||
`&packageName._AdditionalContent`
|
||||
default location is SAS work */
|
||||
, source2 = /*source2*/ /* option to print out details,
|
||||
null by default */
|
||||
, requiredVersion = . /* option to test if loaded package
|
||||
is provided in required version */
|
||||
)/secure
|
||||
/*** HELP END ***/
|
||||
des = 'Macro to load additional content for a SAS package, version 20230207. Run %loadPackageAddCnt() for help info.'
|
||||
minoperator
|
||||
;
|
||||
%if (%superq(packageName) = ) OR (%qupcase(&packageName.) = HELP) %then
|
||||
%do;
|
||||
%local options_tmp ;
|
||||
%let options_tmp = ls=%sysfunc(getoption(ls))ps=%sysfunc(getoption(ps))
|
||||
%sysfunc(getoption(notes)) %sysfunc(getoption(source))
|
||||
msglevel=%sysfunc(getoption(msglevel))
|
||||
;
|
||||
options NOnotes NOsource ls=MAX ps=MAX msglevel=N;
|
||||
%put ;
|
||||
%put #################################################################################;
|
||||
%put ### This is short help information for the `loadPackageAddCnt` macro #;
|
||||
%put #-------------------------------------------------------------------------------#;
|
||||
%put # #;
|
||||
%put # Macro to *load* additional content for a SAS package, version `20230207` #;
|
||||
%put # #;
|
||||
%put # A SAS package is a zip file containing a group #;
|
||||
%put # of SAS codes (macros, functions, data steps generating #;
|
||||
%put # data, etc.) wrapped up together and included by #;
|
||||
%put # a single `load.sas` file (also embedded inside the zip). #;
|
||||
%put # #;
|
||||
%put # The `%nrstr(%%loadPackageAddCnt())` macro loads additional content #;
|
||||
%put # for a package (of course only if one is provided). #;
|
||||
%put # #;
|
||||
%put #-------------------------------------------------------------------------------#;
|
||||
%put #### Parameters: #;
|
||||
%put # #;
|
||||
%put # 1. `packageName` *Required.* Name of a package, e.g. myPackage, #;
|
||||
%put # Required and not null, default use case: #;
|
||||
%put # `%nrstr(%%loadPackageAddCnt(myPackage))`. #;
|
||||
%put # If empty displays this help information. #;
|
||||
%put # #;
|
||||
%put # - `path=` *Optional.* Location of a package. By default it #;
|
||||
%put # looks for location of the **packages** fileref, i.e. #;
|
||||
%put # `%nrstr(%%sysfunc(pathname(packages)))` #;
|
||||
%put # #;
|
||||
%put # - `target=` *Optional.* Location where the directory with #;
|
||||
%put # additional content will be generated, #;
|
||||
%put # name of the directory created is set to #;
|
||||
%put # `<packagename>_AdditionalContent`, the default #;
|
||||
%put # location is `%nrstr(%%sysfunc(pathname(WORK)))` #;
|
||||
%put # #;
|
||||
%put # - `source2=` *Optional.* Option to print out details about #;
|
||||
%put # what is loaded, null by default. #;
|
||||
%put # #;
|
||||
%put # - `requiredVersion=` *Optional.* Option to test if the loaded #;
|
||||
%put # package is provided in required version, #;
|
||||
%put # default value: `.` #;
|
||||
%put # #;
|
||||
%put # #;
|
||||
%put #-------------------------------------------------------------------------------#;
|
||||
%put # #;
|
||||
%put # Visit: `https://github.com/yabwon/SAS_PACKAGES/tree/main/SPF/Documentation` #;
|
||||
%put # to learn more. #;
|
||||
%put # #;
|
||||
%put ### Example 1 ###################################################################;
|
||||
%put # #;
|
||||
%put # Enabling the SAS Package Framework #;
|
||||
%put # from the local directory and installing & loading additional content #;
|
||||
%put # for the SQLinDS package. #;
|
||||
%put # #;
|
||||
%put # Assume that the `SPFinit.sas` file #;
|
||||
%put # is located in the "C:/SAS_PACKAGES/" folder. #;
|
||||
%put # #;
|
||||
%put # Run the following code in your SAS session: #;
|
||||
%put ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~sas;
|
||||
%put %nrstr( filename packages "C:/SAS_PACKAGES"; %%* setup a directory for packages; );
|
||||
%put %nrstr( %%include packages(SPFinit.sas); %%* enable the framework; );
|
||||
%put ;
|
||||
%put %nrstr( %%installPackage(SQLinDS) %%* install the package from the Internet; );
|
||||
%put %nrstr( %%loadPackageAddCnt(SQLinDS) %%* load additional content for the package; );
|
||||
%put ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
|
||||
%put # #;
|
||||
%put #################################################################################;
|
||||
%put ;
|
||||
options &options_tmp.;
|
||||
%GOTO ENDofloadPackageAddCnt;
|
||||
%end;
|
||||
/* local variables for options */
|
||||
%local ls_tmp ps_tmp notes_tmp source_tmp stimer_tmp fullstimer_tmp msglevel_tmp zip;
|
||||
%let ls_tmp = %sysfunc(getoption(ls));
|
||||
%let ps_tmp = %sysfunc(getoption(ps));
|
||||
%let notes_tmp = %sysfunc(getoption(notes));
|
||||
%let source_tmp = %sysfunc(getoption(source));
|
||||
%let stimer_tmp = %sysfunc(getoption(stimer));
|
||||
%let fullstimer_tmp = %sysfunc(getoption(fullstimer));
|
||||
%let msglevel_tmp = %sysfunc(getoption(msglevel));
|
||||
|
||||
%let zip = zip;
|
||||
|
||||
options NOnotes NOsource ls=MAX ps=MAX NOfullstimer NOstimer msglevel=N;
|
||||
|
||||
%local _PackageFileref_;
|
||||
/* %let _PackageFileref_ = P%sysfunc(MD5(%lowcase(&packageName.)),hex7.); */
|
||||
data _null_;
|
||||
call symputX("_PackageFileref_", "A" !! put(MD5("%lowcase(&packageName.)"), hex7. -L), "L");
|
||||
call symputX("_TargetFileref_", "T" !! put(MD5("%lowcase(&packageName.)"), hex7. -L), "L");
|
||||
run;
|
||||
|
||||
/* when the packages reference is multi-directory search for the first one containing the package */
|
||||
data _null_;
|
||||
exists = 0;
|
||||
length packages $ 32767 p $ 4096;
|
||||
packages = resolve(symget("path"));
|
||||
if char(packages,1) ^= "(" then packages = quote(strip(packages)); /* for paths with spaces */
|
||||
do i = 1 to kcountw(packages, "()", "QS");
|
||||
p = dequote(kscanx(packages, i, "()", "QS"));
|
||||
exists + fileexist(catx("/", p, "%lowcase(&packageName.).&zip."));
|
||||
if exists then leave;
|
||||
end;
|
||||
if exists then call symputx("path", p, "L");
|
||||
run;
|
||||
|
||||
filename &_PackageFileref_. &ZIP.
|
||||
/* put location of package myPackageFile.zip here */
|
||||
"&path./%lowcase(&packageName.).&zip."
|
||||
;
|
||||
%if %sysfunc(fexist(&_PackageFileref_.)) %then
|
||||
%do;
|
||||
|
||||
filename &_PackageFileref_. &ZIP.
|
||||
/* check existence of addcnt.zip inside package */
|
||||
"&path./%lowcase(&packageName.).&zip."
|
||||
member='addcnt.zip'
|
||||
;
|
||||
%if %sysfunc(fexist(&_PackageFileref_.)) %then
|
||||
%do;
|
||||
|
||||
/* get metadata */
|
||||
filename &_PackageFileref_. &ZIP.
|
||||
"&path./%lowcase(&packageName.).&zip."
|
||||
;
|
||||
%include &_PackageFileref_.(packagemetadata.sas) / &source2.;
|
||||
filename &_PackageFileref_. clear;
|
||||
|
||||
/* test if required version of package is "good enough" */
|
||||
%local rV pV;
|
||||
%let pV = %sysfunc(compress(&packageVersion.,.,kd));
|
||||
%let pV = %sysevalf((%scan(&pV.,1,.,M)+0)*1e8
|
||||
+ (%scan(&pV.,2,.,M)+0)*1e4
|
||||
+ (%scan(&pV.,3,.,M)+0)*1e0);
|
||||
%let rV = %sysfunc(compress(&requiredVersion.,.,kd));
|
||||
%let rV = %sysevalf((%scan(&rV.,1,.,M)+0)*1e8
|
||||
+ (%scan(&rV.,2,.,M)+0)*1e4
|
||||
+ (%scan(&rV.,3,.,M)+0)*1e0);
|
||||
|
||||
%if %sysevalf(&rV. > &pV.) %then
|
||||
%do;
|
||||
%put ERROR: Additional content for package &packageName. will not be loaded!;
|
||||
%put ERROR- Required version is &requiredVersion.;
|
||||
%put ERROR- Provided version is &packageVersion.;
|
||||
%put ERROR- Verify installed version of the package.;
|
||||
%put ERROR- ;
|
||||
%GOTO WrongVersionOFPackageAddCnt; /*%RETURN;*/
|
||||
%end;
|
||||
|
||||
/*options ls = &ls_tmp. ps = &ps_tmp. ¬es_tmp. &source_tmp.;*/
|
||||
filename &_PackageFileref_. &ZIP.
|
||||
"&path./%lowcase(&packageName.).&zip."
|
||||
member='addcnt.zip'
|
||||
;
|
||||
/*********************/
|
||||
filename &_TargetFileref_. "&target.";
|
||||
%if %sysfunc(fexist(&_TargetFileref_.)) %then
|
||||
%do;
|
||||
|
||||
%if %sysfunc(fileexist(%sysfunc(pathname(&_TargetFileref_.))/%lowcase(&packageName.)_AdditionalContent)) %then
|
||||
%do; /* dir for AC already exists */
|
||||
%put WARNING: Target location:;
|
||||
%put WARNING- %sysfunc(pathname(&_TargetFileref_.))/%lowcase(&packageName.)_AdditionalContent;
|
||||
%put WARNING- already exist. Please remove it manually to upload additional contents.;
|
||||
%put WARNING- Additional Content will not be loaded.;
|
||||
%put WARNING- ;
|
||||
%end;
|
||||
%else
|
||||
%do;
|
||||
/*-+-+-+-*/
|
||||
/* create target location */
|
||||
%put INFO:;
|
||||
%put Additional content will be located in:;
|
||||
%put %sysfunc(dcreate(%lowcase(&packageName.)_AdditionalContent,%sysfunc(pathname(&_TargetFileref_.))));
|
||||
|
||||
%if NOT (%sysfunc(fileexist(%sysfunc(pathname(&_TargetFileref_.))/%lowcase(&packageName.)_AdditionalContent))) %then
|
||||
%do; /* dir for AC cannot be generated */
|
||||
%put ERROR: Cannot create target location:;
|
||||
%put ERROR- %sysfunc(pathname(&_TargetFileref_.))/%lowcase(&packageName.)_AdditionalContent;
|
||||
%put ERROR- Additional Content will not be loaded.;
|
||||
%put ERROR- ;
|
||||
%end;
|
||||
%else
|
||||
%do;
|
||||
/* extract addcnt.zip to work and, if successful, load additional content */
|
||||
%put NOTE- **%sysfunc(DoSubL(%nrstr(
|
||||
;
|
||||
options nonotes nosource ps=min ls=max;
|
||||
data _null_;
|
||||
call symputx("AdditionalContent", 0, "L");
|
||||
|
||||
rc1=filename("in", pathname("&_PackageFileref_."), "ZIP", "lrecl=1 recfm=n member='addcnt.zip'");
|
||||
rc1txt=sysmsg();
|
||||
|
||||
if fexist("in") then
|
||||
do;
|
||||
rc2=filename("out", pathname("WORK")!!"/%lowcase(&packageName.)addcnt.zip", "disk", "lrecl=1 recfm=n");
|
||||
rc2txt=sysmsg();
|
||||
|
||||
rc3=fcopy("in","out");
|
||||
rc3txt=sysmsg();
|
||||
|
||||
if rc3 then put _N_ @12 (rc:) (=);
|
||||
|
||||
if fexist("out") then
|
||||
do;
|
||||
call symputx("AdditionalContent", 1, "L");
|
||||
end;
|
||||
else put "INFO: No additional content for package &packageName..";
|
||||
|
||||
rc1=filename("in");
|
||||
rc2=filename("out");
|
||||
end;
|
||||
else
|
||||
do;
|
||||
call symputx("AdditionalContent", 0, "L");
|
||||
put "INFO: No additional content for package &packageName..";
|
||||
end;
|
||||
run;
|
||||
|
||||
%if &AdditionalContent. %then
|
||||
%do;
|
||||
filename f DUMMY;
|
||||
filename f ZIP "%sysfunc(pathname(WORK))/%lowcase(&packageName.)addcnt.zip";
|
||||
options dlCreateDir;
|
||||
libname outData "%sysfunc(pathname(&_TargetFileref_.))/%lowcase(&packageName.)_AdditionalContent";
|
||||
|
||||
data WORK.__&_TargetFileref_._zip___;
|
||||
did = dopen("f");
|
||||
if not did then
|
||||
do;
|
||||
put "ERROR: Can not access Additional Content data.";
|
||||
stop;
|
||||
end;
|
||||
if did then
|
||||
do i=1 to dnum(did);
|
||||
file = dread(did, i);
|
||||
output;
|
||||
keep file;
|
||||
end;
|
||||
did = dclose(did);
|
||||
run;
|
||||
|
||||
data _null_;
|
||||
set WORK.__&_TargetFileref_._zip___ end = EOF;
|
||||
wc = countw(file,"/\");
|
||||
|
||||
libText = pathname("outData", "L");
|
||||
|
||||
if scan(file, wc , "/\") = "" then
|
||||
do j = 1 to wc-1;
|
||||
libText = catx("/", libText, scan(file, j , "/\"));
|
||||
rc = libname("test", libText);
|
||||
rc = libname("test");
|
||||
end;
|
||||
else
|
||||
do;
|
||||
do j = 1 to wc-1;
|
||||
libText = catx("/", libText, scan(file, j , "/\"));
|
||||
rc = libname("test", libText);
|
||||
rc = libname("test");
|
||||
end;
|
||||
rc1 = filename("in", pathname("f"), "zip", "member='" !! strip(file) !! "' lrecl=1 recfm=n");
|
||||
rc1msg = sysmsg();
|
||||
rc2 = filename("out", catx("/", libText, scan(file, j , "/\")), "disk", "lrecl=1 recfm=n");
|
||||
rc2msg = sysmsg();
|
||||
|
||||
rc3 = fcopy("in", "out");
|
||||
rc3msg = sysmsg();
|
||||
|
||||
loadingProblem + (rc3 & 1);
|
||||
|
||||
if rc3 then
|
||||
do;
|
||||
put "ERROR: Cannot extract: " file;
|
||||
put (rc1 rc2 rc3) (=);
|
||||
put (rc1msg rc2msg rc3msg) (/);
|
||||
put "ERROR-";
|
||||
end;
|
||||
crc1=filename("in");
|
||||
crc2=filename("out");
|
||||
end;
|
||||
|
||||
if EOF and loadingProblem then
|
||||
do;
|
||||
put "ERROR: Not all files from Additional Content were extracted successfully!";
|
||||
end;
|
||||
run;
|
||||
|
||||
data _null_;
|
||||
rc = fdelete("f");
|
||||
run;
|
||||
|
||||
proc delete data = WORK.__&_TargetFileref_._zip___;
|
||||
run;
|
||||
|
||||
libname outData;
|
||||
filename f DUMMY;
|
||||
%end;
|
||||
)))**;
|
||||
%end;
|
||||
/*-+-+-+-*/
|
||||
%end;
|
||||
|
||||
%end;
|
||||
%else
|
||||
%do;
|
||||
%put ERROR: Cannot access target location:;
|
||||
%put ERROR- %sysfunc(pathname(&_TargetFileref_.));
|
||||
%put ERROR- Additional Content will not be loaded.;
|
||||
%put ERROR- ;
|
||||
%end;
|
||||
filename &_TargetFileref_. clear;
|
||||
/*********************/
|
||||
%end;
|
||||
%else %put INFO: No additional content for &packageName. package.;
|
||||
%end;
|
||||
%else %put ERROR:[&sysmacroname] File "&path./&packageName..&zip." does not exist!;
|
||||
filename &_PackageFileref_. clear;
|
||||
|
||||
%WrongVersionOFPackageAddCnt:
|
||||
|
||||
/* restore optionos */
|
||||
options ls = &ls_tmp. ps = &ps_tmp.
|
||||
¬es_tmp. &source_tmp.
|
||||
&stimer_tmp. &fullstimer_tmp.
|
||||
msglevel=&msglevel_tmp.;
|
||||
|
||||
%ENDofloadPackageAddCnt:
|
||||
%mend loadPackageAddCnt;
|
||||
|
||||
|
||||
|
||||
|
||||
/**/
|
||||
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
)/secure
|
||||
/*** HELP END ***/
|
||||
des = 'Macro to load multiple SAS packages at one run, version 20230112. Run %loadPackages() for help info.'
|
||||
des = 'Macro to load multiple SAS packages at one run, version 20230207. Run %loadPackages() for help info.'
|
||||
parmbuff
|
||||
;
|
||||
%if (%superq(packagesNames) = ) OR (%qupcase(&packagesNames.) = HELP) %then
|
||||
@@ -27,7 +27,7 @@ parmbuff
|
||||
%put ### This is short help information for the `loadPackageS` macro #;
|
||||
%put #-------------------------------------------------------------------------------#;
|
||||
%put # #;
|
||||
%put # Macro wrapper for the loadPackage macro, version `20230112` #;
|
||||
%put # Macro wrapper for the loadPackage macro, version `20230207` #;
|
||||
%put # #;
|
||||
%put # A SAS package is a zip file containing a group #;
|
||||
%put # of SAS codes (macros, functions, data steps generating #;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
*/
|
||||
)/secure
|
||||
/*** HELP END ***/
|
||||
des = 'Macro to preview content of a SAS package, version 20230112. Run %previewPackage() for help info.'
|
||||
des = 'Macro to preview content of a SAS package, version 20230207. Run %previewPackage() for help info.'
|
||||
;
|
||||
%if (%superq(packageName) = ) OR (%qupcase(&packageName.) = HELP) %then
|
||||
%do;
|
||||
@@ -38,7 +38,7 @@ des = 'Macro to preview content of a SAS package, version 20230112. Run %preview
|
||||
%put ### This is short help information for the `previewPackage` macro #;
|
||||
%put #-------------------------------------------------------------------------------#;
|
||||
%put # #;
|
||||
%put # Macro to get previwe of a SAS packages, version `20230112` #;
|
||||
%put # Macro to get previwe of a SAS packages, version `20230207` #;
|
||||
%put # #;
|
||||
%put # A SAS package is a zip file containing a group #;
|
||||
%put # of SAS codes (macros, functions, data steps generating #;
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
*/
|
||||
)/secure
|
||||
/*** HELP END ***/
|
||||
des = 'Macro to unload SAS package, version 20230112. Run %unloadPackage() for help info.'
|
||||
des = 'Macro to unload SAS package, version 20230207. Run %unloadPackage() for help info.'
|
||||
;
|
||||
%if (%superq(packageName) = ) OR (%qupcase(&packageName.) = HELP) %then
|
||||
%do;
|
||||
@@ -35,7 +35,7 @@ des = 'Macro to unload SAS package, version 20230112. Run %unloadPackage() for h
|
||||
%put ### This is short help information for the `unloadPackage` macro #;
|
||||
%put #-------------------------------------------------------------------------------#;
|
||||
%put # #;
|
||||
%put # Macro to unload SAS packages, version `20230112` #;
|
||||
%put # Macro to unload SAS packages, version `20230207` #;
|
||||
%put # #;
|
||||
%put # A SAS package is a zip file containing a group #;
|
||||
%put # of SAS codes (macros, functions, data steps generating #;
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
hashing_file() function, SAS 9.4M6 */
|
||||
)/secure
|
||||
/*** HELP END ***/
|
||||
des = 'Macro to verify SAS package with the hash digest, version 20230112. Run %verifyPackage() for help info.'
|
||||
des = 'Macro to verify SAS package with the hash digest, version 20230207. Run %verifyPackage() for help info.'
|
||||
;
|
||||
%if (%superq(packageName) = ) OR (%qupcase(&packageName.) = HELP) %then
|
||||
%do;
|
||||
@@ -28,7 +28,7 @@ des = 'Macro to verify SAS package with the hash digest, version 20230112. Run %
|
||||
%put ### This is short help information for the `verifyPackage` macro #;
|
||||
%put #-------------------------------------------------------------------------------#;
|
||||
%put # #;
|
||||
%put # Macro to verify SAS package with it hash digest, version `20230112` #;
|
||||
%put # Macro to verify SAS package with it hash digest, version `20230207` #;
|
||||
%put # #;
|
||||
%put # A SAS package is a zip file containing a group #;
|
||||
%put # of SAS codes (macros, functions, data steps generating #;
|
||||
|
||||
Reference in New Issue
Block a user