<commit_before>import cgi
import copy
import json
import re

from flask import session, redirect, request, g, render_template, flash, \
  Markup, Blueprint

from yaka.core.extensions import db
from yaka.core.entities import Entity


#
# Helper classes
#
class BreadCrumbs(object):
  def __init__(self, l=()):
    self._bc = []
    for path, label in l:
      self.add(path, label)

  def add(self, path="", label=""):
    if path and not path.startswith("/"):
      previous = self._bc[-1]
      path = previous['path'] + "/" + path
    self._bc.append(dict(path=path, label=label))

  def __getitem__(self, item):
    return self._bc[item]

  def __add__(self, t):
    bc = self.clone()
    bc.add(t[0], t[1])
    return bc

  def clone(self):
    new = BreadCrumbs()
    new._bc = copy.copy(self._bc)
    return new


def add_to_recent_items(entity, type=None):
  if not type:
    type = entity.__class__.__name__.lower()
  g.recent_items.insert(0, dict(type=type, name=entity.name, url=entity.url))
  s = set()
  l = []
  for item in g.recent_items:
    if item['url'] in s:
      continue
    s.add(item['url'])
    l.append(item)
  if len(l) > 10:
    del l[10:]
  session['recent_items'] = g.recent_items = l


#
# UI model classes
#
class EntityListModel(object):
  """Wraps a list of entities for presentation by a TableView."""

  # TODO: not used for now

  def __init__(self, entity_list):
    self.entity_list = entity_list


class SingleEntityModel(object):
  """Wraps an entity for presentation by a SingleView."""

  # TODO: not used for now

  def __init__(self, entity):
    self.entity = entity


#
# UI views
#
class TableView(object):
  def __init__(self, columns):
    self.init_columns(columns)
    self.name = id(self)

  def init_columns(self, columns):
    # TODO
    self.columns = []
    default_width = 0.99 / len(columns)
    for col in columns:
      if type(col) == str:
        self.columns.append(dict(name=col, width=default_width))
      else:
        self.columns.append(col)

  def render(self, model):
    columns = [{'name': labelize(col['name']), 'width': col['width']} for col in self.columns]
    table = []
    for entity in model:
      table.append(self.render_line(entity))

    return Markup(render_template('crm/render_table.html', table=table, columns=columns,
                                  table_name=self.name))

  def render_line(self, entity):
    line = []
    for col in self.columns:
      if type(col) == str:
        column_name = col
      else:
        column_name = col['name']
      value = getattr(entity, column_name)
      if value is None:
        value = ""
      if column_name == 'name':
        cell = Markup('<a href="%s">%s</a>' % (entity.url, cgi.escape(value)))
      elif isinstance(value, Entity):
        cell = Markup('<a href="%s">%s</a>' % (value.url, cgi.escape(value.name)))
      elif (isinstance(value, str) or isinstance(value, unicode))\
      and value.startswith("http://"):
        # XXX: security issue here
        cell = Markup('<a href="%s">%s</a>' % (value, value[len("http://"):]))
      else:
        cell = unicode(value)
      line.append(cell)
    return line


class SingleView(object):
  def __init__(self, *panels):
    self.panels = panels

  def render(self, model):
    # TODO: refactor by passing a model instead
    def get(attr_name):
      return self.get(model, attr_name)

    return Markup(render_template('crm/render_single.html', panels=self.panels, get=get))

  def render_form(self, form, for_new=False):
    # Client-side rules for jQuery.validate
    # See: http://docs.jquery.com/Plugins/Validation/Methods#Validator
    rules = {}
    for field in form:
      rules_for_field = {}
      for validator in field.validators:
        rule_for_validator = getattr(validator, "rule", None)
        if rule_for_validator:
          rules_for_field.update(rule_for_validator)
      if rules_for_field:
        rules[field.name] = rules_for_field
    if rules:
      rules = Markup(json.dumps(rules))
    else:
      rules = None

    return Markup(render_template('crm/render_for_edit.html',
                                  form=form, for_new=for_new, rules=rules))

  def get(self, model, attr_name):
    value = getattr(model, attr_name)
    if value is None:
      return ""
    elif isinstance(value, Entity):
      return Markup('<a href="%s">%s</a>' % (value.url, cgi.escape(value.name)))
    else:
      return unicode(value)


#
# Used to describe single entity views.
#
class Panel(object):
  def __init__(self, label=None, *rows):
    self.label = label
    self.rows = rows

  def __iter__(self):
    return iter(self.rows)

  def __getitem__(self, item):
    return self.rows[item]

  def __len__(self):
    return len(self.rows)


class Row(object):
  def __init__(self, *cols):
    self.cols = cols

  def __iter__(self):
    return iter(self.cols)

  def __getitem__(self, item):
    return self.cols[item]

  def __len__(self):
    return len(self.cols)


def expose(url='/', methods=('GET',)):
  """
      Use this decorator to expose views in your view classes.

      `url`
          Relative URL for the view
      `methods`
          Allowed HTTP methods. By default only GET is allowed.
  """

  def wrap(f):
    if not hasattr(f, '_urls'):
      f._urls = []
    f._urls.append((url, methods))
    return f

  return wrap


