<commit_before>"""
 BBIOServer - v0.1
 Copyright 2012 <NAME>
 A dynamic web interface library for PyBBIO.
"""

import os, sys, urlparse, traceback
from multiprocessing import Process
from SimpleHTTPServer import SimpleHTTPRequestHandler
from BaseHTTPServer import HTTPServer

from bbio import *

THIS_DIR = os.path.dirname(__file__)
PAGES_DIR = "%s/pages" % THIS_DIR
HEADER = "%s/src/header.html" % THIS_DIR
SIDEBAR = "%s/src/sidebar.html" % THIS_DIR
FOOTER = "%s/src/footer.html" % THIS_DIR
INDEX_TEMPLATE = "%s/src/index.html.template" % THIS_DIR
INDEX = "%s/index.html" % THIS_DIR

# Change working directory to the BBIOServer library directory,
# otherwise the request handler will try to deliver pages from the
# directory where the program using the library is being run from:
os.chdir(THIS_DIR)

# This is where we store the function strings indexed by their
# unique ids:
FUNCTION_STRINGS = {}


class BBIORequestHandler(SimpleHTTPRequestHandler):

  def do_GET(self):
    """ Overrides SimpleHTTPRequestHandler.do_GET() to handle
        PyBBIO function calls. """
    url = self.raw_requestline.split(' ')[1]
    if ('?' in url):
      # We've received a request for a PyBBIO function call,
      # parse out parameters:
      url = url.split('?')[1]
      params = urlparse.parse_qs(url)
      function_id = params['function_id'][0]

      # This should be a key in the FUNCTION_STRINGS dictionary: 
      if (function_id in FUNCTION_STRINGS):
        function = FUNCTION_STRINGS[function_id]

        if ("entry_text" in params):
          # This is a request from a text entry, so we also need to
          # parse out the text to be passed to the function:
          text = params['entry_text'][0]
          if (text == " "):
            # An empty text box is converted into a space character
            # by the Javascript, because otherwise the parsed url
            # would not have an entry_text param and we'd get errors
            # trying to call the function; convert it back:
            text = "" 
          # If we inserted the text into the function string and 
          # evaluated it at this point, the text received would be 
          # evaluated by Python, which we really don't want. If we
          # put it in an extra set of quotes it will evaluate to a 
          # string correctly: 
          text = "'%s'" % text
          function = function % (text)

        # Evaluate the function string and capture the return value
        # in a string (which will be an empty string if function has 
        # no return value):
        response = str(eval(function))

      else:
        # The function id is not in the dictionary. This happens if
        # the server has restarted, which generates new function ids, 
        # and the page has not been refreshed.
        response = "*Refresh page*"

      # Send the HTTP headers:
      self.send_response(200)
      self.send_header('Content-Type', 'text/html')
      # Our length is simply the length of our function return value:
      self.send_header("Content-length", len(response))
      self.send_header('Server', 'PyBBIO Server')
      self.end_headers()

      # And finally we write the response:
      self.wfile.write(response)
      return

    # If we get here there's no function id in the request, which
    # means it's a normal page request; let SimpleHTTPRequestHandler
    # handle it the standard way:
    SimpleHTTPRequestHandler.do_GET(self)
    

class BBIOHTTPServer(HTTPServer):

  def handle_error(self, request, client_address):
    """ Overrides HTTPServer.handle_error(). """
    # Sometimes when refreshing or navigating away from pages with
    # monitor divs, a Broken pipe exception is thrown on the socket
    # level. By overriding handle_error() we are able to ignore these:
    error = traceback.format_exc()
    if ("Broken pipe" in error):
      return

    # Otherwise we want to print the error like normal, except that,
    # because BBIOServer redirects stderr by default, we want it to
    # print to stdout:
    traceback.print_exc(file=sys.stdout)
    print '-'*40
    print 'Exception happened during processing of request from',
    print client_address    
    print '-'*40


