def __enter__(self):
        logger.debug('MicrophoneStream.enter ENTER')
        self.closed = False
        try:
            self._audio_stream = self._audio_interface.open(
                input_device_index=self._inputDeviceIndex,
                format=self._format,
                channels=self._num_channels,
                rate=self._rate,
                input=True,
                frames_per_buffer=self._chunk_size,
                # Run the audio stream asynchronously to fill the buffer object.
                # This is necessary so that the input device's buffer doesn't
                # overflow while the calling thread makes network requests, etc.
                stream_callback=self._fill_buff,
            )
        except OSError:
            logger.error("microphone __enter__.OSError")
            self.closed = True
            raise Exception("Microphone Not Functioning")

        self.initRecording()
        logger.debug('MicrophoneStream.enter EXIT')

        return self
示例#2
0
 def canceled(self, evt):
     logger.debug(
         'microsoftTranscribe.ProcessEvents.CANCELED: {}'.format(evt))
     logger.error(
         'microsoftTranscribe terminated. Ensure you have the correct API Key and service region.'
     )
     self.responseQueue.put('canceled')
示例#3
0
def check_folder_writable(folder, fallback, name):
    if not folder:
        folder = fallback

    if not os.path.exists(folder):
        try:
            os.makedirs(folder)
        except OSError as e:
            logger.error("Could not create %s dir '%s': %s" %
                         (name, folder, e))
            if folder != fallback:
                logger.warn("Falling back to %s dir '%s'" % (name, fallback))
                return check_folder_writable(None, fallback, name)
            else:
                return folder, None

    if not os.access(folder, os.W_OK):
        logger.error("Cannot write to %s dir '%s'" % (name, folder))
        if folder != fallback:
            logger.warn("Falling back to %s dir '%s'" % (name, fallback))
            return check_folder_writable(None, fallback, name)
        else:
            return folder, False

    return folder, True
示例#4
0
    def write(self):
        """ Make a copy of the stored config and write it to the configured file """
        new_config = ConfigObj(encoding="UTF-8")
        new_config.filename = self._config_file

        # first copy over everything from the old config, even if it is not
        # correctly defined to keep from losing data
        for key, subkeys in self._config.items():
            if key not in new_config:
                new_config[key] = {}
            for subkey, value in subkeys.items():
                new_config[key][subkey] = value

        # next make sure that everything we expect to have defined is so
        for key in _CONFIG_DEFINITIONS.keys():
            key, definition_type, section, ini_key, default = self._define(key)
            self.check_setting(key)
            if section not in new_config:
                new_config[section] = {}
            new_config[section][ini_key] = self._config[section][ini_key]

        # Write it to file
        logger.info("Config :: Writing configuration to file")

        try:
            new_config.write()
        except IOError as e:
            logger.error("Config :: Error writing configuration file: %s", e)
示例#5
0
 def setReleaseLock(self, release):
     # Set the previous release in the lock file
     try:
         with open(self.release_lock_file, "w") as fp:
             fp.write(release)
     except IOError as e:
         logger.error(u"Unable to write current version to file '%s': %s" %
                      (self.release_lock_file, e))
示例#6
0
 def setVersionLock(self, version_hash):
     # Set the previous version in the lock file
     try:
         with open(self.version_lock_file, "w") as fp:
             fp.write(version_hash)
     except IOError as e:
         logger.error(u"Unable to write current version to file '%s': %s" %
                      (self.version_lock_file, e))
    def run(self):
        if self._ONLINE:
            logger.warn("Transcribe Engine already Started")
            return

        logger.info(
            "Transcribe Engine Starting with the %s%s Speech-To-Text Service" %
            (speakreader.CONFIG.SPEECH_TO_TEXT_SERVICE[0].upper(),
             speakreader.CONFIG.SPEECH_TO_TEXT_SERVICE[1:]))

        FILENAME_DATESTRING = datetime.datetime.now().strftime(
            FILENAME_DATE_FORMAT)
        TRANSCRIPT_FILENAME = FILENAME_PREFIX + FILENAME_DATESTRING + "." + TRANSCRIPT_FILENAME_SUFFIX
        RECORDING_FILENAME = FILENAME_PREFIX + FILENAME_DATESTRING + "." + RECORDING_FILENAME_SUFFIX
        tf = os.path.join(speakreader.CONFIG.TRANSCRIPTS_FOLDER,
                          TRANSCRIPT_FILENAME)
        self.queueManager.transcriptHandler.setFileName(tf)

        try:
            self.microphoneStream = MicrophoneStream(
                speakreader.CONFIG.INPUT_DEVICE)
            self.microphoneStream.recordingFilename = RECORDING_FILENAME
            self.microphoneStream.meterQueue = self.queueManager.meterHandler.getReceiverQueue(
            )
        except Exception as e:
            logger.debug("MicrophoneStream Exception: %s" % e)
            self.transcriptQueue.put_nowait(self.OFFLINE_MESSAGE)
            return

        if speakreader.CONFIG.SPEECH_TO_TEXT_SERVICE == 'google' and self.GOOGLE_SERVICE:
            transcribeService = googleTranscribe(self.microphoneStream)
        elif speakreader.CONFIG.SPEECH_TO_TEXT_SERVICE == 'IBM' and self.IBM_SERVICE:
            transcribeService = ibmTranscribe(self.microphoneStream)
        elif speakreader.CONFIG.SPEECH_TO_TEXT_SERVICE == 'microsoft' and self.MICROSOFT_SERVICE:
            transcribeService = microsoftTranscribe(self.microphoneStream)
        else:
            logger.warn(
                "No Supported Transcribe Service Selected. Can't start Transcribe Engine."
            )
            return

        self.transcriptFile = open(tf, "a+")
        self.transcriptQueue.put_nowait(self.ONLINE_MESSAGE)
        self._ONLINE = True

        try:
            with self.microphoneStream as stream:
                while self._ONLINE:
                    responses = transcribeService.transcribe()
                    self.process_responses(responses)
                logger.info("Transcription Engine Stream Closed")
        except Exception as e:
            logger.error(e)

        self.transcriptFile.close()
        self.transcriptQueue.put_nowait(self.OFFLINE_MESSAGE)
        self._ONLINE = False
        logger.info("Transcribe Engine Terminated")
示例#8
0
    def checkout_git_branch(self, git_remote=None, git_branch=None, **kwargs):
        if git_branch == speakreader.CONFIG.GIT_BRANCH:
            logger.error(u"Already on the %s branch" % git_branch)
            raise cherrypy.HTTPRedirect(speakreader.CONFIG.HTTP_ROOT +
                                        "manage")

        # Set the new git remote and branch
        speakreader.CONFIG.__setattr__('GIT_REMOTE', git_remote)
        speakreader.CONFIG.__setattr__('GIT_BRANCH', git_branch)
        speakreader.CONFIG.write()
        return self.do_state_change('checkout', 'Switching Git Branches', 120)
示例#9
0
    def pip_update(self):
        logger.info("Running pip_update to update the installation tools.")
        try:
            cmd = sys.executable + ' -m pip install --upgrade pip setuptools wheel pip-tools'
            output = self._exec_command(cmd)
            for line in output:
                logger.info('pip_update output: %s' % line)
            return True

        except Exception as e:
            logger.error('Command failed: %s' % e)
            return False
示例#10
0
    def pip_sync(self):
        logger.info("Running pip-sync to synchronize the environment.")
        try:
            cmd = sys.executable + ' -m piptools sync requirements.txt'
            output = self._exec_command(cmd)
            for line in output:
                logger.info('pip-sync output: %s' % line)
            return True

        except Exception as e:
            logger.error('Command failed: %s' % e)
            return False
示例#11
0
 def getVersionLock(self):
     # Get the previous version from the file
     version_hash = "unknown"
     if os.path.isfile(self.version_lock_file):
         try:
             with open(self.version_lock_file, "r") as fp:
                 version_hash = fp.read()
         except IOError as e:
             logger.error(
                 "Unable to read previous version from file '%s': %s" %
                 (self.version_lock_file, e))
     return version_hash
示例#12
0
 def getReleaseLock(self):
     # Get the previous release from the lock file
     release = False
     if os.path.isfile(self.release_lock_file):
         try:
             with open(self.release_lock_file, "r") as fp:
                 release = fp.read()
         except IOError as e:
             logger.error(
                 "Unable to read previous release from file '%s': %s" %
                 (self.release_lock_file, e))
     return release
示例#13
0
def launch_browser(host, port, root):
    if not no_browser:
        if host == '0.0.0.0':
            host = 'localhost'

        if CONFIG.ENABLE_HTTPS:
            protocol = 'https'
        else:
            protocol = 'http'

        try:
            webbrowser.open('%s://%s:%i%s' % (protocol, host, port, root))
        except Exception as e:
            logger.error("Could not launch browser: %s" % e)
示例#14
0
    def runGit(self, args):
        if speakreader.CONFIG.GIT_PATH:
            git_locations = ['"' + speakreader.CONFIG.GIT_PATH + '"']
        else:
            git_locations = ['git']

        output = err = None

        for cur_git in git_locations:
            cmd = cur_git + ' ' + args

            try:
                logger.debug('Trying to execute: "' + cmd +
                             '" with shell in ' + speakreader.PROG_DIR)
                p = subprocess.Popen(cmd,
                                     stdout=subprocess.PIPE,
                                     stderr=subprocess.STDOUT,
                                     shell=True,
                                     cwd=speakreader.PROG_DIR)
                output, err = p.communicate()
                output = output.decode('utf-8').strip()

                for line in output.split('\n'):
                    if line:
                        logger.debug('Git output: ' + line)

            except OSError:
                logger.debug('Command failed: %s', cmd)
                continue

            if 'not found' in output or "not recognized as an internal or external command" in output:
                logger.debug('Unable to find git with command ' + cmd)
                output = None
            elif 'fatal:' in output or err:
                logger.error(
                    'Git returned bad info. Are you sure this is a git installation?'
                )
                output = None
            elif output:
                break

        return (output, err)
示例#15
0
    def checkout_git_branch(self):
        if self.INSTALL_TYPE == 'git':
            output, err = self.runGit('fetch %s' %
                                      speakreader.CONFIG.GIT_REMOTE)
            output, err = self.runGit('checkout %s' %
                                      speakreader.CONFIG.GIT_BRANCH)

            if not output:
                logger.error('Unable to change git branch.')
                return

            for line in output.split('\n'):
                if line.endswith(('Aborting', 'Aborting.')):
                    logger.error('Unable to checkout from git: ' + line)
                    logger.info('Output: ' + str(output))

            output, err = self.runGit(
                'pull %s %s' %
                (speakreader.CONFIG.GIT_REMOTE, speakreader.CONFIG.GIT_BRANCH))
            self.pip_update()
            self.pip_sync()
