<commit_before># Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# MIT License. See license.txt

from __future__ import unicode_literals
import frappe
from frappe.utils import cint
from frappe import _
from six import string_types
import json

class WorkflowStateError(frappe.ValidationError): pass
class WorkflowTransitionError(frappe.ValidationError): pass
class WorkflowPermissionError(frappe.ValidationError): pass

def get_workflow_name(doctype):
	workflow_name = frappe.cache().hget('workflow', doctype)
	if workflow_name is None:
		workflow_name = frappe.db.get_value("Workflow", {"document_type": doctype,
			"is_active": 1}, "name")
		frappe.cache().hset('workflow', doctype, workflow_name or '')

	return workflow_name

@frappe.whitelist()
def get_transitions(doc, workflow = None, raise_exception=False):
	'''Return list of possible transitions for the given doc'''
	doc = frappe.get_doc(frappe.parse_json(doc))

	if doc.is_new():
		return []

	doc.load_from_db()

	frappe.has_permission(doc, 'read', throw=True)
	roles = frappe.get_roles()

	if not workflow:
		workflow = get_workflow(doc.doctype)
	current_state = doc.get(workflow.workflow_state_field)

	if not current_state:
		if raise_exception:
			raise WorkflowStateError
		else:
			frappe.throw(_('Workflow State not set'), WorkflowStateError)

	transitions = []
	for transition in workflow.transitions:
		if transition.state == current_state and transition.allowed in roles:
			if not is_transition_condition_satisfied(transition, doc):
				continue
			transitions.append(transition.as_dict())
	return transitions

def get_workflow_safe_globals():
	# access to frappe.db.get_value, frappe.db.get_list, and date time utils.
	return dict(
		frappe=frappe._dict(
			db=frappe._dict(
				get_value=frappe.db.get_value,
				get_list=frappe.db.get_list
			),
			session=frappe.session,
			utils=frappe._dict(
				now_datetime=frappe.utils.now_datetime,
				add_to_date=frappe.utils.add_to_date,
				get_datetime=frappe.utils.get_datetime,
				now=frappe.utils.now
				)
		)
	)

def is_transition_condition_satisfied(transition, doc):
	if not transition.condition:
		return True
	else:
		return frappe.safe_eval(transition.condition, get_workflow_safe_globals(), dict(doc=doc.as_dict()))

@frappe.whitelist()
def apply_workflow(doc, action):
	'''Allow workflow action on the current doc'''
	doc = frappe.get_doc(frappe.parse_json(doc))
	workflow = get_workflow(doc.doctype)
	transitions = get_transitions(doc, workflow)
	user = frappe.session.user

	# find the transition
	transition = None
	for t in transitions:
		if t.action == action:
			transition = t

	if not transition:
		frappe.throw(_("Not a valid Workflow Action"), WorkflowTransitionError)

	if not has_approval_access(user, doc, transition):
		frappe.throw(_("Self approval is not allowed"))

	# update workflow state field
	doc.set(workflow.workflow_state_field, transition.next_state)

	# find settings for the next state
	next_state = [d for d in workflow.states if d.state == transition.next_state][0]

	# update any additional field
	if next_state.update_field:
		doc.set(next_state.update_field, next_state.update_value)

	new_docstatus = cint(next_state.doc_status)
	if doc.docstatus == 0 and new_docstatus == 0:
		doc.save()
	elif doc.docstatus == 0 and new_docstatus == 1:
		doc.submit()
	elif doc.docstatus == 1 and new_docstatus == 1:
		doc.save()
	elif doc.docstatus == 1 and new_docstatus == 2:
		doc.cancel()
	else:
		frappe.throw(_('Illegal Document Status for {0}').format(next_state.state))

	doc.add_comment('Workflow', _(next_state.state))

	return doc

@frappe.whitelist()
def can_cancel_document(doc):
	doc = frappe.get_doc(frappe.parse_json(doc))
	workflow = get_workflow(doc.doctype)
	for state_doc in workflow.states:
		if state_doc.doc_status == '2':
			for transition in workflow.transitions:
				if transition.next_state == state_doc.state:
					return False
			return True
	return True

def validate_workflow(doc):
	'''Validate Workflow State and Transition for the current user.

	- Check if user is allowed to edit in current state
	- Check if user is allowed to transition to the next state (if changed)
	'''
	workflow = get_workflow(doc.doctype)

	current_state = None
	if getattr(doc, '_doc_before_save', None):
		current_state = doc._doc_before_save.get(workflow.workflow_state_field)
	next_state = doc.get(workflow.workflow_state_field)

	if not next_state:
		next_state = workflow.states[0].state
		doc.set(workflow.workflow_state_field, next_state)

	if not current_state:
		current_state = workflow.states[0].state

	state_row = [d for d in workflow.states if d.state == current_state]
	if not state_row:
		frappe.throw(_('{0} is not a valid Workflow State. Please update your Workflow and try again.').format(frappe.bold(current_state)))
	state_row = state_row[0]

	# if transitioning, check if user is allowed to transition
	if current_state != next_state:
		bold_current = frappe.bold(current_state)
		bold_next = frappe.bold(next_state)

		if not doc._doc_before_save:
			# transitioning directly to a state other than the first
			# e.g from data import
			frappe.throw(_('Workflow State transition not allowed from {0} to {1}').format(bold_current, bold_next),
				WorkflowPermissionError)

		transitions = get_transitions(doc._doc_before_save)
		transition = [d for d in transitions if d.next_state == next_state]
		if not transition:
			frappe.throw(_('Workflow State transition not allowed from {0} to {1}').format(bold_current, bold_next),
				WorkflowPermissionError)

def get_workflow(doctype):
	return frappe.get_doc('Workflow', get_workflow_name(doctype))

def has_approval_access(user, doc, transition):
	return (user == 'Administrator'
		or transition.get('allow_self_approval')
		or user != doc.get('owner'))

def get_workflow_state_field(workflow_name):
	return get_workflow_field_value(workflow_name, 'workflow_state_field')

def send_email_alert(workflow_name):
	return get_workflow_field_value(workflow_name, 'send_email_alert')

def get_workflow_field_value(workflow_name, field):
	value = frappe.cache().hget('workflow_' + workflow_name, field)
	if value is None:
		value = frappe.db.get_value("Workflow", workflow_name, field)
		frappe.cache().hset('workflow_' + workflow_name, field, value)
	return value

@frappe.whitelist()
def bulk_workflow_approval(docnames, doctype, action):
	from collections import defaultdict

	# dictionaries for logging
	failed_transactions = defaultdict(list)
	successful_transactions = defaultdict(list)

	# WARN: message log is cleared
	print("Clearing frappe.message_log...")
	frappe.clear_messages()

	docnames = json.loads(docnames)
	for (idx, docname) in enumerate(docnames, 1):
		message_dict = {}
		try:
			show_progress(docnames, _('Applying: {0}').format(action), idx, docname)
			apply_workflow(frappe.get_doc(doctype, docname), action)
			frappe.db.commit()
		except Exception as e:
			if not frappe.message_log:
				# Exception is  raised manually and not from msgprint or throw
				message = "{0}".format(e.__class__.__name__)
				if e.args:
					message +=  " : {0}".format(e.args[0])
				message_dict = {"docname": docname, "message": message}
				failed_transactions[docname].append(message_dict)

			frappe.db.rollback()
			frappe.log_error(frappe.get_traceback(), "Workflow {0} threw an error for {1} {2}".format(action, doctype, docname))
		finally:
			if not message_dict:
				if frappe.message_log:
					messages = frappe.get_message_log()
					for message in messages:
						frappe.message_log.pop()
						message_dict = {"docname": docname, "message": message.get("message")}

						if message.get("raise_exception", False):
							failed_transactions[docname].append(message_dict)
						else:
							successful_transactions[docname].append(message_dict)
				else:
					successful_transactions[docname].append({"docname": docname, "message": None})

	if failed_transactions and successful_transactions:
		indicator = "orange"
	elif failed_transactions:
		indicator  = "red"
	else:
		indicator = "green"

	print_workflow_log(failed_transactions, _("Failed Transactions"), doctype, indicator)
	print_workflow_log(successful_transactions, _("Successful Transactions"), doctype, indicator)

def print_workflow_log(messages, title, doctype, indicator):
	if messages.keys():
		msg = "
{0}
".format(title)

		for doc in messages.keys():
			if len(messages[doc]):
				html = "{0}".format(frappe.utils.get_link_to_form(doctype, doc))
				for log in messages[doc]:
					if log.get('message'):
						html += "
{0}
".format(log.get('message'))
				html += ""
			else:
				html = "
{0}
".format(doc)
			msg += html

		frappe.msgprint(msg, title=_("Workflow Status"), indicator=indicator, is_minimizable=True)

@frappe.whitelist()
def get_common_transition_actions(docs, doctype):
	common_actions = []
	if isinstance(docs, string_types):
		docs = json.loads(docs)
	try:
		for (i, doc) in enumerate(docs, 1):
			if not doc.get('doctype'):
				doc['doctype'] = doctype
			actions = [t.get('action') for t in get_transitions(doc, raise_exception=True) \
				if has_approval_access(frappe.session.user, doc, t)]
			if not actions:
				return []
			common_actions = actions if i == 1 else set(common_actions).intersection(actions)
			if not common_actions:
				return []
	except WorkflowStateError:
		pass

	return list(common_actions)

def show_progress(docnames, message, i, description):
	n = len(docnames)
	if n >= 5:
		frappe.publish_progress(
			float(i) * 100 / n,
			title = message,
			description = description
		)

def set_workflow_state_on_action(doc, workflow_name, action):
	workflow = frappe.get_doc('Workflow', workflow_name)
	workflow_state_field = workflow.workflow_state_field

	# If workflow state of doc is already correct, don't set workflow state
	for state in workflow.states:
		if state.state == doc.get(workflow_state_field) and doc.docstatus == cint(state.doc_status):
			return

	action_map = {
		'update_after_submit': '1',
		'submit': '1',
		'cancel': '2'
	}
	docstatus = action_map[action]
	for state in workflow.states:
		if state.doc_status == docstatus:
			doc.set(workflow_state_field, state.state)
			return
<commit_msg>style: Black over updated diffs<commit_after># Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# MIT License. See license.txt

from __future__ import unicode_literals
import frappe
from frappe.utils import cint
from frappe import _
from six import string_types
import json

class WorkflowStateError(frappe.ValidationError): pass
class WorkflowTransitionError(frappe.ValidationError): pass
class WorkflowPermissionError(frappe.ValidationError): pass

def get_workflow_name(doctype):
	workflow_name = frappe.cache().hget('workflow', doctype)
	if workflow_name is None:
		workflow_name = frappe.db.get_value("Workflow", {"document_type": doctype,
			"is_active": 1}, "name")
		frappe.cache().hset('workflow', doctype, workflow_name or '')

	return workflow_name

@frappe.whitelist()
def get_transitions(doc, workflow = None, raise_exception=False):
	'''Return list of possible transitions for the given doc'''
	doc = frappe.get_doc(frappe.parse_json(doc))

	if doc.is_new():
		return []

	doc.load_from_db()

	frappe.has_permission(doc, 'read', throw=True)
	roles = frappe.get_roles()

	if not workflow:
		workflow = get_workflow(doc.doctype)
	current_state = doc.get(workflow.workflow_state_field)

	if not current_state:
		if raise_exception:
			raise WorkflowStateError
		else:
			frappe.throw(_('Workflow State not set'), WorkflowStateError)

	transitions = []
	for transition in workflow.transitions:
		if transition.state == current_state and transition.allowed in roles:
			if not is_transition_condition_satisfied(transition, doc):
				continue
			transitions.append(transition.as_dict())
	return transitions

def get_workflow_safe_globals():
	# access to frappe.db.get_value, frappe.db.get_list, and date time utils.
	return dict(
		frappe=frappe._dict(
			db=frappe._dict(get_value=frappe.db.get_value, get_list=frappe.db.get_list),
			session=frappe.session,
			utils=frappe._dict(
				now_datetime=frappe.utils.now_datetime,
				add_to_date=frappe.utils.add_to_date,
				get_datetime=frappe.utils.get_datetime,
				now=frappe.utils.now,
			),
		)
	)

def is_transition_condition_satisfied(transition, doc):
	if not transition.condition:
		return True
	else:
		return frappe.safe_eval(transition.condition, get_workflow_safe_globals(), dict(doc=doc.as_dict()))

@frappe.whitelist()
def apply_workflow(doc, action):
	'''Allow workflow action on the current doc'''
	doc = frappe.get_doc(frappe.parse_json(doc))
	workflow = get_workflow(doc.doctype)
	transitions = get_transitions(doc, workflow)
	user = frappe.session.user

	# find the transition
	transition = None
	for t in transitions:
		if t.action == action:
			transition = t

	if not transition:
		frappe.throw(_("Not a valid Workflow Action"), WorkflowTransitionError)

	if not has_approval_access(user, doc, transition):
		frappe.throw(_("Self approval is not allowed"))

	# update workflow state field
	doc.set(workflow.workflow_state_field, transition.next_state)

	# find settings for the next state
	next_state = [d for d in workflow.states if d.state == transition.next_state][0]

	# update any additional field
	if next_state.update_field:
		doc.set(next_state.update_field, next_state.update_value)

	new_docstatus = cint(next_state.doc_status)
	if doc.docstatus == 0 and new_docstatus == 0:
		doc.save()
	elif doc.docstatus == 0 and new_docstatus == 1:
		doc.submit()
	elif doc.docstatus == 1 and new_docstatus == 1:
		doc.save()
	elif doc.docstatus == 1 and new_docstatus == 2:
		doc.cancel()
	else:
		frappe.throw(_('Illegal Document Status for {0}').format(next_state.state))

	doc.add_comment('Workflow', _(next_state.state))

	return doc

@frappe.whitelist()
def can_cancel_document(doc):
	doc = frappe.get_doc(frappe.parse_json(doc))
	workflow = get_workflow(doc.doctype)
	for state_doc in workflow.states:
		if state_doc.doc_status == '2':
			for transition in workflow.transitions:
				if transition.next_state == state_doc.state:
					return False
			return True
	return True

def validate_workflow(doc):
	'''Validate Workflow State and Transition for the current user.

	- Check if user is allowed to edit in current state
	- Check if user is allowed to transition to the next state (if changed)
	'''
	workflow = get_workflow(doc.doctype)

	current_state = None
	if getattr(doc, '_doc_before_save', None):
		current_state = doc._doc_before_save.get(workflow.workflow_state_field)
	next_state = doc.get(workflow.workflow_state_field)

	if not next_state:
		next_state = workflow.states[0].state
		doc.set(workflow.workflow_state_field, next_state)

	if not current_state:
		current_state = workflow.states[0].state

	state_row = [d for d in workflow.states if d.state == current_state]
	if not state_row:
		frappe.throw(_('{0} is not a valid Workflow State. Please update your Workflow and try again.').format(frappe.bold(current_state)))
	state_row = state_row[0]

	# if transitioning, check if user is allowed to transition
	if current_state != next_state:
		bold_current = frappe.bold(current_state)
		bold_next = frappe.bold(next_state)

		if not doc._doc_before_save:
			# transitioning directly to a state other than the first
			# e.g from data import
			frappe.throw(_('Workflow State transition not allowed from {0} to {1}').format(bold_current, bold_next),
				WorkflowPermissionError)

		transitions = get_transitions(doc._doc_before_save)
		transition = [d for d in transitions if d.next_state == next_state]
		if not transition:
			frappe.throw(_('Workflow State transition not allowed from {0} to {1}').format(bold_current, bold_next),
				WorkflowPermissionError)

def get_workflow(doctype):
	return frappe.get_doc('Workflow', get_workflow_name(doctype))

def has_approval_access(user, doc, transition):
	return (user == 'Administrator'
		or transition.get('allow_self_approval')
		or user != doc.get('owner'))

def get_workflow_state_field(workflow_name):
	return get_workflow_field_value(workflow_name, 'workflow_state_field')

def send_email_alert(workflow_name):
	return get_workflow_field_value(workflow_name, 'send_email_alert')

def get_workflow_field_value(workflow_name, field):
	value = frappe.cache().hget('workflow_' + workflow_name, field)
	if value is None:
		value = frappe.db.get_value("Workflow", workflow_name, field)
		frappe.cache().hset('workflow_' + workflow_name, field, value)
	return value

@frappe.whitelist()
def bulk_workflow_approval(docnames, doctype, action):
	from collections import defaultdict

	# dictionaries for logging
	failed_transactions = defaultdict(list)
	successful_transactions = defaultdict(list)

	# WARN: message log is cleared
	print("Clearing frappe.message_log...")
	frappe.clear_messages()

	docnames = json.loads(docnames)
	for (idx, docname) in enumerate(docnames, 1):
		message_dict = {}
		try:
			show_progress(docnames, _('Applying: {0}').format(action), idx, docname)
			apply_workflow(frappe.get_doc(doctype, docname), action)
			frappe.db.commit()
		except Exception as e:
			if not frappe.message_log:
				# Exception is  raised manually and not from msgprint or throw
				message = "{0}".format(e.__class__.__name__)
				if e.args:
					message +=  " : {0}".format(e.args[0])
				message_dict = {"docname": docname, "message": message}
				failed_transactions[docname].append(message_dict)

			frappe.db.rollback()
			frappe.log_error(frappe.get_traceback(), "Workflow {0} threw an error for {1} {2}".format(action, doctype, docname))
		finally:
			if not message_dict:
				if frappe.message_log:
					messages = frappe.get_message_log()
					for message in messages:
						frappe.message_log.pop()
						message_dict = {"docname": docname, "message": message.get("message")}

						if message.get("raise_exception", False):
							failed_transactions[docname].append(message_dict)
						else:
							successful_transactions[docname].append(message_dict)
				else:
					successful_transactions[docname].append({"docname": docname, "message": None})

	if failed_transactions and successful_transactions:
		indicator = "orange"
	elif failed_transactions:
		indicator  = "red"
	else:
		indicator = "green"

	print_workflow_log(failed_transactions, _("Failed Transactions"), doctype, indicator)
	print_workflow_log(successful_transactions, _("Successful Transactions"), doctype, indicator)

def print_workflow_log(messages, title, doctype, indicator):
	if messages.keys():
		msg = "
{0}
".format(title)

		for doc in messages.keys():
			if len(messages[doc]):
				html = "{0}".format(frappe.utils.get_link_to_form(doctype, doc))
				for log in messages[doc]:
					if log.get('message'):
						html += "
{0}
".format(log.get('message'))
				html += ""
			else:
				html = "
{0}
".format(doc)
			msg += html

		frappe.msgprint(msg, title=_("Workflow Status"), indicator=indicator, is_minimizable=True)

@frappe.whitelist()
def get_common_transition_actions(docs, doctype):
	common_actions = []
	if isinstance(docs, string_types):
		docs = json.loads(docs)
	try:
		for (i, doc) in enumerate(docs, 1):
			if not doc.get('doctype'):
				doc['doctype'] = doctype
			actions = [t.get('action') for t in get_transitions(doc, raise_exception=True) \
				if has_approval_access(frappe.session.user, doc, t)]
			if not actions:
				return []
			common_actions = actions if i == 1 else set(common_actions).intersection(actions)
			if not common_actions:
				return []
	except WorkflowStateError:
		pass

	return list(common_actions)

def show_progress(docnames, message, i, description):
	n = len(docnames)
	if n >= 5:
		frappe.publish_progress(
			float(i) * 100 / n,
			title = message,
			description = description
		)

def set_workflow_state_on_action(doc, workflow_name, action):
	workflow = frappe.get_doc('Workflow', workflow_name)
	workflow_state_field = workflow.workflow_state_field

	# If workflow state of doc is already correct, don't set workflow state
	for state in workflow.states:
		if state.state == doc.get(workflow_state_field) and doc.docstatus == cint(state.doc_status):
			return

	action_map = {
		'update_after_submit': '1',
		'submit': '1',
		'cancel': '2'
	}
	docstatus = action_map[action]
	for state in workflow.states:
		if state.doc_status == docstatus:
			doc.set(workflow_state_field, state.state)
			return
<|endoftext|>


<commit_before>"""
This cog will create messages that will manage channel perms with reacts.
"""
import discord
import datetime
from asyncpg.exceptions import UniqueViolationError
from collections import defaultdict
from .utils import helpers, checks
from discord.ext import commands

class Channels():
    """
    """

    def __init__(self, bot):
        super().__init__()
        self.reaction_emojis = [ '\N{WHITE HEAVY CHECK MARK}'
            '0\u20e3', '1\u20e3', '2\u20e3', '3\u20e3', '4\u20e3',
            '5\u20e3', '6\u20e3', '7\u20e3', '8\u20e3', '9\u20e3',
            '\N{REGIONAL INDICATOR SYMBOL LETTER A}',
            '\N{REGIONAL INDICATOR SYMBOL LETTER B}',
            '\N{REGIONAL INDICATOR SYMBOL LETTER C}',
            '\N{REGIONAL INDICATOR SYMBOL LETTER D}',
            '\N{REGIONAL INDICATOR SYMBOL LETTER E}',
            '\N{REGIONAL INDICATOR SYMBOL LETTER F}',
            ]
        self.bot = bot

    @commands.group()
    @commands.guild_only()
    @checks.has_permissions(manage_channels=True)
    async def channel_message(self, ctx):
         if ctx.invoked_subcommand is None:
            await ctx.send(':thinking:')

    @channel_message.command(aliases=['add'])
    async def create(self, ctx, target_channel: discord.TextChannel, *, description: str):
        if not isinstance(target_channel, discord.TextChannel):
            await ctx.send("that is not a valid channel fam", delete_after=4)
            return
        local_embed = discord.Embed(
            title=f'#{target_channel.name}',
            description=f'{description[:2046]}',
            type="rich"
        )
        message = await ctx.send(embed=local_embed)
        await message.add_reaction(self.reaction_emojis[0])
        try:
            await self.bot.postgres_controller.add_channel_message(
                message.id, target_channel.id, ctx.channel.id)
        except UniqueViolationError:
            await message.delete()
            await ctx.send(
                f"There already exists a link to {target_channel.name} here.")
        await ctx.message.delete()

    @channel_message.command(aliases=['rem'])
    async def remove(self, ctx, target_channel: discord.TextChannel):
        """
        uhhh it removes the thing
        """
        if not isinstance(target_channel, discord.TextChannel):
            await ctx.send("that is not a valid channel fam", delete_after=4)
            return
        try:
            message_id = await self.bot.postgres_controller.get_message_info(
                ctx.channel.id, target_channel.id)
        except Exception as e:
            await ctx.send("something broke", delete_after=3)
            return
        if not message_id:
            return
        og_message = await ctx.channel.get_message(message_id)
        for reaction in og_message.reactions:
            async for user in reaction.users():
                if user.bot:
                    continue
                await og_message.remove_reaction(reaction.emoji, user)
                await self.remove_perms(user, target_channel)
        await og_message.delete()
        await self.bot.postgres_controller.rem_channel_message(target_channel.id, ctx.channel.id)
        await ctx.message.delete()

    @channel_message.command()
    async def edit(self, ctx, target_channel: discord.TextChannel, *, edit: str):
        if not isinstance(target_channel, discord.TextChannel):
            await ctx.send("that is not a valid channel fam", delete_after=4)
            return
        try:
            message_id = await self.bot.postgres_controller.get_message_info(
                ctx.channel.id, target_channel.id)
        except:
            await ctx.send("something broke", delete_after=3)
            return
        if not message_id:
            return
        og_message = await ctx.channel.get_message(message_id)
        og_embed = og_message.embeds[0]
        og_embed.description = edit[:2046]
        await og_message.edit(embed=og_embed)
        await ctx.send(":ok_hand:", delete_after=3)
        await ctx.message.delete()

    async def on_raw_reaction_add(self, emoji, message_id, channel_id, user_id):
        """
        Called when an emoji is added
        """
        target_channel = await self.bot.postgres_controller.get_target_channel(channel_id, message_id)
        if not target_channel:
                return
        channel = self.bot.get_channel(target_channel)
        user = self.bot.get_user(user_id)
        await self.add_perms(user, channel)

    async def on_raw_reaction_remove(self, emoji, message_id, channel_id, user_id):
        """
        Called when an emoji is removed
        """
        target_channel = await self.bot.postgres_controller.get_target_channel(channel_id, message_id)
        if not target_channel:
            return
        channel = self.bot.get_channel(target_channel)
        user = self.bot.get_user(user_id)
        await self.remove_perms(user, channel)

    async def add_perms(self, user, channel):
        """
        Adds a user to channels perms
        """
        try:
            await channel.set_permissions(user, read_messages=True,
                                                        send_messages=True)
        except Exception as e:
            self.bot.logger.warning(f'{e}')

    async def remove_perms(self, user, channel):
        """
        removes a users perms on a channel
        """
        try:
            await channel.set_permissions(user, read_messages=False,
                                                        send_messages=False)
        except Exception as e:
            self.bot.logger.warning(f'{e}')
<commit_msg>LMAO it was the missing comma<commit_after>"""
This cog will create messages that will manage channel perms with reacts.
"""
import discord
import datetime
from asyncpg.exceptions import UniqueViolationError
from collections import defaultdict
from .utils import helpers, checks
from discord.ext import commands

class Channels():
    """
    """

    def __init__(self, bot):
        super().__init__()
        self.reaction_emojis = [ '\N{WHITE HEAVY CHECK MARK}',
            '0\u20e3', '1\u20e3', '2\u20e3', '3\u20e3', '4\u20e3',
            '5\u20e3', '6\u20e3', '7\u20e3', '8\u20e3', '9\u20e3',
            '\N{REGIONAL INDICATOR SYMBOL LETTER A}',
            '\N{REGIONAL INDICATOR SYMBOL LETTER B}',
            '\N{REGIONAL INDICATOR SYMBOL LETTER C}',
            '\N{REGIONAL INDICATOR SYMBOL LETTER D}',
            '\N{REGIONAL INDICATOR SYMBOL LETTER E}',
            '\N{REGIONAL INDICATOR SYMBOL LETTER F}',
            ]
        self.bot = bot

    @commands.group()
    @commands.guild_only()
    @checks.has_permissions(manage_channels=True)
    async def channel_message(self, ctx):
         if ctx.invoked_subcommand is None:
            await ctx.send(':thinking:')

    @channel_message.command(aliases=['add'])
    async def create(self, ctx, target_channel: discord.TextChannel, *, description: str):
        if not isinstance(target_channel, discord.TextChannel):
            await ctx.send("that is not a valid channel fam", delete_after=4)
            return
        local_embed = discord.Embed(
            title=f'#{target_channel.name}',
            description=f'{description[:2046]}',
            type="rich"
        )
        message = await ctx.send(embed=local_embed)
        await message.add_reaction(self.reaction_emojis[0])
        try:
            await self.bot.postgres_controller.add_channel_message(
                message.id, target_channel.id, ctx.channel.id)
        except UniqueViolationError:
            await message.delete()
            await ctx.send(
                f"There already exists a link to {target_channel.name} here.")
        await ctx.message.delete()

    @channel_message.command(aliases=['rem'])
    async def remove(self, ctx, target_channel: discord.TextChannel):
        """
        uhhh it removes the thing
        """
        if not isinstance(target_channel, discord.TextChannel):
            await ctx.send("that is not a valid channel fam", delete_after=4)
            return
        try:
            message_id = await self.bot.postgres_controller.get_message_info(
                ctx.channel.id, target_channel.id)
        except Exception as e:
            await ctx.send("something broke", delete_after=3)
            return
        if not message_id:
            return
        og_message = await ctx.channel.get_message(message_id)
        for reaction in og_message.reactions:
            async for user in reaction.users():
                if user.bot:
                    continue
                await og_message.remove_reaction(reaction.emoji, user)
                await self.remove_perms(user, target_channel)
        await og_message.delete()
        await self.bot.postgres_controller.rem_channel_message(target_channel.id, ctx.channel.id)
        await ctx.message.delete()

    @channel_message.command()
    async def edit(self, ctx, target_channel: discord.TextChannel, *, edit: str):
        if not isinstance(target_channel, discord.TextChannel):
            await ctx.send("that is not a valid channel fam", delete_after=4)
            return
        try:
            message_id = await self.bot.postgres_controller.get_message_info(
                ctx.channel.id, target_channel.id)
        except:
            await ctx.send("something broke", delete_after=3)
            return
        if not message_id:
            return
        og_message = await ctx.channel.get_message(message_id)
        og_embed = og_message.embeds[0]
        og_embed.description = edit[:2046]
        await og_message.edit(embed=og_embed)
        await ctx.send(":ok_hand:", delete_after=3)
        await ctx.message.delete()

    async def on_raw_reaction_add(self, emoji, message_id, channel_id, user_id):
        """
        Called when an emoji is added
        """
        target_channel = await self.bot.postgres_controller.get_target_channel(channel_id, message_id)
        if not target_channel:
                return
        channel = self.bot.get_channel(target_channel)
        user = self.bot.get_user(user_id)
        await self.add_perms(user, channel)

    async def on_raw_reaction_remove(self, emoji, message_id, channel_id, user_id):
        """
        Called when an emoji is removed
        """
        target_channel = await self.bot.postgres_controller.get_target_channel(channel_id, message_id)
        if not target_channel:
            return
        channel = self.bot.get_channel(target_channel)
        user = self.bot.get_user(user_id)
        await self.remove_perms(user, channel)

    async def add_perms(self, user, channel):
        """
        Adds a user to channels perms
        """
        try:
            await channel.set_permissions(user, read_messages=True,
                                                        send_messages=True)
        except Exception as e:
            self.bot.logger.warning(f'{e}')

    async def remove_perms(self, user, channel):
        """
        removes a users perms on a channel
        """
        try:
            await channel.set_permissions(user, read_messages=False,
                                                        send_messages=False)
        except Exception as e:
            self.bot.logger.warning(f'{e}')
<|endoftext|>


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

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

import faint
import os

def erase_columns(x0, x1):
    """Reduces the image width by removing all pixel columns from x0
    to x1 (inclusive).

    """

    x0, x1 = min(x0, x1), max(x0, x1)
    if x0 < 0:
        raise ValueError("Negative column specified.")

    image = faint.get_active_image()

    full = image.get_bitmap()
    w, h = full.get_size()
    w2 = w - (x1 - x0 + 1)
    if w2 <= 0:
        raise ValueError("Can't erase all columns.")

    right = full.subbitmap(x1 + 1, 0, w - x1 - 1, h)
    image.blit((x0,0),right)
    image.set_rect(0,0, w2, h)

