<commit_before>import sublime
import sublime_plugin
import re
import os.path
import pprint
import sys
from urllib.parse import quote
from bs4 import BeautifulSoup

# for dbug
pp = pprint.PrettyPrinter(indent=4)

# Load MarkdownPreview module
mp_module_name = 'Markdown Preview.MarkdownPreview'
try:
    MarkdownPreview = sys.modules[mp_module_name]
except KeyError:
    print("Module not found: %s" % mp_module_name)

pattern_reference_link = re.compile(r'\[.+?\]$') # [Heading][my-id]
pattern_link = re.compile(r'\[(.+?)\]\(.+?\)')  # [link](http://www.sample.com/)
pattern_ex_id = re.compile(r'\{#.+?\}$')         # [Heading]{#my-id}
pattern_tag = re.compile(r'<.*?>')
pattern_anchor = re.compile(r'\s*')
pattern_toc_tag_start = re.compile(r'')

pattern_h1_h2_equal_dash = "^.*?(?:(?:\r\n)|\n|\r)(?:-+|=+)$"

TOCTAG_START = ""
TOCTAG_END = ""

class MarkdowntocInsert(sublime_plugin.TextCommand):

    def run(self, edit):

        if not self.find_tag_and_insert(edit):
            sels = self.view.sel()
            for sel in sels:
                attrs = self.get_settings()

                # add TOCTAG
                toc = TOCTAG_START + "\n"
                toc += "\n"
                toc += self.get_toc(attrs, sel.end(), edit)
                toc += "\n"
                toc += TOCTAG_END + "\n"

                self.view.insert(edit, sel.begin(), toc)
                self.log('inserted TOC')

        # TODO: process to add another toc when tag exists

    def get_toc_open_tag(self):
        search_results = self.view.find_all(
            "^\n",
            sublime.IGNORECASE)
        search_results = self.remove_items_in_codeblock(search_results)

        toc_open_tags = []
        for toc_open in search_results:
            if 0 < len(toc_open):

                toc_open_tag = {"region": toc_open}

                # settings in user settings
                settings_user = self.get_settings()

                # settings in tag
                tag_str = self.view.substr(toc_open)
                settings_tag = self.get_attibutes_from(tag_str)

                # merge
                toc_open_tag.update(settings_user)
                toc_open_tag.update(settings_tag)

                toc_open_tags.append(toc_open_tag)

        return toc_open_tags

    def get_toc_close_tag(self, start):
        close_tags = self.view.find_all("^" + TOCTAG_END + "\n")
        close_tags = self.remove_items_in_codeblock(close_tags)
        for close_tag in close_tags:
            if start < close_tag.begin():
                return close_tag

    def find_tag_and_insert(self, edit):
        """Search MarkdownTOC comments in document"""
        toc_starts = self.get_toc_open_tag()
        for dic in toc_starts:

            toc_start = dic["region"]
            if 0 < len(toc_start):

                toc_close = self.get_toc_close_tag(toc_start.end())

                if toc_close:
                    toc = self.get_toc(dic, toc_close.end(), edit)
                    tocRegion = sublime.Region(
                        toc_start.end(), toc_close.begin())
                    if toc:
                        self.view.replace(edit, tocRegion, "\n" + toc + "\n")
                        self.log('refresh TOC content')
                        return True
                    else:
                        self.view.replace(edit, tocRegion, "\n")
                        self.log('TOC is empty')
                        return False
        self.log('cannot find TOC tags')
        return False

    # TODO: add "end" parameter
    def get_toc(self, attrs, begin, edit):

        def heading_to_id(heading):
            if heading is None:
                return ''
            if strtobool(attrs['delegate_to_markdown_preview']):
                _h1 = MarkdownPreview.GithubCompiler().postprocess_inject_header_id('
%s
' % heading)
                pattern = r'
.*
'
                matchs = re.finditer(pattern, _h1)
                for match in matchs:
                    print(match.groups()[0])
                    _id = match.groups()[0]
            else:
                if strtobool(attrs['lowercase_only_ascii']):
                    # only ascii
                    _id = ''.join(chr(ord(x)+('A'<=x<='Z')*32) for x in heading)
                else:
                    _id = heading.lower()
            return replace_strings_in_id(_id)

        def replace_strings_in_id(_str):
            replacements = self.get_setting('id_replacements')
            for _key in replacements:
                _substitute = _key
                _targets = replacements[_key]
                for _target in _targets:
                    _str = _str.replace(_target, _substitute)
            return _str

        # Search headings in docment
        pattern_hash = "^#+?[^#]"
        headings = self.view.find_all(
            "%s|%s" % (pattern_h1_h2_equal_dash, pattern_hash))

        headings = self.remove_items_in_codeblock(headings)

        if len(headings) < 1:
            return ''

        items = []  # [[headingNum,text,position,anchor_id],...]
        for heading in headings:
            if begin < heading.end():
                lines = self.view.lines(heading)
                if len(lines) == 1:
                    # handle hash headings, ### chapter 1
                    r = sublime.Region(
                        heading.end() - 1, self.view.line(heading).end())
                    text = self.view.substr(r).strip().rstrip('#')
                    indent = heading.size() - 1
                    items.append([indent, text, heading.begin()])
                elif len(lines) == 2:
                    # handle - or + headings, Title 1==== section1----
                    text = self.view.substr(lines[0])
                    if text.strip():
                        indent = 1 if (
                            self.view.substr(lines[1])[0] == '=') else 2
                        items.append([indent, text, heading.begin()])

        if len(items) < 1:
            return ''

        # Shape TOC  ------------------
        items = format(items)

        # Depth limit  ------------------
        _depth = int(attrs['depth'])
        if 0 < _depth:
            items = list(filter((lambda i: i[0] <= _depth), items))

        # Create TOC  ------------------
        toc = ''
        _ids = []
        level_counters = [0]

        for item in items:
            _id = None
            _indent = item[0] - 1
            _text = item[1]
            _text = pattern_tag.sub('', _text) # remove html tags
            _text = _text.rstrip() # remove end space

            # Ignore links: e.g. '[link](http://sample.com/)' -> 'link'
            _text = pattern_link.sub('\\1', _text)

            # Add indent
            for i in range(_indent):
                _prefix = attrs['indent']
                # Support escaped characters like '\t'
                _prefix = _prefix.encode().decode('unicode-escape')
                toc += _prefix

            # Reference-style links: e.g. '# heading [my-anchor]'
            list_reference_link = list(pattern_reference_link.finditer(_text))

            # Markdown-Extra special attribute style: e.g. '# heading {#my-anchor}'
            match_ex_id = pattern_ex_id.search(_text)

            if len(list_reference_link):
                match = list_reference_link[-1]
                _text = _text[0:match.start()].replace('[','').replace(']','').rstrip()
                _id = match.group().replace('[','').replace(']','')
            elif match_ex_id:
                _text = _text[0:match_ex_id.start()].rstrip()
                _id = match_ex_id.group().replace('{#','').replace('}','')
            elif strtobool(attrs['autolink']):
                _id = heading_to_id(_text)
                if strtobool(attrs['uri_encoding']):
                    _id = quote(_id)

                _ids.append(_id)
                n = _ids.count(_id)
                if 1 < n:
                    _id += '-' + str(n-1)

            if attrs['style'] == 'unordered':
                list_prefix = '- '
            elif attrs['style'] == 'ordered':
                list_prefix = '1. '

            # escape brackets
            _text = _text\
                        .replace('(','\(')\
                        .replace(')','\)')\
                        .replace('[','\[')\
                        .replace(']','\]')

            if _id == None:
                toc += list_prefix + _text + '\n'
            elif attrs['bracket'] == 'round':
                toc += list_prefix + '[' + _text + '](#' + _id + ')\n'
            else:
                toc += list_prefix + '[' + _text + '][' + _id + ']\n'

            item.append(_id)

        self.update_anchors(edit, items, strtobool(attrs['autoanchor']))

        return toc

    def update_anchors(self, edit, items, autoanchor):
        """Inserts, updates or deletes a link anchor in the line before each header."""
        v = self.view
        # Iterate in reverse so that inserts don't affect the position
        for item in reversed(items):
            anchor_region = v.line(item[2] - 1)  # -1 to get to previous line
            is_update = pattern_anchor.match(v.substr(anchor_region))
            if autoanchor:
                if is_update:
                    new_anchor = ''.format(item[3])
                    v.replace(edit, anchor_region, new_anchor)
                else:
                    new_anchor = '\n'.format(item[3])
                    v.insert(edit, anchor_region.end(), new_anchor)

            else:
                if is_update:
                    v.erase(edit, sublime.Region(anchor_region.begin(), anchor_region.end() + 1))

    def get_setting(self, attr):
        settings = sublime.load_settings('MarkdownTOC.sublime-settings')
        return settings.get(attr)

    def get_settings(self):
        """return dict of settings"""
        settings = sublime.load_settings("MarkdownTOC.sublime-settings")
        files = sublime.find_resources("MarkdownTOC.sublime-settings")

        for file in files:
            try:
                for key in sublime.decode_value(sublime.load_resource(file)):
                    settings.erase(key)
            except:
                print("Error Loading settings file")
        self.log('settings')
        self.log(settings)
        return {
            "autoanchor":                   self.get_setting('default_autoanchor'),
            "autolink":                     self.get_setting('default_autolink'),
            "bracket":                      self.get_setting('default_bracket'),
            "depth":                        self.get_setting('default_depth'),
            "indent":                       self.get_setting('default_indent'),
            "lowercase_only_ascii":         self.get_setting('default_lowercase_only_ascii'),
            "style":                        self.get_setting('default_style'),
            "uri_encoding":                 self.get_setting('default_uri_encoding'),
            "delegate_to_markdown_preview": self.get_setting('default_delegate_to_markdown_preview')
        }

    def get_attibutes_from(self, tag_str):
        """return dict of settings from tag_str"""

        tag_str_html = pattern_toc_tag_start.sub("<", tag_str)
        tag_str_html = pattern_toc_tag_start.sub(">", tag_str_html)

        soup = BeautifulSoup(tag_str_html, "html.parser")

        return soup.find('markdowntoc').attrs

    def remove_items_in_codeblock(self, items):

        codeblocks = self.view.find_all("^\s*`{3,}[^`]*$")
        codeblockAreas = [] # [[area_begin, area_end], ..]
        i = 0
        while i < len(codeblocks)-1:
            area_begin = codeblocks[i].begin()
            area_end   = codeblocks[i+1].begin()
            if area_begin and area_end:
                codeblockAreas.append([area_begin, area_end])
            i += 2

        items = [h for h in items if is_out_of_areas(h.begin(), codeblockAreas)]
        return items

    def log(self, arg):
        if self.get_setting('logging') == True:
            arg = str(arg)
            sublime.status_message(arg)
            pp.pprint(arg)

def is_out_of_areas(num, areas):
    for area in areas:
        if area[0] < num and num < area[1]:
            return False
    return True

def format(items):
    headings = []
    for item in items:
        headings.append(item[0])
    # --------------------------

    # minimize diff between headings -----
    _depths = list(set(headings)) # sort and unique
    # replace with depth rank
    for i, item in enumerate(headings):
        headings[i] = _depths.index(headings[i])+1
    # ----- /minimize diff between headings

    # --------------------------
    for i, item in enumerate(items):
        item[0] = headings[i]
    return items

def strtobool(val):
    """pick out from 'distutils.util' module"""
    if isinstance(val, str):
        val = val.lower()
        if val in ('y', 'yes', 't', 'true', 'on', '1'):
            return 1
        elif val in ('n', 'no', 'f', 'false', 'off', '0'):
            return 0
        else:
            raise ValueError("invalid truth value %r" % (val,))
    else:
        return bool(val)

# Search and refresh if it's exist

class MarkdowntocUpdate(MarkdowntocInsert):

    def run(self, edit):
        MarkdowntocInsert.find_tag_and_insert(self, edit)

class AutoRunner(sublime_plugin.EventListener):

    def on_pre_save(self, view):
        # limit scope
        root, ext = os.path.splitext(view.file_name())
        ext = ext.lower()
        if ext in [".md", ".markdown", ".mdown", ".mdwn", ".mkdn", ".mkd", ".mark"]:
            view.run_command('markdowntoc_update')
<commit_msg>Cleanup<commit_after>import sublime
import sublime_plugin
import re
import os.path
import pprint
import sys
from urllib.parse import quote
from bs4 import BeautifulSoup

# for dbug
pp = pprint.PrettyPrinter(indent=4)

# Load MarkdownPreview module
mp_module_name = 'Markdown Preview.MarkdownPreview'
try:
    MarkdownPreview = sys.modules[mp_module_name]
except KeyError:
    print("Module not found: %s" % mp_module_name)

pattern_reference_link = re.compile(r'\[.+?\]$') # [Heading][my-id]
pattern_link = re.compile(r'\[(.+?)\]\(.+?\)')  # [link](http://www.sample.com/)
pattern_ex_id = re.compile(r'\{#.+?\}$')         # [Heading]{#my-id}
pattern_tag = re.compile(r'<.*?>')
pattern_anchor = re.compile(r'\s*')
pattern_toc_tag_start = re.compile(r'')

pattern_h1_h2_equal_dash = "^.*?(?:(?:\r\n)|\n|\r)(?:-+|=+)$"

TOCTAG_START = ""
TOCTAG_END = ""

class MarkdowntocInsert(sublime_plugin.TextCommand):

    def run(self, edit):

        if not self.find_tag_and_insert(edit):
            sels = self.view.sel()
            for sel in sels:
                attrs = self.get_settings()

                # add TOCTAG
                toc = TOCTAG_START + "\n"
                toc += "\n"
                toc += self.get_toc(attrs, sel.end(), edit)
                toc += "\n"
                toc += TOCTAG_END + "\n"

                self.view.insert(edit, sel.begin(), toc)
                self.log('inserted TOC')

        # TODO: process to add another toc when tag exists

    def get_toc_open_tag(self):
        search_results = self.view.find_all(
            "^\n",
            sublime.IGNORECASE)
        search_results = self.remove_items_in_codeblock(search_results)

        toc_open_tags = []
        for toc_open in search_results:
            if 0 < len(toc_open):

                toc_open_tag = {"region": toc_open}

                # settings in user settings
                settings_user = self.get_settings()

                # settings in tag
                tag_str = self.view.substr(toc_open)
                settings_tag = self.get_attibutes_from(tag_str)

                # merge
                toc_open_tag.update(settings_user)
                toc_open_tag.update(settings_tag)

                toc_open_tags.append(toc_open_tag)

        return toc_open_tags

    def get_toc_close_tag(self, start):
        close_tags = self.view.find_all("^" + TOCTAG_END + "\n")
        close_tags = self.remove_items_in_codeblock(close_tags)
        for close_tag in close_tags:
            if start < close_tag.begin():
                return close_tag

    def find_tag_and_insert(self, edit):
        """Search MarkdownTOC comments in document"""
        toc_starts = self.get_toc_open_tag()
        for dic in toc_starts:

            toc_start = dic["region"]
            if 0 < len(toc_start):

                toc_close = self.get_toc_close_tag(toc_start.end())

                if toc_close:
                    toc = self.get_toc(dic, toc_close.end(), edit)
                    tocRegion = sublime.Region(
                        toc_start.end(), toc_close.begin())
                    if toc:
                        self.view.replace(edit, tocRegion, "\n" + toc + "\n")
                        self.log('refresh TOC content')
                        return True
                    else:
                        self.view.replace(edit, tocRegion, "\n")
                        self.log('TOC is empty')
                        return False
        self.log('cannot find TOC tags')
        return False

    # TODO: add "end" parameter
    def get_toc(self, attrs, begin, edit):

        def heading_to_id(heading):
            if heading is None:
                return ''
            if strtobool(attrs['delegate_to_markdown_preview']):
                _h1 = MarkdownPreview.GithubCompiler().postprocess_inject_header_id('
%s
' % heading)
                pattern = r'
.*
'
                matchs = re.finditer(pattern, _h1)
                for match in matchs:
                    _id = match.groups()[0]
            else:
                if strtobool(attrs['lowercase_only_ascii']):
                    # only ascii
                    _id = ''.join(chr(ord(x)+('A'<=x<='Z')*32) for x in heading)
                else:
                    _id = heading.lower()
            return replace_strings_in_id(_id)

        def replace_strings_in_id(_str):
            replacements = self.get_setting('id_replacements')
            for _key in replacements:
                _substitute = _key
                _targets = replacements[_key]
                for _target in _targets:
                    _str = _str.replace(_target, _substitute)
            return _str

        # Search headings in docment
        pattern_hash = "^#+?[^#]"
        headings = self.view.find_all(
            "%s|%s" % (pattern_h1_h2_equal_dash, pattern_hash))

        headings = self.remove_items_in_codeblock(headings)

        if len(headings) < 1:
            return ''

        items = []  # [[headingNum,text,position,anchor_id],...]
        for heading in headings:
            if begin < heading.end():
                lines = self.view.lines(heading)
                if len(lines) == 1:
                    # handle hash headings, ### chapter 1
                    r = sublime.Region(
                        heading.end() - 1, self.view.line(heading).end())
                    text = self.view.substr(r).strip().rstrip('#')
                    indent = heading.size() - 1
                    items.append([indent, text, heading.begin()])
                elif len(lines) == 2:
                    # handle - or + headings, Title 1==== section1----
                    text = self.view.substr(lines[0])
                    if text.strip():
                        indent = 1 if (
                            self.view.substr(lines[1])[0] == '=') else 2
                        items.append([indent, text, heading.begin()])

        if len(items) < 1:
            return ''

        # Shape TOC  ------------------
        items = format(items)

        # Depth limit  ------------------
        _depth = int(attrs['depth'])
        if 0 < _depth:
            items = list(filter((lambda i: i[0] <= _depth), items))

        # Create TOC  ------------------
        toc = ''
        _ids = []
        level_counters = [0]

        for item in items:
            _id = None
            _indent = item[0] - 1
            _text = item[1]
            _text = pattern_tag.sub('', _text) # remove html tags
            _text = _text.rstrip() # remove end space

            # Ignore links: e.g. '[link](http://sample.com/)' -> 'link'
            _text = pattern_link.sub('\\1', _text)

            # Add indent
            for i in range(_indent):
                _prefix = attrs['indent']
                # Support escaped characters like '\t'
                _prefix = _prefix.encode().decode('unicode-escape')
                toc += _prefix

            # Reference-style links: e.g. '# heading [my-anchor]'
            list_reference_link = list(pattern_reference_link.finditer(_text))

            # Markdown-Extra special attribute style: e.g. '# heading {#my-anchor}'
            match_ex_id = pattern_ex_id.search(_text)

            if len(list_reference_link):
                match = list_reference_link[-1]
                _text = _text[0:match.start()].replace('[','').replace(']','').rstrip()
                _id = match.group().replace('[','').replace(']','')
            elif match_ex_id:
                _text = _text[0:match_ex_id.start()].rstrip()
                _id = match_ex_id.group().replace('{#','').replace('}','')
            elif strtobool(attrs['autolink']):
                _id = heading_to_id(_text)
                if strtobool(attrs['uri_encoding']):
                    _id = quote(_id)

                _ids.append(_id)
                n = _ids.count(_id)
                if 1 < n:
                    _id += '-' + str(n-1)

            if attrs['style'] == 'unordered':
                list_prefix = '- '
            elif attrs['style'] == 'ordered':
                list_prefix = '1. '

            # escape brackets
            _text = _text\
                        .replace('(','\(')\
                        .replace(')','\)')\
                        .replace('[','\[')\
                        .replace(']','\]')

            if _id == None:
                toc += list_prefix + _text + '\n'
            elif attrs['bracket'] == 'round':
                toc += list_prefix + '[' + _text + '](#' + _id + ')\n'
            else:
                toc += list_prefix + '[' + _text + '][' + _id + ']\n'

            item.append(_id)

        self.update_anchors(edit, items, strtobool(attrs['autoanchor']))

        return toc

    def update_anchors(self, edit, items, autoanchor):
        """Inserts, updates or deletes a link anchor in the line before each header."""
        v = self.view
        # Iterate in reverse so that inserts don't affect the position
        for item in reversed(items):
            anchor_region = v.line(item[2] - 1)  # -1 to get to previous line
            is_update = pattern_anchor.match(v.substr(anchor_region))
            if autoanchor:
                if is_update:
                    new_anchor = ''.format(item[3])
                    v.replace(edit, anchor_region, new_anchor)
                else:
                    new_anchor = '\n'.format(item[3])
                    v.insert(edit, anchor_region.end(), new_anchor)

            else:
                if is_update:
                    v.erase(edit, sublime.Region(anchor_region.begin(), anchor_region.end() + 1))

    def get_setting(self, attr):
        settings = sublime.load_settings('MarkdownTOC.sublime-settings')
        return settings.get(attr)

    def get_settings(self):
        """return dict of settings"""
        settings = sublime.load_settings("MarkdownTOC.sublime-settings")
        files = sublime.find_resources("MarkdownTOC.sublime-settings")

        for file in files:
            try:
                for key in sublime.decode_value(sublime.load_resource(file)):
                    settings.erase(key)
            except:
                print("Error Loading settings file")
        self.log('settings')
        self.log(settings)
        return {
            "autoanchor":                   self.get_setting('default_autoanchor'),
            "autolink":                     self.get_setting('default_autolink'),
            "bracket":                      self.get_setting('default_bracket'),
            "depth":                        self.get_setting('default_depth'),
            "indent":                       self.get_setting('default_indent'),
            "lowercase_only_ascii":         self.get_setting('default_lowercase_only_ascii'),
            "style":                        self.get_setting('default_style'),
            "uri_encoding":                 self.get_setting('default_uri_encoding'),
            "delegate_to_markdown_preview": self.get_setting('default_delegate_to_markdown_preview')
        }

    def get_attibutes_from(self, tag_str):
        """return dict of settings from tag_str"""

        tag_str_html = pattern_toc_tag_start.sub("<", tag_str)
        tag_str_html = pattern_toc_tag_start.sub(">", tag_str_html)

        soup = BeautifulSoup(tag_str_html, "html.parser")

        return soup.find('markdowntoc').attrs

    def remove_items_in_codeblock(self, items):

        codeblocks = self.view.find_all("^\s*`{3,}[^`]*$")
        codeblockAreas = [] # [[area_begin, area_end], ..]
        i = 0
        while i < len(codeblocks)-1:
            area_begin = codeblocks[i].begin()
            area_end   = codeblocks[i+1].begin()
            if area_begin and area_end:
                codeblockAreas.append([area_begin, area_end])
            i += 2

        items = [h for h in items if is_out_of_areas(h.begin(), codeblockAreas)]
        return items

    def log(self, arg):
        if self.get_setting('logging') == True:
            arg = str(arg)
            sublime.status_message(arg)
            pp.pprint(arg)

def is_out_of_areas(num, areas):
    for area in areas:
        if area[0] < num and num < area[1]:
            return False
    return True

def format(items):
    headings = []
    for item in items:
        headings.append(item[0])
    # --------------------------

    # minimize diff between headings -----
    _depths = list(set(headings)) # sort and unique
    # replace with depth rank
    for i, item in enumerate(headings):
        headings[i] = _depths.index(headings[i])+1
    # ----- /minimize diff between headings

    # --------------------------
    for i, item in enumerate(items):
        item[0] = headings[i]
    return items

def strtobool(val):
    """pick out from 'distutils.util' module"""
    if isinstance(val, str):
        val = val.lower()
        if val in ('y', 'yes', 't', 'true', 'on', '1'):
            return 1
        elif val in ('n', 'no', 'f', 'false', 'off', '0'):
            return 0
        else:
            raise ValueError("invalid truth value %r" % (val,))
    else:
        return bool(val)

# Search and refresh if it's exist

class MarkdowntocUpdate(MarkdowntocInsert):

    def run(self, edit):
        MarkdowntocInsert.find_tag_and_insert(self, edit)

class AutoRunner(sublime_plugin.EventListener):

    def on_pre_save(self, view):
        # limit scope
        root, ext = os.path.splitext(view.file_name())
        ext = ext.lower()
        if ext in [".md", ".markdown", ".mdown", ".mdwn", ".mkdn", ".mkd", ".mark"]:
            view.run_command('markdowntoc_update')
<|endoftext|>


<commit_before>import re
from django.conf import settings
from staticgenerator import StaticGenerator

from django_de.apps.documentation.utils import get_absolute_document_urls

class StaticGeneratorMiddleware(object):
    """
    This is a modification of the staticgenerator middleware.
    """
    urls = tuple([re.compile(r'^%s' % url) for url in get_absolute_document_urls()])

    def process_response(self, request, response):
        if response.status_code == 200:
            for url in self.urls:
                if url.match(request.path):
                    gen = StaticGenerator()
                    gen.publish_from_path(request.path, response.content)
                    break
        return response
<commit_msg>/ und /documentation/ werden jetzt auch statisch, basta<commit_after>import re
from django.conf import settings
from staticgenerator import StaticGenerator

from django_de.apps.documentation.utils import get_absolute_document_urls

class StaticGeneratorMiddleware(object):
    """
    This is a modification of the staticgenerator middleware.
    """
    urls = tuple([re.compile(r'^%s' % url) for url in get_absolute_document_urls()+('/', '/documentation/')])

    def process_response(self, request, response):
        if response.status_code == 200:
            for url in self.urls:
                if url.match(request.path):
                    gen = StaticGenerator()
                    gen.publish_from_path(request.path, response.content)
                    break
        return response
<|endoftext|>


<commit_before>import sublime
import sublime_plugin
import re
import os.path
import distutils.util

pattern_reference_link = re.compile(r'\[.+?\]') # [Heading][my-id]
pattern_link = re.compile(r'\[(.+?)\]\(.+?\)')  # [link](http://www.sample.com/)
pattern_ex_id = re.compile(r'\{#.+?\}')         # [Heading]{#my-id}
pattern_tag = re.compile(r'<.*?>')

pattern_h1_h2_equal_dash = "^.*?(?:(?:\r\n)|\n|\r)(?:-+|=+)$"

TOCTAG_START = "<!-- MarkdownTOC -->"
TOCTAG_END = "<!-- /MarkdownTOC -->"

class MarkdowntocInsert(sublime_plugin.TextCommand):

    def run(self, edit):

        if not self.find_tag_and_insert(edit):
            sels = self.view.sel()
            for sel in sels:
                attrs = {
                    "depth":    self.get_setting('default_depth'),
                    "autolink": self.get_setting('default_autolink'),
                    "bracket":  self.get_setting('default_bracket')
                }
                # add TOCTAG
                toc = TOCTAG_START + "\n"
                toc += "\n"
                toc += self.get_toc(attrs, sel.end())
                toc += "\n"
                toc += TOCTAG_END + "\n"

                self.view.insert(edit, sel.begin(), toc)
                log('inserted TOC')

        # TODO: process to add another toc when tag exists

    def get_toc_open_tag(self):
        search_results = self.view.find_all(
            "^<!-- MarkdownTOC .*-->\n",
            sublime.IGNORECASE)
        search_results = self.remove_items_in_codeblock(search_results)

        toc_open_tags = []
        for toc_open in search_results:
            if 0 < len(toc_open):

                tag_str = self.view.substr(toc_open)

                depth_val = self.get_setting('default_depth')
                depth_search = re.search(" depth=(\w+) ", tag_str)
                if depth_search != None:
                    depth_val = int(depth_search.group(1))

                autolink_val = self.get_setting('default_autolink')
                autolink_search = re.search(" autolink=(\w+) ", tag_str)
                if autolink_search != None:
                    autolink_val = distutils.util.strtobool(autolink_search.group(1)) # cast to bool

                bracket_val = self.get_setting('default_bracket')
                bracket_search = re.search(" bracket=(\w+) ", tag_str)
                if bracket_search != None:
                    bracket_val = str(bracket_search.group(1))

                toc_open_tag = {
                    "region":   toc_open,
                    "depth":    depth_val,
                    "autolink": autolink_val,
                    "bracket":  bracket_val
                }
                toc_open_tags.append(toc_open_tag)

        return toc_open_tags

    def get_toc_close_tag(self, start):
        close_tags = self.view.find_all("^" + TOCTAG_END + "\n")
        close_tags = self.remove_items_in_codeblock(close_tags)
        for close_tag in close_tags:
            if start < close_tag.begin():
                return close_tag

    # Search MarkdownTOC comments in document
    def find_tag_and_insert(self, edit):
        toc_starts = self.get_toc_open_tag()
        for dic in toc_starts:

            toc_start = dic["region"]
            if 0 < len(toc_start):

                toc_close = self.get_toc_close_tag(toc_start.end())

                if toc_close:
                    toc = self.get_toc(dic, toc_close.end())
                    tocRegion = sublime.Region(
                        toc_start.end(), toc_close.begin())
                    if toc:
                        self.view.replace(edit, tocRegion, "\n" + toc + "\n")
                        log('refresh TOC content')
                        return True
                    else:
                        self.view.replace(edit, tocRegion, "\n")
                        log('TOC is empty')
                        return False
        log('cannot find TOC tags')
        return False

    # TODO: add "end" parameter
    def get_toc(self, attrs, begin):

        # Search headings in docment
        if attrs['depth'] == 0:
            pattern_hash = "^#+?[^#]"
        else:
            pattern_hash = "^#{1," + str(attrs['depth']) + "}[^#]"
        headings = self.view.find_all(
            "%s|%s" % (pattern_h1_h2_equal_dash, pattern_hash))

        headings = self.remove_items_in_codeblock(headings)

        if len(headings) < 1:
            return False

        items = []  # [[headingNum,text],...]
        for heading in headings:
            if begin < heading.end():
                lines = self.view.lines(heading)
                if len(lines) == 1:
                    # handle hash headings, ### chapter 1
                    r = sublime.Region(
                        heading.end(), self.view.line(heading).end())
                    text = self.view.substr(r)
                    indent = heading.size() - 1
                    items.append([indent, text])
                elif len(lines) == 2:
                    # handle - or + headings, Title 1==== section1----
                    text = self.view.substr(lines[0])
                    if text.strip():
                        indent = 1 if (
                            self.view.substr(lines[1])[0] == '=') else 2
                        items.append([indent, text])

        if len(items) < 1:
            return

        # Shape TOC  ------------------
        items = format(items)

        # Create TOC  ------------------
        toc = ''
        _ids = []
        for item in items:
            _id = None
            _indent  = item[0] - 1
            _text = item[1]
            _text = pattern_tag.sub('', _text) # remove html tags
            _text = _text.rstrip() # remove end space

            # Ignore links: e.g. '[link](http://sample.com/)' -> 'link'
            _text = pattern_link.sub('\\1', _text)

            # Add indent
            for i in range(_indent):
                toc += '\t'

            # Reference-style links: e.g. '# heading [my-anchor]'
            list_reference_link = list(pattern_reference_link.finditer(_text))

            # Markdown-Extra special attribute style: e.g. '# heading {#my-anchor}'
            match_ex_id = pattern_ex_id.search(_text)

            if len(list_reference_link):
                match = list_reference_link[-1]
                _text = _text[0:match.start()].replace('[','').replace(']','').rstrip()
                _id = match.group().replace('[','').replace(']','')
            elif match_ex_id:
                _text = _text[0:match_ex_id.start()]
                _text = _text.rstrip()
                _id = match_ex_id.group().replace('{#','').replace('}','')
            elif attrs['autolink']:
                _id = remove_reserved_chars(_text.lower().replace(" ", "-"))
                _ids.append(_id)
                n = _ids.count(_id)
                if 1 < n:
                    _id += '-' + str(n-1)

            if _id == None:
                toc += '- ' + _text + '\n'
            elif attrs['bracket'] == 'round':
                toc += '- [' + _text + '](#' + _id + ')\n'
            else:
                toc += '- [' + _text + '][' + _id + ']\n'

        return toc

    def get_setting(self, attr):
        settings = sublime.load_settings('MarkdownTOC.sublime-settings')
        return settings.get(attr)

    def remove_items_in_codeblock(self, items):

        codeblocks = self.view.find_all("^`{3,}[^`]*$")
        codeblockAreas = [] # [[area_begin, area_end], ..]
        i = 0
        while i < len(codeblocks)-1:
            area_begin = codeblocks[i].begin()
            area_end   = codeblocks[i+1].begin()
            if area_begin and area_end:
                codeblockAreas.append([area_begin, area_end])
            i += 2

        items = [h for h in items if is_out_of_areas(h.begin(), codeblockAreas)]
        return items

def remove_reserved_chars(str):
    # Percent-encoding reserved characters
    delete = {
        ord(u"!"): None,
        ord(u"#"): None,
        ord(u"$"): None,
        ord(u"&"): None,
        ord(u"'"): None,
        ord(u"("): None,
        ord(u")"): None,
        ord(u"*"): None,
        ord(u"+"): None,
        ord(u","): None,
        ord(u"/"): None,
        ord(u":"): None,
        ord(u";"): None,
        ord(u"="): None,
        ord(u"?"): None,
        ord(u"@"): None,
        ord(u"["): None,
        ord(u"]"): None,
        ord(u"`"): None
    }
    return str.translate(delete)

def is_out_of_areas(num, areas):
    for area in areas:
        if area[0] < num and num < area[1]:
            return False
    return True

def format(items):
    headings = []
    for item in items:
        headings.append(item[0])
    # ----------

    # set root to 1
    min_heading = min(headings)
    if 1 < min_heading:
        for i, item in enumerate(headings):
            headings[i] -= min_heading - 1
    headings[0] = 1  # first item must be 1

    # minimize "jump width"
    for i, item in enumerate(headings):
        if 0 < i and 1 < item - headings[i - 1]:
            before = headings[i]
            after = headings[i - 1] + 1
            headings[i] = after
            for n in range(i + 1, len(headings)):
                if(headings[n] == before):
                    headings[n] = after
                else:
                    break

    # ----------
    for i, item in enumerate(items):
        item[0] = headings[i]
    return items

def log(arg):
    sublime.status_message(arg)
    print(arg)

# Search and refresh if it's exist

class MarkdowntocUpdate(MarkdowntocInsert):

    def run(self, edit):
        MarkdowntocInsert.find_tag_and_insert(self, edit)

class AutoRunner(sublime_plugin.EventListener):

    def on_pre_save(self, view):
        # limit scope
        root, ext = os.path.splitext(view.file_name())
        ext = ext.lower()
        if ext in [".md", ".markdown", ".mdown", ".mdwn", ".mkdn", ".mkd", ".mark"]:
            view.run_command('markdowntoc_update')
<commit_msg>fix(autolink): remove 'double-quotes' from generated slug<commit_after>import sublime
import sublime_plugin
import re
import os.path
import distutils.util

pattern_reference_link = re.compile(r'\[.+?\]') # [Heading][my-id]
pattern_link = re.compile(r'\[(.+?)\]\(.+?\)')  # [link](http://www.sample.com/)
pattern_ex_id = re.compile(r'\{#.+?\}')         # [Heading]{#my-id}
pattern_tag = re.compile(r'<.*?>')

pattern_h1_h2_equal_dash = "^.*?(?:(?:\r\n)|\n|\r)(?:-+|=+)$"

TOCTAG_START = "<!-- MarkdownTOC -->"
TOCTAG_END = "<!-- /MarkdownTOC -->"

class MarkdowntocInsert(sublime_plugin.TextCommand):

    def run(self, edit):

        if not self.find_tag_and_insert(edit):
            sels = self.view.sel()
            for sel in sels:
                attrs = {
                    "depth":    self.get_setting('default_depth'),
                    "autolink": self.get_setting('default_autolink'),
                    "bracket":  self.get_setting('default_bracket')
                }
                # add TOCTAG
                toc = TOCTAG_START + "\n"
                toc += "\n"
                toc += self.get_toc(attrs, sel.end())
                toc += "\n"
                toc += TOCTAG_END + "\n"

                self.view.insert(edit, sel.begin(), toc)
                log('inserted TOC')

        # TODO: process to add another toc when tag exists

    def get_toc_open_tag(self):
        search_results = self.view.find_all(
            "^<!-- MarkdownTOC .*-->\n",
            sublime.IGNORECASE)
        search_results = self.remove_items_in_codeblock(search_results)

        toc_open_tags = []
        for toc_open in search_results:
            if 0 < len(toc_open):

                tag_str = self.view.substr(toc_open)

                depth_val = self.get_setting('default_depth')
                depth_search = re.search(" depth=(\w+) ", tag_str)
                if depth_search != None:
                    depth_val = int(depth_search.group(1))

                autolink_val = self.get_setting('default_autolink')
                autolink_search = re.search(" autolink=(\w+) ", tag_str)
                if autolink_search != None:
                    autolink_val = distutils.util.strtobool(autolink_search.group(1)) # cast to bool

                bracket_val = self.get_setting('default_bracket')
                bracket_search = re.search(" bracket=(\w+) ", tag_str)
                if bracket_search != None:
                    bracket_val = str(bracket_search.group(1))

                toc_open_tag = {
                    "region":   toc_open,
                    "depth":    depth_val,
                    "autolink": autolink_val,
                    "bracket":  bracket_val
                }
                toc_open_tags.append(toc_open_tag)

        return toc_open_tags

    def get_toc_close_tag(self, start):
        close_tags = self.view.find_all("^" + TOCTAG_END + "\n")
        close_tags = self.remove_items_in_codeblock(close_tags)
        for close_tag in close_tags:
            if start < close_tag.begin():
                return close_tag

    # Search MarkdownTOC comments in document
    def find_tag_and_insert(self, edit):
        toc_starts = self.get_toc_open_tag()
        for dic in toc_starts:

            toc_start = dic["region"]
            if 0 < len(toc_start):

                toc_close = self.get_toc_close_tag(toc_start.end())

                if toc_close:
                    toc = self.get_toc(dic, toc_close.end())
                    tocRegion = sublime.Region(
                        toc_start.end(), toc_close.begin())
                    if toc:
                        self.view.replace(edit, tocRegion, "\n" + toc + "\n")
                        log('refresh TOC content')
                        return True
                    else:
                        self.view.replace(edit, tocRegion, "\n")
                        log('TOC is empty')
                        return False
        log('cannot find TOC tags')
        return False

    # TODO: add "end" parameter
    def get_toc(self, attrs, begin):

        # Search headings in docment
        if attrs['depth'] == 0:
            pattern_hash = "^#+?[^#]"
        else:
            pattern_hash = "^#{1," + str(attrs['depth']) + "}[^#]"
        headings = self.view.find_all(
            "%s|%s" % (pattern_h1_h2_equal_dash, pattern_hash))

        headings = self.remove_items_in_codeblock(headings)

        if len(headings) < 1:
            return False

        items = []  # [[headingNum,text],...]
        for heading in headings:
            if begin < heading.end():
                lines = self.view.lines(heading)
                if len(lines) == 1:
                    # handle hash headings, ### chapter 1
                    r = sublime.Region(
                        heading.end(), self.view.line(heading).end())
                    text = self.view.substr(r)
                    indent = heading.size() - 1
                    items.append([indent, text])
                elif len(lines) == 2:
                    # handle - or + headings, Title 1==== section1----
                    text = self.view.substr(lines[0])
                    if text.strip():
                        indent = 1 if (
                            self.view.substr(lines[1])[0] == '=') else 2
                        items.append([indent, text])

        if len(items) < 1:
            return

        # Shape TOC  ------------------
        items = format(items)

        # Create TOC  ------------------
        toc = ''
        _ids = []
        for item in items:
            _id = None
            _indent  = item[0] - 1
            _text = item[1]
            _text = pattern_tag.sub('', _text) # remove html tags
            _text = _text.rstrip() # remove end space

            # Ignore links: e.g. '[link](http://sample.com/)' -> 'link'
            _text = pattern_link.sub('\\1', _text)

            # Add indent
            for i in range(_indent):
                toc += '\t'

            # Reference-style links: e.g. '# heading [my-anchor]'
            list_reference_link = list(pattern_reference_link.finditer(_text))

            # Markdown-Extra special attribute style: e.g. '# heading {#my-anchor}'
            match_ex_id = pattern_ex_id.search(_text)

            if len(list_reference_link):
                match = list_reference_link[-1]
                _text = _text[0:match.start()].replace('[','').replace(']','').rstrip()
                _id = match.group().replace('[','').replace(']','')
            elif match_ex_id:
                _text = _text[0:match_ex_id.start()]
                _text = _text.rstrip()
                _id = match_ex_id.group().replace('{#','').replace('}','')
            elif attrs['autolink']:
                _id = remove_reserved_chars(_text.lower().replace(" ", "-"))
                _ids.append(_id)
                n = _ids.count(_id)
                if 1 < n:
                    _id += '-' + str(n-1)

            if _id == None:
                toc += '- ' + _text + '\n'
            elif attrs['bracket'] == 'round':
                toc += '- [' + _text + '](#' + _id + ')\n'
            else:
                toc += '- [' + _text + '][' + _id + ']\n'

        return toc

    def get_setting(self, attr):
        settings = sublime.load_settings('MarkdownTOC.sublime-settings')
        return settings.get(attr)

    def remove_items_in_codeblock(self, items):

        codeblocks = self.view.find_all("^`{3,}[^`]*$")
        codeblockAreas = [] # [[area_begin, area_end], ..]
        i = 0
        while i < len(codeblocks)-1:
            area_begin = codeblocks[i].begin()
            area_end   = codeblocks[i+1].begin()
            if area_begin and area_end:
                codeblockAreas.append([area_begin, area_end])
            i += 2

        items = [h for h in items if is_out_of_areas(h.begin(), codeblockAreas)]
        return items

def remove_reserved_chars(str):
    # Percent-encoding reserved characters
    delete = {
        ord(u"!"): None,
        ord(u"#"): None,
        ord(u"$"): None,
        ord(u"&"): None,
        ord(u"'"): None,
        ord(u"("): None,
        ord(u")"): None,
        ord(u"*"): None,
        ord(u"+"): None,
        ord(u","): None,
        ord(u"/"): None,
        ord(u":"): None,
        ord(u";"): None,
        ord(u"="): None,
        ord(u"?"): None,
        ord(u"@"): None,
        ord(u"["): None,
        ord(u"]"): None,
        ord(u"`"): None,
        ord(u"\""): None,
    }
    return str.translate(delete)

def is_out_of_areas(num, areas):
    for area in areas:
        if area[0] < num and num < area[1]:
            return False
    return True

def format(items):
    headings = []
    for item in items:
        headings.append(item[0])
    # ----------

    # set root to 1
    min_heading = min(headings)
    if 1 < min_heading:
        for i, item in enumerate(headings):
            headings[i] -= min_heading - 1
    headings[0] = 1  # first item must be 1

    # minimize "jump width"
    for i, item in enumerate(headings):
        if 0 < i and 1 < item - headings[i - 1]:
            before = headings[i]
            after = headings[i - 1] + 1
            headings[i] = after
            for n in range(i + 1, len(headings)):
                if(headings[n] == before):
                    headings[n] = after
                else:
                    break

    # ----------
    for i, item in enumerate(items):
        item[0] = headings[i]
    return items

def log(arg):
    sublime.status_message(arg)
    print(arg)

# Search and refresh if it's exist

class MarkdowntocUpdate(MarkdowntocInsert):

    def run(self, edit):
        MarkdowntocInsert.find_tag_and_insert(self, edit)

class AutoRunner(sublime_plugin.EventListener):

    def on_pre_save(self, view):
        # limit scope
        root, ext = os.path.splitext(view.file_name())
        ext = ext.lower()
        if ext in [".md", ".markdown", ".mdown", ".mdwn", ".mkdn", ".mkd", ".mark"]:
            view.run_command('markdowntoc_update')
<|endoftext|>


<commit_before># coding=utf-8
from datetime import datetime

from django.shortcuts import render_to_response
from django.template.context import RequestContext
from django.utils import translation
import pytz
from django.http.response import JsonResponse, HttpResponseNotAllowed
from realtime.app_settings import LANGUAGE_LIST
from realtime.helpers.rest_push_indicator import RESTPushIndicator
from realtime.helpers.shake_event_indicator import ShakeEventIndicator
from realtime.helpers.shakemap_push_indicator import ShakemapPushIndicator
from realtime.models.user_push import UserPush
from user_map.models.user import User

__author__ = 'Rizky Maulana Nugraha "lucernae" <lana.pcfre@gmail.com>'
__date__ = '02/09/15'

def notify_shakemap_push(request):
    """Notify Realtime that a shakemap push is happening in the processor

    :param request: A django request object. Should be a POST request
    :type request: request

    :returns: Response will be a json with structure { 'success': bool }.
    :rtype: HttpResponse
    """

    retval = {}
    # the call should be authenticated
    # and make sure it is a post request (to follow REST principle)
    if request.user.is_authenticated() and request.method == 'POST':
        user = User.objects.get(email=request.user.email)
        try:
            user_push = UserPush.objects.get(user=user)
        except UserPush.DoesNotExist:
            user_push = UserPush.objects.create(user=user)
            user_push.save()

        # update info
        # get shakemap timestamp
        # calculate from utc
        date_format = '%Y-%m-%d %H:%M:%S'
        timestamp = request.POST['timestamp']
        if timestamp:
            time = datetime.strptime(
                timestamp, date_format).replace(tzinfo=pytz.utc)
        else:
            time = datetime.utcnow()
        user_push.last_shakemap_push = time.replace(tzinfo=pytz.utc)
        user_push.save()
        retval['success'] = True
        return JsonResponse(retval)
    else:
        retval['success'] = False
        return JsonResponse(retval)

def indicator(request):
    """Return a view to show the healthiness of Realtime system

    :param request: A django request object.
    :type request: request

    :returns: Response will be a leaflet map page.
    :rtype: HttpResponse
    """
    # FIXME: comment this out for now
    # fix this after it is clear who can access this page

    # if not request.user.is_authenticated():
    #    return HttpResponseNotAllowed()

    language_code = 'en'
    if request.method == 'GET':
        if 'lang' in request.GET:
            language_code = request.GET.get('lang')

    shakemap_push_indicator = ShakemapPushIndicator()
    shake_event_indicator = ShakeEventIndicator()
    rest_push_indicator = RESTPushIndicator()

    context = RequestContext(request)
    selected_language = {
        'id': 'en',
        'name': 'English'
    }
    for l in LANGUAGE_LIST:
        if l['id'] == language_code:
            selected_language = l

    language_list = [l for l in LANGUAGE_LIST if not l['id'] == language_code]
    context['language'] = {
        'selected_language': selected_language,
        'language_list': language_list,
    }
    translation.activate(selected_language['id'])
    request.session[translation.LANGUAGE_SESSION_KEY] = \
        selected_language['id']

    return render_to_response(
        'realtime/indicator.html',
        {
            'indicators': [
                shakemap_push_indicator,
                shake_event_indicator,
                rest_push_indicator
            ]
        },
        context_instance=context)

def realtime_rest_users(request):
    users = UserPush.objects.all()
    date_format = '%Y-%m-%d %H:%M:%S %Z'
    user_json = [
        {
            'username': u.user.get_username(),
            'email': u.user.email,
            'last_shakemap_push': u.last_shakemap_push.strftime(
                date_format),
            'last_rest_push': u.last_rest_push.strftime(date_format)
        }
        for u in users
    ]
    return JsonResponse({
        'users': user_json
    })
<commit_msg>fix flake8<commit_after># coding=utf-8
from datetime import datetime

from django.shortcuts import render_to_response
from django.template.context import RequestContext
from django.utils import translation
import pytz
from realtime.app_settings import LANGUAGE_LIST
from realtime.helpers.rest_push_indicator import RESTPushIndicator
from realtime.helpers.shake_event_indicator import ShakeEventIndicator
from realtime.helpers.shakemap_push_indicator import ShakemapPushIndicator
from realtime.models.user_push import UserPush
from user_map.models.user import User

__author__ = 'Rizky Maulana Nugraha "lucernae" <lana.pcfre@gmail.com>'
__date__ = '02/09/15'

def notify_shakemap_push(request):
    """Notify Realtime that a shakemap push is happening in the processor

    :param request: A django request object. Should be a POST request
    :type request: request

    :returns: Response will be a json with structure { 'success': bool }.
    :rtype: HttpResponse
    """

    retval = {}
    # the call should be authenticated
    # and make sure it is a post request (to follow REST principle)
    if request.user.is_authenticated() and request.method == 'POST':
        user = User.objects.get(email=request.user.email)
        try:
            user_push = UserPush.objects.get(user=user)
        except UserPush.DoesNotExist:
            user_push = UserPush.objects.create(user=user)
            user_push.save()

        # update info
        # get shakemap timestamp
        # calculate from utc
        date_format = '%Y-%m-%d %H:%M:%S'
        timestamp = request.POST['timestamp']
        if timestamp:
            time = datetime.strptime(
                timestamp, date_format).replace(tzinfo=pytz.utc)
        else:
            time = datetime.utcnow()
        user_push.last_shakemap_push = time.replace(tzinfo=pytz.utc)
        user_push.save()
        retval['success'] = True
        return JsonResponse(retval)
    else:
        retval['success'] = False
        return JsonResponse(retval)

def indicator(request):
    """Return a view to show the healthiness of Realtime system

    :param request: A django request object.
    :type request: request

    :returns: Response will be a leaflet map page.
    :rtype: HttpResponse
    """
    # FIXME: comment this out for now
    # fix this after it is clear who can access this page
    # if not request.user.is_authenticated():
    #    return HttpResponseNotAllowed()

    language_code = 'en'
    if request.method == 'GET':
        if 'lang' in request.GET:
            language_code = request.GET.get('lang')

    shakemap_push_indicator = ShakemapPushIndicator()
    shake_event_indicator = ShakeEventIndicator()
    rest_push_indicator = RESTPushIndicator()

    context = RequestContext(request)
    selected_language = {
        'id': 'en',
        'name': 'English'
    }
    for l in LANGUAGE_LIST:
        if l['id'] == language_code:
            selected_language = l

    language_list = [l for l in LANGUAGE_LIST if not l['id'] == language_code]
    context['language'] = {
        'selected_language': selected_language,
        'language_list': language_list,
    }
    translation.activate(selected_language['id'])
    request.session[translation.LANGUAGE_SESSION_KEY] = \
        selected_language['id']

    return render_to_response(
        'realtime/indicator.html',
        {
            'indicators': [
                shakemap_push_indicator,
                shake_event_indicator,
                rest_push_indicator
            ]
        },
        context_instance=context)

def realtime_rest_users(request):
    users = UserPush.objects.all()
    date_format = '%Y-%m-%d %H:%M:%S %Z'
    user_json = [
        {
            'username': u.user.get_username(),
            'email': u.user.email,
            'last_shakemap_push': u.last_shakemap_push.strftime(
                date_format),
            'last_rest_push': u.last_rest_push.strftime(date_format)
        }
        for u in users
    ]
    return JsonResponse({
        'users': user_json
    })
<|endoftext|>


<commit_before>from django.db import models
from django_sqlalchemy.backend import metadata, Session
from django_sqlalchemy.models import Field
from django_sqlalchemy.models.related import WrappedDynaLoader

import sqlalchemy as sa
from sqlalchemy import orm

# class ForeignRelatedObjectsDescriptor(models.ForeignRelatedObjectsDescriptor):
#     # This class provides the functionality that makes the related-object
#     # managers available as attributes on a model class, for fields that have
#     # multiple "remote" values and have a ForeignKey pointed at them by
#     # some other model. In the example "poll.choice_set", the choice_set
#     # attribute is a ForeignRelatedObjectsDescriptor instance.
#
#     def __get__(self, instance, instance_type=None):
#         if instance is None:
#             raise AttributeError, "Manager must be accessed via instance"
#
#         rel_field = self.related.field
#         rel_model = self.related.model
#
#         # Dynamically create a class that subclasses the related
#         # model's default manager.
#         superclass = self.related.model._default_manager.__class__
#
#         class RelatedManager(superclass):
#             def get_query_set(self):
#                 return superclass.get_query_set(self).filter(**(self.core_filters))
#
#             def add(self, *objs):
#                 for obj in objs:
#                     setattr(obj, rel_field.name, instance)
#                     obj.save()
#             add.alters_data = True
#
#             def create(self, **kwargs):
#                 new_obj = self.model(**kwargs)
#                 self.add(new_obj)
#                 return new_obj
#             create.alters_data = True
#
#             # remove() and clear() are only provided if the ForeignKey can have a value of null.
#             if rel_field.null:
#                 def remove(self, *objs):
#                     val = getattr(instance, rel_field.rel.get_related_field().attname)
#                     for obj in objs:
#                         # Is obj actually part of this descriptor set?
#                         if getattr(obj, rel_field.attname) == val:
#                             setattr(obj, rel_field.name, None)
#                             obj.save()
#                         else:
#                             raise rel_field.rel.to.DoesNotExist, "%r is not related to %r." % (obj, instance)
#                 remove.alters_data = True
#
#                 def clear(self):
#                     for obj in self.all():
#                         setattr(obj, rel_field.name, None)
#                         obj.save()
#                 clear.alters_data = True
#
#         manager = RelatedManager()
#         manager.core_filters = {'%s__pk' % rel_field.name: getattr(instance, rel_field.rel.get_related_field().attname)}
#         manager.model = self.related.model
#
#         return manager
#
#     def __set__(self, instance, value):
#         if instance is None:
#             raise AttributeError, "Manager must be accessed via instance"
#
#         manager = self.__get__(instance)
#         # If the foreign key can support nulls, then completely clear the related set.
#         # Otherwise, just move the named objects into the set.
#         if self.related.field.null:
#             manager.clear()
#         manager.add(*value)

class ForeignKey(models.ForeignKey, Field):
    def __init__(self, to, *args, **kwargs):
        self.relation = kwargs.pop('relation', None)
        models.ForeignKey.__init__(self, to, *args, **kwargs)

    def create_column(self):
        # ForeignKey will be shadowed by the class inside of this method.
        fk_primary = list(self.rel.to.__table__.primary_key)[0]
        self.sa_column = sa.Column('%s_%s' % (
                            self.rel.to._meta.object_name.lower(),
                            self.rel.to._meta.pk.name),
                            fk_primary.type, sa.ForeignKey(fk_primary))
        self.sa_rel_column = self.relation or orm.relation(self.rel.to)
        # self.sa_rel_column = self.relation or orm.relation(self.rel.to,
        #                                           backref=orm.backref(self.related_name,
        #                                           lazy='dynamic'))

        # self.sa_rel_column = self.relation or orm.relation(self.rel.to,
        #                                                   backref=orm.backref(self.related_name,
        #                                                   strategy_class=WrappedDynaLoader))

        # self.sa_rel_column = orm.relation(self.rel.to,
        #                                   primaryjoin=users_table.c.user_id==addresses_table.c.user_id,
        #                                   foreign_keys=[addresses_table.c.user_id])
        return { self.sa_column.name: self.sa_column,
                 self.rel.to._meta.object_name.lower(): self.sa_rel_column }

    def contribute_to_related_class(self, cls, related):
        # fk field needs to know the related_name it belongs to
        # for create_column to work properly.
        super(ForeignKey, self).contribute_to_related_class(cls, related)
        self.related = related
        self.related_name = related.get_accessor_name()

class ManyToManyField(models.ManyToManyField, Field):
    def __init__(self, to, *args, **kwargs):
        super(self.__class__, self).__init__(to, *args, **kwargs)

    def add(self, *args, **kwargs):
        super(self.__class__, self).add(self, *args, **kwargs)
        Session.commit()

    def create_column(self):
        # m2m fields do not have a column
        self.sa_column = None
        self.__table__ = sa.Table(self.m2m_db_table(), metadata,
            sa.Column(self.m2m_column_name(), self.model._meta.pk.sa_column.type),
            sa.Column(self.m2m_reverse_name(), self.rel.to._meta.pk.sa_column.type))
        return self.sa_column

    def contribute_to_class(self, cls, name):
        super(ManyToManyField, self).contribute_to_class(cls, name)
        # m2m field needs to know the model it belongs to for create_column
        # to work properly.
        self.model = cls

<commit_msg>Modifications to get self-referential foreign keys to create the appropriate table structure.  Still has a problem in querying though.  This will require more changes.<commit_after>from django.db import models
from django_sqlalchemy.backend import metadata, Session
from django_sqlalchemy.models import Field
from django_sqlalchemy.models.related import WrappedDynaLoader

import sqlalchemy as sa
from sqlalchemy import orm

# class ForeignRelatedObjectsDescriptor(models.ForeignRelatedObjectsDescriptor):
#     # This class provides the functionality that makes the related-object
#     # managers available as attributes on a model class, for fields that have
#     # multiple "remote" values and have a ForeignKey pointed at them by
#     # some other model. In the example "poll.choice_set", the choice_set
#     # attribute is a ForeignRelatedObjectsDescriptor instance.
#
#     def __get__(self, instance, instance_type=None):
#         if instance is None:
#             raise AttributeError, "Manager must be accessed via instance"
#
#         rel_field = self.related.field
#         rel_model = self.related.model
#
#         # Dynamically create a class that subclasses the related
#         # model's default manager.
#         superclass = self.related.model._default_manager.__class__
#
#         class RelatedManager(superclass):
#             def get_query_set(self):
#                 return superclass.get_query_set(self).filter(**(self.core_filters))
#
#             def add(self, *objs):
#                 for obj in objs:
#                     setattr(obj, rel_field.name, instance)
#                     obj.save()
#             add.alters_data = True
#
#             def create(self, **kwargs):
#                 new_obj = self.model(**kwargs)
#                 self.add(new_obj)
#                 return new_obj
#             create.alters_data = True
#
#             # remove() and clear() are only provided if the ForeignKey can have a value of null.
#             if rel_field.null:
#                 def remove(self, *objs):
#                     val = getattr(instance, rel_field.rel.get_related_field().attname)
#                     for obj in objs:
#                         # Is obj actually part of this descriptor set?
#                         if getattr(obj, rel_field.attname) == val:
#                             setattr(obj, rel_field.name, None)
#                             obj.save()
#                         else:
#                             raise rel_field.rel.to.DoesNotExist, "%r is not related to %r." % (obj, instance)
#                 remove.alters_data = True
#
#                 def clear(self):
#                     for obj in self.all():
#                         setattr(obj, rel_field.name, None)
#                         obj.save()
#                 clear.alters_data = True
#
#         manager = RelatedManager()
#         manager.core_filters = {'%s__pk' % rel_field.name: getattr(instance, rel_field.rel.get_related_field().attname)}
#         manager.model = self.related.model
#
#         return manager
#
#     def __set__(self, instance, value):
#         if instance is None:
#             raise AttributeError, "Manager must be accessed via instance"
#
#         manager = self.__get__(instance)
#         # If the foreign key can support nulls, then completely clear the related set.
#         # Otherwise, just move the named objects into the set.
#         if self.related.field.null:
#             manager.clear()
#         manager.add(*value)

class ForeignKey(models.ForeignKey, Field):
    def __init__(self, to, *args, **kwargs):
        self.relation = kwargs.pop('relation', None)
        models.ForeignKey.__init__(self, to, *args, **kwargs)

    def create_column(self):
        # try to get the ForeignKey using the SA Column.  If it doesn't work
        # then it's likely a self-referential situation and then just build
        # up the quoted name.
        options = self.rel.to._meta

        try:
            fk_primary = list(self.rel.to.__table__.primary_key)[0]
        except:
            fk_primary = '%s.%s' % (options.db_table, options.pk.name)

        self.sa_column = sa.Column('%s_%s' % (
                            options.object_name.lower(),
                            options.pk.name),
                            options.pk.sa_column_type().__class__,
                            sa.ForeignKey(fk_primary))
        self.sa_rel_column = self.relation or orm.relation(self.rel.to)
        # self.sa_rel_column = self.relation or orm.relation(self.rel.to,
        #                                           backref=orm.backref(self.related_name,
        #                                           lazy='dynamic'))

        # self.sa_rel_column = self.relation or orm.relation(self.rel.to,
        #                                                   backref=orm.backref(self.related_name,
        #                                                   strategy_class=WrappedDynaLoader))

        # self.sa_rel_column = orm.relation(self.rel.to,
        #                                   primaryjoin=users_table.c.user_id==addresses_table.c.user_id,
        #                                   foreign_keys=[addresses_table.c.user_id])
        return { self.sa_column.name: self.sa_column,
                 options.object_name.lower(): self.sa_rel_column }

    def contribute_to_related_class(self, cls, related):
        # fk field needs to know the related_name it belongs to
        # for create_column to work properly.
        super(ForeignKey, self).contribute_to_related_class(cls, related)
        self.related = related
        self.related_name = related.get_accessor_name()

class ManyToManyField(models.ManyToManyField, Field):
    def __init__(self, to, *args, **kwargs):
        super(self.__class__, self).__init__(to, *args, **kwargs)

    def add(self, *args, **kwargs):
        super(self.__class__, self).add(self, *args, **kwargs)
        Session.commit()

    def create_column(self):
        # m2m fields do not have a column
        self.sa_column = None
        self.__table__ = sa.Table(self.m2m_db_table(), metadata,
            sa.Column(self.m2m_column_name(), self.model._meta.pk.sa_column.type),
            sa.Column(self.m2m_reverse_name(), self.rel.to._meta.pk.sa_column.type))
        return self.sa_column

    def contribute_to_class(self, cls, name):
        super(ManyToManyField, self).contribute_to_class(cls, name)
        # m2m field needs to know the model it belongs to for create_column
        # to work properly.
        self.model = cls

<|endoftext|>


<commit_before><commit_msg>python -<commit_after><|endoftext|>


<commit_before>'''
ARCHES - a program developed to inventory and manage immovable cultural heritage.
Copyright (C) 2013 J. Paul Getty Trust and World Monuments Fund

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
'''

from django.template import RequestContext
from django.shortcuts import render_to_response, redirect
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.cache import never_cache
from django.contrib.auth import authenticate, login, logout
from django.core.urlresolvers import reverse
from django.conf import settings
from django.db import transaction
from arches.app.models import models
from arches.app.models.resource import Resource
from arches.app.models.concept import Concept
from django.utils.translation import ugettext as _
from arches.app.utils.betterJSONSerializer import JSONSerializer, JSONDeserializer

@csrf_exempt
def resource_manager(request, resourcetypeid='', form_id='', resourceid=''):

    if resourceid != '':
        resource = Resource(resourceid)
    elif resourcetypeid != '':
        resource = Resource({'entitytypeid': resourcetypeid})

    form = resource.get_form(form_id)

    if request.method == 'POST':
        # get the values from the form and pass to the resource
        data = JSONDeserializer().deserialize(request.POST.get('formdata', {}))
        form.update(data)

        with transaction.atomic():
            resource.save()
            #resource.index()
            resourceid = resource.entityid

            return redirect('resource_manager', resourcetypeid=resourcetypeid, form_id=form_id, resourceid=resourceid)

    return render_to_response('resource-manager.htm', {
            'form': form,
            'formdata': JSONSerializer().serialize(form.data),
            'form_template': 'forms/' + form_id + '.htm',
            'form_id': form_id,
            'resourcetypeid': resourcetypeid,
            'resourceid': resourceid,
            'main_script': 'resource-manager',
            'active_page': 'ResourceManger',
            'resource': resource,
            'resource_name': resource.get_primary_name(),
            'resource_type_name': resource.get_type_name(),
            'form_groups': resource.form_groups
        },
        context_instance=RequestContext(request))

class ResourceForm(object):
    id = ''
    icon = ''
    name = ''

    def __init__(self, resource):
        # here is where we can create the basic format for the form data
        self.resource = resource
        self.data = {
            "domains": {},
            "defaults": {}
        }
        self.load()

	def update(self, data):
		# update resource w/ post data
		return

    def get_e55_domain(self, entitytypeid):
        return list(models.VwEntitytypeDomains.objects.filter(entitytypeid=entitytypeid).order_by('sortorder', 'value').values())

    def get_nodes(self, entitytypeid):
        ret = []
        entities = self.resource.find_entities_by_type_id(entitytypeid)
        for entity in entities:
            data = {}

            for entity in entity.flatten():
                #data[entity.entitytypeid] = self.encode_entity(entity)
                data = dict(data.items() + self.encode_entity(entity).items())
            ret.append(data)
        return ret

    def encode_entity(self, entity):
        def enc(entity, attr):
            return '%s__%s' % (entity.entitytypeid.replace('.', '_'), attr)

        ret = {}
        for key, value in entity.__dict__.items():
            if not key.startswith("__"):
                ret[enc(entity, key)] = value
        return ret

    def decode_data_item(self, entity):
        def dec(item):
            # item = "NAME_E41__entitytypeid"
            val = item.split('__')
            if len(val) != 2:
                return False
            entitytypeid = val[0]
            propertyname = val[1]

            v = entitytypeid.split('_')
            entitytypeid = '%s.%s' % ('_'.join(v[:-1]), v[-1])
            return (entitytypeid, propertyname)

        ret = {}
        for key, value in entity.iteritems():
            r = dec(key)
            if r:
                if r[0] not in ret:
                    ret[r[0]] = {}
                ret[r[0]][r[1]] = value

        ret2 = []
        for key, value in ret.iteritems():
            value['entitytypeid'] = key
            ret2.append(value)
        return ret2<commit_msg>refactoring logic for updating nodes into arches resource class for reuse<commit_after>'''
ARCHES - a program developed to inventory and manage immovable cultural heritage.
Copyright (C) 2013 J. Paul Getty Trust and World Monuments Fund

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
'''

from django.template import RequestContext
from django.shortcuts import render_to_response, redirect
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.cache import never_cache
from django.contrib.auth import authenticate, login, logout
from django.core.urlresolvers import reverse
from django.conf import settings
from django.db import transaction
from arches.app.models import models
from arches.app.models.resource import Resource
from arches.app.models.concept import Concept
from django.utils.translation import ugettext as _
from arches.app.utils.betterJSONSerializer import JSONSerializer, JSONDeserializer
from arches.app.models.entity import Entity

@csrf_exempt
def resource_manager(request, resourcetypeid='', form_id='', resourceid=''):

    if resourceid != '':
        resource = Resource(resourceid)
    elif resourcetypeid != '':
        resource = Resource({'entitytypeid': resourcetypeid})

    form = resource.get_form(form_id)

    if request.method == 'POST':
        # get the values from the form and pass to the resource
        data = JSONDeserializer().deserialize(request.POST.get('formdata', {}))
        form.update(data)

        with transaction.atomic():
            resource.save()
            #resource.index()
            resourceid = resource.entityid

            return redirect('resource_manager', resourcetypeid=resourcetypeid, form_id=form_id, resourceid=resourceid)

    return render_to_response('resource-manager.htm', {
            'form': form,
            'formdata': JSONSerializer().serialize(form.data),
            'form_template': 'forms/' + form_id + '.htm',
            'form_id': form_id,
            'resourcetypeid': resourcetypeid,
            'resourceid': resourceid,
            'main_script': 'resource-manager',
            'active_page': 'ResourceManger',
            'resource': resource,
            'resource_name': resource.get_primary_name(),
            'resource_type_name': resource.get_type_name(),
            'form_groups': resource.form_groups
        },
        context_instance=RequestContext(request))

class ResourceForm(object):
    id = ''
    icon = ''
    name = ''

    def __init__(self, resource):
        # here is where we can create the basic format for the form data
        self.resource = resource
        self.data = {
            "domains": {},
            "defaults": {}
        }
        self.load()

	def update(self, data):
		# update resource w/ post data
		return

    def get_e55_domain(self, entitytypeid):
        return list(models.VwEntitytypeDomains.objects.filter(entitytypeid=entitytypeid).order_by('sortorder', 'value').values())

    def get_nodes(self, entitytypeid):
        ret = []
        entities = self.resource.find_entities_by_type_id(entitytypeid)
        for entity in entities:
            data = {}

            for entity in entity.flatten():
                #data[entity.entitytypeid] = self.encode_entity(entity)
                data = dict(data.items() + self.encode_entity(entity).items())
            ret.append(data)
        return ret

    def update_nodes(self, entitytypeid, data):
        for entity in self.resource.find_entities_by_type_id(entitytypeid):
            self.resource.child_entities.remove(entity)

        schema = Entity.get_mapping_schema(self.resource.entitytypeid)
        for value in data[entitytypeid.replace('.', '_')]:
            baseentity = None
            for newentity in self.decode_data_item(value):
                entity = Entity()
                entity.create_from_mapping(self.resource.entitytypeid, schema[newentity['entitytypeid']]['steps'], newentity['entitytypeid'], newentity['value'], newentity['entityid'])

                if baseentity == None:
                    baseentity = entity
                else:
                    baseentity.merge(entity)

            self.resource.merge_at(baseentity, self.resource.entitytypeid)

    def encode_entity(self, entity):
        def enc(entity, attr):
            return '%s__%s' % (entity.entitytypeid.replace('.', '_'), attr)

        ret = {}
        for key, value in entity.__dict__.items():
            if not key.startswith("__"):
                ret[enc(entity, key)] = value
        return ret

    def decode_data_item(self, entity):
        def dec(item):
            # item = "NAME_E41__entitytypeid"
            val = item.split('__')
            if len(val) != 2:
                return False
            entitytypeid = val[0]
            propertyname = val[1]

            v = entitytypeid.split('_')
            entitytypeid = '%s.%s' % ('_'.join(v[:-1]), v[-1])
            return (entitytypeid, propertyname)

        ret = {}
        for key, value in entity.iteritems():
            r = dec(key)
            if r:
                if r[0] not in ret:
                    ret[r[0]] = {}
                ret[r[0]][r[1]] = value

        ret2 = []
        for key, value in ret.iteritems():
            value['entitytypeid'] = key
            ret2.append(value)
        return ret2<|endoftext|>


<commit_before>from django.conf import settings
from django.http import HttpRequest
from django.test import TestCase as DjangoTestCase
import fudge

def with_fake_request(func):
    def inner(self, *args, **kwargs):
        request = fudge.Fake(HttpRequest)
        fudge.clear_calls()

        result = func(self, request, *args, **kwargs)

        fudge.verify()
        fudge.clear_expectations()
        return result
    return inner

class TestCase(DjangoTestCase):
    def setUp(self):
        self._original_settings = settings

    def tearDown(self):
        settings = self._original_settings

<commit_msg>make sure to always clear expectations and calls prior to starting to prevent bleed-over<commit_after>from django.conf import settings
from django.http import HttpRequest
from django.test import TestCase as DjangoTestCase
import fudge

def with_fake_request(func):
    def inner(self, *args, **kwargs):
        request = fudge.Fake(HttpRequest)
        fudge.clear_calls()

        result = func(self, request, *args, **kwargs)

        fudge.verify()
        fudge.clear_expectations()
        return result
    return inner

class TestCase(DjangoTestCase):
    def setUp(self):
        self._original_settings = settings
        fudge.clear_expectations()
        fudge.clear_calls()

    def tearDown(self):
        settings = self._original_settings

<|endoftext|>