
COMPATIBLE_VERSIONS = (
    (1, 4),
    (1, 7),
    (1, 8),
    (1, 9),
    (1, 10),
)

COMPATIBLE_OBJECTS = [
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'get_model',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'get_model_name',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'get_user_model',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'get_username_field',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'import_string',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': True,
        'name': 'commit',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': True,
        'name': 'rollback',
        'notes': 'Transaction savepoint (sid) is required for Django < 1.8'
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'url',
        'notes': 'Function used in `urlpatterns`',
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'user_model_label',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9)],
        'incompatible_versions': [(1, 10)],
        'issues_versions': [],
        'is_tested': False,
        'name': 'patterns',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'include',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'handler404',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'handler500',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'get_ident',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'urlparse',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'parse_qs',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'urlunparse',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'urlencode',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'unquote_plus',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': True,
        'name': 'DjangoJSONEncoder',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': True,
        'name': 'JsonResponse',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'HttpResponseBase',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'python_2_unicode_compatible',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'URLValidator',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'EmailValidator',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'View',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'StringIO',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'BytesIO',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'clean_manytomany_helptext',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'smart_text',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'force_text',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'simplejson',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': True,
        'name': 'import_module',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'VariableNode',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'slugify',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'SortedDict',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'atomic',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': True,
        'name': 'commit_on_success',
        'notes': '`commit_on_success` replaced by `atomic` in Django >= 1.8'
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': True,
        'name': 'format_html',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9)],
        'incompatible_versions': [],
        'issues_versions': [(1, 10)],
        'is_tested': True,
        'name': 'resolve_url',
        'notes': '1.10: Reversing by dotted path has been removed'
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'close_connection',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8),],
        'incompatible_versions': [(1, 9), (1, 10)],
        'issues_versions': [],
        'is_tested': False,
        'name': 'add_to_builtins',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': True,
        'name': 'get_template_loaders',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': True,
        'name': 'render_to_string',
        'notes': 'The new function signature (https://docs.djangoproject.com/en/1.9/releases/1.8/#dictionary-and-context-instance-arguments-of-rendering-functions) is backported to pre-1.8.',
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8),],
        'incompatible_versions': [(1, 9), (1, 10)],
        'issues_versions': [],
        'is_tested': False,
        'name': 'GenericForeignKey',
        'notes': ''
    },
    {

        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'module': 'models',
        'name': 'GenericForeignKey',
        'notes': ''
    },
    {

        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': True,
        'module': 'templatetags.compat',
        'name': 'url',
        'notes': 'Templatetag; import with `{% load url from compat %}`',
    },
    {
        'compatible_versions': [(1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [(1, 4)],
        'is_tested': True,
        'module': 'templatetags.compat',
        'name': 'verbatim',
        'notes': 'Templatetag; import with `{% load verbatim from compat %}`. 1.4: Does not allow specific closing '
                 'tags, e.g. `{% endverbatim myblock %}`, and does not preserve whitespace inside tags.',
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'urlresolvers',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'get_current_site',
        'notes': ''
    },
    {
        'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
        'incompatible_versions': [],
        'issues_versions': [],
        'is_tested': False,
        'name': 'admin_utils',
        'notes': ''
    }
]

# django.core.urlresolvers will be moved to django.urls in 1.10
for urlresolvers_import in [
    'LocaleRegexProvider', 'LocaleRegexURLResolver', 'NoReverseMatch', 'RegexURLPattern', 'RegexURLResolver',
    'Resolver404', 'ResolverMatch', 'clear_url_caches', 'get_callable', 'get_mod_func', 'get_ns_resolver',
    'get_resolver', 'get_script_prefix', 'get_urlconf', 'is_valid_path', 'resolve', 'reverse', 'reverse_lazy',
    'set_script_prefix', 'set_urlconf',
]:
    COMPATIBLE_OBJECTS.append({
            'compatible_versions': [(1, 4), (1, 7), (1, 8), (1, 9), (1, 10)],
            'incompatible_versions': [],
            'issues_versions': [],
            'is_tested': False,
            'name': urlresolvers_import,
            'notes': ''
    })


def is_compatible(object_name, version, module=''):
    for object in COMPATIBLE_OBJECTS:
        if (object['name'] == object_name and
                    version in object['compatible_versions'] and
                    object.get('module', '') == module):
            return True
    return False


# https://guides.github.com/features/mastering-markdown/#GitHub-flavored-markdown
def get_compatible_objects_as_markdown():

    def _version_str(version):
        return '.'.join(map(lambda n:str(n), version))

    def _render_row(row):
        return '|' + '|'.join(row) + '|'

    def _get_row(object):
        name = object['module'] + '.' + object['name'] if 'module' in object else object['name']
        row = ['`' + name + '`']
        if object['is_tested']:
            row.append(':heavy_check_mark:')
        else:
            row.append(':heavy_multiplication_x:')
        for version in COMPATIBLE_VERSIONS:
            if version in object['compatible_versions']:
                row.append(':heavy_check_mark:')
            elif version in object['issues_versions']:
                row.append(':warning:')
            elif version in object['incompatible_versions']:
                row.append(':x:')
            else:
                row.append(':heavy_multiplication_x:')
        row += [object['notes']]
        return _render_row(row)

    def _get_header_line(num_columns):
        return '|' + '|'.join(['---' for i in range(num_columns)]) + '|'

    header_row = (['Compatible object', 'Specifically tested'] +
                  [_version_str(v) for v in COMPATIBLE_VERSIONS] +
                  ['Notes'])
    num_columns = len(header_row)
    rows = ([_render_row(header_row), _get_header_line(num_columns)] +
            [_get_row(o) for o in sorted(COMPATIBLE_OBJECTS, key=lambda o: o['name'])])
    return '\n'.join(rows)

if __name__ == '__main__':
    print(get_compatible_objects_as_markdown())
