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

Issue:
set resolve_lines and resolve_blocks to True
## 🐛 Bug

As discussed in #512 it needs an improvement for the `sort_boxes ` to set the `resolve_lines` and `resolve_blocks` in `builder.py `to True as default

In fact of this the `.render()` and `.export_as_xml()` results are not correct 

## To Reproduce

Steps to reproduce the behavior:

1. test with any document image which has multible text blocks/lines or where the document is slightly crooked in the picture, for example photographed by a mobile phone

## Expected behavior

Correct sorted boxes left-right / top-bottom that the lines and blocks can be resolved correctly

## Environment

-DocTR version: 0.4.1a0
-TensorFlow version: N/A
-PyTorch version: 1.9.1 (torchvision 0.10.1)
-OpenCV version: 4.4.0
-OS: Ubuntu 20.04.3 LTS
-Python version: 3.8
-Is CUDA available (TensorFlow): N/A
-Is CUDA available (PyTorch): No
-CUDA runtime version: Could not collect
-GPU models and configuration: Could not collect
-Nvidia driver version: Could not collect
-cuDNN version: Could not collect


Discussion:

Resolving patch:
diff --git a/doctr/models/builder.py b/doctr/models/builder.py
--- a/doctr/models/builder.py
+++ b/doctr/models/builder.py
@@ -26,8 +26,8 @@ class DocumentBuilder(NestedObject):
 
     def __init__(
         self,
-        resolve_lines: bool = False,
-        resolve_blocks: bool = False,
+        resolve_lines: bool = True,
+        resolve_blocks: bool = True,
         paragraph_break: float = 0.035,
         rotated_bbox: bool = False
     ) -> None:
@@ -214,7 +214,7 @@ def _build_blocks(self, boxes: np.ndarray, word_preds: List[Tuple[str, float]])
         if self.resolve_lines:
             lines = self._resolve_lines(boxes[:, :-1])
             # Decide whether we try to form blocks
-            if self.resolve_blocks:
+            if self.resolve_blocks and len(lines) > 1:
                 _blocks = self._resolve_blocks(boxes[:, :-1], lines)
             else:
                 _blocks = [lines]


Test patch:
diff --git a/test/common/test_models_builder.py b/test/common/test_models_builder.py
--- a/test/common/test_models_builder.py
+++ b/test/common/test_models_builder.py
@@ -11,7 +11,7 @@ def test_documentbuilder():
     num_pages = 2
 
     # Don't resolve lines
-    doc_builder = builder.DocumentBuilder()
+    doc_builder = builder.DocumentBuilder(resolve_lines=False, resolve_blocks=False)
     boxes = np.random.rand(words_per_page, 6)
     boxes[:2] *= boxes[2:4]
Repository: mindee/doctr

Issue:
How to run this github repo on google colab
I want to run this repo on google colab
How can I run this code?


Discussion:
Hi @hammadyounas2008 :wave: 

We're in the middle of adding a few colab tutorials to use docTR! Could you specify what you mean exactly? What would you like to run? a training? or simply using the library? :)

Resolving patch:
diff --git a/docs/source/conf.py b/docs/source/conf.py
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -45,6 +45,8 @@
     'sphinx.ext.autosectionlabel',
     'sphinxemoji.sphinxemoji',  # cf. https://sphinxemojicodes.readthedocs.io/en/stable/
     'sphinx_copybutton',
+    'recommonmark',
+    'sphinx_markdown_tables',
 ]
 
 napoleon_use_ivar = True
@@ -55,7 +57,7 @@
 # List of patterns, relative to source directory, that match files and
 # directories to ignore when looking for source files.
 # This pattern also affects html_static_path and html_extra_path.
-exclude_patterns = [u'_build', 'Thumbs.db', '.DS_Store']
+exclude_patterns = [u'_build', 'Thumbs.db', '.DS_Store', 'notebooks/*.rst']
 
 
 # The name of the Pygments (syntax highlighting) style to use.
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -74,6 +74,8 @@
     "sphinxemoji>=0.1.8",
     "sphinx-copybutton>=0.3.1",
     "docutils<0.18",
+    "recommonmark>=0.7.1",
+    "sphinx-markdown-tables>=0.0.15",
 ]
 
 deps = {b: a for a, b in (re.findall(r"^(([^!=<>]+)(?:[!=<>].*)?$)", x)[0] for x in _deps)}