def erase_rows(y0, y1):
    """Reduces the image height by removing all pixel rows from y0
    to y1 (inclusive).

    """
    y0, y1 = min(y0, y1), max(y0, y1)
    if y0 < 0:
        raise ValueError("Negative row specified.")

    image = faint.get_active_image()

    full = image.get_bitmap()
    w, h = full.get_size()
    h2 = h - (y1 - y0 + 1)
    if h2 <= 0:
        raise ValueError("Can't erase all rows.")

    bottom = full.subbitmap(0, y1 + 1, w, h - y1 - 1)
    image.blit((0, y0),bottom)
    image.set_rect(0,0, w, h2)

def erase_selection():
    """Removes the columns or rows indicated by the raster selection in
    the active image and shrinks the image.

    The raster selection must extend either across all rows or columns
    of the image.

    """

    image = faint.get_active_image()
    x, y, w, h = image.get_selection()
    img_w, img_h = image.get_size()

    if h == img_h:
        erase_columns(x, x + w)
        image.set_selection(0,0,0,0)
        image.command_name = "Erase Columns"

    elif w == img_w:
        erase_rows(y, y + h)
        image.set_selection(0,0,0,0)
        image.command_name = "Erase Rows"

def snowman():
    """Adds a text object with the snowman-character to test unicode
    support.

    """
    s = faint.get_settings()
    s.fontsize = 48
    preferred_font = "DejaVu Sans"
    if preferred_font in faint.list_fonts():
        s.font = preferred_font

    return faint.Text((20,20,100,100), '\u2603', s)

def _open_relative(image, replace, get_new_index):
    if image is None:
        image = faint.get_active_image()
    path = image.get_filename()
    if path is None:
        return

    d, f = os.path.split(path)
    files = sorted(os.listdir(d))

    i = files.index(f)
    new_index = get_new_index(i)
    if new_index < len(files):
        new_image = faint.app.open(os.path.join(d, files[new_index]))
        if replace and new_image is not None:
            faint.app.close(image)

def open_next(image=None, replace=False):
    _open_relative(image, replace, lambda i: i + 1)

def open_prev(image=None, replace=False):
    _open_relative(image, replace, lambda i: i - 1)

def open_first(image=None, replace=False):
    _open_relative(image, replace, lambda i: 0)

def open_last(image=None, replace=False):
    _open_relative(image, replace, lambda i: -1)
<commit_msg>Whitespace.<commit_after>#!/usr/bin/env python3
# -*- coding: utf-8 -*-

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

import faint
import os

def erase_columns(x0, x1):
    """Reduces the image width by removing all pixel columns from x0
    to x1 (inclusive).

    """

    x0, x1 = min(x0, x1), max(x0, x1)
    if x0 < 0:
        raise ValueError("Negative column specified.")

    image = faint.get_active_image()

    full = image.get_bitmap()
    w, h = full.get_size()
    w2 = w - (x1 - x0 + 1)
    if w2 <= 0:
        raise ValueError("Can't erase all columns.")

    right = full.subbitmap(x1 + 1, 0, w - x1 - 1, h)
    image.blit((x0,0),right)
    image.set_rect(0,0, w2, h)

def erase_rows(y0, y1):
    """Reduces the image height by removing all pixel rows from y0
    to y1 (inclusive).

    """
    y0, y1 = min(y0, y1), max(y0, y1)
    if y0 < 0:
        raise ValueError("Negative row specified.")

    image = faint.get_active_image()

    full = image.get_bitmap()
    w, h = full.get_size()
    h2 = h - (y1 - y0 + 1)
    if h2 <= 0:
        raise ValueError("Can't erase all rows.")

    bottom = full.subbitmap(0, y1 + 1, w, h - y1 - 1)
    image.blit((0, y0),bottom)
    image.set_rect(0,0, w, h2)

def erase_selection():
    """Removes the columns or rows indicated by the raster selection in
    the active image and shrinks the image.

    The raster selection must extend either across all rows or columns
    of the image.

    """

    image = faint.get_active_image()
    x, y, w, h = image.get_selection()
    img_w, img_h = image.get_size()

    if h == img_h:
        erase_columns(x, x + w)
        image.set_selection(0,0,0,0)
        image.command_name = "Erase Columns"

    elif w == img_w:
        erase_rows(y, y + h)
        image.set_selection(0,0,0,0)
        image.command_name = "Erase Rows"

def snowman():
    """Adds a text object with the snowman-character to test unicode
    support.

    """
    s = faint.get_settings()
    s.fontsize = 48
    preferred_font = "DejaVu Sans"
    if preferred_font in faint.list_fonts():
        s.font = preferred_font

    return faint.Text((20,20,100,100), '\u2603', s)

def _open_relative(image, replace, get_new_index):
    if image is None:
        image = faint.get_active_image()
    path = image.get_filename()
    if path is None:
        return

    d, f = os.path.split(path)
    files = sorted(os.listdir(d))

    i = files.index(f)
    new_index = get_new_index(i)
    if new_index < len(files):
        new_image = faint.app.open(os.path.join(d, files[new_index]))
        if replace and new_image is not None:
            faint.app.close(image)

def open_next(image=None, replace=False):
    _open_relative(image, replace, lambda i: i + 1)

def open_prev(image=None, replace=False):
    _open_relative(image, replace, lambda i: i - 1)

def open_first(image=None, replace=False):
    _open_relative(image, replace, lambda i: 0)

def open_last(image=None, replace=False):
    _open_relative(image, replace, lambda i: -1)
<|endoftext|>


<commit_before># Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# MIT License. See license.txt

from __future__ import unicode_literals
import json
import datetime
import mimetypes
import os
import frappe
from frappe import _
import frappe.model.document
import frappe.utils
import frappe.sessions
import werkzeug.utils
from werkzeug.local import LocalProxy
from werkzeug.wsgi import wrap_file
from werkzeug.wrappers import Response
from werkzeug.exceptions import NotFound, Forbidden
from frappe.core.doctype.file.file import check_file_permission
from frappe.website.render import render

def report_error(status_code):
	if (status_code!=404 or frappe.conf.logging) and not frappe.local.flags.disable_traceback:
		frappe.errprint(frappe.utils.get_traceback())

	response = build_response("json")
	response.status_code = status_code
	return response

def build_response(response_type=None):
	if "docs" in frappe.local.response and not frappe.local.response.docs:
		del frappe.local.response["docs"]

	response_type_map = {
		'csv': as_csv,
		'download': as_raw,
		'json': as_json,
		'page': as_page,
		'redirect': redirect
	}

	return response_type_map[frappe.response.get('type') or response_type]()

def as_csv():
	response = Response()
	response.headers[b"Content-Type"] = b"text/csv; charset: utf-8"
	response.headers[b"Content-Disposition"] = ("attachment; filename=\"%s.csv\"" % frappe.response['doctype'].replace(' ', '_')).encode("utf-8")
	response.data = frappe.response['result']
	return response

def as_raw():
	response = Response()
	response.headers[b"Content-Type"] = frappe.response.get("content_type") or mimetypes.guess_type(frappe.response['filename'])[0] or b"application/unknown"
	response.headers[b"Content-Disposition"] = ("filename=\"%s\"" % frappe.response['filename'].replace(' ', '_')).encode("utf-8")
	response.data = frappe.response['filecontent']
	return response

def as_json():
	make_logs()
	response = Response()
	if frappe.local.response.http_status_code:
		response.status_code = frappe.local.response['http_status_code']
		del frappe.local.response['http_status_code']

	response.headers[b"Content-Type"] = b"application/json; charset: utf-8"
	response.data = json.dumps(frappe.local.response, default=json_handler, separators=(',',':'))
	return response

def make_logs(response = None):
	"""make strings for msgprint and errprint"""
	if not response:
		response = frappe.local.response

	if frappe.error_log:
		# frappe.response['exc'] = json.dumps("\n".join([cstr(d) for d in frappe.error_log]))
		response['exc'] = json.dumps([frappe.utils.cstr(d) for d in frappe.local.error_log])

	if frappe.local.message_log:
		response['_server_messages'] = json.dumps([frappe.utils.cstr(d) for
			d in frappe.local.message_log])

	if frappe.debug_log and frappe.conf.get("logging") or False:
		response['_debug_messages'] = json.dumps(frappe.local.debug_log)

def json_handler(obj):
	"""serialize non-serializable data for json"""
	# serialize date
	if isinstance(obj, (datetime.date, datetime.timedelta, datetime.datetime)):
		return unicode(obj)
	elif isinstance(obj, LocalProxy):
		return unicode(obj)
	elif isinstance(obj, frappe.model.document.BaseDocument):
		doc = obj.as_dict(no_nulls=True)

		return doc
	else:
		raise TypeError, """Object of type %s with value of %s is not JSON serializable""" % \
			(type(obj), repr(obj))

def as_page():
	"""print web page"""
	return render(frappe.response['page_name'], http_status_code=frappe.response.get("http_status_code"))

def redirect():
	return werkzeug.utils.redirect(frappe.response.location)

def download_backup(path):
	try:
		frappe.only_for(("System Manager", "Administrator"))
	except frappe.PermissionError:
		raise Forbidden(_("You need to be logged in and have System Manager Role to be able to access backups."))

	return send_private_file(path)

def download_private_file(path):
	"""Checks permissions and sends back private file"""
	try:
		check_file_permission(path)

	except frappe.PermissionError:
		raise Forbidden(_("You don't have permission to access this file"))

	return send_private_file(path.split("/private", 1)[1])

def send_private_file(path):
	path = os.path.join(frappe.local.conf.get('private_path', 'private'), path.strip("/"))

	if frappe.local.request.headers.get('X-Use-X-Accel-Redirect'):
		path = '/protected/' + path
		response = Response()
		response.headers[b'X-Accel-Redirect'] = path

	else:
		filename = os.path.basename(path)
		filepath = frappe.utils.get_site_path(path)
		try:
			f = open(filepath, 'rb')
		except IOError:
			raise NotFound

		response = Response(wrap_file(frappe.local.request.environ, f))

		# no need for content disposition, let browser handle it
		# response.headers.add(b'Content-Disposition', 'attachment', filename=filename.encode("utf-8"))

		response.headers[b'Content-Type'] = mimetypes.guess_type(filename)[0] or b'application/octet-stream'

	return response

def handle_session_stopped():
	response = Response("""

											Updating.
											We will be back in a few moments...

					""")
	response.status_code = 503
	response.content_type = 'text/html'
	return response
<commit_msg>[fix] send private file via dev server: use direct_passthrough=True for faster delivery<commit_after># Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# MIT License. See license.txt

from __future__ import unicode_literals
import json
import datetime
import mimetypes
import os
import frappe
from frappe import _
import frappe.model.document
import frappe.utils
import frappe.sessions
import werkzeug.utils
from werkzeug.local import LocalProxy
from werkzeug.wsgi import wrap_file
from werkzeug.wrappers import Response
from werkzeug.exceptions import NotFound, Forbidden
from frappe.core.doctype.file.file import check_file_permission
from frappe.website.render import render

def report_error(status_code):
	if (status_code!=404 or frappe.conf.logging) and not frappe.local.flags.disable_traceback:
		frappe.errprint(frappe.utils.get_traceback())

	response = build_response("json")
	response.status_code = status_code
	return response

def build_response(response_type=None):
	if "docs" in frappe.local.response and not frappe.local.response.docs:
		del frappe.local.response["docs"]

	response_type_map = {
		'csv': as_csv,
		'download': as_raw,
		'json': as_json,
		'page': as_page,
		'redirect': redirect
	}

	return response_type_map[frappe.response.get('type') or response_type]()

def as_csv():
	response = Response()
	response.headers[b"Content-Type"] = b"text/csv; charset: utf-8"
	response.headers[b"Content-Disposition"] = ("attachment; filename=\"%s.csv\"" % frappe.response['doctype'].replace(' ', '_')).encode("utf-8")
	response.data = frappe.response['result']
	return response

def as_raw():
	response = Response()
	response.headers[b"Content-Type"] = frappe.response.get("content_type") or mimetypes.guess_type(frappe.response['filename'])[0] or b"application/unknown"
	response.headers[b"Content-Disposition"] = ("filename=\"%s\"" % frappe.response['filename'].replace(' ', '_')).encode("utf-8")
	response.data = frappe.response['filecontent']
	return response

def as_json():
	make_logs()
	response = Response()
	if frappe.local.response.http_status_code:
		response.status_code = frappe.local.response['http_status_code']
		del frappe.local.response['http_status_code']

	response.headers[b"Content-Type"] = b"application/json; charset: utf-8"
	response.data = json.dumps(frappe.local.response, default=json_handler, separators=(',',':'))
	return response

def make_logs(response = None):
	"""make strings for msgprint and errprint"""
	if not response:
		response = frappe.local.response

	if frappe.error_log:
		# frappe.response['exc'] = json.dumps("\n".join([cstr(d) for d in frappe.error_log]))
		response['exc'] = json.dumps([frappe.utils.cstr(d) for d in frappe.local.error_log])

	if frappe.local.message_log:
		response['_server_messages'] = json.dumps([frappe.utils.cstr(d) for
			d in frappe.local.message_log])

	if frappe.debug_log and frappe.conf.get("logging") or False:
		response['_debug_messages'] = json.dumps(frappe.local.debug_log)

def json_handler(obj):
	"""serialize non-serializable data for json"""
	# serialize date
	if isinstance(obj, (datetime.date, datetime.timedelta, datetime.datetime)):
		return unicode(obj)
	elif isinstance(obj, LocalProxy):
		return unicode(obj)
	elif isinstance(obj, frappe.model.document.BaseDocument):
		doc = obj.as_dict(no_nulls=True)

		return doc
	else:
		raise TypeError, """Object of type %s with value of %s is not JSON serializable""" % \
			(type(obj), repr(obj))

def as_page():
	"""print web page"""
	return render(frappe.response['page_name'], http_status_code=frappe.response.get("http_status_code"))

def redirect():
	return werkzeug.utils.redirect(frappe.response.location)

def download_backup(path):
	try:
		frappe.only_for(("System Manager", "Administrator"))
	except frappe.PermissionError:
		raise Forbidden(_("You need to be logged in and have System Manager Role to be able to access backups."))

	return send_private_file(path)

def download_private_file(path):
	"""Checks permissions and sends back private file"""
	try:
		check_file_permission(path)

	except frappe.PermissionError:
		raise Forbidden(_("You don't have permission to access this file"))

	return send_private_file(path.split("/private", 1)[1])

def send_private_file(path):
	path = os.path.join(frappe.local.conf.get('private_path', 'private'), path.strip("/"))

	if frappe.local.request.headers.get('X-Use-X-Accel-Redirect'):
		path = '/protected/' + path
		response = Response()
		response.headers[b'X-Accel-Redirect'] = path

	else:
		filename = os.path.basename(path)
		filepath = frappe.utils.get_site_path(path)
		try:
			f = open(filepath, 'rb')
		except IOError:
			raise NotFound

		response = Response(wrap_file(frappe.local.request.environ, f), direct_passthrough=True)

		# no need for content disposition, let browser handle it
		# response.headers.add(b'Content-Disposition', 'attachment', filename=filename.encode("utf-8"))

		response.headers[b'Content-Type'] = mimetypes.guess_type(filename)[0] or b'application/octet-stream'

	return response

def handle_session_stopped():
	response = Response("""

											Updating.
											We will be back in a few moments...

					""")
	response.status_code = 503
	response.content_type = 'text/html'
	return response
<|endoftext|>


<commit_before>import asyncio

from discord.ext import commands
import discord

from db.dbase import DBase
from db.query_wrappers import get_event_role
from cogs.utils.messages import MessageManager
from cogs.utils.format import format_role_name

class Settings:

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

    @commands.group()
    @commands.guild_only()
    async def settings(self, ctx):
        """Manage the bot's server specific settings (Manage Server only)"""
        if ctx.invoked_subcommand is None:
            cmd = self.bot.get_command('help')
            await ctx.invoke(cmd, 'settings')

    @settings.command()
    @commands.guild_only()
    @commands.has_permissions(manage_guild=True)
    async def setprefix(self, ctx, new_prefix):
        """
        Change the server's command prefix (Manage Server only)
        """
        manager = MessageManager(self.bot, ctx.author, ctx.channel, [ctx.message])

        if len(new_prefix) > 5:
            await manager.say("Prefix must be less than 6 characters.")
            return await manager.clear()

        with DBase() as db:
            db.set_prefix(ctx.guild.id, new_prefix)
        await manager.say("Command prefix has been changed to " + new_prefix)
        return await manager.clear()

    @setprefix.error
    async def setprefix_error(self, ctx, error):
        if isinstance(error, commands.MissingRequiredArgument):
            manager = MessageManager(self.bot, ctx.author, ctx.channel, [ctx.message])
            await manager.say("Oops! You didn't provide a new prefix.")
            await manager.clear()

    @settings.command()
    @commands.guild_only()
    @commands.has_permissions(manage_guild=True)
    async def seteventrole(self, ctx, *, event_role):
        """Set the lowest role that is able to create events (Manage Server only)

        By default, creating events requires the user to have Administrator permissions.
        But if an event role is set, then any user that is of the event role or higher may
        create events.

        **Note:** Mentioning the role directly with this command will not work. You must provide
        only the name of the role without mentioning it.
        """
        manager = MessageManager(self.bot, ctx.author, ctx.channel, [ctx.message])

        guild_event_role = None
        for role in ctx.guild.roles:
            if role.name in (event_role, "@{}".format(event_role)):
                guild_event_role = role

        if not guild_event_role:
            await manager.say("I couldn't find a role called **{}** on this server.\n".format(event_role)
                            + "Note that you must provide only the name of the role. "
                            + "Mentioning it with the @ sign won't work.")
            return await manager.clear()

        with DBase() as db:
            db.set_event_role_id(ctx.guild.id, guild_event_role.id)

        await manager.say("The event role has been set to: **{}**".format(format_role_name(guild_event_role)))
        return await manager.clear()

    @seteventrole.error
    async def seteventrole_error(self, ctx, error):
        if isinstance(error, commands.MissingRequiredArgument):
            manager = MessageManager(self.bot, ctx.author, ctx.channel, [ctx.message])
            event_role = get_event_role(ctx.guild)

            if not event_role:
                role_display = 'None (anyone can make events)'
            else:
                role_display = format_role_name(event_role)

            await manager.say("The current event role is: **{}**\n\n".format(role_display)
                            + "To change the event role, use '{}settings seteventrole <role_name>'".format(ctx.prefix))
            await manager.clear()

    @settings.command()
    @commands.guild_only()
    @commands.has_permissions(manage_guild=True)
    async def togglecleanup(self, ctx):
        """
        Toggle command message cleanup on/off (Manage Server only)

        When enabled, command message spam will be deleted a few seconds
        after a command has been invoked. This feature is designed to
        keep bot related spam to a minimum. Only non important messages will
        be deleted if this is enabled; messages like the help message or the
        roster, for example, will not be removed.
        """
        manager = MessageManager(self.bot, ctx.author, ctx.channel, [ctx.message])

        with DBase() as db:
            db.toggle_cleanup(ctx.guild.id)
            rows = db.get_cleanup(ctx.guild.id)

        if len(rows) and len(rows[0]):
            cleanup = rows[0][0]
        else:
            raise ValueError("Could not retrieve 'cleanup' from database")

        status = 'enabled' if cleanup else 'disabled'
        await manager.say("Command message cleanup is now *{}*".format(status))
        return await manager.clear()
<commit_msg>update seteventrole help messages<commit_after>import asyncio

from discord.ext import commands
import discord

from db.dbase import DBase
from db.query_wrappers import get_event_role
from cogs.utils.messages import MessageManager
from cogs.utils.format import format_role_name

class Settings:

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

    @commands.group()
    @commands.guild_only()
    async def settings(self, ctx):
        """Manage the bot's server specific settings (Manage Server only)"""
        if ctx.invoked_subcommand is None:
            cmd = self.bot.get_command('help')
            await ctx.invoke(cmd, 'settings')

    @settings.command()
    @commands.guild_only()
    @commands.has_permissions(manage_guild=True)
    async def setprefix(self, ctx, new_prefix):
        """
        Change the server's command prefix (Manage Server only)
        """
        manager = MessageManager(self.bot, ctx.author, ctx.channel, [ctx.message])

        if len(new_prefix) > 5:
            await manager.say("Prefix must be less than 6 characters.")
            return await manager.clear()

        with DBase() as db:
            db.set_prefix(ctx.guild.id, new_prefix)
        await manager.say("Command prefix has been changed to " + new_prefix)
        return await manager.clear()

    @setprefix.error
    async def setprefix_error(self, ctx, error):
        if isinstance(error, commands.MissingRequiredArgument):
            manager = MessageManager(self.bot, ctx.author, ctx.channel, [ctx.message])
            await manager.say("Oops! You didn't provide a new prefix.")
            await manager.clear()

    @settings.command()
    @commands.guild_only()
    @commands.has_permissions(manage_guild=True)
    async def seteventrole(self, ctx, *, event_role):
        """Set the lowest role that is able to create events (Manage Server only)

        By default, creating events requires the user to have Administrator permissions.
        But if an event role is set, then any user that is of the event role or higher may
        create events.

        **Note:** Mentioning the role directly with this command will not work. You must provide
        only the name of the role without mentioning it. The role name is also case sensitive!
        """
        manager = MessageManager(self.bot, ctx.author, ctx.channel, [ctx.message])

        guild_event_role = None
        for role in ctx.guild.roles:
            if role.name in (event_role, "@{}".format(event_role)):
                guild_event_role = role

        if not guild_event_role:
            await manager.say("I couldn't find a role called **{}** on this server.\n".format(event_role)
                            + "Note that you must provide only the name of the role. "
                            + "Mentioning it with the @ sign won't work. The role name is also "
                            + "case sensitive!")
            return await manager.clear()

        with DBase() as db:
            db.set_event_role_id(ctx.guild.id, guild_event_role.id)

        await manager.say("The event role has been set to: **{}**".format(format_role_name(guild_event_role)))
        return await manager.clear()

    @seteventrole.error
    async def seteventrole_error(self, ctx, error):
        if isinstance(error, commands.MissingRequiredArgument):
            manager = MessageManager(self.bot, ctx.author, ctx.channel, [ctx.message])
            event_role = get_event_role(ctx.guild)

            if not event_role:
                role_display = 'None (anyone can make events)'
            else:
                role_display = format_role_name(event_role)

            await manager.say("The current event role is: **{}**\n\n".format(role_display)
                            + "To change the event role, use '{}settings seteventrole <role_name>'".format(ctx.prefix))
            await manager.clear()

    @settings.command()
    @commands.guild_only()
    @commands.has_permissions(manage_guild=True)
    async def togglecleanup(self, ctx):
        """
        Toggle command message cleanup on/off (Manage Server only)

        When enabled, command message spam will be deleted a few seconds
        after a command has been invoked. This feature is designed to
        keep bot related spam to a minimum. Only non important messages will
        be deleted if this is enabled; messages like the help message or the
        roster, for example, will not be removed.
        """
        manager = MessageManager(self.bot, ctx.author, ctx.channel, [ctx.message])

        with DBase() as db:
            db.toggle_cleanup(ctx.guild.id)
            rows = db.get_cleanup(ctx.guild.id)

        if len(rows) and len(rows[0]):
            cleanup = rows[0][0]
        else:
            raise ValueError("Could not retrieve 'cleanup' from database")

        status = 'enabled' if cleanup else 'disabled'
        await manager.say("Command message cleanup is now *{}*".format(status))
        return await manager.clear()
<|endoftext|>


<commit_before># Run this code to load only a small subset of the PLT files into the database.
#  This code should not be used for further research, but just to demonstrate
#  the underlying code is fully functional.

import logging
logging.basicConfig(
  level=logging.DEBUG,
  filename='/tmp/geolife.log',
  filemode='w'
)
logger = logging.getLogger("geolife")
stdout = logging.StreamHandler()
stdout.setLevel(logging.INFO)
logger.addHandler(stdout)

import geolife
import time
from datetime import timedelta
import tempfile
import pltfile
import random
import os
import shutil
random.seed(0)

def make_subset_copy(src, dst):
    pltfiles = pltfile.get_plt_files(src)
    small_subset_of_pltfiles = random.sample(pltfiles, 50)
    for f in small_subset_of_pltfiles:
      logger.debug(f)
      # Isolate the subdirectory that will need to be created in the temporary
      #  destination to preserve user information.
      directory = os.path.dirname(f)
      destination_subpath = directory.split(src+"/")[1]
      logger.debug("{0} will be created in {1}".format(
        destination_subpath, sample_dir
      ))

      # Create subdirectories if not present, and copy file.
      destination_path = os.path.join(dst, destination_subpath)
      logger.debug("Create path {0} if non-existent".format(destination_path))
      try:
        os.makedirs(destination_path)
      except:
        pass
      shutil.copy(f, destination_path)

if __name__ == "__main__":
  start = time.time()
  try:
    # To lighten the load of demonstrating the underlying code works,
    #  the following code will copy only a small subset of the GeoLife
    #  dataset for loading into the database.

    # Copy a subset of the actual GeoLife dataset into a temporary directory.
    import sys
    geolife_source = sys.argv[-1]
    geolife_root_directory = geolife.find_geolife_root(geolife_source)
    logger.info("PLT files will come from {0}".format(geolife_root_directory))

    sample_dir = tempfile.mkdtemp()
    logger.info("Selected PLT files will be copied to {0}".format(sample_dir))

    make_subset_copy(src=geolife_root_directory, dst=sample_dir)

  except:
    logger.exception("Stuff didn't do")

  duration = time.time() - start
  duration_delta = timedelta(seconds=duration)
  print("Total execution time: {0}".format(duration_delta))
<commit_msg>corrected import error due to moving things<commit_after># Run this code to load only a small subset of the PLT files into the database.
#  This code should not be used for further research, but just to demonstrate
#  the underlying code is fully functional.

import logging
logging.basicConfig(
  level=logging.DEBUG,
  filename='/tmp/geolife.log',
  filemode='w'
)
logger = logging.getLogger("geolife")
stdout = logging.StreamHandler()
stdout.setLevel(logging.INFO)
logger.addHandler(stdout)

import geolife
import time
from datetime import timedelta
import tempfile
from raw import pltfile
import random
import os
import shutil
random.seed(0)

def make_subset_copy(src, dst):
    pltfiles = pltfile.get_plt_files(src)
    small_subset_of_pltfiles = random.sample(pltfiles, 50)
    for f in small_subset_of_pltfiles:
      logger.debug(f)
      # Isolate the subdirectory that will need to be created in the temporary
      #  destination to preserve user information.
      directory = os.path.dirname(f)
      destination_subpath = directory.split(src+"/")[1]
      logger.debug("{0} will be created in {1}".format(
        destination_subpath, sample_dir
      ))

      # Create subdirectories if not present, and copy file.
      destination_path = os.path.join(dst, destination_subpath)
      logger.debug("Create path {0} if non-existent".format(destination_path))
      try:
        os.makedirs(destination_path)
      except:
        pass
      shutil.copy(f, destination_path)

if __name__ == "__main__":
  start = time.time()
  try:
    # To lighten the load of demonstrating the underlying code works,
    #  the following code will copy only a small subset of the GeoLife
    #  dataset for loading into the database.

    # Copy a subset of the actual GeoLife dataset into a temporary directory.
    import sys
    geolife_source = sys.argv[-1]
    geolife_root_directory = geolife.find_geolife_root(geolife_source)
    logger.info("PLT files will come from {0}".format(geolife_root_directory))

    sample_dir = tempfile.mkdtemp()
    logger.info("Selected PLT files will be copied to {0}".format(sample_dir))

    make_subset_copy(src=geolife_root_directory, dst=sample_dir)

  except:
    logger.exception("Stuff didn't do")

  duration = time.time() - start
  duration_delta = timedelta(seconds=duration)
  print("Total execution time: {0}".format(duration_delta))
<|endoftext|>


<commit_before># Module to test
# the galfit wrapper

import pytest
import os
import shutil
import numpy as np

from astropy.io import fits
from astropy.table import Table
from astropy.wcs import WCS

from pkg_resources import resource_filename

from frb.galaxies.frbgalaxy import FRBHost

try:
    from frb.galaxies import galfit as glf
except ImportError:
    pass

def test_platescale():
    cutout_file = resource_filename('frb','data/analysis/GALFIT/cutout_DES_i.fits')
    _, hdr = fits.getdata(cutout_file, header=True)
    wcs = WCS(hdr)
    platescale = glf.get_platescale(wcs)
    assert np.isclose(platescale, 0.263)

def test_run():
    cutout_file = resource_filename('frb','data/analysis/GALFIT/cutout_DES_i.fits')
    psf_file = resource_filename('frb', 'data/analysis/GALFIT/avg_DES_psf_i.fits')
    badpix = resource_filename('frb', 'data/analysis/GALFIT/badpix.fits')
    outdir = resource_filename('frb', 'data/analysis/GALFIT/galfit_out')
    return_val = glf.run(cutout_file, psf_file, outdir=outdir, badpix=badpix, r_e=4, n=2, pa=0, finesample=4)
    assert return_val==0
    assert os.path.isdir(outdir)
    outfile = os.path.join(outdir, 'out.fits')
    assert os.path.isfile(outfile)
    hdulist = fits.open(outfile)
    assert len(hdulist)==5
    result_tab = Table(hdulist[4].data)
    assert len(result_tab)==1
    assert np.isclose(result_tab['reff_ang'][0], 0.57071,rtol=1e-2, atol=1e-4)
    shutil.rmtree(outdir)

<commit_msg>There's no try. Only do.<commit_after># Module to test
# the galfit wrapper

import pytest
import os
import shutil
import numpy as np

from astropy.io import fits
from astropy.table import Table
from astropy.wcs import WCS

from pkg_resources import resource_filename

from frb.galaxies.frbgalaxy import FRBHost

from frb.galaxies import galfit as glf

def test_platescale():
    cutout_file = resource_filename('frb','data/analysis/GALFIT/cutout_DES_i.fits')
    _, hdr = fits.getdata(cutout_file, header=True)
    wcs = WCS(hdr)
    platescale = glf.get_platescale(wcs)
    assert np.isclose(platescale, 0.263)

def test_run():
    cutout_file = resource_filename('frb','data/analysis/GALFIT/cutout_DES_i.fits')
    psf_file = resource_filename('frb', 'data/analysis/GALFIT/avg_DES_psf_i.fits')
    badpix = resource_filename('frb', 'data/analysis/GALFIT/badpix.fits')
    outdir = resource_filename('frb', 'data/analysis/GALFIT/galfit_out')
    return_val = glf.run(cutout_file, psf_file, outdir=outdir, badpix=badpix, r_e=4, n=2, pa=0, finesample=4)
    assert return_val==0
    assert os.path.isdir(outdir)
    outfile = os.path.join(outdir, 'out.fits')
    assert os.path.isfile(outfile)
    hdulist = fits.open(outfile)
    assert len(hdulist)==5
    result_tab = Table(hdulist[4].data)
    assert len(result_tab)==1
    assert np.isclose(result_tab['reff_ang'][0], 0.57071,rtol=1e-2, atol=1e-4)
    shutil.rmtree(outdir)

<|endoftext|>


<commit_before>__all__= ["fc_install"]
__version__ = "0.1"

import os
import subprocess
import tempfile

from distutils.command.install import install as dist_install

class fc_install(dist_install):
    def initialize_options(self):
        dist_install.initialize_options(self)
        path = self.get_freecad_path()
        self.install_base = path
        self.install_lib = path
        self.install_headers = path
        self.install_scripts = path
        self.install_data = path

    def get_freecad_path(self):
        if os.getuid() == 0:
            command = "FreeCAD.getHomePath()"
        else:
            command = "FreeCAD.getUserAppDataDir()"

        with open( tempfile.gettempdir() + "/get_freecad_app_data.py", "w") as fp:
            fp.write("print("+ command +")\nexit()")
            fp.close()
        try:
            a = subprocess.Popen("freecad -c "+ fp.name, shell=True, stdout=subprocess.PIPE, stderr=None)
            installation_path = a.stdout.readlines()[-1][:-2]
            return installation_path + "/Mod"
        except:
            print("INSTALLATION ERROR: this package needs freecad to be installed")
            sys.exit()
<commit_msg>setup-tools<commit_after>__all__= ["fc_install"]
__version__ = "0.1.1"

import os
import subprocess
import tempfile

from setuptools.command.install import install as dist_install

class fc_install(dist_install):
    def initialize_options(self):
        dist_install.initialize_options(self)
        path = self.get_freecad_path()
        self.install_base = path
        self.install_lib = path
        self.install_headers = path
        self.install_scripts = path
        self.install_data = path

    def get_freecad_path(self):
        if os.getuid() == 0:
            command = "FreeCAD.getHomePath()"
        else:
            command = "FreeCAD.getUserAppDataDir()"

        with open( tempfile.gettempdir() + "/get_freecad_app_data.py", "w") as fp:
            fp.write("print("+ command +")\nexit()")
            fp.close()
        try:
            a = subprocess.Popen("freecad -c "+ fp.name, shell=True, stdout=subprocess.PIPE, stderr=None)
            installation_path = a.stdout.readlines()[-1][:-2]
            return installation_path + "/Mod"
        except:
            print("INSTALLATION ERROR: this package needs freecad to be installed")
            sys.exit()
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

# GSettings

from gi.repository import Gio
import logging

__author__ = "nil.gradisnik@gmail.com"

SCHEMA_ID = 'org.nil.indicator.coinprice'

DEFAULTS = {
    'refresh': 30,
    'exchange': 'kraken',
    'asset-pair': 'XXBTZUSD', # hyphen because of how GSettings handles names
}

class Settings(object):
    def __init__(self, manual_settings=None):
        if manual_settings == 'DEFAULTS':
            self.manual_settings = [DEFAULTS['exchange'], DEFAULTS['assetpair'], DEFAULTS['refresh']]
            return

        self.settings = None
        self.manual_settings = None

        if manual_settings:
            self.manual_settings = manual_settings.split(':')
        else:
            source = Gio.SettingsSchemaSource.get_default()
            if source.lookup(SCHEMA_ID, True):
                self.settings = Gio.Settings(SCHEMA_ID)
            else:
                self.settings = None
                logging.info("GSettings: schema [" + SCHEMA_ID + "] not installed. Using defaults.")

    def get_refresh(self):
        if self.manual_settings:
            return int(self.manual_settings[2])
        elif self.settings:
            return self.settings.get_int('refresh')
        else:
            return DEFAULTS['refresh']

    def set_refresh(self, val):
        if not self.manual_settings:
            self.settings.set_int('refresh', val)
            return True

    def get_exchange(self):
        if self.manual_settings:
            return self.manual_settings[0].lower()
        elif self.settings:
            return self.settings.get_string('exchange')
        else:
            return DEFAULTS['exchange']

    def set_exchange(self, val):
        if not self.manual_settings:
            self.settings.set_string('exchange', val)
            return True

    def get_asset_pair(self):
        if self.manual_settings:
            return self.manual_settings[1].upper()
        elif self.settings:
            return self.settings.get_string('asset-pair')
        else:
            return DEFAULTS['asset-pair']

    def set_asset_pair(self, val):
        if not self.manual_settings:
            self.settings.set_string('asset-pair', val.upper())
            return True<commit_msg>and settings bug<commit_after># -*- coding: utf-8 -*-

# GSettings

from gi.repository import Gio
import logging

__author__ = "nil.gradisnik@gmail.com"

SCHEMA_ID = 'org.nil.indicator.coinprice'

DEFAULTS = {
    'refresh': 30,
    'exchange': 'kraken',
    'asset-pair': 'XXBTZUSD', # hyphen because of how GSettings handles names
}

class Settings(object):
    def __init__(self, manual_settings=None):
        if manual_settings == 'DEFAULTS':
            self.manual_settings = [DEFAULTS['exchange'], DEFAULTS['asset-pair'], DEFAULTS['refresh']]
            return

        self.settings = None
        self.manual_settings = None

        if manual_settings:
            self.manual_settings = manual_settings.split(':')
        else:
            source = Gio.SettingsSchemaSource.get_default()
            if source.lookup(SCHEMA_ID, True):
                self.settings = Gio.Settings(SCHEMA_ID)
            else:
                self.settings = None
                logging.info("GSettings: schema [" + SCHEMA_ID + "] not installed. Using defaults.")

    def get_refresh(self):
        if self.manual_settings:
            return int(self.manual_settings[2])
        elif self.settings:
            return self.settings.get_int('refresh')
        else:
            return DEFAULTS['refresh']

    def set_refresh(self, val):
        if not self.manual_settings:
            self.settings.set_int('refresh', val)
            return True

    def get_exchange(self):
        if self.manual_settings:
            return self.manual_settings[0].lower()
        elif self.settings:
            return self.settings.get_string('exchange')
        else:
            return DEFAULTS['exchange']

    def set_exchange(self, val):
        if not self.manual_settings:
            self.settings.set_string('exchange', val)
            return True

    def get_asset_pair(self):
        if self.manual_settings:
            return self.manual_settings[1].upper()
        elif self.settings:
            return self.settings.get_string('asset-pair')
        else:
            return DEFAULTS['asset-pair']

    def set_asset_pair(self, val):
        if not self.manual_settings:
            self.settings.set_string('asset-pair', val.upper())
            return True<|endoftext|>


<commit_before># coding: utf8
from ontology_tools import check_date

def index():
    """
    Entry point to the ontology load/update tools;
    """
    import ontology_tools
    ontologies = db().select(db.ontology_source.ALL)
    result = [ontology for ontology in ontologies]
    return {"ontologies": result}

_CONF_OBJ_DICT = {}

def get_conf(request,domain):
    """
    Lifted from phylografter's externalproc.py (so presumibly originally
    from Mark Holder), this manages configuration for ontology parsing.
    This allows definition of domain specific parsing and filtering rules
    (once fully implemented)
    """
    global _CONF_OBJ_DICT
    app_name = request.application
    c = _CONF_OBJ_DICT.get(app_name)
    if c is None:
        from ConfigParser import SafeConfigParser
        c = SafeConfigParser({})
        c.read("applications/%s/private/config" % request.application)
        _CONF_OBJ_DICT[app_name] = c
    return c

UPDATE_FORMAT = "%a, %d %b %Y %H:%M:%S GMT"

def check_modified():
    """
    for each source in the ontology source table, pulls the uri,
    tries to determine a last modified date, then reloads the ontology
    into the terms table if the date in source is older than the date
    retrived from the uri.
    """
    from ontology_tools import check_date,update_ontology
    from datetime import datetime
    import time
    config = get_conf(request,'')  #domain not currently used
    ontologies = db().select(db.ontology_source.ALL)
    for ont in ontologies:
        source_update = check_date(ont.source_url)
        if source_update != '':
            source_update_struct = time.strptime(source_update.rstrip(),UPDATE_FORMAT)
        else:
            source_update_struct = None
        if source_update_struct:
            source_update_secs = time.mktime(source_update_struct)
        else:
            source_update_secs = None
        old_date = ont.last_update
        if old_date:
            old_date_struct = old_date.utctimetuple()
        else:
            old_date_struct = None
        if old_date_struct:
            old_date_secs = time.mktime(old_date_struct)
        else:
            old_date_secs = None
        if source_update_secs or True:
            if (old_date_secs is None) or (source_update_secs > old_date_secs) or True:
                print "Need to update %s, date is %s" % (ont.name,str(old_date))
                type_name = db.ontology_processing[ont.processing].type_name
                terms = update_ontology(ont,type_name,config,request.application)
                merge_terms(terms,ont)
                time_now = datetime.now()
                db(db.ontology_source.id == ont.id).update(last_update=time_now)
                ont.last_update
    ont.update()
    redirect('index')

def merge_terms(terms,ont):
    """
    adds any term in terms not in the term table.  String compare of
    id/uri is used for equality.  Probably not sufficient for merging
    taxonomy.
    """
    updateCount = 0
    for term in terms:
        t = None
        new_id = -1
        if isinstance(term,dict) and 'about' in term:
            t = term
            term_irl = t['about']
            old_term = db(db.term.source_id == term_irl).select()
            if len(old_term) == 0:
                new_id = db.term.insert(source_id=t['about'])
                row = db.term[new_id]
                updateCount = updateCount + 1;
                if 'label' in t:
                    db(db.term.id==new_id).update(label=t['label'])
                if 'class_comment' in t:
                    db(db.term.id==new_id).update(comment=t['class_comment'])
                db(db.term.id==new_id).update(domain=ont.domain)
    print "loaded %d terms from %s" % (updateCount,ont.name)
<commit_msg>re-enable date check for ontology cache update<commit_after># coding: utf8
from ontology_tools import check_date

def index():
    """
    Entry point to the ontology load/update tools;
    """
    import ontology_tools
    ontologies = db().select(db.ontology_source.ALL)
    result = [ontology for ontology in ontologies]
    return {"ontologies": result}

_CONF_OBJ_DICT = {}

def get_conf(request,domain):
    """
    Lifted from phylografter's externalproc.py (so presumibly originally
    from Mark Holder), this manages configuration for ontology parsing.
    This allows definition of domain specific parsing and filtering rules
    (once fully implemented)
    """
    global _CONF_OBJ_DICT
    app_name = request.application
    c = _CONF_OBJ_DICT.get(app_name)
    if c is None:
        from ConfigParser import SafeConfigParser
        c = SafeConfigParser({})
        c.read("applications/%s/private/config" % request.application)
        _CONF_OBJ_DICT[app_name] = c
    return c

UPDATE_FORMAT = "%a, %d %b %Y %H:%M:%S GMT"

def check_modified():
    """
    for each source in the ontology source table, pulls the uri,
    tries to determine a last modified date, then reloads the ontology
    into the terms table if the date in source is older than the date
    retrived from the uri.
    """
    from ontology_tools import check_date,update_ontology
    from datetime import datetime
    import time
    config = get_conf(request,'')  #domain not currently used
    ontologies = db().select(db.ontology_source.ALL)
    for ont in ontologies:
        source_update = check_date(ont.source_url)
        if source_update != '':
            source_update_struct = time.strptime(source_update.rstrip(),UPDATE_FORMAT)
        else:
            source_update_struct = None
        if source_update_struct:
            source_update_secs = time.mktime(source_update_struct)
        else:
            source_update_secs = None
        old_date = ont.last_update
        if old_date:
            old_date_struct = old_date.utctimetuple()
        else:
            old_date_struct = None
        if old_date_struct:
            old_date_secs = time.mktime(old_date_struct)
        else:
            old_date_secs = None
        if source_update_secs or True:
            if (old_date_secs is None) or (source_update_secs > old_date_secs):
                print "Need to update %s, date is %s" % (ont.name,str(old_date))
                type_name = db.ontology_processing[ont.processing].type_name
                terms = update_ontology(ont,type_name,config,request.application)
                merge_terms(terms,ont)
                time_now = datetime.now()
                db(db.ontology_source.id == ont.id).update(last_update=time_now)
                ont.last_update
    ont.update()
    redirect('index')

def merge_terms(terms,ont):
    """
    adds any term in terms not in the term table.  String compare of
    id/uri is used for equality.  Probably not sufficient for merging
    taxonomy.
    """
    updateCount = 0
    for term in terms:
        t = None
        new_id = -1
        if isinstance(term,dict) and 'about' in term:
            t = term
            term_irl = t['about']
            old_term = db(db.term.source_id == term_irl).select()
            if len(old_term) == 0:
                new_id = db.term.insert(source_id=t['about'])
                row = db.term[new_id]
                updateCount = updateCount + 1;
                if 'label' in t:
                    db(db.term.id==new_id).update(label=t['label'])
                if 'class_comment' in t:
                    db(db.term.id==new_id).update(comment=t['class_comment'])
                db(db.term.id==new_id).update(domain=ont.domain)
    print "loaded %d terms from %s" % (updateCount,ont.name)
<|endoftext|>


<commit_before>from vtdb import dbexceptions

# A simple class to trap and re-export only variables referenced from
# the sql statement since bind dictionaries can be *very* noisy.  This
# is a by-product of converting the DB-API %(name)s syntax to our
# :name syntax.
class BindVarsProxy(object):
  def __init__(self, bind_vars):
    self.bind_vars = bind_vars
    self.accessed_keys = set()

  def __getitem__(self, name):
    var = self.bind_vars[name]
    self.bind_vars[name]
    self.accessed_keys.add(name)
    if isinstance(var, list) or isinstance(var, tuple) or isinstance(var, set):
      return '::%s' % name

    return ':%s' % name

  def export_bind_vars(self):
    return dict([(k, self.bind_vars[k]) for k in self.accessed_keys])

# convert bind style from %(name)s to :name and export only the
# variables bound.
def prepare_query_bind_vars(query, bind_vars):
  bind_vars_proxy = BindVarsProxy(bind_vars)
  try:
    query = query % bind_vars_proxy
  except KeyError as e:
    raise dbexceptions.InterfaceError(e[0], query, bind_vars)

  return query, bind_vars_proxy.export_bind_vars()
<commit_msg>small cleanup for matching isinstance.<commit_after>from vtdb import dbexceptions

# A simple class to trap and re-export only variables referenced from
# the sql statement since bind dictionaries can be *very* noisy.  This
# is a by-product of converting the DB-API %(name)s syntax to our
# :name syntax.
class BindVarsProxy(object):
  def __init__(self, bind_vars):
    self.bind_vars = bind_vars
    self.accessed_keys = set()

  def __getitem__(self, name):
    var = self.bind_vars[name]
    self.bind_vars[name]
    self.accessed_keys.add(name)
    if isinstance(var, (list, set, tuple)):
      return '::%s' % name

    return ':%s' % name

  def export_bind_vars(self):
    return dict([(k, self.bind_vars[k]) for k in self.accessed_keys])

# convert bind style from %(name)s to :name and export only the
# variables bound.
def prepare_query_bind_vars(query, bind_vars):
  bind_vars_proxy = BindVarsProxy(bind_vars)
  try:
    query = query % bind_vars_proxy
  except KeyError as e:
    raise dbexceptions.InterfaceError(e[0], query, bind_vars)

  return query, bind_vars_proxy.export_bind_vars()
<|endoftext|>


<commit_before>from flask import abort, request, render_template
from flask.ext.restful import Resource, reqparse
import requests

from coldframe import app, api, influx_db

class ReportTempsV0(Resource):
    def post(self):
        """
        v0 of the report_temps resource for the coldframe api.
        Expects the following form data to be submitted:
            token: API authorization token (string)
            series1: value1
            series2: value2
            ...
            seriesN: valueN
        """

        parser = reqparse.RequestParser()
        parser.add_argument('token', required=True, choices=app.config['ACCESS_TOKENS'])
        parser.add_argument('top', type=float)
        parser.add_argument('bottom', type=float)
        parser.add_argument('ambient', type=float)
        args = parser.parse_args()
        del args['token']

        series = []
        for key, value in args.iteritems():
            series.append({
                'name'    : 'coldframe.%s.temp_c' % key,
                'columns' : ['value'],
                'points'  : [[value]]
                })

        wu_data = get_wunderground_data()
        observation_epoch = float(wu_data.pop('observation_epoch'))
        for key, value in wu_data.iteritems():
            series.append({
                'name'    : 'pws.%s.%s' % (app.config['WEATHER_STATION'], key),
                'columns' : ['time', 'value'],
                'points'  : [[observation_epoch, value]]
                })
        dbconn = influx_db.connection
        try:
            result = dbconn.write_points(series)
        except Exception as e:
            #TODO: Log exception (and data?) to file?
            raise e

        return result

api.add_resource(ReportTempsV0, "/api/v0/report_temps")

def get_wunderground_data():
    endpoint = "http://api.wunderground.com/api"
    query = "conditions/q/pws:%s.json" % app.config['WEATHER_STATION']
    key = app.config['WUNDERGROUND_KEY']
    resp = requests.get('/'.join([endpoint, key, query]))
    data = resp.json()['current_observation']
    interesting_data = ['observation_epoch', 'weather', 'temp_c',
            'dewpoint_c', 'precip_today_in', 'pressure_mb',
            'relative_humidity', 'solarradiation', 'wind_degrees', 'wind_kph',
            'wind_gust_kph', 'wind_string', 'windchill_c']
    return {k: data[k] for k in interesting_data}
<commit_msg>api: remove solarradiation from interesting data<commit_after>from flask import abort, request, render_template
from flask.ext.restful import Resource, reqparse
import requests

from coldframe import app, api, influx_db

class ReportTempsV0(Resource):
    def post(self):
        """
        v0 of the report_temps resource for the coldframe api.
        Expects the following form data to be submitted:
            token: API authorization token (string)
            series1: value1
            series2: value2
            ...
            seriesN: valueN
        """

        parser = reqparse.RequestParser()
        parser.add_argument('token', required=True, choices=app.config['ACCESS_TOKENS'])
        parser.add_argument('top', type=float)
        parser.add_argument('bottom', type=float)
        parser.add_argument('ambient', type=float)
        args = parser.parse_args()
        del args['token']

        series = []
        for key, value in args.iteritems():
            series.append({
                'name'    : 'coldframe.%s.temp_c' % key,
                'columns' : ['value'],
                'points'  : [[value]]
                })

        wu_data = get_wunderground_data()
        observation_epoch = float(wu_data.pop('observation_epoch'))
        for key, value in wu_data.iteritems():
            series.append({
                'name'    : 'pws.%s.%s' % (app.config['WEATHER_STATION'], key),
                'columns' : ['time', 'value'],
                'points'  : [[observation_epoch, value]]
                })
        dbconn = influx_db.connection
        try:
            result = dbconn.write_points(series)
        except Exception as e:
            #TODO: Log exception (and data?) to file?
            raise e

        return result

api.add_resource(ReportTempsV0, "/api/v0/report_temps")

def get_wunderground_data():
    endpoint = "http://api.wunderground.com/api"
    query = "conditions/q/pws:%s.json" % app.config['WEATHER_STATION']
    key = app.config['WUNDERGROUND_KEY']
    resp = requests.get('/'.join([endpoint, key, query]))
    data = resp.json()['current_observation']
    interesting_data = ['observation_epoch', 'weather', 'temp_c',
            'dewpoint_c', 'precip_today_in', 'pressure_mb',
            'relative_humidity', 'wind_degrees', 'wind_kph',
            'wind_gust_kph', 'wind_string', 'windchill_c']
    return {k: data[k] for k in interesting_data}
<|endoftext|>