mirror of
https://github.com/TREX-CoE/trexio.git
synced 2024-12-22 20:35:44 +01:00
Merge pull request #75 from TREX-CoE/add-inquire-functionality
Add inquire functionality
This commit is contained in:
commit
51c43fe1ac
@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/bin/bash
|
||||
|
||||
set -x
|
||||
set -e
|
||||
@ -38,12 +38,12 @@ python3 -m pip install -r requirements.txt
|
||||
|
||||
# Create build directory and compile extension files (*.c)
|
||||
# --no-user-cfg disables custom .cfg files of the user machine, so that only setup.cfg is used
|
||||
#python3 -s setup.py --no-user-cfg build
|
||||
#python3 -s setup.py --no-user-cfg build
|
||||
|
||||
# Local inplace build of the .so module with SWIG-produced pytrexio_wrap.c (from the SWIG documentation)
|
||||
#python3 setup.py build_ext --inplace --swig-opts="-modern"
|
||||
|
||||
# Create distributions:
|
||||
# Create distributions:
|
||||
|
||||
# OLD WAY (DEPRECATED BY PYPA)
|
||||
# 1) sdist produces .tar.gz with all files necessary for manual compilation;
|
||||
@ -54,14 +54,7 @@ python3 -m pip install -r requirements.txt
|
||||
python3 -m build --sdist --wheel --outdir dist/
|
||||
|
||||
# Install pytrexio in the current environment from the aforementioned wheel
|
||||
|
||||
# OLD WAY
|
||||
# --force-reinstall is needed here because build-system pre-installs pytrexio in the environment
|
||||
# but does not install things in the corresponding site-packages directory
|
||||
#python3 -m pip install dist/trexio-*.whl --force-reinstall
|
||||
|
||||
# NEW WAY
|
||||
python3 -m pip install dist/trexio-*.whl
|
||||
python3 -m pip install dist/trexio-*.whl --force-reinstall
|
||||
|
||||
# Run the command below in the root directory to install the package in 'editable' (-e) mode without dependencies (--no-deps)
|
||||
#python -m pip install -e . --no-deps
|
||||
@ -83,7 +76,6 @@ rm -rf build dist trexio.egg-info
|
||||
|
||||
# Additional information related to the installation of the TREXIO Python API
|
||||
|
||||
#Removing MANIFEST.in leads to issues in the installation. In particular, the .c and .h source files do not get copied
|
||||
#from the src/ directory into the tar.gz which is produced by setup sdist command.
|
||||
#Removing MANIFEST.in leads to issues in the installation. In particular, the .c and .h source files do not get copied
|
||||
#from the src/ directory into the tar.gz which is produced by setup sdist command.
|
||||
#These source files are required to build the pytrexio.so extension module, which is needed for the Python API.
|
||||
|
||||
|
@ -40,6 +40,7 @@ except:
|
||||
|
||||
# create TREXIO file and open it for writing
|
||||
test_file = trexio.File(output_filename, mode='w', back_end=TEST_TREXIO_BACKEND)
|
||||
assert test_file.exists
|
||||
|
||||
# Print docstring of the trexio.open function
|
||||
#print(trexio.open.__doc__)
|
||||
@ -153,6 +154,7 @@ del test_file
|
||||
|
||||
# open previously created TREXIO file, now in 'read' mode
|
||||
test_file2 = trexio.File(output_filename, 'r', TEST_TREXIO_BACKEND)
|
||||
assert test_file2.exists
|
||||
|
||||
# check for existence of some of the previously written variables
|
||||
assert trexio.has_nucleus_num
|
||||
|
@ -1,5 +1,4 @@
|
||||
#+TITLE: Front end API
|
||||
break;
|
||||
#+PROPERTY: comments org
|
||||
#+SETUPFILE: ../../docs/theme.setup
|
||||
# -*- mode: org -*-
|
||||
@ -696,12 +695,15 @@ class File:
|
||||
self.back_end = back_end
|
||||
|
||||
self.isOpen = False
|
||||
self.exists = False
|
||||
if pytrexio_s is None:
|
||||
self.pytrexio_s = open(filename, mode, back_end)
|
||||
self.pytrexio_s = _open(filename, mode, back_end)
|
||||
self.isOpen = True
|
||||
self.exists = True
|
||||
else:
|
||||
self.pytrexio_s = pytrexio_s
|
||||
self.isOpen = None
|
||||
self.exists = None
|
||||
|
||||
self.info = info
|
||||
|
||||
@ -710,17 +712,23 @@ class File:
|
||||
"""Close a TREXIO File."""
|
||||
|
||||
if self.isOpen:
|
||||
close(self.pytrexio_s)
|
||||
_close(self.pytrexio_s)
|
||||
self.isOpen = False
|
||||
else:
|
||||
raise Exception("TREXIO File object has not been opened.")
|
||||
|
||||
|
||||
def inquire(self):
|
||||
"""Inquire whether a TREXIO file exists."""
|
||||
|
||||
self.exists = _inquire(self.filename)
|
||||
|
||||
|
||||
def __del__(self):
|
||||
"""This is a TREXIO File destructor."""
|
||||
|
||||
if self.isOpen:
|
||||
close(self.pytrexio_s)
|
||||
_close(self.pytrexio_s)
|
||||
elif self.isOpen is None:
|
||||
raise Exception("[WIP]: TREXIO file handle provided but what if the file is already closed?")
|
||||
else:
|
||||
@ -972,7 +980,7 @@ end interface
|
||||
*** Python
|
||||
|
||||
#+begin_src python :tangle basic_python.py
|
||||
def open(file_name: str, mode: str, back_end: int):
|
||||
def _open(file_name: str, mode: str, back_end: int):
|
||||
"""Create TREXIO file or open existing one.
|
||||
|
||||
Parameters:
|
||||
@ -1149,7 +1157,7 @@ end interface
|
||||
*** Python
|
||||
|
||||
#+begin_src python :tangle basic_python.py
|
||||
def close(trexio_file):
|
||||
def _close(trexio_file):
|
||||
"""Close TREXIO file.
|
||||
|
||||
Parameter is a ~trexio_file~ object that has been created by a call to ~open~ function.
|
||||
@ -1163,6 +1171,77 @@ def close(trexio_file):
|
||||
raise
|
||||
#+end_src
|
||||
|
||||
** File existence
|
||||
|
||||
~trexio_inquire~ check whether TREXIO file exists.
|
||||
|
||||
input parameters:
|
||||
~file_name~ - string containing file name
|
||||
|
||||
output:
|
||||
~trexio_exit_code~ exit code.
|
||||
|
||||
*** C
|
||||
|
||||
#+begin_src c :tangle prefix_front.h :exports none
|
||||
trexio_exit_code trexio_inquire(const char* file_name);
|
||||
#+end_src
|
||||
|
||||
#+begin_src c :tangle prefix_front.c
|
||||
trexio_exit_code
|
||||
trexio_inquire (const char* file_name)
|
||||
{
|
||||
|
||||
if (file_name == NULL || file_name[0] == '\0') return TREXIO_INVALID_ARG_1;
|
||||
|
||||
/* First check if the TREXIO file exists and if it is a directory */
|
||||
trexio_exit_code rc_text = trexio_text_inquire(file_name);
|
||||
|
||||
#ifdef HAVE_HDF5
|
||||
/* FILE_ERROR here means that the file exists but it is not a directory -> check with HDF5 */
|
||||
if (rc_text == TREXIO_FILE_ERROR) {
|
||||
trexio_exit_code rc_hdf5 = trexio_hdf5_inquire(file_name);
|
||||
return rc_hdf5;
|
||||
/* If rc_text is TREXIO_SUCCESS -> file is a TREXIO directory; TREXIO_FAILURE -> file/directory does not exist */
|
||||
} else {
|
||||
return rc_text;
|
||||
}
|
||||
#else
|
||||
return rc_text;
|
||||
#endif
|
||||
}
|
||||
#+end_src
|
||||
|
||||
*** Fortran
|
||||
|
||||
The function below is a C binding.
|
||||
The front end Fortran function for ~trexio_inquire~ can be found in the ~Fortran helper/wrapper functions~.
|
||||
|
||||
#+begin_src f90 :tangle prefix_fortran.f90
|
||||
interface
|
||||
integer function trexio_inquire_c (filename) bind(C, name="trexio_inquire")
|
||||
use, intrinsic :: iso_c_binding
|
||||
import
|
||||
character(kind=c_char), dimension(*) :: filename
|
||||
end function trexio_inquire_c
|
||||
end interface
|
||||
#+end_src
|
||||
|
||||
*** Python
|
||||
|
||||
#+begin_src python :tangle basic_python.py
|
||||
def _inquire(file_name: str) -> bool:
|
||||
"""Check whether ~file_name~ TREXIO file exists.
|
||||
"""
|
||||
rc = pytr.trexio_inquire(trexio_file_name)
|
||||
if rc == TREXIO_SUCCESS:
|
||||
return True
|
||||
elif rc == TREXIO_FAILURE:
|
||||
return False
|
||||
else:
|
||||
raise Error(rc)
|
||||
#+end_src
|
||||
|
||||
* Templates for front end
|
||||
** Description
|
||||
|
||||
@ -1769,7 +1848,7 @@ trexio_write_$group_dset$_64 (trexio_t* const file, const $group_dset_dtype_doub
|
||||
|
||||
case TREXIO_HDF5:
|
||||
#ifdef HAVE_HDF5
|
||||
rc = trexio_hdf5_write_$group_dset$(file,
|
||||
rc = trexio_hdf5_write_$group_dset$(file,
|
||||
(const $group_dset_dtype_double$*) $group_dset$_p,
|
||||
rank, dims);
|
||||
break;
|
||||
@ -2629,7 +2708,7 @@ trexio_write_$group_dset$(trexio_t* const file,
|
||||
if (file->one_based) {
|
||||
|
||||
uint64_t index_size = rank * buffer_size;
|
||||
|
||||
|
||||
int32_t* index_sparse_p = CALLOC(index_size, int32_t);
|
||||
if (index_sparse_p == NULL) return TREXIO_ALLOCATION_FAILED;
|
||||
|
||||
@ -3801,6 +3880,23 @@ contains
|
||||
end function trexio_open
|
||||
#+end_src
|
||||
|
||||
The function below adapts the original C-based ~trexio_inquire~ for Fortran.
|
||||
This is needed due to the same reasons as for ~trexio_open~ function.
|
||||
Note, that Fortran interface calls the main ~TREXIO~ API, which is written in C.
|
||||
|
||||
#+begin_src f90 :tangle helper_fortran.f90
|
||||
integer function trexio_inquire (filename)
|
||||
use, intrinsic :: iso_c_binding
|
||||
implicit none
|
||||
character(len=*), intent(in) :: filename
|
||||
character(len=len_trim(filename)+1) :: filename_c
|
||||
|
||||
filename_c = trim(filename) // c_null_char
|
||||
trexio_inquire = trexio_inquire_c(filename_c)
|
||||
end function trexio_inquire
|
||||
|
||||
#+end_src
|
||||
|
||||
The subroutine below transforms an array of Fortran strings into one big string using ~TREXIO_DELIM~ symbol
|
||||
as a delimeter and adds ~NULL~ character in the end in order to properly pass the desired string to
|
||||
C API. This is needed due to the fact that strings in C are terminated by ~NULL~ character ~\0~.
|
||||
|
@ -69,13 +69,29 @@ typedef struct trexio_hdf5_s {
|
||||
} trexio_hdf5_t;
|
||||
#+end_src
|
||||
|
||||
** Template for HDF5 init/deinit
|
||||
|
||||
#+begin_src c :tangle struct_hdf5.h :exports none
|
||||
trexio_exit_code trexio_hdf5_init(trexio_t* const file);
|
||||
trexio_exit_code trexio_hdf5_deinit(trexio_t* const file);
|
||||
trexio_exit_code trexio_hdf5_inquire(const char* file_name);
|
||||
#+end_src
|
||||
|
||||
** Template for HDF5 init/deinit
|
||||
#+begin_src c :tangle basic_hdf5.c
|
||||
trexio_exit_code
|
||||
trexio_hdf5_inquire(const char* file_name)
|
||||
{
|
||||
/* H5Fis_hdf5 determines whether file is in HDF5 format */
|
||||
htri_t rc = H5Fis_hdf5(file_name);
|
||||
if (rc > 0 ) {
|
||||
return TREXIO_SUCCESS; //exists and HDF5
|
||||
} else if (rc == 0) {
|
||||
return TREXIO_FILE_ERROR; //exists but not HDF5
|
||||
} else {
|
||||
return TREXIO_FAILURE; //does not exist or function fails
|
||||
}
|
||||
}
|
||||
#+end_src
|
||||
|
||||
#+begin_src c :tangle basic_hdf5.c
|
||||
trexio_exit_code
|
||||
@ -134,7 +150,9 @@ trexio_hdf5_init (trexio_t* const file)
|
||||
|
||||
return TREXIO_SUCCESS;
|
||||
}
|
||||
#+end_src
|
||||
|
||||
#+begin_src c :tangle basic_hdf5.c
|
||||
trexio_exit_code
|
||||
trexio_hdf5_deinit (trexio_t* const file)
|
||||
{
|
||||
|
@ -105,6 +105,33 @@ typedef struct trexio_text_s {
|
||||
|
||||
#+begin_src c :tangle basic_text.h :exports none
|
||||
trexio_exit_code trexio_text_init(trexio_t* const file);
|
||||
trexio_exit_code trexio_text_inquire(const char* file_name);
|
||||
trexio_exit_code trexio_text_deinit(trexio_t* const file);
|
||||
trexio_exit_code trexio_text_lock(trexio_t* const file);
|
||||
trexio_exit_code trexio_text_unlock(trexio_t* const file);
|
||||
#+end_src
|
||||
|
||||
#+begin_src c :tangle basic_text.c
|
||||
trexio_exit_code
|
||||
trexio_text_inquire (const char* file_name)
|
||||
{
|
||||
/* Check if the file with "file_name" exists and that it is a directory */
|
||||
struct stat st;
|
||||
|
||||
int rc = stat(file_name, &st);
|
||||
|
||||
bool file_exists = rc == 0;
|
||||
|
||||
if (file_exists) {
|
||||
|
||||
bool is_a_directory = st.st_mode & S_IFDIR;
|
||||
if (!is_a_directory) return TREXIO_FILE_ERROR;
|
||||
|
||||
return TREXIO_SUCCESS;
|
||||
} else {
|
||||
return TREXIO_FAILURE;
|
||||
}
|
||||
}
|
||||
#+end_src
|
||||
|
||||
#+begin_src c :tangle basic_text.c
|
||||
@ -119,30 +146,19 @@ trexio_text_init (trexio_t* const file)
|
||||
/* Put all pointers to NULL but leave parent untouched */
|
||||
memset(&(f->parent)+1,0,sizeof(trexio_text_t)-sizeof(trexio_t));
|
||||
|
||||
/* If directory doesn't exist, create it in write mode */
|
||||
struct stat st;
|
||||
/* Check if directory exists */
|
||||
trexio_exit_code rc;
|
||||
rc = trexio_text_inquire(file->file_name);
|
||||
/* TREXIO file exists but is not a directory */
|
||||
if (rc == TREXIO_FILE_ERROR) return rc;
|
||||
/* If directory does not exist - create it in write mode */
|
||||
if (rc == TREXIO_FAILURE) {
|
||||
|
||||
int rc = stat(file->file_name, &st);
|
||||
if (file->mode == 'r') return TREXIO_READONLY;
|
||||
|
||||
bool file_exists = rc == 0;
|
||||
int rc_dir = mkdir(file->file_name, 0777);
|
||||
if (rc_dir != 0) return TREXIO_ERRNO;
|
||||
|
||||
if (file_exists) {
|
||||
|
||||
bool is_a_directory = st.st_mode & S_IFDIR;
|
||||
if (!is_a_directory) {
|
||||
return TREXIO_FILE_ERROR;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (file->mode == 'r') {
|
||||
return TREXIO_READONLY;
|
||||
}
|
||||
|
||||
rc = mkdir(file->file_name, 0777);
|
||||
if (rc != 0) {
|
||||
return TREXIO_ERRNO;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create the lock file in the directory */
|
||||
@ -166,7 +182,7 @@ trexio_text_init (trexio_t* const file)
|
||||
if (errno == EACCES) {
|
||||
/* The directory is read-only and the lock file can't be written.
|
||||
Create a dummy temporary file for dummy locking.
|
||||
*/
|
||||
,*/
|
||||
char dirname[TREXIO_MAX_FILENAME_LENGTH] = "/tmp/trexio.XXXXXX";
|
||||
if (mkdtemp(dirname) == NULL) return TREXIO_ERRNO;
|
||||
strncpy (file_name, dirname, TREXIO_MAX_FILENAME_LENGTH);
|
||||
@ -184,10 +200,6 @@ trexio_text_init (trexio_t* const file)
|
||||
}
|
||||
#+end_src
|
||||
|
||||
#+begin_src c :tangle basic_text.h :exports none
|
||||
trexio_exit_code trexio_text_lock(trexio_t* const file);
|
||||
#+end_src
|
||||
|
||||
#+begin_src c :tangle basic_text.c
|
||||
trexio_exit_code trexio_text_lock(trexio_t* const file) {
|
||||
if (file == NULL) return TREXIO_INVALID_ARG_1;
|
||||
@ -210,15 +222,6 @@ trexio_exit_code trexio_text_lock(trexio_t* const file) {
|
||||
}
|
||||
#+end_src
|
||||
|
||||
|
||||
#+begin_src c :tangle basic_text.h :exports none
|
||||
trexio_exit_code trexio_text_deinit(trexio_t* const file);
|
||||
#+end_src
|
||||
|
||||
#+begin_src c :tangle basic_text.h :exports none
|
||||
trexio_exit_code trexio_text_unlock(trexio_t* const file);
|
||||
#+end_src
|
||||
|
||||
#+begin_src c :tangle basic_text.c
|
||||
trexio_exit_code
|
||||
trexio_text_unlock (trexio_t* const file)
|
||||
|
@ -85,7 +85,7 @@ static int test_open_errors (const back_end_t backend) {
|
||||
fprintf(stderr, "%s \n", trexio_string_of_error(rc));
|
||||
|
||||
// open existing file with non-supported back end, should return TREXIO_INVALID_ARG_3
|
||||
file = trexio_open(TREXIO_VOID, 'w', 666, &rc);
|
||||
file = trexio_open(TREXIO_FILE, 'w', 666, &rc);
|
||||
assert (file == NULL);
|
||||
assert (rc == TREXIO_INVALID_ARG_3);
|
||||
fprintf(stderr, "%s \n", trexio_string_of_error(rc));
|
||||
@ -96,6 +96,28 @@ static int test_open_errors (const back_end_t backend) {
|
||||
}
|
||||
|
||||
|
||||
static int test_inquire (const back_end_t backend) {
|
||||
|
||||
/* Try to call trexio_inquire function */
|
||||
|
||||
trexio_exit_code rc;
|
||||
|
||||
/*================= START OF TEST ==================*/
|
||||
|
||||
// inquire non-existing file
|
||||
rc = trexio_inquire(TREXIO_VOID);
|
||||
assert (rc == TREXIO_FAILURE);
|
||||
|
||||
// inquire existing file
|
||||
rc = trexio_inquire(TREXIO_FILE);
|
||||
assert (rc == TREXIO_SUCCESS);
|
||||
|
||||
/*================= END OF TEST ==================*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main(void) {
|
||||
|
||||
/*============== Test launcher ================*/
|
||||
@ -107,11 +129,10 @@ int main(void) {
|
||||
test_open_w (TREXIO_FILE, TEST_BACKEND);
|
||||
test_open_r (TREXIO_FILE, TEST_BACKEND);
|
||||
test_open_errors(TEST_BACKEND);
|
||||
test_inquire (TEST_BACKEND);
|
||||
|
||||
rc = system(RM_COMMAND);
|
||||
assert (rc == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -85,7 +85,7 @@ static int test_open_errors (const back_end_t backend) {
|
||||
fprintf(stderr, "%s \n", trexio_string_of_error(rc));
|
||||
|
||||
// open existing file with non-supported back end, should return TREXIO_INVALID_ARG_3
|
||||
file = trexio_open(TREXIO_VOID, 'w', 666, &rc);
|
||||
file = trexio_open(TREXIO_FILE, 'w', 666, &rc);
|
||||
assert (file == NULL);
|
||||
assert (rc == TREXIO_INVALID_ARG_3);
|
||||
fprintf(stderr, "%s \n", trexio_string_of_error(rc));
|
||||
@ -96,6 +96,28 @@ static int test_open_errors (const back_end_t backend) {
|
||||
}
|
||||
|
||||
|
||||
static int test_inquire (const back_end_t backend) {
|
||||
|
||||
/* Try to call trexio_inquire function */
|
||||
|
||||
trexio_exit_code rc;
|
||||
|
||||
/*================= START OF TEST ==================*/
|
||||
|
||||
// inquire non-existing file
|
||||
rc = trexio_inquire(TREXIO_VOID);
|
||||
assert (rc == TREXIO_FAILURE);
|
||||
|
||||
// inquire existing file
|
||||
rc = trexio_inquire(TREXIO_FILE);
|
||||
assert (rc == TREXIO_SUCCESS);
|
||||
|
||||
/*================= END OF TEST ==================*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main(void) {
|
||||
|
||||
/*============== Test launcher ================*/
|
||||
@ -107,11 +129,10 @@ int main(void) {
|
||||
test_open_w (TREXIO_FILE, TEST_BACKEND);
|
||||
test_open_r (TREXIO_FILE, TEST_BACKEND);
|
||||
test_open_errors(TEST_BACKEND);
|
||||
test_inquire (TEST_BACKEND);
|
||||
|
||||
rc = system(RM_COMMAND);
|
||||
assert (rc == 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -103,6 +103,9 @@ subroutine test_write(file_name, back_end)
|
||||
|
||||
! ================= START OF TEST ===================== !
|
||||
|
||||
rc = trexio_inquire(file_name)
|
||||
call trexio_assert(rc, TREXIO_FAILURE)
|
||||
|
||||
trex_file = trexio_open(file_name, 'w', back_end, rc)
|
||||
call trexio_assert(rc, TREXIO_SUCCESS)
|
||||
|
||||
@ -217,6 +220,9 @@ subroutine test_read(file_name, back_end)
|
||||
|
||||
! ================= START OF TEST ===================== !
|
||||
|
||||
rc = trexio_inquire(file_name)
|
||||
call trexio_assert(rc, TREXIO_SUCCESS)
|
||||
|
||||
trex_file = trexio_open(file_name, 'r', back_end, rc)
|
||||
call trexio_assert(rc, TREXIO_SUCCESS)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user