<commit_before># ----- Info ------------------------------------------------------------------

__author__ = 'Michael Montero <mcmontero@gmail.com>'

# ----- Imports ---------------------------------------------------------------

from tinyAPI.base.services.data import Serializer
from tinyAPI.base.services.data import Validator
from tinyAPI.base.services.exception import SerializerException

import phonenumbers
import tinyAPI
import unittest

# ----- Tests -----------------------------------------------------------------

class DataTestCase(unittest.TestCase):

    def test_serializer_errors(self):
        try:
            Serializer().to_json({'__abc__': 123})

            self.fail('Was able to format a record to JSON even though no '
                      + 'variable was defined.')
        except SerializerException as e:
            self.assertEqual('could not format to JSON for key "__abc__"',
                             e.get_message())

    def test_serializer_simple(self):
        data = Serializer().to_json({'abc': 123})
        self.assertTrue('abc' in data)
        self.assertEqual(123, data['abc'])

    def test_serializer_single(self):
        data = Serializer().to_json({'__one__two': 123})
        self.assertTrue('one' in data)
        self.assertTrue('two' in data['one'])
        self.assertEqual(123, data['one']['two'])

    def test_serializer_double(self):
        data = Serializer().to_json({'__one____two__three': 123})
        self.assertTrue('one' in data)
        self.assertTrue('two' in data['one'])
        self.assertTrue('three' in data['one']['two'])
        self.assertEqual(123, data['one']['two']['three'])

    def test_serializer_triple(self):
        data = Serializer().to_json({'__one____two____three__four': 123})
        self.assertTrue('one' in data)
        self.assertTrue('two' in data['one'])
        self.assertTrue('three' in data['one']['two'])
        self.assertTrue('four' in data['one']['two']['three'])
        self.assertEqual(123, data['one']['two']['three']['four'])

    def test_non_valid_email_addresses(self):
        invalid = [
            '',
            'email',
            'a@',
            '@b.com',
            'a!@b.com',
            'a@b',
            'a@b!.com',
            'a@.com',
            'a@...com',
            'a@b.c^.com',
            'a@b.c',
            'a@b.com@d.com',
            ' a@b.com',
            'a@b.com ',
            'a@b.com\n',
            'a@\nb.com'
        ]

        for em_address in invalid:
            self.assertFalse(Validator().email_is_valid(em_address))

    def test_valid_email_addresses(self):
        valid = [
            'a@b.com',
            'a+b_c@d.com',
            'a.b@c.com',
            'a%b@c.com',
            'a12345@b.com',
            'A@B.COM',
            'a@b.c.d.com',
            'abc@a-b.c.org',
            'a@b.solutions'
        ]

        for em_address in valid:
            self.assertTrue(Validator().email_is_valid(em_address))

    def test_serializer_to_json_none(self):
        self.assertIsNone(Serializer().to_json(None))

    def test_serializer_to_json_depth_errors(self):
        try:
            Serializer().to_json({'__a____b____c____d____e__f': 123})

            self.fail('Was able to serialize to JSON even though the depth '
                      + 'is not supported.')
        except SerializerException as e:
            self.assertEqual(
              'depth of 11 not supported for key "__a____b____c____d____e__f"',
              e.get_message())

    def test_latitude_is_valid(self):
        self.assertTrue(Validator().latitude_is_valid(-90.00))
        self.assertTrue(Validator().latitude_is_valid(90.00))
        self.assertFalse(Validator().latitude_is_valid(-90.01))
        self.assertFalse(Validator().latitude_is_valid(90.01))

    def test_longitude_is_valid(self):
        self.assertTrue(Validator().longitude_is_valid(-180.00))
        self.assertTrue(Validator().longitude_is_valid(180.00))
        self.assertFalse(Validator().longitude_is_valid(-180.01))
        self.assertFalse(Validator().longitude_is_valid(180.01))

    def test_non_us_phone_number(self):
        p = phonenumbers.parse('+442083661177', None)
        self.assertEqual(44, p.country_code)
        self.assertEqual(2083661177, p.national_number)

    def test_us_phone_number(self):
        p = phonenumbers.parse('+17184734811', None)
        self.assertEqual(1, p.country_code)
        self.assertEqual(7184734811, p.national_number)

    def test_is_valid_number(self):
        p = phonenumbers.parse('+11234567890')
        self.assertFalse(phonenumbers.is_possible_number(p))
        self.assertFalse(phonenumbers.is_valid_number(p))

        p = phonenumbers.parse('+17184734811')
        self.assertTrue(phonenumbers.is_possible_number(p))
        self.assertTrue(phonenumbers.is_valid_number(p))

    def test_formatting_e164(self):
        p = phonenumbers.parse('+17184734811')
        self.assertEqual(
            '+17184734811',
            phonenumbers.format_number(p, phonenumbers.PhoneNumberFormat.E164)
        )

    def test_phone_number_is_valid(self):
        self.assertFalse(Validator().phone_number_is_valid('+11234567890'))
        self.assertTrue(Validator().phone_number_is_valid('+17184734811'))

# ----- Main ------------------------------------------------------------------

if __name__ == '__main__':
    unittest.main()
<commit_msg>Fixes for the new PhoneNumbers library.<commit_after># ----- Info ------------------------------------------------------------------

__author__ = 'Michael Montero <mcmontero@gmail.com>'

# ----- Imports ---------------------------------------------------------------

from tinyAPI.base.services.data import Serializer
from tinyAPI.base.services.data import Validator
from tinyAPI.base.services.exception import SerializerException

import phonenumbers
import tinyAPI
import unittest

# ----- Tests -----------------------------------------------------------------

class DataTestCase(unittest.TestCase):

    def test_serializer_errors(self):
        try:
            Serializer().to_json({'__abc__': 123})

            self.fail('Was able to format a record to JSON even though no '
                      + 'variable was defined.')
        except SerializerException as e:
            self.assertEqual('could not format to JSON for key "__abc__"',
                             e.get_message())

    def test_serializer_simple(self):
        data = Serializer().to_json({'abc': 123})
        self.assertTrue('abc' in data)
        self.assertEqual(123, data['abc'])

    def test_serializer_single(self):
        data = Serializer().to_json({'__one__two': 123})
        self.assertTrue('one' in data)
        self.assertTrue('two' in data['one'])
        self.assertEqual(123, data['one']['two'])

    def test_serializer_double(self):
        data = Serializer().to_json({'__one____two__three': 123})
        self.assertTrue('one' in data)
        self.assertTrue('two' in data['one'])
        self.assertTrue('three' in data['one']['two'])
        self.assertEqual(123, data['one']['two']['three'])

    def test_serializer_triple(self):
        data = Serializer().to_json({'__one____two____three__four': 123})
        self.assertTrue('one' in data)
        self.assertTrue('two' in data['one'])
        self.assertTrue('three' in data['one']['two'])
        self.assertTrue('four' in data['one']['two']['three'])
        self.assertEqual(123, data['one']['two']['three']['four'])

    def test_non_valid_email_addresses(self):
        invalid = [
            '',
            'email',
            'a@',
            '@b.com',
            'a!@b.com',
            'a@b',
            'a@b!.com',
            'a@.com',
            'a@...com',
            'a@b.c^.com',
            'a@b.c',
            'a@b.com@d.com',
            ' a@b.com',
            'a@b.com ',
            'a@b.com\n',
            'a@\nb.com'
        ]

        for em_address in invalid:
            self.assertFalse(Validator().email_is_valid(em_address))

    def test_valid_email_addresses(self):
        valid = [
            'a@b.com',
            'a+b_c@d.com',
            'a.b@c.com',
            'a%b@c.com',
            'a12345@b.com',
            'A@B.COM',
            'a@b.c.d.com',
            'abc@a-b.c.org',
            'a@b.solutions'
        ]

        for em_address in valid:
            self.assertTrue(Validator().email_is_valid(em_address))

    def test_serializer_to_json_none(self):
        self.assertIsNone(Serializer().to_json(None))

    def test_serializer_to_json_depth_errors(self):
        try:
            Serializer().to_json({'__a____b____c____d____e__f': 123})

            self.fail('Was able to serialize to JSON even though the depth '
                      + 'is not supported.')
        except SerializerException as e:
            self.assertEqual(
              'depth of 11 not supported for key "__a____b____c____d____e__f"',
              e.get_message())

    def test_latitude_is_valid(self):
        self.assertTrue(Validator().latitude_is_valid(-90.00))
        self.assertTrue(Validator().latitude_is_valid(90.00))
        self.assertFalse(Validator().latitude_is_valid(-90.01))
        self.assertFalse(Validator().latitude_is_valid(90.01))

    def test_longitude_is_valid(self):
        self.assertTrue(Validator().longitude_is_valid(-180.00))
        self.assertTrue(Validator().longitude_is_valid(180.00))
        self.assertFalse(Validator().longitude_is_valid(-180.01))
        self.assertFalse(Validator().longitude_is_valid(180.01))

    def test_non_us_phone_number(self):
        p = phonenumbers.parse('+442083661177', None)
        self.assertEqual(44, p.country_code)
        self.assertEqual(2083661177, p.national_number)

    def test_us_phone_number(self):
        p = phonenumbers.parse('+17184734811', None)
        self.assertEqual(1, p.country_code)
        self.assertEqual(7184734811, p.national_number)

    def test_is_valid_number(self):
        p = phonenumbers.parse('+1123456789')
        self.assertFalse(phonenumbers.is_possible_number(p))
        self.assertFalse(phonenumbers.is_valid_number(p))

        p = phonenumbers.parse('+17184734811')
        self.assertTrue(phonenumbers.is_possible_number(p))
        self.assertTrue(phonenumbers.is_valid_number(p))

    def test_formatting_e164(self):
        p = phonenumbers.parse('+17184734811')
        self.assertEqual(
            '+17184734811',
            phonenumbers.format_number(p, phonenumbers.PhoneNumberFormat.E164)
        )

    def test_phone_number_is_valid(self):
        self.assertFalse(Validator().phone_number_is_valid('+11234567890'))
        self.assertTrue(Validator().phone_number_is_valid('+17184734811'))