示例#16
0
    def update(self):
        if speakreader.CONFIG.SERVER_ENVIRONMENT.lower() != 'production':
            logger.info(
                "Updating bypassed because this is not a production environment"
            )
            return False

        if not self.UPDATE_AVAILABLE:
            logger.info("No Updates Available")
            return False

        if self.INSTALL_TYPE == 'git':

            output, err = self.runGit(
                'diff --name-only %s/%s' %
                (speakreader.CONFIG.GIT_REMOTE, speakreader.CONFIG.GIT_BRANCH))

            if output == '':
                logger.debug("No differences found from the origin")

            elif output == 'requirements.txt':
                logger.warn(
                    'Requirements file is out of sync. Restoring to original.')
                output, err = self.runGit('checkout %s/%s requirements.txt' %
                                          (speakreader.CONFIG.GIT_REMOTE,
                                           speakreader.CONFIG.GIT_BRANCH))
            else:
                logger.error("Differences Found. Unable to update.")
                logger.info('Output: ' + str(output))
                return False

            output, err = self.runGit('pull ' + speakreader.CONFIG.GIT_REMOTE +
                                      ' ' + speakreader.CONFIG.GIT_BRANCH)

            if not output:
                logger.error('Unable to download latest version')
                return False

            for line in output.split('\n'):
                if 'Already up-to-date.' in line:
                    logger.info('No update available, not updating')
                    logger.info('Output: ' + str(output))
                    return False
                elif line.endswith(('Aborting', 'Aborting.')):
                    logger.error('Unable to update from git: ' + line)
                    logger.info('Output: ' + str(output))
                    return False

        else:
            tar_download_url = 'https://api.github.com/repos/{}/{}/tarball/{}'.format(
                speakreader.CONFIG.GIT_USER, speakreader.CONFIG.GIT_REPO,
                speakreader.CONFIG.GIT_BRANCH)
            if speakreader.CONFIG.GIT_TOKEN:
                tar_download_url = tar_download_url + '?access_token=%s' % speakreader.CONFIG.GIT_TOKEN
            update_dir = os.path.join(speakreader.PROG_DIR, 'update')
            version_path = os.path.join(speakreader.PROG_DIR, 'version.txt')

            logger.info('Downloading update from: ' + tar_download_url)
            try:
                data = requests.get(tar_download_url, timeout=10)
            except Exception as e:
                logger.warn('Failed to establish a connection to GitHub')
                return False

            if not data:
                logger.error(
                    "Unable to retrieve new version from '%s', can't update",
                    tar_download_url)
                return False

            download_name = speakreader.CONFIG.GIT_BRANCH + '-github'
            tar_download_path = os.path.join(speakreader.PROG_DIR,
                                             download_name)

            # Save tar to disk
            with open(tar_download_path, 'wb') as f:
                f.write(data.content)

            # Extract the tar to update folder
            logger.info('Extracting file: ' + tar_download_path)
            tar = tarfile.open(tar_download_path)
            tar.extractall(update_dir)
            tar.close()

            # Delete the tar.gz
            logger.info('Deleting file: ' + tar_download_path)
            os.remove(tar_download_path)

            # Find update dir name
            update_dir_contents = [
                x for x in os.listdir(update_dir)
                if os.path.isdir(os.path.join(update_dir, x))
            ]
            if len(update_dir_contents) != 1:
                logger.error("Invalid update data, update failed: " +
                             str(update_dir_contents))
                return False
            content_dir = os.path.join(update_dir, update_dir_contents[0])

            # walk temp folder and move files to main folder
            for dirname, dirnames, filenames in os.walk(content_dir):
                dirname = dirname[len(content_dir) + 1:]
                for curfile in filenames:
                    old_path = os.path.join(content_dir, dirname, curfile)
                    new_path = os.path.join(speakreader.PROG_DIR, dirname,
                                            curfile)

                    if os.path.isfile(new_path):
                        os.remove(new_path)
                    os.renames(old_path, new_path)

            # Update version.txt
            try:
                with open(version_path, 'w') as f:
                    f.write(str(self.LATEST_VERSION_HASH))
            except IOError as e:
                logger.error(
                    "Unable to write current version to version.txt, update not complete: %s"
                    % e)
                return False

        self.pip_update()
        self.pip_sync()
        logger.info("Update Complete")
        return True
示例#17
0
def main():
    """
    SpeakReader application entry point. Parses arguments, setups encoding and
    initializes the application.
    """

    DAEMON = False
    NOFORK = False

    QUIET = False
    VERBOSE = False
    NOLAUNCH = False
    HTTP_PORT = None

    PLATFORM = system()
    PLATFORM_RELEASE = release()
    PLATFORM_VERSION = version()
    PLATFORM_LINUX_DISTRO = None

    PLATFORM_PROCESSOR = processor()
    PLATFORM_MACHINE = machine()
    PLATFORM_IS_64BITS = sys.maxsize > 2**32
    SYS_PLATFORM = sys.platform

    # Fixed paths to application
    if hasattr(sys, 'frozen'):
        FULL_PATH = os.path.abspath(sys.executable)
    else:
        FULL_PATH = os.path.abspath(__file__)

    PROG_DIR = os.path.dirname(FULL_PATH)

    # Ensure only one instance of SpeakReader running.
    PIDFILE = os.path.join(PROG_DIR, 'pidfile')
    myPid = os.getpid()
    if os.path.exists(PIDFILE) and os.path.isfile(PIDFILE):
        for p in psutil.process_iter():
            if 'python' in p.name() and p.pid != myPid:
                for f in p.open_files():
                    if f.path == PIDFILE:
                        logger.error(
                            "SpeakReader is already Running. Exiting.")
                        sys.exit(0)

    myPidFile = open(PIDFILE, 'w+')
    myPidFile.write(str(myPid))
    myPidFile.flush()

    try:
        locale.setlocale(locale.LC_ALL, "")
    except (locale.Error, IOError):
        pass

    try:
        SYS_TIMEZONE = str(tzlocal.get_localzone())
        SYS_UTC_OFFSET = datetime.datetime.now(
            pytz.timezone(SYS_TIMEZONE)).strftime('%z')
    except (pytz.UnknownTimeZoneError, LookupError, ValueError) as e:
        logger.error("Could not determine system timezone: %s" % e)
        SYS_TIMEZONE = 'Unknown'
        SYS_UTC_OFFSET = '+0000'

    # Parse any passed startup arguments
    ARGS = sys.argv[1:]
    # Set up and gather command line arguments
    parser = argparse.ArgumentParser(
        description=
        'A Python based monitoring and tracking tool for Plex Media Server.')

    parser.add_argument('-v',
                        '--verbose',
                        action='store_true',
                        help='Increase console logging verbosity')
    parser.add_argument('-q',
                        '--quiet',
                        action='store_true',
                        help='Turn off console logging')
    parser.add_argument('-d',
                        '--daemon',
                        action='store_true',
                        help='Run as a daemon')
    parser.add_argument('-p',
                        '--port',
                        type=int,
                        help='Force SpeakReader to run on a specified port')
    parser.add_argument(
        '--datadir', help='Specify a directory where to store your data files')
    parser.add_argument('--config', help='Specify a config file to use')
    parser.add_argument('--nolaunch',
                        action='store_true',
                        help='Prevent browser from launching on startup')
    parser.add_argument(
        '--nofork',
        action='store_true',
        help='Start SpeakReader as a service, do not fork when restarting')

    args = parser.parse_args()

    # Force the http port if necessary
    if args.port:
        HTTP_PORT = args.port
        logger.info('Using forced web server port: %i', HTTP_PORT)

    # Don't launch the browser
    if args.nolaunch:
        NOLAUNCH = True

    if args.verbose:
        VERBOSE = True
    if args.quiet:
        QUIET = True

    if args.daemon:
        if SYS_PLATFORM == 'win32':
            sys.stderr.write(
                "Daemonizing not supported under Windows, starting normally\n")
        else:
            DAEMON = True
            QUIET = True

    if args.nofork:
        NOFORK = True
        logger.info(
            "SpeakReader is running as a service, it will not fork when restarted."
        )

    # Determine which data directory and config file to use
    if args.datadir:
        DATA_DIR = args.datadir
    else:
        DATA_DIR = os.path.join(PROG_DIR, 'data')

    if args.config:
        CONFIG_FILE = args.config
    else:
        CONFIG_FILE = os.path.join(DATA_DIR, config.FILENAME)

    # Try to create the DATA_DIR if it doesn't exist
    if not os.path.exists(DATA_DIR):
        try:
            os.makedirs(DATA_DIR)
        except OSError:
            raise SystemExit('Could not create data directory: ' + DATA_DIR +
                             '. Exiting....')

    # Make sure the DATA_DIR is writeable
    if not os.access(DATA_DIR, os.W_OK):
        raise SystemExit('Cannot write to the data directory: ' + DATA_DIR +
                         '. Exiting...')

    # Do an initial setup of the logging.
    logger.initLogger(console=not QUIET, log_dir=False, verbose=VERBOSE)

    # Initialize the configuration from the config file
    CONFIG = config.Config(CONFIG_FILE)
    assert CONFIG is not None

    if CONFIG.SERVER_ENVIRONMENT.lower() != 'production':
        VERBOSE = True

    CONFIG.LOG_DIR, log_writable = check_folder_writable(
        CONFIG.LOG_DIR, os.path.join(DATA_DIR, 'logs'), 'logs')
    if not log_writable and not QUIET:
        sys.stderr.write(
            "Unable to create the log directory. Logging to screen only.\n")

    # Start the logger, disable console if needed
    logger.initLogger(console=not QUIET,
                      log_dir=CONFIG.LOG_DIR if log_writable else None,
                      verbose=VERBOSE)

    logger.info("Initializing {} {}".format(speakreader.PRODUCT,
                                            speakreader.VERSION_RELEASE))
    logger.info("{} {} ({}{})".format(
        PLATFORM, PLATFORM_RELEASE, PLATFORM_VERSION,
        ' - {}'.format(PLATFORM_LINUX_DISTRO)
        if PLATFORM_LINUX_DISTRO else ''))
    logger.info("{} ({} {})".format(
        PLATFORM_PROCESSOR, PLATFORM_MACHINE,
        '{}'.format('64-BIT') if PLATFORM_IS_64BITS else '32-BIT'))
    logger.info("Python {}".format(sys.version))
    logger.info("{} (UTC{})".format(SYS_TIMEZONE, SYS_UTC_OFFSET))
    logger.info("Program Dir: {}".format(PROG_DIR))
    logger.info("Config File: {}".format(CONFIG_FILE))

    CONFIG.TRANSCRIPTS_FOLDER, _ = check_folder_writable(
        CONFIG.TRANSCRIPTS_FOLDER, os.path.join(DATA_DIR, 'transcripts'),
        'transcripts')

    CONFIG.RECORDINGS_FOLDER, _ = check_folder_writable(
        CONFIG.RECORDINGS_FOLDER, os.path.join(DATA_DIR, 'recordings'),
        'recordings')

    if DAEMON:
        daemonize(myPidFile)

    # Store the original umask
    UMASK = os.umask(0)
    os.umask(UMASK)

    initOptions = {
        'config': CONFIG,
        'http_port': HTTP_PORT,
        'nolaunch': NOLAUNCH,
        'prog_dir': PROG_DIR,
        'data_dir': DATA_DIR,
    }

    # Read config and start logging
    global SR
    SR = SpeakReader(initOptions)

    # Wait endlessly for a signal to happen
    restart = False
    checkout = False
    update = False
    while True:
        if not SR.SIGNAL:
            try:
                time.sleep(1)
            except KeyboardInterrupt:
                SR.SIGNAL = 'shutdown'
        else:
            logger.info('Received signal: %s', SR.SIGNAL)

            if SR.SIGNAL == 'shutdown':
                break
            elif SR.SIGNAL == 'restart':
                restart = True
                break
            elif SR.SIGNAL == 'update':
                restart = True
                update = True
                break
            elif SR.SIGNAL == 'checkout':
                restart = True
                checkout = True
                break
            else:
                SR.SIGNAL = None

    SR.shutdown(restart=restart, update=update, checkout=checkout)

    myPidFile.close()
    os.remove(PIDFILE)

    if restart:
        logger.info("SpeakReader is restarting...")

        exe = sys.executable
        args = [exe, FULL_PATH]
        args += ARGS
        if '--nolaunch' not in args:
            args += ['--nolaunch']

        # Separate out logger so we can shutdown logger after
        if NOFORK:
            logger.info('Running as service, not forking. Exiting...')
        elif os.name == 'nt':
            logger.info('Restarting SpeakReader with %s', args)
        else:
            logger.info('Restarting SpeakReader with %s', args)

        logger.shutdown()

        if NOFORK:
            pass
        elif os.name == 'nt':
            subprocess.Popen(args, cwd=os.getcwd())
        else:
            os.execv(exe, args)

    else:
        logger.info("SpeakReader Terminated")
        logger.shutdown()

    sys.exit(0)
