From 2262dad38e7699a98c3df2a8c0de3ccf3d6e6373 Mon Sep 17 00:00:00 2001 From: parmentelat Date: Tue, 11 Dec 2018 15:15:29 +0100 Subject: [PATCH] more ironing in the corner of that 'types' modules --- PLC/Accessors/Factory.py | 193 ++++++++++++++++++++------------------- PLC/Method.py | 34 +++---- PLC/Parameter.py | 11 +-- PLC/PostgreSQL.py | 70 +++++++------- PLC/Timestamp.py | 2 +- PLC/sendmail.py | 1 - 6 files changed, 157 insertions(+), 154 deletions(-) diff --git a/PLC/Accessors/Factory.py b/PLC/Accessors/Factory.py index ce39769..6073c7f 100644 --- a/PLC/Accessors/Factory.py +++ b/PLC/Accessors/Factory.py @@ -1,7 +1,7 @@ # # Thierry Parmentelat - INRIA # -from types import NoneType +# pylint: disable=c0103, c0111 from PLC.Faults import * @@ -25,28 +25,29 @@ from PLC.PersonTags import PersonTags, PersonTag from PLC.AuthorizeHelpers import AuthorizeHelpers # known classes : { class -> details } -taggable_classes = { Node : {'table_class' : Nodes, - 'joins_class' : NodeTags, 'join_class' : NodeTag, - 'secondary_key': 'hostname'}, - Interface : {'table_class' : Interfaces, - 'joins_class': InterfaceTags, 'join_class': InterfaceTag, - 'secondary_key' : 'ip'}, - Slice: {'table_class' : Slices, - 'joins_class': SliceTags, 'join_class': SliceTag, - 'secondary_key':'name'}, - Site: {'table_class' : Sites, - 'joins_class': SiteTags, 'join_class': SiteTag, - 'secondary_key':'login_base'}, - Person: {'table_class' : Persons, - 'joins_class': PersonTags, 'join_class': PersonTag, - 'secondary_key':'email'}, - } +taggable_classes = { + Node : {'table_class' : Nodes, + 'joins_class' : NodeTags, 'join_class' : NodeTag, + 'secondary_key': 'hostname'}, + Interface : {'table_class' : Interfaces, + 'joins_class': InterfaceTags, 'join_class': InterfaceTag, + 'secondary_key' : 'ip'}, + Slice: {'table_class' : Slices, + 'joins_class': SliceTags, 'join_class': SliceTag, + 'secondary_key':'name'}, + Site: {'table_class' : Sites, + 'joins_class': SiteTags, 'join_class': SiteTag, + 'secondary_key':'login_base'}, + Person: {'table_class' : Persons, + 'joins_class': PersonTags, 'join_class': PersonTag, + 'secondary_key':'email'}, +} # xxx probably defined someplace else admin_roles = ['admin'] -person_roles = [ 'admin', 'pi', 'tech', 'user' ] -all_roles = [ 'admin', 'pi', 'tech', 'user', 'node' ] -tech_roles = [ 'admin', 'pi', 'tech' ] +person_roles = ['admin', 'pi', 'tech', 'user'] +all_roles = ['admin', 'pi', 'tech', 'user', 'node'] +tech_roles = ['admin', 'pi', 'tech'] # # generates 2 method classes: @@ -62,7 +63,7 @@ tech_roles = [ 'admin', 'pi', 'tech' ] # # in addition a convenience method like e.g. LocateNodeArch is defined # in the Accessor class; its purpose is to retrieve the tag, or to create it if needed -# +# # Legacy NOTE: # prior to plcapi-5.0-19, this used to accept an additional argument # named min_role_id; this was redundant and confusing, it has been @@ -73,17 +74,17 @@ tech_roles = [ 'admin', 'pi', 'tech' ] # you then end up with e.g. GetPersonMyStuff # the entry point accepts a single class or a list of classes -def define_accessors (module, objclasses, *args, **kwds): - if not isinstance(objclasses,list): - objclasses=[objclasses] +def define_accessors(module, objclasses, *args, **kwds): + if not isinstance(objclasses, list): + objclasses = [objclasses] for objclass in objclasses: - define_accessors_ (module, objclass, *args, **kwds) + define_accessors_(module, objclass, *args, **kwds) # this is for one class -def define_accessors_ (module, objclass, methodsuffix, tagname, - category, description, - get_roles=all_roles, set_roles=admin_roles, - expose_in_api = False): +def define_accessors_(module, objclass, methodsuffix, tagname, + category, description, + get_roles=all_roles, set_roles=admin_roles, + expose_in_api=False): if objclass not in taggable_classes: try: @@ -93,43 +94,45 @@ def define_accessors_ (module, objclass, methodsuffix, tagname, # side-effect on, say, Node.tags, if required if expose_in_api: - getattr(objclass,'tags')[tagname]=Parameter(str,"accessor") + getattr(objclass, 'tags')[tagname] = Parameter(str, "accessor") - classname=objclass.__name__ + classname = objclass.__name__ get_name = "Get" + classname + methodsuffix set_name = "Set" + classname + methodsuffix locator_name = "Locate" + classname + methodsuffix # accessor method objects under PLC.Method.Method - get_class = type (get_name, (Method,), - {"__doc__":"Accessor 'get' method designed for %s objects using tag %s"%\ - (classname,tagname)}) - set_class = type (set_name, (Method,), - {"__doc__":"Accessor 'set' method designed for %s objects using tag %s"%\ - (classname,tagname)}) + get_class = type(get_name, (Method,), + {"__doc__": + "Accessor 'get' method designed for %s objects using tag %s"%\ + (classname, tagname)}) + set_class = type(set_name, (Method,), + {"__doc__": + "Accessor 'set' method designed for %s objects using tag %s"%\ + (classname, tagname)}) # accepts - get_accepts = [ Auth () ] - primary_key=objclass.primary_key + get_accepts = [Auth()] + primary_key = objclass.primary_key secondary_key = taggable_classes[objclass]['secondary_key'] - get_accepts += [ Mixed (objclass.fields[primary_key], objclass.fields[secondary_key]) ] + get_accepts += [Mixed(objclass.fields[primary_key], objclass.fields[secondary_key])] # for set, idem set of arguments + one additional arg, the new value - set_accepts = get_accepts + [ Parameter (str,"New tag value") ] + set_accepts = get_accepts + [Parameter(str, "New tag value")] # returns - get_returns = Mixed (Parameter (str), Parameter(NoneType)) - set_returns = Parameter(NoneType) + get_returns = Mixed(Parameter(str), Parameter(type(None))) + set_returns = Parameter(type(None)) # store in classes - setattr(get_class,'roles',get_roles) - setattr(get_class,'accepts',get_accepts) - setattr(get_class,'returns', get_returns) + setattr(get_class, 'roles', get_roles) + setattr(get_class, 'accepts', get_accepts) + setattr(get_class, 'returns', get_returns) # that was useful for legacy method only, but we now need type_checking # setattr(get_class,'skip_type_check',True) - setattr(set_class,'roles',set_roles) - setattr(set_class,'accepts',set_accepts) - setattr(set_class,'returns', set_returns) + setattr(set_class, 'roles', set_roles) + setattr(set_class, 'accepts', set_accepts) + setattr(set_class, 'returns', set_returns) # that was useful for legacy method only, but we now need type_checking # setattr(set_class,'skip_type_check',True) @@ -139,29 +142,30 @@ def define_accessors_ (module, objclass, methodsuffix, tagname, # locate the tag and create it if needed # this method is attached to the Accessor class - def tag_locator (self, enforce=False): - return self.locate_or_create_tag (tagname=tagname, - category=category, - description=description, - roles=set_roles, - enforce=enforce) + def tag_locator(self, enforce=False): + return self.locate_or_create_tag( + tagname=tagname, + category=category, + description=description, + roles=set_roles, + enforce=enforce) # attach it to the Accessor class - Accessor.register_tag_locator(locator_name,tag_locator) + Accessor.register_tag_locator(locator_name, tag_locator) # body of the get method - def get_call (self, auth, id_or_name): + def get_call(self, auth, id_or_name): # locate the tag, see above tag_locator = Accessor.retrieve_tag_locator(locator_name) tag_type = tag_locator(AccessorSingleton(self.api)) - tag_type_id=tag_type['tag_type_id'] + tag_type_id = tag_type['tag_type_id'] - filter = {'tag_type_id':tag_type_id} - if isinstance (id_or_name,int): - filter[primary_key]=id_or_name + filter = {'tag_type_id': tag_type_id} + if isinstance(id_or_name, int): + filter[primary_key] = id_or_name else: - filter[secondary_key]=id_or_name - joins = joins_class (self.api,filter,['value']) + filter[secondary_key] = id_or_name + joins = joins_class(self.api, filter, ['value']) if not joins: # xxx - we return None even if id_or_name is not valid return None @@ -169,22 +173,22 @@ def define_accessors_ (module, objclass, methodsuffix, tagname, return joins[0]['value'] # attach it - setattr (get_class,"call",get_call) + setattr(get_class, "call", get_call) # body of the set method - def set_call (self, auth, id_or_name, value): + def set_call(self, auth, id_or_name, value): # locate the object - if isinstance (id_or_name, int): - filter={primary_key:id_or_name} + if isinstance(id_or_name, int): + filter = {primary_key:id_or_name} else: - filter={secondary_key:id_or_name} + filter = {secondary_key:id_or_name} # we need the full monty b/c of the permission system # objs = table_class(self.api, filter,[primary_key,secondary_key]) objs = table_class(self.api, filter) if not objs: - raise PLCInvalidArgument("Cannot set tag on %s %r"%(objclass.__name__,id_or_name)) + raise PLCInvalidArgument("Cannot set tag on %s %r"%(objclass.__name__, id_or_name)) # the object being tagged - obj=objs[0] + obj = objs[0] primary_id = obj[primary_key] # locate the tag, see above @@ -193,36 +197,37 @@ def define_accessors_ (module, objclass, methodsuffix, tagname, tag_type_id = tag_type['tag_type_id'] # check authorization - if not hasattr(objclass,'caller_may_write_tag'): - raise PLCAuthenticationFailure("class %s misses method caller_may_write_tag"%objclass.__name__) - obj.caller_may_write_tag (self.api,self.caller,tag_type) + if not hasattr(objclass, 'caller_may_write_tag'): + raise PLCAuthenticationFailure( + "class %s misses method caller_may_write_tag"%objclass.__name__) + obj.caller_may_write_tag(self.api, self.caller, tag_type) # locate the join object (e.g. NodeTag or similar) - filter = {'tag_type_id':tag_type_id} - if isinstance (id_or_name,int): - filter[primary_key]=id_or_name + filter = {'tag_type_id': tag_type_id} + if isinstance(id_or_name, int): + filter[primary_key] = id_or_name else: - filter[secondary_key]=id_or_name - joins = joins_class (self.api,filter) + filter[secondary_key] = id_or_name + joins = joins_class(self.api, filter) # setting to something non void if value is not None: if not joins: - join = join_class (self.api) - join['tag_type_id']=tag_type_id - join[primary_key]=primary_id - join['value']=value + join = join_class(self.api) + join['tag_type_id'] = tag_type_id + join[primary_key] = primary_id + join['value'] = value join.sync() else: - joins[0]['value']=value + joins[0]['value'] = value joins[0].sync() # providing an empty value means clean up else: if joins: - join=joins[0] + join = joins[0] join.delete() # log it - self.event_objects= { objclass.__name__ : [primary_id] } - self.message=objclass.__name__ + self.event_objects = {objclass.__name__ : [primary_id]} + self.message = objclass.__name__ if secondary_key in objs[0]: self.message += " %s "%objs[0][secondary_key] else: @@ -231,15 +236,15 @@ def define_accessors_ (module, objclass, methodsuffix, tagname, return value # attach it - setattr (set_class,"call",set_call) + setattr(set_class, "call", set_call) # define in module - setattr(module,get_name,get_class) - setattr(module,set_name,set_class) + setattr(module, get_name, get_class) + setattr(module, set_name, set_class) # add in .methods try: - methods=getattr(module,'methods') - except: - methods=[] - methods += [get_name,set_name] - setattr(module,'methods',methods) + methods = getattr(module, 'methods') + except Exception: + methods = [] + methods += [get_name, set_name] + setattr(module, 'methods', methods) diff --git a/PLC/Method.py b/PLC/Method.py index 81a1747..836eea0 100644 --- a/PLC/Method.py +++ b/PLC/Method.py @@ -4,23 +4,21 @@ # Mark Huang # Copyright (C) 2006 The Trustees of Princeton University # -import xmlrpc.client -from types import * +#import xmlrpc.client import textwrap -import os import time import pprint from PLC.Faults import * from PLC.Parameter import Parameter, Mixed, python_type, xmlrpc_type from PLC.Auth import Auth -from PLC.Debug import profile +#from PLC.Debug import profile from PLC.Events import Event, Events from PLC.Nodes import Node, Nodes from PLC.Persons import Person, Persons # we inherit object because we use new-style classes for legacy methods -class Method (object): +class Method: """ Base class for all PLCAPI functions. At a minimum, all PLCAPI functions must define: @@ -57,13 +55,13 @@ class Method (object): return True - def __init__(self, api,caller=None): + def __init__(self, api, caller=None): self.name = self.__class__.__name__ self.api = api if caller: # let a method call another one by propagating its caller - self.caller=caller + self.caller = caller else: # Auth may set this to a Person instance (if an anonymous # method, will remain None). @@ -84,7 +82,7 @@ class Method (object): # legacy code cannot be type-checked, due to the way Method.args() works # as of 5.0-rc16 we don't use skip_type_check anymore - if not hasattr(self,"skip_type_check"): + if not hasattr(self, "skip_type_check"): (min_args, max_args, defaults) = self.args() # Check that the right number of arguments were passed in @@ -150,7 +148,8 @@ class Method (object): continue # what type of auth this is if 'AuthMethod' in arg: - auth_methods = ['session', 'password', 'capability', 'gpg', 'hmac','anonymous'] + auth_methods = ['session', 'password', 'capability', + 'gpg', 'hmac', 'anonymous'] auth_method = arg['AuthMethod'] if auth_method in auth_methods: event['auth_type'] = auth_method @@ -171,12 +170,12 @@ class Method (object): elif isinstance(self.caller, Node): event['node_id'] = self.caller['node_id'] - event.sync(commit = False) + event.sync(commit=False) if hasattr(self, 'event_objects') and isinstance(self.event_objects, dict): - for key in list(self.event_objects.keys()): + for key in self.event_objects.keys(): for object_id in self.event_objects[key]: - event.add_object(key, object_id, commit = False) + event.add_object(key, object_id, commit=False) # Set the message for this event @@ -188,7 +187,7 @@ class Method (object): # Commit event.sync() - def help(self, indent = " "): + def help(self, indent=" "): """ Text documentation for the method. """ @@ -228,9 +227,10 @@ class Method (object): # Print parameter documentation right below type if isinstance(param, Parameter): - wrapper = textwrap.TextWrapper(width = 70, - initial_indent = " " * param_offset, - subsequent_indent = " " * param_offset) + wrapper = textwrap.TextWrapper( + width=70, + initial_indent=" " * param_offset, + subsequent_indent = " " * param_offset) text += "\n".join(wrapper.wrap(param.doc)) + "\n" param = param.type @@ -338,7 +338,7 @@ class Method (object): # Integers and long integers are also special types. Accept # either int or long types if an int or long is expected. - elif expected_type in (IntType, LongType) and isinstance(value, (IntType, LongType)): + elif expected_type is int and isinstance(value, int): pass elif not isinstance(value, expected_type): diff --git a/PLC/Parameter.py b/PLC/Parameter.py index 6d20307..1144ec8 100644 --- a/PLC/Parameter.py +++ b/PLC/Parameter.py @@ -5,7 +5,6 @@ # Copyright (C) 2006 The Trustees of Princeton University # -# from types import * from PLC.Faults import * class Parameter: @@ -15,11 +14,11 @@ class Parameter: sub-parameters (i.e., dict fields). """ - def __init__(self, typeval, doc = "", - min = None, max = None, - optional = None, - ro = False, - nullok = False): + def __init__(self, typeval, doc="", + min=None, max=None, + optional=None, + ro=False, + nullok=False): # Basic type of the parameter. Must be a builtin type # that can be marshalled by XML-RPC. self.type = typeval diff --git a/PLC/PostgreSQL.py b/PLC/PostgreSQL.py index ae6c55a..2368419 100644 --- a/PLC/PostgreSQL.py +++ b/PLC/PostgreSQL.py @@ -5,6 +5,12 @@ # Mark Huang # Copyright (C) 2006 The Trustees of Princeton University # +# pylint: disable=c0103, c0111 + +import subprocess +import re +from pprint import pformat +from datetime import datetime as DateTimeType import psycopg2 import psycopg2.extensions @@ -12,16 +18,9 @@ psycopg2.extensions.register_type(psycopg2.extensions.UNICODE) # UNICODEARRAY not exported yet psycopg2.extensions.register_type(psycopg2._psycopg.UNICODEARRAY) -import types -import traceback -import subprocess -import re -from pprint import pformat - from PLC.Logger import logger -from PLC.Debug import profile +#from PLC.Debug import profile from PLC.Faults import * -from datetime import datetime as DateTimeType class PostgreSQL: def __init__(self, api): @@ -35,16 +34,18 @@ class PostgreSQL: # (Re)initialize database connection try: # Try UNIX socket first - self.connection = psycopg2.connect(user = self.api.config.PLC_DB_USER, - password = self.api.config.PLC_DB_PASSWORD, - database = self.api.config.PLC_DB_NAME) + self.connection = psycopg2.connect( + user=self.api.config.PLC_DB_USER, + password=self.api.config.PLC_DB_PASSWORD, + database=self.api.config.PLC_DB_NAME) except psycopg2.OperationalError: # Fall back on TCP - self.connection = psycopg2.connect(user = self.api.config.PLC_DB_USER, - password = self.api.config.PLC_DB_PASSWORD, - database = self.api.config.PLC_DB_NAME, - host = self.api.config.PLC_DB_HOST, - port = self.api.config.PLC_DB_PORT) + self.connection = psycopg2.connect( + user=self.api.config.PLC_DB_USER, + password=self.api.config.PLC_DB_PASSWORD, + database=self.api.config.PLC_DB_NAME, + host=self.api.config.PLC_DB_HOST, + port=self.api.config.PLC_DB_PORT) self.connection.set_client_encoding("UNICODE") (self.rowcount, self.description, self.lastrowid) = \ @@ -63,7 +64,7 @@ class PostgreSQL: if isinstance(x, DateTimeType): x = str(x) elif isinstance(x, str): - x = x.encode( 'utf-8' ) + x = x.encode('utf-8') if isinstance(x, bytes): x = "'%s'" % str(x).replace("\\", "\\\\").replace("'", "''") @@ -72,7 +73,7 @@ class PostgreSQL: elif x is None: x = 'NULL' elif isinstance(x, (list, tuple, set)): - x = 'ARRAY[%s]' % ', '.join([str(_quote(x)) for x in x]) + x = 'ARRAY[%s]' % ', '.join([str(PostgreSQL._quote(x)) for x in x]) elif hasattr(x, '__pg_repr__'): x = x.__pg_repr__() else: @@ -84,7 +85,7 @@ class PostgreSQL: """ Returns quoted version of the specified value. """ - return PostgreSQL._quote (value) + return PostgreSQL._quote(value) # following is an unsuccessful attempt to re-use lib code as much as possible # def quote(self, value): @@ -103,7 +104,7 @@ class PostgreSQL: # return adapt (value) @classmethod - def param(self, name, value): + def param(cls, name, value): # None is converted to the unquoted string NULL if isinstance(value, type(None)): conversion = "s" @@ -129,25 +130,24 @@ class PostgreSQL: def rollback(self): self.connection.rollback() - def do(self, query, params = None): + def do(self, query, params=None): cursor = self.execute(query, params) cursor.close() return self.rowcount def next_id(self, table_name, primary_key): - sequence = "%(table_name)s_%(primary_key)s_seq" % locals() - sql = "SELECT nextval('%(sequence)s')" % locals() - rows = self.selectall(sql, hashref = False) + sequence = "{}_{}_seq".format(table_name, primary_key) + sql = "SELECT nextval('{}')".format(sequence) + rows = self.selectall(sql, hashref=False) if rows: return rows[0][0] - return None def last_insert_id(self, table_name, primary_key): if isinstance(self.lastrowid, int): sql = "SELECT %s FROM %s WHERE oid = %d" % \ (primary_key, table_name, self.lastrowid) - rows = self.selectall(sql, hashref = False) + rows = self.selectall(sql, hashref=False) if rows: return rows[0][0] @@ -158,7 +158,7 @@ class PostgreSQL: # see http://www.python.org/dev/peps/pep-0249/ # accepts either None, a single dict, a tuple of single dict - in which case it execute's # or a tuple of several dicts, in which case it executemany's - def execute(self, query, params = None): + def execute(self, query, params=None): cursor = self.cursor() try: @@ -171,7 +171,7 @@ class PostgreSQL: if psycopg2: query = re.sub(r'(%\([^)]*\)|%)[df]', r'\1s', query) # rewrite wildcards set by Filter.py as '***' into '%' - query = query.replace ('***','%') + query = query.replace('***', '%') if not params: if self.debug: @@ -182,12 +182,12 @@ class PostgreSQL: logger.debug('execute-dict: params {} query {}' .format(params, query%params)) cursor.execute(query, params) - elif isinstance(params,tuple) and len(params)==1: + elif isinstance(params, tuple) and len(params) == 1: if self.debug: logger.debug('execute-tuple {}'.format(query%params[0])) - cursor.execute(query,params[0]) + cursor.execute(query, params[0]) else: - param_seq=(params,) + param_seq = (params,) if self.debug: for params in param_seq: logger.debug('executemany {}'.format(query%params)) @@ -209,7 +209,7 @@ class PostgreSQL: return cursor - def selectall(self, query, params = None, hashref = True, key_field = None): + def selectall(self, query, params=None, hashref=True, key_field=None): """ Return each row as a dictionary keyed on field name (like DBI selectrow_hashref()). If key_field is specified, return rows @@ -233,11 +233,11 @@ class PostgreSQL: if key_field is not None and key_field in labels: # Return rows as a dictionary keyed on the specified field # (like DBI selectall_hashref()). - return dict([(row[key_field], row) for row in rows]) + return {row[key_field]: row for row in rows} else: return rows - def fields(self, table, notnull = None, hasdef = None): + def fields(self, table, notnull=None, hasdef=None): """ Return the names of the fields of the specified table. """ @@ -258,7 +258,7 @@ class PostgreSQL: if hasdef is not None: sql += " AND atthasdef is %(hasdef)s" - rows = self.selectall(sql, locals(), hashref = False) + rows = self.selectall(sql, locals(), hashref=False) self.fields_cache[(table, notnull, hasdef)] = [row[0] for row in rows] diff --git a/PLC/Timestamp.py b/PLC/Timestamp.py index faad925..44df1da 100644 --- a/PLC/Timestamp.py +++ b/PLC/Timestamp.py @@ -14,7 +14,7 @@ from PLC.Parameter import Parameter, Mixed # a dummy class mostly used as a namespace class Timestamp: - debug=False + debug = False # debug=True # this is how we expose times to SQL diff --git a/PLC/sendmail.py b/PLC/sendmail.py index accb0bb..dbaeaad 100644 --- a/PLC/sendmail.py +++ b/PLC/sendmail.py @@ -1,7 +1,6 @@ import os import sys import pprint -from types import StringTypes from email.MIMEText import MIMEText from email.Header import Header from smtplib import SMTP -- 2.43.0