class NoPrint():
  # This acts as a file object, but it doesn't print anything.
  def write(self, string):
    pass
  def flush(self):
    pass

class BBIOServer():
  def __init__(self, port=8000, verbose=False):
    if not(verbose):
      # A log of every request to the server is written to stderr.
      # This makes for a lot of printing when using the monitors. 
      # We can avoid this by redirecting stderr to a NoPrint() instance:
      sys.stderr = NoPrint()

    self._server = BBIOHTTPServer(('',port), BBIORequestHandler)

  def start(self, *pages):
    """ Takes a list of Page instances, creates html files, and starts
        the server. """

    # Make sure pages/ directory exists:
    if not(os.path.exists(PAGES_DIR)):
      os.system("mkdir %s" % PAGES_DIR)
    # Remove old pages if any:
    if (os.listdir(PAGES_DIR)):
      os.system("rm %s/*" % PAGES_DIR)
    
    # We treat the first page passed in as the home page and create
    # an index.html page in the base directory that redirects to it:
    home = pages[0]
    with open(INDEX, 'w') as index:
      with open(INDEX_TEMPLATE, 'r') as index_template:
        index.write(index_template.read() % home.filename)

    # Generate a list of links for the sidebar:
    links = ''
    for page in pages:
      links += '<li><a href="%s">%s</a></li>\n' % (page.filename, page.title)

    # Add sidebar to each page and write them to files:
    for page in pages:
      path =  "%s/%s" % (PAGES_DIR, page.filename)
      with open(path, 'w') as f:
        f.write(str(page) % links)

    # The server is started as a subprocess. This way it's easy
    # to catch a KeyboardInterrupt and stop the server happily:
    self._server_process = Process(target=self._server.serve_forever)<commit_msg>make sure at least one page passed to BBIOServer.start()<commit_after>"""
 BBIOServer - v0.1
 Copyright 2012 <NAME>
 A dynamic web interface library for PyBBIO.
"""

import os, sys, urlparse, traceback
from multiprocessing import Process
from SimpleHTTPServer import SimpleHTTPRequestHandler
from BaseHTTPServer import HTTPServer

from bbio import *

THIS_DIR = os.path.dirname(__file__)
PAGES_DIR = "%s/pages" % THIS_DIR
HEADER = "%s/src/header.html" % THIS_DIR
SIDEBAR = "%s/src/sidebar.html" % THIS_DIR
FOOTER = "%s/src/footer.html" % THIS_DIR
INDEX_TEMPLATE = "%s/src/index.html.template" % THIS_DIR
INDEX = "%s/index.html" % THIS_DIR

# Change working directory to the BBIOServer library directory,
# otherwise the request handler will try to deliver pages from the
# directory where the program using the library is being run from:
os.chdir(THIS_DIR)

# This is where we store the function strings indexed by their
# unique ids:
FUNCTION_STRINGS = {}


