<commit_before>from ..libs.view_helpers import *
from ..libs.text_helpers import *
from ..libs import log
from .event_hub import EventHub

class TimeoutScheduler:
    """
    If there are multiple timeouts set for the same function, only call the
    function in the last timeout in chronological order.
    """
    def __init__(self, handler):
        self.timeout_count = 0 # number of pending timeouts
        self.handler = handler

    def reset_timeout(self, mstime):
        self.timeout_count += 1
        sublime.set_timeout(self._check_timeout_count, mstime)

    def _check_timeout_count(self):
        self.timeout_count -= 1
        if self.timeout_count == 0:
            self.handler()

class IdleListener:
    def __init__(self):
        self.just_changed_focus = False
        self.modified = False  # Flag to check if buffer has just been modified
        self.event_handler_added = False
        self.occurrences_event_handler_added = False

        self.on_idle_timeout_scheduler = TimeoutScheduler(self.on_idle)
        self.on_selection_idle_timeout_scheduler = TimeoutScheduler(self.on_selection_idle)

    # LISTENERS

    def on_activated_with_info(self, view, info):
        # Set modified and selection idle timers, so we can read diagnostics
        # and update status line
        self.on_idle_timeout_scheduler.reset_timeout(IDLE_TIME_LENGTH)
        self.on_selection_idle_timeout_scheduler.reset_timeout(IDLE_TIME_LENGTH)
        self.just_changed_focus = True

    def post_on_modified(self, view):
        if not is_special_view(view):
            self.modified = True
            self.on_idle_timeout_scheduler.reset_timeout(100)

    def on_selection_modified_with_info(self, view, info):
        if self.modified:
            self.on_selection_idle_timeout_scheduler.reset_timeout(1250)
        else:
            self.on_selection_idle_timeout_scheduler.reset_timeout(100)
        self.modified = False

    # HELPER METHODS

    def on_idle(self):
        """
        If file hasn't been modified for a period of time, send a request for
        errors.
        """
        log.debug("on_idle")
        view = active_view()
        info = get_info(view)
        if info:
            self.request_errors(view, info, 500)

    def on_selection_idle(self):
        """
        If selection is idle (cursor is not moving around), update the status
        line (error message or quick info, if any) and update document highlights.
        """
        log.debug("on_selection_idle")
        view = active_view()
        info = get_info(view)
        if info:
            self.update_status(view, info)
            if not IS_ST2 and view.settings().get('typescript_highlight_occurrences', 'true'):
                self.request_document_highlights(view, info)

    def request_errors(self, view, info, error_delay):
        """
        Ask the server for diagnostic information on all opened ts files in
        most-recently-used order
        """
        if not self.event_handler_added:
            cli.service.add_event_handler("syntaxDiag", lambda ev: self.show_errors(ev["body"], syntactic=True))
            cli.service.add_event_handler("semanticDiag", lambda ev: self.show_errors(ev["body"], syntactic=False))
            self.event_handler_added = True

        # Todo: limit this request to ts files currently visible in views
        if info and (self.just_changed_focus or info.change_count_when_last_err_req_sent < change_count(view)):
            self.just_changed_focus = False
            info.change_count_when_last_err_req_sent = change_count(view)
            window = sublime.active_window()
            group_number = window.num_groups()
            files = []
            for i in range(group_number):
                group_active_view = window.active_view_in_group(i)
                info = get_info(group_active_view)
                if info:
                    files.append(group_active_view.file_name())
                    check_update_view(group_active_view)
            if len(files) > 0:
                cli.service.request_get_err(error_delay, files)

    def show_errors(self, diagno_event_body, syntactic):
        """
        Error messages arrived from the server; show them in view
        """
        log.debug("show_errors")
        filename = diagno_event_body["file"]
        if os.name == 'nt' and filename:
            filename = filename.replace('/', '\\')

        info = get_info_with_filename(filename)
        if not info:
            return

        view = info.view
        if not info.change_count_when_last_err_req_sent == change_count(view):
            log.debug("The error info is outdated")
            self.on_idle_timeout_scheduler.reset_timeout(200)
            return

        region_key = 'syntacticDiag' if syntactic else 'semanticDiag'
        view.erase_regions(region_key)

        client_info = cli.get_or_add_file(filename)
        client_info.errors[region_key] = []
        error_regions = []

        diagnos = diagno_event_body["diagnostics"]
        if diagnos:
            for diagno in diagnos:
                start_line, start_offset = extract_line_offset(diagno["start"])
                start = view.text_point(start_line, start_offset)

                end_line, end_offset = extract_line_offset(diagno["end"])
                end = view.text_point(end_line, end_offset)

                if end <= view.size():
                    # Creates a <sublime.Region> from <start> to <end> to
                    # highlight the error. If the region coincides with the
                    # EOF character, use the region of the last visible
                    # character instead so user can still see the highlight.
                    if start == view.size() and start == end:
                        region = last_visible_character_region(view)
                    else:
                        region = sublime.Region(start, end)

                    client_info.errors[region_key].append((region, diagno["text"]))
                    error_regions.append(region)

        # Update status bar with error information
        info.has_errors = cli.has_errors(filename)
        self.update_status(view, info)

        # Highlight error regions in view
        if IS_ST2:
            view.add_regions(region_key, error_regions, "keyword", "",
                             sublime.DRAW_OUTLINED)
        else:
            view.add_regions(region_key, error_regions, "keyword", "",
                             sublime.DRAW_NO_FILL +
                             sublime.DRAW_NO_OUTLINE +
                             sublime.DRAW_SQUIGGLY_UNDERLINE)

    def update_status(self, view, info):
        """Update the status line with error info and quick info if no error info"""
        # Error info
        if is_inline_error_tips_enabled():
            view.erase_phantoms("typescript_error")
        view.erase_status("typescript_error")

        if info.has_errors:
            view.run_command('typescript_error_info')

        # Quick info
        error_status = view.get_status('typescript_error')
        if error_status and len(error_status) > 0:
            view.erase_status("typescript_info")
        else:
            view.run_command('typescript_quick_info')

    def request_document_highlights(self, view, info):
        if is_typescript(view):
            location = get_location_from_view(view)
            cli.service.async_document_highlights(view.file_name(), location, self.highlight_occurrences)

    def highlight_occurrences(self, response):
        view = active_view()
        if not view.file_name():
            return

        region_key = 'occurrences'
        view.erase_regions(region_key)

        if not response['success']:
            return

        occurrence_regions = []

        for file_highlight in response['body']:
            if file_highlight['file'] != view.file_name().replace('\\', '/'):
                continue

            for occurrence in file_highlight['highlightSpans']:
                start_line, start_offset = extract_line_offset(occurrence['start'])
                start_point = view.text_point(start_line, start_offset)

                end_line, end_offset = extract_line_offset(occurrence['end'])
                end_point = view.text_point(end_line, end_offset)

                occurrence_regions.append(sublime.Region(start_point, end_point))

        view.add_regions(region_key, occurrence_regions, 'comment', '',
                         sublime.DRAW_NO_FILL |
                         sublime.DRAW_NO_OUTLINE |
                         sublime.DRAW_SOLID_UNDERLINE)

listener = IdleListener()
EventHub.subscribe("on_activated_with_info", listener.on_activated_with_info)
EventHub.subscribe("post_on_modified", listener.post_on_modified)
EventHub.subscribe("on_selection_modified_with_info", listener.on_selection_modified_with_info)
<commit_msg>Always erase phantom when supported<commit_after>from ..libs.view_helpers import *
from ..libs.text_helpers import *
from ..libs import log
from .event_hub import EventHub

class TimeoutScheduler:
    """
    If there are multiple timeouts set for the same function, only call the
    function in the last timeout in chronological order.
    """
    def __init__(self, handler):
        self.timeout_count = 0 # number of pending timeouts
        self.handler = handler

    def reset_timeout(self, mstime):
        self.timeout_count += 1
        sublime.set_timeout(self._check_timeout_count, mstime)

    def _check_timeout_count(self):
        self.timeout_count -= 1
        if self.timeout_count == 0:
            self.handler()

