##// END OF EJS Templates
Fix str error in path again
kevin1kevin1k -
Show More
@@ -1,212 +1,212
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 This module defines the things that are used in setup.py for building IPython
3 This module defines the things that are used in setup.py for building IPython
4
4
5 This includes:
5 This includes:
6
6
7 * The basic arguments to setup
7 * The basic arguments to setup
8 * Functions for finding things like packages, package data, etc.
8 * Functions for finding things like packages, package data, etc.
9 * A function for checking dependencies.
9 * A function for checking dependencies.
10 """
10 """
11
11
12 # Copyright (c) IPython Development Team.
12 # Copyright (c) IPython Development Team.
13 # Distributed under the terms of the Modified BSD License.
13 # Distributed under the terms of the Modified BSD License.
14
14
15 import os
15 import os
16 from pathlib import Path
16 from pathlib import Path
17 import re
17 import re
18 import sys
18 import sys
19 from glob import glob
19 from glob import glob
20 from logging import log
20 from logging import log
21
21
22 from setuptools import Command
22 from setuptools import Command
23 from setuptools.command.build_py import build_py
23 from setuptools.command.build_py import build_py
24
24
25 from setuptools.command.install import install
25 from setuptools.command.install import install
26 from setuptools.command.install_scripts import install_scripts
26 from setuptools.command.install_scripts import install_scripts
27
27
28
28
29 #-------------------------------------------------------------------------------
29 #-------------------------------------------------------------------------------
30 # Useful globals and utility functions
30 # Useful globals and utility functions
31 #-------------------------------------------------------------------------------
31 #-------------------------------------------------------------------------------
32
32
33 # A few handy globals
33 # A few handy globals
34 repo_root = Path(__file__).resolve().parent
34 repo_root = Path(__file__).resolve().parent
35
35
36 def execfile(path, globs, locs=None):
36 def execfile(path, globs, locs=None):
37 locs = locs or globs
37 locs = locs or globs
38 with path.open(encoding="utf-8") as f:
38 with path.open(encoding="utf-8") as f:
39 exec(compile(f.read(), str(path), "exec"), globs, locs)
39 exec(compile(f.read(), str(path), "exec"), globs, locs)
40
40
41 #---------------------------------------------------------------------------
41 #---------------------------------------------------------------------------
42 # Basic project information
42 # Basic project information
43 #---------------------------------------------------------------------------
43 #---------------------------------------------------------------------------
44
44
45 # release.py contains version, authors, license, url, keywords, etc.
45 # release.py contains version, authors, license, url, keywords, etc.
46 execfile(Path(repo_root, "IPython", "core", "release.py"), globals())
46 execfile(Path(repo_root, "IPython", "core", "release.py"), globals())
47
47
48 # Create a dict with the basic information
48 # Create a dict with the basic information
49 # This dict is eventually passed to setup after additional keys are added.
49 # This dict is eventually passed to setup after additional keys are added.
50 setup_args = dict(
50 setup_args = dict(
51 author = author,
51 author = author,
52 author_email = author_email,
52 author_email = author_email,
53 license = license,
53 license = license,
54 )
54 )
55
55
56 #---------------------------------------------------------------------------
56 #---------------------------------------------------------------------------
57 # Check package data
57 # Check package data
58 #---------------------------------------------------------------------------
58 #---------------------------------------------------------------------------
59
59
60 def check_package_data(package_data):
60 def check_package_data(package_data):
61 """verify that package_data globs make sense"""
61 """verify that package_data globs make sense"""
62 print("checking package data")
62 print("checking package data")
63 for pkg, data in package_data.items():
63 for pkg, data in package_data.items():
64 pkg_root = Path(*pkg.split("."))
64 pkg_root = Path(*pkg.split("."))
65 for d in data:
65 for d in data:
66 path = pkg_root / d
66 path = pkg_root / d
67 if "*" in str(path):
67 if "*" in str(path):
68 assert len(glob(path)) > 0, "No files match pattern %s" % path
68 assert len(glob(str(path))) > 0, "No files match pattern %s" % path
69 else:
69 else:
70 assert path.exists(), f"Missing package data: {path}"
70 assert path.exists(), f"Missing package data: {path}"
71
71
72
72
73 def check_package_data_first(command):
73 def check_package_data_first(command):
74 """decorator for checking package_data before running a given command
74 """decorator for checking package_data before running a given command
75
75
76 Probably only needs to wrap build_py
76 Probably only needs to wrap build_py
77 """
77 """
78 class DecoratedCommand(command):
78 class DecoratedCommand(command):
79 def run(self):
79 def run(self):
80 check_package_data(self.package_data)
80 check_package_data(self.package_data)
81 command.run(self)
81 command.run(self)
82 return DecoratedCommand
82 return DecoratedCommand
83
83
84
84
85 #---------------------------------------------------------------------------
85 #---------------------------------------------------------------------------
86 # Find data files
86 # Find data files
87 #---------------------------------------------------------------------------
87 #---------------------------------------------------------------------------
88
88
89 def find_data_files():
89 def find_data_files():
90 """
90 """
91 Find IPython's data_files.
91 Find IPython's data_files.
92
92
93 Just man pages at this point.
93 Just man pages at this point.
94 """
94 """
95
95
96 if "freebsd" in sys.platform:
96 if "freebsd" in sys.platform:
97 manpagebase = Path("man") / "man1"
97 manpagebase = Path("man") / "man1"
98 else:
98 else:
99 manpagebase = Path("share") / "man" / "man1"
99 manpagebase = Path("share") / "man" / "man1"
100
100
101 # Simple file lists can be made by hand
101 # Simple file lists can be made by hand
102 manpages = [f for f in Path("docs/man").glob("*.1.gz") if f.is_file()]
102 manpages = [f for f in Path("docs/man").glob("*.1.gz") if f.is_file()]
103 if not manpages:
103 if not manpages:
104 # When running from a source tree, the manpages aren't gzipped
104 # When running from a source tree, the manpages aren't gzipped
105 manpages = [f for f in Path("docs/man").glob("*.1") if f.is_file()]
105 manpages = [f for f in Path("docs/man").glob("*.1") if f.is_file()]
106
106
107 # And assemble the entire output list
107 # And assemble the entire output list
108 data_files = [(str(manpagebase), [str(f) for f in manpages])]
108 data_files = [(str(manpagebase), [str(f) for f in manpages])]
109
109
110 return data_files
110 return data_files
111
111
112
112
113 # The two functions below are copied from IPython.utils.path, so we don't need
113 # The two functions below are copied from IPython.utils.path, so we don't need
114 # to import IPython during setup, which fails on Python 3.
114 # to import IPython during setup, which fails on Python 3.
115
115
116 def target_outdated(target, deps):
116 def target_outdated(target, deps):
117 """Determine whether a target is out of date.
117 """Determine whether a target is out of date.
118
118
119 target_outdated(target,deps) -> 1/0
119 target_outdated(target,deps) -> 1/0
120
120
121 deps: list of filenames which MUST exist.
121 deps: list of filenames which MUST exist.
122 target: single filename which may or may not exist.
122 target: single filename which may or may not exist.
123
123
124 If target doesn't exist or is older than any file listed in deps, return
124 If target doesn't exist or is older than any file listed in deps, return
125 true, otherwise return false.
125 true, otherwise return false.
126 """
126 """
127 try:
127 try:
128 target_time = Path(target).stat().st_mtime
128 target_time = Path(target).stat().st_mtime
129 except FileNotFoundError:
129 except FileNotFoundError:
130 return 1
130 return 1
131 for dep in deps:
131 for dep in deps:
132 dep_time = Path(dep).stat().st_mtime
132 dep_time = Path(dep).stat().st_mtime
133 if dep_time > target_time:
133 if dep_time > target_time:
134 # print("For target",target,"Dep failed:",dep) # dbg
134 # print("For target",target,"Dep failed:",dep) # dbg
135 # print("times (dep,tar):",dep_time,target_time) # dbg
135 # print("times (dep,tar):",dep_time,target_time) # dbg
136 return 1
136 return 1
137 return 0
137 return 0
138
138
139
139
140 def target_update(target, deps, cmd):
140 def target_update(target, deps, cmd):
141 """Update a target with a given command given a list of dependencies.
141 """Update a target with a given command given a list of dependencies.
142
142
143 target_update(target,deps,cmd) -> runs cmd if target is outdated.
143 target_update(target,deps,cmd) -> runs cmd if target is outdated.
144
144
145 This is just a wrapper around target_outdated() which calls the given
145 This is just a wrapper around target_outdated() which calls the given
146 command if target is outdated."""
146 command if target is outdated."""
147
147
148 if target_outdated(target, deps):
148 if target_outdated(target, deps):
149 os.system(cmd)
149 os.system(cmd)
150
150
151 #---------------------------------------------------------------------------
151 #---------------------------------------------------------------------------
152 # VCS related
152 # VCS related
153 #---------------------------------------------------------------------------
153 #---------------------------------------------------------------------------
154
154
155 def git_prebuild(pkg_dir, build_cmd=build_py):
155 def git_prebuild(pkg_dir, build_cmd=build_py):
156 """Return extended build or sdist command class for recording commit
156 """Return extended build or sdist command class for recording commit
157
157
158 records git commit in IPython.utils._sysinfo.commit
158 records git commit in IPython.utils._sysinfo.commit
159
159
160 for use in IPython.utils.sysinfo.sys_info() calls after installation.
160 for use in IPython.utils.sysinfo.sys_info() calls after installation.
161 """
161 """
162
162
163 class MyBuildPy(build_cmd):
163 class MyBuildPy(build_cmd):
164 ''' Subclass to write commit data into installation tree '''
164 ''' Subclass to write commit data into installation tree '''
165 def run(self):
165 def run(self):
166 # loose as `.dev` is suppose to be invalid
166 # loose as `.dev` is suppose to be invalid
167 print("check version number")
167 print("check version number")
168 loose_pep440re = re.compile(r'^(\d+)\.(\d+)\.(\d+((a|b|rc)\d+)?)(\.post\d+)?(\.dev\d*)?$')
168 loose_pep440re = re.compile(r'^(\d+)\.(\d+)\.(\d+((a|b|rc)\d+)?)(\.post\d+)?(\.dev\d*)?$')
169 if not loose_pep440re.match(version):
169 if not loose_pep440re.match(version):
170 raise ValueError("Version number '%s' is not valid (should match [N!]N(.N)*[{a|b|rc}N][.postN][.devN])" % version)
170 raise ValueError("Version number '%s' is not valid (should match [N!]N(.N)*[{a|b|rc}N][.postN][.devN])" % version)
171
171
172
172
173 build_cmd.run(self)
173 build_cmd.run(self)
174 # this one will only fire for build commands
174 # this one will only fire for build commands
175 if hasattr(self, 'build_lib'):
175 if hasattr(self, 'build_lib'):
176 self._record_commit(self.build_lib)
176 self._record_commit(self.build_lib)
177
177
178 def make_release_tree(self, base_dir, files):
178 def make_release_tree(self, base_dir, files):
179 # this one will fire for sdist
179 # this one will fire for sdist
180 build_cmd.make_release_tree(self, base_dir, files)
180 build_cmd.make_release_tree(self, base_dir, files)
181 self._record_commit(base_dir)
181 self._record_commit(base_dir)
182
182
183 def _record_commit(self, base_dir):
183 def _record_commit(self, base_dir):
184 import subprocess
184 import subprocess
185 proc = subprocess.Popen('git rev-parse --short HEAD',
185 proc = subprocess.Popen('git rev-parse --short HEAD',
186 stdout=subprocess.PIPE,
186 stdout=subprocess.PIPE,
187 stderr=subprocess.PIPE,
187 stderr=subprocess.PIPE,
188 shell=True)
188 shell=True)
189 repo_commit, _ = proc.communicate()
189 repo_commit, _ = proc.communicate()
190 repo_commit = repo_commit.strip().decode("ascii")
190 repo_commit = repo_commit.strip().decode("ascii")
191
191
192 out_pth = Path(base_dir) / pkg_dir / "utils" / "_sysinfo.py"
192 out_pth = Path(base_dir) / pkg_dir / "utils" / "_sysinfo.py"
193 if out_pth.is_file() and not repo_commit:
193 if out_pth.is_file() and not repo_commit:
194 # nothing to write, don't clobber
194 # nothing to write, don't clobber
195 return
195 return
196
196
197 print(f"writing git commit '{repo_commit}' to {out_pth}")
197 print(f"writing git commit '{repo_commit}' to {out_pth}")
198
198
199 # remove to avoid overwriting original via hard link
199 # remove to avoid overwriting original via hard link
200 try:
200 try:
201 out_pth.unlink()
201 out_pth.unlink()
202 except FileNotFoundError:
202 except FileNotFoundError:
203 pass
203 pass
204 with out_pth.open("w", encoding="utf-8") as out_file:
204 with out_pth.open("w", encoding="utf-8") as out_file:
205 out_file.writelines(
205 out_file.writelines(
206 [
206 [
207 "# GENERATED BY setup.py\n",
207 "# GENERATED BY setup.py\n",
208 f'commit = "{repo_commit}"\n',
208 f'commit = "{repo_commit}"\n',
209 ]
209 ]
210 )
210 )
211
211
212 return MyBuildPy
212 return MyBuildPy
General Comments 0
You need to be logged in to leave comments. Login now