diff --git a/python/MANIFEST.in b/python/MANIFEST.in index 95330015e4dbf..cad89c137928c 100644 --- a/python/MANIFEST.in +++ b/python/MANIFEST.in @@ -1,4 +1,3 @@ -include README include MANIFEST.in include *.txt include *.py diff --git a/python/build.py b/python/build.py index b5942dbfcf665..2eb4062859368 100644 --- a/python/build.py +++ b/python/build.py @@ -64,6 +64,7 @@ def get_python_executable(): shutil.rmtree('taichi/lib', ignore_errors=True) shutil.rmtree('taichi/tests', ignore_errors=True) +shutil.rmtree('taichi/examples', ignore_errors=True) os.makedirs('taichi/lib', exist_ok=True) shutil.rmtree('build', ignore_errors=True) shutil.rmtree('dist', ignore_errors=True) @@ -80,6 +81,7 @@ def get_python_executable(): 'taichi/lib/taichi_core.pyd') shutil.copytree('../tests/python', './taichi/tests') +shutil.copytree('../examples', './taichi/examples') if get_os_name() != 'osx': libdevice_path = ti.core.libdevice_path() @@ -106,6 +108,7 @@ def get_python_executable(): shutil.rmtree('taichi/lib') shutil.rmtree('taichi/tests') +shutil.rmtree('taichi/examples') shutil.rmtree('./build') if mode == 'upload': diff --git a/python/taichi/main.py b/python/taichi/main.py index edd9e3b1e6f89..a023eb3d6a839 100644 --- a/python/taichi/main.py +++ b/python/taichi/main.py @@ -8,6 +8,8 @@ from collections import defaultdict from colorama import Fore, Back, Style from taichi.tools.video import make_video, interpolate_frames, mp4_to_gif, scale_video, crop_video, accelerate_video +from pathlib import Path +import runpy def test_python(args): @@ -72,6 +74,43 @@ def test_cpp(args): return int(task.run(*test_files)) +def get_examples_dir() -> Path: + """Get the path to the examples directory.""" + import taichi as ti + + root_dir = ti.package_root() if ti.is_release() else ti.get_repo_directory( + ) + examples_dir = Path(root_dir) / 'examples' + return examples_dir + + +def get_available_examples() -> set: + """Get a set of all available example names.""" + examples_dir = get_examples_dir() + all_examples = examples_dir.rglob('*.py') + all_example_names = { + str(f.resolve()).split('/')[-1].split('.')[0] + for f in all_examples + } + return all_example_names + + +def run_example(name: str): + """Run an example based on the example NAME.""" + all_example_names = get_available_examples() + if name not in all_example_names: + sys.exit( + f"Sorry, {name} is not an available example name!\nAvailable example names are: {sorted(all_example_names)}" + ) + examples_dir = get_examples_dir() + target = str((examples_dir / f"{name}.py").resolve()) + # we need to modify path for examples that use + # implicit relative imports + sys.path.append(str(examples_dir.resolve())) + print(f"Running example {name} ...") + runpy.run_path(target, run_name='__main__') + + def get_benchmark_baseline_dir(): import taichi as ti return os.path.join(ti.core.get_repo_dir(), 'benchmarks', 'baseline') @@ -267,7 +306,9 @@ def main(debug=False): " ti gif |-> Convert mp4 file to gif\n" " ti doc |-> Build documentation\n" " ti release |-> Make source code release\n" - " ti debug [script.py] |-> Debug script\n") + " ti debug [script.py] |-> Debug script\n" + " ti example [name] |-> Run an example by name\n" + ) return 0 t = time.time() @@ -411,6 +452,7 @@ def main(debug=False): framerate = 24 mp4_to_gif(input_fn, output_fn, framerate) elif mode == "convert": + import shutil # http://www.commandlinefu.com/commands/view/3584/remove-color-codes-special-characters-with-sed # TODO: Windows support for fn in sys.argv[2:]: @@ -442,6 +484,13 @@ def main(debug=False): fn = f'taichi-src-v{ver[0]}-{ver[1]}-{ver[2]}-{commit}-{md5}.zip' import shutil shutil.move('release.zip', fn) + elif mode == "example": + if len(sys.argv) != 3: + sys.exit( + f"Invalid arguments! Usage: ti example [name]\nAvailable example names are: {sorted(get_available_examples())}" + ) + example = sys.argv[2] + run_example(name=example) else: name = sys.argv[1] print('Running task [{}]...'.format(name)) diff --git a/setup.py b/setup.py index cddffc1df6d1b..a33e30e2a115b 100644 --- a/setup.py +++ b/setup.py @@ -16,7 +16,7 @@ data_files = glob.glob('python/lib/*') print(data_files) -packages = setuptools.find_packages() +packages = setuptools.find_packages() + ['taichi.examples'] print(packages) setuptools.setup(