def labelize(s):
  return " ".join([w.capitalize() for w in s.split("_")])


class ModuleMeta(type):
  """
      Module metaclass.

      Does some precalculations (like getting list of view methods from the class) to avoid
      calculating them for each view class instance.
  """

  def __init__(cls, classname, bases, fields):
    type.__init__(cls, classname, bases, fields)

    # Gather exposed views
    cls._urls = []
    cls._default_view = None

    for p in dir(cls):
      attr = getattr(cls, p)

      if hasattr(attr, '_urls'):
        # Collect methods
        for url, methods in attr._urls:
          cls._urls.append((url, p, methods))

          if url == '/':
            cls._default_view = p

            # Wrap views
            #setattr(cls, p, _wrap_view(attr))


class Module(object):
  __metaclass__ = ModuleMeta

  id = None
  endpoint = None
  label = None
  managed_class = None
  list_view = None
  list_view_columns = []
  single_view = None
  edit_form = None
  url = None
  name = None
  static_folder = None
  related_views = []

  _urls = []


  def __init__(self):
    # If endpoint name is not provided, get it from the class name
    if self.endpoint is None:
      self.endpoint = self.__class__.__name__.lower()

    if self.label is None:
      self.label = labelize(self.endpoint)

    if self.id is None:
      self.id = self.managed_class.__name__.lower()

  def create_blueprint(self, crud_app):
    """
        Create Flask blueprint.
    """
    # Store admin instance
    self.crud_app = crud_app
    self.app = crud_app.app

    # If url is not provided, generate it from endpoint name
    if self.url is None:
      self.url = '%s/%s' % (self.crud_app.url, self.endpoint)
    else:
      if not self.url.startswith('/'):
        self.url = '%s/%s' % (self.crud_app.url, self.url)

    # If name is not provided, use capitalized endpoint name
    if self.name is None:
      self.name = self._prettify_name(self.__class__.__name__)

    # Create blueprint and register rules
    self.blueprint = Blueprint(self.endpoint, __name__,
                               url_prefix=self.url,
                               template_folder='templates/crm',
                               static_folder=self.static_folder)

    for url, name, methods in self._urls:
      self.blueprint.add_url_rule(url,
                                  name,<commit_msg>Single views can be generated from form.<commit_after>import cgi
import copy
import json
import re

from flask import session, redirect, request, g, render_template, flash,\
  Markup, Blueprint

from yaka.core.extensions import db
from yaka.core.entities import Entity


#
# Helper classes
#
class BreadCrumbs(object):
  def __init__(self, l=()):
    self._bc = []
    for path, label in l:
      self.add(path, label)

  def add(self, path="", label=""):
    if path and not path.startswith("/"):
      previous = self._bc[-1]
      path = previous['path'] + "/" + path
    self._bc.append(dict(path=path, label=label))

  def __getitem__(self, item):
    return self._bc[item]

  def __add__(self, t):
    bc = self.clone()
    bc.add(t[0], t[1])
    return bc

  def clone(self):
    new = BreadCrumbs()
    new._bc = copy.copy(self._bc)
    return new


def add_to_recent_items(entity, type=None):
  if not type:
    type = entity.__class__.__name__.lower()
  g.recent_items.insert(0, dict(type=type, name=entity.name, url=entity.url))
  s = set()
  l = []
  for item in g.recent_items:
    if item['url'] in s:
      continue
    s.add(item['url'])
    l.append(item)
  if len(l) > 10:
    del l[10:]
  session['recent_items'] = g.recent_items = l


#
# UI model classes
#
class EntityListModel(object):
  """Wraps a list of entities for presentation by a TableView."""

  # TODO: not used for now

  def __init__(self, entity_list):
    self.entity_list = entity_list


class SingleEntityModel(object):
  """Wraps an entity for presentation by a SingleView."""

  # TODO: not used for now

  def __init__(self, entity):
    self.entity = entity


#
# UI views
#
class TableView(object):
  def __init__(self, columns):
    self.init_columns(columns)
    self.name = id(self)

  def init_columns(self, columns):
    # TODO
    self.columns = []
    default_width = 0.99 / len(columns)
    for col in columns:
      if type(col) == str:
        self.columns.append(dict(name=col, width=default_width))
      else:
        self.columns.append(col)

  def render(self, model):
    columns = [{'name': labelize(col['name']), 'width': col['width']} for col in self.columns]
    table = []
    for entity in model:
      table.append(self.render_line(entity))

    return Markup(render_template('crm/render_table.html', table=table, columns=columns,
                                  table_name=self.name))

  def render_line(self, entity):
    line = []
    for col in self.columns:
      if type(col) == str:
        column_name = col
      else:
        column_name = col['name']
      value = getattr(entity, column_name)
      if value is None:
        value = ""
      if column_name == 'name':
        cell = Markup('<a href="%s">%s</a>' % (entity.url, cgi.escape(value)))
      elif isinstance(value, Entity):
        cell = Markup('<a href="%s">%s</a>' % (value.url, cgi.escape(value.name)))
      elif (isinstance(value, str) or isinstance(value, unicode))\
      and value.startswith("http://"):
        # XXX: security issue here
        cell = Markup('<a href="%s">%s</a>' % (value, value[len("http://"):]))
      else:
        cell = unicode(value)
      line.append(cell)
    return line


class SingleView(object):
  def __init__(self, *panels):
    self.panels = panels

  def render(self, model):
    # TODO: refactor by passing a model instead
    def get(attr_name):
      return self.get(model, attr_name)

    return Markup(render_template('crm/render_single.html', panels=self.panels, get=get))

  def render_form(self, form, for_new=False):
    # Client-side rules for jQuery.validate
    # See: http://docs.jquery.com/Plugins/Validation/Methods#Validator
    rules = {}
    for field in form:
      rules_for_field = {}
      for validator in field.validators:
        rule_for_validator = getattr(validator, "rule", None)
        if rule_for_validator:
          rules_for_field.update(rule_for_validator)
      if rules_for_field:
        rules[field.name] = rules_for_field
    if rules:
      rules = Markup(json.dumps(rules))
    else:
      rules = None

    return Markup(render_template('crm/render_for_edit.html',
                                  form=form, for_new=for_new, rules=rules))

  def get(self, model, attr_name):
    value = getattr(model, attr_name)
    if value is None:
      return ""
    elif isinstance(value, Entity):
      return Markup('<a href="%s">%s</a>' % (value.url, cgi.escape(value.name)))
    else:
      return unicode(value)


#
# Used to describe single entity views.
#
class Panel(object):
  def __init__(self, label=None, *rows):
    self.label = label
    self.rows = rows

  def __iter__(self):
    return iter(self.rows)

  def __getitem__(self, item):
    return self.rows[item]

  def __len__(self):
    return len(self.rows)


class Row(object):
  def __init__(self, *cols):
    self.cols = cols

  def __iter__(self):
    return iter(self.cols)

  def __getitem__(self, item):
    return self.cols[item]

  def __len__(self):
    return len(self.cols)


def expose(url='/', methods=('GET',)):
  """
      Use this decorator to expose views in your view classes.

      `url`
          Relative URL for the view
      `methods`
          Allowed HTTP methods. By default only GET is allowed.
  """

  def wrap(f):
    if not hasattr(f, '_urls'):
      f._urls = []
    f._urls.append((url, methods))
    return f

  return wrap


def labelize(s):
  return " ".join([w.capitalize() for w in s.split("_")])


def make_single_view(form):
  panels = []
  for g in form._groups:
    panel = Panel(g[0], *[ Row(x) for x in g[1] ])
    panels.append(panel)
  return SingleView(*panels)




class ModuleMeta(type):
  """
      Module metaclass.

      Does some precalculations (like getting list of view methods from the class) to avoid
      calculating them for each view class instance.
  """

  def __init__(cls, classname, bases, fields):
    type.__init__(cls, classname, bases, fields)

    # Gather exposed views
    cls._urls = []
    cls._default_view = None

    for p in dir(cls):
      attr = getattr(cls, p)

      if hasattr(attr, '_urls'):
        # Collect methods
        for url, methods in attr._urls:
          cls._urls.append((url, p, methods))

          if url == '/':
            cls._default_view = p

            # Wrap views
            #setattr(cls, p, _wrap_view(attr))


class Module(object):
  __metaclass__ = ModuleMeta

  id = None
  endpoint = None
  label = None
  managed_class = None
  list_view = None
  list_view_columns = []
  single_view = None
  edit_form = None
  url = None
  name = None
  static_folder = None
  related_views = []

  _urls = []



  def __init__(self):
    # If endpoint name is not provided, get it from the class name
    if self.endpoint is None:
      self.endpoint = self.__class__.__name__.lower()

    if self.label is None:
      self.label = labelize(self.endpoint)

    if self.id is None:
      self.id = self.managed_class.__name__.lower()

    self.single_view = make_single_view(self.edit_form)

  def create_blueprint(self, crud_app):
    """
        Create Flask blueprint.
    """
    # Store admin instance
    self.crud_app = crud_app
    self.app = crud_app.app

    # If url is not provided, generate it from endpoint name
    if self.url is None:
      self.url = '%s/%s' % (self.crud_app.url, self.endpoint)
    else:
      if not self.url.startswith('/'):
        self.url = '%s/%s' % (self.crud_app.url, self.url)

    # If name is not provided, use capitalized endpoint name
    if self.name is None:
      self.name = self._prettify_name(self.__class__.__name__)

    # Create blueprint and register rules
    self.blueprint = Blueprint(self.endpoint, __name__,
                               url_prefix=self.url,
                               template_folder='templates/crm',
                               static_folder=self.static_folder)

    for url, name, methods in self._urls:
      self.blueprint.add_url_rule(url,
                                  name,
{'fraction_non_alphanumeric': 0.12374857432518059, 'fraction_numerical': 0.0015207198073754911, 'mean_word_length': 2.6416705122288877, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6678548', 'n_tokens_mistral': 5182, 'n_tokens_neox': 5057, 'n_words': 1356}