Source code for dob.details

# This file exists within 'dob':
#
#   https://github.com/hotoffthehamster/dob
#
# Copyright © 2018-2020 Landon Bouma. All rights reserved.
#
# 'dob' 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 3  of the License,  or  (at your option)  any   later    version.
#
# 'dob' 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 can find the GNU General Public License reprinted in the file titled 'LICENSE',
# or visit <http://www.gnu.org/licenses/>.

import os

from gettext import gettext as _

from nark.items.fact import Fact

# Profiling: load AppDirs: ~ 0.011 secs.
from dob_bright.config.app_dirs import AppDirs
from dob_bright.termio import ascii_art, attr, click_echo, fg, highlight_value

from .clickux.plugin_group import ClickPluginGroup

from . import get_version, __package_name__

__all__ = (
    'echo_app_details',
    'echo_app_environs',
    'echo_data_stats',
    'hamster_time',
)


[docs]def echo_app_details(controller, full=False): """List details about the runtime environment.""" def _echo_app_details(): echo_name_version() echo_config_path() echo_plugins_basepath() echo_logfile_path() echo_db_info() echo_app_dirs() def echo_name_version(): click_echo(_( "You are running {appname} version {version}" ).format( appname=highlight_value(__package_name__), version=highlight_value(get_version()), )) def echo_config_path(): click_echo(_( "Configuration file at: {}" ).format( highlight_value(controller.configurable.config_path), )) def echo_plugins_basepath(): click_echo(_( "Plugins directory at: {}" ).format( # (lb): Such hack. highlight_value(ClickPluginGroup().plugins_basepath), )) def echo_logfile_path(): click_echo(_( "Logfile stored at: {}" ).format( highlight_value(controller.config['log.filepath']), )) def echo_db_info(): click_echo(get_db_info()) def get_db_info(): result = None # For now we do not need to check for various store option as we allow # only one anyway. result = get_sqlalchemy_info() return result def get_sqlalchemy_info(): """""" def _get_sqlalchemy_info(): engine = controller.config['db.engine'] if engine == 'sqlite': return sqlalchemy_string_sqlite() else: return sqlalchemy_string_remote(engine) def sqlalchemy_string_sqlite(): sqlalchemy_string = _( "Using {engine} on database: {db_path}" .format( engine=highlight_value('sqlite'), db_path=highlight_value(controller.config['db.path']), ) ) return sqlalchemy_string def sqlalchemy_string_remote(engine): port = controller.config['db.port'] if port: port = ':{}'.format(port) sqlalchemy_string = _( "Using {engine} on database {db_name} at:" " {username}@{host}{port}".format( engine=highlight_value(engine), db_name=highlight_value(controller.config['db.name']), username=highlight_value(controller.config['db.user']), host=highlight_value(controller.config['db.host']), port=highlight_value(port), ) ) return sqlalchemy_string return _get_sqlalchemy_info() def echo_app_dirs(): if not full: return appdir_paths = existent_app_dirs(include_errs=True, highlight=True) for prop in sorted(appdir_paths.keys()): path = appdir_paths[prop] click_echo('AppDirs.{}: {}'.format(prop, highlight_value(path))) _echo_app_details()
[docs]def echo_app_environs(controller): """List details about runtime in source'able name=value format.""" environs = {} def _echo_app_environs(): environs_add_all() environs_echo() def environs_add_all(): environs_add_appname_ver() environs_add_config_path() environs_add_plugins_path() environs_add_log_path() environs_add_db_url() environs_add_db_path() environs_add_user_app_dirs() def environs_echo(): for key in sorted(environs.keys()): val = environs[key] click_echo('DOB_{}="{}"'.format(key.upper(), val)) def environs_add_appname_ver(): environs['appname'] = __package_name__ environs['version'] = get_version() def environs_add_config_path(): environs['conf'] = controller.configurable.config_path def environs_add_plugins_path(): environs['plugins'] = ClickPluginGroup().plugins_basepath def environs_add_log_path(): # environs['log_filepath'] = controller.config['log.filepath'] environs['CONFIG_LOG_FILEPATH'] = controller.config['log.filepath'] def environs_add_db_url(): environs['db_url'] = controller.store.db_url def environs_add_db_path(): if controller.config['db.path']: # environs['db_path'] = controller.config['db.path'] environs['CONFIG_DB_PATH'] = controller.config['db.path'] def environs_add_user_app_dirs(): for prop, path in existent_app_dirs().items(): environs[prop] = path return _echo_app_environs()
def existent_app_dirs(include_errs=False, highlight=False): """""" def _existent_app_dirs(): was_create = appdirs_disable_create() prop_paths = build_prop_paths() appdirs_restore_create(was_create) return prop_paths def appdirs_disable_create(): # (lb): Our AppDirs defaults to trying to create directories. Tell it not to. # NOTE: I consider this side effect a bug. Paths should be lazy-created only # when a file stored therein is opened for writing. was_create = AppDirs.create AppDirs.create = False return was_create def appdirs_restore_create(was_create): AppDirs.create = was_create def build_prop_paths(): actual_prop_paths = {} # CONFIRM: (lb): On virtualenv install, no site_* dirs. # Will this not be the case for site-wide, non-virtenv installs? for prop in [ 'user_data_dir', 'site_data_dir', 'user_config_dir', 'site_config_dir', 'user_cache_dir', 'user_log_dir', ]: path = getattr(AppDirs, prop) path = check_exists(path) if path is not None: actual_prop_paths[prop] = path return actual_prop_paths def check_exists(path): if not os.path.exists(path): if include_errs: dne = _(' [dne]') if highlight: dne = _('{}{}{}').format(fg('red_3b'), dne, attr('reset')) path += dne else: path = None return path return _existent_app_dirs()
[docs]def echo_data_stats(controller): def _echo_data_stats(): echo_counts() echo_facts_interesting() def echo_counts(): # MAYBE: Add filtering, like activity, category, search_term, after, until, etc. num_activities = controller.activities.get_all(count_results=True) num_categories = controller.categories.get_all(count_results=True) num_facts = controller.facts.get_all(count_results=True) num_tags = controller.tags.get_all(count_results=True) # FIXME: Calculate length of Hamstering, i.e., delta first and last facts. # FIXME: Other stats? click_echo(_("No. of Facts: {}").format(highlight_value(num_facts))) click_echo(_("No. of Tag names: {}").format(highlight_value(num_tags))) click_echo(_("No. of Activities: {}").format(highlight_value(num_activities))) click_echo(_("No. of Categories: {}").format(highlight_value(num_categories))) def echo_facts_interesting(): first_facts = controller.facts.get_all( sort_cols=('start',), sort_orders=('asc',), limit=1, ) final_facts = controller.facts.get_all( sort_cols=('start',), sort_orders=('desc',), limit=1, ) assert len(first_facts) <= 1 assert len(final_facts) <= 1 if not first_facts: assert not final_facts return first_fact = first_facts.pop() final_fact = final_facts.pop() time_0 = first_fact.start time_n = final_fact.end or controller.now spanner = Fact(activity=None, start=time_0, end=time_n) elapsed = spanner.format_delta(style='') click_echo(_("Lifetime of Facts: {}").format(highlight_value(elapsed))) _echo_data_stats()
[docs]def hamster_time(posits=[]): if posits: arts = ascii_art.fetch_asciis(posits) else: arts = [ascii_art.randomster()] for one_art_please in arts: click_echo(one_art_please)