r"""
Write flint header files.
"""
import os
import shutil
from .env import AUTOGEN_DIR, FLINT_GIT_DIR, FLINT_DOC_DIR, FLINT_INCLUDE_DIR
from .reader import extract_functions
def write_flint_cython_headers(output_dir, documentation=False):
r"""
Write cython header files.
Arguments
output_dir -- (string) path where to write the .pxd files
Requires gitpython to be installed.
"""
if not os.path.isdir(os.path.join(FLINT_GIT_DIR, ".git")):
raise ValueError(f"FLINT_GIT_DIR(={FLINT_GIT_DIR}) is not a Git repository")
import git
repo = git.Repo(FLINT_GIT_DIR)
commit = repo.head.commit
print(f"Generating cython headers from {commit}")
header_list = []
pxd_list = []
for filename in os.listdir(FLINT_DOC_DIR):
if not filename.endswith('.rst'):
continue
prefix = filename[:-4]
absolute_filename = os.path.join(FLINT_DOC_DIR, filename)
content = extract_functions(absolute_filename)
if not content:
continue
header = prefix + '.h'
if prefix == 'flint':
header = header + '.in'
absolute_header = os.path.join(FLINT_INCLUDE_DIR, header)
if not os.path.isfile(absolute_header):
print('Warning: skipping {} because no associated .h found'.format(filename))
continue
if prefix == 'machine_vectors' or prefix == 'fft_small':
print('Warning: ignoring machine_vectors and fft_small because architecture dependent')
continue
if prefix == 'acb_theta':
print('Warning: ignoring acb_theta because not in stable release')
continue
header_list.append(prefix + '.h')
pxd_list.append(prefix + '.pxd')
output = open(os.path.join(output_dir, prefix + '.pxd'), 'w')
print('# distutils: libraries = flint', file=output)
print('# distutils: depends = flint/{}'.format(prefix + '.h'), file=output)
print(file=output)
print('#' * 80, file=output)
print('# This file is auto-generated by the script', file=output)
print('# SAGE_ROOT/tools/flint-autogen/flint_autogen.py.', file=output)
print('# From the commit {}'.format(commit), file=output)
print('# Do not modify by hand! Fix and rerun the script instead.', file=output)
print('#' * 80, file=output)
print(file=output)
print('from libc.stdio cimport FILE', file=output)
print('from sage.libs.gmp.types cimport *', file=output)
print('from sage.libs.mpfr.types cimport *', file=output)
print('from sage.libs.flint.types cimport *', file=output)
print(file=output)
print('cdef extern from "flint_wrap.h":', file=output)
for section in content:
if section is not None:
print(' ## {}'.format(section), file=output)
for func_signatures, doc in content[section]:
if documentation:
print(file=output)
for line in doc:
print(' # {}'.format(line), file=output)
for line in func_signatures:
print(' {} noexcept'.format(line), file=output)
if os.path.isfile(os.path.join(AUTOGEN_DIR, 'macros', prefix + '_macros.pxd')):
print('\nfrom .{} cimport *'.format(prefix + '_macros'), file=output)
output.close()
for extra_header in ['nmod_types.h']:
if extra_header in header_list:
print('Warning: {} already in HEADER_LIST'.format(extra_header))
header_list.append(extra_header)
header_list.sort()
pxd_list.sort()
with open(os.path.join(AUTOGEN_DIR, 'templates', 'flint_wrap.h.template')) as f:
text = f.read()
with open(os.path.join(output_dir, 'flint_wrap.h'), 'w') as output:
output.write(text.format(HEADER_LIST='\n'.join('#include <flint/{}>'.format(header) for header in header_list)))
with open(os.path.join(AUTOGEN_DIR, 'templates', 'types.pxd.template')) as f:
text = f.read()
with open(os.path.join(output_dir, 'types.pxd'), 'w') as output:
output.write(text.format(HEADER_LIST=' '.join('flint/{}'.format(header) for header in header_list)))
for filename in os.listdir(os.path.join(AUTOGEN_DIR, 'macros')):
prefix = filename[:-4]
shutil.copy(os.path.join(AUTOGEN_DIR, 'macros', filename), os.path.join(output_dir, filename))
with open(os.path.join(AUTOGEN_DIR, 'templates', 'flint_sage.pyx.template')) as f:
text = f.read()
with open(os.path.join(output_dir, 'flint_sage.pyx'), 'w') as output:
output.write(text.format(CYTHON_IMPORTS='\n'.join('from .{} cimport *'.format(header[:-4]) for header in pxd_list)))