# Path: stolos/runner.py
# def build_arg_parser_and_parse_args():
#     # """
#     # Get an argparse.Namespace from sys.argv,
#     # Lazily import the appropriate plugin module based on the given app name
#     # And recreate the namespace with arguments specific to that plugin module
#     # """
# 
#     parser = at.build_arg_parser([at.group(
#         "Runtime options",
#         at.app_name,
#         at.add_argument(
#             '--bypass_scheduler', action='store_true', help=(
#                 "Run a task directly. Do not schedule it."
#                 "  Do not obtain a lock on this job."
#                 "  Requires passing --job_id")),
#         at.add_argument(
#             '--timeout', type=int, default=2,
#             help='time to wait for task to appear in queue before dying'),
#         at.add_argument(
#             '--max_retry', type=int, default=5,
#             help='Maximum number of times to retry a failed task.'),
#         at.add_argument(
#             '--job_id', help=(
#                 'run a specific job_id. If a job is already queued,'
#                 ' it will run twice')),
#     )], description=(
#         "This script intelligently executes your application's jobs."
#         " Specifically, an instance of this script fetches exactly 1 job"
#         " from your application's queue, decides how to perform those jobs,"
#         " and then dies.  Because jobs are managed in a DAG, Stolos may choose"
#         " to delay execution of a job until dependencies have been met."
#         " It may also queue child or parent jobs depending on their status."),
#     )
#     parser, ns = initialize(
#         [parser(), dt, cb, qb],
#         parse_known_args=True)
# 
#     # get plugin parser
#     plugin = importlib.import_module(
#         'stolos.plugins.%s_plugin' % dt.get_job_type(ns.app_name))
#     ns = at.build_arg_parser(
#         parents=[parser, plugin.build_arg_parser()],
#         add_help=True
#     ).parse_args()
#     ns.job_type_func = plugin.main
#     return ns
# 
# def main(ns):
#     """
#     Fetch a job_id from the `app_name` queue and figure out what to with it.
# 
#     If the job is runnable, execute it and then queue its children into their
#     respective queues.  If it's not runnable, queue its parents into respective
#     parent queues and remove the job from its own queue.
#     If the job fails, either requeue it or mark it as permanently failed
#     """
#     assert ns.app_name in dt.get_task_names()
#     if ns.bypass_scheduler:
#         log.info(
#             "Running a task without scheduling anything"
#             " or fetching from a queue", extra=dict(
#                 app_name=ns.app_name, job_id=ns.job_id))
#         assert ns.job_id
#         ns.job_type_func(ns=ns)
#         return
# 
#     log.info("Beginning Stolos", extra=dict(**ns.__dict__))
#     q = qb.get_qbclient().LockingQueue(ns.app_name)
#     if ns.job_id:
#         lock = _handle_manually_given_job_id(ns)
#         q.consume = object  # do nothing
#     else:
#         ns.job_id = q.get(timeout=ns.timeout)
#         if not validate_job_id(app_name=ns.app_name, job_id=ns.job_id,
#                                q=q, timeout=ns.timeout):
#             return
#         try:
#             lock = get_lock_if_job_is_runnable(
#                 app_name=ns.app_name, job_id=ns.job_id)
#         except exceptions.NoNodeError:
#             q.consume()
#             log.exception(
#                 "Job failed. The job is queued, so why does its state not"
#                 " exist?  The Queue backend may be in an inconsistent state."
#                 " Consuming this job",
#                 extra=dict(app_name=ns.app_name, job_id=ns.job_id))
#             return
# 
#     log.debug(
#         "Stolos got a job_id.", extra=dict(
#             app_name=ns.app_name, job_id=ns.job_id, acquired_lock=bool(lock)))
#     if lock is False:
#         # infinite loop: some jobs will always requeue if lock is unobtainable
#         log.info("Could not obtain a lock.  Will requeue and try again later",
#                  extra=dict(app_name=ns.app_name, job_id=ns.job_id))
#         _send_to_back_of_queue(
#             q=q, app_name=ns.app_name, job_id=ns.job_id)
#         return
# 
#     if not parents_completed(ns.app_name, ns.job_id, q=q, lock=lock):
#         return
# 
#     log.info(
#         "Job starting!", extra=dict(app_name=ns.app_name, job_id=ns.job_id))
#     try:
#         ns.job_type_func(ns=ns)
#     except exceptions.CodeError:  # assume error is previously logged
#         _handle_failure(ns, q, lock)
#         return
#     except Exception as err:
#         log.exception(
#             ("Job failed!  Unhandled exception in an application!"
#              " Fix ASAP because"
#              " it is unclear how to handle this failure.  %s: %s")
#             % (err.__class__.__name__, err), extra=dict(
#                 app_name=ns.app_name, job_id=ns.job_id, failed=True))
#         return
#     _handle_success(ns, q, lock)


from stolos.runner import build_arg_parser_and_parse_args, main
"""
Convert a directory into an executable
"""


def go():
    NS = build_arg_parser_and_parse_args()

