コード例 #1
0
 def setUp(self):
     self.settings = Settings()
     self.real_isdir = os.path.isdir
     self.tempdir = None
     self.old_home = os.environ.get('HOME')
     self.old_gtimelog_home = os.environ.get('GTIMELOG_HOME')
     self.old_xdg_config_home = os.environ.get('XDG_CONFIG_HOME')
     self.old_xdg_data_home = os.environ.get('XDG_DATA_HOME')
     os.environ['HOME'] = os.path.normpath('/tmp/home')
     os.environ.pop('GTIMELOG_HOME', None)
     os.environ.pop('XDG_CONFIG_HOME', None)
     os.environ.pop('XDG_DATA_HOME', None)
コード例 #2
0
 def __init__(self, config):
     self.settings = Settings()
     self.timelog = TimeLog(self.settings.get_timelog_file(),
                            self.settings.virtual_midnight)
     self.aliases = config.get('aliases', {})
     self.line_format = config.get('line_format', '')
     if self.line_format == 'categorized':
         self.line_format_str = "category: task description | comment"
         self.delimiter = " "
     else:
         self.line_format_str = "task: description | comment"
         self.delimiter = ":"
コード例 #3
0
ファイル: main.py プロジェクト: ollyfg/gtimelog
 def do_handle_local_options(self, options):
     if options.contains('version'):
         print(gtimelog.__version__)
         return 0
     if options.contains('sample-config'):
         settings = Settings()
         settings.save("gtimelogrc.sample")
         print("Sample configuration file written to gtimelogrc.sample")
         print("Edit it and save as %s" % settings.get_config_file())
         return 0
     self.debug = options.contains('debug')
     self.start_minimized = options.contains('tray')
     if options.contains('quit'):
         print('gtimelog: Telling the already-running instance to quit')
     return -1  # send the args to the remote instance for processing
コード例 #4
0
 def do_handle_local_options(self, options):
     if options.contains('version'):
         print(gtimelog.__version__)
         return 0
     if options.contains('sample-config'):
         settings = Settings()
         settings.save("gtimelogrc.sample")
         print("Sample configuration file written to gtimelogrc.sample")
         print("Edit it and save as %s" % settings.get_config_file())
         return 0
     self.debug = options.contains('debug')
     self.start_minimized = options.contains('tray')
     if options.contains('quit'):
         print('gtimelog: Telling the already-running instance to quit')
     return -1  # send the args to the remote instance for processing
コード例 #5
0
ファイル: benchmark.py プロジェクト: wosc/gtimelog
def parse_two():  # slower than parse_one
    filename = Settings().get_timelog_file()
    for line in open(filename):
        try:
            time, entry = line.split(': ', 1)
            time = parse_datetime(time)
        except ValueError:
            continue
コード例 #6
0
ファイル: benchmark.py プロジェクト: wosc/gtimelog
def parse_three():  # fastest
    filename = Settings().get_timelog_file()
    for line in open(filename):
        time, sep, entry = line.partition(': ')
        if not sep:
            continue
        try:
            time = parse_datetime(time)
        except ValueError:
            continue
コード例 #7
0
ファイル: benchmark.py プロジェクト: wosc/gtimelog
def parse_one():
    filename = Settings().get_timelog_file()
    for line in open(filename):
        if ': ' not in line:
            continue
        time, entry = line.split(': ', 1)
        try:
            time = parse_datetime(time)
        except ValueError:
            continue
コード例 #8
0
ファイル: benchmark.py プロジェクト: wosc/gtimelog
def parse_and_strip():
    filename = Settings().get_timelog_file()
    for line in open(filename):
        time, sep, entry = line.partition(': ')
        if not sep:
            continue
        try:
            time = parse_datetime(time)
        except ValueError:
            continue
        entry = entry.strip()
コード例 #9
0
ファイル: benchmark.py プロジェクト: wosc/gtimelog
def parse_and_collect():
    items = []
    filename = Settings().get_timelog_file()
    for line in open(filename):
        time, sep, entry = line.partition(': ')
        if not sep:
            continue
        try:
            time = parse_datetime(time)
        except ValueError:
            continue
        entry = entry.strip()
        items.append((time, entry))
    return items
コード例 #10
0
class GtimelogParser(object):
    def __init__(self, config):
        self.settings = Settings()
        self.timelog = TimeLog(self.settings.get_timelog_file(),
                               self.settings.virtual_midnight)
        self.aliases = config.get('aliases', {})

    def skip_entry(self, entry):
        if '**' in entry:
            return True
        if entry.strip() in ('arrive', 'arrived', 'start'):
            return True
        return False

    def get_entries(self, date_window):
        window = self.timelog.window_for(date_window.start, date_window.stop)

        worklogs = []
        attendances = []
        for start, stop, duration, tags, entry in window.all_entries():
            if self.skip_entry(entry):
                continue
            if attendances and attendances[-1][1] == start:
                attendances[-1] = (attendances[-1][0], stop)
            else:
                attendances += [(start, stop)]
            try:
                issue, description = [
                    x.strip() for x in entry.split(':', 1) if x.strip()
                ]
            except ValueError:
                print(
                    'Entry must be in the format `task: description`. '
                    'Got ', entry)
                continue

            # no matter what we find as `issue`:
            # if we have an alias override it takes precedence
            if issue in self.aliases:
                issue = self.aliases[issue]
            worklogs.append(
                MultiLog(None, issue, int(duration.total_seconds()),
                         start.date(), description))

        # Dangling attendance for today
        if attendances and attendances[-1][1].date() == date.today():
            attendances[-1] = (attendances[-1][0], None)

        return attendances, worklogs
コード例 #11
0
ファイル: benchmark.py プロジェクト: wosc/gtimelog
def parse_and_sort_unicode():
    items = []
    filename = Settings().get_timelog_file()
    for line in open(filename, 'rb').read().decode('UTF-8').splitlines():
        time, sep, entry = line.partition(': ')
        if not sep:
            continue
        try:
            time = parse_datetime(time)
        except ValueError:
            continue
        entry = entry.strip()
        items.append((time, entry))
    items.sort(key=itemgetter(0))
    return items
コード例 #12
0
ファイル: benchmark.py プロジェクト: wosc/gtimelog
def parse_and_sort_incorrectly():
    items = []
    filename = Settings().get_timelog_file()
    for line in open(filename):
        time, sep, entry = line.partition(': ')
        if not sep:
            continue
        try:
            time = parse_datetime(time)
        except ValueError:
            continue
        entry = entry.strip()
        items.append((time, entry))
    items.sort()  # XXX: can reorder lines
    return items
コード例 #13
0
ファイル: benchmark.py プロジェクト: wosc/gtimelog
def parse_and_sort_unicode_piecemeal():
    items = []
    filename = Settings().get_timelog_file()
    for line in open(filename, 'rb'):
        time, sep, entry = line.partition(b': ')
        if not sep:
            continue
        try:
            time = parse_datetime(time.decode('ASCII'))
        except (ValueError, UnicodeError):
            continue
        entry = entry.strip().decode('UTF-8')
        items.append((time, entry))
    items.sort(key=itemgetter(0))
    return items
コード例 #14
0
ファイル: tests.py プロジェクト: ollyfg/gtimelog
class TestSettings(unittest.TestCase):

    def setUp(self):
        from gtimelog.settings import Settings
        self.settings = Settings()
        self.real_isdir = os.path.isdir
        self.tempdir = None
        self.old_home = os.environ.get('HOME')
        self.old_gtimelog_home = os.environ.get('GTIMELOG_HOME')
        self.old_xdg_config_home = os.environ.get('XDG_CONFIG_HOME')
        self.old_xdg_data_home = os.environ.get('XDG_DATA_HOME')
        os.environ['HOME'] = os.path.normpath('/tmp/home')
        os.environ.pop('GTIMELOG_HOME', None)
        os.environ.pop('XDG_CONFIG_HOME', None)
        os.environ.pop('XDG_DATA_HOME', None)

    def tearDown(self):
        os.path.isdir = self.real_isdir
        if self.tempdir:
            shutil.rmtree(self.tempdir)
        self.restore_env('HOME', self.old_home)
        self.restore_env('GTIMELOG_HOME', self.old_gtimelog_home)
        self.restore_env('XDG_CONFIG_HOME', self.old_xdg_config_home)
        self.restore_env('XDG_DATA_HOME', self.old_xdg_data_home)

    def restore_env(self, envvar, value):
        if value is not None:
            os.environ[envvar] = value
        else:
            os.environ.pop(envvar, None)

    def mkdtemp(self):
        if self.tempdir is None:
            self.tempdir = tempfile.mkdtemp(prefix='gtimelog-test-')
        return self.tempdir

    def test_get_config_dir_1(self):
        # Case 1: GTIMELOG_HOME is present in the environment
        os.environ['GTIMELOG_HOME'] = os.path.normpath('~/.gt')
        self.assertEqual(self.settings.get_config_dir(),
                         os.path.normpath('/tmp/home/.gt'))

    def test_get_config_dir_2(self):
        # Case 2: ~/.gtimelog exists
        os.path.isdir = lambda dir: True
        self.assertEqual(self.settings.get_config_dir(),
                         os.path.normpath('/tmp/home/.gtimelog'))

    def test_get_config_dir_3(self):
        # Case 3: ~/.gtimelog does not exist, so we use XDG
        os.path.isdir = lambda dir: False
        self.assertEqual(self.settings.get_config_dir(),
                         os.path.normpath('/tmp/home/.config/gtimelog'))

    def test_get_config_dir_4(self):
        # Case 4: XDG_CONFIG_HOME is present in the environment
        os.environ['XDG_CONFIG_HOME'] = os.path.normpath('~/.conf')
        self.assertEqual(self.settings.get_config_dir(),
                         os.path.normpath('/tmp/home/.conf/gtimelog'))

    def test_get_data_dir_1(self):
        # Case 1: GTIMELOG_HOME is present in the environment
        os.environ['GTIMELOG_HOME'] = os.path.normpath('~/.gt')
        self.assertEqual(self.settings.get_data_dir(),
                         os.path.normpath('/tmp/home/.gt'))

    def test_get_data_dir_2(self):
        # Case 2: ~/.gtimelog exists
        os.path.isdir = lambda dir: True
        self.assertEqual(self.settings.get_data_dir(),
                         os.path.normpath('/tmp/home/.gtimelog'))

    def test_get_data_dir_3(self):
        # Case 3: ~/.gtimelog does not exist, so we use XDG
        os.path.isdir = lambda dir: False
        self.assertEqual(self.settings.get_data_dir(),
                         os.path.normpath('/tmp/home/.local/share/gtimelog'))

    def test_get_data_dir_4(self):
        # Case 4: XDG_CONFIG_HOME is present in the environment
        os.environ['XDG_DATA_HOME'] = os.path.normpath('~/.data')
        self.assertEqual(self.settings.get_data_dir(),
                         os.path.normpath('/tmp/home/.data/gtimelog'))

    def test_get_config_file(self):
        self.settings.get_config_dir = lambda: os.path.normpath('~/.config/gtimelog')
        self.assertEqual(self.settings.get_config_file(),
                         os.path.normpath('~/.config/gtimelog/gtimelogrc'))

    def test_get_timelog_file(self):
        self.settings.get_data_dir = lambda: os.path.normpath('~/.local/share/gtimelog')
        self.assertEqual(self.settings.get_timelog_file(),
                         os.path.normpath('~/.local/share/gtimelog/timelog.txt'))

    def test_load(self):
        self.settings.load('/dev/null')

    def test_save(self):
        tempdir = self.mkdtemp()
        self.settings.save(os.path.join(tempdir, 'config'))
コード例 #15
0
ファイル: test_settings.py プロジェクト: wfailla/gtimelog
class TestSettings(unittest.TestCase):
    def setUp(self):
        self.settings = Settings()
        self.real_isdir = os.path.isdir
        self.tempdir = None
        self.old_home = os.environ.get('HOME')
        self.old_userprofile = os.environ.get('USERPROFILE')
        self.old_gtimelog_home = os.environ.get('GTIMELOG_HOME')
        self.old_xdg_config_home = os.environ.get('XDG_CONFIG_HOME')
        self.old_xdg_data_home = os.environ.get('XDG_DATA_HOME')
        os.environ['HOME'] = os.path.normpath('/tmp/home')
        os.environ['USERPROFILE'] = os.path.normpath('/tmp/home')
        os.environ.pop('GTIMELOG_HOME', None)
        os.environ.pop('XDG_CONFIG_HOME', None)
        os.environ.pop('XDG_DATA_HOME', None)

    def tearDown(self):
        os.path.isdir = self.real_isdir
        if self.tempdir:
            shutil.rmtree(self.tempdir)
        self.restore_env('HOME', self.old_home)
        self.restore_env('USERPROFILE', self.old_userprofile)
        self.restore_env('GTIMELOG_HOME', self.old_gtimelog_home)
        self.restore_env('XDG_CONFIG_HOME', self.old_xdg_config_home)
        self.restore_env('XDG_DATA_HOME', self.old_xdg_data_home)

    def restore_env(self, envvar, value):
        if value is not None:
            os.environ[envvar] = value
        else:
            os.environ.pop(envvar, None)

    def mkdtemp(self):
        if self.tempdir is None:
            self.tempdir = tempfile.mkdtemp(prefix='gtimelog-test-')
        return self.tempdir

    def test_get_config_dir_1(self):
        # Case 1: GTIMELOG_HOME is present in the environment
        os.environ['GTIMELOG_HOME'] = os.path.normpath('~/.gt')
        self.assertEqual(self.settings.get_config_dir(),
                         os.path.normpath('/tmp/home/.gt'))

    def test_get_config_dir_2(self):
        # Case 2: ~/.gtimelog exists
        os.path.isdir = lambda dir: True
        self.assertEqual(self.settings.get_config_dir(),
                         os.path.normpath('/tmp/home/.gtimelog'))

    def test_get_config_dir_3(self):
        # Case 3: ~/.gtimelog does not exist, so we use XDG
        os.path.isdir = lambda dir: False
        self.assertEqual(self.settings.get_config_dir(),
                         os.path.normpath('/tmp/home/.config/gtimelog'))

    def test_get_config_dir_4(self):
        # Case 4: XDG_CONFIG_HOME is present in the environment
        os.environ['XDG_CONFIG_HOME'] = os.path.normpath('~/.conf')
        self.assertEqual(self.settings.get_config_dir(),
                         os.path.normpath('/tmp/home/.conf/gtimelog'))

    def test_get_data_dir_1(self):
        # Case 1: GTIMELOG_HOME is present in the environment
        os.environ['GTIMELOG_HOME'] = os.path.normpath('~/.gt')
        self.assertEqual(self.settings.get_data_dir(),
                         os.path.normpath('/tmp/home/.gt'))

    def test_get_data_dir_2(self):
        # Case 2: ~/.gtimelog exists
        os.path.isdir = lambda dir: True
        self.assertEqual(self.settings.get_data_dir(),
                         os.path.normpath('/tmp/home/.gtimelog'))

    def test_get_data_dir_3(self):
        # Case 3: ~/.gtimelog does not exist, so we use XDG
        os.path.isdir = lambda dir: False
        self.assertEqual(self.settings.get_data_dir(),
                         os.path.normpath('/tmp/home/.local/share/gtimelog'))

    def test_get_data_dir_4(self):
        # Case 4: XDG_CONFIG_HOME is present in the environment
        os.environ['XDG_DATA_HOME'] = os.path.normpath('~/.data')
        self.assertEqual(self.settings.get_data_dir(),
                         os.path.normpath('/tmp/home/.data/gtimelog'))

    def test_get_config_file(self):
        self.settings.get_config_dir = lambda: os.path.normpath(
            '~/.config/gtimelog')
        self.assertEqual(self.settings.get_config_file(),
                         os.path.normpath('~/.config/gtimelog/gtimelogrc'))

    def test_get_timelog_file(self):
        self.settings.get_data_dir = lambda: os.path.normpath(
            '~/.local/share/gtimelog')
        self.assertEqual(
            self.settings.get_timelog_file(),
            os.path.normpath('~/.local/share/gtimelog/timelog.txt'))

    def test_get_report_log_file(self):
        self.settings.get_data_dir = lambda: os.path.normpath(
            '~/.local/share/gtimelog')
        self.assertEqual(
            self.settings.get_report_log_file(),
            os.path.normpath('~/.local/share/gtimelog/sentreports.log'))

    def test_get_task_list_file(self):
        self.settings.get_data_dir = lambda: os.path.normpath(
            '~/.local/share/gtimelog')
        self.assertEqual(self.settings.get_task_list_file(),
                         os.path.normpath('~/.local/share/gtimelog/tasks.txt'))

    def test_get_task_list_cache_file(self):
        self.settings.get_data_dir = lambda: os.path.normpath(
            '~/.local/share/gtimelog')
        self.assertEqual(
            self.settings.get_task_list_cache_file(),
            os.path.normpath('~/.local/share/gtimelog/remote-tasks.txt'))

    def test_load(self):
        self.settings.load('/dev/null')
        self.assertEqual(self.settings.name, 'Anonymous')

    def test_load_default_file(self):
        self.settings.load()

    def test_save(self):
        tempdir = self.mkdtemp()
        self.settings.save(os.path.join(tempdir, 'config'))
コード例 #16
0
def full():
    return Settings().get_time_log().items
コード例 #17
0
ファイル: main.py プロジェクト: ollyfg/gtimelog
    def do_activate(self):
        if self.main_window is not None:
            self.main_window.main_window.present()
            return

        debug = self.debug
        start_minimized = self.start_minimized

        log.addHandler(logging.StreamHandler(sys.stdout))
        if debug:
            log.setLevel(logging.DEBUG)
        else:
            log.setLevel(logging.INFO)

        if debug:
            print('GTimeLog version: %s' % gtimelog.__version__)
            print('Python version: %s' % sys.version)
            print('Gtk+ version: %s.%s.%s' % (Gtk.MAJOR_VERSION, Gtk.MINOR_VERSION, Gtk.MICRO_VERSION))
            print('Config directory: %s' % Settings().get_config_dir())
            print('Data directory: %s' % Settings().get_data_dir())

        settings = Settings()
        configdir = settings.get_config_dir()
        datadir = settings.get_data_dir()
        try:
            # Create configdir if it doesn't exist.
            os.makedirs(configdir)
        except OSError as error:
            if error.errno != errno.EEXIST:
                # XXX: not the most friendly way of error reporting for a GUI app
                raise
        try:
            # Create datadir if it doesn't exist.
            os.makedirs(datadir)
        except OSError as error:
            if error.errno != errno.EEXIST:
                raise

        settings_file = settings.get_config_file()
        if not os.path.exists(settings_file):
            if debug:
                print('Saving settings to %s' % settings_file)
            settings.save(settings_file)
        else:
            if debug:
                print('Loading settings from %s' % settings_file)
            settings.load(settings_file)
        if debug:
            print('Assuming date changes at %s' % settings.virtual_midnight)
            print('Loading time log from %s' % settings.get_timelog_file())
        timelog = TimeLog(settings.get_timelog_file(),
                          settings.virtual_midnight)
        if settings.task_list_url:
            if debug:
                print('Loading cached remote tasks from %s' %
                      os.path.join(datadir, 'remote-tasks.txt'))
            tasks = RemoteTaskList(settings.task_list_url,
                                   os.path.join(datadir, 'remote-tasks.txt'))
        else:
            if debug:
                print('Loading tasks from %s' % os.path.join(datadir, 'tasks.txt'))
            tasks = TaskList(os.path.join(datadir, 'tasks.txt'))
        self.main_window = MainWindow(timelog, settings, tasks)
        self.add_window(self.main_window.main_window)
        start_in_tray = False

        if settings.show_tray_icon:
            if debug:
                print('Tray icon preference: %s' % ('AppIndicator'
                                                    if settings.prefer_app_indicator
                                                    else 'SimpleStatusIcon'))

            if settings.prefer_app_indicator and have_app_indicator:
                tray_icon = AppIndicator(self.main_window)
            else:
                tray_icon = SimpleStatusIcon(self.main_window)

            if tray_icon:
                if debug:
                    print('Using: %s' % tray_icon.__class__.__name__)

                start_in_tray = (settings.start_in_tray
                                 if settings.start_in_tray
                                 else start_minimized)

        if debug:
            print('GTK+ completion: %s' % ('enabled' if settings.enable_gtk_completion else 'disabled'))

        if not start_in_tray:
            self.main_window.on_show_activate()
        else:
            if debug:
                print('Starting minimized')

        # This is needed to make ^C terminate gtimelog when we're using
        # gobject-introspection.
        signal.signal(signal.SIGINT, signal.SIG_DFL)
