Ran black on sources
This commit is contained in:
parent
5e5f3efc24
commit
db17ece61b
4 changed files with 73 additions and 45 deletions
|
|
@ -2650,40 +2650,46 @@ class CmdFind(COMMAND_DEFAULT_CLASS):
|
||||||
switches.append("loc")
|
switches.append("loc")
|
||||||
|
|
||||||
searchstring = self.lhs
|
searchstring = self.lhs
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Try grabbing the actual min/max id values by database aggregation
|
# 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())
|
low, high = sorted(qs.values())
|
||||||
if not (low and high):
|
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:
|
except Exception as e:
|
||||||
logger.log_trace(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.
|
# bound and do a less-efficient query to find the upper.
|
||||||
low, high = 1, ObjectDB.objects.all().order_by("-id").first().id
|
low, high = 1, ObjectDB.objects.all().order_by("-id").first().id
|
||||||
|
|
||||||
if self.rhs:
|
if self.rhs:
|
||||||
try:
|
try:
|
||||||
# Check that rhs is either a valid dbref or dbref range
|
# 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
|
# dbref() will return either a valid int or None
|
||||||
assert bounds
|
assert bounds
|
||||||
# None should not exist in the bounds list
|
# None should not exist in the bounds list
|
||||||
assert None not in bounds
|
assert None not in bounds
|
||||||
|
|
||||||
low = bounds[0]
|
low = bounds[0]
|
||||||
if len(bounds) > 1:
|
if len(bounds) > 1:
|
||||||
high = bounds[-1]
|
high = bounds[-1]
|
||||||
|
|
||||||
except AssertionError:
|
except AssertionError:
|
||||||
caller.msg("Invalid dbref range provided (not a number).")
|
caller.msg("Invalid dbref range provided (not a number).")
|
||||||
return
|
return
|
||||||
except IndexError as e:
|
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)
|
logger.log_trace(e)
|
||||||
|
|
||||||
low = min(low, high)
|
low = min(low, high)
|
||||||
high = max(low, high)
|
high = max(low, high)
|
||||||
|
|
||||||
|
|
@ -2754,36 +2760,45 @@ class CmdFind(COMMAND_DEFAULT_CLASS):
|
||||||
# Keep the initial queryset handy for later reuse
|
# Keep the initial queryset handy for later reuse
|
||||||
result_qs = ObjectDB.objects.filter(keyquery | aliasquery).distinct()
|
result_qs = ObjectDB.objects.filter(keyquery | aliasquery).distinct()
|
||||||
nresults = result_qs.count()
|
nresults = result_qs.count()
|
||||||
|
|
||||||
# Use iterator to minimize memory ballooning on large result sets
|
# Use iterator to minimize memory ballooning on large result sets
|
||||||
results = result_qs.iterator()
|
results = result_qs.iterator()
|
||||||
|
|
||||||
# Check and see if type filtering was requested; skip it if not
|
# Check and see if type filtering was requested; skip it if not
|
||||||
if any(x in switches for x in ("room", "exit", "char")):
|
if any(x in switches for x in ("room", "exit", "char")):
|
||||||
obj_ids = set()
|
obj_ids = set()
|
||||||
for obj in results:
|
for obj in results:
|
||||||
if ("room" in switches and inherits_from(obj, ROOM_TYPECLASS)) \
|
if (
|
||||||
or ("exit" in switches and inherits_from(obj, EXIT_TYPECLASS)) \
|
("room" in switches and inherits_from(obj, ROOM_TYPECLASS))
|
||||||
or ("char" in switches and inherits_from(obj, CHAR_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)
|
obj_ids.add(obj.id)
|
||||||
|
|
||||||
# Filter previous queryset instead of requesting another
|
# Filter previous queryset instead of requesting another
|
||||||
filtered_qs = result_qs.filter(id__in=obj_ids).distinct()
|
filtered_qs = result_qs.filter(id__in=obj_ids).distinct()
|
||||||
nresults = filtered_qs.count()
|
nresults = filtered_qs.count()
|
||||||
|
|
||||||
# Use iterator again to minimize memory ballooning
|
# Use iterator again to minimize memory ballooning
|
||||||
results = filtered_qs.iterator()
|
results = filtered_qs.iterator()
|
||||||
|
|
||||||
# still results after type filtering?
|
# still results after type filtering?
|
||||||
if nresults:
|
if nresults:
|
||||||
if nresults > 1: header = f'{nresults} Matches'
|
if nresults > 1:
|
||||||
else: header = 'One Match'
|
header = f"{nresults} Matches"
|
||||||
|
else:
|
||||||
|
header = "One Match"
|
||||||
|
|
||||||
string = f"|w{header}|n(#{low}-#{high}{restrictions}):"
|
string = f"|w{header}|n(#{low}-#{high}{restrictions}):"
|
||||||
res = None
|
res = None
|
||||||
for res in results:
|
for res in results:
|
||||||
string += f"\n |g{res.get_display_name(caller)} - {res.path}|n"
|
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)"
|
string += f" (|wlocation|n: |g{res.location.get_display_name(caller)}|n)"
|
||||||
else:
|
else:
|
||||||
string = f"|wNo Matches|n(#{low}-#{high}{restrictions}):"
|
string = f"|wNo Matches|n(#{low}-#{high}{restrictions}):"
|
||||||
|
|
|
||||||
|
|
@ -598,7 +598,11 @@ class CmdObjects(COMMAND_DEFAULT_CLASS):
|
||||||
typetable.align = "l"
|
typetable.align = "l"
|
||||||
dbtotals = ObjectDB.objects.get_typeclass_totals()
|
dbtotals = ObjectDB.objects.get_typeclass_totals()
|
||||||
for stat in dbtotals:
|
for stat in dbtotals:
|
||||||
typetable.add_row(stat.get('typeclass', '<error>'), stat.get('count', -1), "%.2f" % stat.get('percent', -1))
|
typetable.add_row(
|
||||||
|
stat.get("typeclass", "<error>"),
|
||||||
|
stat.get("count", -1),
|
||||||
|
"%.2f" % stat.get("percent", -1),
|
||||||
|
)
|
||||||
|
|
||||||
# last N table
|
# last N table
|
||||||
objs = ObjectDB.objects.all().order_by("db_date_created")[max(0, nobjs - nlim) :]
|
objs = ObjectDB.objects.all().order_by("db_date_created")[max(0, nobjs - nlim) :]
|
||||||
|
|
|
||||||
|
|
@ -1042,20 +1042,23 @@ class TestBuilding(CommandTest):
|
||||||
self.call(building.CmdFind(), "/room Obj", "No Matches")
|
self.call(building.CmdFind(), "/room Obj", "No Matches")
|
||||||
self.call(building.CmdFind(), "/exit Obj", "No Matches")
|
self.call(building.CmdFind(), "/exit Obj", "No Matches")
|
||||||
self.call(building.CmdFind(), "/exact Obj", "One Match")
|
self.call(building.CmdFind(), "/exact Obj", "One Match")
|
||||||
|
|
||||||
# Test multitype filtering
|
# 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 Obj", "No Matches")
|
||||||
self.call(building.CmdFind(), "/char/room/exit Char", "2 Matches")
|
self.call(building.CmdFind(), "/char/room/exit Char", "2 Matches")
|
||||||
self.call(building.CmdFind(), "/char/room/exit/startswith Cha", "2 Matches")
|
self.call(building.CmdFind(), "/char/room/exit/startswith Cha", "2 Matches")
|
||||||
|
|
||||||
# Test null search
|
# Test null search
|
||||||
self.call(building.CmdFind(), "=", "Usage: ")
|
self.call(building.CmdFind(), "=", "Usage: ")
|
||||||
|
|
||||||
# Test bogus dbref range with no search term
|
# Test bogus dbref range with no search term
|
||||||
self.call(building.CmdFind(), "= obj", "Invalid dbref range provided (not a number).")
|
self.call(building.CmdFind(), "= obj", "Invalid dbref range provided (not a number).")
|
||||||
self.call(building.CmdFind(), "= #1a", "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
|
# Test valid dbref ranges with no search term
|
||||||
self.call(building.CmdFind(), "=#1", "7 Matches(#1-#7)")
|
self.call(building.CmdFind(), "=#1", "7 Matches(#1-#7)")
|
||||||
self.call(building.CmdFind(), "=1-2", "2 Matches(#1-#2):")
|
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):")
|
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):
|
def test_script(self):
|
||||||
self.call(building.CmdScript(), "Obj = ", "No scripts defined on Obj")
|
self.call(building.CmdScript(), "Obj = ", "No scripts defined on Obj")
|
||||||
self.call(
|
self.call(
|
||||||
|
|
@ -1500,4 +1503,4 @@ class TestSystemCommands(CommandTest):
|
||||||
mock_channeldb.objects.get_channel = mock.MagicMock(return_value=channel)
|
mock_channeldb.objects.get_channel = mock.MagicMock(return_value=channel)
|
||||||
|
|
||||||
self.call(syscommands.SystemSendToChannel(), "public:Hello")
|
self.call(syscommands.SystemSendToChannel(), "public:Hello")
|
||||||
channel.msg.assert_called()
|
channel.msg.assert_called()
|
||||||
|
|
|
||||||
|
|
@ -484,7 +484,7 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
||||||
if max_dbref is not None:
|
if max_dbref is not None:
|
||||||
retval = retval.filter(id__lte=self.dbref(max_dbref, reqhash=False))
|
retval = retval.filter(id__lte=self.dbref(max_dbref, reqhash=False))
|
||||||
return retval
|
return retval
|
||||||
|
|
||||||
def get_typeclass_totals(self, *args, **kwargs) -> object:
|
def get_typeclass_totals(self, *args, **kwargs) -> object:
|
||||||
"""
|
"""
|
||||||
Returns a queryset of typeclass composition statistics.
|
Returns a queryset of typeclass composition statistics.
|
||||||
|
|
@ -495,18 +495,24 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
||||||
the percentage of objects associated with the typeclass.
|
the percentage of objects associated with the typeclass.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return self.values('db_typeclass_path').distinct().annotate(
|
return (
|
||||||
# Get count of how many objects for each typeclass exist
|
self.values("db_typeclass_path")
|
||||||
count=Count('db_typeclass_path')
|
.distinct()
|
||||||
).annotate(
|
.annotate(
|
||||||
# Rename db_typeclass_path field to something more human
|
# Get count of how many objects for each typeclass exist
|
||||||
typeclass=F('db_typeclass_path'),
|
count=Count("db_typeclass_path")
|
||||||
# Calculate this class' percentage of total composition
|
)
|
||||||
percent=ExpressionWrapper(
|
.annotate(
|
||||||
((F('count') / float(self.count())) * 100.0), output_field=FloatField()
|
# Rename db_typeclass_path field to something more human
|
||||||
),
|
typeclass=F("db_typeclass_path"),
|
||||||
).values('typeclass', 'count', 'percent')
|
# 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):
|
def object_totals(self):
|
||||||
"""
|
"""
|
||||||
Get info about database statistics.
|
Get info about database statistics.
|
||||||
|
|
@ -518,8 +524,8 @@ class TypedObjectManager(idmapper.manager.SharedMemoryManager):
|
||||||
object having that typeclass set on themselves).
|
object having that typeclass set on themselves).
|
||||||
|
|
||||||
"""
|
"""
|
||||||
stats = self.get_typeclass_totals().order_by('typeclass')
|
stats = self.get_typeclass_totals().order_by("typeclass")
|
||||||
return {x.get('typeclass'):x.get('count') for x in stats}
|
return {x.get("typeclass"): x.get("count") for x in stats}
|
||||||
|
|
||||||
def typeclass_search(self, typeclass, include_children=False, include_parents=False):
|
def typeclass_search(self, typeclass, include_children=False, include_parents=False):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue