-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsetup_develop_mode.py
More file actions
92 lines (73 loc) · 3.44 KB
/
setup_develop_mode.py
File metadata and controls
92 lines (73 loc) · 3.44 KB
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
import os
import sys
import glob
import shutil
import setuptools.command.develop as develop
"""
This module contains some little workaround for the problem that
`python setup.py develop` (and thus `pip install -e .`) is incompatible
with a package layout where the modules are living on the top level.
However, that top-level-layout is needed for backward compatibility.
"""
current_dir = os.path.dirname(os.path.abspath(sys.modules.get(__name__).__file__))
parent_dir = os.path.dirname(current_dir)
def install_develop_mode(dist):
"""
`python setup.py develop` assumes a directory structure where the package
to be installed lives in a subdirectory. This function assumes that this command
has already been run. Now it remains to
- adapt the path inside the <package_name>.egg-link-text file (-> parent_dir)
- adapt the path inside easy_install.pth (-> parent_dir)
- move the directory <package_name>.egg-info to parent_dir
For safety reasons the following directory structure is assumed:
<arbitrary_dir_name>/ <- the .egg-link will point here
│
├── <package_name>/ <- all the source lives here
│ ├── .git/
│ ├── setup.py
│ ├── setup_develop_mode.py
│ └── ...
└── <package_name.egg-info>/ <- autogenerated by setuptools, moved here by this function
Note: No other directories or files are allowed inside <arbitrary_dir_name>.
:param dist: setuptools.dist object
:return:
"""
# noinspection PyArgumentList
dev_obj = develop.develop(dist)
dev_obj.ensure_finalized()
old_egg_path = dev_obj.egg_path
new_egg_path = os.path.dirname(old_egg_path)
# ensure the required directory structure is met
sibling_dirs = glob.glob(os.path.join(parent_dir, "*"))
# remove the trivial case:
sibling_dirs.remove(current_dir)
# allow egg-info dir from previous install (will be overwritten anyway)
parent_egg_info = os.path.join(parent_dir, os.path.split(dev_obj.dist.egg_info)[1])
if parent_egg_info in sibling_dirs:
sibling_dirs.remove(parent_egg_info)
if len(sibling_dirs) > 0:
# maybe it would be convenient to allow some exceptions here like, e.g. for config files
msg = "The following files/directories contradict the assumed directory structure:\n{}"
msg = msg.format("\n".join(sibling_dirs))
raise FileExistsError(msg)
if dev_obj.dry_run:
return
# this heavily inspired by setuptools.commands.develop.develop.install_for_development
with open(dev_obj.egg_link, "w") as f:
f.write(new_egg_path + "\n" + dev_obj.setup_path)
# now move the egg-info directory one level higher
egg_info_dirs = glob.glob(os.path.join(current_dir, "*egg-info"))
assert len(egg_info_dirs) == 1
source = egg_info_dirs[0]
target = os.path.join(parent_dir, os.path.split(source)[1])
assert target == parent_egg_info
shutil.rmtree(target, ignore_errors=True)
shutil.move(source, target)
# this is inspired by pip._internals.req.req_uninstall.UninstallPathSet.from_dist
easy_install_pth = os.path.join(os.path.dirname(dev_obj.egg_link), 'easy-install.pth')
with open(easy_install_pth, "r") as f:
all_paths = f.read()
if old_egg_path in all_paths:
all_paths = all_paths.replace(old_egg_path, new_egg_path)
with open(easy_install_pth, "w") as f:
f.write(all_paths)