@@ -142,6 +144,8 @@ def deps_list(*pkgs):
     "sphinxemoji",
     "sphinx-copybutton",
     "docutils",
+    "recommonmark",
+    "sphinx-markdown-tables",
 )
 
 extras["docs"] = extras["all"] + extras["docs_specific"]


Test patch:
Repository: mindee/doctr

Issue:
Text recognition: Split wide crops parameter highly decrease performances
### 🚀 The feature

Fine tune the wide crops splitting method

### Motivation, pitch

Hey!

It's not a bug per se, because my code is running well. But I retrained a text recognition model, and the performances on my test set were very low compared to my validation set (both from the same dataset).

I digged a bit into the code, and noticed thes lines:
```
remapped = False
if self.split_wide_crops:
    new_crops, crop_map, remapped = split_crops(crops, self.critical_ar, self.target_ar, self.dil_factor)
    if remapped:
        crops = new_crops
```

I commented them, and the performances were back to what's expected.

I understand the motivation on this feature, but i noticed that it creates a lot of characters repetition in the output strings.

Example:
"AZZ812ZZF21" -> "AZZ81212ZZF21"

It's behaving as the cut was adding some padding, and some characters are recognized twice, leading to a repetition when reconstructing the final output.

I can send you a few sample data on Mindee's slack community if you need it.


### Alternatives

_No response_

### Additional context

_No response_


Discussion:
Hi @jonathanMindee, it would be great to have samples indeed on the slack community!
Thanks for that!
Hi @charlesmindee: Done on the docTR channel
Coming back to this, should we then change the hyperparams of split/merge of crops to close this issue?
As it turns out, this doesn't occur on our pretrained crnn. 
I tried a target_ar of 6, it is slightly better so I will open a PR to close this issue.

Resolving patch:
diff --git a/doctr/models/recognition/predictor/pytorch.py b/doctr/models/recognition/predictor/pytorch.py
--- a/doctr/models/recognition/predictor/pytorch.py
+++ b/doctr/models/recognition/predictor/pytorch.py
@@ -38,7 +38,7 @@ def __init__(
         self.split_wide_crops = split_wide_crops
         self.critical_ar = 8  # Critical aspect ratio
         self.dil_factor = 1.4  # Dilation factor to overlap the crops
-        self.target_ar = 4  # Target aspect ratio
+        self.target_ar = 6  # Target aspect ratio
 
     @torch.no_grad()
     def forward(
diff --git a/doctr/models/recognition/predictor/tensorflow.py b/doctr/models/recognition/predictor/tensorflow.py
--- a/doctr/models/recognition/predictor/tensorflow.py
+++ b/doctr/models/recognition/predictor/tensorflow.py
@@ -41,7 +41,7 @@ def __init__(
         self.split_wide_crops = split_wide_crops
         self.critical_ar = 8  # Critical aspect ratio
         self.dil_factor = 1.4  # Dilation factor to overlap the crops
-        self.target_ar = 4  # Target aspect ratio
+        self.target_ar = 6  # Target aspect ratio
 
     def __call__(
         self,


Test patch:
Repository: mindee/doctr

Issue:
Fix encode_string function
### Bug description

Currently there is no check if the single characters are also available in the given vocabulary.
We need a check for this :) 

TODO's:

- [ ] check that in the function and throw a meaningful exception
- [ ] improve the corresponding test 

discussion:
#926 

### Code snippet to reproduce the bug

```python
from doctr.datasets.utils import encode_string
from doctr.datasets import VOCABS

x = encode_string(input_string='abcDÄÜ', vocab=VOCABS['english'])   # Ä and Ü does not exist in vocab
# raises ValueError: substring not found
```

### Error traceback

```
Traceback (most recent call last):
  File "/home/felix/Desktop/doctr/test.py", line 7, in <module>
    x = encode_string(input_string='abcDÄÜ', vocab=VOCABS['english'])   # Ä and Ü does not exist in vocab
  File "/home/felix/Desktop/doctr/doctr/datasets/utils.py", line 75, in encode_string
    return list(map(vocab.index, input_string))  # type: ignore[arg-type]
ValueError: substring not found
```

### Environment

not need :)

### Deep Learning backend

same


Discussion:
Thanks for the issue 🙏 
I'd argue it's a documentation/error message clarity issue rather than a bug (meaning that we don't want the code to stop failing in this snippet)

Resolving patch:
diff --git a/doctr/datasets/utils.py b/doctr/datasets/utils.py
--- a/doctr/datasets/utils.py
+++ b/doctr/datasets/utils.py
@@ -72,7 +72,10 @@ def encode_string(
     Returns:
         A list encoding the input_string"""
 
-    return list(map(vocab.index, input_string))  # type: ignore[arg-type]
+    try:
+        return list(map(vocab.index, input_string))  # type: ignore[arg-type]
+    except ValueError:
+        raise ValueError("some characters cannot be found in 'vocab'")
 
 
 def decode_sequence(


Test patch:
Repository: weni-ai/bothub-engine

Issue:
Next link in pagination broken in production
The links starts with ```https://bothub/```, correct is ```https://bothub.it/```


Discussion:

Resolving patch:
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -7,7 +7,7 @@
 
 setup(
     name='bothub',
-    version='1.7.1',
+    version='1.7.2',
     description='bothub',
     packages=find_packages(),
     install_requires=install_requires,


Test patch:
Repository: weni-ai/bothub-engine

Issue:
Is possible translate example to same language



Discussion:

Resolving patch:
diff --git a/bothub/api/serializers/translate.py b/bothub/api/serializers/translate.py
--- a/bothub/api/serializers/translate.py
+++ b/bothub/api/serializers/translate.py
@@ -9,6 +9,7 @@
 from ..validators import CanContributeInRepositoryTranslatedExampleValidator
 from ..validators import CanContributeInRepositoryExampleValidator
 from ..validators import TranslatedExampleEntitiesValidator
+from ..validators import TranslatedExampleLanguageValidator
 
 
 class RepositoryTranslatedExampleEntitySeralizer(serializers.ModelSerializer):
@@ -95,6 +96,7 @@ class Meta:
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
         self.validators.append(TranslatedExampleEntitiesValidator())
+        self.validators.append(TranslatedExampleLanguageValidator())
 
     original_example = serializers.PrimaryKeyRelatedField(
         queryset=RepositoryExample.objects,
diff --git a/bothub/api/validators.py b/bothub/api/validators.py
--- a/bothub/api/validators.py
+++ b/bothub/api/validators.py
@@ -51,3 +51,11 @@ def __call__(self, attrs):
             list(map(lambda x: x.to_dict, original_example.entities.all())))
         if not entities_valid:
             raise ValidationError({'entities': _('Invalid entities')})
+
+
+class TranslatedExampleLanguageValidator(object):
+    def __call__(self, attrs):
+        original_example = attrs.get('original_example')
+        language = attrs.get('language')
+        if original_example.repository_update.language == language:
+            raise ValidationError({'language': _('Can\'t translate to same language')})


Test patch:
diff --git a/bothub/api/tests/translate.py b/bothub/api/tests/translate.py
--- a/bothub/api/tests/translate.py
+++ b/bothub/api/tests/translate.py
@@ -163,6 +163,22 @@ def test_entities_no_valid(self):
             len(content_data.get('entities')),
             1)
 
+    def test_can_not_translate_to_same_language(self):
+        response, content_data = self.request(
+            {
+                'original_example': self.example.id,
+                'language': self.example.repository_update.language,
+                'text': 'oi',
+                'entities': [],
+            },
+            self.owner_token)
+        self.assertEqual(
+            response.status_code,
+            status.HTTP_400_BAD_REQUEST)
+        self.assertIn(
+            'language',
+            content_data.keys())
+
 
 class RepositoryTranslatedExampleRetrieveTestCase(TestCase):
     def setUp(self):
Repository: weni-ai/bothub-engine

Issue:
Is possible translate example to same language



Discussion:

Resolving patch:
diff --git a/bothub/api/serializers/translate.py b/bothub/api/serializers/translate.py
--- a/bothub/api/serializers/translate.py
+++ b/bothub/api/serializers/translate.py
@@ -9,6 +9,7 @@
 from ..validators import CanContributeInRepositoryTranslatedExampleValidator
 from ..validators import CanContributeInRepositoryExampleValidator
 from ..validators import TranslatedExampleEntitiesValidator
+from ..validators import TranslatedExampleLanguageValidator
 
 
 class RepositoryTranslatedExampleEntitySeralizer(serializers.ModelSerializer):
@@ -95,6 +96,7 @@ class Meta:
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
         self.validators.append(TranslatedExampleEntitiesValidator())
+        self.validators.append(TranslatedExampleLanguageValidator())
 
     original_example = serializers.PrimaryKeyRelatedField(
         queryset=RepositoryExample.objects,
diff --git a/bothub/api/validators.py b/bothub/api/validators.py
--- a/bothub/api/validators.py
+++ b/bothub/api/validators.py
@@ -51,3 +51,11 @@ def __call__(self, attrs):
             list(map(lambda x: x.to_dict, original_example.entities.all())))
         if not entities_valid:
             raise ValidationError({'entities': _('Invalid entities')})
+
+
+class TranslatedExampleLanguageValidator(object):
+    def __call__(self, attrs):
+        original_example = attrs.get('original_example')
+        language = attrs.get('language')
+        if original_example.repository_update.language == language:
+            raise ValidationError({'language': _('Can\'t translate to same language')})
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -7,7 +7,7 @@
 
 setup(
     name='bothub',
-    version='1.7.2',
+    version='1.7.3',
     description='bothub',
     packages=find_packages(),
     install_requires=install_requires,


Test patch:
diff --git a/bothub/api/tests/translate.py b/bothub/api/tests/translate.py
--- a/bothub/api/tests/translate.py
+++ b/bothub/api/tests/translate.py
@@ -163,6 +163,22 @@ def test_entities_no_valid(self):
             len(content_data.get('entities')),
             1)
 
+    def test_can_not_translate_to_same_language(self):
+        response, content_data = self.request(
+            {
+                'original_example': self.example.id,
+                'language': self.example.repository_update.language,
+                'text': 'oi',
+                'entities': [],
+            },
+            self.owner_token)
+        self.assertEqual(
+            response.status_code,
+            status.HTTP_400_BAD_REQUEST)
+        self.assertIn(
+            'language',
+            content_data.keys())
+
 
 class RepositoryTranslatedExampleRetrieveTestCase(TestCase):
     def setUp(self):
Repository: weni-ai/bothub-engine

Issue:
Forbidden analyze text in public repository



Discussion:
"Analyze text" use POST method, the validators assume it as write action and block the request.

Fix here:
https://github.com/push-flow/bothub/blob/master/bothub/api/views.py#L282

Resolving patch:
diff --git a/bothub/api/views.py b/bothub/api/views.py
--- a/bothub/api/views.py
+++ b/bothub/api/views.py
@@ -352,7 +352,8 @@ def train(self, request, **kwargs):
 
     @detail_route(
         methods=['POST'],
-        url_name='repository-analyze')
+        url_name='repository-analyze',
+        permission_classes=[])
     def analyze(self, request, **kwargs):
         repository = self.get_object()
         user_authorization = repository.get_user_authorization(request.user)
@@ -369,12 +370,9 @@ def analyze(self, request, **kwargs):
             except Exception:
                 pass
             raise APIException(  # pragma: no cover
-                {
-                    'status_code': request.status_code,
-                    'response': response,
-                },
+                response,
                 code=request.status_code)
-        return Response(request.json())  # pragma: no cover
+        return Response(response)  # pragma: no cover
 
     def get_serializer_class(self):
         if self.request and self.request.method in \


Test patch:
diff --git a/bothub/api/tests/repository.py b/bothub/api/tests/repository.py
--- a/bothub/api/tests/repository.py
+++ b/bothub/api/tests/repository.py
@@ -525,6 +525,12 @@ def setUp(self):
             name='Testing',
             slug='test',
             language=languages.LANGUAGE_EN)
+        self.private_repository = Repository.objects.create(
+            owner=self.owner,
+            name='Testing',
+            slug='private',
+            language=languages.LANGUAGE_EN,
+            is_private=True)
 
     def request(self, repository, token, data):
         authorization_header = {
@@ -536,14 +542,17 @@ def request(self, repository, token, data):
                 repository.slug),
             data,
             **authorization_header)
-        response = RepositoryViewSet.as_view({'post': 'analyze'})(request)
+        response = RepositoryViewSet.as_view({'post': 'analyze'})(
+            request,
+            owner__nickname=repository.owner.nickname,
+            slug=repository.slug)
         response.render()
         content_data = json.loads(response.content)
         return (response, content_data,)
 
-    def test_permission_denied(self):
+    def test_permission_denied_in_private_repository(self):
         response, content_data = self.request(
-            self.repository,
+            self.private_repository,
             self.user_token,
             {
                 'language': 'en',
Repository: weni-ai/bothub-engine

Issue:
Forbidden analyze text in public repository



Discussion:
"Analyze text" use POST method, the validators assume it as write action and block the request.

Fix here:
https://github.com/push-flow/bothub/blob/master/bothub/api/views.py#L282

Resolving patch:
diff --git a/bothub/api/views.py b/bothub/api/views.py
--- a/bothub/api/views.py
+++ b/bothub/api/views.py
@@ -352,7 +352,8 @@ def train(self, request, **kwargs):
 
     @detail_route(
         methods=['POST'],
-        url_name='repository-analyze')
+        url_name='repository-analyze',
+        permission_classes=[])
     def analyze(self, request, **kwargs):
         repository = self.get_object()
         user_authorization = repository.get_user_authorization(request.user)
@@ -369,12 +370,9 @@ def analyze(self, request, **kwargs):
             except Exception:
                 pass
             raise APIException(  # pragma: no cover
-                {
-                    'status_code': request.status_code,
-                    'response': response,
-                },
+                response,
                 code=request.status_code)
-        return Response(request.json())  # pragma: no cover
+        return Response(response)  # pragma: no cover
 
     def get_serializer_class(self):
         if self.request and self.request.method in \
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -7,7 +7,7 @@
 
 setup(
     name='bothub',
-    version='1.7.4',
+    version='1.7.5',
     description='bothub',
     packages=find_packages(),
     install_requires=install_requires,


Test patch:
diff --git a/bothub/api/tests/repository.py b/bothub/api/tests/repository.py
--- a/bothub/api/tests/repository.py
+++ b/bothub/api/tests/repository.py
@@ -525,6 +525,12 @@ def setUp(self):
             name='Testing',
             slug='test',
             language=languages.LANGUAGE_EN)
+        self.private_repository = Repository.objects.create(
+            owner=self.owner,
+            name='Testing',
+            slug='private',
+            language=languages.LANGUAGE_EN,
+            is_private=True)
 
     def request(self, repository, token, data):
         authorization_header = {
@@ -536,14 +542,17 @@ def request(self, repository, token, data):
                 repository.slug),
             data,
             **authorization_header)
-        response = RepositoryViewSet.as_view({'post': 'analyze'})(request)
+        response = RepositoryViewSet.as_view({'post': 'analyze'})(
+            request,
+            owner__nickname=repository.owner.nickname,
+            slug=repository.slug)
         response.render()
         content_data = json.loads(response.content)
         return (response, content_data,)
 
-    def test_permission_denied(self):
+    def test_permission_denied_in_private_repository(self):
         response, content_data = self.request(
-            self.repository,
+            self.private_repository,
             self.user_token,
             {
                 'language': 'en',
Repository: weni-ai/bothub-engine

Issue:
Example retrieve need user authenticated
AnonUser can't retireve example infos.


Discussion:

Resolving patch:
diff --git a/bothub/api/views.py b/bothub/api/views.py
--- a/bothub/api/views.py
+++ b/bothub/api/views.py
@@ -453,7 +453,6 @@ class RepositoryExampleViewSet(
     queryset = RepositoryExample.objects
     serializer_class = RepositoryExampleSerializer
     permission_classes = [
-        permissions.IsAuthenticated,
         RepositoryExamplePermission,
     ]
 


Test patch:
Repository: weni-ai/bothub-engine

Issue:
Example retrieve need user authenticated
AnonUser can't retireve example infos.


Discussion:

Resolving patch:
diff --git a/bothub/api/views.py b/bothub/api/views.py
--- a/bothub/api/views.py
+++ b/bothub/api/views.py
@@ -453,7 +453,6 @@ class RepositoryExampleViewSet(
     queryset = RepositoryExample.objects
     serializer_class = RepositoryExampleSerializer
     permission_classes = [
-        permissions.IsAuthenticated,
         RepositoryExamplePermission,
     ]
 
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -7,7 +7,7 @@
 
 setup(
     name='bothub',
-    version='1.8.0',
+    version='1.8.1',
     description='bothub',
     packages=find_packages(),
     install_requires=install_requires,


Test patch: