update Client to v 1.2.1, add fetchAnnotations() function

Change-Id: I8576ccc4ac7ea361a26f09c87ecbd381cffd7e26
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8bc6a0c..d810f1b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
 # Version history
 
+## 1.2.1
+
+- Updates recommended RKorAPClient version to 1.2.1
+- fetchAnnotations() method added to KorAPQuery class, to fetch annotations for all collected matches
+
 ## 1.1.0
 
 - Updates recommended RKorAPClient version to 1.1.0
diff --git a/KorAPClient/__init__.py b/KorAPClient/__init__.py
index 3392209..398858c 100644
--- a/KorAPClient/__init__.py
+++ b/KorAPClient/__init__.py
@@ -16,7 +16,7 @@
 from packaging import version
 from rpy2.robjects.methods import RS4
 
-CURRENT_R_PACKAGE_VERSION = "1.1.0"
+CURRENT_R_PACKAGE_VERSION = "1.2.1"
 
 KorAPClient = packages.importr('RKorAPClient')
 if version.parse(KorAPClient.__version__) < version.parse(CURRENT_R_PACKAGE_VERSION):
@@ -395,3 +395,48 @@
         super().__init__(res)
         return self
 
+    def fetchAnnotations(self, *args, **kwargs):
+            """Fetches and parses linguistic annotations for the collected matches.
+
+            This method enriches the `collectedMatches` DataFrame with additional columns
+            containing linguistic annotations like lemma, part-of-speech (POS), and
+            morphology for each token in the match and its context.
+
+            Args:
+                foundry (str, optional): The foundry (annotation layer) to fetch.
+                                        Defaults to "tt" (TreeTagger).
+                overwrite (bool, optional): If True, existing annotation columns will be
+                                            overwritten. Defaults to False.
+                verbose (bool, optional): If True, prints progress information. Defaults
+                                        to the verbosity setting of the
+                                        KorAPConnection object.
+                *args: Positional arguments passed to the underlying R function.
+                **kwargs: Keyword arguments passed to the underlying R function.
+
+            Returns:
+                KorAPQuery: A new KorAPQuery object with the `collectedMatches` DataFrame
+                            updated to include the fetched annotations.
+
+            Example:
+                ```
+                from KorAPClient import KorAPConnection
+
+                # Authentication might be required for snippets and annotations
+                kcon = KorAPConnection(verbose=True).auth()
+
+                # Perform a query and fetch all matches
+                q = kcon.corpusQuery("Ameisenplage", metadataOnly=False).fetchAll()
+
+                # Fetch annotations for the matches
+                q_annotated = q.fetchAnnotations()
+
+                # Display the collected matches with new annotation columns
+                print(q_annotated.slots['collectedMatches'][['snippet', 'lemma.left', 'lemma.match', 'lemma.right']].head())
+                ```
+            """
+            res = KorAPClient.fetchAnnotations(self, *args, **kwargs)
+            with localconverter(fix_lists_in_dataframes):
+                df = res.slots['collectedMatches']
+            res.slots['collectedMatches'] = df
+            super().__init__(res)
+            return self
\ No newline at end of file
diff --git a/Readme.md b/Readme.md
index d5d366a..553e393 100644
--- a/Readme.md
+++ b/Readme.md
@@ -157,6 +157,25 @@
   python -m KorAPClient -v --query "Hello World" "Hallo Welt" --vc "pubDate in 2017" "pubDate in 2018" "pubDate in 2019"
 ```
 
+### Querying and fetching annotations
+To fetch the annotations for all matches in a KorAPQuery object, use the fetchAnnotations() method (defaults to "tt" (TreeTagger) as foundry):
+```python
+from KorAPClient import KorAPConnection
+
+# Authentication might be required for snippets and annotations
+kcon = KorAPConnection(verbose=True).auth()
+
+# Perform a query and fetch all matches
+q = kcon.corpusQuery("Ameisenplage", metadataOnly=False).fetchAll()
+
+# Fetch annotations for the matches
+q = q.fetchAnnotations()
+
+# Display the collected matches with new annotation columns
+q.slots['collectedMatches'][['snippet', 'lemma.left', 'lemma.match', 'lemma.right']].head()
+```
+The annotations (here: lemmas) are stored in `q.slots['collectedMatches'][['lemma.left', 'lemma.match', 'lemma.right']]`.
+
 ### Accessed API Services
 By using the KorAPClient you agree to the respective terms of use of the accessed KorAP API services which will be printed upon opening a connection.
 
diff --git a/pyproject.toml b/pyproject.toml
index 82af6e1..d48f97f 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
 [project]
 name = "KorAPClient"
-version = "1.1.0"
+version = "1.2.1"
 description = "Client package to access KorAP's web service API"
 authors = [
     {name = "Marc Kupietz",email = "kupietz@ids-mannheim.de"},