示例#18
0
    def __init__(self):

        self.INSTALL_TYPE = None
        self.INSTALLED_VERSION_HASH = None
        self.INSTALLED_RELEASE = speakreader.VERSION_RELEASE
        self.LATEST_VERSION_HASH = None
        self.LATEST_RELEASE = "Unknown"
        self.LATEST_RELEASE_URL = ""
        self.COMMITS_BEHIND = 0
        self.UPDATE_AVAILABLE = False
        self.REMOTE_NAME = None
        self.BRANCH_NAME = None
        self.version_lock_file = os.path.join(speakreader.PROG_DIR,
                                              "version.lock")
        self.release_lock_file = os.path.join(speakreader.PROG_DIR,
                                              "release.lock")

        installed_release = self.getReleaseLock()
        if self.INSTALLED_RELEASE != installed_release:
            self.setReleaseLock(self.INSTALLED_RELEASE)

        if os.path.isdir(os.path.join(speakreader.PROG_DIR, '.git')):
            self.INSTALL_TYPE = 'git'

            output, err = self.runGit('rev-parse HEAD')
            if output:
                if re.match('^[a-z0-9]+$', output):
                    self.INSTALLED_VERSION_HASH = output
                    installed_version_hash = self.getVersionLock()
                    if self.INSTALLED_VERSION_HASH != installed_version_hash:
                        self.setVersionLock(self.INSTALLED_VERSION_HASH)
                else:
                    logger.error(
                        'Output does not look like a hash, not using it.')
            else:
                logger.error('Could not find latest installed version.')

            if speakreader.CONFIG.DO_NOT_OVERRIDE_GIT_BRANCH and speakreader.CONFIG.GIT_BRANCH:
                self.BRANCH_NAME = speakreader.CONFIG.GIT_BRANCH
            else:
                remote_branch, err = self.runGit(
                    'rev-parse --abbrev-ref --symbolic-full-name @{u}')
                remote_branch = remote_branch.rsplit(
                    '/', 1) if remote_branch else []
                if len(remote_branch) == 2:
                    self.REMOTE_NAME, self.BRANCH_NAME = remote_branch

                if not self.REMOTE_NAME and speakreader.CONFIG.GIT_REMOTE:
                    logger.error(
                        'Could not retrieve remote name from git. Falling back to %s.'
                        % speakreader.CONFIG.GIT_REMOTE)
                    self.REMOTE_NAME = speakreader.CONFIG.GIT_REMOTE

                if not self.REMOTE_NAME:
                    logger.error(
                        'Could not retrieve remote name from git. Defaulting to origin.'
                    )
                    self.REMOTE_NAME = 'origin'

                if not self.BRANCH_NAME and speakreader.CONFIG.GIT_BRANCH:
                    logger.error(
                        'Could not retrieve branch name from git. Falling back to %s.'
                        % speakreader.CONFIG.GIT_BRANCH)
                    self.BRANCH_NAME = speakreader.CONFIG.GIT_BRANCH

                if not self.BRANCH_NAME:
                    logger.error(
                        'Could not retrieve branch name from git. Defaulting to master.'
                    )
                    self.BRANCH_NAME = 'master'

                speakreader.CONFIG.GIT_REMOTE = self.REMOTE_NAME
                speakreader.CONFIG.GIT_BRANCH = self.BRANCH_NAME

        else:
            self.INSTALL_TYPE = 'source'
            self.REMOTE_NAME = 'origin'
            self.BRANCH_NAME = speakreader.GITHUB_BRANCH
            self.INSTALLED_VERSION_HASH = self.getVersionLock()

        if speakreader.CONFIG.CHECK_GITHUB:
            self.checkForUpdate()
