''' Created on Nov 28, 2017 @author: Charlie McLouth ''' from P4 import P4 as _P4, DepotFile, FilelogOutputHandler, Integration, Map, \ OutputHandler, P4Exception, processFilelog, Progress, ReportHandler, \ Resolver, Revision, Spec, TextProgress class P4(_P4): ''' classdocs ''' # static set of commands supporting the -m limit withlimits = set(["branches", "changes", "clients", "groups", "jobs", "labels", "property", "remotes", "repos", "streams", "users", "counters", "describe", "diff", "filelog", "files", "fixes", "fstat", "journals", "keys", "logparse", "opened", "print", "sizes"]) # commands to ignore limits withoutlimits = set(["sync"]) extendedattributes = {} def __init__(self, *args, **kargs): # add a global result limit self.extendedattributes.setdefault("resultLimit", 0) resultlimit = kargs.pop("limit", 0) if resultlimit is not None: if not isinstance(resultlimit, int): try: resultlimit = int(resultlimit) if resultlimit < 0: resultlimit = 0 except: resultlimit = 0 self.extendedattributes["resultLimit"] = resultlimit self.specfields.update({"ldaps": ("ldap","Name"), "remotes": ("remote","RemoteID"), "repos": ("repo","Repo"), "servers": ("server","ServerID")}) return _P4.__init__(self, *args, **kargs) def run(self, *args, **kargs): command = args[0] offset = kargs.pop("offset", None) if offset is not None and not isinstance(offset, int): try: offset = int(offset) if offset < 0: offset = 0 except: offset = None limit = kargs.pop("limit", self.extendedattributes["resultLimit"]) if limit is not None and not isinstance(limit, int): try: limit = int(limit) if limit < 1: limit = 0 except: limit = 0 # ignore limits if command in self.withoutlimits: offset = None limit = 0 # if the command supports -m limit add them if limit > 0 and command in self.withlimits: args = (args[0], "-m", str(limit + 1 + (offset or 0))) + args[1:] result = _P4.run(self, *args, **kargs) if isinstance(result, list) \ and (limit > 0 or offset is not None): if offset is not None and offset > 0: if offset < len(result): result = result[offset:] elif offset >= len(result): message = "Positioning offset({}) greater than result "\ "count({}).".format(offset, len(result)) self.warnings.append(message) self.warnings.append({"offset": offset, "count": len(result)}) if self.exception_level >= _P4.RAISE_ALL: raise P4Exception(message) result = [] if limit > 0: if limit < len(result): message = "More results available at positioning offset"\ "({}).".format(limit + (offset or 0)) self.warnings.append(message) self.warnings.append({"next_offset": limit + (offset or 0)}) result = result[:limit] if self.exception_level >= _P4.RAISE_ALL: raise P4Exception(message) return result def __specgenerator(self, cmd, specs): '''generator that accumulates warnings warnings are preserved in the order they occur ''' spec = self.specfields[cmd][0] field = self.specfields[cmd][1] for x in specs: # copy any previous warnings previouswarnings = list(self.warnings) # run the command result = self.run(spec, '-o', x[field]) # insert previous warnings self.warnings[0:0] = previouswarnings yield result[0] def __iterate(self, cmd, *args, **kargs): if cmd in self.specfields: specs = self.run(cmd, *args, **kargs) return self.__specgenerator(cmd, specs) else: raise Exception('Unknown spec list command: %s', cmd)