Source code for ly.server.main
# This file is part of python-ly, https://pypi.python.org/pypi/python-ly
#
# Copyright (c) 2014 - 2015 by Wilbert Berendsen
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
# See http://www.gnu.org/licenses/ for more information.
"""
The entry point for the 'ly-server' command.
"""
from __future__ import unicode_literals
from __future__ import print_function
try:
from http.server import HTTPServer
except ImportError:
# Python 2:
from BaseHTTPServer import HTTPServer
import copy
import sys
import ly.pkginfo
from . import options
from . import handler
[docs]def usage():
"""Print usage info."""
from . import doc
sys.stdout.write(doc.__doc__)
[docs]def usage_short():
"""Print short usage info."""
sys.stdout.write("""\
Usage: ly-server [options]
An HTTP server for manipulating LilyPond input code
See ly-server -h for a full list of commands and options.
""")
[docs]def version():
"""Print version info."""
sys.stdout.write("ly-server {0}\n".format(ly.pkginfo.version))
[docs]def die(message):
"""Exit with message to STDERR.
In ly-server this should only be called upon startup, not while processing
requests. Then the error should be sent back to the client."""
sys.stderr.write("error: " + message + '\n')
sys.stderr.write(
"See ly-server -h for a full list of commands and options.\n")
sys.exit(1)
[docs]def parse_command_line():
"""Returns a two-tuple(server_opts, cmd_opts)
server_opts is a ServerOptions instance configuring the server behaviour
cmd_opts is an Options instance with default options for future command
executions triggered by HTTP requests.
Also performs error handling and may exit on certain circumstances.
"""
if isinstance(sys.argv[0], type('')):
# python 3 - arguments are unicode strings
args = iter(sys.argv[1:])
else:
# python 2 - arguments are bytes, decode them
fsenc = sys.getfilesystemencoding() or 'latin1'
args = (a.decode(fsenc) for a in sys.argv[1:])
server_opts = options.ServerOptions()
cmd_opts = options.Options()
def next_arg(message):
"""Get the next argument, if missing, die with message."""
try:
return next(args)
except StopIteration:
die(message)
for arg in args:
if arg in ('-h', '--help'):
usage()
sys.exit(0)
elif arg in ('-v', '--version'):
version()
sys.exit(0)
# Server Options
elif arg in ('-p', '--port'):
server_opts.port = int(next_arg("missing port number"))
elif arg in ('-t', '--timeout'):
server_opts.timeout = int(next_arg("missing timeout (in ms)"))
# Command Options
elif arg in ('-e', '--encoding'):
cmd_opts.encoding = next_arg("missing encoding name")
elif arg == '--output-encoding':
cmd_opts.output_encoding = next_arg("missing output encoding name")
elif arg in ('-l', '--language'):
s = next_arg("missing language name")
cmd_opts.set_variable("default-language", s)
# Command configuration Variables
elif arg == '-d':
s = next_arg("missing variable=value")
try:
name, value = s.split('=', 1)
except ValueError:
die("missing '=' in variable set")
cmd_opts.set_variable(name, value)
elif arg.startswith('-'):
die('unknown option: ' + arg)
return server_opts, cmd_opts
[docs]def main():
server_opts, cmd_opts = parse_command_line()
handler.default_opts = copy.deepcopy(cmd_opts)
exit_code = 0
try:
server = HTTPServer(('', server_opts.port), handler.RequestHandler)
print("Welcome to the python-ly HTTP server")
print("Listening on port {port}".format(port=server_opts.port))
server.serve_forever()
except KeyboardInterrupt:
print("\nKeyboard interrupt received. Shutting down server")
server.socket.close()
print("Successfully closed. Bye...")
return exit_code