# ----- Main ------------------------------------------------------------------

if __name__ == '__main__':
    unittest.main()
<|endoftext|>


<commit_before>from wsgiref.simple_server import make_server

import forgeLandWall.settings as settings

__author__ = 'Jesse'

import forgeLandWall.dbSetup as dbSetup
import forgeLandWall.views as views

def main():
	ip = settings.getIpAddress()
	port = settings.globalVars.portNumber
	dbSetup.setupDB()

	# TEST CODE
	# TODO Need to test this code

	# dbObj = models.messageModel()
	# dbObj.message("dogs")

	# dbObj2 = models.messageModel(21)
	# dbObj2.message("newMessage")
	#
	# dbObj3 = models.messageModel(20)
	# dbObj3.deleteRecord()
	#
	# dbObj4 = models.messageModel(message="fuck")
	# print(dbObj4.message() + " " + dbObj4.getTimestamp())
	#
	# dbObj4 = models.messageModel(message="new")
	# print(dbObj4.message() + " " + dbObj4.getTimestamp())
	#
	# msg = models.messageModel(30)
	# print(msg.message() + msg.getTimestamp())

	print("Serving on: http://" + str(ip) + ":" + str(port))
	httpd = make_server(ip, port, webHandler)
	# httpd.serve_forever()

class webHandler:
	def __init__(self, environ, start_response):
		self.environ = environ
		self.start = start_response

	def __iter__(self):
		path = self.environ['PATH_INFO']

		if path == "/":
			return views.GET_index(self)
		if path == "/post":
			return views.rawPostInput(self)
		if path == "/hi":
			return views.GET_hi(self)
		else:
			return views.notfound(self)

if __name__ == "__main__":  # Runs Script
	main()<commit_msg>Cleaned up main module<commit_after>from wsgiref.simple_server import make_server
import forgeLandWall.settings as settings

__author__ = 'Jesse'

import forgeLandWall.dbSetup as dbSetup
import forgeLandWall.views as views

def main():
	ip = settings.getIpAddress()
	port = settings.globalVars.portNumber
	dbSetup.setupDB()

	print("Serving on: http://" + str(ip) + ":" + str(port))
	httpd = make_server(ip, port, webHandler)
	httpd.serve_forever()

class webHandler:
	def __init__(self, environ, start_response):
		self.environ = environ
		self.start = start_response

	def __iter__(self):
		path = self.environ['PATH_INFO']

		if path == "/":
			return views.GET_index(self)
		if path == "/post":
			return views.rawPostInput(self)
		if path == "/hi":
			return views.GET_hi(self)
		else:
			return views.notfound(self)

if __name__ == "__main__":  # Runs Script
	main()<|endoftext|>


<commit_before>#!/usr/bin/env python

import codecs
import os
import re
import operator
import logging

from localization_objects import *

# Regexp to parse and inspect strings in format JTL('Key Name', 'Key Comment')
JTL_REGEX = r"""JTL\(['"](.+?)['"],\s*['"](.+?)['"]\)"""

# Regexp to parse and inspect localization entries in the strings file.
HEADER_COMMENT_KEY_VALUE_TUPLES_REGEX = '((/\*\*\* *[^\n]*? *\*\*\*/\n\n)*)(/\* *[^;]* *\*/\n)"(.*?)" *= *"(.*?)";\s*\n'

def rewrite_localization_file_with_entry_modifications(localizable_file, output_file, modification_func):

    file_descriptor = open_strings_file(localizable_file, "r")

    output_file_elements = []

    for header_comment, comments, key, value in extract_header_comment_key_value_tuples_from_file(file_descriptor):

        if len(header_comment) > 0:
            output_file_elements.append(Comment(header_comment))

        output_file_elements.append(modification_func(LocalizationEntry(comments, key, value)))

    write_file_elements_to_strings_file(output_file, output_file_elements)

def open_strings_file(file_path, mode):
    """ Open the strings file

    Args:
        file_path (str): The path to the strings file
        mode (str): string representation of the mode in which to open the file (read, write, append, etc.)
    """
    return codecs.open(file_path, mode, "utf-16")

def write_file_elements_to_strings_file(file_path, file_elements):
    """ Write elements to the string file

    Args:
        file_path (str): The path to the strings file
        file_elements (list) : List of elements to write to the file.
    """
    f = open_strings_file(file_path, "w")
    for element in file_elements:
        f.write(unicode(element))
        f.write(u"\n")

    f.close()

def setup_logging(args=None):
    """ Setup logging module.

    Args:
        args (optional): The arguments returned by the argparse module.
    """
    if args is not None and args.log_path != "":
        logging.basicConfig(filename=args.log_path, level=logging.INFO)
    else:
        logging.basicConfig(level=logging.INFO)

def __generate_localization_dictionary_from_file(file_path, localization_entry_attribute_name_for_key):
    """ Generates a dictionary mapping between keys (defined by the given attribute name) and localization entries.

    Args:
        file_path (str): The strings file path.
        localization_entry_attribute_name_for_key: The name of the attribute of LocalizationEntry to use as key.

    Returns:
        dict: A dictionary mapping between keys (defined by the given attribute name) and localization entries.
    """
    localization_dictionary = {}
    f = open_strings_file(file_path, "r+")
    header_comment_key_value_tuples = extract_header_comment_key_value_tuples_from_file(f)
    for header_comment, comments, key, value in header_comment_key_value_tuples:
        localization_entry = LocalizationEntry(comments, key, value)
        localization_dictionary[localization_entry.__getattribute__(localization_entry_attribute_name_for_key)] = localization_entry
    f.close()
    return localization_dictionary

def generate_localization_key_to_entry_dictionary_from_file(file_path):
    """ Generates a dictionary mapping between localization keys and entries.

    Args:
        file_path (str): The strings file path.

    Returns:
        dict: A dictionary mapping between localization keys and entries.
    """
    return __generate_localization_dictionary_from_file(file_path, "key")

def generate_localization_value_to_entry_dictionary_from_file(file_path):
    """ Generates a dictionary mapping between localization values and entries.

    Args:
        file_path (str): The strings file path.

    Returns:
        dict: A dictionary mapping between localization values and entries.
    """
    return __generate_localization_dictionary_from_file(file_path, "value")

def extract_header_comment_key_value_tuples_from_file(file_descriptor):
    """ Extracts tuples representing comments and localization entries from strings file.

    Args:
        file_descriptor (file): The file to read the tuples from

    Returns:
        list : List of tuples representing the headers and localization entries.

    """
    file_data = file_descriptor.read()
    findall_result = re.findall(HEADER_COMMENT_KEY_VALUE_TUPLES_REGEX, file_data, re.MULTILINE | re.DOTALL)

    returned_list = []
    for header_comment, _ignored, raw_comments, key, value in findall_result:
        comments = re.findall("/\* (.*?) \*/", raw_comments)
        if len(comments) == 0:
            comments = [u""]
        returned_list.append((header_comment, comments, key, value))

    return returned_list

def extract_jtl_string_pairs_from_text_file(results_dict, file_path):
    """ Extracts all string pairs matching the JTL pattern from given text file.

    This can be used as an "extract_func" argument in the extract_string_pairs_in_directory method.

    Args:
        results_dict (dict): The dict to add the the string pairs to.
        file_path (str): The path of the file from which to extract the string pairs.

    """
    result_pairs = re.findall(JTL_REGEX, open(file_path).read())
    for result_key, result_comment in result_pairs:
        results_dict[result_key] = result_comment
    return results_dict

def extract_string_pairs_in_directory(directory_path, extract_func, filter_func):
    """ Retrieves all string pairs in the directory

    Args:
        directory_path (str): The path of the directory containing the file to extract string pairs from.
        extract_func (function): Function for extracting the localization keys and comments from the files.
            The extract function receives 2 parameters:
            - dict that the keys (a key in the dict) and comments (a value in the dict) are added to.
            - str representing file path

        filter_func (function): Function for filtering files in the directory.
            The filter function receives the file name and returns a bool representing the filter result.
            True if the file name passed the filter, False otherwise.

    Returns:
        dict: A mapping between string pairs first value (probably the key), and the second value (probably the comment).
    """
    result = {}
    for root, dirnames, filenames in os.walk(directory_path):
        for file_name in filenames:
            if filter_func(file_name):
                file_path = os.path.join(root, file_name)
                try:
                    extract_func(result, file_path)
                except Exception as e:
                    print "Error in file " + file_name
                    print e
    return result

def write_entry_to_file(file_descriptor, entry_comment, entry_key):
    """ Writes a localization entry to the file

    Args:
        file_descriptor (file, instance): The file to write the entry to.
        entry_comment (str): The entry's comment.
        entry_key (str): The entry's key.
    """
    escaped_key = re.sub(r'([^\\])"', '\\1\\"', entry_key)
    file_descriptor.write(u'/* %s */\n' % entry_comment)
    file_descriptor.write(u'"%s" = "%s";\n' % (escaped_key, escaped_key))

def write_section_header_to_file(file_descriptor, section_name):
    """ Writes a section header to the file

    Args:
        file_descriptor (file, instance): The file to writes the section header to.
        section_name (str): The name of the section.
    """
    file_descriptor.write('/*** %s ***/\n' % section_name)

def append_dictionary_to_file(localization_key_to_comment, file_path, section_name):
    """ Appends dictionary of localization keys and comments to a file

    Args:
        localization_key_to_comment (dict): A mapping between localization keys and comments.
        file_path (str): The path of the file to append to.
        section_name (str): The name of the section.

    """
    output_file = open_strings_file(file_path, "a")
    write_section_header_to_file(output_file, section_name)
    for entry_key, entry_comment in sorted(localization_key_to_comment.iteritems(), key=operator.itemgetter(1)):
        output_file.write(u'\n')
        write_entry_to_file(output_file, entry_comment, entry_key)
    output_file.close()

def write_dict_to_new_file(file_name, localization_key_to_comment):
    """ Writes dictionary of localization keys and comments to a file.

    Args:
        localization_key_to_comment (dict): A mapping between localization keys and comments.
        file_path (str): The path of the file to append to.

    """
    output_file_descriptor = open_strings_file(file_name, "w")
    for entry_key, entry_comment in sorted(localization_key_to_comment.iteritems(), key=operator.itemgetter(1)):
        write_entry_to_file(output_file_descriptor, entry_comment, entry_key)
        output_file_descriptor.write(u'\n')
    output_file_descriptor.close()
<commit_msg>Adding a warning when no strings were found in a file<commit_after>#!/usr/bin/env python

import codecs
import os
import re
import operator
import logging

from localization_objects import *

# Regexp to parse and inspect strings in format JTL('Key Name', 'Key Comment')
JTL_REGEX = r"""JTL\(['"](.+?)['"],\s*['"](.+?)['"]\)"""

# Regexp to parse and inspect localization entries in the strings file.
HEADER_COMMENT_KEY_VALUE_TUPLES_REGEX = '((/\*\*\* *[^\n]*? *\*\*\*/\n\n)*)(/\* *[^;]* *\*/\n)"(.*?)" *= *"(.*?)";\s*\n'

def rewrite_localization_file_with_entry_modifications(localizable_file, output_file, modification_func):

    file_descriptor = open_strings_file(localizable_file, "r")

    output_file_elements = []

    for header_comment, comments, key, value in extract_header_comment_key_value_tuples_from_file(file_descriptor):

        if len(header_comment) > 0:
            output_file_elements.append(Comment(header_comment))

        output_file_elements.append(modification_func(LocalizationEntry(comments, key, value)))

    write_file_elements_to_strings_file(output_file, output_file_elements)

def open_strings_file(file_path, mode):
    """ Open the strings file

    Args:
        file_path (str): The path to the strings file
        mode (str): string representation of the mode in which to open the file (read, write, append, etc.)
    """
    return codecs.open(file_path, mode, "utf-16")

def write_file_elements_to_strings_file(file_path, file_elements):
    """ Write elements to the string file

    Args:
        file_path (str): The path to the strings file
        file_elements (list) : List of elements to write to the file.
    """
    f = open_strings_file(file_path, "w")
    for element in file_elements:
        f.write(unicode(element))
        f.write(u"\n")

    f.close()

def setup_logging(args=None):
    """ Setup logging module.

    Args:
        args (optional): The arguments returned by the argparse module.
    """
    if args is not None and args.log_path != "":
        logging.basicConfig(filename=args.log_path, level=logging.INFO)
    else:
        logging.basicConfig(level=logging.INFO)

def __generate_localization_dictionary_from_file(file_path, localization_entry_attribute_name_for_key):
    """ Generates a dictionary mapping between keys (defined by the given attribute name) and localization entries.

    Args:
        file_path (str): The strings file path.
        localization_entry_attribute_name_for_key: The name of the attribute of LocalizationEntry to use as key.

    Returns:
        dict: A dictionary mapping between keys (defined by the given attribute name) and localization entries.
    """
    localization_dictionary = {}
    f = open_strings_file(file_path, "r+")
    header_comment_key_value_tuples = extract_header_comment_key_value_tuples_from_file(f)

    if len(header_comment_key_value_tuples) == 0:
        logging.warning("Couldn't find any strings in file '%s'. Check encoding and format." % file_path)

    for header_comment, comments, key, value in header_comment_key_value_tuples:
        localization_entry = LocalizationEntry(comments, key, value)
        localization_dictionary[localization_entry.__getattribute__(localization_entry_attribute_name_for_key)] = localization_entry
    f.close()
    return localization_dictionary

def generate_localization_key_to_entry_dictionary_from_file(file_path):
    """ Generates a dictionary mapping between localization keys and entries.

    Args:
        file_path (str): The strings file path.

    Returns:
        dict: A dictionary mapping between localization keys and entries.
    """
    return __generate_localization_dictionary_from_file(file_path, "key")

def generate_localization_value_to_entry_dictionary_from_file(file_path):
    """ Generates a dictionary mapping between localization values and entries.

    Args:
        file_path (str): The strings file path.

    Returns:
        dict: A dictionary mapping between localization values and entries.
    """
    return __generate_localization_dictionary_from_file(file_path, "value")

def extract_header_comment_key_value_tuples_from_file(file_descriptor):
    """ Extracts tuples representing comments and localization entries from strings file.

    Args:
        file_descriptor (file): The file to read the tuples from

    Returns:
        list : List of tuples representing the headers and localization entries.

    """
    file_data = file_descriptor.read()
    findall_result = re.findall(HEADER_COMMENT_KEY_VALUE_TUPLES_REGEX, file_data, re.MULTILINE | re.DOTALL)

    returned_list = []
    for header_comment, _ignored, raw_comments, key, value in findall_result:
        comments = re.findall("/\* (.*?) \*/", raw_comments)
        if len(comments) == 0:
            comments = [u""]
        returned_list.append((header_comment, comments, key, value))

    return returned_list

def extract_jtl_string_pairs_from_text_file(results_dict, file_path):
    """ Extracts all string pairs matching the JTL pattern from given text file.

    This can be used as an "extract_func" argument in the extract_string_pairs_in_directory method.

    Args:
        results_dict (dict): The dict to add the the string pairs to.
        file_path (str): The path of the file from which to extract the string pairs.

    """
    result_pairs = re.findall(JTL_REGEX, open(file_path).read())
    for result_key, result_comment in result_pairs:
        results_dict[result_key] = result_comment
    return results_dict

def extract_string_pairs_in_directory(directory_path, extract_func, filter_func):
    """ Retrieves all string pairs in the directory

    Args:
        directory_path (str): The path of the directory containing the file to extract string pairs from.
        extract_func (function): Function for extracting the localization keys and comments from the files.
            The extract function receives 2 parameters:
            - dict that the keys (a key in the dict) and comments (a value in the dict) are added to.
            - str representing file path

        filter_func (function): Function for filtering files in the directory.
            The filter function receives the file name and returns a bool representing the filter result.
            True if the file name passed the filter, False otherwise.

    Returns:
        dict: A mapping between string pairs first value (probably the key), and the second value (probably the comment).
    """
    result = {}
    for root, dirnames, filenames in os.walk(directory_path):
        for file_name in filenames:
            if filter_func(file_name):
                file_path = os.path.join(root, file_name)
                try:
                    extract_func(result, file_path)
                except Exception as e:
                    print "Error in file " + file_name
                    print e
    return result

def write_entry_to_file(file_descriptor, entry_comment, entry_key):
    """ Writes a localization entry to the file

    Args:
        file_descriptor (file, instance): The file to write the entry to.
        entry_comment (str): The entry's comment.
        entry_key (str): The entry's key.
    """
    escaped_key = re.sub(r'([^\\])"', '\\1\\"', entry_key)
    file_descriptor.write(u'/* %s */\n' % entry_comment)
    file_descriptor.write(u'"%s" = "%s";\n' % (escaped_key, escaped_key))

