# Path: pypasta/MAINTAINERS.py
# def load_maintainers(config, versions):
#     def __load_maintainers(ret, config, versions):
#         if ret is None:
#             ret = dict()
# 
#         # Only load what's not yet cached
#         versions -= ret.keys()
# 
#         if len(versions) == 0:
#             return ret, False
# 
#         global _repo
#         _repo = config.repo
#         p = Pool(processes=cpu_count())
#         function = partial(_load_maintainer,
#                            d_cluster = config.d_maintainers_cluster,
#                            project_name = config.project_name)
# 
#         for tag, maintainers in tqdm(p.imap_unordered(function, versions),
#                                      total=len(versions), desc='MAINTAINERS'):
#             ret[tag] = maintainers
# 
#         p.close()
#         p.join()
#         _repo = None
# 
#         return ret, True
# 
#     log.info('Loading/Updating MAINTAINERS...')
#     maintainers_version = load_pkl_and_update(config.f_maintainers_pkl,
#                                               __load_maintainers, config,
#                                               versions)
#     return maintainers_version
# 
# Path: pypasta/Util.py
# def get_first_upstream(repo, cluster, commit):
#     upstream = cluster.get_upstream(commit)
#     if not upstream:
#         return None
#     return min(upstream, key=lambda x: repo[x].committer.date)
# 
# def load_pkl_and_update(filename, update_command, *params):
#     ret = None
#     if os.path.isfile(filename):
#         ret = pickle.load(open(filename, 'rb'))
# 
#     if len(params) == 0:
#         ret, changed = update_command(ret)
#     else:
#         ret, changed = update_command(ret, *params)
# 
#     if changed:
#         pickle.dump(ret, open(filename, 'wb'))
# 
#     return ret
# 
# def mail_parse_date(date_str, assume_epoch=False):
#     try:
#         date = email.utils.parsedate_to_datetime(date_str)
#     except Exception:
#         date = None
# 
#     if not date:
#         try:
#             date = dateparser.parse(date_str)
#         except Exception:
#             date = None
# 
#     if not date:
#         date = datetime.datetime.utcfromtimestamp(0)
# 
#     if date.tzinfo is None:
#         date = date.replace(tzinfo=datetime.timezone.utc)
# 
#     return date


import csv
import email
import re
from anytree import LevelOrderIter
from enum import Enum
from logging import getLogger
from multiprocessing import Pool, cpu_count
from .MAINTAINERS import load_maintainers
from .Util import get_first_upstream, load_pkl_and_update, mail_parse_date
    from .BuildrootMailCharacteristics import BuildrootMailCharacteristics
    from .DPDKMailCharacteristics import DPDKMailCharacteristics
    from .GitMailCharacteristics import GitMailCharacteristics
    from .JailhouseMailCharacteristics import JailhouseMailCharacteristics
    from .LinuxMailCharacteristics import LinuxMailCharacteristics
    from .OpenembeddedMailCharacteristics import OpenembeddedMailCharacteristics
    from .QemuMailCharacteristics import QemuMailCharacteristics
    from .UBootMailCharacteristics import UBootMailCharacteristics
    from .XenMailCharacteristics import XenMailCharacteristics

    def _load_characteristics(ret):
        if ret is None:
            ret = dict()

        missing = message_ids - ret.keys()
        if len(missing) == 0:
            return ret, False

        global _repo, _maintainers_version, _clustering, _characteristics_class
        _maintainers_version = maintainers_version
        _clustering = clustering
        _repo = repo
        _characteristics_class = _characteristics_classes[config.project_name]

        p = Pool(processes=int(0.25*cpu_count()), maxtasksperchild=4)

        missing = p.map(_load_mail_characteristic, missing, chunksize=1000)
        missing = dict(missing)
        print('Done')
        p.close()
        p.join()
        _repo = None
        _maintainers_version = None
        _clustering = None
        _characteristics_class = None

        return {**ret, **missing}, True

    log.info('Loading/Updating patch characteristics...')