# Path: stolos/runner.py
# def build_arg_parser_and_parse_args():
#     # """
#     # Get an argparse.Namespace from sys.argv,
#     # Lazily import the appropriate plugin module based on the given app name
#     # And recreate the namespace with arguments specific to that plugin module
#     # """
# 
#     parser = at.build_arg_parser([at.group(
#         "Runtime options",
#         at.app_name,
#         at.add_argument(
#             '--bypass_scheduler', action='store_true', help=(
#                 "Run a task directly. Do not schedule it."
#                 "  Do not obtain a lock on this job."
#                 "  Requires passing --job_id")),
#         at.add_argument(
#             '--timeout', type=int, default=2,
#             help='time to wait for task to appear in queue before dying'),
#         at.add_argument(
#             '--max_retry', type=int, default=5,
#             help='Maximum number of times to retry a failed task.'),
#         at.add_argument(
#             '--job_id', help=(
#                 'run a specific job_id. If a job is already queued,'
#                 ' it will run twice')),
#     )], description=(
#         "This script intelligently executes your application's jobs."
#         " Specifically, an instance of this script fetches exactly 1 job"
#         " from your application's queue, decides how to perform those jobs,"
#         " and then dies.  Because jobs are managed in a DAG, Stolos may choose"
#         " to delay execution of a job until dependencies have been met."
#         " It may also queue child or parent jobs depending on their status."),
#     )
#     parser, ns = initialize(
#         [parser(), dt, cb, qb],
#         parse_known_args=True)
# 
#     # get plugin parser
#     plugin = importlib.import_module(
#         'stolos.plugins.%s_plugin' % dt.get_job_type(ns.app_name))
#     ns = at.build_arg_parser(
#         parents=[parser, plugin.build_arg_parser()],
#         add_help=True
#     ).parse_args()
#     ns.job_type_func = plugin.main
#     return ns
# 
# def main(ns):
#     """
#     Fetch a job_id from the `app_name` queue and figure out what to with it.
# 
#     If the job is runnable, execute it and then queue its children into their
#     respective queues.  If it's not runnable, queue its parents into respective
#     parent queues and remove the job from its own queue.
#     If the job fails, either requeue it or mark it as permanently failed
#     """
#     assert ns.app_name in dt.get_task_names()
#     if ns.bypass_scheduler:
#         log.info(
#             "Running a task without scheduling anything"
#             " or fetching from a queue", extra=dict(
#                 app_name=ns.app_name, job_id=ns.job_id))
#         assert ns.job_id
#         ns.job_type_func(ns=ns)
#         return
# 
#     log.info("Beginning Stolos", extra=dict(**ns.__dict__))
#     q = qb.get_qbclient().LockingQueue(ns.app_name)
#     if ns.job_id:
#         lock = _handle_manually_given_job_id(ns)
#         q.consume = object  # do nothing
#     else:
#         ns.job_id = q.get(timeout=ns.timeout)
#         if not validate_job_id(app_name=ns.app_name, job_id=ns.job_id,
#                                q=q, timeout=ns.timeout):
#             return
#         try:
#             lock = get_lock_if_job_is_runnable(
#                 app_name=ns.app_name, job_id=ns.job_id)
#         except exceptions.NoNodeError:
#             q.consume()
#             log.exception(
#                 "Job failed. The job is queued, so why does its state not"
#                 " exist?  The Queue backend may be in an inconsistent state."
#                 " Consuming this job",
#                 extra=dict(app_name=ns.app_name, job_id=ns.job_id))
#             return
# 
#     log.debug(
#         "Stolos got a job_id.", extra=dict(
#             app_name=ns.app_name, job_id=ns.job_id, acquired_lock=bool(lock)))
#     if lock is False:
#         # infinite loop: some jobs will always requeue if lock is unobtainable
#         log.info("Could not obtain a lock.  Will requeue and try again later",
#                  extra=dict(app_name=ns.app_name, job_id=ns.job_id))
#         _send_to_back_of_queue(
#             q=q, app_name=ns.app_name, job_id=ns.job_id)
#         return
# 
#     if not parents_completed(ns.app_name, ns.job_id, q=q, lock=lock):
#         return
# 
#     log.info(
#         "Job starting!", extra=dict(app_name=ns.app_name, job_id=ns.job_id))
#     try:
#         ns.job_type_func(ns=ns)
#     except exceptions.CodeError:  # assume error is previously logged
#         _handle_failure(ns, q, lock)
#         return
#     except Exception as err:
#         log.exception(
#             ("Job failed!  Unhandled exception in an application!"
#              " Fix ASAP because"
#              " it is unclear how to handle this failure.  %s: %s")
#             % (err.__class__.__name__, err), extra=dict(
#                 app_name=ns.app_name, job_id=ns.job_id, failed=True))
#         return
#     _handle_success(ns, q, lock)


# Path: stolos/__main__.py
from stolos.runner import build_arg_parser_and_parse_args, main

"""
Convert a directory into an executable
"""


def go():
    NS = build_arg_parser_and_parse_args()

    main(NS)