#!/usr/bin/python3 -B

# update-pyflakes-tags -- update Lintian data about pyflakes tags
#
# Copyright © 2011, 2012, 2013, 2014 Jakub Wilk
#
# This program is free software.  It is distributed under the terms of the GNU
# General Public License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# this program.  If not, you can find it on the World Wide Web at
# http://www.gnu.org/copyleft/gpl.html, or write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.

import argparse
import ast
import os
import re
import sys

import debian.deb822 as deb822

if sys.version_info > (3,):
    if not sys.flags.dont_write_bytecode:
        raise RuntimeError('cowardly refusing to import Python 2.X modules')
    # Close your eyes here.
    sys.path += ['/usr/share/pyshared']
    import pyflakes
    del sys.path[-1]
    # You can open your eyes now.

import pyflakes.messages as messages

import misc

def extract_blacklist(node):
    for child in ast.iter_child_nodes(node):
        if not isinstance(child, ast.Assign):
            continue
        try:
            [target] = child.targets
        except ValueError:
            continue
        if not isinstance(target, ast.Name):
            continue
        if target.id != 'blacklist':
            continue
        return ast.literal_eval(child.value)
    raise NotImplementedError

def main():
    ap = argparse.ArgumentParser()
    ap.add_argument('--dry-run', action='store_true')
    options = ap.parse_args()
    os.chdir(misc.root)
    filename = 'helpers/python/pyflakes'
    with open(filename, 'r', encoding='UTF-8') as file:
        contents = file.read()
        node = ast.parse(contents, filename=filename)
        blacklist = set(extract_blacklist(node))
    tags = {}
    for cls in messages.Message.__subclasses__():
        tag = 'pyflakes' + re.sub('[A-Z]', lambda m: '-' + m.group(0).lower(), cls.__name__)
        if tag.split('-', 1)[1] in blacklist:
            continue
        description = (cls.message
            .replace('line %r', 'line <i>n</i>')
            .replace('%r', '<i>var</i>')
            .replace('%s', '<i>var</i>')
        )
        tags[tag] = description
    t = 'pyflakes-undefined-name'
    assert t in tags
    tags[t + '-underscore'] = tags[t]
    del t
    old_tags = {}
    desc_path = 'checks/python/pyflakes.desc'
    first = True
    with open('checks/python/pyflakes.desc', 'r', encoding='UTF-8') as file:
        for para in deb822.Deb822.iter_paragraphs(file):
            if first:
                first_para = para
            else:
                old_tags[para['tag']] = para
            first = False
    if set(tags) == set(old_tags):
        print('{path} is up-to-date'.format(path=desc_path), file=sys.stderr)
        sys.exit(0)
    elif options.dry_run:
        print('{path} is not up-to-date'.format(path=desc_path), file=sys.stderr)
        sys.exit(1)
    first = True
    with open(desc_path, 'w', encoding='UTF-8') as file:
        file.write(str(first_para))
        for tag, description in sorted(tags.items()):
            try:
                para = old_tags[tag]
            except LookupError:
                para = deb822.Deb822()
                para['Tag'] = tag
                para['Severity'] = 'wishlist'
                para['Certainty'] = 'wild-guess'
                para['Experimental'] = 'yes'
                para['Info'] = 'pyflakes emitted the following message:\n  ' + description
            file.write('\n')
            file.write(str(para))
            first = False
    print('{path} has been updated'.format(path=desc_path), file=sys.stderr)
    sys.exit(1)

if __name__ == '__main__':
    main()

# Local Variables:
# indent-tabs-mode: nil
# End:
# vim: syntax=python sw=4 sts=4 sr et