def write_section_header_to_file(file_descriptor, section_name):
    """ Writes a section header to the file

    Args:
        file_descriptor (file, instance): The file to writes the section header to.
        section_name (str): The name of the section.
    """
    file_descriptor.write('/*** %s ***/\n' % section_name)

def append_dictionary_to_file(localization_key_to_comment, file_path, section_name):
    """ Appends dictionary of localization keys and comments to a file

    Args:
        localization_key_to_comment (dict): A mapping between localization keys and comments.
        file_path (str): The path of the file to append to.
        section_name (str): The name of the section.

    """
    output_file = open_strings_file(file_path, "a")
    write_section_header_to_file(output_file, section_name)
    for entry_key, entry_comment in sorted(localization_key_to_comment.iteritems(), key=operator.itemgetter(1)):
        output_file.write(u'\n')
        write_entry_to_file(output_file, entry_comment, entry_key)
    output_file.close()

def write_dict_to_new_file(file_name, localization_key_to_comment):
    """ Writes dictionary of localization keys and comments to a file.

    Args:
        localization_key_to_comment (dict): A mapping between localization keys and comments.
        file_path (str): The path of the file to append to.

    """
    output_file_descriptor = open_strings_file(file_name, "w")
    for entry_key, entry_comment in sorted(localization_key_to_comment.iteritems(), key=operator.itemgetter(1)):
        write_entry_to_file(output_file_descriptor, entry_comment, entry_key)
        output_file_descriptor.write(u'\n')
    output_file_descriptor.close()
<|endoftext|>


<commit_before># Django settings for fortuitus project.
import os

WORKDIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

DEBUG = True
TEMPLATE_DEBUG = DEBUG

ADMINS = (
    # ('Your Name', 'your_email@example.com'),
)

MANAGERS = ADMINS

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': 'fortuitus.sqlite',                      # Or path to database file if using sqlite3.
        'USER': '',                      # Not used with sqlite3.
        'PASSWORD': '',                  # Not used with sqlite3.
        'HOST': '',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
    }
}

# Local time zone for this installation. Choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
# although not all choices may be available on all operating systems.
# In a Windows environment this must be set to your system time zone.
TIME_ZONE = 'America/Chicago'

# Language code for this installation. All choices can be found here:
# http://www.i18nguy.com/unicode/language-identifiers.html
LANGUAGE_CODE = 'en-us'

SITE_ID = 1

# If you set this to False, Django will make some optimizations so as not
# to load the internationalization machinery.
USE_I18N = True

# If you set this to False, Django will not format dates, numbers and
# calendars according to the current locale.
USE_L10N = True

# If you set this to False, Django will not use timezone-aware datetimes.
USE_TZ = True

# Absolute filesystem path to the directory that will hold user-uploaded files.
# Example: "/home/media/media.lawrence.com/media/"
MEDIA_ROOT = ''

# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash.
# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
MEDIA_URL = ''

# Absolute path to the directory static files should be collected to.
# Don't put anything in this directory yourself; store your static files
# in apps' "static/" subdirectories and in STATICFILES_DIRS.
# Example: "/home/media/media.lawrence.com/static/"
STATIC_ROOT = os.path.join(WORKDIR, 'static')

# URL prefix for static files.
# Example: "http://media.lawrence.com/static/"
STATIC_URL = '/static/'

# Additional locations of static files
STATICFILES_DIRS = (os.path.join(WORKDIR, 'my_static'),)

# List of finder classes that know how to find static files in
# various locations.
STATICFILES_FINDERS = (
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
#    'django.contrib.staticfiles.finders.DefaultStorageFinder',
    'compressor.finders.CompressorFinder',
)

# Make this unique, and don't share it with anybody.
SECRET_KEY = '_1d50#kedv79grq$zqdzax2c2*z*0p&ksjcew&92w$3agqyru^'

# List of callables that know how to import templates from various sources.
TEMPLATE_LOADERS = (
    'django.template.loaders.filesystem.Loader',
    'django.template.loaders.app_directories.Loader',
#     'django.template.loaders.eggs.Loader',
)

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

ROOT_URLCONF = 'fortuitus.urls'

# Python dotted path to the WSGI application used by Django's runserver.
WSGI_APPLICATION = 'fortuitus.wsgi.application'

TEMPLATE_DIRS = (os.path.join(WORKDIR, 'templates'),)

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.admin',
#    'django.contrib.admindocs',
    'south',
    'compressor',

    'fortuitus.fcore',
    'fortuitus.feditor',
)

# A sample logging configuration. The only tangible logging
# performed by this configuration is to send an email to
# the site admins on every HTTP 500 error when DEBUG=False.
# See http://docs.djangoproject.com/en/dev/topics/logging for
# more details on how to customize your logging configuration.
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'filters': {
        'require_debug_false': {
            '()': 'django.utils.log.RequireDebugFalse'
        }
    },
    'handlers': {
        'mail_admins': {
            'level': 'ERROR',
            'filters': ['require_debug_false'],
            'class': 'django.utils.log.AdminEmailHandler'
        }
    },
    'loggers': {
        'django.request': {
            'handlers': ['mail_admins'],
            'level': 'ERROR',
            'propagate': True,
        },
    }
}

# Django-compressor settings
COMPRESS_OFFLINE = True
COMPRESS_CSS_FILTERS = (
    'compressor.filters.cssmin.CSSMinFilter',
    'compressor.filters.datauri.CssDataUriFilter',
)
COMPRESS_JS_FILTERS = ('compressor.filters.jsmin.SlimItFilter',)

try:
    from settings_local import *
except ImportError:
    pass
<commit_msg>Add django-celery settings<commit_after># Django settings for fortuitus project.
import os

WORKDIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

DEBUG = True
TEMPLATE_DEBUG = DEBUG

ADMINS = (
    # ('Your Name', 'your_email@example.com'),
)

MANAGERS = ADMINS

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
        'NAME': 'fortuitus.sqlite',                      # Or path to database file if using sqlite3.
        'USER': '',                      # Not used with sqlite3.
        'PASSWORD': '',                  # Not used with sqlite3.
        'HOST': '',                      # Set to empty string for localhost. Not used with sqlite3.
        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
    }
}

# Local time zone for this installation. Choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
# although not all choices may be available on all operating systems.
# In a Windows environment this must be set to your system time zone.
TIME_ZONE = 'America/Chicago'

# Language code for this installation. All choices can be found here:
# http://www.i18nguy.com/unicode/language-identifiers.html
LANGUAGE_CODE = 'en-us'

SITE_ID = 1

# If you set this to False, Django will make some optimizations so as not
# to load the internationalization machinery.
USE_I18N = True

# If you set this to False, Django will not format dates, numbers and
# calendars according to the current locale.
USE_L10N = True

# If you set this to False, Django will not use timezone-aware datetimes.
USE_TZ = True

# Absolute filesystem path to the directory that will hold user-uploaded files.
# Example: "/home/media/media.lawrence.com/media/"
MEDIA_ROOT = ''

# URL that handles the media served from MEDIA_ROOT. Make sure to use a
# trailing slash.
# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
MEDIA_URL = ''

# Absolute path to the directory static files should be collected to.
# Don't put anything in this directory yourself; store your static files
# in apps' "static/" subdirectories and in STATICFILES_DIRS.
# Example: "/home/media/media.lawrence.com/static/"
STATIC_ROOT = os.path.join(WORKDIR, 'static')

# URL prefix for static files.
# Example: "http://media.lawrence.com/static/"
STATIC_URL = '/static/'

# Additional locations of static files
STATICFILES_DIRS = (os.path.join(WORKDIR, 'my_static'),)

# List of finder classes that know how to find static files in
# various locations.
STATICFILES_FINDERS = (
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
#    'django.contrib.staticfiles.finders.DefaultStorageFinder',
    'compressor.finders.CompressorFinder',
)

# Make this unique, and don't share it with anybody.
SECRET_KEY = '_1d50#kedv79grq$zqdzax2c2*z*0p&ksjcew&92w$3agqyru^'

# List of callables that know how to import templates from various sources.
TEMPLATE_LOADERS = (
    'django.template.loaders.filesystem.Loader',
    'django.template.loaders.app_directories.Loader',
#     'django.template.loaders.eggs.Loader',
)

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

ROOT_URLCONF = 'fortuitus.urls'

# Python dotted path to the WSGI application used by Django's runserver.
WSGI_APPLICATION = 'fortuitus.wsgi.application'

TEMPLATE_DIRS = (os.path.join(WORKDIR, 'templates'),)

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.admin',
#    'django.contrib.admindocs',
    'south',
    'compressor',
    'djcelery',

    'fortuitus.fcore',
    'fortuitus.feditor',
)

# A sample logging configuration. The only tangible logging
# performed by this configuration is to send an email to
# the site admins on every HTTP 500 error when DEBUG=False.
# See http://docs.djangoproject.com/en/dev/topics/logging for
# more details on how to customize your logging configuration.
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'filters': {
        'require_debug_false': {
            '()': 'django.utils.log.RequireDebugFalse'
        }
    },
    'handlers': {
        'mail_admins': {
            'level': 'ERROR',
            'filters': ['require_debug_false'],
            'class': 'django.utils.log.AdminEmailHandler'
        }
    },
    'loggers': {
        'django.request': {
            'handlers': ['mail_admins'],
            'level': 'ERROR',
            'propagate': True,
        },
    }
}

# Django-compressor settings
COMPRESS_OFFLINE = True
COMPRESS_CSS_FILTERS = (
    'compressor.filters.cssmin.CSSMinFilter',
    'compressor.filters.datauri.CssDataUriFilter',
)
COMPRESS_JS_FILTERS = ('compressor.filters.jsmin.SlimItFilter',)

# Celery settings
import djcelery
djcelery.setup_loader()

BROKER_URL = 'django://'

try:
    from settings_local import *
except ImportError:
    pass
<|endoftext|>


<commit_before>"""
multiplication-table.py
Author: <your name here>
Credit: <list sources used, if any>
Assignment:

Write and submit a Python program that prints a multiplication table. The user
must be able to determine the width and height of the table before it is printed.

The final multiplication table should look like this:

Width of multiplication table: 10
Height of multiplication table: 8

  1   2   3   4   5   6   7   8   9  10
  2   4   6   8  10  12  14  16  18  20
  3   6   9  12  15  18  21  24  27  30
  4   8  12  16  20  24  28  32  36  40
  5  10  15  20  25  30  35  40  45  50
  6  12  18  24  30  36  42  48  54  60
  7  14  21  28  35  42  49  56  63  70
  8  16  24  32  40  48  56  64  72  80
"""

i = input ("Width of multiplication table: ")
i = int(i)
j = input ("Height of multiplication table: ")
j = int(j)
for x in range(j)
    print ["X" for x in range(i)]

    <commit_msg>Updated from Brython Server: 9/21/2015 2:54:07 PM<commit_after>"""
multiplication-table.py
Author: <your name here>
Credit: <list sources used, if any>
Assignment:

Write and submit a Python program that prints a multiplication table. The user
must be able to determine the width and height of the table before it is printed.

The final multiplication table should look like this:

Width of multiplication table: 10
Height of multiplication table: 8

  1   2   3   4   5   6   7   8   9  10
  2   4   6   8  10  12  14  16  18  20
  3   6   9  12  15  18  21  24  27  30
  4   8  12  16  20  24  28  32  36  40
  5  10  15  20  25  30  35  40  45  50
  6  12  18  24  30  36  42  48  54  60
  7  14  21  28  35  42  49  56  63  70
  8  16  24  32  40  48  56  64  72  80
"""

i = input ("Width of multiplication table: ")
i = int(i)
j = input ("Height of multiplication table: ")
j = int(j)
for t in range(j)
    x = 1
    while x < i:
        print ("X  ")
        x = x + 1

    <|endoftext|>


<commit_before>"""
multiplication-table.py
Author: <your name here>
Credit: <list sources used, if any>
Assignment:

Write and submit a Python program that prints a multiplication table. The user
must be able to determine the width and height of the table before it is printed.

The final multiplication table should look like this:

Width of multiplication table: 10
Height of multiplication table: 8

  1   2   3   4   5   6   7   8   9  10
  2   4   6   8  10  12  14  16  18  20
  3   6   9  12  15  18  21  24  27  30
  4   8  12  16  20  24  28  32  36  40
  5  10  15  20  25  30  35  40  45  50
  6  12  18  24  30  36  42  48  54  60
  7  14  21  28  35  42  49  56  63  70
  8  16  24  32  40  48  56  64  72  80
"""
width=[1,2,3,4,5,6,7,8,9,10]
height=[1,2,3,4,5,6,7,8]
l=[0]
for y in width:
    for x in height:
        l.append(y*x)
    print(str(l))<commit_msg>Updated from Brython Server: February 4, 2016 2:24:15 PM EST<commit_after>"""
multiplication-table.py
Author: <your name here>
Credit: <list sources used, if any>
Assignment:

Write and submit a Python program that prints a multiplication table. The user
must be able to determine the width and height of the table before it is printed.

The final multiplication table should look like this:

Width of multiplication table: 10
Height of multiplication table: 8

  1   2   3   4   5   6   7   8   9  10
  2   4   6   8  10  12  14  16  18  20
  3   6   9  12  15  18  21  24  27  30
  4   8  12  16  20  24  28  32  36  40
  5  10  15  20  25  30  35  40  45  50
  6  12  18  24  30  36  42  48  54  60
  7  14  21  28  35  42  49  56  63  70
  8  16  24  32  40  48  56  64  72  80
"""
width=[1,2,3,4,5,6,7,8,9,10]
height=[1,2,3,4,5,6,7,8]
l=[0]
for y in width:
    for x in height:
        print(y*x, " ", end="")<|endoftext|>


<commit_before>ec0debe6-2ead-11e5-8557-7831c1d44c14<commit_msg>Final commit :sunglasses:<commit_after>print('Hello world')<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
#import lxml.html
#import lxml.etree
import requests
import urlparse
import re
from random import choice
import urllib
from BaseHTTPServer import BaseHTTPRequestHandler
import chardet
import htmlentitydefs
from hurry import filesize

import time

import plugin

defaults = {
        'http_url_blacklist': [],
        }

user_agents = [
    'Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11',
    'Opera/9.25 (Windows NT 5.1; U; en)',
    'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)',
    'Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.5 (like Gecko) (Kubuntu)',
    'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.12) Gecko/20070731 Ubuntu/dapper-security Firefox/1.5.0.12',
    'Lynx/2.8.5rel.1 libwww-FM/2.14 SSL-MM/1.4.1 GNUTLS/1.2.9'
]
html_types = ['text/html','application/xhtml+xml']
redirect_codes = [301,302,303]

responses = BaseHTTPRequestHandler.responses

def choose_agent():
    return choice(user_agents)

def ajax_url(url):
    """ AJAX HTML snapshot URL parsing, pretty much required for a modern scraper. """
    """ https://developers.google.com/webmasters/ajax-crawling/docs/specification """
    hashbang_index = url.find('#!')
    if hashbang_index != -1:
        base = url[:hashbang_index]
        joiner = '?' if '?' not in base else '&'
        url = ''.join((base, joiner, '_escaped_fragment_=', urllib.quote(url[hashbang_index+2:], '=')))
    return url

def prettify_url(url):
    """ Removes URL baggage to display a clean hostname/path. """
    """ Can be passed a string or a urlparse.ParseResult object. """
    if isinstance(url, urlparse.ParseResult) == False:
        url = urlparse.urlparse(url)
    return url.hostname + re.sub('/$', '', url.path)

class NoTitleError(Exception):
    def __init__(self):
        pass

""" Thanks to Fredrik Lundh: http://effbot.org/zone/re-sub.htm#unescape-html """
##
# Removes HTML or XML character references and entities from a text string.
#
# @param text The HTML (or XML) source text.
# @return The plain text, as a Unicode string, if necessary.
def unescape(text):
    def fixup(m):
        text = m.group(0)
        if text[:2] == "&#":
            # character reference
            try:
                if text[:3] == "&#x":
                    return unichr(int(text[3:-1], 16))
                else:
                    return unichr(int(text[2:-1]))
            except ValueError:
                pass
        else:
            # named entity
            try:
                text = unichr(htmlentitydefs.name2codepoint[text[1:-1]])
            except KeyError:
                pass
        return text # leave as is
    return re.sub("&#?\w+;", fixup, text)

filesizes = [
    (1024 ** 5, ' PiB'),
    (1024 ** 4, ' TiB'),
    (1024 ** 3, ' GiB'),
    (1024 ** 2, ' MiB'),
    (1024 ** 1, ' KiB'),
    (1024 ** 0, ' B'),
    ]

class Plugin(plugin.Plugin):
    def register_commands(self):
        self.regexes = [
                ('(?i).*https?://.', self.title)
                ]

    def title(self, message, args):
        """ Returns the HTML title tag of URLs posted.
        $https://twitter.com/#!/camh/statuses/147449116551680001
        >Twitter / Cameron Kenley Hunt: There are only three hard  ... \x03#|\x03 \x02twitter.com\x02
        """
        for word in re.findall('(?iu)https?://.*?(?=\\s|\\Z)', message.content.decode('utf-8')):
            permitted = True

            for i in self.conf.conf['http_url_blacklist']:
                channel, blacklist = i.split(' ')

                if channel == message.source and re.match(blacklist, word):
                    permitted = False

            if permitted:
                """ Set it up. """
                url_parsed = urlparse.urlparse(word)
                url_hostname = url_parsed.hostname
                word = ajax_url(self.irc.strip_formatting(word))
                agent = choose_agent()
                request_headers = {'User-Agent': agent}
                request_headers_405 = {'User-Agent': agent, 'Range': 'bytes=1-5'}

                """ GO! """
                start_time = time.time()
                try:
                    resource = requests.head(word, headers=request_headers, allow_redirects=True)
                    if resource.status_code == 405:
                        resource = requests.get(word, headers=request_headers_405, allow_redirects=True)
                    else:
                        resource.raise_for_status()

                    if resource.history != [] and resource.history[-1].status_code in redirect_codes:
                        word = resource.history[-1].headers['Location']
                        redirection_url = urlparse.urlparse(word)
                        if redirection_url.netloc == '':
                            word = ''.join((url_parsed.scheme, '://', url_parsed.netloc, redirection_url.path))
                        elif redirection_url.hostname != url_hostname:
                            url_hostname = '%s \x03#->\x03 %s' % (url_hostname, prettify_url(word))
                        word = ajax_url(word)

                    resource_type = resource.headers['Content-Type'].split(';')[0]
                    if resource_type in html_types:
                        resource = requests.get(word, headers=request_headers)
                        resource.raise_for_status()
                        if resource.encoding == 'ISO-8859-1':
                            resource.encoding = chardet.detect(resource.content)['encoding']
                        """Seems that most pages claiming to be XHTML—including many large websites—
                        are not strict enough to parse correctly, usually for some very minor reason,
                        and it's a waste to attempt to parse it as XML first. This code will remain
                        for the day we can reliably parse XHTML as XML for the majority of sites."""
                        #if (html_types[1] in resource_type) or (('xhtml' or 'xml') in resource.text.split('>')[0].lower()):  # application/xhtml+xml
                        #    title = lxml.etree.fromstring(resource.text).find('.//xhtml:title', namespaces={'xhtml':'http://www.w3.org/1999/xhtml'}).text.strip()
                        #else:  # text/html

                        #title = lxml.html.fromstring(resource.text).find(".//title").text.replace('\n','').strip()
                        title = re.findall('(?si)(?<=<title>).*(?=</title>)', resource.text)[0]
                        if title == '':
                            raise NoTitleError
                        else:
                            title = re.sub('(?s)\s+', ' ', unescape(title).strip())
                    else:
                        """TODO: Make this feature togglable, since it can seem spammy for image dumps."""
                        raise NoTitleError
                except requests.exceptions.ConnectionError:
                    title = 'server connection error'
                except requests.exceptions.HTTPError, httpe:
                    title = '%s %s' % (httpe.response.status_code, responses[httpe.response.status_code][0])
                except NoTitleError:
                    try:
                        data_length = filesize.size(float(resource.headers['Content-Length']), filesizes)
                    except TypeError:
                        data_length = 'size unknown'
                    title = '%s \x03#|\x03 %s' % (resource_type, data_length)
                end_time = time.time()

                time_length = '%s seconds' % round(end_time-start_time, 2)
                summary = '%s \x03#|\x03 %s \x03#|\x03 \x02%s\x02' % (title, time_length, url_hostname)
                self.irc.privmsg(message.source, summary)
<commit_msg>Improvements to documentation, efficiency, and clarity.<commit_after>import requests
import urlparse
import re
from random import choice
import urllib
from BaseHTTPServer import BaseHTTPRequestHandler
import chardet
import htmlentitydefs
from hurry import filesize
import time

import plugin

# The plugin-specific configuration defaults; overridden by values in the user's config.py
defaults = {
        'http_url_blacklist': [],
        }

# List of common browser user agents.
user_agents = [
    'Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11',
    'Opera/9.25 (Windows NT 5.1; U; en)',
    'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)',
    'Mozilla/5.0 (compatible; Konqueror/3.5; Linux) KHTML/3.5.5 (like Gecko) (Kubuntu)',
    'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.12) Gecko/20070731 Ubuntu/dapper-security Firefox/1.5.0.12',
    'Lynx/2.8.5rel.1 libwww-FM/2.14 SSL-MM/1.4.1 GNUTLS/1.2.9'
]
# List of HTML MIME types.
html_types = ['text/html', 'application/xhtml+xml']
# List of HTTP status codes appropriate for detecting normal redirection.
redirect_codes = [301, 302, 303]
# A structure required by hurry.filesize for custom suffixes.
filesizes = [
    (1024 ** 5, ' PiB'),
    (1024 ** 4, ' TiB'),
    (1024 ** 3, ' GiB'),
    (1024 ** 2, ' MiB'),
    (1024 ** 1, ' KiB'),
    (1024 ** 0, ' B'),
    ]

def ajax_url(url):
    """ AJAX HTML snapshot URL parsing, pretty much required for a modern scraper.
    https://developers.google.com/webmasters/ajax-crawling/docs/specification
    Take a URL string, turn its #! fragment into the prescribed query, and return a string.
    """
    hashbang_index = url.find('#!')
    if hashbang_index != -1:
        base = url[:hashbang_index]
        joiner = '?' if '?' not in base else '&'
        url = ''.join((base, joiner, '_escaped_fragment_=', urllib.quote(url[hashbang_index+2:], '!"$\'()*,/:;<=>?@[\\]^`{|}~')))
    return url

def prettify_url(url):
    """ Removes URL baggage to display a clean hostname/path.
    Passed a string or a urlparse.ParseResult object; return a string.
    """
    if isinstance(url, urlparse.ParseResult) == False:
        url = urlparse.urlparse(url)
    return url.hostname + re.sub('/$', '', url.path)

class NoTitleError(Exception):
    """ Just a simple, fake, and unique exception to faciliate the main logic. """
    def __init__(self):
        pass

# Thanks to Fredrik Lundh: http://effbot.org/zone/re-sub.htm#unescape-html
def unescape(text):
    """ Removes HTML or XML character references and entities from a text string.
    @param text The HTML (or XML) source text.
    @return The plain text, as a Unicode string, if necessary.
    """
    def fixup(m):
        text = m.group(0)
        if text[:2] == "&#":
            # character reference
            try:
                if text[:3] == "&#x":
                    return unichr(int(text[3:-1], 16))
                else:
                    return unichr(int(text[2:-1]))
            except ValueError:
                pass
        else:
            # named entity
            try:
                text = unichr(htmlentitydefs.name2codepoint[text[1:-1]])
            except KeyError:
                pass
        return text # leave as is
    return re.sub("&#?\w+;", fixup, text)

class Plugin(plugin.Plugin):
    def register_commands(self):
        """ Matches http:// or https:// if followed by non-control character. """
        all_controls_and_space = ' \x00-\x1F\x7F-\x9F'
        self.regexes = [
                ('(?i).*https?://[^%s]' % all_controls_and_space, self.title),
                ]

    def title(self, message, args):
        """ Returns metadata about URLs posted:  For HTML documents, the title element; for all other links, the MIME type and file size.
        $https://twitter.com/#!/camh/statuses/147449116551680001
        >Twitter / Cameron Kenley Hunt: There are only three hard  ... \x03#|\x03 \x02twitter.com\x02
        """
        for word in re.findall('(?i)https?://.*?(?=\\s|\\Z)', message.content.decode('utf-8')):
            permitted = True

            for i in self.conf.conf['http_url_blacklist']:
                channel, blacklist = i.split(' ')

                if channel == message.source and re.match(blacklist, word):
                    permitted = False

            if permitted:
                # Set it up.
                url_parsed = urlparse.urlparse(word)
                url_hostname = url_parsed.hostname
                word = ajax_url(self.irc.strip_formatting(word))
                request_headers = {'User-Agent': choice(user_agents)}

                # GO!
                start_time = time.time()
                try:
                    resource = requests.head(word, headers=request_headers, allow_redirects=True)
                    if resource.status_code == 405:
                        resource = requests.get(word, headers=dict(request_headers.items() + [('Range', 'bytes=1-5')]), allow_redirects=True)
                    else:
                        resource.raise_for_status()

                    if resource.history != [] and resource.history[-1].status_code in redirect_codes:
                        word = resource.history[-1].headers['Location']
                        redirection_url = urlparse.urlparse(word)
                        if redirection_url.netloc == '':
                            word = ''.join((url_parsed.scheme, '://', url_parsed.netloc, redirection_url.path))
                        elif redirection_url.hostname != url_hostname:
                            url_hostname = '%s \x03#->\x03 %s' % (url_hostname, prettify_url(word))
                        word = ajax_url(word)

                    resource_type = resource.headers['Content-Type'].split(';')[0]
                    if resource_type in html_types:
                        resource = requests.get(word, headers=request_headers)
                        resource.raise_for_status()
                        # RFC 2616 (HTTP/1.1) discourages this, but then again it also doesn't require the charset to be specified.
                        # The requests library, in accordance with the RFC, falls back to Latin-1 if charset is not in the Content-Type header.
                        # This conditional at least ensures that the charset is checked, even if the result is incorrect.
                        # https://github.com/kennethreitz/requests/issues/592
                        if resource.encoding == 'ISO-8859-1':
                            resource.encoding = chardet.detect(resource.content)['encoding']
                        try:
                            title = re.findall('(?si)(?<=<title>).*(?=</title>)', resource.text)[0]
                        except IndexError:
                            raise NoTitleError
                        title = re.sub('(?s)\s+', ' ', unescape(title).strip())
                    else:
                        # TODO: Make this feature togglable, since it can seem spammy for image dumps.
                        raise NoTitleError
                except requests.exceptions.ConnectionError:
                    title = 'server connection error'
                except requests.exceptions.HTTPError, httpe:
                    title = '%s %s' % (httpe.response.status_code, BaseHTTPRequestHandler.responses[httpe.response.status_code][0])
                except NoTitleError:
                    try:
                        data_length = filesize.size(float(resource.headers['Content-Length']), filesizes)
                    except TypeError:
                        data_length = 'size unknown'
                    title = '%s \x03#|\x03 %s' % (resource_type, data_length)
                # STOP!
                end_time = time.time()

                time_length = '%.2f seconds' % (end_time - start_time)
                summary = '%s \x03#|\x03 %s \x03#|\x03 \x02%s\x02' % (title, time_length, url_hostname)
                self.irc.privmsg(message.source, summary)

