<commit_before>#
# Base class for all PLCAPI functions
#
# <NAME> <<EMAIL>>
# Copyright (C) 2006 The Trustees of Princeton University
#
# $Id: Method.py,v 1.1 2006/09/06 15:36:07 mlhuang Exp $
#

import xmlrpclib
from types import *
import textwrap
import os

from PLC.Faults import *
from PLC.Parameter import Parameter, Mixed
from PLC.Auth import Auth

class Method:
    """
    Base class for all PLCAPI functions. At a minimum, all PLCAPI
    functions must define:

    roles = [list of roles]
    accepts = [Parameter(arg1_type, arg1_doc), Parameter(arg2_type, arg2_doc), ...]
    returns = Parameter(return_type, return_doc)
    call(arg1, arg2, ...): method body

    Argument types may be Python types (e.g., int, bool, etc.), typed
    values (e.g., 1, True, etc.), a Parameter, or lists or
    dictionaries of possibly mixed types, values, and/or Parameters
    (e.g., [int, bool, ...]  or {'arg1': int, 'arg2': bool}).

    Once function decorators in Python 2.4 are fully supported,
    consider wrapping calls with accepts() and returns() functions
    instead of performing type checking manually.
    """

    # Defaults. Could implement authentication and type checking with
    # decorators, but they are not supported in Python 2.3 and it
    # would be hard to generate documentation without writing a code
    # parser.

    roles = []
    accepts = []
    returns = bool
    status = "current"

    def call(self):
        """
        Method body for all PLCAPI functions. Must override.
        """

        return True

    def __init__(self, api):
        self.name = self.__class__.__name__
        self.api = api

        # Auth may set this to a Person instance (if an anonymous
        # method, will remain None).
        self.caller = None

        # API may set this to a (addr, port) tuple if known
        self.source = None

    def __call__(self, *args):
        """
        Main entry point for all PLCAPI functions. Type checks
        arguments, authenticates, and executes call().
        """

        try:
            (min_args, max_args, defaults) = self.args()

            # Check that the right number of arguments were passed in
            if len(args) < len(min_args) or len(args) > len(max_args):
                raise PLCInvalidArgumentCount(len(args), len(min_args), len(max_args))

            for name, value, expected in zip(max_args, args, self.accepts):
                self.type_check(name, value, expected)

            # The first argument to all methods that require
            # authentication, should be an Auth structure. The rest of the
            # arguments to the call may also be used in the authentication
            # check. For example, calls made by the Boot Manager are
            # verified by comparing a hash of the message parameters to
            # the value in the authentication structure.        

            if len(self.accepts):
                auth = None
                if isinstance(self.accepts[0], Auth):
                    auth = self.accepts[0]
                elif isinstance(self.accepts[0], Mixed):
                    for auth in self.accepts[0]:
                        if isinstance(auth, Auth):
                            break
                if isinstance(auth, Auth):
                    auth.check(self, *args)

            return self.call(*args)

        except PLCFault, fault:
            # Prepend method name to expected faults
            fault.faultString = self.name + ": " + fault.faultString
            raise fault

    def help(self, indent = "  "):
        """
        Text documentation for the method.
        """
<commit_msg>- added log()<commit_after>#
# Base class for all PLCAPI functions
#
# <NAME> <<EMAIL>>
# Copyright (C) 2006 The Trustees of Princeton University
#
# $Id: Method.py,v 1.2 2006/09/08 19:44:31 mlhuang Exp $
#

import xmlrpclib
from types import *
import textwrap
import os
import time

from PLC.Faults import *
from PLC.Parameter import Parameter, Mixed
from PLC.Auth import Auth
from PLC.Debug import profile, log

class Method:
    """
    Base class for all PLCAPI functions. At a minimum, all PLCAPI
    functions must define:

    roles = [list of roles]
    accepts = [Parameter(arg1_type, arg1_doc), Parameter(arg2_type, arg2_doc), ...]
    returns = Parameter(return_type, return_doc)
    call(arg1, arg2, ...): method body

    Argument types may be Python types (e.g., int, bool, etc.), typed
    values (e.g., 1, True, etc.), a Parameter, or lists or
    dictionaries of possibly mixed types, values, and/or Parameters
    (e.g., [int, bool, ...]  or {'arg1': int, 'arg2': bool}).

    Once function decorators in Python 2.4 are fully supported,
    consider wrapping calls with accepts() and returns() functions
    instead of performing type checking manually.
    """

    # Defaults. Could implement authentication and type checking with
    # decorators, but they are not supported in Python 2.3 and it
    # would be hard to generate documentation without writing a code
    # parser.

    roles = []
    accepts = []
    returns = bool
    status = "current"

    def call(self, *args):
        """
        Method body for all PLCAPI functions. Must override.
        """

        return True

    def __init__(self, api):
        self.name = self.__class__.__name__
        self.api = api

        # Auth may set this to a Person instance (if an anonymous
        # method, will remain None).
        self.caller = None

        # API may set this to a (addr, port) tuple if known
        self.source = None
	self.__call__ = self.log(self.__call__) 

    	
    def __call__(self, *args):
        """
        Main entry point for all PLCAPI functions. Type checks
        arguments, authenticates, and executes call().
        """

        try:
            (min_args, max_args, defaults) = self.args()
	        		
	    # Check that the right number of arguments were passed in
            if len(args) < len(min_args) or len(args) > len(max_args):
                raise PLCInvalidArgumentCount(len(args), len(min_args), len(max_args))

            for name, value, expected in zip(max_args, args, self.accepts):
                self.type_check(name, value, expected)
	
            # The first argument to all methods that require
            # authentication, should be an Auth structure. The rest of the
            # arguments to the call may also be used in the authentication
            # check. For example, calls made by the Boot Manager are
            # verified by comparing a hash of the message parameters to
            # the value in the authentication structure.        

            if len(self.accepts):
                auth = None
                if isinstance(self.accepts[0], Auth):
                    auth = self.accepts[0]
                elif isinstance(self.accepts[0], Mixed):
                    for auth in self.accepts[0]:
                        if isinstance(auth, Auth):
                            break
                if isinstance(auth, Auth):
                    auth.check(self, *args)

	    	
	    return self.call(*args)

        except PLCFault, fault:
            # Prepend method name to expected faults
            fault.faultString = self.name + ": " + fault.faultString
            raise fault


    def log(self, callable):
        """
        Log the transaction 
        """
	def __log__(vars):
		"""
		Commit the transaction 
		"""

		# Do not log listMethods call
		if vars['call_name'] in ['listMethods']:
			return False
	 
		sql = "INSERT INTO events " \
                        " (person_id, event_type, object_type, fault_code, call, runtime)" \
                        " VALUES (%d, '%s', '%s', %d, '%s', %f)" %  \
                        (vars['person_id'], vars['event_type'], vars['object_type'], 
			vars['fault_code'], vars['call'], vars['runtime'])
                self.api.db.do(sql)
                self.api.db.commit()
			

        def wrapper(*args, **kwds):
		
		fault_code = 0
		# XX Get real person_id
		person_id = 1
		event_type = 'Unknown'
		object_type = 'Unknown'
		call_name = callable.im_class.__module__.split('.')[-1:][0]
		call_args = ", ".join([str(arg) for arg in list(args)[1:]]).replace('\'', '\\\'')
		call = "%s(%s)" % (call_name, call_args)
		
		if hasattr(self, 'event_type'):
			event_type = self.event_type
		
                if hasattr(self, 'object_type'):
			object_type = self.object_type
	        
		start = time.time()
			
	        try:
                	result =  callable(*args, **kwds)
			runtime =  time.time() - start
			__log__(locals())			
			return result
				                                       
                except PLCFault, fault:
                	fault_code = fault.faultCode
                	runtime =  time.time() - start
			__log__(locals())
			print fault
			
    	return wrapper
	

    def help(self, indent = "  "):
        """
        Text documentation for the method.
        """

{'fraction_non_alphanumeric': 0.09832775919732442, 'fraction_numerical': 0.008807134894091417, 'mean_word_length': 2.019522046449007, 'pattern_counts': {'":': 2, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2428549', 'n_tokens_mistral': 2629, 'n_tokens_neox': 2413, 'n_words': 879}