Skip to content

Commit

Permalink
reimplement url2local without using the python c-api
Browse files Browse the repository at this point in the history
  • Loading branch information
tkittel committed Mar 3, 2024
1 parent 0f83f40 commit bf8c113
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 8 deletions.
15 changes: 15 additions & 0 deletions src/simplebuild_dgcode/data/pkgs/Utils/Utils/libinc/Cmd.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#ifndef Utils_Cmd_hh
#define Utils_Cmd_hh

#include <utility>
#include <string>

namespace Utils {
//Launch command and get both exit code and stdout of command. The
//reserve_size parameter can be used to reserve capacity in the output string,
//but is only needed for a very small performance gain:
std::pair<int, std::string> launch_cmd( const char* cmd,
std::size_t reserve_size = 0 );
}

#endif
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#ifndef Utils_Url2Local_hh
#define Utils_Url2Local_hh

#include <string>

namespace Utils {

//If input_filename is a local path (or an invalid filename), it will be
Expand Down
44 changes: 44 additions & 0 deletions src/simplebuild_dgcode/data/pkgs/Utils/Utils/libsrc/Cmd.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#include "Utils/Cmd.hh"
#include <array>
#include <stdexcept>
#include <cstdio>

namespace {
struct UtilsProcWrapper {
//RAII wrapper
FILE * procptr = nullptr;
UtilsProcWrapper( const char * cmd )
: procptr(popen(cmd,"r"))
{
}
int close_and_get_rc()
{
if ( !procptr )
throw std::runtime_error("launch_cmd: unexpected error");
auto pp = procptr;
procptr = nullptr;
return pclose( pp );
}
~UtilsProcWrapper()
{
if ( procptr )
pclose( procptr );
}
};
}

std::pair<int, std::string> Utils::launch_cmd( const char* cmd,
std::size_t reserve_size )
{
std::array<char, 256> buf;
std::pair<int, std::string> res;
if (reserve_size)
res.second.reserve( reserve_size );
UtilsProcWrapper theproc( cmd );
if ( theproc.procptr != nullptr ) {
while ( fgets( buf.data(), buf.size(), theproc.procptr ) != nullptr )
res.second += buf.data();
}
res.first = theproc.close_and_get_rc();
return res;
}
31 changes: 26 additions & 5 deletions src/simplebuild_dgcode/data/pkgs/Utils/Utils/libsrc/Url2Local.cc
Original file line number Diff line number Diff line change
@@ -1,10 +1,31 @@
#include "Core/Python.hh"
#include "Utils/Url2Local.hh"
#include "Utils/Cmd.hh"
#include "Core/String.hh"
#include <stdexcept>
#include <vector>
#include <iostream>

std::string Utils::url2local(std::string input_filename, std::string cachedir)
{
pyextra::ensurePyInit();
py::object mod = pyextra::pyimport("Utils.dl_url_to_local_cache");
auto res = mod.attr("dl_with_cache")(input_filename,cachedir);
return res.cast<std::string>();
//Wrap sb_utils_url2local command, except for local files:
if ( input_filename.find("://") == std::string::npos )
return input_filename;//not an url
std::string cmd("sb_utils_url2local ");
cmd += '"';
cmd += input_filename;
cmd += "\" \"";
cmd += cachedir;
cmd += '"';
auto res = Utils::launch_cmd( cmd.c_str() );
if ( res.first != 0 )
throw std::runtime_error(std::string("cmd failed: ")+cmd);
//Only return the last line of the output, and re-print the rest:
std::vector<std::string> parts;
Core::split_noempty(parts,res.second,"\n\r");
if ( parts.empty() )
throw std::runtime_error(std::string("cmd gave unexpected output: ")+cmd);
auto itBack = std::prev(parts.end());
for ( auto it = parts.begin(); it != itBack; ++it )
std::cout<<*it<<std::endl;
return std::move(*itBack);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from __future__ import print_function
import Core.System as Sys
import os

Expand All @@ -7,7 +6,7 @@ def _clean_expr(x):
return re.sub('\W|^(?=\d)','_', x)

def dl_with_cache(url,cachedir=None):
if not '://' in url:
if '://' not in url:
return url
op=os.path
if not cachedir:
Expand All @@ -16,7 +15,7 @@ def dl_with_cache(url,cachedir=None):
cachedir=os.path.join(cachedir,_clean_expr(url))
if not op.exists(cachedir):
Sys.mkdir_p(cachedir)
target=op.join(cachedir,op.basename(url) or 'content')
target=op.join(cachedir,op.basename(url).strip() or 'content')
if op.exists(target):
print('Acquiring file from local cache: %s'%url)
else:
Expand All @@ -25,3 +24,18 @@ def dl_with_cache(url,cachedir=None):
urllib.request.urlretrieve(url, target)

return target

def _cli():
import sys
args = sys.argv[1:]
if len(args) not in (1,2) or '-h' in args or '--help' in args:
bn = os.path.basename(sys.argv[0])
print("Usage:")
print(f"{bn} <URL-OR-LOCALFILE> [<cachedir>]")
raise SystemExit(1)
url = args[0]
cachedir = args[1] if len(args)==2 else None
print( dl_with_cache( url, cachedir or None ) )

if __name__ == '__main__':
_cli()
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env python3
from Utils.dl_url_to_local_cache import _cli
_cli()
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include "Utils/Url2Local.hh"
#include <iostream>
int main( int argc, char** argv )
{
if (argc<2||argc>3)
return 1;
std::string fn = argv[1];
std::string cachedir = argc==3 ? argv[2] : "";
std::cout<< Utils::url2local(fn, cachedir)<<std::endl;
return 0;
}

0 comments on commit bf8c113

Please sign in to comment.