internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: evennia/evennia

Issue:
[BUG - Develop] Built in funcparser method, `$round` is broken (doesn't return its value)
#### Describe the bug
The func parser method `$round`, implemented [here](https://github.com/evennia/evennia/blob/develop/evennia/utils/funcparser.py#L776), doesn't return its value. It is broken because of this and evaluates to the literal string `"None"`.

See following test:

```
            ("$round(2.9) apples", "3.0 apples"),
            ("$round(2.967, 1) apples", "3.0 apples"),
```

Which fail with:

```
======================================================================
FAIL: test_other_callables_22__round_2_9_apples (evennia.utils.tests.test_funcparser.TestDefaultCallables)
Test default callables [with string='$round(2.9) apples', expected='3.0 apples'].
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/tmoney/code/gamedir/venv/lib/python3.9/site-packages/parameterized/parameterized.py", line 533, in standalone_func
    return func(*(a + p.args), **p.kwargs)
  File "/home/tmoney/code/evennia/evennia/utils/tests/test_funcparser.py", line 513, in test_other_callables
    self.assertEqual(expected, ret)
AssertionError: '3.0 apples' != 'None apples'
- 3.0 apples
+ None apples


======================================================================
FAIL: test_other_callables_23__round_2_967_1_apples (evennia.utils.tests.test_funcparser.TestDefaultCallables)
Test default callables [with string='$round(2.967, 1) apples', expected='3.0 apples'].
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/tmoney/code/gamedir/venv/lib/python3.9/site-packages/parameterized/parameterized.py", line 533, in standalone_func
    return func(*(a + p.args), **p.kwargs)
  File "/home/tmoney/code/evennia/evennia/utils/tests/test_funcparser.py", line 513, in test_other_callables
    self.assertEqual(expected, ret)
AssertionError: '3.0 apples' != 'None apples'
- 3.0 apples
+ None apples
```

#### To Reproduce
Run tests.

#### Expected behavior
Per tests.

#### Develop-branch commit
b0f24f9975e14fddeabef06a19b5b61575957b1c

#### Additional context
Obviously this is a one line fix, it just needs to return the value it's computing. I'm filing this bug because I'm trying to write tests and my general best practice is to not modify the code-under-test at the same time, because it gets confusing. Better to just submit a skipped, failing test and come back to it.



Discussion:

Resolving patch:
diff --git a/evennia/utils/funcparser.py b/evennia/utils/funcparser.py
--- a/evennia/utils/funcparser.py
+++ b/evennia/utils/funcparser.py
@@ -799,7 +799,7 @@ def funcparser_callable_round(*args, **kwargs):
     num, *significant = args
     significant = significant[0] if significant else 0
     try:
-        round(num, significant)
+        return round(num, significant)
     except Exception:
         if kwargs.get("raise_errors"):
             raise


Test patch:
Repository: evennia/evennia

Issue:
[BUG - Develop] Funcparser `$search()` doesn't check access appropriately
#### Describe the bug
This line in funcparser:

https://github.com/evennia/evennia/blob/develop/evennia/utils/funcparser.py#L1165

This seems to be intended to check if `caller` can access `target`. But it seems to always pass, possibly because `access` is meant to be called with two arguments and this invocation is slurping the `"control"` access level as an unused args?

#### To Reproduce
Failing test:

```
    def test_search_no_access(self):
        string = "Go to $search(Room)"
        with self.assertRaises(funcparser.ParsingError):
            self.parser.parse(string, caller=self.char2, return_list=True, raise_errors=True)
```

Failure:
```
======================================================================
FAIL: test_search_no_access (evennia.utils.tests.test_funcparser.TestCallableSearch)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/tmoney/code/evennia/evennia/utils/tests/test_funcparser.py", line 708, in test_search_no_access
    self.parser.parse(string, caller=self.char2, return_list=True, raise_errors=True)
AssertionError: ParsingError not raised

----------------------------------------------------------------------
```

#### Expected behavior
Test passes because `self.char2` doesn't have a "control" access on any rooms.

#### Develop-branch commit
b0f24f9975e14fddeabef06a19b5b61575957b1c

#### Additional context
Again, a small bug that should be easy to fix, but I'd rather submit a skipped failing test and fix it after review.



Discussion:

Resolving patch:
diff --git a/evennia/utils/funcparser.py b/evennia/utils/funcparser.py
--- a/evennia/utils/funcparser.py
+++ b/evennia/utils/funcparser.py
@@ -1162,7 +1162,7 @@ def funcparser_callable_search(*args, caller=None, access="control", **kwargs):
         )
 
     for target in targets:
-        if not target.access(caller, target, access):
+        if not target.access(caller, access):
             raise ParsingError("$search Cannot add found entity - access failure.")
 
     return list(targets) if return_list else targets[0]


Test patch:
diff --git a/evennia/utils/tests/test_funcparser.py b/evennia/utils/tests/test_funcparser.py
--- a/evennia/utils/tests/test_funcparser.py
+++ b/evennia/utils/tests/test_funcparser.py
@@ -528,6 +528,7 @@ def test_search_account(self):
         """
         string = "$search(TestAccount, type=account)"
         expected = self.account
+        self.account.locks.add("control:id(%s)" % self.char1.dbref)
 
         ret = self.parser.parse(string, caller=self.char1, return_str=False, raise_errors=True)
         self.assertEqual(expected, ret)
@@ -539,6 +540,7 @@ def test_search_script(self):
         """
         string = "$search(Script, type=script)"
         expected = self.script
+        self.script.locks.add("control:id(%s)" % self.char1.dbref)
 
         ret = self.parser.parse(string, caller=self.char1, return_str=False, raise_errors=True)
         self.assertEqual(expected, ret)
Repository: evennia/evennia

Issue:
[BUG - Develop] `$search` in funcparser throws wrong exception when no results found
#### Describe the bug
The `$search()` func should throw funcparser.ParsingError when no results found. Instead it throws NameError because the variable used in the f string is not found.

#### To Reproduce
Test:
```
    def test_search_not_found(self):
        string = "$search(foo)"
        with self.assertRaises(funcparser.ParsingError):
            self.parser.parse(string, caller=self.char1, return_str=False, raise_errors=True)

        ret = self.parser.parse(string, caller=self.char1, return_str=False, raise_errors=False)
        self.assertEqual("$search(foo)", ret)

        ret = self.parser.parse(string, caller=self.char1, return_list=True, raise_errors=False)
        self.assertEqual([], ret)
```

Result:
```
======================================================================
ERROR: test_search_not_found (evennia.utils.tests.test_funcparser.TestCallableSearch)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/tmoney/code/evennia/evennia/utils/tests/test_funcparser.py", line 688, in test_search_not_found
    self.parser.parse(string, caller=self.char1, return_str=False, raise_errors=True)
  File "/home/tmoney/code/evennia/evennia/utils/funcparser.py", line 540, in parse
    exec_return = self.execute(
  File "/home/tmoney/code/evennia/evennia/utils/funcparser.py", line 259, in execute
    ret = func(*args, **kwargs)
  File "/home/tmoney/code/evennia/evennia/utils/funcparser.py", line 1156, in funcparser_callable_search
    raise ParsingError(f"$search: Query '{query}' gave no matches.")
NameError: name 'query' is not defined

----------------------------------------------------------------------
```

https://github.com/evennia/evennia/blob/develop/evennia/utils/funcparser.py#L1160

#### Expected behavior
The proper ParsingError is thrown.

#### Develop-branch commit
b0f24f9975e14fddeabef06a19b5b61575957b1c

#### Additional context
This is a pretty simple bug to fix, but I'm trying to write tests to increase test coverage without modifying any code-under-test, since that confuses things. I will add the failing test with a 'skip' to demonstrate the issue, and it can be unskipped when it is fixed.



Discussion:
Fixed in https://github.com/audiodude/evennia/tree/search-f-string

Resolving patch:
diff --git a/evennia/utils/funcparser.py b/evennia/utils/funcparser.py
--- a/evennia/utils/funcparser.py
+++ b/evennia/utils/funcparser.py
@@ -1153,7 +1153,7 @@ def funcparser_callable_search(*args, caller=None, access="control", **kwargs):
     if not targets:
         if return_list:
             return []
-        raise ParsingError(f"$search: Query '{query}' gave no matches.")
+        raise ParsingError(f"$search: Query '{args[0]}' gave no matches.")
 
     if len(targets) > 1 and not return_list:
         raise ParsingError(


Test patch:
Repository: evennia/evennia

Issue:
[BUG - Develop] Exception when teleporting by name
#### Describe the bug
When attempting to teleport to a room by name such as "Limbo", an exception is thrown and the command fails. Teleporting by dbref works as intended.

```
Traceback (most recent call last):
  File "/home/david/muddev/evennia/evennia/commands/cmdhandler.py", line 617, in _run_command
    yield cmd.parse()
  File "/home/david/muddev/evennia/evennia/commands/default/building.py", line 3634, in parse
    self.destination = self.caller.search(self.lhs, global_search=True)
  File "/home/david/muddev/evennia/evennia/objects/objects.py", line 501, in search
    return _AT_SEARCH_RESULT(
  File "/home/david/muddev/evennia/evennia/utils/utils.py", line 2296, in at_search_result
    aliases = [alias for alias in aliases if alias.category not in ("plural_key",)]
  File "/home/david/muddev/evennia/evennia/utils/utils.py", line 2296, in <listcomp>
    aliases = [alias for alias in aliases if alias.category not in ("plural_key",)]
AttributeError: 'Tag' object has no attribute 'category'
```

#### To Reproduce
Steps to reproduce the behavior:
1.Type `tel Limbo`
2. See error

#### Expected behavior
The player should be teleported to a matching object or presented a list if encountering multiple matches.

#### Develop-branch commit
0eda75187



Discussion:
Looks like this is from a very recent bugfix (probably unintentionally) removing a previous `hasattr` check, I'll put in a quick patch for it.

Resolving patch:
diff --git a/evennia/utils/utils.py b/evennia/utils/utils.py
--- a/evennia/utils/utils.py
+++ b/evennia/utils/utils.py
@@ -2293,7 +2293,7 @@ def at_search_result(matches, caller, query="", quiet=False, **kwargs):
                 # result is a typeclassed entity where `.aliases` is an AliasHandler.
                 aliases = result.aliases.all(return_objs=True)
                 # remove pluralization aliases
-                aliases = [alias for alias in aliases if alias.category not in ("plural_key",)]
+                aliases = [alias for alias in aliases if hasattr(alias, "category") and alias.category not in ("plural_key",)]
             else:
                 # result is likely a Command, where `.aliases` is a list of strings.
                 aliases = result.aliases


Test patch:
Repository: evennia/evennia

Issue:
[BUG] Leading whitespace getting stripped from py shell input
#### Describe the bug
When you try to enter py code with indentation through the game client, the python shell responds with IndentationError as if you didn't add any indentation. This came up while following the [Beginner's Tutorial Part 1 Lesson 7](https://www.evennia.com/docs/latest/Howtos/Beginner-Tutorial/Part1/Beginner-Tutorial-Learning-Typeclasses.html)

#### To Reproduce
Steps to reproduce the behavior:
1. Log into the webclient (e.g. 127.0.0.1:4001/webclient/ on a local install) as an admin
2. Enter "py" by itself to enter into the python shell
3. Try to input the following code line by line:
```python
for i in [0,1,2]:
    print(i)
```
4. Outputs "IndentationError: expected an indented block after 'for' statement on line 1"

#### Expected behavior
Output of:
```
0
1
2
```

#### Environment, Evennia version, OS etc
    Evennia 1.0.1
    OS: nt
    Python: 3.11.0
    Twisted: 22.10.0
    Django: 4.1.4

#### Additional context
I inspected the websocket connection, and it appear the "print" line is being sent with leading whitespace, so the issue doesn't seem to be on the client side js.


Discussion:

Resolving patch:
diff --git a/evennia/typeclasses/attributes.py b/evennia/typeclasses/attributes.py
--- a/evennia/typeclasses/attributes.py
+++ b/evennia/typeclasses/attributes.py
@@ -1737,7 +1737,7 @@ def nickreplace(self, raw_string, categories=("inputline", "channel"), include_a
                 regex = re.compile(nick_regex, re.I + re.DOTALL + re.U)
                 self._regex_cache[nick_regex] = regex
 
-            is_match, raw_string = parse_nick_template(raw_string.strip(), regex, template)
+            is_match, raw_string = parse_nick_template(raw_string, regex, template)
             if is_match:
                 break
         return raw_string


Test patch:
Repository: evennia/evennia

Issue:
Clothing system bug with covering
#### Brief summary of issue / Description of requested feature:

Wearing an 'undershirt', then wearing a 'top' produces an error because of the top covering the undershirt

#### Steps to reproduce the issue / Reasons for adding feature:

1. Wear an undershirt
2. Wear a top


#### Error output / Expected result of feature
  File "C:\Program Files\Python310\Lib\site-packages\evennia\commands\cmdhandler.py", line 624, in _run_command
    ret = cmd.func()
  File "C:\Program Files\Python310\Lib\site-packages\evennia\contrib\game_systems\clothing\clothing.py", line 500, in func
    clothing.wear(self.caller, wearstyle)
  File "C:\Program Files\Python310\Lib\site-packages\evennia\contrib\game_systems\clothing\clothing.py", line 281, in wear
    wearer.location.msg_contents(message + ".", from_obj=wearer)
  File "C:\Program Files\Python310\Lib\site-packages\evennia\objects\objects.py", line 784, in msg_contents
    outmessage = outmessage.format_map(
KeyError: 'iter_to_str(to_cover)'

#### Extra information, such as Evennia revision/repo/branch, operating system and ideas for how to solve / implement:



Discussion:

Resolving patch:
diff --git a/evennia/contrib/game_systems/clothing/clothing.py b/evennia/contrib/game_systems/clothing/clothing.py
--- a/evennia/contrib/game_systems/clothing/clothing.py
+++ b/evennia/contrib/game_systems/clothing/clothing.py
@@ -277,7 +277,7 @@ def wear(self, wearer, wearstyle, quiet=False):
             else:
                 message = f"$You() $conj(put) on {self.name}"
             if to_cover:
-                message += ", covering {iter_to_str(to_cover)}"
+                message += f", covering {iter_to_str(to_cover)}"
             wearer.location.msg_contents(message + ".", from_obj=wearer)
 
     def remove(self, wearer, quiet=False):


Test patch:
Repository: evennia/evennia

Issue:
[BUG] Extended Room Contrib throws a traceback when looking at an object
#### Describe the bug
If a character looks at an object in a room created using the ExtendedRoom Contrib, a traceback occurs and the character does not get the object's description.

#### To Reproduce
Steps to reproduce the behavior:
1. create a room using Extended Room
2. create/drop a standard object in the room
3. Look at object
4. See error

#### Expected behavior
The character should see (assuming they have view access) the object's description.

#### Environment, Evennia version, OS etc
 Evennia version: 2.0.0

#### Additional context
2023-06-13 11:47:51 [!!] Traceback (most recent call last):
2023-06-13 11:47:51 [!!]   File "/home/deej/muddev/evenv/lib/python3.11/site-packages/evennia/commands/cmdhandler.py", line 624, in _run_command
2023-06-13 11:47:51 [!!]     ret = cmd.func()
2023-06-13 11:47:51 [!!]           ^^^^^^^^^^
2023-06-13 11:47:51 [!!]   File "/home/deej/muddev/evenv/lib/python3.11/site-packages/evennia/contrib/grid/extended_room/extended_room.py", line 618, in func
2023-06-13 11:47:51 [!!]     desc = caller.at_look(target)
2023-06-13 11:47:51 [!!]            ^^^^^^^^^^^^^^^^^^^^^^
2023-06-13 11:47:51 [!!]   File "/home/deej/muddev/evenv/lib/python3.11/site-packages/evennia/objects/objects.py", line 2160, in at_look
2023-06-13 11:47:51 [!!]     if not target.access(self, "view"):
2023-06-13 11:47:51 [!!]            ^^^^^^^^^^^^^
2023-06-13 11:47:51 [!!] AttributeError: 'list' object has no attribute 'access'
2023-06-13 11:47:51 [EE] User input was: 'l bowl



Discussion:

Resolving patch:
diff --git a/evennia/contrib/grid/extended_room/extended_room.py b/evennia/contrib/grid/extended_room/extended_room.py
--- a/evennia/contrib/grid/extended_room/extended_room.py
+++ b/evennia/contrib/grid/extended_room/extended_room.py
@@ -612,8 +612,15 @@ def func(self):
         else:
             # search, waiting to return errors so we can also check details
             target = caller.search(self.args, quiet=True)
-            if not target and not self.look_detail():
-                _AT_SEARCH_RESULT(target, caller, self.args, quiet=False)
+            # if there's no target, check details
+            if not target:
+                # no target AND no detail means run the normal no-results message
+                if not self.look_detail():
+                    _AT_SEARCH_RESULT(target, caller, self.args, quiet=False)
+                return
+            # otherwise, run normal search result handling
+            target = _AT_SEARCH_RESULT(target, caller, self.args, quiet=False)
+            if not target:
                 return
         desc = caller.at_look(target)
         # add the type=look to the outputfunc to make it


Test patch:
Repository: evennia/evennia

Issue:
[BUG] EvMenu no longer supports nodetext as str
#### Describe the bug
Providing EvMenu nodetext as a string results in the following error:

```
  File "/home/awranthyr/muddev/evennia/evennia/utils/evmenu.py", line 936, in goto
    if helptext:
       ^^^^^^^^
UnboundLocalError: cannot access local variable 'helptext' where it is not associated with a value
```

#### To Reproduce
Steps to reproduce the behavior:
1.  End a menu node with `return "", {}` or any other instance of a str value for the nodetext.
2.  Enter the menu node and see above error.

#### Expected behavior
EvMenu is intended to gracefully handle nodetext as a str.

#### Environment, Evennia version, OS etc
```
    Evennia 2.2.0 (rev c4c4cb14ff)
    OS: posix
    Python: 3.11.4
    Twisted: 22.10.0
    Django: 4.1.4
```

#### Additional context
Seems to just be an unintended oversight that occurred with the removal of `helptext = ""` on line 917 of utils/evmenu.py.  Restoring that line should fix the problem.



Discussion:

Resolving patch:
diff --git a/evennia/utils/evmenu.py b/evennia/utils/evmenu.py
--- a/evennia/utils/evmenu.py
+++ b/evennia/utils/evmenu.py
@@ -918,6 +918,8 @@ def goto(self, nodename_or_callable, raw_string, **kwargs):
         # helptext can also be a dict, which allows for tooltip command-text (key-value) or
         # ((key,aliases)-value) pairs.
 
+        # make sure helptext is defined
+        helptext = ""       
         if is_iter(nodetext):
             nodetext, *helptext = nodetext
             helptext = helptext[0] if helptext else ""


Test patch:
Repository: evennia/evennia

Issue:
[BUG] Ajax portal error
#### portal error related to Ajax

Reported on Discord by @tgenedavis
This occured after an update over the weekend. 

Portal starting ...
An error has occurred: b"ImportError: \nCould not load typeclass 'evennia.server.portal.webclient.ajax.AjaxWebClient'."
Please look at log file for more information.




Discussion:
~~This might have been fixed with e544b508661531713b5f2495354bf2f93525792d yesterday - waiting on the original error source to confirm what commit they're on~~

Confirmed the error, this happens with the latest commit; that fix doesn't fix it
User reported the following information:

git checkout e8aafa0dae9d54d9d3c79bd4712aa9f86cec6206

Resolving patch:
diff --git a/evennia/settings_default.py b/evennia/settings_default.py
--- a/evennia/settings_default.py
+++ b/evennia/settings_default.py
@@ -1182,7 +1182,7 @@
 # resilient to IP address changes.
 
 # The Ajax Client Class is used to manage all AJAX sessions.
-AJAX_CLIENT_CLASS = "evennia.server.portal.webclient.ajax.AjaxWebClient"
+AJAX_CLIENT_CLASS = "evennia.server.portal.webclient_ajax.AjaxWebClient"
 
 # Ajax Protocol Class is used for all AJAX client connections.
 AJAX_PROTOCOL_CLASS = "evennia.server.portal.webclient_ajax.AjaxWebClientSession"


Test patch:
Repository: evennia/evennia

Issue:
[Feature Request] EvMenu Enhanced Screenreader Support
#### Is your feature request related to a problem? Please describe.
Due to EvMenu's method of assigning various options to multiple columns, Screenreaders do not easily distinguish multiple options when they are on the same line.

#### Describe the solution you'd like
I believe EvMenu should only provide a single column for all options for users using a Screenreader.

#### Describe alternatives you've considered
I'm sure alternatives exist, but I'm not sure what they might be. Maximizing nrows does feel like a dirty fix.



Discussion:
Oh this is a great idea, I'll poke at it.

Resolving patch:
diff --git a/evennia/utils/evmenu.py b/evennia/utils/evmenu.py
--- a/evennia/utils/evmenu.py
+++ b/evennia/utils/evmenu.py
@@ -1206,7 +1206,16 @@ def options_formatter(self, optionlist):
                 else:
                     # add a default white color to key
                     table.append(f" |lc{raw_key}|lt|w{key}|n|le{desc_string}")
-        ncols = _MAX_TEXT_WIDTH // table_width_max  # number of columns
+
+        # check if the caller is using a screenreader
+        screenreader_mode = False
+        if sessions := getattr(self.caller, 'sessions', None):
+            screenreader_mode = any(sess.protocol_flags.get("SCREENREADER") for sess in sessions.all())
+        # the caller doesn't have a session; check it directly
+        elif hasattr(self.caller, 'protocol_flags'):
+            screenreader_mode = self.caller.protocol_flags.get("SCREENREADER")
+
+        ncols = 1 if screenreader_mode else _MAX_TEXT_WIDTH // table_width_max
 
         if ncols < 0:
             # no visible options at all


Test patch: