Skip to content

Commit bef9df4

Browse files
committed
Update setupbase
1 parent 4730545 commit bef9df4

File tree

2 files changed

+98
-40
lines changed

2 files changed

+98
-40
lines changed

setup.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import sys
66

77
from setupbase import (
8-
setup,
98
log,
109
create_cmdclass,
1110
install_npm,
@@ -14,6 +13,8 @@
1413
get_version,
1514
)
1615

16+
from setuptools import setup
17+
1718

1819
log.set_verbosity(log.DEBUG)
1920
log.info('setup.py entered')
@@ -26,12 +27,13 @@
2627
version = get_version(os.path.join(here, name, '_version.py'))
2728

2829

29-
cmdclass = create_cmdclass('js',
30+
cmdclass = create_cmdclass(
31+
'js',
3032
data_files_spec=[
31-
('share/jupyter/nbextensions/jupyter-threejs', [
32-
name + '/static/*.js',
33-
name + '/static/*.js.map',
34-
]),
33+
('share/jupyter/nbextensions/jupyter-threejs',
34+
name, 'static/*.js'),
35+
('share/jupyter/nbextensions/jupyter-threejs',
36+
name, 'static/*.js.map'),
3537
],
3638
)
3739
cmdclass['js'] = combine_commands(

setupbase.py

Lines changed: 90 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
contains a set of useful utilities for including npm packages
1010
within a Python package.
1111
"""
12+
from collections import defaultdict
1213
from os.path import join as pjoin
1314
import io
1415
import os
@@ -20,12 +21,18 @@
2021
import sys
2122

2223

23-
from setuptools import Command, setup
24-
from setuptools.command.build_py import build_py
25-
from setuptools.command.sdist import sdist
24+
# BEFORE importing distutils, remove MANIFEST. distutils doesn't properly
25+
# update it when the contents of directories change.
26+
if os.path.exists('MANIFEST'): os.remove('MANIFEST')
27+
28+
29+
from distutils.cmd import Command
30+
from distutils.command.build_py import build_py
31+
from distutils.command.sdist import sdist
32+
from distutils import log
33+
2634
from setuptools.command.develop import develop
2735
from setuptools.command.bdist_egg import bdist_egg
28-
from distutils import log
2936

3037
try:
3138
from wheel.bdist_wheel import bdist_wheel
@@ -117,6 +124,17 @@ def update_package_data(distribution):
117124
build_py.finalize_options()
118125

119126

127+
class bdist_egg_disabled(bdist_egg):
128+
"""Disabled version of bdist_egg
129+
130+
Prevents setup.py install performing setuptools' default easy_install,
131+
which it should never ever do.
132+
"""
133+
def run(self):
134+
sys.exit("Aborting implicit building of eggs. Use `pip install .` "
135+
" to install from source.")
136+
137+
120138
def create_cmdclass(prerelease_cmd=None, package_data_spec=None,
121139
data_files_spec=None):
122140
"""Create a command class with the given optional prerelease class.
@@ -129,8 +147,9 @@ def create_cmdclass(prerelease_cmd=None, package_data_spec=None,
129147
A dictionary whose keys are the dotted package names and
130148
whose values are a list of glob patterns.
131149
data_files_spec: list, optional
132-
A list of (path, patterns) tuples where the path is the
133-
`data_files` install path and the patterns are glob patterns.
150+
A list of (path, dname, pattern) tuples where the path is the
151+
`data_files` install path, dname is the source directory, and the
152+
pattern is a glob pattern.
134153
135154
Notes
136155
-----
@@ -142,28 +161,35 @@ def create_cmdclass(prerelease_cmd=None, package_data_spec=None,
142161
name.
143162
e.g. `dict(foo=['./bar/*', './baz/**'])`
144163
145-
The data files glob patterns should be absolute paths or relative paths
146-
from the root directory of the repository.
147-
e.g. `('share/foo/bar', ['pkgname/bizz/*', 'pkgname/baz/**'])`
164+
The data files directories should be absolute paths or relative paths
165+
from the root directory of the repository. Data files are specified
166+
differently from `package_data` because we need a separate path entry
167+
for each nested folder in `data_files`, and this makes it easier to
168+
parse.
169+
e.g. `('share/foo/bar', 'pkgname/bizz, '*')`
148170
"""
149-
egg = bdist_egg if 'bdist_egg' in sys.argv else bdist_egg_disabled
150171
wrapped = [prerelease_cmd] if prerelease_cmd else []
151172
if package_data_spec or data_files_spec:
152173
wrapped.append('handle_files')
153174
wrapper = functools.partial(_wrap_command, wrapped)
154175
handle_files = _get_file_handler(package_data_spec, data_files_spec)
155176

177+
if 'bdist_egg' in sys.argv:
178+
egg = wrapper(bdist_egg, strict=True)
179+
else:
180+
egg = bdist_egg_disabled
181+
156182
cmdclass = dict(
157183
build_py=wrapper(build_py, strict=is_repo),
158-
sdist=wrapper(sdist, strict=True),
159184
bdist_egg=egg,
160-
develop=wrapper(develop, strict=True),
185+
sdist=wrapper(sdist, strict=True),
161186
handle_files=handle_files,
162187
)
163188

164189
if bdist_wheel:
165190
cmdclass['bdist_wheel'] = wrapper(bdist_wheel, strict=True)
166191

192+
cmdclass['develop'] = wrapper(develop, strict=True)
167193
return cmdclass
168194

169195

@@ -221,6 +247,7 @@ def combine_commands(*commands):
221247
"""Return a Command that combines several commands."""
222248

223249
class CombinedCommand(Command):
250+
user_options = []
224251

225252
def initialize_options(self):
226253
self.commands = []
@@ -448,23 +475,14 @@ def run(self):
448475

449476
update_packages(self)
450477

451-
result = cls.run(self)
452478
# update package data
453479
update_package_data(self.distribution)
480+
481+
result = cls.run(self)
454482
return result
455483
return WrappedCommand
456484

457485

458-
class bdist_egg_disabled(bdist_egg):
459-
"""Disabled version of bdist_egg
460-
Prevents setup.py install performing setuptools' default easy_install,
461-
which it should never ever do.
462-
"""
463-
def run(self):
464-
sys.exit("Aborting implicit building of eggs. Use `pip install .` " +
465-
" to install from source.")
466-
467-
468486
def _get_file_handler(package_data_spec, data_files_spec):
469487
"""Get a package_data and data_files handler command.
470488
"""
@@ -473,20 +491,58 @@ class FileHandler(BaseCommand):
473491
def run(self):
474492
package_data = self.distribution.package_data
475493
package_spec = package_data_spec or dict()
476-
data_spec = data_files_spec or []
477494

478495
for (key, patterns) in package_spec.items():
479496
package_data[key] = _get_package_data(key, patterns)
480497

481-
data_files = self.distribution.data_files or []
482-
for (path, patterns) in data_spec:
483-
data_files.append((path, _get_files(patterns)))
484-
485-
self.distribution.data_files = data_files
498+
self.distribution.data_files = _get_data_files(
499+
data_files_spec, self.distribution.data_files
500+
)
486501

487502
return FileHandler
488503

489504

505+
def _get_data_files(data_specs, existing):
506+
"""Expand data file specs into valid data files metadata.
507+
508+
Parameters
509+
----------
510+
data_specs: list of tuples
511+
See [createcmdclass] for description.
512+
existing: list of tuples
513+
The existing distrubution data_files metadata.
514+
515+
Returns
516+
-------
517+
A valid list of data_files items.
518+
"""
519+
# Extract the existing data files into a staging object.
520+
file_data = defaultdict(list)
521+
for (path, files) in existing or []:
522+
file_data[path] = files
523+
524+
# Extract the files and assign them to the proper data
525+
# files path.
526+
for (path, dname, pattern) in data_specs or []:
527+
dname = dname.replace(os.sep, '/')
528+
offset = len(dname) + 1
529+
530+
files = _get_files(pjoin(dname, pattern))
531+
for fname in files:
532+
# Normalize the path.
533+
root = os.path.dirname(fname)
534+
full_path = '/'.join([path, root[offset:]])
535+
if full_path.endswith('/'):
536+
full_path = full_path[:-1]
537+
file_data[full_path].append(fname)
538+
539+
# Construct the data files spec.
540+
data_files = []
541+
for (path, files) in file_data.items():
542+
data_files.append((path, files))
543+
return data_files
544+
545+
490546
def _get_files(file_patterns, top=HERE):
491547
"""Expand file patterns to a list of paths.
492548
@@ -621,7 +677,7 @@ def _translate_glob_part(pat):
621677
res = []
622678
while i < n:
623679
c = pat[i]
624-
i = i+1
680+
i = i + 1
625681
if c == '*':
626682
# Match anything but path separators:
627683
res.append('[^%s]*' % SEPARATORS)
@@ -630,16 +686,16 @@ def _translate_glob_part(pat):
630686
elif c == '[':
631687
j = i
632688
if j < n and pat[j] == '!':
633-
j = j+1
689+
j = j + 1
634690
if j < n and pat[j] == ']':
635-
j = j+1
691+
j = j + 1
636692
while j < n and pat[j] != ']':
637-
j = j+1
693+
j = j + 1
638694
if j >= n:
639695
res.append('\\[')
640696
else:
641697
stuff = pat[i:j].replace('\\', '\\\\')
642-
i = j+1
698+
i = j + 1
643699
if stuff[0] == '!':
644700
stuff = '^' + stuff[1:]
645701
elif stuff[0] == '^':

0 commit comments

Comments
 (0)