We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Link in `nf-core modules info` broken
### Description of the bug

The link created by `nf-core modules info` is broken since the move from the github api. The link is set on https://github.com/nf-core/tools/blob/dev/nf_core/modules/info.py#L164-L168, but the `self.remote_location` is either a https or ssh address so the link is broken.

### Command used and terminal output

```console
$ nf-core modules info
```


### System information

nf-core/tools @2.5dev

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `nf_core/modules/info.py`
Content:
```
1 import logging
2 import os
3 
4 import questionary
5 import yaml
6 from rich import box
7 from rich.console import Group
8 from rich.markdown import Markdown
9 from rich.panel import Panel
10 from rich.table import Table
11 from rich.text import Text
12 
13 import nf_core.utils
14 from nf_core.modules.modules_json import ModulesJson
15 
16 from .module_utils import get_repo_type
17 from .modules_command import ModuleCommand
18 from .modules_repo import NF_CORE_MODULES_REMOTE
19 
20 log = logging.getLogger(__name__)
21 
22 
23 class ModuleInfo(ModuleCommand):
24     def __init__(self, pipeline_dir, tool, remote_url, branch, no_pull, base_path):
25         super().__init__(pipeline_dir, remote_url, branch, no_pull, base_path)
26         self.meta = None
27         self.local_path = None
28         self.remote_location = None
29 
30         # Quietly check if this is a pipeline or not
31         if pipeline_dir:
32             try:
33                 pipeline_dir, repo_type = get_repo_type(pipeline_dir, use_prompt=False)
34                 log.debug(f"Found {repo_type} repo: {pipeline_dir}")
35             except UserWarning as e:
36                 log.debug(f"Only showing remote info: {e}")
37                 pipeline_dir = None
38 
39         if self.repo_type == "pipeline":
40             self.modules_json = ModulesJson(self.dir)
41             self.modules_json.check_up_to_date()
42         else:
43             self.modules_json = None
44         self.module = self.init_mod_name(tool)
45 
46     def init_mod_name(self, module):
47         """
48         Makes sure that we have a module name before proceeding.
49 
50         Args:
51             module: str: Module name to check
52         """
53         if module is None:
54             local = questionary.confirm(
55                 "Is the module locally installed?", style=nf_core.utils.nfcore_question_style
56             ).unsafe_ask()
57             if local:
58                 if self.repo_type == "modules":
59                     modules = self.get_modules_clone_modules()
60                 else:
61                     modules = self.modules_json.get_all_modules().get(self.modules_repo.fullname)
62                     if modules is None:
63                         raise UserWarning(f"No modules installed from '{self.modules_repo.remote_url}'")
64             else:
65                 modules = self.modules_repo.get_avail_modules()
66             module = questionary.autocomplete(
67                 "Please select a module", choices=modules, style=nf_core.utils.nfcore_question_style
68             ).unsafe_ask()
69             while module not in modules:
70                 log.info(f"'{module}' is not a valid module name")
71                 module = questionary.autocomplete(
72                     "Please select a new module", choices=modules, style=nf_core.utils.nfcore_question_style
73                 ).unsafe_ask()
74 
75         return module
76 
77     def get_module_info(self):
78         """Given the name of a module, parse meta.yml and print usage help."""
79 
80         # Running with a local install, try to find the local meta
81         if self.dir:
82             self.meta = self.get_local_yaml()
83 
84         # Either failed locally or in remote mode
85         if not self.meta:
86             self.meta = self.get_remote_yaml()
87 
88         # Could not find the meta
89         if self.meta is False:
90             raise UserWarning(f"Could not find module '{self.module}'")
91 
92         return self.generate_module_info_help()
93 
94     def get_local_yaml(self):
95         """Attempt to get the meta.yml file from a locally installed module.
96 
97         Returns:
98             dict or bool: Parsed meta.yml found, False otherwise
99         """
100 
101         if self.repo_type == "pipeline":
102             # Try to find and load the meta.yml file
103             repo_name = self.modules_repo.fullname
104             module_base_path = os.path.join(self.dir, "modules", repo_name)
105             # Check that we have any modules installed from this repo
106             modules = self.modules_json.get_all_modules().get(repo_name)
107             if modules is None:
108                 raise LookupError(f"No modules installed from {self.modules_repo.remote_url}")
109 
110             if self.module in modules:
111                 mod_dir = os.path.join(module_base_path, self.module)
112                 meta_fn = os.path.join(mod_dir, "meta.yml")
113                 if os.path.exists(meta_fn):
114                     log.debug(f"Found local file: {meta_fn}")
115                     with open(meta_fn, "r") as fh:
116                         self.local_path = mod_dir
117                         return yaml.safe_load(fh)
118 
119             log.debug(f"Module '{self.module}' meta.yml not found locally")
120         else:
121             module_base_path = os.path.join(self.dir, "modules")
122             if self.module in os.listdir(module_base_path):
123                 mod_dir = os.path.join(module_base_path, self.module)
124                 meta_fn = os.path.join(mod_dir, "meta.yml")
125                 if os.path.exists(meta_fn):
126                     log.debug(f"Found local file: {meta_fn}")
127                     with open(meta_fn, "r") as fh:
128                         self.local_path = mod_dir
129                         return yaml.safe_load(fh)
130             log.debug(f"Module '{self.module}' meta.yml not found locally")
131 
132         return None
133 
134     def get_remote_yaml(self):
135         """Attempt to get the meta.yml file from a remote repo.
136 
137         Returns:
138             dict or bool: Parsed meta.yml found, False otherwise
139         """
140         # Check if our requested module is there
141         if self.module not in self.modules_repo.get_avail_modules():
142             return False
143 
144         file_contents = self.modules_repo.get_meta_yml(self.module)
145         if file_contents is None:
146             return False
147         self.remote_location = self.modules_repo.remote_url
148         return yaml.safe_load(file_contents)
149 
150     def generate_module_info_help(self):
151         """Take the parsed meta.yml and generate rich help.
152 
153         Returns:
154             rich renderable
155         """
156 
157         renderables = []
158 
159         # Intro panel
160         intro_text = Text()
161         if self.local_path:
162             intro_text.append(Text.from_markup(f"Location: [blue]{self.local_path}\n"))
163         elif self.remote_location:
164             intro_text.append(
165                 Text.from_markup(
166                     f":globe_with_meridians: Repository: [link=https://github.com/{self.remote_location}]{self.remote_location}[/]\n"
167                 )
168             )
169 
170         if self.meta.get("tools"):
171             tools_strings = []
172             for tool in self.meta["tools"]:
173                 for tool_name, tool_meta in tool.items():
174                     if "homepage" in tool_meta:
175                         tools_strings.append(f"[link={tool_meta['homepage']}]{tool_name}[/link]")
176                     else:
177                         tools_strings.append(f"{tool_name}")
178             intro_text.append(Text.from_markup(f":wrench: Tools: {', '.join(tools_strings)}\n", style="dim"))
179 
180         if self.meta.get("description"):
181             intro_text.append(Text.from_markup(f":book: Description: {self.meta['description']}", style="dim"))
182 
183         renderables.append(
184             Panel(
185                 intro_text,
186                 title=f"[bold]Module: [green]{self.module}\n",
187                 title_align="left",
188             )
189         )
190 
191         # Inputs
192         if self.meta.get("input"):
193             inputs_table = Table(expand=True, show_lines=True, box=box.MINIMAL_HEAVY_HEAD, padding=0)
194             inputs_table.add_column(":inbox_tray: Inputs")
195             inputs_table.add_column("Description")
196             inputs_table.add_column("Pattern", justify="right", style="green")
197             for input in self.meta["input"]:
198                 for key, info in input.items():
199                     inputs_table.add_row(
200                         f"[orange1 on black] {key} [/][dim i] ({info['type']})",
201                         Markdown(info["description"] if info["description"] else ""),
202                         info.get("pattern", ""),
203                     )
204 
205             renderables.append(inputs_table)
206 
207         # Outputs
208         if self.meta.get("output"):
209             outputs_table = Table(expand=True, show_lines=True, box=box.MINIMAL_HEAVY_HEAD, padding=0)
210             outputs_table.add_column(":outbox_tray: Outputs")
211             outputs_table.add_column("Description")
212             outputs_table.add_column("Pattern", justify="right", style="green")
213             for output in self.meta["output"]:
214                 for key, info in output.items():
215                     outputs_table.add_row(
216                         f"[orange1 on black] {key} [/][dim i] ({info['type']})",
217                         Markdown(info["description"] if info["description"] else ""),
218                         info.get("pattern", ""),
219                     )
220 
221             renderables.append(outputs_table)
222 
223         # Installation command
224         if self.remote_location:
225             cmd_base = "nf-core modules"
226             if self.remote_location != NF_CORE_MODULES_REMOTE:
227                 cmd_base = f"nf-core modules --git-remote {self.remote_location}"
228             renderables.append(
229                 Text.from_markup(f"\n :computer:  Installation command: [magenta]{cmd_base} install {self.module}\n")
230             )
231 
232         return Group(*renderables)
233
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/nf_core/modules/info.py b/nf_core/modules/info.py
--- a/nf_core/modules/info.py
+++ b/nf_core/modules/info.py
@@ -21,11 +21,46 @@
 
 
 class ModuleInfo(ModuleCommand):
+    """
+    Class to print information of a module.
+
+    Attributes
+    ----------
+    meta : YAML object
+        stores the information from meta.yml file
+    local_path : str
+        path of the local modules
+    remote_location : str
+        remote repository URL
+    local : bool
+        indicates if the module is locally installed or not
+    repo_type : str
+        repository type. Can be either 'pipeline' or 'modules'
+    modules_json : ModulesJson object
+        contains 'modules.json' file information from a pipeline
+    module : str
+        name of the tool to get information from
+
+    Methods
+    -------
+    init_mod_name(module)
+        Makes sure that we have a module name
+    get_module_info()
+        Given the name of a module, parse meta.yml and print usage help
+    get_local_yaml()
+        Attempt to get the meta.yml file from a locally installed module
+    get_remote_yaml()
+        Attempt to get the meta.yml file from a remote repo
+    generate_module_info_help()
+        Take the parsed meta.yml and generate rich help
+    """
+
     def __init__(self, pipeline_dir, tool, remote_url, branch, no_pull, base_path):
         super().__init__(pipeline_dir, remote_url, branch, no_pull, base_path)
         self.meta = None
         self.local_path = None
         self.remote_location = None
+        self.local = None
 
         # Quietly check if this is a pipeline or not
         if pipeline_dir:
@@ -51,10 +86,10 @@
             module: str: Module name to check
         """
         if module is None:
-            local = questionary.confirm(
+            self.local = questionary.confirm(
                 "Is the module locally installed?", style=nf_core.utils.nfcore_question_style
             ).unsafe_ask()
-            if local:
+            if self.local:
                 if self.repo_type == "modules":
                     modules = self.get_modules_clone_modules()
                 else:
@@ -78,7 +113,7 @@
         """Given the name of a module, parse meta.yml and print usage help."""
 
         # Running with a local install, try to find the local meta
-        if self.dir:
+        if self.local:
             self.meta = self.get_local_yaml()
 
         # Either failed locally or in remote mode
@@ -163,7 +198,11 @@
         elif self.remote_location:
             intro_text.append(
                 Text.from_markup(
-                    f":globe_with_meridians: Repository: [link=https://github.com/{self.remote_location}]{self.remote_location}[/]\n"
+                    ":globe_with_meridians: Repository: "
+                    f"{ '[link={self.remote_location}]' if self.remote_location.startswith('http') else ''}"
+                    f"{self.remote_location}"
+                    f"{'[/link]' if self.remote_location.startswith('http') else '' }"
+                    "\n"
                 )
             )

{"golden_diff": "diff --git a/nf_core/modules/info.py b/nf_core/modules/info.py\n--- a/nf_core/modules/info.py\n+++ b/nf_core/modules/info.py\n@@ -21,11 +21,46 @@\n \n \n class ModuleInfo(ModuleCommand):\n+    \"\"\"\n+    Class to print information of a module.\n+\n+    Attributes\n+    ----------\n+    meta : YAML object\n+        stores the information from meta.yml file\n+    local_path : str\n+        path of the local modules\n+    remote_location : str\n+        remote repository URL\n+    local : bool\n+        indicates if the module is locally installed or not\n+    repo_type : str\n+        repository type. Can be either 'pipeline' or 'modules'\n+    modules_json : ModulesJson object\n+        contains 'modules.json' file information from a pipeline\n+    module : str\n+        name of the tool to get information from\n+\n+    Methods\n+    -------\n+    init_mod_name(module)\n+        Makes sure that we have a module name\n+    get_module_info()\n+        Given the name of a module, parse meta.yml and print usage help\n+    get_local_yaml()\n+        Attempt to get the meta.yml file from a locally installed module\n+    get_remote_yaml()\n+        Attempt to get the meta.yml file from a remote repo\n+    generate_module_info_help()\n+        Take the parsed meta.yml and generate rich help\n+    \"\"\"\n+\n     def __init__(self, pipeline_dir, tool, remote_url, branch, no_pull, base_path):\n         super().__init__(pipeline_dir, remote_url, branch, no_pull, base_path)\n         self.meta = None\n         self.local_path = None\n         self.remote_location = None\n+        self.local = None\n \n         # Quietly check if this is a pipeline or not\n         if pipeline_dir:\n@@ -51,10 +86,10 @@\n             module: str: Module name to check\n         \"\"\"\n         if module is None:\n-            local = questionary.confirm(\n+            self.local = questionary.confirm(\n                 \"Is the module locally installed?\", style=nf_core.utils.nfcore_question_style\n             ).unsafe_ask()\n-            if local:\n+            if self.local:\n                 if self.repo_type == \"modules\":\n                     modules = self.get_modules_clone_modules()\n                 else:\n@@ -78,7 +113,7 @@\n         \"\"\"Given the name of a module, parse meta.yml and print usage help.\"\"\"\n \n         # Running with a local install, try to find the local meta\n-        if self.dir:\n+        if self.local:\n             self.meta = self.get_local_yaml()\n \n         # Either failed locally or in remote mode\n@@ -163,7 +198,11 @@\n         elif self.remote_location:\n             intro_text.append(\n                 Text.from_markup(\n-                    f\":globe_with_meridians: Repository: [link=https://github.com/{self.remote_location}]{self.remote_location}[/]\\n\"\n+                    \":globe_with_meridians: Repository: \"\n+                    f\"{ '[link={self.remote_location}]' if self.remote_location.startswith('http') else ''}\"\n+                    f\"{self.remote_location}\"\n+                    f\"{'[/link]' if self.remote_location.startswith('http') else '' }\"\n+                    \"\\n\"\n                 )\n             )\n", "issue": "Link in `nf-core modules info` broken\n### Description of the bug\r\n\r\nThe link created by `nf-core modules info` is broken since the move from the github api. The link is set on https://github.com/nf-core/tools/blob/dev/nf_core/modules/info.py#L164-L168, but the `self.remote_location` is either a https or ssh address so the link is broken.\r\n\r\n### Command used and terminal output\r\n\r\n```console\r\n$ nf-core modules info\r\n```\r\n\r\n\r\n### System information\r\n\r\nnf-core/tools @2.5dev\n", "before_files": [{"content": "import logging\nimport os\n\nimport questionary\nimport yaml\nfrom rich import box\nfrom rich.console import Group\nfrom rich.markdown import Markdown\nfrom rich.panel import Panel\nfrom rich.table import Table\nfrom rich.text import Text\n\nimport nf_core.utils\nfrom nf_core.modules.modules_json import ModulesJson\n\nfrom .module_utils import get_repo_type\nfrom .modules_command import ModuleCommand\nfrom .modules_repo import NF_CORE_MODULES_REMOTE\n\nlog = logging.getLogger(__name__)\n\n\nclass ModuleInfo(ModuleCommand):\n    def __init__(self, pipeline_dir, tool, remote_url, branch, no_pull, base_path):\n        super().__init__(pipeline_dir, remote_url, branch, no_pull, base_path)\n        self.meta = None\n        self.local_path = None\n        self.remote_location = None\n\n        # Quietly check if this is a pipeline or not\n        if pipeline_dir:\n            try:\n                pipeline_dir, repo_type = get_repo_type(pipeline_dir, use_prompt=False)\n                log.debug(f\"Found {repo_type} repo: {pipeline_dir}\")\n            except UserWarning as e:\n                log.debug(f\"Only showing remote info: {e}\")\n                pipeline_dir = None\n\n        if self.repo_type == \"pipeline\":\n            self.modules_json = ModulesJson(self.dir)\n            self.modules_json.check_up_to_date()\n        else:\n            self.modules_json = None\n        self.module = self.init_mod_name(tool)\n\n    def init_mod_name(self, module):\n        \"\"\"\n        Makes sure that we have a module name before proceeding.\n\n        Args:\n            module: str: Module name to check\n        \"\"\"\n        if module is None:\n            local = questionary.confirm(\n                \"Is the module locally installed?\", style=nf_core.utils.nfcore_question_style\n            ).unsafe_ask()\n            if local:\n                if self.repo_type == \"modules\":\n                    modules = self.get_modules_clone_modules()\n                else:\n                    modules = self.modules_json.get_all_modules().get(self.modules_repo.fullname)\n                    if modules is None:\n                        raise UserWarning(f\"No modules installed from '{self.modules_repo.remote_url}'\")\n            else:\n                modules = self.modules_repo.get_avail_modules()\n            module = questionary.autocomplete(\n                \"Please select a module\", choices=modules, style=nf_core.utils.nfcore_question_style\n            ).unsafe_ask()\n            while module not in modules:\n                log.info(f\"'{module}' is not a valid module name\")\n                module = questionary.autocomplete(\n                    \"Please select a new module\", choices=modules, style=nf_core.utils.nfcore_question_style\n                ).unsafe_ask()\n\n        return module\n\n    def get_module_info(self):\n        \"\"\"Given the name of a module, parse meta.yml and print usage help.\"\"\"\n\n        # Running with a local install, try to find the local meta\n        if self.dir:\n            self.meta = self.get_local_yaml()\n\n        # Either failed locally or in remote mode\n        if not self.meta:\n            self.meta = self.get_remote_yaml()\n\n        # Could not find the meta\n        if self.meta is False:\n            raise UserWarning(f\"Could not find module '{self.module}'\")\n\n        return self.generate_module_info_help()\n\n    def get_local_yaml(self):\n        \"\"\"Attempt to get the meta.yml file from a locally installed module.\n\n        Returns:\n            dict or bool: Parsed meta.yml found, False otherwise\n        \"\"\"\n\n        if self.repo_type == \"pipeline\":\n            # Try to find and load the meta.yml file\n            repo_name = self.modules_repo.fullname\n            module_base_path = os.path.join(self.dir, \"modules\", repo_name)\n            # Check that we have any modules installed from this repo\n            modules = self.modules_json.get_all_modules().get(repo_name)\n            if modules is None:\n                raise LookupError(f\"No modules installed from {self.modules_repo.remote_url}\")\n\n            if self.module in modules:\n                mod_dir = os.path.join(module_base_path, self.module)\n                meta_fn = os.path.join(mod_dir, \"meta.yml\")\n                if os.path.exists(meta_fn):\n                    log.debug(f\"Found local file: {meta_fn}\")\n                    with open(meta_fn, \"r\") as fh:\n                        self.local_path = mod_dir\n                        return yaml.safe_load(fh)\n\n            log.debug(f\"Module '{self.module}' meta.yml not found locally\")\n        else:\n            module_base_path = os.path.join(self.dir, \"modules\")\n            if self.module in os.listdir(module_base_path):\n                mod_dir = os.path.join(module_base_path, self.module)\n                meta_fn = os.path.join(mod_dir, \"meta.yml\")\n                if os.path.exists(meta_fn):\n                    log.debug(f\"Found local file: {meta_fn}\")\n                    with open(meta_fn, \"r\") as fh:\n                        self.local_path = mod_dir\n                        return yaml.safe_load(fh)\n            log.debug(f\"Module '{self.module}' meta.yml not found locally\")\n\n        return None\n\n    def get_remote_yaml(self):\n        \"\"\"Attempt to get the meta.yml file from a remote repo.\n\n        Returns:\n            dict or bool: Parsed meta.yml found, False otherwise\n        \"\"\"\n        # Check if our requested module is there\n        if self.module not in self.modules_repo.get_avail_modules():\n            return False\n\n        file_contents = self.modules_repo.get_meta_yml(self.module)\n        if file_contents is None:\n            return False\n        self.remote_location = self.modules_repo.remote_url\n        return yaml.safe_load(file_contents)\n\n    def generate_module_info_help(self):\n        \"\"\"Take the parsed meta.yml and generate rich help.\n\n        Returns:\n            rich renderable\n        \"\"\"\n\n        renderables = []\n\n        # Intro panel\n        intro_text = Text()\n        if self.local_path:\n            intro_text.append(Text.from_markup(f\"Location: [blue]{self.local_path}\\n\"))\n        elif self.remote_location:\n            intro_text.append(\n                Text.from_markup(\n                    f\":globe_with_meridians: Repository: [link=https://github.com/{self.remote_location}]{self.remote_location}[/]\\n\"\n                )\n            )\n\n        if self.meta.get(\"tools\"):\n            tools_strings = []\n            for tool in self.meta[\"tools\"]:\n                for tool_name, tool_meta in tool.items():\n                    if \"homepage\" in tool_meta:\n                        tools_strings.append(f\"[link={tool_meta['homepage']}]{tool_name}[/link]\")\n                    else:\n                        tools_strings.append(f\"{tool_name}\")\n            intro_text.append(Text.from_markup(f\":wrench: Tools: {', '.join(tools_strings)}\\n\", style=\"dim\"))\n\n        if self.meta.get(\"description\"):\n            intro_text.append(Text.from_markup(f\":book: Description: {self.meta['description']}\", style=\"dim\"))\n\n        renderables.append(\n            Panel(\n                intro_text,\n                title=f\"[bold]Module: [green]{self.module}\\n\",\n                title_align=\"left\",\n            )\n        )\n\n        # Inputs\n        if self.meta.get(\"input\"):\n            inputs_table = Table(expand=True, show_lines=True, box=box.MINIMAL_HEAVY_HEAD, padding=0)\n            inputs_table.add_column(\":inbox_tray: Inputs\")\n            inputs_table.add_column(\"Description\")\n            inputs_table.add_column(\"Pattern\", justify=\"right\", style=\"green\")\n            for input in self.meta[\"input\"]:\n                for key, info in input.items():\n                    inputs_table.add_row(\n                        f\"[orange1 on black] {key} [/][dim i] ({info['type']})\",\n                        Markdown(info[\"description\"] if info[\"description\"] else \"\"),\n                        info.get(\"pattern\", \"\"),\n                    )\n\n            renderables.append(inputs_table)\n\n        # Outputs\n        if self.meta.get(\"output\"):\n            outputs_table = Table(expand=True, show_lines=True, box=box.MINIMAL_HEAVY_HEAD, padding=0)\n            outputs_table.add_column(\":outbox_tray: Outputs\")\n            outputs_table.add_column(\"Description\")\n            outputs_table.add_column(\"Pattern\", justify=\"right\", style=\"green\")\n            for output in self.meta[\"output\"]:\n                for key, info in output.items():\n                    outputs_table.add_row(\n                        f\"[orange1 on black] {key} [/][dim i] ({info['type']})\",\n                        Markdown(info[\"description\"] if info[\"description\"] else \"\"),\n                        info.get(\"pattern\", \"\"),\n                    )\n\n            renderables.append(outputs_table)\n\n        # Installation command\n        if self.remote_location:\n            cmd_base = \"nf-core modules\"\n            if self.remote_location != NF_CORE_MODULES_REMOTE:\n                cmd_base = f\"nf-core modules --git-remote {self.remote_location}\"\n            renderables.append(\n                Text.from_markup(f\"\\n :computer:  Installation command: [magenta]{cmd_base} install {self.module}\\n\")\n            )\n\n        return Group(*renderables)\n", "path": "nf_core/modules/info.py"}], "after_files": [{"content": "import logging\nimport os\n\nimport questionary\nimport yaml\nfrom rich import box\nfrom rich.console import Group\nfrom rich.markdown import Markdown\nfrom rich.panel import Panel\nfrom rich.table import Table\nfrom rich.text import Text\n\nimport nf_core.utils\nfrom nf_core.modules.modules_json import ModulesJson\n\nfrom .module_utils import get_repo_type\nfrom .modules_command import ModuleCommand\nfrom .modules_repo import NF_CORE_MODULES_REMOTE\n\nlog = logging.getLogger(__name__)\n\n\nclass ModuleInfo(ModuleCommand):\n    \"\"\"\n    Class to print information of a module.\n\n    Attributes\n    ----------\n    meta : YAML object\n        stores the information from meta.yml file\n    local_path : str\n        path of the local modules\n    remote_location : str\n        remote repository URL\n    local : bool\n        indicates if the module is locally installed or not\n    repo_type : str\n        repository type. Can be either 'pipeline' or 'modules'\n    modules_json : ModulesJson object\n        contains 'modules.json' file information from a pipeline\n    module : str\n        name of the tool to get information from\n\n    Methods\n    -------\n    init_mod_name(module)\n        Makes sure that we have a module name\n    get_module_info()\n        Given the name of a module, parse meta.yml and print usage help\n    get_local_yaml()\n        Attempt to get the meta.yml file from a locally installed module\n    get_remote_yaml()\n        Attempt to get the meta.yml file from a remote repo\n    generate_module_info_help()\n        Take the parsed meta.yml and generate rich help\n    \"\"\"\n\n    def __init__(self, pipeline_dir, tool, remote_url, branch, no_pull, base_path):\n        super().__init__(pipeline_dir, remote_url, branch, no_pull, base_path)\n        self.meta = None\n        self.local_path = None\n        self.remote_location = None\n        self.local = None\n\n        # Quietly check if this is a pipeline or not\n        if pipeline_dir:\n            try:\n                pipeline_dir, repo_type = get_repo_type(pipeline_dir, use_prompt=False)\n                log.debug(f\"Found {repo_type} repo: {pipeline_dir}\")\n            except UserWarning as e:\n                log.debug(f\"Only showing remote info: {e}\")\n                pipeline_dir = None\n\n        if self.repo_type == \"pipeline\":\n            self.modules_json = ModulesJson(self.dir)\n            self.modules_json.check_up_to_date()\n        else:\n            self.modules_json = None\n        self.module = self.init_mod_name(tool)\n\n    def init_mod_name(self, module):\n        \"\"\"\n        Makes sure that we have a module name before proceeding.\n\n        Args:\n            module: str: Module name to check\n        \"\"\"\n        if module is None:\n            self.local = questionary.confirm(\n                \"Is the module locally installed?\", style=nf_core.utils.nfcore_question_style\n            ).unsafe_ask()\n            if self.local:\n                if self.repo_type == \"modules\":\n                    modules = self.get_modules_clone_modules()\n                else:\n                    modules = self.modules_json.get_all_modules().get(self.modules_repo.fullname)\n                    if modules is None:\n                        raise UserWarning(f\"No modules installed from '{self.modules_repo.remote_url}'\")\n            else:\n                modules = self.modules_repo.get_avail_modules()\n            module = questionary.autocomplete(\n                \"Please select a module\", choices=modules, style=nf_core.utils.nfcore_question_style\n            ).unsafe_ask()\n            while module not in modules:\n                log.info(f\"'{module}' is not a valid module name\")\n                module = questionary.autocomplete(\n                    \"Please select a new module\", choices=modules, style=nf_core.utils.nfcore_question_style\n                ).unsafe_ask()\n\n        return module\n\n    def get_module_info(self):\n        \"\"\"Given the name of a module, parse meta.yml and print usage help.\"\"\"\n\n        # Running with a local install, try to find the local meta\n        if self.local:\n            self.meta = self.get_local_yaml()\n\n        # Either failed locally or in remote mode\n        if not self.meta:\n            self.meta = self.get_remote_yaml()\n\n        # Could not find the meta\n        if self.meta is False:\n            raise UserWarning(f\"Could not find module '{self.module}'\")\n\n        return self.generate_module_info_help()\n\n    def get_local_yaml(self):\n        \"\"\"Attempt to get the meta.yml file from a locally installed module.\n\n        Returns:\n            dict or bool: Parsed meta.yml found, False otherwise\n        \"\"\"\n\n        if self.repo_type == \"pipeline\":\n            # Try to find and load the meta.yml file\n            repo_name = self.modules_repo.fullname\n            module_base_path = os.path.join(self.dir, \"modules\", repo_name)\n            # Check that we have any modules installed from this repo\n            modules = self.modules_json.get_all_modules().get(repo_name)\n            if modules is None:\n                raise LookupError(f\"No modules installed from {self.modules_repo.remote_url}\")\n\n            if self.module in modules:\n                mod_dir = os.path.join(module_base_path, self.module)\n                meta_fn = os.path.join(mod_dir, \"meta.yml\")\n                if os.path.exists(meta_fn):\n                    log.debug(f\"Found local file: {meta_fn}\")\n                    with open(meta_fn, \"r\") as fh:\n                        self.local_path = mod_dir\n                        return yaml.safe_load(fh)\n\n            log.debug(f\"Module '{self.module}' meta.yml not found locally\")\n        else:\n            module_base_path = os.path.join(self.dir, \"modules\")\n            if self.module in os.listdir(module_base_path):\n                mod_dir = os.path.join(module_base_path, self.module)\n                meta_fn = os.path.join(mod_dir, \"meta.yml\")\n                if os.path.exists(meta_fn):\n                    log.debug(f\"Found local file: {meta_fn}\")\n                    with open(meta_fn, \"r\") as fh:\n                        self.local_path = mod_dir\n                        return yaml.safe_load(fh)\n            log.debug(f\"Module '{self.module}' meta.yml not found locally\")\n\n        return None\n\n    def get_remote_yaml(self):\n        \"\"\"Attempt to get the meta.yml file from a remote repo.\n\n        Returns:\n            dict or bool: Parsed meta.yml found, False otherwise\n        \"\"\"\n        # Check if our requested module is there\n        if self.module not in self.modules_repo.get_avail_modules():\n            return False\n\n        file_contents = self.modules_repo.get_meta_yml(self.module)\n        if file_contents is None:\n            return False\n        self.remote_location = self.modules_repo.remote_url\n        return yaml.safe_load(file_contents)\n\n    def generate_module_info_help(self):\n        \"\"\"Take the parsed meta.yml and generate rich help.\n\n        Returns:\n            rich renderable\n        \"\"\"\n\n        renderables = []\n\n        # Intro panel\n        intro_text = Text()\n        if self.local_path:\n            intro_text.append(Text.from_markup(f\"Location: [blue]{self.local_path}\\n\"))\n        elif self.remote_location:\n            intro_text.append(\n                Text.from_markup(\n                    \":globe_with_meridians: Repository: \"\n                    f\"{ '[link={self.remote_location}]' if self.remote_location.startswith('http') else ''}\"\n                    f\"{self.remote_location}\"\n                    f\"{'[/link]' if self.remote_location.startswith('http') else '' }\"\n                    \"\\n\"\n                )\n            )\n\n        if self.meta.get(\"tools\"):\n            tools_strings = []\n            for tool in self.meta[\"tools\"]:\n                for tool_name, tool_meta in tool.items():\n                    if \"homepage\" in tool_meta:\n                        tools_strings.append(f\"[link={tool_meta['homepage']}]{tool_name}[/link]\")\n                    else:\n                        tools_strings.append(f\"{tool_name}\")\n            intro_text.append(Text.from_markup(f\":wrench: Tools: {', '.join(tools_strings)}\\n\", style=\"dim\"))\n\n        if self.meta.get(\"description\"):\n            intro_text.append(Text.from_markup(f\":book: Description: {self.meta['description']}\", style=\"dim\"))\n\n        renderables.append(\n            Panel(\n                intro_text,\n                title=f\"[bold]Module: [green]{self.module}\\n\",\n                title_align=\"left\",\n            )\n        )\n\n        # Inputs\n        if self.meta.get(\"input\"):\n            inputs_table = Table(expand=True, show_lines=True, box=box.MINIMAL_HEAVY_HEAD, padding=0)\n            inputs_table.add_column(\":inbox_tray: Inputs\")\n            inputs_table.add_column(\"Description\")\n            inputs_table.add_column(\"Pattern\", justify=\"right\", style=\"green\")\n            for input in self.meta[\"input\"]:\n                for key, info in input.items():\n                    inputs_table.add_row(\n                        f\"[orange1 on black] {key} [/][dim i] ({info['type']})\",\n                        Markdown(info[\"description\"] if info[\"description\"] else \"\"),\n                        info.get(\"pattern\", \"\"),\n                    )\n\n            renderables.append(inputs_table)\n\n        # Outputs\n        if self.meta.get(\"output\"):\n            outputs_table = Table(expand=True, show_lines=True, box=box.MINIMAL_HEAVY_HEAD, padding=0)\n            outputs_table.add_column(\":outbox_tray: Outputs\")\n            outputs_table.add_column(\"Description\")\n            outputs_table.add_column(\"Pattern\", justify=\"right\", style=\"green\")\n            for output in self.meta[\"output\"]:\n                for key, info in output.items():\n                    outputs_table.add_row(\n                        f\"[orange1 on black] {key} [/][dim i] ({info['type']})\",\n                        Markdown(info[\"description\"] if info[\"description\"] else \"\"),\n                        info.get(\"pattern\", \"\"),\n                    )\n\n            renderables.append(outputs_table)\n\n        # Installation command\n        if self.remote_location:\n            cmd_base = \"nf-core modules\"\n            if self.remote_location != NF_CORE_MODULES_REMOTE:\n                cmd_base = f\"nf-core modules --git-remote {self.remote_location}\"\n            renderables.append(\n                Text.from_markup(f\"\\n :computer:  Installation command: [magenta]{cmd_base} install {self.module}\\n\")\n            )\n\n        return Group(*renderables)\n", "path": "nf_core/modules/info.py"}]}