From db17ece61b60faedbbc2d0733a03863aa018db56 Mon Sep 17 00:00:00 2001 From: Griatch Date: Sat, 18 Jan 2020 00:15:02 +0100 Subject: [PATCH] Ran black on sources --- evennia/commands/default/building.py | 59 +++++++++++++++++----------- evennia/commands/default/system.py | 6 ++- evennia/commands/default/tests.py | 17 ++++---- evennia/typeclasses/managers.py | 36 ++++++++++------- 4 files changed, 73 insertions(+), 45 deletions(-) diff --git a/evennia/commands/default/building.py b/evennia/commands/default/building.py index 2ed20f171b..47ebaa9296 100644 --- a/evennia/commands/default/building.py +++ b/evennia/commands/default/building.py @@ -2650,40 +2650,46 @@ class CmdFind(COMMAND_DEFAULT_CLASS): switches.append("loc") searchstring = self.lhs - + try: # Try grabbing the actual min/max id values by database aggregation - qs = ObjectDB.objects.values('id').aggregate(low=Min('id'), high=Max('id')) + qs = ObjectDB.objects.values("id").aggregate(low=Min("id"), high=Max("id")) low, high = sorted(qs.values()) if not (low and high): - raise ValueError(f"{self.__class__.__name__}: Min and max ID not returned by aggregation; falling back to queryset slicing.") + raise ValueError( + f"{self.__class__.__name__}: Min and max ID not returned by aggregation; falling back to queryset slicing." + ) except Exception as e: logger.log_trace(e) - # If that doesn't work for some reason (empty DB?), guess the lower + # If that doesn't work for some reason (empty DB?), guess the lower # bound and do a less-efficient query to find the upper. low, high = 1, ObjectDB.objects.all().order_by("-id").first().id - + if self.rhs: try: # Check that rhs is either a valid dbref or dbref range - bounds = tuple(sorted(dbref(x, False) for x in re.split('[-\s]+', self.rhs.strip()))) - + bounds = tuple( + sorted(dbref(x, False) for x in re.split("[-\s]+", self.rhs.strip())) + ) + # dbref() will return either a valid int or None assert bounds # None should not exist in the bounds list assert None not in bounds - + low = bounds[0] if len(bounds) > 1: high = bounds[-1] - + except AssertionError: caller.msg("Invalid dbref range provided (not a number).") return except IndexError as e: - logger.log_err(f"{self.__class__.__name__}: Error parsing upper and lower bounds of query.") + logger.log_err( + f"{self.__class__.__name__}: Error parsing upper and lower bounds of query." + ) logger.log_trace(e) - + low = min(low, high) high = max(low, high) @@ -2754,36 +2760,45 @@ class CmdFind(COMMAND_DEFAULT_CLASS): # Keep the initial queryset handy for later reuse result_qs = ObjectDB.objects.filter(keyquery | aliasquery).distinct() nresults = result_qs.count() - + # Use iterator to minimize memory ballooning on large result sets results = result_qs.iterator() - + # Check and see if type filtering was requested; skip it if not if any(x in switches for x in ("room", "exit", "char")): obj_ids = set() for obj in results: - if ("room" in switches and inherits_from(obj, ROOM_TYPECLASS)) \ - or ("exit" in switches and inherits_from(obj, EXIT_TYPECLASS)) \ - or ("char" in switches and inherits_from(obj, CHAR_TYPECLASS)): + if ( + ("room" in switches and inherits_from(obj, ROOM_TYPECLASS)) + or ("exit" in switches and inherits_from(obj, EXIT_TYPECLASS)) + or ("char" in switches and inherits_from(obj, CHAR_TYPECLASS)) + ): obj_ids.add(obj.id) - + # Filter previous queryset instead of requesting another filtered_qs = result_qs.filter(id__in=obj_ids).distinct() nresults = filtered_qs.count() - + # Use iterator again to minimize memory ballooning results = filtered_qs.iterator() # still results after type filtering? if nresults: - if nresults > 1: header = f'{nresults} Matches' - else: header = 'One Match' - + if nresults > 1: + header = f"{nresults} Matches" + else: + header = "One Match" + string = f"|w{header}|n(#{low}-#{high}{restrictions}):" res = None for res in results: string += f"\n |g{res.get_display_name(caller)} - {res.path}|n" - if "loc" in self.switches and nresults == 1 and res and getattr(res, 'location', None): + if ( + "loc" in self.switches + and nresults == 1 + and res + and getattr(res, "location", None) + ): string += f" (|wlocation|n: |g{res.location.get_display_name(caller)}|n)" else: string = f"|wNo Matches|n(#{low}-#{high}{restrictions}):" diff --git a/evennia/commands/default/system.py b/evennia/commands/default/system.py index ad356a5d57..25e075ddcc 100644 --- a/evennia/commands/default/system.py +++ b/evennia/commands/default/system.py @@ -598,7 +598,11 @@ class CmdObjects(COMMAND_DEFAULT_CLASS): typetable.align = "l" dbtotals = ObjectDB.objects.get_typeclass_totals() for stat in dbtotals: - typetable.add_row(stat.get('typeclass', ''), stat.get('count', -1), "%.2f" % stat.get('percent', -1)) + typetable.add_row( + stat.get("typeclass", ""), + stat.get("count", -1), + "%.2f" % stat.get("percent", -1), + ) # last N table objs = ObjectDB.objects.all().order_by("db_date_created")[max(0, nobjs - nlim) :] diff --git a/evennia/commands/default/tests.py b/evennia/commands/default/tests.py index c6ae160361..a836982899 100644 --- a/evennia/commands/default/tests.py +++ b/evennia/commands/default/tests.py @@ -1042,20 +1042,23 @@ class TestBuilding(CommandTest): self.call(building.CmdFind(), "/room Obj", "No Matches") self.call(building.CmdFind(), "/exit Obj", "No Matches") self.call(building.CmdFind(), "/exact Obj", "One Match") - + # Test multitype filtering - with mock.patch('evennia.commands.default.building.CHAR_TYPECLASS', 'evennia.objects.objects.DefaultCharacter'): + with mock.patch( + "evennia.commands.default.building.CHAR_TYPECLASS", + "evennia.objects.objects.DefaultCharacter", + ): self.call(building.CmdFind(), "/char/room Obj", "No Matches") self.call(building.CmdFind(), "/char/room/exit Char", "2 Matches") self.call(building.CmdFind(), "/char/room/exit/startswith Cha", "2 Matches") - + # Test null search self.call(building.CmdFind(), "=", "Usage: ") - + # Test bogus dbref range with no search term self.call(building.CmdFind(), "= obj", "Invalid dbref range provided (not a number).") self.call(building.CmdFind(), "= #1a", "Invalid dbref range provided (not a number).") - + # Test valid dbref ranges with no search term self.call(building.CmdFind(), "=#1", "7 Matches(#1-#7)") self.call(building.CmdFind(), "=1-2", "2 Matches(#1-#2):") @@ -1063,7 +1066,7 @@ class TestBuilding(CommandTest): self.call(building.CmdFind(), "=1- #2", "2 Matches(#1-#2):") self.call(building.CmdFind(), "=1-#2", "2 Matches(#1-#2):") self.call(building.CmdFind(), "=#1-2", "2 Matches(#1-#2):") - + def test_script(self): self.call(building.CmdScript(), "Obj = ", "No scripts defined on Obj") self.call( @@ -1500,4 +1503,4 @@ class TestSystemCommands(CommandTest): mock_channeldb.objects.get_channel = mock.MagicMock(return_value=channel) self.call(syscommands.SystemSendToChannel(), "public:Hello") - channel.msg.assert_called() \ No newline at end of file + channel.msg.assert_called() diff --git a/evennia/typeclasses/managers.py b/evennia/typeclasses/managers.py index 1c1eb456ce..e9ad42ed11 100644 --- a/evennia/typeclasses/managers.py +++ b/evennia/typeclasses/managers.py @@ -484,7 +484,7 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager): if max_dbref is not None: retval = retval.filter(id__lte=self.dbref(max_dbref, reqhash=False)) return retval - + def get_typeclass_totals(self, *args, **kwargs) -> object: """ Returns a queryset of typeclass composition statistics. @@ -495,18 +495,24 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager): the percentage of objects associated with the typeclass. """ - return self.values('db_typeclass_path').distinct().annotate( - # Get count of how many objects for each typeclass exist - count=Count('db_typeclass_path') - ).annotate( - # Rename db_typeclass_path field to something more human - typeclass=F('db_typeclass_path'), - # Calculate this class' percentage of total composition - percent=ExpressionWrapper( - ((F('count') / float(self.count())) * 100.0), output_field=FloatField() - ), - ).values('typeclass', 'count', 'percent') - + return ( + self.values("db_typeclass_path") + .distinct() + .annotate( + # Get count of how many objects for each typeclass exist + count=Count("db_typeclass_path") + ) + .annotate( + # Rename db_typeclass_path field to something more human + typeclass=F("db_typeclass_path"), + # Calculate this class' percentage of total composition + percent=ExpressionWrapper( + ((F("count") / float(self.count())) * 100.0), output_field=FloatField() + ), + ) + .values("typeclass", "count", "percent") + ) + def object_totals(self): """ Get info about database statistics. @@ -518,8 +524,8 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager): object having that typeclass set on themselves). """ - stats = self.get_typeclass_totals().order_by('typeclass') - return {x.get('typeclass'):x.get('count') for x in stats} + stats = self.get_typeclass_totals().order_by("typeclass") + return {x.get("typeclass"): x.get("count") for x in stats} def typeclass_search(self, typeclass, include_children=False, include_parents=False): """