class IdleListener:
    def __init__(self):
        self.just_changed_focus = False
        self.modified = False  # Flag to check if buffer has just been modified
        self.event_handler_added = False
        self.occurrences_event_handler_added = False

        self.on_idle_timeout_scheduler = TimeoutScheduler(self.on_idle)
        self.on_selection_idle_timeout_scheduler = TimeoutScheduler(self.on_selection_idle)

    # LISTENERS

    def on_activated_with_info(self, view, info):
        # Set modified and selection idle timers, so we can read diagnostics
        # and update status line
        self.on_idle_timeout_scheduler.reset_timeout(IDLE_TIME_LENGTH)
        self.on_selection_idle_timeout_scheduler.reset_timeout(IDLE_TIME_LENGTH)
        self.just_changed_focus = True

    def post_on_modified(self, view):
        if not is_special_view(view):
            self.modified = True
            self.on_idle_timeout_scheduler.reset_timeout(100)

    def on_selection_modified_with_info(self, view, info):
        if self.modified:
            self.on_selection_idle_timeout_scheduler.reset_timeout(1250)
        else:
            self.on_selection_idle_timeout_scheduler.reset_timeout(100)
        self.modified = False

    # HELPER METHODS

    def on_idle(self):
        """
        If file hasn't been modified for a period of time, send a request for
        errors.
        """
        log.debug("on_idle")
        view = active_view()
        info = get_info(view)
        if info:
            self.request_errors(view, info, 500)

    def on_selection_idle(self):
        """
        If selection is idle (cursor is not moving around), update the status
        line (error message or quick info, if any) and update document highlights.
        """
        log.debug("on_selection_idle")
        view = active_view()
        info = get_info(view)
        if info:
            self.update_status(view, info)
            if not IS_ST2 and view.settings().get('typescript_highlight_occurrences', 'true'):
                self.request_document_highlights(view, info)

    def request_errors(self, view, info, error_delay):
        """
        Ask the server for diagnostic information on all opened ts files in
        most-recently-used order
        """
        if not self.event_handler_added:
            cli.service.add_event_handler("syntaxDiag", lambda ev: self.show_errors(ev["body"], syntactic=True))
            cli.service.add_event_handler("semanticDiag", lambda ev: self.show_errors(ev["body"], syntactic=False))
            self.event_handler_added = True

        # Todo: limit this request to ts files currently visible in views
        if info and (self.just_changed_focus or info.change_count_when_last_err_req_sent < change_count(view)):
            self.just_changed_focus = False
            info.change_count_when_last_err_req_sent = change_count(view)
            window = sublime.active_window()
            group_number = window.num_groups()
            files = []
            for i in range(group_number):
                group_active_view = window.active_view_in_group(i)
                info = get_info(group_active_view)
                if info:
                    files.append(group_active_view.file_name())
                    check_update_view(group_active_view)
            if len(files) > 0:
                cli.service.request_get_err(error_delay, files)

    def show_errors(self, diagno_event_body, syntactic):
        """
        Error messages arrived from the server; show them in view
        """
        log.debug("show_errors")
        filename = diagno_event_body["file"]
        if os.name == 'nt' and filename:
            filename = filename.replace('/', '\\')

        info = get_info_with_filename(filename)
        if not info:
            return

        view = info.view
        if not info.change_count_when_last_err_req_sent == change_count(view):
            log.debug("The error info is outdated")
            self.on_idle_timeout_scheduler.reset_timeout(200)
            return

        region_key = 'syntacticDiag' if syntactic else 'semanticDiag'
        view.erase_regions(region_key)

        client_info = cli.get_or_add_file(filename)
        client_info.errors[region_key] = []
        error_regions = []

        diagnos = diagno_event_body["diagnostics"]
        if diagnos:
            for diagno in diagnos:
                start_line, start_offset = extract_line_offset(diagno["start"])
                start = view.text_point(start_line, start_offset)

                end_line, end_offset = extract_line_offset(diagno["end"])
                end = view.text_point(end_line, end_offset)

                if end <= view.size():
                    # Creates a <sublime.Region> from <start> to <end> to
                    # highlight the error. If the region coincides with the
                    # EOF character, use the region of the last visible
                    # character instead so user can still see the highlight.
                    if start == view.size() and start == end:
                        region = last_visible_character_region(view)
                    else:
                        region = sublime.Region(start, end)

                    client_info.errors[region_key].append((region, diagno["text"]))
                    error_regions.append(region)

        # Update status bar with error information
        info.has_errors = cli.has_errors(filename)
        self.update_status(view, info)

        # Highlight error regions in view
        if IS_ST2:
            view.add_regions(region_key, error_regions, "keyword", "",
                             sublime.DRAW_OUTLINED)
        else:
            view.add_regions(region_key, error_regions, "keyword", "",
                             sublime.DRAW_NO_FILL +
                             sublime.DRAW_NO_OUTLINE +
                             sublime.DRAW_SQUIGGLY_UNDERLINE)

    def update_status(self, view, info):
        """Update the status line with error info and quick info if no error info"""
        # Error info
        if PHANTOM_SUPPORT:
            view.erase_phantoms("typescript_error")
        view.erase_status("typescript_error")

        if info.has_errors:
            view.run_command('typescript_error_info')

        # Quick info
        error_status = view.get_status('typescript_error')
        if error_status and len(error_status) > 0:
            view.erase_status("typescript_info")
        else:
            view.run_command('typescript_quick_info')

    def request_document_highlights(self, view, info):
        if is_typescript(view):
            location = get_location_from_view(view)
            cli.service.async_document_highlights(view.file_name(), location, self.highlight_occurrences)

    def highlight_occurrences(self, response):
        view = active_view()
        if not view.file_name():
            return

        region_key = 'occurrences'
        view.erase_regions(region_key)

        if not response['success']:
            return

        occurrence_regions = []

        for file_highlight in response['body']:
            if file_highlight['file'] != view.file_name().replace('\\', '/'):
                continue

            for occurrence in file_highlight['highlightSpans']:
                start_line, start_offset = extract_line_offset(occurrence['start'])
                start_point = view.text_point(start_line, start_offset)

                end_line, end_offset = extract_line_offset(occurrence['end'])
                end_point = view.text_point(end_line, end_offset)

                occurrence_regions.append(sublime.Region(start_point, end_point))

        view.add_regions(region_key, occurrence_regions, 'comment', '',
                         sublime.DRAW_NO_FILL |
                         sublime.DRAW_NO_OUTLINE |
                         sublime.DRAW_SOLID_UNDERLINE)

listener = IdleListener()
EventHub.subscribe("on_activated_with_info", listener.on_activated_with_info)
EventHub.subscribe("post_on_modified", listener.post_on_modified)
EventHub.subscribe("on_selection_modified_with_info", listener.on_selection_modified_with_info)
<|endoftext|>


<commit_before># Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt

from __future__ import unicode_literals
import frappe
from frappe import session, _
from frappe.utils import today

from erpnext.utilities.transaction_base import TransactionBase

class CustomerIssue(TransactionBase):

	def validate(self):
		if session['user'] != 'Guest' and not self.customer:
			frappe.throw(_("Customer is required"))

		if self.status=="Closed" and \
			frappe.db.get_value("Customer Issue", self.name, "status")!="Closed":
			self.resolution_date = today()
			self.resolved_by = frappe.session.user

	def on_cancel(self):
		lst = frappe.db.sql("""select t1.name
			from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2
			where t2.parent = t1.name and t2.prevdoc_docname = %s and	t1.docstatus!=2""",
			(self.name))
		if lst:
			lst1 = ','.join([x[0] for x in lst])
			frappe.throw(_("Cancel Material Visit {0} before cancelling this Customer Issue").format(lst1))
		else:
			frappe.db.set(self, 'status', 'Cancelled')

	def on_update(self):
		pass

@frappe.whitelist()
def make_maintenance_visit(source_name, target_doc=None):
	from frappe.model.mapper import get_mapped_doc, map_child_doc

	def _update_links(source_doc, target_doc, source_parent):
		target_doc.prevdoc_doctype = source_parent.doctype
		target_doc.prevdoc_docname = source_parent.name

	visit = frappe.db.sql("""select t1.name
		from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2
		where t2.parent=t1.name and t2.prevdoc_docname=%s
		and t1.docstatus=1 and t1.completion_status='Fully Completed'""", source_name)

	if not visit:
		target_doc = get_mapped_doc("Customer Issue", source_name, {
			"Customer Issue": {
				"doctype": "Maintenance Visit",
				"field_map": {
					"complaint": "description",
					"doctype": "prevdoc_doctype",
					"name": "prevdoc_docname"
				}
			}
		}, target_doc)

		source_doc = frappe.get_doc("Customer Issue", source_name)
		if source_doc.get("item_code"):
			table_map = {
				"doctype": "Maintenance Visit Purpose",
				"postprocess": _update_links
			}
			map_child_doc(source_doc, target_doc, table_map, source_doc)

		return target_doc
<commit_msg>Minor fix in customer issue<commit_after># Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt

from __future__ import unicode_literals
import frappe
from frappe import session, _
from frappe.utils import today

from erpnext.utilities.transaction_base import TransactionBase

class CustomerIssue(TransactionBase):

	def validate(self):
		if session['user'] != 'Guest' and not self.customer:
			frappe.throw(_("Customer is required"))

		if self.status=="Closed" and \
			frappe.db.get_value("Customer Issue", self.name, "status")!="Closed":
			self.resolution_date = today()

	def on_cancel(self):
		lst = frappe.db.sql("""select t1.name
			from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2
			where t2.parent = t1.name and t2.prevdoc_docname = %s and	t1.docstatus!=2""",
			(self.name))
		if lst:
			lst1 = ','.join([x[0] for x in lst])
			frappe.throw(_("Cancel Material Visit {0} before cancelling this Customer Issue").format(lst1))
		else:
			frappe.db.set(self, 'status', 'Cancelled')

	def on_update(self):
		pass

@frappe.whitelist()
def make_maintenance_visit(source_name, target_doc=None):
	from frappe.model.mapper import get_mapped_doc, map_child_doc

	def _update_links(source_doc, target_doc, source_parent):
		target_doc.prevdoc_doctype = source_parent.doctype
		target_doc.prevdoc_docname = source_parent.name

	visit = frappe.db.sql("""select t1.name
		from `tabMaintenance Visit` t1, `tabMaintenance Visit Purpose` t2
		where t2.parent=t1.name and t2.prevdoc_docname=%s
		and t1.docstatus=1 and t1.completion_status='Fully Completed'""", source_name)

	if not visit:
		target_doc = get_mapped_doc("Customer Issue", source_name, {
			"Customer Issue": {
				"doctype": "Maintenance Visit",
				"field_map": {
					"complaint": "description",
					"doctype": "prevdoc_doctype",
					"name": "prevdoc_docname"
				}
			}
		}, target_doc)

		source_doc = frappe.get_doc("Customer Issue", source_name)
		if source_doc.get("item_code"):
			table_map = {
				"doctype": "Maintenance Visit Purpose",
				"postprocess": _update_links
			}
			map_child_doc(source_doc, target_doc, table_map, source_doc)

		return target_doc
<|endoftext|>


<commit_before>from cumulusci.robotframework.utils import capture_screenshot_on_error
from cumulusci.robotframework.pageobjects import BasePage
from cumulusci.robotframework.pageobjects import pageobject
from selenium.webdriver.common.keys import Keys

object_manager = {
    "button": "//input[@title='{}']",
    "input": "//input[@id='{}']",
    "select_related": "//select[@id = '{}']",
    "select_related_option": "//select[@id = 'DomainEnumOrId']/option[@value='{}']",
    "search_result": "//tbody/tr/td/a/span[contains(text(),'{}')]",
    "formula_txtarea": "//textarea[@id = '{}']",
    "object_result": "//th/a[text()='{}']",
    "link-text": "//a[contains(text(),'{}')]",
    "button-with-text": "//button[contains(text(),'{}')]",
    "frame_new": "//iframe[contains(@name, '{}') or contains(@title, '{}')]",
    "action_menu": "//a[contains(@class,'rowActionsPlaceHolder')]",
    "action_menu_item": "//span[text() = '{}']",
    "delete_confirm_btn": "//button[contains(@class,'forceActionButton')]",
}
# All common elements
search_button = object_manager["input"].format("globalQuickfind")
currency_locator = object_manager["input"].format("dtypeC")
next_button = object_manager["button"].format("Next")
save_button = object_manager["button"].format("Save")
text_locator = object_manager["input"].format("dtypeS")
formula_locator = object_manager["input"].format("dtypeZ")
checkbox_option = object_manager["input"].format("fdtypeB")
formula_txtarea = object_manager["formula_txtarea"].format("CalculatedFormula")
check_syntax = object_manager["button"].format("Check Syntax")
actions_menu = object_manager["action_menu"]
action_item_delete = object_manager["action_menu_item"].format("Delete")
confirm_delete = object_manager["delete_confirm_btn"]
lookup_locator = object_manager["input"].format("dtypeY")

@pageobject(page_type="ObjectManager")
class ObjectManagerPage(BasePage):
    """A page object representing the Object Manager of an object.
    Example
    | Go to page   ObjectManager  Contact
    """

    def _go_to_page(self):
        url_template = "{root}/lightning/setup/ObjectManager/home"
        url = url_template.format(root=self.cumulusci.org.lightning_base_url)
        self.selenium.go_to(url)
        object_name = self.object_name
        self.salesforce.wait_until_loading_is_complete()
        self.selenium.wait_until_page_contains_element(search_button)
        self.selenium.get_webelement(search_button).send_keys(object_name)
        self.selenium.get_webelement(search_button).send_keys(Keys.ENTER)
        object = object_manager["object_result"].format(object_name)
        self.selenium.wait_until_page_contains_element(object)
        self.selenium.click_element(object)
        self.selenium.wait_until_location_contains("Details/view", timeout=90)

    def _is_current_page(self):
        self.selenium.location_should_contain("Details/view")

    @capture_screenshot_on_error
    def switch_tab_to(self, tab):
        """Clicks on the name of the tab specified and sets the page view to be on the tab specified
        Example
        | Switch Tab To     Fields & Relationships
        """
        leftnavoption = object_manager["link-text"].format(tab)
        self.selenium.click_element(leftnavoption)

    def _is_current_tab(self, tab):
        tab_view = f"{tab}/view"
        self.selenium.location_should_contain(tab_view)

    @capture_screenshot_on_error
    def create_currency_field(self, field_name):
        """Creates a currency field by taking in the field name"""
        self.selenium.wait_until_page_contains_element(currency_locator, timeout=60)
        self.selenium.click_element(currency_locator)
        self.selenium.wait_until_page_contains_element(next_button, 60)
        self.selenium.click_element(next_button)
        self.salesforce.populate_field("Field Label", field_name)
        self.salesforce.populate_field("Length", "16")
        self.salesforce.populate_field("Decimal Places", "2")
        self.salesforce.populate_field(
            "Description", "This is a custom field generated during automation"
        )
        self.selenium.click_element(next_button)
        self.selenium.click_element(next_button)
        self.selenium.click_element(save_button)
        self.selenium.wait_until_location_contains(
            "FieldsAndRelationships/view",
            timeout=90,
            message="Fields And Relationships page did not load in 1 min",
        )

    @capture_screenshot_on_error
    def create_text_field(self, field_name):
        """Creates a text field by taking in the field name"""
        self.selenium.wait_until_page_contains_element(text_locator, timeout=60)
        self.selenium.click_element(text_locator)
        self.selenium.click_element(next_button)
        self.salesforce.populate_field("Field Label", field_name)
        self.salesforce.populate_field("Length", "255")
        self.salesforce.populate_field(
            "Description", "This is a custom field generated during automation"
        )
        self.selenium.click_element(next_button)
        self.selenium.click_element(next_button)
        self.selenium.click_element(save_button)
        self.selenium.wait_until_location_contains(
            "FieldsAndRelationships/view",
            timeout=90,
            message="Fields And Relationships page did not load in 1 min",
        )

    @capture_screenshot_on_error
    def create_formula_field(self, field_name, formula):
        """ Creates a formula field by providing the field_name, formula and forumla fields"""
        self.selenium.wait_until_page_contains_element(formula_locator, 60)
        self.selenium.click_element(formula_locator)
        self.selenium.wait_until_page_contains_element(next_button, 60)
        self.selenium.click_element(next_button)
        self.salesforce.populate_field("Field Label", field_name)
        self.selenium.wait_until_page_contains_element(checkbox_option, 60)
        self.selenium.click_element(checkbox_option)
        self.selenium.click_element(next_button)
        self.selenium.wait_until_page_contains_element(formula_txtarea, 60)
        self.selenium.get_webelement(formula_txtarea).send_keys(formula)
        self.selenium.click_element(check_syntax)
        self.selenium.click_element(next_button)
        self.selenium.click_element(next_button)
        self.selenium.click_element(save_button)
        self.selenium.wait_until_location_contains(
            "FieldsAndRelationships/view",
            timeout=90,
            message="Detail page did not load in 1 min",
        )

    def create_lookup_field(self, field_name, related):
        """Creates a Lookup field by taking in the inputs field_name and related field"""
        option = object_manager["select_related_option"].format(related)
        related = object_manager["select_related"].format("DomainEnumOrId")
        self.selenium.wait_until_page_contains_element(lookup_locator, 60)
        self.selenium.click_element(lookup_locator)
        self.selenium.wait_until_page_contains_element(next_button, 60)
        self.selenium.click_element(next_button)
        self.selenium.wait_until_page_contains_element(related, 60)
        self.selenium.scroll_element_into_view(related)
        self.selenium.get_webelement(related).click()
        self.selenium.click_element(option)
        self.selenium.wait_until_page_contains_element(next_button, 60)
        self.selenium.click_element(next_button)
        self.salesforce.populate_field("Field Label", field_name)
        self.salesforce.populate_field(
            "Description", "This is a custom field generated during automation"
        )
        self.selenium.click_element(next_button)
        self.selenium.click_element(next_button)
        self.selenium.click_element(next_button)
        self.selenium.click_element(save_button)
        self.selenium.wait_until_location_contains(
            "FieldsAndRelationships/view",
            timeout=90,
            message="Detail page did not load in 1 min",
        )

    @capture_screenshot_on_error
    def is_field_present(self, field_name):
        """Searches for the field name (field_name) and asserts the field got created """
        self.selenium.wait_until_page_contains_element(search_button, 60)
        self.selenium.get_webelement(search_button).clear()
        self.selenium.get_webelement(search_button).send_keys(field_name)
        self.selenium.get_webelement(search_button).send_keys(Keys.ENTER)
        self.salesforce.wait_until_loading_is_complete()
        search_results = object_manager["search_result"].format(field_name)
        assert (
            len(self.selenium.get_webelements(search_results)) == 1
        ), "Expected result count to be 1 but found {}".format(
            len(self.selenium.get_webelements(search_results))
        )

    @capture_screenshot_on_error
    def delete_custom_field(self, field_name):
        """Searches for the custom field and performs the delete action from the actions menu next to the field"""
        self.is_field_present(field_name)
        self.selenium.wait_until_page_contains_element(actions_menu, 60)
        self.selenium.click_element(actions_menu)
        self.selenium.wait_until_page_contains_element(action_item_delete, 60)
        self.selenium.click_element(action_item_delete)
        self.selenium.wait_until_page_contains_element(confirm_delete, 60)
        self.selenium.click_element(confirm_delete)
        self.selenium.wait_until_location_contains("/view", timeout=90)

    @capture_screenshot_on_error
    def create_custom_field(self, **kwargs):
        """creates a custom field if one doesn't already exist by the given name (Field_Name)
        |  Example
        | Create custom field
        | ...  Object=Payment
        | ...  Field_Type=Formula
        | ...  Field_Name=Is Opportunity From Prior Year
        | ...  Formula=YEAR( npe01__Opportunity__r.CloseDate ) < YEAR( npe01__Payment_Date__c )
        """
        self.selenium.wait_until_page_contains_element(search_button, 60)
        self.selenium.get_webelement(search_button).send_keys(kwargs["Field_Name"])
        self.selenium.get_webelement(search_button).send_keys(Keys.ENTER)
        self.salesforce.wait_until_loading_is_complete()
        search_results = object_manager["search_result"].format(kwargs["Field_Name"])
        count = len(self.selenium.get_webelements(search_results))
        if count != 1:
            locator = object_manager["button-with-text"].format("New")
            self.selenium.wait_until_page_contains_element(locator, 60)
            self.selenium.get_webelement(locator).click()
            self.salesforce.wait_until_loading_is_complete()
            framelocator = object_manager["frame_new"].format("vfFrameId", "vfFrameId")
            self.selenium.wait_until_element_is_visible(framelocator, timeout=60)
            frame = self.selenium.get_webelement(framelocator)
            self.selenium.select_frame(frame)
            type = kwargs["Field_Type"]
            if type.lower() == "lookup":
                self.create_lookup_field(kwargs["Field_Name"], kwargs["Related_To"])
            elif type.lower() == "currency":
                self.create_currency_field(kwargs["Field_Name"])
            elif type.lower() == "formula":
                self.create_formula_field(kwargs["Field_Name"], kwargs["Formula"])
            elif type.lower() == "text":
                self.create_text_field(kwargs["Field_Name"])
            self.selenium.unselect_frame()
<commit_msg>Attempt to make object manage page object less flakey Sadly, I had to add a hard-coded sleep at one point; I can't quite figure out what I need to wait on. I'm going to go ahead and check this in so I can get some forward progress.<commit_after>from cumulusci.robotframework.utils import capture_screenshot_on_error
from cumulusci.robotframework.pageobjects import BasePage
from cumulusci.robotframework.pageobjects import pageobject
from selenium.webdriver.common.keys import Keys

object_manager = {
    "button": "//input[@title='{}']",
    "input": "//input[@id='{}']",
    "select_related": "//select[@id = '{}']",
    "select_related_option": "//select[@id = 'DomainEnumOrId']/option[@value='{}']",
    "search_result": "//section[@class='related-list-card']//a[.=\"{}\"]",
    "formula_txtarea": "//textarea[@id = '{}']",
    "object_result": "//th/a[text()='{}']",
    "link-text": "//a[contains(text(),'{}')]",
    "button-with-text": "//button[contains(text(),'{}')]",
    "frame_new": "//iframe[contains(@name, '{}') or contains(@title, '{}')]",
    "action_menu": "//tr[.//a[.='{}']]//div[contains(@class, 'objectManagerVirtualActionMenu')]//a",
    "action_menu_item": "//div[@class='actionMenu']//a[@role='menuitem' and .='{}']",
    "delete_confirm_btn": "//button[contains(@class,'forceActionButton')]",
}
# All common elements
search_button = object_manager["input"].format("globalQuickfind")
currency_locator = object_manager["input"].format("dtypeC")
next_button = object_manager["button"].format("Next")
save_button = object_manager["button"].format("Save")
text_locator = object_manager["input"].format("dtypeS")
formula_locator = object_manager["input"].format("dtypeZ")
checkbox_option = object_manager["input"].format("fdtypeB")
formula_txtarea = object_manager["formula_txtarea"].format("CalculatedFormula")
check_syntax = object_manager["button"].format("Check Syntax")
actions_menu = object_manager["action_menu"]
action_item_delete = object_manager["action_menu_item"].format("Delete")
confirm_delete = object_manager["delete_confirm_btn"]
lookup_locator = object_manager["input"].format("dtypeY")

