Northy1717/SWE-bench-Live huggingface dataset:
Repository: aiogram/aiogram

Issue:
Wrong markdown v2 custom emoji parsing
### Checklist

- [X] I am sure the error is coming from aiogram code
- [X] I have searched in the issue tracker for similar bug reports, including closed ones

### Operating system

Windows 11

### Python version

3.11

### aiogram version

3.3.0

### Expected behavior

Custom emoji entity starts with '!' character like discribed in telegram [markdownv2 documentation](https://core.telegram.org/bots/api#markdownv2-style)

### Current behavior

Wrong parsing of custom emoji entity in message.md_text property. Missing '!' in start of custom emoji entity
![image](https://github.com/aiogram/aiogram/assets/101830798/17ba64e3-4473-44a5-a3e8-6d7a3ab6d402)


### Steps to reproduce

1. Send message text with custom emoji
2. Get message.md_text parameter
3. It's missing '!' character in start of entity. 

### Code example

_No response_

### Logs

_No response_

### Additional information

_No response_


Discussion:

Patch:
diff --git a/CHANGES/1496.bugfix.rst b/CHANGES/1496.bugfix.rst
new file mode 100644
index 0000000000..02d44dbf30
--- /dev/null
+++ b/CHANGES/1496.bugfix.rst
@@ -0,0 +1,1 @@
+Fixed wrong :code:`MarkdownV2` custom emoji parsing in :code:`aiogram.utils.text_decorations`
diff --git a/aiogram/utils/text_decorations.py b/aiogram/utils/text_decorations.py
index 58d6c0f4aa..ae6227d3f4 100644
--- a/aiogram/utils/text_decorations.py
+++ b/aiogram/utils/text_decorations.py
@@ -253,7 +253,7 @@ def quote(self, value: str) -> str:
         return re.sub(pattern=self.MARKDOWN_QUOTE_PATTERN, repl=r"\\\1", string=value)
 
     def custom_emoji(self, value: str, custom_emoji_id: str) -> str:
-        return self.link(value=value, link=f"tg://emoji?id={custom_emoji_id}")
+        return f'!{self.link(value=value, link=f"tg://emoji?id={custom_emoji_id}")}'
 
     def blockquote(self, value: str) -> str:
         return "\n".join(f">{line}" for line in value.splitlines())


Test patch:
diff --git a/tests/test_utils/test_text_decorations.py b/tests/test_utils/test_text_decorations.py
index 6a177ab3cb..2696f07831 100644
--- a/tests/test_utils/test_text_decorations.py
+++ b/tests/test_utils/test_text_decorations.py
@@ -99,7 +99,7 @@ class TestTextDecoration:
             [
                 markdown_decoration,
                 MessageEntity(type="custom_emoji", offset=0, length=5, custom_emoji_id="42"),
-                "[test](tg://emoji?id=42)",
+                "![test](tg://emoji?id=42)",
             ],
             [
                 markdown_decoration,
Repository: stanfordnlp/dspy

Issue:
Signature indentation
If there is an intendation in the docstring/signature, indentations will not be removed like they are when processing docstrings. 

For example:
```python3
import dspy
class SignatureExample(dspy.Signature):
    """Im not indented.
    I am indented.
    """

if __name__ == '__main__':
    print(SignatureExample.__doc__)
```
This produces:
```
Im not indented.
    I am indented.
```

However, Python convention would suggest common indents are removed (https://peps.python.org/pep-0257/):

> Docstring processing tools will strip a uniform amount of indentation from the second and further lines of the docstring, equal to the minimum indentation of all non-blank lines after the first line. Any indentation in the first line of the docstring (i.e., up to the first newline) is insignificant and removed. Relative indentation of later lines in the docstring is retained. Blank lines should be removed from the beginning and end of the docstring.

I'll add a PR.


Discussion:

Patch:
diff --git a/dspy/signatures/signature.py b/dspy/signatures/signature.py
index d10f71718c..3ad35c31b2 100644
--- a/dspy/signatures/signature.py
+++ b/dspy/signatures/signature.py
@@ -1,4 +1,5 @@
 import ast
+import inspect
 import re
 import types
 import typing
@@ -88,7 +89,7 @@ def signature(cls) -> str:
 
     @property
     def instructions(cls) -> str:
-        return getattr(cls, "__doc__", "")
+        return inspect.cleandoc(getattr(cls, "__doc__", ""))
 
     def with_instructions(cls, instructions: str) -> Type["Signature"]:
         return Signature(cls.fields, instructions)
@@ -217,9 +218,9 @@ def ensure_signature(signature: Union[str, Type[Signature]], instructions=None)
 
 
 def make_signature(
-    signature: Union[str, Dict[str, Tuple[type, FieldInfo]]],
-    instructions: str = None,
-    signature_name: str = "StringSignature",
+        signature: Union[str, Dict[str, Tuple[type, FieldInfo]]],
+        instructions: str = None,
+        signature_name: str = "StringSignature",
 ) -> Type[Signature]:
     """Create a new Signature type with the given fields and instructions.
 


Test patch:
diff --git a/tests/signatures/test_signature.py b/tests/signatures/test_signature.py
index d0eb899d13..e635455b91 100644
--- a/tests/signatures/test_signature.py
+++ b/tests/signatures/test_signature.py
@@ -183,7 +183,8 @@ class SubSignature(Signature):
 def test_multiline_instructions():
     class MySignature(Signature):
         """First line
-        Second line"""
+        Second line
+            Third line"""
 
         output = OutputField()
 
@@ -195,7 +196,8 @@ class MySignature(Signature):
 
     assert lm.get_convo(-1) == textwrap.dedent("""\
         First line
-                Second line
+        Second line
+            Third line
         
         ---
Repository: instructlab/instructlab

Issue:
Could not copy into data directory: list index out of range
Initially I thought it's a dup of https://github.com/instructlab/instructlab/issues/608, but I got fewer errors:

```
(venv) ➜  instructlab git:(stable) ilab train
Could not copy into data directory: list index out of range
```

My computer is Apple M1 Pro with 14.4.1 (23E224)


Discussion:
Did you run `ilab generate` first? The error message should be clearer btw.



Patch:
diff --git a/src/instructlab/lab.py b/src/instructlab/lab.py
index 2e56ac09f4..f5868962e1 100644
--- a/src/instructlab/lab.py
+++ b/src/instructlab/lab.py
@@ -924,6 +924,13 @@ def train(
             # generated input files reverse sorted by name (contains timestamp)
             train_files = sorted(glob(input_dir + "/train_*"), reverse=True)
             test_files = sorted(glob(input_dir + "/test_*"), reverse=True)
+
+            if not train_files or not test_files:
+                click.secho(
+                    f"{input_dir} does not contain training or test files, did you run `ilab generate`?",
+                    fg="red",
+                )
+                raise click.exceptions.Exit(1)
             if len(train_files) > 1 or len(test_files) > 1:
                 # pylint: disable=f-string-without-interpolation
                 click.secho(
@@ -945,12 +952,6 @@ def train(
                 fg="red",
             )
             raise click.exceptions.Exit(1)
-        except IndexError as exc:
-            click.secho(
-                f"Could not copy into data directory: {exc}",
-                fg="red",
-            )
-            raise click.exceptions.Exit(1)
 
     if not utils.is_macos_with_m_chip():
         # Local


Test patch:
diff --git a/tests/test_lab_train.py b/tests/test_lab_train.py
index 4407e6565d..3feb591c6d 100644
--- a/tests/test_lab_train.py
+++ b/tests/test_lab_train.py
@@ -158,7 +158,7 @@ def test_invalid_taxonomy(self):
             result = runner.invoke(lab.train, ["--input-dir", INPUT_DIR])
             self.assertIsNotNone(result.exception)
             self.assertIn(
-                "Could not copy into data directory: list index out of range",
+                f"{INPUT_DIR} does not contain training or test files, did you run `ilab generate`?",
                 result.output,
             )
             self.assertEqual(result.exit_code, 1)