class BBIORequestHandler(SimpleHTTPRequestHandler):

  def do_GET(self):
    """ Overrides SimpleHTTPRequestHandler.do_GET() to handle
        PyBBIO function calls. """
    url = self.raw_requestline.split(' ')[1]
    if ('?' in url):
      # We've received a request for a PyBBIO function call,
      # parse out parameters:
      url = url.split('?')[1]
      params = urlparse.parse_qs(url)
      function_id = params['function_id'][0]

      # This should be a key in the FUNCTION_STRINGS dictionary: 
      if (function_id in FUNCTION_STRINGS):
        function = FUNCTION_STRINGS[function_id]

        if ("entry_text" in params):
          # This is a request from a text entry, so we also need to
          # parse out the text to be passed to the function:
          text = params['entry_text'][0]
          if (text == " "):
            # An empty text box is converted into a space character
            # by the Javascript, because otherwise the parsed url
            # would not have an entry_text param and we'd get errors
            # trying to call the function; convert it back:
            text = "" 
          # If we inserted the text into the function string and 
          # evaluated it at this point, the text received would be 
          # evaluated by Python, which we really don't want. If we
          # put it in an extra set of quotes it will evaluate to a 
          # string correctly: 
          text = "'%s'" % text
          function = function % (text)

        # Evaluate the function string and capture the return value
        # in a string (which will be an empty string if function has 
        # no return value):
        response = str(eval(function))

      else:
        # The function id is not in the dictionary. This happens if
        # the server has restarted, which generates new function ids, 
        # and the page has not been refreshed.
        response = "*Refresh page*"

      # Send the HTTP headers:
      self.send_response(200)
      self.send_header('Content-Type', 'text/html')
      # Our length is simply the length of our function return value:
      self.send_header("Content-length", len(response))
      self.send_header('Server', 'PyBBIO Server')
      self.end_headers()

      # And finally we write the response:
      self.wfile.write(response)
      return

    # If we get here there's no function id in the request, which
    # means it's a normal page request; let SimpleHTTPRequestHandler
    # handle it the standard way:
    SimpleHTTPRequestHandler.do_GET(self)
    

class BBIOHTTPServer(HTTPServer):

  def handle_error(self, request, client_address):
    """ Overrides HTTPServer.handle_error(). """
    # Sometimes when refreshing or navigating away from pages with
    # monitor divs, a Broken pipe exception is thrown on the socket
    # level. By overriding handle_error() we are able to ignore these:
    error = traceback.format_exc()
    if ("Broken pipe" in error):
      return

    # Otherwise we want to print the error like normal, except that,
    # because BBIOServer redirects stderr by default, we want it to
    # print to stdout:
    traceback.print_exc(file=sys.stdout)
    print '-'*40
    print 'Exception happened during processing of request from',
    print client_address    
    print '-'*40


class NoPrint():
  # This acts as a file object, but it doesn't print anything.
  def write(self, string):
    pass
  def flush(self):
    pass

class BBIOServer():
  def __init__(self, port=8000, verbose=False):
    if not(verbose):
      # A log of every request to the server is written to stderr.
      # This makes for a lot of printing when using the monitors. 
      # We can avoid this by redirecting stderr to a NoPrint() instance:
      sys.stderr = NoPrint()

    self._server = BBIOHTTPServer(('',port), BBIORequestHandler)

  def start(self, *pages):
    """ Takes a list of Page instances, creates html files, and starts
        the server. """

    # Make sure at least one page has been given:
    if not(pages):
      print "*Can't start server - no pages provided."
      return

    # Make sure pages/ directory exists:
    if not(os.path.exists(PAGES_DIR)):
      os.system("mkdir %s" % PAGES_DIR)
    # Remove old pages if any:
    if (os.listdir(PAGES_DIR)):
      os.system("rm %s/*" % PAGES_DIR)
    
    # We treat the first page passed in as the home page and create
    # an index.html page in the base directory that redirects to it:
    home = pages[0]
    with open(INDEX, 'w') as index:
      with open(INDEX_TEMPLATE, 'r') as index_template:
        index.write(index_template.read() % home.filename)

    # Generate a list of links for the sidebar:
    links = ''
    for page in pages:
      links += '<li><a href="%s">%s</a></li>\n' % (page.filename, page.title)

    # Add sidebar to each page and write them to files:
    for page in pages:
      path =  "%s/%s" % (PAGES_DIR, page.filename)
      with open(path, 'w') as f:
        f.write(str(page) % links)

    # The server is started as a subprocess. This way it's easy
    # to catch a KeyboardInterrupt and stop the server happily:
    self._server_process = Process(target=self._server.serve_forever)
{'fraction_non_alphanumeric': 0.0887315828463248, 'fraction_numerical': 0.0036216972590336653, 'mean_word_length': 2.854695431472081, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, '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': '6420478', 'n_tokens_mistral': 3538, 'n_tokens_neox': 3437, 'n_words': 1372}