<commit_before>import json
import socket
import threading
from time import sleep
from datetime import date, datetime, timedelta, time
import arrow

import dateutil.tz
import pytz
from pytz import timezone
from apscheduler.scheduler import Scheduler
from sqlalchemy.exc import DatabaseError

from rootio.config import DefaultConfig
from rootio.content import ContentMusicArtist, ContentMusicAlbum, ContentMusic
from rootio.radio.models import ScheduledProgram
from sqlalchemy import text

from radio_program import RadioProgram


class ProgramHandler:

    def __init__(self, radio_station):
        self.__radio_station = radio_station
        self.__scheduler = None
        self.__scheduled_jobs = None
        self.__start_listeners()
        self.__is_starting_up = True
        self.__running_program = None
        self.__interval_hours = 3  # Time after which to schedule again
        self.__radio_station.logger.info("Done initialising ProgramHandler for {0}".format(radio_station.station.name))

    def run(self):
        self.run_current_schedule()
        self.__is_starting_up = False

    def __prepare_schedule(self):
        self.__load_programs()
        self.__scheduler = Scheduler(timezone=pytz.utc)
        self.__scheduled_jobs = dict()

    def run_current_schedule(self):
        self.__prepare_schedule()
        self.__scheduler.start()
        self.__schedule_programs()
        #self.__schedule_next_schedule()

    def set_running_program(self, running_program):
        self.__stop_program()
        self.__running_program = running_program

    def stop(self):
        self.__stop_program()
        # any clean up goes here
        # unschedule stuff

    def __schedule_next_schedule(self):
        base_date = datetime.now()
        next_schedule_date = base_date + timedelta(0, 0, 0, 0, 0, self.__interval_hours)  # 3 hours
        self.__scheduler.add_date_job(getattr(self, 'run_current_schedule'), next_schedule_date)

    def __schedule_programs(self):
        for scheduled_program in self.__scheduled_programs:
            if not self.__is_program_expired(scheduled_program):
                self.__add_scheduled_job(scheduled_program)
                self.__radio_station.logger.info(
                    "Scheduled program {0} for station {1} starting at {2}".format(scheduled_program.program.name,
                                                                                   self.__radio_station.station.name,
                                                                                   scheduled_program.start))

    def __add_scheduled_job(self, scheduled_program):
        start_time = self.__get_program_start_time(scheduled_program).replace(tzinfo=None)
        program = RadioProgram(scheduled_program, self.__radio_station, self)
        try:
            scheduled_job = self.__scheduler.add_date_job(getattr(program, 'start'),  start_time)
            self.__scheduled_jobs[scheduled_program.id] = scheduled_job
        except Exception as e:
            self.__radio_station.logger.error("Error {err} in __add_scheduled_job".format(err=e.message))

    def __delete_scheduled_job(self, index):
        if not self.__scheduled_jobs:
            self.__radio_station.logger.warning("Failed to delete job (no jobs are scheduled)")
            return

        if index in self.__scheduled_jobs:
            try:
                self.__scheduler.unschedule_job(self.__scheduled_jobs[index])
            except:
                # The job probably ran already
                self.__radio_station.logger.warning("Failed to remove unscheduled job #{}".format(index))
            del self.__scheduled_jobs[index]

        # Stop the program if it is running
        if self.__running_program is not None and self.__running_program.id == index:
            self.__running_program.stop()

    def __stop_program(self):
        try:
            if self.__running_program is not None:
                self.__running_program.stop()
                sleep(2)
        except:
            return

    def __run_program(self):
        # self.__running_program.run()
        return

    def __load_programs(self):
        timezone = self.__radio_station.station.timezone
        #if self.__is_starting_up:
        date_filter = "((date(start) = date(now())) or (start < now() and radio_scheduledprogram.end > now()))"
        #else:
        #   date_filter = "(start >= now() at time zone '{tz}' and start < now() at time zone '{tz}' + interval '{interval} hour')".format(
        #        tz=timezone, interval=self.__interval_hours)
        query = self.__radio_station.db.query(ScheduledProgram).filter(
            ScheduledProgram.station_id == self.__radio_station.station.id).filter(text(date_filter)).filter(
            ScheduledProgram.deleted == False)
        self.__scheduled_programs = query.all()
        self.__radio_station.logger.info("Loaded {1} programs for {0}".format(self.__radio_station.station.name, len(self.__scheduled_programs)))

    def __load_program(self, program_id):
        self.__radio_station.db.commit()
        return self.__radio_station.db.query(ScheduledProgram).filter(ScheduledProgram.id == program_id).first()

    def __start_listeners(self):
        t = threading.Thread(target=self.__listen_for_scheduling_changes,<commit_msg>Pre-committing shared session object to make it available for reuse, pending re-write<commit_after>import json
import socket
import threading
from time import sleep
from datetime import date, datetime, timedelta, time
import arrow

import dateutil.tz
import pytz
from pytz import timezone
from apscheduler.scheduler import Scheduler
from sqlalchemy.exc import DatabaseError

from rootio.config import DefaultConfig
from rootio.content import ContentMusicArtist, ContentMusicAlbum, ContentMusic
from rootio.radio.models import ScheduledProgram
from sqlalchemy import text

from radio_program import RadioProgram


class ProgramHandler:

    def __init__(self, radio_station):
        self.__radio_station = radio_station
        self.__scheduler = None
        self.__scheduled_jobs = None
        self.__start_listeners()
        self.__is_starting_up = True
        self.__running_program = None
        self.__interval_hours = 3  # Time after which to schedule again
        self.__radio_station.logger.info("Done initialising ProgramHandler for {0}".format(radio_station.station.name))

    def run(self):
        self.run_current_schedule()
        self.__is_starting_up = False

    def __prepare_schedule(self):
        self.__load_programs()
        self.__scheduler = Scheduler(timezone=pytz.utc)
        self.__scheduled_jobs = dict()

    def run_current_schedule(self):
        self.__prepare_schedule()
        self.__scheduler.start()
        self.__schedule_programs()
        #self.__schedule_next_schedule()

    def set_running_program(self, running_program):
        self.__stop_program()
        self.__running_program = running_program

    def stop(self):
        self.__stop_program()
        # any clean up goes here
        # unschedule stuff

    def __schedule_next_schedule(self):
        base_date = datetime.now()
        next_schedule_date = base_date + timedelta(0, 0, 0, 0, 0, self.__interval_hours)  # 3 hours
        self.__scheduler.add_date_job(getattr(self, 'run_current_schedule'), next_schedule_date)

    def __schedule_programs(self):
        for scheduled_program in self.__scheduled_programs:
            if not self.__is_program_expired(scheduled_program):
                self.__add_scheduled_job(scheduled_program)
                self.__radio_station.logger.info(
                    "Scheduled program {0} for station {1} starting at {2}".format(scheduled_program.program.name,
                                                                                   self.__radio_station.station.name,
                                                                                   scheduled_program.start))

    def __add_scheduled_job(self, scheduled_program):
        start_time = self.__get_program_start_time(scheduled_program).replace(tzinfo=None)
        program = RadioProgram(scheduled_program, self.__radio_station, self)
        try:
            scheduled_job = self.__scheduler.add_date_job(getattr(program, 'start'),  start_time)
            self.__scheduled_jobs[scheduled_program.id] = scheduled_job
        except Exception as e:
            self.__radio_station.logger.error("Error {err} in __add_scheduled_job".format(err=e.message))

    def __delete_scheduled_job(self, index):
        if not self.__scheduled_jobs:
            self.__radio_station.logger.warning("Failed to delete job (no jobs are scheduled)")
            return

        if index in self.__scheduled_jobs:
            try:
                self.__scheduler.unschedule_job(self.__scheduled_jobs[index])
            except:
                # The job probably ran already
                self.__radio_station.logger.warning("Failed to remove unscheduled job #{}".format(index))
            del self.__scheduled_jobs[index]

        # Stop the program if it is running
        if self.__running_program is not None and self.__running_program.id == index:
            self.__running_program.stop()

    def __stop_program(self):
        try:
            if self.__running_program is not None:
                self.__running_program.stop()
                sleep(2)
        except:
            return

    def __run_program(self):
        # self.__running_program.run()
        return

    def __load_programs(self):
        timezone = self.__radio_station.station.timezone
        #if self.__is_starting_up:
        date_filter = "((date(start) = date(now())) or (start < now() and radio_scheduledprogram.end > now()))"
        #else:
        #   date_filter = "(start >= now() at time zone '{tz}' and start < now() at time zone '{tz}' + interval '{interval} hour')".format(
        #        tz=timezone, interval=self.__interval_hours)
        query = self.__radio_station.db.query(ScheduledProgram).filter(
            ScheduledProgram.station_id == self.__radio_station.station.id).filter(text(date_filter)).filter(
            ScheduledProgram.deleted == False)
        self.__scheduled_programs = query.all()
        self.__radio_station.logger.info("Loaded {1} programs for {0}".format(self.__radio_station.station.name, len(self.__scheduled_programs)))

    def __load_program(self, program_id):
        self.__radio_station.db._model_changes = {}
        self.__radio_station.db.commit()
        return self.__radio_station.db.query(ScheduledProgram).filter(ScheduledProgram.id == program_id).first()

    def __start_listeners(self):
        t = threading.Thread(target=self.__listen_for_scheduling_changes,
{'fraction_non_alphanumeric': 0.08446385430217432, 'fraction_numerical': 0.0026017468871956887, 'mean_word_length': 2.7113793103448276, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 12, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3802483', 'n_tokens_mistral': 2960, 'n_tokens_neox': 2864, 'n_words': 631}