<|endoftext|>


<commit_before>"""
multiplication-table.py
Author: Payton
Credit: Ethan
Assignment:

Write and submit a Python program that prints a multiplication table. The user
must be able to determine the width and height of the table before it is printed.

The final multiplication table should look like this:

Width of multiplication table: 10
Height of multiplication table: 8

  1   2   3   4   5   6   7   8   9  10
  2   4   6   8  10  12  14  16  18  20
  3   6   9  12  15  18  21  24  27  30
  4   8  12  16  20  24  28  32  36  40
  5  10  15  20  25  30  35  40  45  50
  6  12  18  24  30  36  42  48  54  60
  7  14  21  28  35  42  49  56  63  70
  8  16  24  32  40  48  56  64  72  80
"""
width = int(float(input("What is the width of the multiplication table? ")))
height = int(float(inpt("What is the height of the multiplication table? ")))

for (y, width):
    for (x, height):<commit_msg>Updated from Brython Server: 2/4/2016 2:31:04 PM<commit_after>"""
multiplication-table.py
Author: Payton
Credit: Ethan
Assignment:

Write and submit a Python program that prints a multiplication table. The user
must be able to determine the width and height of the table before it is printed.

The final multiplication table should look like this:

Width of multiplication table: 10
Height of multiplication table: 8

  1   2   3   4   5   6   7   8   9  10
  2   4   6   8  10  12  14  16  18  20
  3   6   9  12  15  18  21  24  27  30
  4   8  12  16  20  24  28  32  36  40
  5  10  15  20  25  30  35  40  45  50
  6  12  18  24  30  36  42  48  54  60
  7  14  21  28  35  42  49  56  63  70
  8  16  24  32  40  48  56  64  72  80
"""
width = int(float(input("What is the width of the multiplication table? ")))
height = int(float(inpt("What is the height of the multiplication table? ")))

for x in range (1, height):
    for y in range (1, height):<|endoftext|>


<commit_before># Copyright 2014 Rackspace
# All Rights Reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

from __future__ import print_function

import argparse
import ConfigParser
import os
import re
import socket
import sys

from gevent import ssl
import tendril

# Default port for the HeyU hub
HEYU_PORT = 4859

# Regular expression for parsing a hub specification
HUB_RE = re.compile(r'^(?P<hostname>[^:\s\[\]]+|\[[0-9a-fA-F:]+\])'
                    r'(?::(?P<port>\d+))?$')

class HubException(Exception):
    """
    Exception raised if there's an error parsing the hub
    specification.
    """

    pass

def parse_hub(hub):
    """
    Parse a hub specification.

    :param hub: The hub specification.  Can be either a bare
                "hostname" or a "hostname:port".  If the hostname is
                an IPv6 address, it should be enclosed in brackets,
                i.e. "[::1]:4859".

    :returns: A tuple of the hostname and integer port number.
    """

    # Interpret the hostname
    match = HUB_RE.match(hub)
    if not match:
        raise HubException("Could not understand hub address '%s'" % hub)

    # Extract the hostname
    hostname = match.group('hostname')
    if hostname[0] == '[':
        # Unwrap an IPv6 address
        hostname = hostname[1:-1]

    # Now extract the port
    port = match.group('port')
    if port is None:
        port = HEYU_PORT
    else:
        port = int(port)

    # We have hostname and port, now let's resolve it
    try:
        result = socket.getaddrinfo(hostname, port, 0, socket.SOCK_STREAM)
    except Exception as e:
        raise HubException("Could not resolve hub hostname '%s': %s" %
                           (hostname, e))

    return result[0][4]

def default_hub():
    """
    Retrieve the default hub specification.

    :returns: A tuple of the hostname and integer port number.
    """

    # Start off by trying to parse ~/.heyu.hub
    try:
        with open(os.path.expanduser('~/.heyu.hub')) as f:
            return parse_hub(f.read().strip())
    except Exception:
        # Return our default
        return ('127.0.0.1', HEYU_PORT)

def outgoing_endpoint(target):
    """
    The ``tendril.get_manager()`` function must be called with the
    appropriate originating endpoint for the target address
    family--that is, if the hub is on an IPv4 address,
    ``tendril.get_manager()`` must be called with an endpoint of
    ``('', 0)``, and if it is an IPv6 address, the endpoint must be
    ``('::', 0)``.  This helper function selects the correct
    originating endpoint given the target address.

    :param target: The target of the connection.

    :returns: One of ``('', 0)`` or ``('::', 0)``, depending on the
              address family of ``target``.
    """

    # Need the address family of the target
    fam = tendril.addr_info(target)

    # Select the correct endpoint
    if fam == socket.AF_INET6:
        return ('::', 0)
    return ('', 0)

# Regular expression for parsing a certificate configuration
# specification
CERTCONF_RE = re.compile(r'^(?P<conf_path>[^\[\]]+)'
                         r'(?:\[(?P<profile>\w+)\])?$')

class CertException(Exception):
    """
    Exception raised if there's an error parsing the certificate
    configuration specification.
    """

    pass

def cert_wrapper(cert_conf, profile, server_side=False, secure=True):
    """
    Compute and return a ``tendril.TendrilPartial`` object which will
    set up TLS on the HeyU port.

    :param cert_conf: The path to the certificate profile
                      configuration file.  If ``None``, "~/.heyu.cert"
                      is used.  The path is tilde-expanded.  Note that
                      the path may included an alternate profile name,
                      enclosed in braces ('[]') and appended to the
                      end of the path; this will override the value of
                      ``profile``.
    :param profile: The name of the default profile to use.
    :param server_side: If ``True``, TLS will be set up for the server
                        side of the connection, rather than the client
                        side.  Defaults to ``False``.
    :param secure: If ``True``, TLS will be set up, and an error
                   raised if the certificate configuration file cannot
                   be found.  If ``False``, TLS will not be set up.

    :returns: A wrapper callable, suitable for use with Tendril, that
              will set up TLS authentication and encryption for the
              HeyU connection.
    """

    # Set up no wrappers if we're set up insecure
    if not secure:
        return None

    # We need to find the certificate configuration file...
    if cert_conf is None:
        cert_conf = '~/.heyu.cert'
    else:
        # Parse the configuration specification
        match = CERTCONF_RE.match(cert_conf)
        if not match:
            raise CertException("Could not understand certificate "
                                "configuration path '%s'" % cert_conf)

        # Set the stripped path
        cert_conf = match.group('conf_path')

        # Was the profile overridden?
        override = match.group('profile')
        if override:
            profile = override

    # Look up and read the certificate configuration
    cert_path = os.path.expanduser(cert_conf)
    cp = ConfigParser.SafeConfigParser()
    if not cp.read(cert_path):
        raise CertException("Could not read certificate configuration "
                            "file '%s'" % cert_path)

    # Suck in the profile
    try:
        conf = dict(cp.items(profile))
    except ConfigParser.NoSectionError:
        raise CertException("No such profile [%s] in configuration file '%s'" %
                            (profile, cert_path))
    except Exception as exc:
        raise CertException("Could not load profile [%s] from '%s': %s" %
                            (profile, cert_path, exc))

    # All we need now is the three essential configuration settings
    missing = [key for key in ('cafile', 'certfile', 'keyfile')
               if key not in conf]
    if missing:
        raise CertException("Missing configuration for the following "
                            "values in the [%s] profile of '%s': %s" %
                            (profile, cert_path, ', '.join(sorted(missing))))

    return tendril.TendrilPartial(
        ssl.wrap_socket,
        keyfile=conf['keyfile'], certfile=conf['certfile'],
        ca_certs=conf['cafile'],
        server_side=server_side, cert_reqs=ssl.CERT_REQUIRED,
        ssl_version=ssl.PROTOCOL_TLSv1)