@pageobject(page_type="ObjectManager")
class ObjectManagerPage(BasePage):
    """A page object representing the Object Manager of an object.
    Example
    | Go to page   ObjectManager  Contact
    """

    def _go_to_page(self):
        url_template = "{root}/lightning/setup/ObjectManager/home"
        url = url_template.format(root=self.cumulusci.org.lightning_base_url)
        self.selenium.go_to(url)
        object_name = self.object_name
        self.salesforce.wait_until_loading_is_complete()
        self.selenium.wait_until_page_contains_element(search_button)
        self.selenium.press_keys(search_button, object_name, "RETURN")
        object_locator = object_manager["object_result"].format(object_name)
        self.selenium.wait_until_element_is_visible(object_locator)
        self.salesforce._jsclick(object_locator)
        self.selenium.wait_until_location_contains("Details/view", timeout=90)

    def _is_current_page(self):
        self.selenium.location_should_contain("Details/view")

    @capture_screenshot_on_error
    def switch_tab_to(self, tab):
        """Clicks on the name of the tab specified and sets the page view to be on the tab specified
        Example
        | Switch Tab To     Fields & Relationships
        """
        leftnavoption = object_manager["link-text"].format(tab)
        self.selenium.click_element(leftnavoption)

    def _is_current_tab(self, tab):
        tab_view = f"{tab}/view"
        self.selenium.location_should_contain(tab_view)

    @capture_screenshot_on_error
    def create_currency_field(self, field_name):
        """Creates a currency field by taking in the field name"""
        self.selenium.wait_until_page_contains_element(currency_locator, timeout=60)
        self.selenium.click_element(currency_locator)
        self.selenium.wait_until_page_contains_element(next_button, 60)
        self.selenium.click_element(next_button)
        self.salesforce.populate_field("Field Label", field_name)
        self.salesforce.populate_field("Length", "16")
        self.salesforce.populate_field("Decimal Places", "2")
        self.salesforce.populate_field(
            "Description", "This is a custom field generated during automation"
        )
        self.selenium.click_element(next_button)
        self.selenium.click_element(next_button)
        self.selenium.click_element(save_button)
        self.selenium.wait_until_location_contains(
            "FieldsAndRelationships/view",
            timeout=90,
            message="Fields And Relationships page did not load in 1 min",
        )

    @capture_screenshot_on_error
    def create_text_field(self, field_name):
        """Creates a text field by taking in the field name"""
        self.selenium.wait_until_page_contains_element(text_locator, timeout=60)
        self.selenium.click_element(text_locator)
        self.selenium.click_element(next_button)
        self.salesforce.populate_field("Field Label", field_name)
        self.salesforce.populate_field("Length", "255")
        self.salesforce.populate_field(
            "Description", "This is a custom field generated during automation"
        )
        self.selenium.click_element(next_button)
        self.selenium.click_element(next_button)
        self.selenium.click_element(save_button)
        self.selenium.wait_until_location_contains(
            "FieldsAndRelationships/view",
            timeout=90,
            message="Fields And Relationships page did not load in 1 min",
        )

    @capture_screenshot_on_error
    def create_formula_field(self, field_name, formula):
        """ Creates a formula field by providing the field_name, formula and forumla fields"""
        self.selenium.wait_until_page_contains_element(formula_locator, 60)
        self.selenium.click_element(formula_locator)
        self.selenium.wait_until_page_contains_element(next_button, 60)
        self.selenium.click_element(next_button)
        self.salesforce.populate_field("Field Label", field_name)
        self.selenium.wait_until_page_contains_element(checkbox_option, 60)
        self.selenium.click_element(checkbox_option)
        self.selenium.click_element(next_button)
        self.selenium.wait_until_page_contains_element(formula_txtarea, 60)
        self.selenium.get_webelement(formula_txtarea).send_keys(formula)
        self.selenium.click_element(check_syntax)
        self.selenium.click_element(next_button)
        self.selenium.click_element(next_button)
        self.selenium.click_element(save_button)
        self.selenium.wait_until_location_contains(
            "FieldsAndRelationships/view",
            timeout=90,
            message="Detail page did not load in 1 min",
        )

    def create_lookup_field(self, field_name, related):
        """Creates a Lookup field by taking in the inputs field_name and related field"""
        option = object_manager["select_related_option"].format(related)
        related = object_manager["select_related"].format("DomainEnumOrId")
        self.selenium.wait_until_page_contains_element(lookup_locator, 60)
        self.selenium.click_element(lookup_locator)
        self.selenium.wait_until_page_contains_element(next_button, 60)
        self.selenium.click_element(next_button)
        self.selenium.wait_until_page_contains_element(related, 60)
        self.selenium.scroll_element_into_view(related)
        self.selenium.get_webelement(related).click()
        self.selenium.click_element(option)
        self.selenium.wait_until_page_contains_element(next_button, 60)
        self.selenium.click_element(next_button)
        self.salesforce.populate_field("Field Label", field_name)
        self.salesforce.populate_field(
            "Description", "This is a custom field generated during automation"
        )
        self.selenium.click_element(next_button)
        self.selenium.click_element(next_button)
        self.selenium.click_element(next_button)
        self.selenium.click_element(save_button)
        self.selenium.wait_until_location_contains(
            "FieldsAndRelationships/view",
            timeout=90,
            message="Detail page did not load in 1 min",
        )

    @capture_screenshot_on_error
    def is_field_present(self, field_name):
        """Searches for the field name (field_name) and asserts the field got created """
        self.selenium.wait_until_page_contains_element(search_button)
        self.selenium.get_webelement(search_button).clear()
        self.selenium.get_webelement(search_button).send_keys(field_name)
        self.selenium.get_webelement(search_button).send_keys(Keys.ENTER)
        search_results = object_manager["search_result"].format(field_name)
        self.selenium.wait_until_page_contains_element(search_results)
        # I hate adding a hard-coded sleep, but I can't figure out what else to
        # wait on. It appears that part of the page will eventually refresh
        # but I don't know what triggers it.
        self.builtin.sleep("500ms")

    @capture_screenshot_on_error
    def delete_custom_field(self, field_name):
        """Searches for the custom field and performs the delete action from the actions menu next to the field"""
        action_menu_button = actions_menu.format(field_name)
        self.is_field_present(field_name)
        self.selenium.wait_until_page_contains_element(action_menu_button)
        self.selenium.scroll_element_into_view(action_menu_button)

        self.salesforce._jsclick(action_menu_button)
        self.selenium.wait_until_element_is_visible(action_item_delete)
        self.selenium.click_element(action_item_delete, action_chain=True)
        self.selenium.wait_until_element_is_visible(confirm_delete)
        self.selenium.click_element(confirm_delete, action_chain=True)
        self.selenium.wait_until_location_contains("/view", timeout=90)

    @capture_screenshot_on_error
    def create_custom_field(self, **kwargs):
        """creates a custom field if one doesn't already exist by the given name (Field_Name)
        |  Example
        | Create custom field
        | ...  Object=Payment
        | ...  Field_Type=Formula
        | ...  Field_Name=Is Opportunity From Prior Year
        | ...  Formula=YEAR( npe01__Opportunity__r.CloseDate ) < YEAR( npe01__Payment_Date__c )
        """
        self.selenium.wait_until_page_contains_element(search_button, 60)
        self.selenium.get_webelement(search_button).send_keys(kwargs["Field_Name"])
        self.selenium.get_webelement(search_button).send_keys(Keys.ENTER)
        self.salesforce.wait_until_loading_is_complete()
        search_results = object_manager["search_result"].format(kwargs["Field_Name"])
        count = len(self.selenium.get_webelements(search_results))
        if count != 1:
            locator = object_manager["button-with-text"].format("New")
            self.selenium.wait_until_page_contains_element(locator, 60)
            self.selenium.get_webelement(locator).click()
            self.salesforce.wait_until_loading_is_complete()
            framelocator = object_manager["frame_new"].format("vfFrameId", "vfFrameId")
            self.selenium.wait_until_element_is_visible(framelocator, timeout=60)
            frame = self.selenium.get_webelement(framelocator)
            self.selenium.select_frame(frame)
            type = kwargs["Field_Type"]
            if type.lower() == "lookup":
                self.create_lookup_field(kwargs["Field_Name"], kwargs["Related_To"])
            elif type.lower() == "currency":
                self.create_currency_field(kwargs["Field_Name"])
            elif type.lower() == "formula":
                self.create_formula_field(kwargs["Field_Name"], kwargs["Formula"])
            elif type.lower() == "text":
                self.create_text_field(kwargs["Field_Name"])
            self.selenium.unselect_frame()
<|endoftext|>


<commit_before>import os
import json
import yaml
from flask import Flask, render_template, jsonify
from flask_debugtoolbar import DebugToolbarExtension
from flask_caching import Cache
from flask_sqlalchemy import SQLAlchemy
from base.utils.data_utils import json_encoder
from base.utils.text_utils import render_markdown
from base.constants import CENDR_VERSION, APP_CONFIG
from flaskext.markdown import Markdown

# Create
app = Flask(__name__,
            static_url_path='/static')

# Add markdown
Markdown(app)

# Configuration - First load non-sensitive configuration info
app.config['json_encoder'] = json_encoder

# Load Credentials
# (BASE_VARS are the same regardless of whether we are debugging or in production)
BASE_VARS = yaml.load(open("env_config/base.yaml").read())
APP_CONFIG_VARS = yaml.load(open(f"env_config/{APP_CONFIG}.yaml").read())

app.config.update(BASE_VARS)
app.config.update(APP_CONFIG_VARS)

# Setup cache
cache = Cache(app, config={'CACHE_TYPE': 'base.utils.cache.datastore_cache'})

# Database
db_2 = SQLAlchemy(app)

# Set the json_encoder
app.json_encoder = json_encoder

def autoconvert(s):
    for fn in (int, float):
        try:
            return fn(s)
        except ValueError:
            pass
    return s

if os.getenv('HOME') == "/root":
    """
        Running on server
    """
    app.debug = False
    app.config["debug"] = False
    from flask_sslify import SSLify
    # Ignore leading slash of urls; skips must use start of path
    sslify = SSLify(app)
elif app.config['DEBUG']:
    app.debug = True
    #app.config["debug"] = True
    app.config['SECRET_KEY'] = "test"
    toolbar = DebugToolbarExtension(app)

def gs_static(url, prefix='static'):
    return f"https://storage.googleapis.com/elegansvariation.org/{prefix}/{url}"

# Template filters
from base.utils.template_filters import *

# About Pages
from base.views.about import about_bp
app.register_blueprint(about_bp, url_prefix='/about')

# Strain Pages
from base.views.strains import strain_bp
app.register_blueprint(strain_bp, url_prefix='/strain')

# Order Pages
from base.views.order import order_bp
app.register_blueprint(order_bp, url_prefix='/order')

# Data Pages
from base.views.data import data_bp
app.register_blueprint(data_bp, url_prefix='/data')

# Mapping Pages -
from base.views.mapping import mapping_bp
app.register_blueprint(mapping_bp, url_prefix='')

# Gene Pages
from base.views.gene import gene_bp
app.register_blueprint(gene_bp, url_prefix='/gene')

# Main Pages - Homepage, Outreach, Contact
from base.views.primary import primary_bp
app.register_blueprint(primary_bp, url_prefix='')

# User Pages
from base.views.user import user_bp
app.register_blueprint(user_bp, url_prefix='/user')

# Authentication
from base.auth import *

# Inject globals
@app.context_processor
def inject():
    """
        Used to inject variables that
        need to be accessed globally
    """
    return dict(version=CENDR_VERSION,
                json=json,
                list=list,
                str=str,
                gs_static=gs_static,
                render_markdown=render_markdown)

@app.errorhandler(404)
def page_not_found(e):
    return render_template('404.html'), 404

@app.errorhandler(500)
def internal_server_error(e):
    return render_template('500.html'), 500

from base.views.api import *
from base.manage import (init_db)
<commit_msg>Fix sslify<commit_after>import os
import json
import yaml
from flask import Flask, render_template, jsonify
from flask_debugtoolbar import DebugToolbarExtension
from flask_caching import Cache
from flask_sqlalchemy import SQLAlchemy
from base.utils.data_utils import json_encoder
from base.utils.text_utils import render_markdown
from base.constants import CENDR_VERSION, APP_CONFIG
from flaskext.markdown import Markdown

# Create
app = Flask(__name__,
            static_url_path='/static')

# Add markdown
Markdown(app)

# Configuration - First load non-sensitive configuration info
app.config['json_encoder'] = json_encoder

# Load Credentials
# (BASE_VARS are the same regardless of whether we are debugging or in production)
BASE_VARS = yaml.load(open("env_config/base.yaml").read())
APP_CONFIG_VARS = yaml.load(open(f"env_config/{APP_CONFIG}.yaml").read())

app.config.update(BASE_VARS)
app.config.update(APP_CONFIG_VARS)

# Setup cache
cache = Cache(app, config={'CACHE_TYPE': 'base.utils.cache.datastore_cache'})

# Database
db_2 = SQLAlchemy(app)

# Set the json_encoder
app.json_encoder = json_encoder

def autoconvert(s):
    for fn in (int, float):
        try:
            return fn(s)
        except ValueError:
            pass
    return s

if os.getenv('HOME') == "/root":
    """
        Running on server
    """
    app.debug = False
    from flask_sslify import SSLify
    # Ignore leading slash of urls; skips must use start of path
    sslify = SSLify(app)
elif app.config['DEBUG']:
    app.debug = True
    #app.config["debug"] = True
    app.config['SECRET_KEY'] = "test"
    toolbar = DebugToolbarExtension(app)

def gs_static(url, prefix='static'):
    return f"https://storage.googleapis.com/elegansvariation.org/{prefix}/{url}"

# Template filters
from base.utils.template_filters import *

# About Pages
from base.views.about import about_bp
app.register_blueprint(about_bp, url_prefix='/about')

# Strain Pages
from base.views.strains import strain_bp
app.register_blueprint(strain_bp, url_prefix='/strain')

# Order Pages
from base.views.order import order_bp
app.register_blueprint(order_bp, url_prefix='/order')

# Data Pages
from base.views.data import data_bp
app.register_blueprint(data_bp, url_prefix='/data')

# Mapping Pages -
from base.views.mapping import mapping_bp
app.register_blueprint(mapping_bp, url_prefix='')

# Gene Pages
from base.views.gene import gene_bp
app.register_blueprint(gene_bp, url_prefix='/gene')

# Main Pages - Homepage, Outreach, Contact
from base.views.primary import primary_bp
app.register_blueprint(primary_bp, url_prefix='')

# User Pages
from base.views.user import user_bp
app.register_blueprint(user_bp, url_prefix='/user')

# Authentication
from base.auth import *

# Inject globals
@app.context_processor
def inject():
    """
        Used to inject variables that
        need to be accessed globally
    """
    return dict(version=CENDR_VERSION,
                json=json,
                list=list,
                str=str,
                gs_static=gs_static,
                render_markdown=render_markdown)

@app.errorhandler(404)
def page_not_found(e):
    return render_template('404.html'), 404

@app.errorhandler(500)
def internal_server_error(e):
    return render_template('500.html'), 500

from base.views.api import *
from base.manage import (init_db)
<|endoftext|>


<commit_before>from django.db import models

# Create your models here.
<commit_msg>Include a first model, Job<commit_after>"""
Module bdp_fe.jobconf.models

Create your models here.
"""

from django.db import models

class Job(models.Model):
    """
    A Job is a calculation to be run on the BDP
    """
    date = models.DateTimeField('date created')
<|endoftext|>


<commit_before>#!/usr/bin/python3
""""
Running HBMQTT as MQTT broker.

Copyright (c) 2015-2020, Fabian Affolter <fabian@affolter-engineering.ch>
Released under the MIT license. See LICENSE file for details.

Source: https://github.com/beerfactory/hbmqtt/blob/develop/samples/broker_start.py
"""
import asyncio
import logging

from hbmqtt.broker import Broker

logger = logging.getLogger(__name__)

config = {
    'listeners': {
        'default': {
            'type': 'tcp',
            'bind': '0.0.0.0:1883',
        },
        'ws-mqtt': {
            'bind': '0.0.0.0:3000',
            'type': 'ws',
            'max_connections': 10,
        },
#        'topic-check': {
#            'enabled': True,
#            'plugins': ['topic_taboo'],
#        },
    },
}

broker = Broker(config)

#@asyncio.coroutine
#def start_broker():
#    """Start the broker."""
#    yield from broker.start()

async def start_broker():
    """Start the broker."""
    await broker.start()

if __name__ == '__main__':
    formatter = "[%(asctime)s] :: %(levelname)s :: %(name)s :: %(message)s"
    logging.basicConfig(level=logging.INFO, format=formatter)
    asyncio.get_event_loop().run_until_complete(start_broker())
    asyncio.get_event_loop().run_forever()

<commit_msg>Remove hbmqtt MQTT broker<commit_after><|endoftext|>


<commit_before>import ast

import click

from parsing.parser import FileVisitor

@click.command()
@click.argument('code', type=click.File('rb'))
@click.option('--printed', default=False, is_flag=True, help='Pretty prints the call tree for each class in the file')
@click.option('--remove-builtins', default=False, is_flag=True, help='Removes builtin functions from call trees')
def cli(code, printed, remove_builtins):
    """
    Parses a file.
    codegrapher [file_name]
    """
    parsed_code = ast.parse(code.read(), filename='code.py')
    visitor = FileVisitor()
    visitor.visit(parsed_code)
    if printed:
        click.echo('Classes in file:')
        for class_object in visitor.classes:
            if remove_builtins:
                class_object.remove_builtins()
            click.echo('=' * 80)
            click.echo(class_object.name)
            click.echo(class_object.pprint())
            click.echo('')
<commit_msg>Add graphviz file output argument<commit_after>import ast

import click

from graphing.graph import FunctionGrapher
from parsing.parser import FileVisitor

@click.command()
@click.argument('code', type=click.File('rb'))
@click.option('--printed', default=False, is_flag=True, help='Pretty prints the call tree for each class in the file')
@click.option('--remove-builtins', default=False, is_flag=True, help='Removes builtin functions from call trees')
@click.option('--output', help='Graphviz output file name')
def cli(code, printed, remove_builtins, output):
    """
    Parses a file.
    codegrapher [file_name]
    """
    parsed_code = ast.parse(code.read(), filename='code.py')
    visitor = FileVisitor()
    visitor.visit(parsed_code)
    if printed:
        click.echo('Classes in file:')
        for class_object in visitor.classes:
            if remove_builtins:
                class_object.remove_builtins()
            click.echo('=' * 80)
            click.echo(class_object.name)
            click.echo(class_object.pprint())
            click.echo('')
    if output:
        graph = FunctionGrapher()
        class_names = set(cls.name for cls in visitor.classes)
        for cls in visitor.classes:
            graph.add_dict_to_graph(class_names, cls.call_tree)
        graph.add_classes_to_graph(visitor.classes)
        graph.name = output
        graph.render()
<|endoftext|>


<commit_before>import requests
import pandas as pd
from pandas.io.json import json_normalize

# Create CSV from street_edge table with street_edge_id, x1, y1, x2, y2
# Name it street_edge_endpoints.csv and put it in the root directory, then run this script.
# It will output a CSV called streets_with_no_imagery.csv. Use this to mark those edges as "deleted" in the database.

if __name__ == '__main__':

    # Read google maps API key from file.
    api_key_file = open("google_maps_api_key.txt", "r")
    api_key = api_key_file.readline().strip()
    api_key_file.close()

    # Read street edge data from CSV.
    street_data = pd.read_csv('street_edge_endpoints.csv')

    # Create dataframes that will hold output data.
    one_endpoint_data = pd.DataFrame(columns=['street_edge_id','problem_endpoint'])
    both_endpoints_data = pd.DataFrame(columns=['street_edge_id'])

    for index, street in street_data.iterrows():
        # Check if there is imagery at each endpoint
        first_endpoint = requests.get('https://maps.googleapis.com/maps/api/streetview/metadata?source=outdoor&radius=25&location=' + str(street.y1) + ',' + str(street.x1) + '&key=' + api_key)
        second_endpoint = requests.get('https://maps.googleapis.com/maps/api/streetview/metadata?source=outdoor&radius=25&location=' + str(street.y2) + ',' + str(street.x2) + '&key=' + api_key)

        first_endpoint_status = json_normalize(first_endpoint.json()).status[0]
        second_endpoint_status = json_normalize(second_endpoint.json()).status[0]

        # If there is no GSV data at either endpoint, add to both_endpoints_data. If only one endpoint is missing GSV
        # imagery, add to one_endpoint_data.
        if first_endpoint_status == 'ZERO_RESULTS' and second_endpoint_status == 'ZERO_RESULTS':
            both_endpoints_data = both_endpoints_data.append({'street_edge_id': street.street_edge_id}, ignore_index=True)
        elif first_endpoint_status == 'ZERO_RESULTS':
            one_endpoint_data = one_endpoint_data.append({'street_edge_id': street.street_edge_id, 'problem_endpoint': 1}, ignore_index=True)
        elif second_endpoint_status == 'ZERO_RESULTS':
            one_endpoint_data = one_endpoint_data.append({'street_edge_id': street.street_edge_id, 'problem_endpoint': 2}, ignore_index=True)

    # Convert street_edge_id columns from float to int.
    one_endpoint_data.street_edge_id = one_endpoint_data.street_edge_id.astype('int32')
    one_endpoint_data.problem_endpoint = one_endpoint_data.problem_endpoint.astype('int32')
    both_endpoints_data.street_edge_id = both_endpoints_data.street_edge_id.astype('int32')

    # Output both_endpoints_data and one_endpoint_data as CSVs.
    one_endpoint_data.to_csv('streets_with_partial_imagery.csv', index=False)
    both_endpoints_data.to_csv('streets_with_no_imagery.csv', index=False)
<commit_msg>made duplicated URL a variable<commit_after>import requests
import pandas as pd
from pandas.io.json import json_normalize

# Create CSV from street_edge table with street_edge_id, x1, y1, x2, y2
# Name it street_edge_endpoints.csv and put it in the root directory, then run this script.
# It will output a CSV called streets_with_no_imagery.csv. Use this to mark those edges as "deleted" in the database.

if __name__ == '__main__':

    # Read google maps API key from file.
    api_key_file = open("google_maps_api_key.txt", "r")
    api_key = api_key_file.readline().strip()
    api_key_file.close()

    # Read street edge data from CSV.
    street_data = pd.read_csv('street_edge_endpoints.csv')

    # Create dataframes that will hold output data.
    one_endpoint_data = pd.DataFrame(columns=['street_edge_id','problem_endpoint'])
    both_endpoints_data = pd.DataFrame(columns=['street_edge_id'])

    for index, street in street_data.iterrows():
        # Check if there is imagery at each endpoint
        gsv_url = 'https://maps.googleapis.com/maps/api/streetview/metadata?source=outdoor&radius=25&key=' + api_key
        first_endpoint = requests.get(gsv_url + '&location=' + str(street.y1) + ',' + str(street.x1))
        second_endpoint = requests.get(gsv_url + '&location=' + str(street.y2) + ',' + str(street.x2))

        first_endpoint_status = json_normalize(first_endpoint.json()).status[0]
        second_endpoint_status = json_normalize(second_endpoint.json()).status[0]

        # If there is no GSV data at either endpoint, add to both_endpoints_data. If only one endpoint is missing GSV
        # imagery, add to one_endpoint_data.
        if first_endpoint_status == 'ZERO_RESULTS' and second_endpoint_status == 'ZERO_RESULTS':
            both_endpoints_data = both_endpoints_data.append({'street_edge_id': street.street_edge_id}, ignore_index=True)
        elif first_endpoint_status == 'ZERO_RESULTS':
            one_endpoint_data = one_endpoint_data.append({'street_edge_id': street.street_edge_id, 'problem_endpoint': 1}, ignore_index=True)
        elif second_endpoint_status == 'ZERO_RESULTS':
            one_endpoint_data = one_endpoint_data.append({'street_edge_id': street.street_edge_id, 'problem_endpoint': 2}, ignore_index=True)

    # Convert street_edge_id columns from float to int.
    one_endpoint_data.street_edge_id = one_endpoint_data.street_edge_id.astype('int32')
    one_endpoint_data.problem_endpoint = one_endpoint_data.problem_endpoint.astype('int32')
    both_endpoints_data.street_edge_id = both_endpoints_data.street_edge_id.astype('int32')

    # Output both_endpoints_data and one_endpoint_data as CSVs.
    one_endpoint_data.to_csv('streets_with_partial_imagery.csv', index=False)
    both_endpoints_data.to_csv('streets_with_no_imagery.csv', index=False)
<|endoftext|>


<commit_before>#!/usr/bin/python3
# -*- coding: utf-8 -*-

import os
import sys
import re
import subprocess as sp
import urllib3

from ply import lex, yacc

# Retain a copy so we don't unneccessarily waste time recreating them
http          = urllib3.PoolManager()

global_lexer  = None
global_parser = None
tokens        = None

def process_file( file_path, script_vars={}, compress=False, escape=None ):
    '''This is essentially a router for matching file extensions with the
    appropriate processor. If no appropriate processor is available
    default_processor is used. Since some content may be embedded in a string it
    may be necessary to escape the quote characters for that string
    implementation'''

    # get the file extention
    ext = file_path.rsplit( '.', 1 )[-1]

    handler = {
        'htm':  html_processor,
        'html': html_processor,
        'sass': sass_processor,
        'css':  css_processor,
        'js':   js_processor
    }.get( ext, default_processor )

    content = handler( file_path, script_vars, compress )

    # if the content is used in a string then we'll need to ensure the correct
    # string syntax is escaped.
    # TODO: consider performing a full escape
    if escape:
        content = content.replace( '\\', '\\\\' ).replace( escape, "\\{0}".format( escape ) )

    return content

def import_file( filepath ):
    # global http

    # if filepath.startswith( 'http://' )
    #     respone = http.request( 'GET', filepath )
    #     print( respone.status, file=sys.stderr )

    #     assert False

    # TODO: proto = file:// for files from root

    if filepath.startswith( '/' ):
        filepath = filepath[1:]
    else:
        filepath = '{0}/{1}'.format( p.lexer.dir_path, filepath )

    return process_file( filepath, compress=True, escape="'" )

#TODO: catch url contents
def include_file( filepath, dirpath, script_vars ):
    global http

    # TODO: proto = file:// for files from root
    proto = r'^http(s)?://'

    if re.match( proto, filepath ):
        response = http.request( 'GET', filepath )

        if response.status != 200:
            msg = 'Error while including: {0}, status: {1}'.format( filepath, response.status )
            print( msg, file=sys.stderr )
            exit( 1 )

        content_type = response.headers['content-type']
        content_type = content_type.split( '; ' )

        charset = 'utf-8'

        for ct in content_type:
            match = re.match( r'^charset=(.*?)$', ct )

            if match:
                charset = match.group( 1 )
                break

        return response.data.decode( charset )

    if filepath.startswith( '/' ):
        path = filepath[1:]
    else:
        path = '{0}/{1}'.format( dirpath, filepath )

    return js_processor( path, script_vars )

################################################################################
# Lexer ########################################################################
################################################################################

def create_lexer( file_path, script_vars ):
    '''This will generate the lexer for the processor. Since this can be time
    consuming and may be called for each individual file ( to which there may be
    many ), then we'll store a lexer globally and clone it each time we need a
    new one'''

    global global_lexer
    global tokens

    dir_path = os.path.dirname( file_path )

    if global_lexer:
        lexer = global_lexer.clone()
        lexer.file_path   = file_path   # used when displaying systax errors
        lexer.dir_path    = dir_path    # used for finding files via a relative path
        lexer.script_vars = script_vars # we store the variables here as they're generated

        return lexer

    reserved = {
        'begin_scope': 'SCOPE_BEGIN',
        'end_scope':   'SCOPE_END',
        'use_strict':  'USE_STRICT',
        'include':     'INCLUDE',
        'echo':        'ECHO',
    }

    tokens = [
        'BLOCK',
        'DELIMITER',
        'NEW_LINE',
        'COMMENT',
        'SEPARATOR',
        # 'LPAREN',
        # 'RPAREN',
        'STRING',
        'ID' ] + list( reserved.values() )

    t_DELIMITER = r';'
    t_SEPARATOR = r','
    t_COMMENT   = r'\#.*?\n'
    # t_LPAREN    = r'\('
    # t_RPAREN    = r'\)'

    def t_NEW_LINE( t ):
        r'\n'

        t.lexer.lineno += 1
        return t

    # we use this to represent a block of text
    def t_BLOCK( t ):
        r'%%BLOCK_BEGIN%%(\n|.)*?%%BLOCK_END%%'

        # we're only interested in the content of the block
        # TODO: move to parser
        block = r'%%BLOCK_BEGIN%%((\n|.)*?)%%BLOCK_END%%'
        t.value = re.match( block, t.value ).group( 1 )

        t.lexer.lineno += t.value.count( '\n' )

        return t

    # string token processor
    def t_STRING( t ):
        r'"(\\"|[^"])*?"'

        # remove the quotes and unescape the text
        # TODO: move to parser
        str = t.value[1:-1]
        t.value = str.encode().decode( 'unicode-escape' )

        return t

    def t_ID( t ):
        r'[a-zA-Z_][a-zA-Z0-9_]*'

        # cast the id to a reserved token if its found in the dict
        t.type = reserved.get( t.value, 'ID' )
        return t

    t_ignore = '[ \t]' # TODO: add comment?

    #error processor
    def t_error( t ):
        print( 'Unknown text "{0}"'.format( t.value[0] ), file=sys.stderr )

    global_lexer = lex.lex()

    lexer = global_lexer.clone()
    lexer.file_path   = file_path   # used when displaying systax errors
    lexer.dir_path    = dir_path    # used for finding files via a relative path
    lexer.script_vars = script_vars # we store the variables here as they're generated

    return lexer

################################################################################
# Parser #######################################################################
################################################################################

def create_parser():
    '''This will generate the parser for the processor. Since this can be time
    consuming and may be called for each individual file ( to which there may be
    many ), then we'll store a parser globally return that every time we need a
    new one'''

    global global_parser
    global tokens

    if global_parser:
        return global_parser

    #TODO: FIX
    # calculate the distance of the lexer position from the previous new line
    def find_column( input, t ):
        last_cr = input.rfind( '\n', 0, t.lexpos )
        if last_cr < 0:
            last_cr = 0

        return t.lexpos - last_cr + 1

    def p_output( p ):
        '''output : output block
                  | output delimiter
                  | output new_line
                  | block'''

        p[0] = p[1] + p[2] if len( p ) > 2 else p[1]

    def p_use_scrict( p ):
        '''block : USE_STRICT delimiter
                 | USE_STRICT new_line
                 | USE_STRICT block'''

        p[0] = '"use strict";\n'

    def p_include_1( p ):
        '''block : INCLUDE string delimiter
                 | INCLUDE string new_line
                 | INCLUDE string block'''

        # TODO: actually include

        data = include_file( p[2], p.lexer.dir_path, p.lexer.script_vars )

        p[0] = '{0}\n{1}'.format( data, p[3] )

    def p_echo( p ):
        '''block : ECHO string delimiter
                 | ECHO string new_line
                 | ECHO string block'''

        string = p[2]

        # TODO: move to p_string ???
        importer = r'\$\{(.*?)\}'

        while True:
            match = re.search( importer, string )
            if not match:
                break

            source, value = match.group( 0 ), match.group( 1 )

            value = import_file( value )

            string = string.replace( source, value, 1 )

        p[0] = '{0}\n{1}'.format( string, p[3] )

    ## Function scopes

    # empty scope params
    def p_begin_scope( p ):
        '''begin_scope : SCOPE_BEGIN delimiter
                       | SCOPE_BEGIN new_line'''

        p[0] = ''

    def p_end_scope( p ):
        '''end_scope : SCOPE_END delimiter
                     | SCOPE_END new_line'''

        p[0] = ''

    #scopes with params
    def p_begin_scope_params_1( p ):
        'begin_scope_params : SCOPE_BEGIN string'

        p[0] = p[2]

    def p_begin_scope_params_2( p ):
        'begin_scope_params : begin_scope_params separator string'

        p[0] = p[1] + ',' + p[3]

    def p_begin_scope_with_params( p ):
        '''begin_scope : begin_scope_params delimiter
                       | begin_scope_params new_line'''

        p[0] = p[1]

    def p_end_scope_params_1( p ):
        'end_scope_params : SCOPE_END string'

        p[0] = p[2]

    def p_end_scope_params_2( p ):
        'end_scope_params : end_scope_params separator string'

        p[0] = p[1] + ',' + p[3]

    def p_end_scope_with_params( p ):
        '''end_scope : end_scope_params delimiter
                     | end_scope_params new_line'''

        p[0] = p[1]

    #clear any excess delimiters
    def p_begin_scope_delimiter( p ):
        '''begin_scope : begin_scope delimiter
                       | begin_scope new_line'''
        p[0] = p[1]

    # join the scopes
    def p_scope( p ):
        'block : begin_scope output end_scope'

        p[0] = ';(function({0}){{\n{1}\n}})({2});\n'.format( p[1], p[2], p[3] )

    def p_separator( p ):
        '''separator : separator new_line
                     | SEPARATOR'''

        p[0] = ','

    def p_string( p ):
        'string : STRING'

        p[0] = p[1]

    def p_block_1( p ):
        'block : BLOCK'

        p[0] = p[1]

    def p_new_line( p ):
        'new_line : NEW_LINE'

        p[0] = ''

    def p_delimiter( p ):
        '''delimiter : DELIMITER
                     | COMMENT
                     | begin_scope end_scope''' # an empty scope is pointless, get rid of it

        p[0] = ''

    def p_error( p ):
        # msg = repr( dir( p ) )
        msg = 'Syntax error: unexpected {0} "{1}" in {2} line {3}'.format(
            p.type, p.value, p.lexer.file_path, p.lineno )
        print( msg, file=sys.stderr )

    # TODO: if ( debug )
    global_parser = yacc.yacc()
    return global_parser

