Created
July 19, 2013 21:14
-
-
Save jedie/6042398 to your computer and use it in GitHub Desktop.
change django url syntax
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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