# -*- coding: utf-8 -*-
"""Implementation of pydocstyle integration with Flake8.

pydocstyle docstrings convention needs error code and class parser for be
included as module into flake8
"""

import sys
try:
    import pydocstyle as pep257
    module_name = 'pydocstyle'
except ImportError:
    import pep257
    module_name = 'pep257'

if sys.version_info >= (3, 2):
    from tokenize import open as tokenize_open
else:
    tokenize_open = open

__version__ = '1.4.0'
__all__ = ('pep257Checker',)


class _ContainsAll(object):
    def __contains__(self, code):  # type: (str) -> bool
        return True


class EnvironError(pep257.Error):

    def __init__(self, err):
        super(EnvironError, self).__init__(
            code='D998',
            short_desc='EnvironmentError: ' + str(err),
            context=None,
        )

    @property
    def line(self):
        """Return 0 as line number for EnvironmentError."""
        return 0


class AllError(pep257.Error):

    def __init__(self, err):
        super(AllError, self).__init__(
            code='D999',
            short_desc=str(err).partition('\n')[0],
            context=None,
        )

    @property
    def line(self):
        """pep257.AllError does not contain line number. Return 0 instead."""
        return 0


class pep257Checker(object):
    """Flake8 needs a class to check python file."""

    name = 'flake8-docstrings'
    version = '{}, {}: {}'.format(__version__, module_name, pep257.__version__)

    def __init__(self, tree, filename, lines):
        """Placeholder."""
        self.tree = tree
        self.filename = filename
        self.checker = pep257.ConventionChecker()
        self.source = ''.join(lines)

    @classmethod
    def add_options(cls, parser):
        """Add plugin configuration option to flake8."""
        parser.add_option(
            '--docstring-convention', action='store', parse_from_config=True,
            default="pep257", choices=sorted(pep257.conventions) + ['all'],
            help=(
                "pydocstyle docstring convention, default 'pep257'. "
                "Use the special value 'all' to enable all codes (note: "
                "some codes are conflicting so you'll need to then exclude "
                "those)."
            )
        )

    @classmethod
    def parse_options(cls, options):
        """Parse the configuration options given to flake8."""
        cls.convention = options.docstring_convention

    def _check_source(self):
        try:
            # TODO: Naive fix for `pydocstyle 2.0.0` with default settings.
            # Should probably add a proper setting so `ignore_decorators` can
            # be set when calling through the CLI
            for err in self.checker.check_source(
                self.source,
                self.filename,
                ignore_decorators=None,
            ):
                yield err
        except pep257.AllError as err:
            yield AllError(err)
        except EnvironmentError as err:
            yield EnvironError(err)

    def run(self):
        """Use directly check() api from pydocstyle."""
        if self.convention == 'all':
            checked_codes = _ContainsAll()
        else:
            checked_codes = (
                pep257.conventions[self.convention] | {'D998', 'D999'}
            )
        for error in self._check_source():
            if isinstance(error, pep257.Error) and error.code in checked_codes:
                # NOTE(sigmavirus24): Fixes GitLab#3
                message = '%s %s' % (error.code, error.short_desc)
                yield (error.line, 0, message, type(self))

@@ -185,16 +185,45 @@
 e8%0A%22%22%22%0A%0A
+from re import compile as re%0A
 import s
@@ -2302,24 +2302,539 @@
  )%0A        )
+%0A        parser.add_option(%0A            %22--ignore-decorators%22,%0A            action=%22store%22,%0A            parse_from_config=True,%0A            default=None,%0A            help=(%0A                %22pydocstyle ignore-decorators regular expression, %22%0A                %22default None. %22%0A                %22Ignore any functions or methods that are decorated by %22%0A                %22a function with a name fitting this regular expression. %22%0A                %22The default is not ignore any decorated functions. %22%0A            ),%0A        )
 %0A%0A    @class
@@ -2998,182 +2998,95 @@
 ion%0A
-%0A
     
-def _check_source(self):%0A        try:%0A            # TODO: Naive fix for %60pydocstyle 2.0.0%60 with default settings.%0A            # Should probably add a proper setting so %60
+    cls.ignore_decorators = (%0A            re(options.ignore_decorators) if options.
 igno
@@ -3102,13 +3102,8 @@
 tors
-%60 can
 %0A   
@@ -3115,45 +3115,70 @@
     
-# be set when calling through the CLI
+else None%0A        )%0A%0A    def _check_source(self):%0A        try:
 %0A   
@@ -3318,20 +3318,38 @@
 orators=
-None
+self.ignore_decorators
 ,%0A      

Implement --ignore-decorators option