# Path: pypasta/MAINTAINERS.py
# def load_maintainers(config, versions):
#     def __load_maintainers(ret, config, versions):
#         if ret is None:
#             ret = dict()
# 
#         # Only load what's not yet cached
#         versions -= ret.keys()
# 
#         if len(versions) == 0:
#             return ret, False
# 
#         global _repo
#         _repo = config.repo
#         p = Pool(processes=cpu_count())
#         function = partial(_load_maintainer,
#                            d_cluster = config.d_maintainers_cluster,
#                            project_name = config.project_name)
# 
#         for tag, maintainers in tqdm(p.imap_unordered(function, versions),
#                                      total=len(versions), desc='MAINTAINERS'):
#             ret[tag] = maintainers
# 
#         p.close()
#         p.join()
#         _repo = None
# 
#         return ret, True
# 
#     log.info('Loading/Updating MAINTAINERS...')
#     maintainers_version = load_pkl_and_update(config.f_maintainers_pkl,
#                                               __load_maintainers, config,
#                                               versions)
#     return maintainers_version
# 
# Path: pypasta/Util.py
# def get_first_upstream(repo, cluster, commit):
#     upstream = cluster.get_upstream(commit)
#     if not upstream:
#         return None
#     return min(upstream, key=lambda x: repo[x].committer.date)
# 
# def load_pkl_and_update(filename, update_command, *params):
#     ret = None
#     if os.path.isfile(filename):
#         ret = pickle.load(open(filename, 'rb'))
# 
#     if len(params) == 0:
#         ret, changed = update_command(ret)
#     else:
#         ret, changed = update_command(ret, *params)
# 
#     if changed:
#         pickle.dump(ret, open(filename, 'wb'))
# 
#     return ret
# 
# def mail_parse_date(date_str, assume_epoch=False):
#     try:
#         date = email.utils.parsedate_to_datetime(date_str)
#     except Exception:
#         date = None
# 
#     if not date:
#         try:
#             date = dateparser.parse(date_str)
#         except Exception:
#             date = None
# 
#     if not date:
#         date = datetime.datetime.utcfromtimestamp(0)
# 
#     if date.tzinfo is None:
#         date = date.replace(tzinfo=datetime.timezone.utc)
# 
#     return date


# Path: pypasta/MailCharacteristics.py
import csv
import email
import re
from anytree import LevelOrderIter
from enum import Enum
from logging import getLogger
from multiprocessing import Pool, cpu_count
from .MAINTAINERS import load_maintainers
from .Util import get_first_upstream, load_pkl_and_update, mail_parse_date
    from .BuildrootMailCharacteristics import BuildrootMailCharacteristics
    from .DPDKMailCharacteristics import DPDKMailCharacteristics
    from .GitMailCharacteristics import GitMailCharacteristics
    from .JailhouseMailCharacteristics import JailhouseMailCharacteristics
    from .LinuxMailCharacteristics import LinuxMailCharacteristics
    from .OpenembeddedMailCharacteristics import OpenembeddedMailCharacteristics
    from .QemuMailCharacteristics import QemuMailCharacteristics
    from .UBootMailCharacteristics import UBootMailCharacteristics
    from .XenMailCharacteristics import XenMailCharacteristics


    def _load_characteristics(ret):
        if ret is None:
            ret = dict()

        missing = message_ids - ret.keys()
        if len(missing) == 0:
            return ret, False

        global _repo, _maintainers_version, _clustering, _characteristics_class
        _maintainers_version = maintainers_version
        _clustering = clustering
        _repo = repo
        _characteristics_class = _characteristics_classes[config.project_name]

        p = Pool(processes=int(0.25*cpu_count()), maxtasksperchild=4)

        missing = p.map(_load_mail_characteristic, missing, chunksize=1000)
        missing = dict(missing)
        print('Done')
        p.close()
        p.join()
        _repo = None
        _maintainers_version = None
        _clustering = None
        _characteristics_class = None

        return {**ret, **missing}, True

    log.info('Loading/Updating patch characteristics...')

    characteristics = load_pkl_and_update(config.f_characteristics_pkl,