Repository: pdm-project/pdm
Pull request #1855 (2023-04-26 01:37:28)

feat(scripts): hide tasks starting with an underscore from listing
## Pull Request Checklist

- [x] A news fragment is added in `news/` describing what is new.
- [x] Test cases added for changed code.

## Describe what you have changed in this PR.

This PR is considering the tasks with a name starting with an underscore as internal tasks (helpers for composite...) and hide them from the listing.

codecov-commenter: ## [Codecov](https://codecov.io/gh/pdm-project/pdm/pull/1855?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pdm-project) Report
Patch coverage: **`100.00`**% and project coverage change: **`+0.03`** :tada:
> Comparison is base [(`1d6d490`)](https://codecov.io/gh/pdm-project/pdm/commit/1d6d49009b72df27854d6916853c983a71ec169c?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pdm-project) 85.36% compared to head [(`e38bff0`)](https://codecov.io/gh/pdm-project/pdm/pull/1855?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pdm-project) 85.39%.

:mega: This organization is not using Codecov’s [GitHub App Integration](https://github.com/apps/codecov). We recommend you install it so Codecov can continue to function properly for your repositories. [Learn more](https://about.codecov.io/blog/codecov-is-updating-its-github-integration/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pdm-project)

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main    #1855      +/-   ##
==========================================
+ Coverage   85.36%   85.39%   +0.03%     
==========================================
  Files          99       99              
  Lines        9066     9071       +5     
  Branches     1960     1960              
==========================================
+ Hits         7739     7746       +7     
+ Misses        896      895       -1     
+ Partials      431      430       -1     
```

| Flag | Coverage Δ | |
|---|---|---|
| unittests | `85.20% <100.00%> (+0.03%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pdm-project#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/pdm-project/pdm/pull/1855?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pdm-project) | Coverage Δ | |
|---|---|---|
| [src/pdm/cli/commands/run.py](https://codecov.io/gh/pdm-project/pdm/pull/1855?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pdm-project#diff-c3JjL3BkbS9jbGkvY29tbWFuZHMvcnVuLnB5) | `93.56% <100.00%> (+0.75%)` | :arrow_up: |

... and [3 files with indirect coverage changes](https://codecov.io/gh/pdm-project/pdm/pull/1855/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pdm-project)

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pdm-project). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pdm-project)

</details>

[:umbrella: View full report in Codecov by Sentry](https://codecov.io/gh/pdm-project/pdm/pull/1855?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pdm-project).   
:loudspeaker: Do you have feedback about the report comment? [Let us know in this issue](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pdm-project).


Patch:
diff --git a/docs/docs/usage/scripts.md b/docs/docs/usage/scripts.md
index 42e66639..4c44a92f 100644
--- a/docs/docs/usage/scripts.md
+++ b/docs/docs/usage/scripts.md
@@ -260,6 +260,9 @@ $ pdm run --list
 
 You can add an `help` option with the description of the script, and it will be displayed in the `Description` column in the above output.
 
+!!! note
+    Tasks with a name starting with an underscore (`_`) are considered internal (helpers...) and are not shown in the listing.
+
 ## Pre & Post Scripts
 
 Like `npm`, PDM also supports tasks composition by pre and post scripts, pre script will be run before the given task and post script will be run after.
diff --git a/news/1847.bugfix b/news/1847.bugfix.md
similarity index 100%
rename from news/1847.bugfix
rename to news/1847.bugfix.md
diff --git a/news/1855.feature.md b/news/1855.feature.md
new file mode 100644
index 00000000..a9e75a7b
--- /dev/null
+++ b/news/1855.feature.md
@@ -0,0 +1,1 @@
+Consider tasks with a name starting by an underscore (`_`) as internal tasks and hide them from the listing.
diff --git a/pdm.lock b/pdm.lock
index d2cb356d..035cf4f1 100644
--- a/pdm.lock
+++ b/pdm.lock
@@ -461,6 +461,15 @@ dependencies = [
     "pytest>=4.6",
 ]
 
+[[package]]
+name = "pytest-httpserver"
+version = "1.0.6"
+requires_python = ">=3.7,<4.0"
+summary = "pytest-httpserver is a httpserver for pytest"
+dependencies = [
+    "Werkzeug>=2.0.0",
+]
+
 [[package]]
 name = "pytest-mock"
 version = "3.10.0"
@@ -684,6 +693,15 @@ version = "2.2.1"
 requires_python = ">=3.6"
 summary = "Filesystem events monitoring"
 
+[[package]]
+name = "werkzeug"
+version = "2.2.3"
+requires_python = ">=3.7"
+summary = "The comprehensive WSGI web application library."
+dependencies = [
+    "MarkupSafe>=2.1.1",
+]
+
 [[package]]
 name = "zipp"
 version = "3.11.0"
@@ -693,7 +711,7 @@ summary = "Backport of pathlib-compatible object wrapper for zip files"
 [metadata]
 lock_version = "4.2"
 groups = ["default", "doc", "pytest", "test", "tox", "workflow"]
-content_hash = "sha256:054d7fa5635e78a5f7397dea5c6f61c3ad3a198554b6958bda09005df76c4ed3"
+content_hash = "sha256:591bfc7fe0ffac8e787d014ca3c531786ca9a5aad6ca17d99372159ee319f227"
 
 [metadata.files]
 "arpeggio 2.0.0" = [
@@ -1043,6 +1061,10 @@ content_hash = "sha256:054d7fa5635e78a5f7397dea5c6f61c3ad3a198554b6958bda09005df
     {url = "https://files.pythonhosted.org/packages/ea/70/da97fd5f6270c7d2ce07559a19e5bf36a76f0af21500256f005a69d9beba/pytest-cov-4.0.0.tar.gz", hash = "sha256:996b79efde6433cdbd0088872dbc5fb3ed7fe1578b68cdbba634f14bb8dd0470"},
     {url = "https://files.pythonhosted.org/packages/fe/1f/9ec0ddd33bd2b37d6ec50bb39155bca4fe7085fa78b3b434c05459a860e3/pytest_cov-4.0.0-py3-none-any.whl", hash = "sha256:2feb1b751d66a8bd934e5edfa2e961d11309dc37b73b0eabe73b5945fee20f6b"},
 ]
+"pytest-httpserver 1.0.6" = [
+    {url = "https://files.pythonhosted.org/packages/27/7b/3f5bdca6a6732fd02f5bd61ed6a7971c76db422ed2a93b61111bfa1dac43/pytest_httpserver-1.0.6.tar.gz", hash = "sha256:9040d07bf59ac45d8de3db1d4468fd2d1d607975e4da4c872ecc0402cdbf7b3e"},
+    {url = "https://files.pythonhosted.org/packages/c3/53/73bcf0bae91ae9cb85d9926a08865c168973a9d3affa499e238d8fce0110/pytest_httpserver-1.0.6-py3-none-any.whl", hash = "sha256:ac2379acc91fe8bdbe2911c93af8dd130e33b5899fb9934d15669480739c6d32"},
+]
 "pytest-mock 3.10.0" = [
     {url = "https://files.pythonhosted.org/packages/91/84/c951790e199cd54ddbf1021965b62a5415b81193ebdb4f4af2659fd06a73/pytest_mock-3.10.0-py3-none-any.whl", hash = "sha256:f4c973eeae0282963eb293eb173ce91b091a79c1334455acfac9ddee8a1c784b"},
     {url = "https://files.pythonhosted.org/packages/f6/2b/137a7db414aeaf3d753d415a2bc3b90aba8c5f61dff7a7a736d84b2ec60d/pytest-mock-3.10.0.tar.gz", hash = "sha256:fbbdb085ef7c252a326fd8cdcac0aa3b1333d8811f131bdcc701002e1be7ed4f"},
@@ -1297,6 +1319,10 @@ content_hash = "sha256:054d7fa5635e78a5f7397dea5c6f61c3ad3a198554b6958bda09005df
     {url = "https://files.pythonhosted.org/packages/f4/20/f02d47f27d2e395eca01a96438411ed343be76855481da95e18e2d6c6546/watchdog-2.2.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a480d122740debf0afac4ddd583c6c0bb519c24f817b42ed6f850e2f6f9d64a8"},
     {url = "https://files.pythonhosted.org/packages/f8/35/98996332b9ae5a805ae8f7bad4834f51c0c8b070c223e7417163820732c5/watchdog-2.2.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a09483249d25cbdb4c268e020cb861c51baab2d1affd9a6affc68ffe6a231260"},
 ]
+"werkzeug 2.2.3" = [
+    {url = "https://files.pythonhosted.org/packages/02/3c/baaebf3235c87d61d6593467056d5a8fba7c75ac838b8d100a5e64eba7a0/Werkzeug-2.2.3.tar.gz", hash = "sha256:2e1ccc9417d4da358b9de6f174e3ac094391ea1d4fbef2d667865d819dfd0afe"},
+    {url = "https://files.pythonhosted.org/packages/f6/f8/9da63c1617ae2a1dec2fbf6412f3a0cfe9d4ce029eccbda6e1e4258ca45f/Werkzeug-2.2.3-py3-none-any.whl", hash = "sha256:56433961bc1f12533306c624f3be5e744389ac61d722175d543e1751285da612"},
+]
 "zipp 3.11.0" = [
     {url = "https://files.pythonhosted.org/packages/8e/b3/8b16a007184714f71157b1a71bbe632c5d66dd43bc8152b3c799b13881e1/zipp-3.11.0.tar.gz", hash = "sha256:a7a22e05929290a67401440b39690ae6563279bced5f314609d9d03798f56766"},
     {url = "https://files.pythonhosted.org/packages/d8/20/256eb3f3f437c575fb1a2efdce5e801a5ce3162ea8117da96c43e6ee97d8/zipp-3.11.0-py3-none-any.whl", hash = "sha256:83a28fcb75844b5c0cdaf5aa4003c2d728c77e05f5aeabe8e95e56727005fbaa"},
diff --git a/pyproject.toml b/pyproject.toml
index daf2c878..548a433f 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -84,6 +84,7 @@ test = [
     "pytest-cov",
     "pytest-xdist>=1.31.0",
     "pytest-rerunfailures>=10.2",
+    "pytest-httpserver>=1.0.6",
 ]
 tox = [
     "tox",
diff --git a/src/pdm/cli/commands/run.py b/src/pdm/cli/commands/run.py
index cd6c8142..822f4bed 100644
--- a/src/pdm/cli/commands/run.py
+++ b/src/pdm/cli/commands/run.py
@@ -289,7 +289,7 @@ class TaskRunner:
         columns = ["Name", "Type", "Description"]
         result = []
         for name in sorted(self.project.scripts):
-            if name == "_":
+            if name.startswith("_"):
                 continue
             task = self.get_task(name)
             assert task is not None


Test patch:
diff --git a/tests/cli/test_run.py b/tests/cli/test_run.py
index 1cd2eb9b..51d5ee29 100644
--- a/tests/cli/test_run.py
+++ b/tests/cli/test_run.py
@@ -386,6 +386,17 @@ def test_run_show_list_of_scripts(project, invoke):
     assert result_lines[4][1:-1].strip() == "test_shell     │ shell     │ shell command"
 
 
+def test_run_show_list_of_scripts_hide_internals(project, invoke):
+    project.pyproject.settings["scripts"] = {
+        "public": "true",
+        "_internal": "true",
+    }
+    project.pyproject.write()
+    result = invoke(["run", "--list"], obj=project)
+    assert "public" in result.output
+    assert "_internal" not in result.output
+
+
 def test_run_json_list_of_scripts(project, invoke):
     project.pyproject.settings["scripts"] = {
         "_": {"env_file": ".env"},
diff --git a/tests/test_project.py b/tests/test_project.py
index 1e9ad4de..0160c9a8 100644
--- a/tests/test_project.py
+++ b/tests/test_project.py
@@ -5,6 +5,7 @@ from pathlib import Path
 
 import pytest
 from packaging.version import parse
+from pytest_httpserver import HTTPServer
 
 from pdm.cli.commands.venv.utils import get_venv_python
 from pdm.environments import PythonEnvironment
@@ -275,19 +276,20 @@ def test_no_index_raise_error(project):
             pass
 
 
-@pytest.mark.network
-def test_access_index_with_auth(project):
-    url = "https://httpbin.org/basic-auth/foo/bar"
+def test_access_index_with_auth(project, httpserver: HTTPServer):
+    httpserver.expect_request(
+        "/simple/my-package", method="GET", headers={"Authorization": "Basic Zm9vOmJhcg=="}
+    ).respond_with_data("OK")
     project.global_config.update(
         {
-            "pypi.extra.url": "https://httpbin.org",
+            "pypi.extra.url": httpserver.url_for("/simple"),
             "pypi.extra.username": "foo",
             "pypi.extra.password": "bar",
         }
     )
     with project.environment.get_finder() as finder:
         session = finder.session
-        resp = session.get(url)
+        resp = session.get(httpserver.url_for("/simple/my-package"))
         assert resp.ok