- Use a dummy import statement like import('STUB') where needed, and replace these with import('my_movable_package.*') using an init.m script.
- Place this script in the package's root folder to recursively update all files with the correct fully qualified paths.
Future-proofness of my relative import solution?
    5 visualizzazioni (ultimi 30 giorni)
  
       Mostra commenti meno recenti
    
I am trying to solve the "relative-import" problem (import statements need to be absolute which makes using packages as subpackages in other packages hard).
I am solving this with a helper function located in the private-folder that is called `get_import_str`
function [import_str,parent_dir] = get_import_str()
% Returns the import string needed to import all sub-packages
%
% Usage: Place in the top of a package function to provide a relative import
% 
% function out = functionA(arg1,arg2)
% % Package function located in <some_path>/+<some_package1>/+<some_package2>/
%     % Import subpackages
%     import_str = get_import_str();
%     import(import_str);
%     
%     arg3 = functionB(arg1); % Sibling function
%     out = arg1+arg2+arg3;
% end
%
    stack_info = dbstack('-completenames');
    if length(stack_info) <= 1, error('This function must be called from a m-file.'); end
    caller_fn = stack_info(2).file;
    [parent_dir,fname,~] = fileparts(fileparts(caller_fn));
    while true
        if ~strcmp(fname(1),'+')
            parent_dir = fullfile(parent_dir,fname);
            import_str = fileparts(caller_fn);
            import_str = [replace(import_str(length(parent_dir)+3:end),[filesep,'+'],'.'),'.*'];
            return
        end
        [parent_dir,fname,~] = fileparts(parent_dir);
    end
end
To call a sibling package function you use the
function out = functionA(arg1,arg2)
    import_str = get_import_str();
    import(import_str);
    arg3 = functionB(arg1);  % Sibling function: Returns arg1*10
    arg4 = sub_package.functionC(arg2);  % Child-package-function: Returns arg2*pi
    out = arg1+arg2+arg3+arg4;
end
This seems to work fine (please inform me if you se any issues) but now to my question:
Question: How future-proof is this? I get a warning saying
"In a future release, IMPORT will not accept variable names, function calls, or operators. Use literal char vectors instead."
At my company we run a old version of matlab (R2018b) but I don't want my stuff to break when we upgrade.
Details
<some-path>
    +my_movable_package
        private/
            get_import_str.m
        functionA.m
        functionB.m
        +sub_package
            functionC.m
0 Commenti
Risposte (1)
  Arnav
 il 7 Nov 2024
        To avoid deprecation warnings when using import function dynamically, switch to using fully qualified path names in the import statement. Alternatively, you can replace import statements statically before any function execution. 
You can refer to the below: 
To recursively find all .m files in a package you can use the code snippet shown: 
function INIT() 
    script_full_path = mfilename('fullpath'); 
    [package_root, ~, ~] = fileparts(script_full_path); 
    files = dir(fullfile(package_root, '**', '*.m')); 
    for k = 1:length(files) 
        file_path = fullfile(files(k).folder, files(k).name); 
        if strcmp(files(k).name, 'init.m') 
            continue; 
        end         
        replace_stub(file_path, package_root); 
    end 
end 
function replace_stub(file_path, package_root) 
    fid = fopen(file_path, 'r'); 
    file_content = fread(fid, '*char')'; 
    fclose(fid); 
    relative_path = strrep(file_path, [fileparts(package_root), filesep], ''); 
    relative_path = fileparts(relative_path);  
    package_path = strrep(relative_path, ['+', filesep], ''); 
    package_path = strrep(package_path, '+', ''); 
    package_path = strrep(package_path, filesep, '.'); 
    import_statement = sprintf("import('%s.*')", package_path); 
    new_content = strrep(file_content, "import('STUB')", import_statement); 
    fid = fopen(file_path, 'w'); 
    fwrite(fid, new_content); 
    fclose(fid); 
end 
INIT();
This package can then be imported and used as shown below: 
>> import my_movable_package.* 
>> init
>> functionA(10, 12)
>> functionB(10)
0 Commenti
Vedere anche
Categorie
				Scopri di più su Foundation and Custom Domains in Help Center e File Exchange
			
	Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!