示例#19
0
    def read_changelog(self, latest_only=False, since_prev_release=False):
        changelog_file = os.path.join(speakreader.PROG_DIR, 'CHANGELOG.md')

        if not os.path.isfile(changelog_file):
            return '<h4>Missing changelog file</h4>'

        try:
            output = ['']
            prev_level = 0

            latest_version_found = False

            header_pattern = re.compile(r'(^#+)\s(.+)')
            list_pattern = re.compile(r'(^[ \t]*\*\s)(.+)')

            with open(changelog_file, "r") as logfile:
                for line in logfile:
                    line_header_match = re.search(header_pattern, line)
                    line_list_match = re.search(list_pattern, line)

                    if line_header_match:
                        header_level = str(len(line_header_match.group(1)))
                        header_text = line_header_match.group(2)

                        if header_text.lower() == 'changelog':
                            continue

                        if latest_version_found:
                            break
                        elif latest_only:
                            latest_version_found = True
                        # Add a space to the end of the release to match tags
                        elif since_prev_release and str(
                                self.INSTALLED_RELEASE) + ' ' in header_text:
                            break

                        output[
                            -1] += '<h' + header_level + '>' + header_text + '</h' + header_level + '>'

                    elif line_list_match:
                        line_level = len(line_list_match.group(1)) / 2
                        line_text = line_list_match.group(2)

                        if line_level > prev_level:
                            output[-1] += '<ul>' * int(
                                line_level -
                                prev_level) + '<li>' + line_text + '</li>'
                        elif line_level < prev_level:
                            output[-1] += '</ul>' * int(
                                prev_level -
                                line_level) + '<li>' + line_text + '</li>'
                        else:
                            output[-1] += '<li>' + line_text + '</li>'

                        prev_level = line_level

                    elif line.strip() == '' and prev_level:
                        output[-1] += '</ul>' * int(prev_level)
                        output.append('')
                        prev_level = 0

            if since_prev_release:
                output.reverse()

            return ''.join(output)

        except IOError as e:
            logger.error('Unable to open changelog file. %s' % e)
            return '<h4>Unable to open changelog file</h4>'