Skip to content

Commit 95f903f

Browse files
author
Stefaan Lippens
committed
Issue spotify#838: setup.py: improve packaging of 'bin' scripts with 'entry_points/console_scripts'
1 parent 8aae1f8 commit 95f903f

12 files changed

+96
-52
lines changed

.travis.yml

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ cache:
2727
- $HOME/.pip-cache
2828

2929
install:
30+
- pip install .
3031
- pip install tox
3132

3233
before_script:

MANIFEST.in

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
include bin/luigid
21
include README.rst
32
include LICENSE
43
include examples/*.py

bin/luigi

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
#!/usr/bin/env python
22

3-
import luigi
3+
import sys
4+
import warnings
5+
import luigi.cmdline
6+
7+
8+
def main(argv):
9+
warnings.warn("'bin/luigi' has moved to console script 'luigi'", DeprecationWarning)
10+
luigi.cmdline.luigi_run(argv)
11+
412

513
if __name__ == '__main__':
6-
luigi.run(use_dynamic_argparse=True)
14+
main(sys.argv[1:])

bin/luigid

+5-31
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,14 @@
11
#!/usr/bin/env python
22

3-
import luigi.server
4-
import luigi.process
5-
import os
6-
import luigi.configuration
7-
import optparse
8-
import logging
93
import sys
4+
import warnings
5+
import luigi.cmdline
106

11-
def main(argv):
12-
parser = optparse.OptionParser()
13-
parser.add_option(u'--background', help=u'Run in background mode', action='store_true')
14-
parser.add_option(u'--pidfile', help=u'Write pidfile')
15-
parser.add_option(u'--logdir', help=u'log directory')
16-
parser.add_option(u'--state-path', help=u'Pickled state file')
17-
parser.add_option(u'--address', help=u'Listening interface')
18-
parser.add_option(u'--port', default=8082, help=u'Listening port')
19-
20-
opts, args = parser.parse_args(argv)
217

22-
if opts.state_path:
23-
config = luigi.configuration.get_config()
24-
config.set('scheduler', 'state-path', opts.state_path)
8+
def main(argv):
9+
warnings.warn("'bin/luigid' has moved to console script 'luigid'", DeprecationWarning)
10+
luigi.cmdline.luigid(argv)
2511

26-
if opts.background:
27-
# daemonize sets up logging to spooled log files
28-
logging.getLogger().setLevel(logging.INFO)
29-
luigi.process.daemonize(luigi.server.run, api_port=opts.port,
30-
address=opts.address, pidfile=opts.pidfile,
31-
logdir=opts.logdir)
32-
else:
33-
if opts.logdir:
34-
logging.basicConfig(level=logging.INFO, format=luigi.process.get_log_format(), filename=os.path.join(opts.logdir, "luigi-server.log"))
35-
else:
36-
logging.basicConfig(level=logging.INFO, format=luigi.process.get_log_format())
37-
luigi.server.run(api_port=opts.port, address=opts.address)
3812

3913
if __name__ == '__main__':
4014
main(sys.argv[1:])

doc/central_scheduler.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ To run the server as a daemon run:
2424

2525
::
2626

27-
PYTHONPATH=. python bin/luigid --background --pidfile <PATH_TO_PIDFILE> --logdir <PATH_TO_LOGDIR> --state-path <PATH_TO_STATEFILE>
27+
luigid --background --pidfile <PATH_TO_PIDFILE> --logdir <PATH_TO_LOGDIR> --state-path <PATH_TO_STATEFILE>
2828

2929
Note that this requires ``python-daemon``.
3030
By default, the server starts on port ``8082``

doc/example_top_artists.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ If you run
238238

239239
::
240240

241-
PYTHONPATH=. python bin/luigid
241+
luigid
242242

243243
in the background and then run
244244

luigi/cmdline.py

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import os
2+
import optparse
3+
import logging
4+
import sys
5+
6+
import luigi.server
7+
import luigi.process
8+
import luigi.configuration
9+
import luigi.interface
10+
11+
12+
def luigi_run(argv=sys.argv[1:]):
13+
luigi.interface.run(argv, use_dynamic_argparse=True)
14+
15+
16+
def luigid(argv=sys.argv[1:]):
17+
parser = optparse.OptionParser()
18+
parser.add_option(u'--background', help=u'Run in background mode', action='store_true')
19+
parser.add_option(u'--pidfile', help=u'Write pidfile')
20+
parser.add_option(u'--logdir', help=u'log directory')
21+
parser.add_option(u'--state-path', help=u'Pickled state file')
22+
parser.add_option(u'--address', help=u'Listening interface')
23+
parser.add_option(u'--port', default=8082, help=u'Listening port')
24+
25+
opts, args = parser.parse_args(argv)
26+
27+
if opts.state_path:
28+
config = luigi.configuration.get_config()
29+
config.set('scheduler', 'state-path', opts.state_path)
30+
31+
if opts.background:
32+
# daemonize sets up logging to spooled log files
33+
logging.getLogger().setLevel(logging.INFO)
34+
luigi.process.daemonize(luigi.server.run, api_port=opts.port,
35+
address=opts.address, pidfile=opts.pidfile,
36+
logdir=opts.logdir)
37+
else:
38+
if opts.logdir:
39+
logging.basicConfig(level=logging.INFO, format=luigi.process.get_log_format(),
40+
filename=os.path.join(opts.logdir, "luigi-server.log"))
41+
else:
42+
logging.basicConfig(level=logging.INFO, format=luigi.process.get_log_format())
43+
luigi.server.run(api_port=opts.port, address=opts.address)

luigi/server.py

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838

3939
from luigi.scheduler import CentralPlannerScheduler
4040

41+
4142
logger = logging.getLogger("luigi.server")
4243

4344

bin/deps.py luigi/tools/deps.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ def find_deps_cli():
8888
return find_deps(task, upstream)
8989

9090

91-
if __name__ == '__main__':
91+
def main():
9292
deps = find_deps_cli()
9393
for d in deps:
9494
task_name = d
@@ -105,3 +105,7 @@ def find_deps_cli():
105105
task_output = "to be determined"
106106
print(u""" TASK: {0}
107107
: {1}""".format(task_name, task_output))
108+
109+
110+
if __name__ == '__main__':
111+
main()

bin/luigi-grep.py luigi/tools/luigi_grep.py

+15-11
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,6 @@
77

88
from luigi import six
99

10-
parser = argparse.ArgumentParser(
11-
"luigi-grep is used to search for workflows using the luigi scheduler's json api")
12-
parser.add_argument(
13-
"--scheduler-host", default="localhost", help="hostname of the luigi scheduler")
14-
parser.add_argument(
15-
"--scheduler-port", default="8082", help="port of the luigi scheduler")
16-
parser.add_argument("--prefix", help="prefix of a task query to search for", default=None)
17-
parser.add_argument("--status", help="search for jobs with the given status", default=None)
18-
1910

2011
class LuigiGrep(object):
2112

@@ -29,7 +20,7 @@ def graph_url(self):
2920

3021
def _fetch_json(self):
3122
"""Returns the json representation of the dep graph"""
32-
print "Fetching from url: " + self.graph_url
23+
print("Fetching from url: " + self.graph_url)
3324
resp = urllib2.urlopen(self.graph_url).read()
3425
return json.loads(resp)
3526

@@ -61,7 +52,17 @@ def status_search(self, status):
6152
if job_info['status'].lower() == status.lower():
6253
yield self._build_results(jobs, job)
6354

64-
if __name__ == '__main__':
55+
56+
def main():
57+
parser = argparse.ArgumentParser(
58+
"luigi-grep is used to search for workflows using the luigi scheduler's json api")
59+
parser.add_argument(
60+
"--scheduler-host", default="localhost", help="hostname of the luigi scheduler")
61+
parser.add_argument(
62+
"--scheduler-port", default="8082", help="port of the luigi scheduler")
63+
parser.add_argument("--prefix", help="prefix of a task query to search for", default=None)
64+
parser.add_argument("--status", help="search for jobs with the given status", default=None)
65+
6566
args = parser.parse_args()
6667
grep = LuigiGrep(args.scheduler_host, args.scheduler_port)
6768

@@ -77,3 +78,6 @@ def status_search(self, status):
7778
print(" status={status}".format(status=status))
7879
for job in jobs:
7980
print(" {job}".format(job=job))
81+
82+
if __name__ == '__main__':
83+
main()

setup.py

+8-4
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,14 @@ def get_static_files(path):
6969
package_data={
7070
'luigi': luigi_package_data
7171
},
72-
scripts=[
73-
'bin/luigid',
74-
'bin/luigi'
75-
],
72+
entry_points={
73+
'console_scripts': [
74+
'luigi = luigi.cmdline:luigi_run',
75+
'luigid = luigi.cmdline:luigid',
76+
'luigi-grep = luigi.tools.luigi_grep:main',
77+
'luigi-deps = luigi.tools.deps:main',
78+
]
79+
},
7680
install_requires=install_requires,
7781
classifiers=[
7882
'Development Status :: 5 - Production/Stable',

test/cmdline_test.py

+6
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,12 @@ def test_bin_luigi(self):
177177
self._run_cmdline(args)
178178
self.assertTrue(t.exists())
179179

180+
def test_console_script_luigi(self):
181+
t = luigi.LocalTarget(is_tmp=True)
182+
args = ['luigi', '--module', 'cmdline_test', 'WriteToFile', '--filename', t.path, '--local-scheduler', '--no-lock']
183+
self._run_cmdline(args)
184+
self.assertTrue(t.exists())
185+
180186
def test_direct_python(self):
181187
t = luigi.LocalTarget(is_tmp=True)
182188
args = ['python', 'test/cmdline_test.py', 'WriteToFile', '--filename', t.path, '--local-scheduler', '--no-lock']

0 commit comments

Comments
 (0)