Skip to content

Instantly share code, notes, and snippets.

@jedie
Created July 19, 2013 21:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jedie/6042398 to your computer and use it in GitHub Desktop.
Save jedie/6042398 to your computer and use it in GitHub Desktop.
change django url syntax
#!/usr/bin/python
# coding: UTF-8
""" origin from: https://github.com/futurecolors/django-future-url/blob/master/django_future_url/core.py
"""
import re
import os
import logging
import difflib
log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)
log.handlers = [logging.StreamHandler()] # setting would be import more than one time
CURRENT_PATH = os.path.abspath('.')
file_formats = ['.html', '.txt']
re_flags = re.I | re.X | re.U
# Deprecated url tag
r_depr_url_finder = re.compile(r" {% \s* url \s+ [^\"\'\s]+ \s+ ", re_flags)
# And url tag
r_url_finder = re.compile(r"{% \s* url \s+ ", re_flags)
# {% load url from future %}
r_load_finder = re.compile(r" {% \s* load \s+ url \s+ from \s+ future \s* %} ", re_flags)
# {% extends ... %} tag
r_extends_finder = re.compile(r"{% \s* extends \s* \S+ \s* %}", re_flags)
# Modernizing url tag replace pattern
r_url_pattern = re.compile(r"""
(?P<before> {% \s*
url \s+ )
(?P<name> \S+ )
(?P<attrs> \s+ .*? )
(?P<after> \s* %} )
""", re_flags)
# Add load from future after extends
r_load_extends_pattern = re.compile(
r"(?P<template_head> [\s\S]* {% \s* extends \s* \S+ \s* %} )",
re_flags | re.M,
)
# Adding load tag pattern
r_load_extends_replace = """\g<template_head>\n\n%s\n""" % load_tag
def display_plaintext_diff(content1, content2):
"""
Display a diff.
"""
content1 = content1.splitlines()
content2 = content2.splitlines()
diff = difflib.Differ().compare(content1, content2)
def is_diff_line(line):
for char in ("-", "+", "?"):
if line.startswith(char):
return True
return False
print "line | text\n-------------------------------------------"
old_line = ""
in_block = False
old_lineno = lineno = 0
for line in diff:
if line.startswith(" ") or line.startswith("+"):
lineno += 1
if old_lineno == lineno:
display_line = "%4s | %s" % ("", line.rstrip())
else:
display_line = "%4s | %s" % (lineno, line.rstrip())
if is_diff_line(line):
if not in_block:
print "..."
# Display previous line
print old_line
in_block = True
print display_line
else:
if in_block:
# Display the next line aber a diff-block
print display_line
in_block = False
old_line = display_line
old_lineno = lineno
print "..."
def make_me_magic(write):
""" Main script.
Here we find templates, replace old-style url tags and add future import where necessary.
"""
# Search for files with appropriate extensions.
log.info('Files needing modification:')
found = False
for file_path in find_files(os.walk(CURRENT_PATH)):
#log.debug(file_path)
with open(file_path, 'r+') as t_file:
file_content = t_file.read()
# Checking for presence of old-style tags and absence of load url from future
if has_deprecated_tag(file_content):
found = True
log.info(file_path.replace(CURRENT_PATH + '/', ''))
new_content = parse_file(file_content)
display_plaintext_diff(file_content, new_content)
if write:
t_file.seek(0)
t_file.write(new_content)
log.info(' File updated')
if not found:
log.info('All files are up to date. Congrats!')
else:
if not write:
log.info('No actual changes made. Run future_url --write to fix files right now.')
def find_files(paths):
for dirpath, _, filenames in paths:
for path in search_template_files(dirpath, filenames):
yield path
def parse_file(file_content):
if not has_deprecated_tag(file_content):
return file_content
# Handle files with deprecated url tags
if r_depr_url_finder.search(file_content):
if check_comma_in_attributes(file_content):
log.warn(" Comma separated attributes in url tag are no longer supported.")
file_content = process_url_tag(file_content)
return file_content
def url_replacer(match):
""" Handle single url tag. """
matches = match.groupdict()
if ',' in match.group('attrs'):
matches['attrs'] = re.sub('\s*,\s*', ' ', match.group('attrs'))
repl = "{before}'{name}'{attrs}{after}".format(**matches)
logging.info(" Proposed replace: {0} -> {1}".format(match.group(0), repl))
return repl
def process_url_tag(html):
""" Modernize url tag. """
return r_url_pattern.sub(url_replacer, html)
def check_comma_in_attributes(html):
""" Attributes of url tag can't be separated by comma. """
search = r_url_pattern.search(html)
return ',' in search.group('attrs')
def has_deprecated_tag(html):
""" Check if html needs modernizing. """
# File is already up-to-date
has_load_tag = r_load_finder.search(html)
# No load tag and (deprecated) url tag present
return not has_load_tag and (r_depr_url_finder.search(html) or r_url_finder.search(html))
def search_template_files(dirname, fnames):
""" Search for suitable files """
for file_name in fnames:
if os.path.splitext(file_name)[1] in file_formats:
yield os.path.join(dirname, file_name)
make_me_magic(write=False)
#make_me_magic(write=True)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment