<commit_before>require 'sinatra/base'

require 'haml'
require 'sass'
require 'coffee-script'
require 'neo4j'
require 'sprockets'

module Neo; module Viz; end; end

module Neo::Viz

  def self.install_path
    return File.expand_path('../..', __FILE__)
  end

  class App < Sinatra::Base

    configure do
      set :public, File.expand_path('../../public/', __FILE__)
      set :views, File.expand_path('../../views/', __FILE__)
    end

    configure(:development) do
      require 'sinatra/reloader'
      register Sinatra::Reloader
      also_reload "lib/**/*.rb"
    end

    get '/' do
      redirect to('/index')
    end

    get '/index' do
      haml :index
    end

    # Consumers of /embedded have to redefine this method inside
    # the Sprockets environment. See config.ru.
    def root_url
      '.'
    end

    get '/javascripts/main.js' do
      coffee(erb(:'coffeescript/main.coffee'))
    end

    get '/javascripts/canvas_util.js' do
      coffee :'coffeescript/canvas_util'
    end

    get '/embedded' do
      @assets_url_prefix = request.env["rack.mount.prefix"] || ''
      haml :embedded
    end

    get '/stylesheets/main.css' do
      scss :'scss/main'
    end

    get '/node-count' do
      Neo4j.management.get_number_of_node_ids_in_use.to_s
    end

    get '/tree' do
      Neo4j.ref_node.rels.map { |rel| rel.end_node.attributes }.inspect
    end

    get '/nodes/0' do
      data_for_node(Neo4j.ref_node, depth).to_json
    end

    get '/nodes/:id' do |id|
      node = Neo4j::Node._load(id)
      data_for_node(node, depth).to_json
    end

    get '/env' do
      p request.env
      request.env.inspect
    end

    get '/eval' do 
      code = params[:code]
      p code
      ret = eval_code code, depth
      if ret.kind_of?(Hash)
        ret.to_json
      else
        { :result => "#{ret}" }.to_json
      end
    end


    private

    def depth
      params[:depth].try(:to_i) || 1
    end

    def eval_code(code, depth)
      code = underscore code
      ret = eval <<-EOT
        begin
          $Depth = #{depth}
          #{code}
        rescue => e
          e
        end
      EOT
    end

    # This changes the code to use the internal versions that
    # don't use classes, but just pure nodes and relations.
    def underscore code
      code.
        gsub(/\bload\b/, '_load').
        gsub(/\brels\b/, '_rels').
        gsub(/\bnode\b/, '_node')
    end

    def viz(*args) 
      depth = $Depth 
      data = { :nodes => [], :rels => [] }
      args.each do |arg|
        data_for(data, arg, depth)
      end
      data
    end<commit_msg>Wrapping code eval in Neo4j transaction<commit_after>require 'sinatra/base'

require 'haml'
require 'sass'
require 'coffee-script'
require 'neo4j'
require 'sprockets'

module Neo; module Viz; end; end

module Neo::Viz

  def self.install_path
    return File.expand_path('../..', __FILE__)
  end

  class App < Sinatra::Base

    configure do
      set :public, File.expand_path('../../public/', __FILE__)
      set :views, File.expand_path('../../views/', __FILE__)
    end

    configure(:development) do
      require 'sinatra/reloader'
      register Sinatra::Reloader
      also_reload "lib/**/*.rb"
    end

    get '/' do
      redirect to('/index')
    end

    get '/index' do
      haml :index
    end

    # Consumers of /embedded have to redefine this method inside
    # the Sprockets environment. See config.ru.
    def root_url
      '.'
    end

    get '/javascripts/main.js' do
      coffee(erb(:'coffeescript/main.coffee'))
    end

    get '/javascripts/canvas_util.js' do
      coffee :'coffeescript/canvas_util'
    end

    get '/embedded' do
      @assets_url_prefix = request.env["rack.mount.prefix"] || ''
      haml :embedded
    end

    get '/stylesheets/main.css' do
      scss :'scss/main'
    end

    get '/node-count' do
      Neo4j.management.get_number_of_node_ids_in_use.to_s
    end

    get '/tree' do
      Neo4j.ref_node.rels.map { |rel| rel.end_node.attributes }.inspect
    end

    get '/nodes/0' do
      data_for_node(Neo4j.ref_node, depth).to_json
    end

    get '/nodes/:id' do |id|
      node = Neo4j::Node._load(id)
      data_for_node(node, depth).to_json
    end

    get '/env' do
      p request.env
      request.env.inspect
    end

    get '/eval' do 
      code = params[:code]
      p code
      ret = eval_code code, depth
      if ret.kind_of?(Hash)
        ret.to_json
      else
        { :result => "#{ret}" }.to_json
      end
    end


    private

    def depth
      params[:depth].try(:to_i) || 1
    end

    def eval_code(code, depth)
      code = underscore code
      ret = eval <<-EOT

        def inner_eval
            #{code}
        end

        result = ''
        begin
          $Depth = #{depth}
          tx = Neo4j::Transaction.new
          result = inner_eval
          tx.success
          result
        rescue => e
          e
        ensure
          tx.finish
        end
      EOT
    end

    # This changes the code to use the internal versions that
    # don't use classes, but just pure nodes and relations.
    def underscore code
      code.
        gsub(/\bload\b/, '_load').
        gsub(/\brels\b/, '_rels').
        gsub(/\bnode\b/, '_node')
    end

    def viz(*args) 
      depth = $Depth 
      data = { :nodes => [], :rels => [] }
      args.each do |arg|
        data_for(data, arg, depth)
      end
      data
    end
{'fraction_non_alphanumeric': 0.11896869244935543, 'fraction_numerical': 0.0029465930018416206, 'mean_word_length': 1.884227296866702, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3571551', 'n_tokens_mistral': 1885, 'n_tokens_neox': 1805, 'n_words': 472}