def daemonize(workdir='/', pidfile=None):
    """
    Turns the process into a daemon.  Standard input, output, and
    error are redirected to /dev/null, the current directory is
    switched, and the standard task of double-forking is performed.

    :param workdir: The directory to switch to.  This should usually
                    be the root directory.
    :param pidfile: If provided, the name of a file to write the
                    process ID into.
    """

    # Begin by setting up for the daemonizing
    os.chdir(workdir)
    os.umask(0)

    # Do the first fork
    if os.fork() > 0:
        os._exit(0)

    # Make ourself a session leader
    os.setsid()

    # Do the second fork
    if os.fork() > 0:
        os._exit(0)

    # Redirect standard input, standard output, and standard error
    devnull = os.open(os.devnull, os.O_RDWR)
    os.dup2(devnull, sys.stdin.fileno())
    os.dup2(devnull, sys.stdout.fileno())
    os.dup2(devnull, sys.stderr.fileno())
    if devnull not in (sys.stdin.fileno(), sys.stdout.fileno(),
                       sys.stderr.fileno()):
        os.close(devnull)

    # Create the PID file
    if pidfile:
        with open(pidfile, 'w') as f:
            print(str(os.getpid()), file=f)
<commit_msg>Begin updating util.py<commit_after># Copyright 2014 Rackspace
# All Rights Reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

from __future__ import print_function

import argparse
import ConfigParser
import os
import re
import socket
import ssl
import sys

# Import the correct asyncio library
try:
    import asyncio
except ImportError:
    import trollius as asyncio

# Select the correct SSLContext class to use
if hasattr(ssl, 'SSLContext'):
    SSLContext = ssl.SSLContext
else:
    SSLContext = asyncio.SSLContext

# Default port for the HeyU hub
HEYU_PORT = 4859

# Regular expression for parsing a hub specification
HUB_RE = re.compile(r'^(?P<hostname>[^:\s\[\]]+|\[[0-9a-fA-F:]+\])'
                    r'(?::(?P<port>\d+))?$')

class HubException(Exception):
    """
    Exception raised if there's an error parsing the hub
    specification.
    """

    pass

def parse_hub(hub):
    """
    Parse a hub specification.

    :param hub: The hub specification.  Can be either a bare
                "hostname" or a "hostname:port".  If the hostname is
                an IPv6 address, it should be enclosed in brackets,
                i.e. "[::1]:4859".

    :returns: A tuple of the hostname and integer port number.
    """

    # Interpret the hostname
    match = HUB_RE.match(hub)
    if not match:
        raise HubException("Could not understand hub address '%s'" % hub)

    # Extract the hostname
    hostname = match.group('hostname')
    if hostname[0] == '[':
        # Unwrap an IPv6 address
        hostname = hostname[1:-1]

    # Now extract the port
    port = match.group('port')
    if port is None:
        port = HEYU_PORT
    else:
        port = int(port)

    # We have hostname and port, now let's resolve it
    try:
        result = socket.getaddrinfo(hostname, port, 0, socket.SOCK_STREAM)
    except Exception as e:
        raise HubException("Could not resolve hub hostname '%s': %s" %
                           (hostname, e))

    return result[0][4]

def default_hub():
    """
    Retrieve the default hub specification.

    :returns: A tuple of the hostname and integer port number.
    """

    # Start off by trying to parse ~/.heyu.hub
    try:
        with open(os.path.expanduser('~/.heyu.hub')) as f:
            return parse_hub(f.read().strip())
    except Exception:
        # Return our default
        return ('127.0.0.1', HEYU_PORT)

# def outgoing_endpoint(target):
#     """
#     The ``tendril.get_manager()`` function must be called with the
#     appropriate originating endpoint for the target address
#     family--that is, if the hub is on an IPv4 address,
#     ``tendril.get_manager()`` must be called with an endpoint of
#     ``('', 0)``, and if it is an IPv6 address, the endpoint must be
#     ``('::', 0)``.  This helper function selects the correct
#     originating endpoint given the target address.

#     :param target: The target of the connection.

#     :returns: One of ``('', 0)`` or ``('::', 0)``, depending on the
#               address family of ``target``.
#     """

#     # Need the address family of the target
#     fam = tendril.addr_info(target)

#     # Select the correct endpoint
#     if fam == socket.AF_INET6:
#         return ('::', 0)
#     return ('', 0)

# Regular expression for parsing a certificate configuration
# specification
CERTCONF_RE = re.compile(r'^(?P<conf_path>[^\[\]]+)'
                         r'(?:\[(?P<profile>\w+)\])?$')

class CertException(Exception):
    """
    Exception raised if there's an error parsing the certificate
    configuration specification.
    """

    pass

# def cert_wrapper(cert_conf, profile, server_side=False, secure=True):
#     """
#     Compute and return a ``tendril.TendrilPartial`` object which will
#     set up TLS on the HeyU port.

#     :param cert_conf: The path to the certificate profile
#                       configuration file.  If ``None``, "~/.heyu.cert"
#                       is used.  The path is tilde-expanded.  Note that
#                       the path may included an alternate profile name,
#                       enclosed in braces ('[]') and appended to the
#                       end of the path; this will override the value of
#                       ``profile``.
#     :param profile: The name of the default profile to use.
#     :param server_side: If ``True``, TLS will be set up for the server
#                         side of the connection, rather than the client
#                         side.  Defaults to ``False``.
#     :param secure: If ``True``, TLS will be set up, and an error
#                    raised if the certificate configuration file cannot
#                    be found.  If ``False``, TLS will not be set up.

#     :returns: A wrapper callable, suitable for use with Tendril, that
#               will set up TLS authentication and encryption for the
#               HeyU connection.
#     """

#     # Set up no wrappers if we're set up insecure
#     if not secure:
#         return None

#     # We need to find the certificate configuration file...
#     if cert_conf is None:
#         cert_conf = '~/.heyu.cert'
#     else:
#         # Parse the configuration specification
#         match = CERTCONF_RE.match(cert_conf)
#         if not match:
#             raise CertException("Could not understand certificate "
#                                 "configuration path '%s'" % cert_conf)

#         # Set the stripped path
#         cert_conf = match.group('conf_path')

#         # Was the profile overridden?
#         override = match.group('profile')
#         if override:
#             profile = override

#     # Look up and read the certificate configuration
#     cert_path = os.path.expanduser(cert_conf)
#     cp = ConfigParser.SafeConfigParser()
#     if not cp.read(cert_path):
#         raise CertException("Could not read certificate configuration "
#                             "file '%s'" % cert_path)

#     # Suck in the profile
#     try:
#         conf = dict(cp.items(profile))
#     except ConfigParser.NoSectionError:
#         raise CertException("No such profile [%s] in configuration file '%s'" %
#                             (profile, cert_path))
#     except Exception as exc:
#         raise CertException("Could not load profile [%s] from '%s': %s" %
#                             (profile, cert_path, exc))

#     # All we need now is the three essential configuration settings
#     missing = [key for key in ('cafile', 'certfile', 'keyfile')
#                if key not in conf]
#     if missing:
#         raise CertException("Missing configuration for the following "
#                             "values in the [%s] profile of '%s': %s" %
#                             (profile, cert_path, ', '.join(sorted(missing))))

#     return tendril.TendrilPartial(
#         ssl.wrap_socket,
#         keyfile=conf['keyfile'], certfile=conf['certfile'],
#         ca_certs=conf['cafile'],
#         server_side=server_side, cert_reqs=ssl.CERT_REQUIRED,
#         ssl_version=ssl.PROTOCOL_TLSv1)

def daemonize(workdir='/', pidfile=None):
    """
    Turns the process into a daemon.  Standard input, output, and
    error are redirected to /dev/null, the current directory is
    switched, and the standard task of double-forking is performed.

    :param workdir: The directory to switch to.  This should usually
                    be the root directory.
    :param pidfile: If provided, the name of a file to write the
                    process ID into.
    """

    # Begin by setting up for the daemonizing
    os.chdir(workdir)
    os.umask(0)

    # Do the first fork
    if os.fork() > 0:
        os._exit(0)

    # Make ourself a session leader
    os.setsid()

    # Do the second fork
    if os.fork() > 0:
        os._exit(0)

    # Redirect standard input, standard output, and standard error
    devnull = os.open(os.devnull, os.O_RDWR)
    os.dup2(devnull, sys.stdin.fileno())
    os.dup2(devnull, sys.stdout.fileno())
    os.dup2(devnull, sys.stderr.fileno())
    if devnull not in (sys.stdin.fileno(), sys.stdout.fileno(),
                       sys.stderr.fileno()):
        os.close(devnull)

    # Create the PID file
    if pidfile:
        with open(pidfile, 'w') as f:
            print(str(os.getpid()), file=f)
<|endoftext|>