<commit_before># coding: utf-8
from os.path import join, basename
import os
import sys
import re
import urllib
import tarfile
import setuptools
import logging
import stat
import imp
import shutil
import ConfigParser
import distutils.core
import pkg_resources
try:
    from collections import OrderedDict
except ImportError:  # Python < 2.7
    from ordereddict import OrderedDict  # noqa
from zc.buildout.easy_install import MissingDistribution
from zc.buildout import UserError
from zc.buildout.easy_install import VersionConflict
from zc.buildout.easy_install import Installer

from zc.buildout.easy_install import IncompatibleConstraintError

import zc.recipe.egg
import httplib
import rfc822
from urlparse import urlparse
from . import vcs
from . import utils
from .utils import option_splitlines, option_strip, conf_ensure_section

logger = logging.getLogger(__name__)


def rfc822_time(h):
    """Parse RFC 2822-formatted http header and return a time int."""
    rfc822.mktime_tz(rfc822.parsedate_tz(h))


class MainSoftware(object):
    """Placeholder to represent the main software instead of an addon location.

    Should just have a singleton instance: :data:`main_software`,
    whose meaning depends on the concrete recipe class using it.

    For example, in :class:`anybox.recipe.odoo.server.ServerRecipe`,
    :data:`main_software` represents the OpenObject server or the Odoo
    standard distribution.
    """

    def __str__(self):
        return 'Main Software'

main_software = MainSoftware()

GP_VCS_EXTEND_DEVELOP = 'vcs-extend-develop'
GP_DEVELOP_DIR = 'develop-dir'

WITH_ODOO_REQUIREMENTS_FILE_OPTION = 'apply-requirements-file'


def pip_version():
    import pip
    return tuple(int(x) for x in pip.__version__.split('.'))


class BaseRecipe(object):
    """Base class for other recipes.

    It implements notably fetching of the main software part plus addons.

    The :attr:`sources` attribute is a ``dict`` storing how to fetch the main
    software part and the specified addons, with the following structure:

       ``local path -> (type, location_spec, options)``, in which:

       :local path: is either the :data:`main_software` singleton
                    (see :class:`MainSoftware`) or a local path to an
                    addons directory.
       :type: can be either

              * ``'local'``
              * ``'downloadable'``
              * one of the supported vcs

       :location_spec: is, depending on the type, a tuple specifying how
                       fetch is to be done:<commit_msg>Robustness in pip version parsing: (most) PEP 440 schemes<commit_after># coding: utf-8
from os.path import join, basename
import os
import sys
import re
import urllib
import tarfile
import setuptools
import logging
import stat
import imp
import shutil
import ConfigParser
import distutils.core
import pkg_resources
try:
    from collections import OrderedDict
except ImportError:  # Python < 2.7
    from ordereddict import OrderedDict  # noqa
from zc.buildout.easy_install import MissingDistribution
from zc.buildout import UserError
from zc.buildout.easy_install import VersionConflict
from zc.buildout.easy_install import Installer

from zc.buildout.easy_install import IncompatibleConstraintError

import zc.recipe.egg
import httplib
import rfc822
from urlparse import urlparse
from . import vcs
from . import utils
from .utils import option_splitlines, option_strip, conf_ensure_section

logger = logging.getLogger(__name__)


def rfc822_time(h):
    """Parse RFC 2822-formatted http header and return a time int."""
    rfc822.mktime_tz(rfc822.parsedate_tz(h))


class MainSoftware(object):
    """Placeholder to represent the main software instead of an addon location.

    Should just have a singleton instance: :data:`main_software`,
    whose meaning depends on the concrete recipe class using it.

    For example, in :class:`anybox.recipe.odoo.server.ServerRecipe`,
    :data:`main_software` represents the OpenObject server or the Odoo
    standard distribution.
    """

    def __str__(self):
        return 'Main Software'

main_software = MainSoftware()

GP_VCS_EXTEND_DEVELOP = 'vcs-extend-develop'
GP_DEVELOP_DIR = 'develop-dir'

WITH_ODOO_REQUIREMENTS_FILE_OPTION = 'apply-requirements-file'


def pip_version():
    import pip
    # we don't use pip or setuptools APIs for that to avoid going
    # in a swath of instability.
    # TODO we could try and use the version class from runtime.session
    # (has the advantage over pkf_resources' of direct transparent
    # comparison to tuples), but that'd introduced logical deps problems
    # that I don't want to solve right now.

    pip_version = pip.__version__
    # Naturally, pip has strictly conformed to PEP440, and does not use
    # version epochs, since at least v1.2. the oldest I could easily check
    # (we claim to support >= 1.4.1).
    # This equates all pre versions with the final one, and that's good
    # enough for current purposes:
    for suffix in ('a', 'b', 'rc', '.dev', '.post'):
        pip_version = pip_version.split(suffix)[0]
    return tuple(int(x) for x in pip_version.split('.'))


class BaseRecipe(object):
    """Base class for other recipes.

    It implements notably fetching of the main software part plus addons.

    The :attr:`sources` attribute is a ``dict`` storing how to fetch the main
    software part and the specified addons, with the following structure:

       ``local path -> (type, location_spec, options)``, in which:

       :local path: is either the :data:`main_software` singleton
                    (see :class:`MainSoftware`) or a local path to an
                    addons directory.
       :type: can be either

              * ``'local'``
              * ``'downloadable'``
              * one of the supported vcs

       :location_spec: is, depending on the type, a tuple specifying how
                       fetch is to be done:
{'fraction_non_alphanumeric': 0.07336819025130713, 'fraction_numerical': 0.008433125316242199, 'mean_word_length': 3.5060790273556233, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5800341', 'n_tokens_mistral': 1764, 'n_tokens_neox': 1658, 'n_words': 640}