Skip to content

Commit 8673f7b

Browse files
Add support for editable installs (AcademySoftwareFoundation#1460)
* Add support for editable installs Signed-off-by: Jean-Christophe Morin <[email protected]> Signed-off-by: Michele Spina <[email protected]>
1 parent 4b6659e commit 8673f7b

File tree

4 files changed

+36
-28
lines changed

4 files changed

+36
-28
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,5 @@ docs/_build
2121
.tox
2222
cpp_cov_html/
2323
lcov_html_report/
24+
*.so
25+
*.pyd

MANIFEST.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ exclude */.DS_Store
2323
exclude .clang-format
2424
exclude OTIO_VERSION.json
2525
global-exclude *.pyc
26+
global-exclude *.so
27+
global-exclude *.pyd
2628

2729
prune maintainers
2830
prune tsc

docs/tutorials/quickstart.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ with OpenTimelineIO due to spaces in the path.
6262
6363
## To build OTIO for Python development:
6464
65-
+ `python -m pip install .`
65+
+ `python -m pip install -e .`
6666
6767
## To build OTIO for both C++ and Python development:
6868

setup.py

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
import sys
1717
import platform
1818
import subprocess
19-
import unittest
2019
import tempfile
2120
import shutil
2221

@@ -46,23 +45,30 @@ def join_args(args):
4645
return ' '.join(map(shlex.quote, args))
4746

4847

49-
class CMakeExtension(Extension):
50-
def __init__(self, name):
51-
Extension.__init__(self, name, sources=[])
52-
53-
5448
class OTIO_build_ext(setuptools.command.build_ext.build_ext):
5549
"""
5650
def initialize_options(self):
5751
super(setuptools.command.build_ext.build_ext, self).initialize_options()
5852
"""
5953

54+
built = False
55+
6056
def run(self):
61-
# This works around the fact that we build _opentime and _otio
62-
# extensions as a one-shot cmake invocation. Usually we'd build each
63-
# separately using build_extension.
6457
self.announce('running OTIO build_ext', level=2)
65-
self.build()
58+
# Let the original build_ext class do its job.
59+
# This is rather important because build_ext.run takes care of a
60+
# couple of things, one of which is to copy the built files into
61+
# the source tree (in src/py-opentimelineio/opentimelineio)
62+
# when building in editable mode.
63+
super().run()
64+
65+
def build_extension(self, _ext: Extension):
66+
# This works around the fact that we build _opentime and _otio
67+
# extensions as a one-shot cmake invocation. Setuptools calls
68+
# build_extension for each Extension registered in the setup function.
69+
if not self.built:
70+
self.build()
71+
self.built = True
6672

6773
def build(self):
6874
self.build_temp_dir = (
@@ -256,22 +262,17 @@ class OTIO_build_py(setuptools.command.build_py.build_py):
256262
"""Stamps PROJECT_METADATA into __init__ files."""
257263

258264
def run(self):
259-
setuptools.command.build_py.build_py.run(self)
260-
261-
if not self.dry_run:
265+
super().run()
266+
267+
if not self.dry_run and not self.editable_mode:
268+
# Only run when not in dry-mode (a dry run should not have any side effect)
269+
# and in non-editable mode. We don't want to edit files when in editable
270+
# mode because that could lead to modifications to the source files.
271+
# Note that setuptools will set self.editable_mode to True
272+
# when "pip install -e ." is run.
262273
_append_version_info_to_init_scripts(self.build_lib)
263274

264275

265-
def test_otio():
266-
"""Discovers and runs tests"""
267-
try:
268-
# Clear the environment of a preset media linker
269-
del os.environ['OTIO_DEFAULT_MEDIA_LINKER']
270-
except KeyError:
271-
pass
272-
return unittest.TestLoader().discover('tests')
273-
274-
275276
# copied from first paragraph of README.md
276277
LONG_DESCRIPTION = """OpenTimelineIO is an interchange format and API for
277278
editorial cut information. OTIO is not a container format for media, rather it
@@ -339,8 +340,13 @@ def test_otio():
339340
),
340341

341342
ext_modules=[
342-
CMakeExtension('_opentimelineio'),
343-
CMakeExtension('_opentime'),
343+
# The full and correct module name is required here because
344+
# setuptools needs to resolve the name to find the built file
345+
# and copy it into the source tree. (Because yes, editable install
346+
# means that the install should point to the source tree, which
347+
# means the .sos need to also be there alongside the python files).
348+
Extension('opentimelineio._otio', sources=[]),
349+
Extension('opentimelineio._opentime', sources=[]),
344350
],
345351

346352
package_dir={
@@ -382,8 +388,6 @@ def test_otio():
382388
]
383389
},
384390

385-
test_suite='setup.test_otio',
386-
387391
# because we need to open() the adapters manifest, we aren't zip-safe
388392
zip_safe=False,
389393

0 commit comments

Comments
 (0)