################################################################################
# Default Processor ############################################################
################################################################################

def default_processor( file_path, script_vars={}, compress=False ):
    '''not yet implemented'''
    return ''

################################################################################
# SASS Application #############################################################
################################################################################

def call_sass( params ):
    params = ' '.join( params )

    cmd = 'sass {0}'.format( params )

    proc = sp.Popen( cmd, stdout=sp.PIPE, stdin=sp.PIPE, shell=True )

    output, error = proc.communicate()

    return output.decode( 'utf-8' )

################################################################################
# SASS Processor ###############################################################
################################################################################

def sass_processor( file_path, script_vars={}, compress=False ):
    '''This require ruby and sass to be installed.'''
    params = []

    if compress:
        params.append( '-t compressed' )

    params.append( file_path )

    css = call_sass( params )

    # sass leaves a trailing \n
    if compress:
        css = css.replace( '\n', '' )

    return css

################################################################################
# HTML Processor ###############################################################
################################################################################

def html_processor( file_path, script_vars={}, compress=False ):
    '''This requires java installed for compression'''
    # TODO: Do some actual processing ( maybe use bottles preprocessor )

    try:
        source = open( file_path, 'r' ).read()
    except ( OSError, IOError ) as e:
        print( e, file=sys.stderr )
        exit( 1 )

    if compress:
        # we'll use the html compressor in /tools
        cmd = 'java -jar {0}/tools/html-compressor/htmlcompressor-1.5.3.jar'.format( os.path.dirname( __file__ ) )

        proc = sp.Popen( cmd, stdout=sp.PIPE, stdin=sp.PIPE, shell=True )
        proc.stdin.write( source.encode() )

        output, error = proc.communicate()

        source = output.decode( 'utf-8' )

    return source

################################################################################
# CSS Processor ################################################################
################################################################################

def css_processor( file_path, script_vars={}, compress=False ):
    '''Not yet implemented.'''
    return ''

################################################################################
# JS Processor #################################################################
################################################################################

def js_processor( file_path, script_vars={}, compress=False ):
    '''Process a given source file, returning the processed JS. the optional
    vars allow for variables not present in the script to bhe passed in to the
    processor. By default compression is not carried out and single quotes/new
    lines are not escaped. compression should be enabled only at the top level
    and escaping should only be performed where the result will be inserted into
     a string'''
    # todo should strings be completely escaped or not?

    lexer    = create_lexer( file_path, script_vars )
    parser   = create_parser()

    try:
        source = open( file_path, 'r' ).read()
    except ( OSError, IOError ) as e:
        print( e, file=sys.stderr )
        exit( 1 )

    code = enclose_js( source )
    code = parser.parse( code, lexer=lexer )

    if compress:
        pass

    return code

# TODO: use a tokenising switcher in the lexer
def enclose_js( source ):
    '''In order to aid tokenising we'll wrap the JS code in a JS block and
    remove the preprocessor code from the block by finding it and replacing the
    comment tokens with block tokens. We're effectively inverting the code from
    JS code with buildr blocks to buildr code with JS blocks'''

    # wrap all the code ( useful for when there is no buildr code )
    code = '%%BLOCK_BEGIN%%{0}%%BLOCK_END%%'.format( source )

    block = r'/\*##(.*?)\*/'
    container = '%%BLOCK_END%%{0}%%BLOCK_BEGIN%%'

    # replace all buildr code blocks
    while True:
        match = re.search( block, code, re.DOTALL )
        if not match:
            break

        comment, content = match.group( 0 ), match.group( 1 )
        content = container.format( content )

        code = code.replace( comment, content, 1 )

    line = r'//##(.*?)\n'
    container = '%%BLOCK_END%%{0}\n%%BLOCK_BEGIN%%'

    while True:
        match = re.search( line, code )
        if not match:
            break

        comment, content = match.group( 0 ), match.group( 1 )
        content = container.format( content )

        code = code.replace( comment, content, 1 )

    return code

<commit_msg>Add window and undefined as reserved JS words Add JS compression<commit_after>#!/usr/bin/python3
# -*- coding: utf-8 -*-

import os
import sys
import re
import subprocess as sp
import urllib3

from ply import lex, yacc

# Retain a copy so we don't unneccessarily waste time recreating them
http          = urllib3.PoolManager()

global_lexer  = None
global_parser = None
tokens        = None

def process_file( file_path, script_vars={}, compress=False, escape=None ):
    '''This is essentially a router for matching file extensions with the
    appropriate processor. If no appropriate processor is available
    default_processor is used. Since some content may be embedded in a string it
    may be necessary to escape the quote characters for that string
    implementation'''

    # get the file extention
    ext = file_path.rsplit( '.', 1 )[-1]

    handler = {
        'htm':  html_processor,
        'html': html_processor,
        'sass': sass_processor,
        'css':  css_processor,
        'js':   js_processor
    }.get( ext, default_processor )

    content = handler( file_path, script_vars, compress )

    # if the content is used in a string then we'll need to ensure the correct
    # string syntax is escaped.
    # TODO: consider performing a full escape
    if escape:
        content = content.replace( '\\', '\\\\' ).replace( escape, "\\{0}".format( escape ) )

    return content

def import_file( filepath ):
    # global http

    # if filepath.startswith( 'http://' )
    #     respone = http.request( 'GET', filepath )
    #     print( respone.status, file=sys.stderr )

    #     assert False

    # TODO: proto = file:// for files from root

    if filepath.startswith( '/' ):
        filepath = filepath[1:]
    else:
        filepath = '{0}/{1}'.format( p.lexer.dir_path, filepath )

    return process_file( filepath, compress=True, escape="'" )

#TODO: catch url contents
def include_file( filepath, dirpath, script_vars ):
    global http

    # TODO: proto = file:// for files from root
    proto = r'^http(s)?://'

    if re.match( proto, filepath ):
        response = http.request( 'GET', filepath )

        if response.status != 200:
            msg = 'Error while including: {0}, status: {1}'.format( filepath, response.status )
            print( msg, file=sys.stderr )
            exit( 1 )

        content_type = response.headers['content-type']
        content_type = content_type.split( '; ' )

        charset = 'utf-8'

        for ct in content_type:
            match = re.match( r'^charset=(.*?)$', ct )

            if match:
                charset = match.group( 1 )
                break

        return response.data.decode( charset )

    if filepath.startswith( '/' ):
        path = filepath[1:]
    else:
        path = '{0}/{1}'.format( dirpath, filepath )

    return js_processor( path, script_vars )

################################################################################
# Lexer ########################################################################
################################################################################

def create_lexer( file_path, script_vars ):
    '''This will generate the lexer for the processor. Since this can be time
    consuming and may be called for each individual file ( to which there may be
    many ), then we'll store a lexer globally and clone it each time we need a
    new one'''

    global global_lexer
    global tokens

    dir_path = os.path.dirname( file_path )

    if global_lexer:
        lexer = global_lexer.clone()
        lexer.file_path   = file_path   # used when displaying systax errors
        lexer.dir_path    = dir_path    # used for finding files via a relative path
        lexer.script_vars = script_vars # we store the variables here as they're generated

        return lexer

    reserved = {
        'begin_scope': 'SCOPE_BEGIN',
        'end_scope':   'SCOPE_END',
        'use_strict':  'USE_STRICT',
        'include':     'INCLUDE',
        'echo':        'ECHO',
    }

    # A list of js reserved ids that we'll recognise in buildr
    js_reserved = {
        'window':    'STRING',
        'undefined': 'STRING'
    }

    tokens = [
        'BLOCK',
        'DELIMITER',
        'NEW_LINE',
        'COMMENT',
        'SEPARATOR',
        # 'LPAREN',
        # 'RPAREN',
        'STRING',
        'ID' ] + list( reserved.values() )

    t_DELIMITER = r';'
    t_SEPARATOR = r','
    t_COMMENT   = r'\#.*?\n'
    # t_LPAREN    = r'\('
    # t_RPAREN    = r'\)'

    def t_NEW_LINE( t ):
        r'\n'

        t.lexer.lineno += 1
        return t

    # we use this to represent a block of text
    def t_BLOCK( t ):
        r'%%BLOCK_BEGIN%%(\n|.)*?%%BLOCK_END%%'

        # we're only interested in the content of the block
        # TODO: move to parser
        block = r'%%BLOCK_BEGIN%%((\n|.)*?)%%BLOCK_END%%'
        t.value = re.match( block, t.value ).group( 1 )

        t.lexer.lineno += t.value.count( '\n' )

        return t

    # string token processor
    def t_STRING( t ):
        r'"(\\"|[^"])*?"'

        # remove the quotes and unescape the text
        # TODO: move to parser
        str = t.value[1:-1]
        t.value = str.encode().decode( 'unicode-escape' )

        return t

    def t_ID( t ):
        r'[a-zA-Z_][a-zA-Z0-9_]*'

        # cast the id to a reserved token if its found in the dict
        t.type = reserved.get( t.value, 'ID' )

        if t.type != 'ID':
            return t

        # cast the id to a js_reserved token if its found in the dict
        t.type = js_reserved.get( t.value, 'ID' )
        return t

    t_ignore = '[ \t]' # TODO: add comment?

    #error processor
    def t_error( t ):
        print( 'Unknown text "{0}"'.format( t.value[0] ), file=sys.stderr )

    global_lexer = lex.lex()

    lexer = global_lexer.clone()
    lexer.file_path   = file_path   # used when displaying systax errors
    lexer.dir_path    = dir_path    # used for finding files via a relative path
    lexer.script_vars = script_vars # we store the variables here as they're generated

    return lexer

################################################################################
# Parser #######################################################################
################################################################################

def create_parser():
    '''This will generate the parser for the processor. Since this can be time
    consuming and may be called for each individual file ( to which there may be
    many ), then we'll store a parser globally return that every time we need a
    new one'''

    global global_parser
    global tokens

    if global_parser:
        return global_parser

    #TODO: FIX
    # calculate the distance of the lexer position from the previous new line
    def find_column( input, t ):
        last_cr = input.rfind( '\n', 0, t.lexpos )
        if last_cr < 0:
            last_cr = 0

        return t.lexpos - last_cr + 1

    def p_output( p ):
        '''output : output block
                  | output delimiter
                  | output new_line
                  | block'''

        p[0] = p[1] + p[2] if len( p ) > 2 else p[1]

    def p_use_scrict( p ):
        '''block : USE_STRICT delimiter
                 | USE_STRICT new_line
                 | USE_STRICT block'''

        p[0] = '"use strict";\n'

    def p_include_1( p ):
        '''block : INCLUDE string delimiter
                 | INCLUDE string new_line
                 | INCLUDE string block'''

        # TODO: actually include

        data = include_file( p[2], p.lexer.dir_path, p.lexer.script_vars )

        p[0] = '{0}\n{1}'.format( data, p[3] )

    def p_echo( p ):
        '''block : ECHO string delimiter
                 | ECHO string new_line
                 | ECHO string block'''

        string = p[2]

        # TODO: move to p_string ???
        importer = r'\$\{(.*?)\}'

        while True:
            match = re.search( importer, string )
            if not match:
                break

            source, value = match.group( 0 ), match.group( 1 )

            value = import_file( value )

            string = string.replace( source, value, 1 )

        p[0] = '{0}\n{1}'.format( string, p[3] )

    ## Function scopes

    # empty scope params
    def p_begin_scope( p ):
        '''begin_scope : SCOPE_BEGIN delimiter
                       | SCOPE_BEGIN new_line'''

        p[0] = ''

    def p_end_scope( p ):
        '''end_scope : SCOPE_END delimiter
                     | SCOPE_END new_line'''

        p[0] = ''

    #scopes with params
    def p_begin_scope_params_1( p ):
        'begin_scope_params : SCOPE_BEGIN string'

        p[0] = p[2]

    def p_begin_scope_params_2( p ):
        'begin_scope_params : begin_scope_params separator string'

        p[0] = p[1] + ',' + p[3]

    def p_begin_scope_with_params( p ):
        '''begin_scope : begin_scope_params delimiter
                       | begin_scope_params new_line'''

        p[0] = p[1]

    def p_end_scope_params_1( p ):
        'end_scope_params : SCOPE_END string'

        p[0] = p[2]

    def p_end_scope_params_2( p ):
        'end_scope_params : end_scope_params separator string'

        p[0] = p[1] + ',' + p[3]

    def p_end_scope_with_params( p ):
        '''end_scope : end_scope_params delimiter
                     | end_scope_params new_line'''

        p[0] = p[1]

    #clear any excess delimiters
    def p_begin_scope_delimiter( p ):
        '''begin_scope : begin_scope delimiter
                       | begin_scope new_line'''
        p[0] = p[1]

    # join the scopes
    def p_scope( p ):
        'block : begin_scope output end_scope'

        p[0] = ';(function({0}){{\n{1}\n}})({2});\n'.format( p[1], p[2], p[3] )

    def p_separator( p ):
        '''separator : separator new_line
                     | SEPARATOR'''

        p[0] = ','

    def p_string( p ):
        'string : STRING'

        p[0] = p[1]

    def p_block_1( p ):
        'block : BLOCK'

        p[0] = p[1]

    def p_new_line( p ):
        'new_line : NEW_LINE'

        p[0] = ''

    def p_delimiter( p ):
        '''delimiter : DELIMITER
                     | COMMENT
                     | begin_scope end_scope''' # an empty scope is pointless, get rid of it

        p[0] = ''

    def p_error( p ):
        # msg = repr( dir( p ) )
        msg = 'Syntax error: unexpected {0} "{1}" in {2} line {3}'.format(
            p.type, p.value, p.lexer.file_path, p.lineno )
        print( msg, file=sys.stderr )

    # TODO: if ( debug )
    global_parser = yacc.yacc()
    return global_parser

################################################################################
# Default Processor ############################################################
################################################################################

def default_processor( file_path, script_vars={}, compress=False ):
    '''not yet implemented'''
    return ''

################################################################################
# SASS Application #############################################################
################################################################################

def call_sass( params ):
    params = ' '.join( params )

    cmd = 'sass {0}'.format( params )

    proc = sp.Popen( cmd, stdout=sp.PIPE, stdin=sp.PIPE, shell=True )

    output, error = proc.communicate()

    return output.decode( 'utf-8' )

################################################################################
# SASS Processor ###############################################################
################################################################################

def sass_processor( file_path, script_vars={}, compress=False ):
    '''This require ruby and sass to be installed.'''
    params = []

    if compress:
        params.append( '-t compressed' )

    params.append( file_path )

    css = call_sass( params )

    # sass leaves a trailing \n
    if compress:
        css = css.replace( '\n', '' )

    return css

################################################################################
# HTML Processor ###############################################################
################################################################################

def html_processor( file_path, script_vars={}, compress=False ):
    '''This requires java installed for compression'''
    # TODO: Do some actual processing ( maybe use bottles preprocessor )

    try:
        source = open( file_path, 'r' ).read()
    except ( OSError, IOError ) as e:
        print( e, file=sys.stderr )
        exit( 1 )

    if compress:
        # we'll use the html compressor in /tools
        cmd = 'java -jar {0}/tools/html-compressor/htmlcompressor-1.5.3.jar'.format( os.path.dirname( __file__ ) )

        proc = sp.Popen( cmd, stdout=sp.PIPE, stdin=sp.PIPE, shell=True )
        proc.stdin.write( source.encode() )

        output, error = proc.communicate()

        source = output.decode( 'utf-8' )

    return source

################################################################################
# CSS Processor ################################################################
################################################################################

def css_processor( file_path, script_vars={}, compress=False ):
    '''Not yet implemented.'''
    return ''

################################################################################
# JS Processor #################################################################
################################################################################

def js_processor( file_path, script_vars={}, compress=False ):
    '''Process a given source file, returning the processed JS. the optional
    vars allow for variables not present in the script to bhe passed in to the
    processor. By default compression is not carried out and single quotes/new
    lines are not escaped. compression should be enabled only at the top level
    and escaping should only be performed where the result will be inserted into
     a string'''
    # todo should strings be completely escaped or not?

    lexer    = create_lexer( file_path, script_vars )
    parser   = create_parser()

    try:
        source = open( file_path, 'r' ).read()
    except ( OSError, IOError ) as e:
        print( e, file=sys.stderr )
        exit( 1 )

    code = enclose_js( source )
    code = parser.parse( code, lexer=lexer )

    if compress:
        cmd = 'java -jar {0}/tools/yui-compressor/yuicompressor-2.4.8.jar --type js'.format( os.path.dirname( __file__ ) )

        proc = sp.Popen( cmd, stdout=sp.PIPE, stdin=sp.PIPE, shell=True )
        proc.stdin.write( code.encode() )

        output, error = proc.communicate()

        code = output.decode( 'utf-8' )

    return code

# TODO: use a tokenising switcher in the lexer
def enclose_js( source ):
    '''In order to aid tokenising we'll wrap the JS code in a JS block and
    remove the preprocessor code from the block by finding it and replacing the
    comment tokens with block tokens. We're effectively inverting the code from
    JS code with buildr blocks to buildr code with JS blocks'''

    # wrap all the code ( useful for when there is no buildr code )
    code = '%%BLOCK_BEGIN%%{0}%%BLOCK_END%%'.format( source )

    block = r'/\*##(.*?)\*/'
    container = '%%BLOCK_END%%{0}%%BLOCK_BEGIN%%'

    # replace all buildr code blocks
    while True:
        match = re.search( block, code, re.DOTALL )
        if not match:
            break

        comment, content = match.group( 0 ), match.group( 1 )
        content = container.format( content )

        code = code.replace( comment, content, 1 )

    line = r'//##(.*?)\n'
    container = '%%BLOCK_END%%{0}\n%%BLOCK_BEGIN%%'

    while True:
        match = re.search( line, code )
        if not match:
            break

        comment, content = match.group( 0 ), match.group( 1 )
        content = container.format( content )

        code = code.replace( comment, content, 1 )

    return code

<|endoftext|>


<commit_before>"""A simple Flask web application.

Lasya Sreepada
Yale University '19
CPSC 184

May 6, 2017
"""

from flask import Flask, render_template
from questions import quiz
app = Flask(__name__)

@app.route("/")
def main():
    return render_template('index.html')

@app.route("/home")
def home():
    return render_template('home.html')

@app.route("/quiz")
def runquiz():
    return quiz()

@app.route("/memes")
def memes():
    return render_template('memes.html')

@app.route("/copyright")
def copyright():
    return render_template('copyright.html')

@app.route("/trademark")
def trademark():
    return render_template('trademark.html')

@app.route("/patent")
def patent():
    return render_template('patents.html')

if __name__ == "__main__":
    app.run()

if __name__ == "__quiz__":
    app.run()

if __name__ == "__memes__":
    app.run()
<commit_msg>undoing stupid changes<commit_after>"""A simple Flask web application.

Lasya Sreepada
Yale University '19
CPSC 184

May 6, 2017
"""

from flask import Flask, render_template
from questions import quiz
app = Flask(__name__)

@app.route("/")
def main():
    return render_template('index.html')

@app.route("/home")
def home():
    return render_template('home.html')

@app.route("/quiz")
def quiz():
    return render_template('quiz.html')

@app.route("/memes")
def memes():
    return render_template('memes.html')

@app.route("/copyright")
def copyright():
    return render_template('copyright.html')

@app.route("/trademark")
def trademark():
    return render_template('trademark.html')

@app.route("/patent")
def patent():
    return render_template('patents.html')

if __name__ == "__main__":
    app.run()

if __name__ == "__quiz__":
    app.run()

if __name__ == "__memes__":
    app.run()
<|endoftext|>