Repository: qiskit-community/ecosystem (python)

Issue:
Submission: implement python parser for template
<!-- ⚠️ If you do not respect this template, your issue will be closed -->
<!-- ⚠️ Make sure to browse the opened and closed issues to confirm this idea does not exist. -->

### What is the expected behavior?

Submission for membership in ecosystem is handled through github issues. Specifically using[ submission template](https://github.com/qiskit-community/ecosystem/blob/main/.github/ISSUE_TEMPLATE/submission.yml). 
In order to make use of information inside issue we need to implement a parser, which will extract all necessary information. 
Later on we will use this information in CI processes and save it to json db

A.k.a we need to implement function:
```python
def parse_submission_issue(body_of_issue: str) -> Repository:
    """Parses body of issue and creates Repository object."""
    ...
```


**Related story:**  as community member of ecosystem I want to be able to submit my project so that it would be included into ecosystem

**Epic** #9 

Pull request description:
Submission: implement python parser for template
### Summary
Add parser script for submission form.

- [x] parse
- [x] test


Closes #10 

Patch:
diff --git a/.pylintrc b/.pylintrc
index e54adeb..304f3e1 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -588,7 +588,7 @@ valid-metaclass-classmethod-first-arg=cls
 max-args=20
 
 # Maximum number of attributes for a class (see R0902).
-max-attributes=12
+max-attributes=13
 
 # Maximum number of boolean expressions in an if statement (see R0916).
 max-bool-expr=5
diff --git a/ecosystem/entities.py b/ecosystem/entities.py
index 95e4b41..5fdd655 100644
--- a/ecosystem/entities.py
+++ b/ecosystem/entities.py
@@ -101,6 +101,7 @@ class Repository(JsonSerializable):
                  licence: str,
                  contact_info: Optional[str] = None,
                  alternatives: Optional[str] = None,
+                 affiliations: Optional[str] = None,
                  labels: Optional[List[str]] = None,
                  created_at: Optional[int] = None,
                  updated_at: Optional[int] = None,
@@ -115,6 +116,7 @@ class Repository(JsonSerializable):
             licence: licence
             contact_info: contact information
             alternatives: alternatives to project
+            affiliations : affiliations of the project
             labels: labels
             created_at: creation date
             updated_at: update date
@@ -126,6 +128,7 @@ class Repository(JsonSerializable):
         self.licence = licence
         self.contact_info = contact_info
         self.alternatives = alternatives
+        self.affiliations = affiliations
         self.labels = labels if labels is not None else []
         self.created_at = created_at if created_at is not None else datetime.now().timestamp()
         self.updated_at = updated_at if updated_at is not None else datetime.now().timestamp()
diff --git a/ecosystem/manager.py b/ecosystem/manager.py
index d2ee67a..0ac05ee 100644
--- a/ecosystem/manager.py
+++ b/ecosystem/manager.py
@@ -1,15 +1,38 @@
 """Manager class for controlling all CLI functions."""
 import os
+import re
 from typing import Optional, List
 
 from jinja2 import Environment, PackageLoader, select_autoescape
 
 from .controller import Controller
 from .controllers.runner import PythonRunner
-from .entities import Tier, TestType, TestResult
+from .entities import Tier, TestType, TestResult, Repository
 from .utils import logger
 
 
+def parse_submission_issue(body_of_issue: str) -> Repository:
+    """Parse issue body."""
+
+    parse = re.findall(r'^([\s\S]*?)(?:\n{2,}|\Z)', body_of_issue, re.M)
+
+    repo_name = parse[1].split("/")
+
+    name = repo_name[-1]
+    url = parse[1]
+    description = parse[3]
+    contact_info = parse[5]
+    alternatives = parse[7]
+    licence = parse[9]
+    affiliations = parse[11]
+
+    labels = re.findall(r"([\w\]+)([\w\-\_]+)", parse[13])
+
+    repo = Repository(name, url, description, licence,
+                      contact_info, alternatives, affiliations, labels)
+    return repo
+
+
 class Manager:
     """Manager class.
     Entrypoint for all CLI commands.


Test patch:
diff --git a/tests/ressources/issue.md b/tests/ressources/issue.md
new file mode 100644
index 0000000..b570147
--- /dev/null
+++ b/tests/ressources/issue.md
@@ -0,0 +1,27 @@
+### Github repo
+
+http://github.com/awesome/awesome
+
+### Description
+
+An awesome repo for awesome project
+
+### Email
+
+toto@gege.com
+
+### Alternatives
+
+tititata
+
+### License
+
+Apache License 2.0
+
+### Affiliations
+
+_No response_
+
+### Tags
+
+tool, tutorial
diff --git a/tests/test_manager.py b/tests/test_manager.py
new file mode 100644
index 0000000..d4e0864
--- /dev/null
+++ b/tests/test_manager.py
@@ -0,0 +1,26 @@
+"""Tests for manager."""
+from unittest import TestCase
+from ecosystem.entities import Repository
+from ecosystem.manager import parse_submission_issue
+
+
+class TestManager(TestCase):
+    """Test class for manager functions."""
+
+    def setUp(self) -> None:
+        with open("tests/ressources/issue.md", "r") as issue_body_file:
+            self.issue_body = issue_body_file.read()
+
+    def test_issue_parsing(self):
+        """"Tests issue parsing function"""
+        parsed_result = parse_submission_issue(self.issue_body)
+
+        self.assertTrue(isinstance(parsed_result, Repository))
+        self.assertEqual(parsed_result.name, "awesome")
+        self.assertEqual(parsed_result.url, "http://github.com/awesome/awesome")
+        self.assertEqual(parsed_result.description, "An awesome repo for awesome project")
+        self.assertEqual(parsed_result.contact_info, "toto@gege.com")
+        self.assertEqual(parsed_result.alternatives, "tititata")
+        self.assertEqual(parsed_result.licence, "Apache License 2.0")
+        self.assertEqual(parsed_result.affiliations, "_No response_")
+        self.assertEqual(parsed_result.labels, ["tool", "tutorial"])