コード例 #18
0
 def __init__(self, config):
     self.settings = Settings()
     self.timelog = TimeLog(self.settings.get_timelog_file(),
                            self.settings.virtual_midnight)
     self.aliases = config.get('aliases', {})
コード例 #19
0
    def do_activate(self):
        if self.main_window is not None:
            self.main_window.main_window.present()
            return

        log.addHandler(logging.StreamHandler(sys.stdout))
        if self.opts.debug:
            log.setLevel(logging.DEBUG)
        else:
            log.setLevel(logging.INFO)

        if self.opts.sample_config:
            settings = Settings()
            settings.save("gtimelogrc.sample")
            print("Sample configuration file written to gtimelogrc.sample")
            print("Edit it and save as %s" % settings.get_config_file())
            return

        if self.opts.debug:
            print('GTimeLog version: %s' % gtimelog.__version__)
            print('Gtk+ version: %s.%s.%s' % (Gtk.MAJOR_VERSION, Gtk.MINOR_VERSION, Gtk.MICRO_VERSION))
            print('Config directory: %s' % Settings().get_config_dir())
            print('Data directory: %s' % Settings().get_data_dir())

        settings = Settings()
        configdir = settings.get_config_dir()
        datadir = settings.get_data_dir()
        try:
            # Create configdir if it doesn't exist.
            os.makedirs(configdir)
        except OSError as error:
            if error.errno != errno.EEXIST:
                # XXX: not the most friendly way of error reporting for a GUI app
                raise
        try:
            # Create datadir if it doesn't exist.
            os.makedirs(datadir)
        except OSError as error:
            if error.errno != errno.EEXIST:
                raise

        settings_file = settings.get_config_file()
        if not os.path.exists(settings_file):
            if self.opts.debug:
                print('Saving settings to %s' % settings_file)
            settings.save(settings_file)
        else:
            if self.opts.debug:
                print('Loading settings from %s' % settings_file)
            settings.load(settings_file)
        if self.opts.debug:
            print('Assuming date changes at %s' % settings.virtual_midnight)
            print('Loading time log from %s' % settings.get_timelog_file())
        timelog = TimeLog(settings.get_timelog_file(),
                          settings.virtual_midnight)
        if settings.task_list_url:
            if self.opts.debug:
                print('Loading cached remote tasks from %s' %
                      os.path.join(datadir, 'remote-tasks.txt'))
            tasks = RemoteTaskList(settings.task_list_url,
                                   os.path.join(datadir, 'remote-tasks.txt'))
        else:
            if self.opts.debug:
                print('Loading tasks from %s' % os.path.join(datadir, 'tasks.txt'))
            tasks = TaskList(os.path.join(datadir, 'tasks.txt'))
        self.main_window = MainWindow(timelog, settings, tasks)
        self.add_window(self.main_window.main_window)
        start_in_tray = False

        if settings.show_tray_icon:
            if self.opts.debug:
                print('Tray icon preference: %s' % ('AppIndicator'
                                                    if settings.prefer_app_indicator
                                                    else 'SimpleStatusIcon'))

            if settings.prefer_app_indicator and have_app_indicator:
                tray_icon = AppIndicator(self.main_window)
            else:
                tray_icon = SimpleStatusIcon(self.main_window)

            if tray_icon:
                if self.opts.debug:
                    print('Using: %s' % tray_icon.__class__.__name__)

                start_in_tray = (settings.start_in_tray
                                 if settings.start_in_tray
                                 else self.opts.tray)

        if not start_in_tray:
            self.main_window.on_show_activate()
        else:
            if self.opts.debug:
                print('Starting minimized')

        # This is needed to make ^C terminate gtimelog when we're using
        # gobject-introspection.
        signal.signal(signal.SIGINT, signal.SIG_DFL)
コード例 #20
0
ファイル: benchmark.py プロジェクト: wosc/gtimelog
def full():
    return TimeLog(Settings().get_timelog_file(),
                   Settings().virtual_midnight).items
コード例 #21
0
ファイル: benchmark.py プロジェクト: wosc/gtimelog
def split():
    filename = Settings().get_timelog_file()
    for line in open(filename):
        if ': ' not in line:
            continue
        time, entry = line.split(': ', 1)
コード例 #22
0
ファイル: benchmark.py プロジェクト: wosc/gtimelog
def just_read():
    filename = Settings().get_timelog_file()
    open(filename).readlines()