<commit_before># -*- coding: utf-8 -*-
'''
    watdo.editor
    ~~~~~~~~~~~~

    This module provides utilities for generating and parsing the markdown file
    for editor mode.

    :copyright: (c) 2013 <NAME>
    :license: MIT, see LICENSE for more details.
'''

from .datastructures import EventWrapper
from .filesystem import walk_calendars
import datetime
import os

DESCRIPTION_INDENT = '    '


def change_modify_event(old_event, new_event):
    def inner():
        old_event.main.update(dict((k, v) for k, v in
                                   new_event.main.iteritems() if v))
        old_event.main.pop('last-modified', None)
        old_event.main.add('last-modified', datetime.datetime.now())

        with open(old_event.filepath, 'wb') as f:
            f.write(old_event.vcal.to_ical())
    return u'Modify event: {}'.format(old_event.main.get('summary', '')), inner


def change_add_event(event):
    '''event is actually a simple dict'''
    def inner():
        raise NotImplementedError('Adding events is not yet implemented.')
    return u'Add event: "{}"'.format(event.main.get('summary', '')), inner


def change_delete_event(event):
    def inner():
        os.remove(event.filepath)
    return u'Delete event: "{}"'.format(event.main.get('summary', '')), inner


def generate_tmpfile(f, calendars_path, description_indent=DESCRIPTION_INDENT):
    '''Given a file-like object ``f`` and a path, write todo file to ``f``,
    return a ``ids`` object'''

    calendars = walk_calendars(calendars_path)
    ids = {}
    p = lambda x=u'': f.write((x + u'\n').encode('utf-8'))

    for calendar, events in sorted(calendars, key=lambda x: x[0]):
        # sort by name
        p()
        p(u'# {}'.format(calendar))
        # sort by deadline
        events.sort(key=(lambda x:
                         x.main.get('dtend', None) or datetime.datetime.now()))
        ids.setdefault(calendar, {})

        for i, event in enumerate(events, start=1):
            ids[calendar][i] = event
            p(u'{i}.  {t}'.format(i=i, t=event.main.get('summary', '')))
            for l in event.main.get('description', '').splitlines():
                p(description_indent + l)
    return ids


def parse_tmpfile(lines, description_indent=DESCRIPTION_INDENT):
    ids = {}
    calendar_name = None
    event_id = None

    for lineno, line in enumerate(lines, start=1):
        line = line.decode('utf-8').rstrip('\n')
        if line.startswith(description_indent) or not line:
            if event_id:
                if line:
                    line = line[len(description_indent):]
                ids[calendar_name][event_id].main['description'].append(line)
        elif line.startswith(u'# '):
            calendar_name = line[2:]
            event_id = None
            ids[calendar_name] = {}
        elif calendar_name and line[0].isdigit():
            event_id, event_summary = line.split(u'.  ', 1)
            event_id = int(event_id)
            if event_id in ids[calendar_name]:
                raise RuntimeError('Line {}: This list index already has been '
                                   'used for this calendar'.format(lineno))
            ids[calendar_name][event_id] = EventWrapper(main={
                'summary': event_summary,
                'description': []
            })
        else:
            raise RuntimeError('Line {}: Not decipherable'.format(lineno))

    for events in ids.itervalues():
        for event in events.itervalues():
            event = event.main
            event['description'] = '\n'.join(event['description'])
            if not event['description']:
                del event['description']

    return ids


def diff_calendars(ids_a, ids_b):
    '''Get difference between two ``ids`` objects'''
    if set(ids_a) != set(ids_b):
        raise RuntimeError('Adding, renaming and deleting calendars is not '
                           'supported.', set(ids_a), set(ids_b))<commit_msg>Fix bug that wouldn't delete descriptions<commit_after># -*- coding: utf-8 -*-
'''
    watdo.editor
    ~~~~~~~~~~~~

    This module provides utilities for generating and parsing the markdown file
    for editor mode.

    :copyright: (c) 2013 <NAME>
    :license: MIT, see LICENSE for more details.
'''

from .datastructures import EventWrapper
from .filesystem import walk_calendars
import datetime
import os

DESCRIPTION_INDENT = '    '


def change_modify_event(old_event, new_event):
    def inner():
        old_event.main.update(new_event.main)
        old_event.main.pop('last-modified', None)
        old_event.main.add('last-modified', datetime.datetime.now())

        with open(old_event.filepath, 'wb') as f:
            f.write(old_event.vcal.to_ical())
    return u'Modify event: {}'.format(old_event.main.get('summary', '')), inner


def change_add_event(event):
    '''event is actually a simple dict'''
    def inner():
        raise NotImplementedError('Adding events is not yet implemented.')
    return u'Add event: "{}"'.format(event.main.get('summary', '')), inner


def change_delete_event(event):
    def inner():
        os.remove(event.filepath)
    return u'Delete event: "{}"'.format(event.main.get('summary', '')), inner


def generate_tmpfile(f, calendars_path, description_indent=DESCRIPTION_INDENT):
    '''Given a file-like object ``f`` and a path, write todo file to ``f``,
    return a ``ids`` object'''

    calendars = walk_calendars(calendars_path)
    ids = {}
    p = lambda x=u'': f.write((x + u'\n').encode('utf-8'))

    for calendar, events in sorted(calendars, key=lambda x: x[0]):
        # sort by name
        p()
        p(u'# {}'.format(calendar))
        # sort by deadline
        events.sort(key=(lambda x:
                         x.main.get('dtend', None) or datetime.datetime.now()))
        ids.setdefault(calendar, {})

        for i, event in enumerate(events, start=1):
            ids[calendar][i] = event
            p(u'{i}.  {t}'.format(i=i, t=event.main.get('summary', '')))
            for l in event.main.get('description', '').splitlines():
                p(description_indent + l)
    return ids


def parse_tmpfile(lines, description_indent=DESCRIPTION_INDENT):
    ids = {}
    calendar_name = None
    event_id = None

    for lineno, line in enumerate(lines, start=1):
        line = line.decode('utf-8').rstrip('\n')
        if line.startswith(description_indent) or not line:
            if event_id:
                if line:
                    line = line[len(description_indent):]
                ids[calendar_name][event_id].main['description'].append(line)
        elif line.startswith(u'# '):
            calendar_name = line[2:]
            event_id = None
            ids[calendar_name] = {}
        elif calendar_name and line[0].isdigit():
            event_id, event_summary = line.split(u'.  ', 1)
            event_id = int(event_id)
            if event_id in ids[calendar_name]:
                raise RuntimeError('Line {}: This list index already has been '
                                   'used for this calendar'.format(lineno))
            ids[calendar_name][event_id] = EventWrapper(main={
                'summary': event_summary,
                'description': []
            })
        else:
            raise RuntimeError('Line {}: Not decipherable'.format(lineno))

    for events in ids.itervalues():
        for event in events.itervalues():
            event = event.main
            event['description'] = '\n'.join(event['description'])

    return ids


def diff_calendars(ids_a, ids_b):
    '''Get difference between two ``ids`` objects'''
    if set(ids_a) != set(ids_b):
        raise RuntimeError('Adding, renaming and deleting calendars is not '
                           'supported.', set(ids_a), set(ids_b))
{'fraction_non_alphanumeric': 0.1365446371226718, 'fraction_numerical': 0.0033397559409120104, 'mean_word_length': 2.4375275938189844, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3987478', 'n_tokens_mistral': 2354, 'n_tokens_neox': 2274, 'n_words': 569}