1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
|
#!/usr/bin/env python
#
# Copyright (c) 2008-2022 by Enthought, Inc.
# All rights reserved.
from setuptools import Command, Extension, setup, find_packages
from setuptools.command.build_py import build_py
from setuptools.command.develop import develop
from setuptools.command.install import install
import os
import time
import subprocess
import shutil
import re
import sys
from os.path import (abspath, basename, dirname, exists, getmtime, isdir,
join, split)
from pathlib import Path
from tvtk._setup import can_compile_extensions, gen_tvtk_classes_zip # noqa
MY_DIR = os.path.dirname(__file__)
MODE = 'normal'
if len(sys.argv) >= 2 and \
('--help' in sys.argv[1:] or
sys.argv[1] in ('--help-commands', 'egg_info', '--version',
'clean', 'sdist')):
MODE = 'info'
info = {}
fname = join('mayavi', '__init__.py')
exec(compile(open(fname).read(), fname, 'exec'), info)
DEFAULT_HTML_TARGET_DIR = join('docs', 'build')
DEFAULT_INPUT_DIR = join('docs', 'source',)
class GenDocs(Command):
description = (
"This command generates generated part of the documentation "
"when needed. It's run automatically before a build_docs, and that's "
"the only time it needs to be run."
)
user_options = [
('None', None, 'this command has no options'),
]
def latest_modified(self, the_path, filetypes='', ignore_dirs=''):
"""Traverse a path looking for the most recently modified file.
Parameters
----------
the_path : string
Contains path to be traversed or filename to be inspected.
filetypes : string
Regular expression pattern of files to examine. If specified, other
files are ignored. Otherwise, all files are examined.
ignore_dirs : string
Regular expression pattern of directories to be ignored. If ignore
specified, all directories are walked.
Returns
-------
latest_time : float
Modification time of latest_path.
latest_path : string
Most recently modified file.
"""
file_re = re.compile(filetypes)
dir_re = re.compile(ignore_dirs)
if not exists(the_path):
return 0, the_path
if isdir(the_path):
latest_time = 0
latest_path = the_path
for root, dirs, files in os.walk(the_path):
if ignore_dirs != '':
# This needs to iterate over a copy of the list. Otherwise,
# as things get removed from the original list, the indices
# become invalid.
for dir in dirs[:]:
if dir_re.search(dir):
dirs.remove(dir)
for file in files:
if filetypes != '':
if not file_re.search(file):
continue
current_file_time = getmtime(join(root, file))
if current_file_time > latest_time:
latest_time = current_file_time
latest_path = join(root, file)
return latest_time, latest_path
else:
return getmtime(the_path), the_path
def mlab_reference(self):
"""If mayavi is installed, run the mlab_reference generator."""
# XXX: This is really a hack: the script is not made to be used
# for different projects, but it ended up being. This part is
# mayavi-specific.
mlab_ref_dir = join(DEFAULT_INPUT_DIR, 'mayavi', 'auto')
source_path = 'mayavi'
sources = r'(\.py)|(\.rst)$'
excluded_dirs = r'^\.'
target_path = mlab_ref_dir
target_time = self.latest_modified(target_path,
ignore_dirs=excluded_dirs)[0]
if (self.latest_modified(source_path, filetypes=sources,
ignore_dirs=excluded_dirs)[0] > target_time
or self.latest_modified('mlab_reference.py')[0] > target_time
or not exists(join('docs', 'source', 'mayavi', 'auto',
'mlab_reference.rst'))):
try:
from mayavi import mlab
from mayavi.tools import auto_doc
print("Generating the mlab reference documentation")
os.system('python mlab_reference.py')
except Exception:
pass
def example_files(self):
"""Generate the documentation files for the examples."""
mlab_ref_dir = join(DEFAULT_INPUT_DIR, 'mayavi', 'auto')
source_path = join('examples', 'mayavi')
sources = r'(\.py)|(\.rst)$'
excluded_dirs = r'^\.'
target_path = mlab_ref_dir
target_time = self.latest_modified(target_path,
ignore_dirs=excluded_dirs)[0]
script_file_name = join('docs', 'source', 'render_examples.py')
if (self.latest_modified(source_path, filetypes=sources,
ignore_dirs=excluded_dirs)[0] > target_time
or self.latest_modified(script_file_name)[0] > target_time
or not exists(join('docs', 'source', 'mayavi', 'auto',
'examples.rst'))
):
try:
from mayavi import mlab
from mayavi.tools import auto_doc
print("Generating the example list")
subprocess.call('python %s' %
basename(script_file_name), shell=True,
cwd=dirname(script_file_name))
except:
pass
def run(self):
self.mlab_reference()
self.example_files()
def initialize_options(self):
pass
def finalize_options(self):
pass
class BuildDocs(Command):
description = \
"This command generates the documentation by running Sphinx. " \
"It then zips the docs into an html.zip file."
user_options = [
('None', None, 'this command has no options'),
]
def make_docs(self):
if os.name == 'nt':
print("Please impelemnt sphinx building on windows here.")
else:
subprocess.call(['make', 'html'], cwd='docs')
def run(self):
self.make_docs()
def initialize_options(self):
pass
def finalize_options(self):
pass
# Functions to generate the docs
def list_doc_projects():
""" List the different source directories under DEFAULT_INPUT_DIR
for which we have docs.
"""
source_dir = join(abspath(MY_DIR), DEFAULT_INPUT_DIR)
source_list = os.listdir(source_dir)
# Check to make sure we're using non-hidden directories.
source_dirs = [listing for listing in source_list
if isdir(join(source_dir, listing))
and not listing.startswith('.')]
return source_dirs
def list_docs_data_files(project):
""" List the files to add to a project by inspecting the
documentation directory. This works only if called after the
build step, as the files have to be built.
returns a list of (install_dir, [data_files, ]) tuples.
"""
project_target_dir = join(DEFAULT_HTML_TARGET_DIR, project, 'html')
return_list = []
for root, dirs, files in os.walk(project_target_dir, topdown=True):
# Modify inplace the list of directories to walk
dirs[:] = [d for d in dirs if not d.startswith('.')]
if len(files) == 0:
continue
install_dir = root.replace(project_target_dir, join(project, 'html'))
return_list.append((install_dir, [join(root, f) for f in files]))
return return_list
def _tvtk_built_recently(zipfile, delay):
"""Returns True if the TVTK classes in zipfile was built in the last
delay seconds.
"""
if not os.path.exists(zipfile):
return False
ctime = os.stat(zipfile).st_ctime
tdiff = time.time() - ctime
return tdiff < delay
# Our custom distutils hooks
def build_tvtk_classes_zip():
zipfile = os.path.join(MY_DIR, 'tvtk', 'tvtk_classes.zip')
if _tvtk_built_recently(zipfile, delay=120):
print("Already built tvtk_classes.zip")
return
else:
print("Building tvtk_classes.zip")
gen_tvtk_classes_zip()
class MyBuildPy(build_py):
"""A build hook to generate the documentation."""
def run(self):
build_tvtk_classes_zip()
super().run()
class MyDevelop(develop):
"""A hook to build the TVTK ZIP file on develop."""
def run(self):
build_tvtk_classes_zip()
super().run()
###########################################################################
# Similar to package_data, but installed before build
build_package_data = {'mayavi.images': ['docs/source/mayavi/_static/m2_about.jpg']}
# Install our data files at build time. This is iffy,
# but we need to do this before distutils kicks in.
for package, files in build_package_data.items():
target_path = package.replace('.', os.sep)
for filename in files:
shutil.copy(filename, target_path)
try:
import numpy as np
except Exception:
HAS_NUMPY = False
else:
HAS_NUMPY = True
if not HAS_NUMPY and MODE != 'info':
msg = '''
Numpy is required to build Mayavi correctly, please install it first.
'''
print('*'*80)
print(msg)
print('*'*80)
raise RuntimeError(msg)
###########################################################################
# The actual setup call
if __name__ == '__main__':
ext_modules = list()
packages = find_packages(exclude=["docs", "examples"])
packages += [ # otherwise we get warnings. Maybe these should be excluded?
"mayavi.core.images",
"mayavi.core.ui.images",
"mayavi.images",
"mayavi.preferences.images",
"mayavi.tests.csv_files",
"mayavi.tests.data",
"mayavi.tools.static.x3d",
"tvtk.pipeline.images",
"tvtk.pyface.images",
"tvtk.src",
"tvtk.tools.images",
]
if can_compile_extensions():
import numpy as np
ext_modules.append(
Extension(
"tvtk.array_ext",
sources=[join("tvtk", "src", "array_ext.c")],
depends=[join("tvtk", "src", "array_ext.pyx")],
include_dirs=[np.get_include()],
)
)
setup(
name='mayavi',
version=info['__version__'],
author="Prabhu Ramachandran, et al.",
author_email="prabhu@aero.iitb.ac.in",
maintainer='ETS Developers',
python_requires='>=3.9',
maintainer_email='mayavi-users@lists.sf.net',
url='http://docs.enthought.com/mayavi/mayavi/',
classifiers=[c.strip() for c in """\
Development Status :: 5 - Production/Stable
Intended Audience :: Developers
Intended Audience :: Science/Research
License :: OSI Approved :: BSD License
Operating System :: MacOS
Operating System :: Microsoft :: Windows
Operating System :: OS Independent
Operating System :: POSIX
Operating System :: Unix
Programming Language :: C
Programming Language :: Python
Topic :: Scientific/Engineering
Topic :: Software Development
Topic :: Software Development :: Libraries
""".splitlines() if len(c.split()) > 0],
cmdclass={
'build_py': MyBuildPy,
'develop': MyDevelop,
'gen_docs': GenDocs,
'build_docs': BuildDocs,
},
description='3D scientific data visualization library and application',
download_url=('https://www.github.com/enthought/mayavi'),
entry_points={
'gui_scripts': [
'mayavi2 = mayavi.scripts.mayavi2:main',
'tvtk_doc = tvtk.tools.tvtk_doc:main'
],
'envisage.plugins': [
'tvtk.scene = tvtk.plugins.scene.scene_plugin:ScenePlugin',
'tvtk.scene_ui = tvtk.plugins.scene.ui.scene_ui_plugin:SceneUIPlugin',
'tvtk.browser = tvtk.plugins.browser.browser_plugin:BrowserPlugin',
'mayavi = mayavi.plugins.mayavi_plugin:MayaviPlugin',
'mayavi_ui = mayavi.plugins.mayavi_ui_plugin:MayaviUIPlugin'
],
'tvtk.toolkits': [
'qt4 = tvtk.pyface.ui.qt4.init:toolkit_object',
'qt = tvtk.pyface.ui.qt4.init:toolkit_object',
'wx = tvtk.pyface.ui.wx.init:toolkit_object',
'null = tvtk.pyface.ui.null.init:toolkit_object',
]
},
extras_require=info['__extras_require__'],
packages=packages,
include_package_data=True,
package_data={"tvtk": ["tvtk_classes.zip"]},
ext_modules=ext_modules,
install_requires=info['__requires__'],
license="BSD",
long_description=Path('README.rst').read_text(encoding='utf-8'),
platforms=["Windows", "Linux", "Mac OS-X", "Unix", "Solaris"],
zip_safe=False,
)
|