peterbe: @mythmon r?
mythmon: Perhaps the log output above should be in a code block? I think Github is messing with your formatting by erasing the newlines, or something.
peterbe: Ah, I didn't have the backticks inside there. And [apprently you need a leading newline before the ticks](https://github.com/dear-github/dear-github/issues/166#issuecomment-322367328).
peterbe: You're right about the English prefixes before printing those things. It could be better but I'm also wary of explaining the verbose output too much. The most important thing is there and more English verbiage isn't likely to be much use. 

By the way, the original intent of the `--verbose` was for the "paranoid" to manually check the downloaded files and see that each one doesn't have malicious stuff in it. That feature kinda went away (slowly and quietly) when using pypi.org and extracting the `sha256` straight from the JSON. Now, if you're paranoid, you'd have to manually `wget` each of those files and basically check that what pypi is hosting is files that haven't been tampered with. 
diff --git a/README.rst b/README.rst
index 91b83ea..4be9060 100644
--- a/README.rst
+++ b/README.rst
@@ -221,6 +221,11 @@ put it directly into ``pip``.
 Version History
 ===============
 
+0.13.x
+
+  * Don't show URLs when using ``--verbose`` if files don't need to be
+    downloaded. See https://github.com/peterbe/hashin/issues/73
+
 0.13.3
   * Makes it possible to install ``nltk`` on Windows.
     `Thanks @chrispbailey! <https://github.com/peterbe/hashin/pull/72>`_
diff --git a/hashin.py b/hashin.py
index c2a4a0d..12918f7 100755
--- a/hashin.py
+++ b/hashin.py
@@ -364,15 +364,17 @@ def get_package_data(package, verbose=False):
 
 def get_releases_hashes(releases, algorithm, verbose=False):
     for found in releases:
-        url = found['url']
-        if verbose:
-            _verbose('Found URL', url)
         digests = found['digests']
         try:
             found['hash'] = digests[algorithm]
+            if verbose:
+                _verbose('Found hash for', found['url'])
         except KeyError:
             # The algorithm is NOT in the 'digests' dict.
             # We have to download the file and use pip
+            url = found['url']
+            if verbose:
+                _verbose('Found URL', url)
             download_dir = tempfile.gettempdir()
             filename = os.path.join(
                 download_dir,
@@ -390,7 +392,6 @@ def get_releases_hashes(releases, algorithm, verbose=False):
         if verbose:
             _verbose('  Hash', found['hash'])
         yield {
-            'url': url,
             'hash': found['hash']
         }
 

Verbose option doesn't make sense any more when the algorithm is in the release
When we [started using pypi.org instead](https://github.com/peterbe/hashin/commit/66aa748a6d80e436283f26526b5af2b3b9a0d62f) one important change was that now we can (almost) always get the digests as part of the JSON payload. Before we had to get each URL for each release file, download that file, and run `pip` on it to get the checksum. Instead now can we can just get it from `.releases[<desired version][N].digests.sha256` for example. In https://pypi.org/pypi/psycopg2/json for example every release has a `md5` and `sha256` digest. So we don't need to process a specific URL. 


diff --git a/tests/test_cli.py b/tests/test_cli.py
index 336eb2e..ad4ecfb 100644
--- a/tests/test_cli.py
+++ b/tests/test_cli.py
@@ -417,7 +417,7 @@ selenium==2.53.1 \
                 out_lines[1]
             )
             self.assertTrue(
-                'Found URL https://pypi.org/packages' in out_lines[1],
+                'Found hash for https://pypi.org/packages/2.7/p/hashin/hashin-0.10-py2-none-any.whl' in out_lines[1],
                 out_lines[1]
             )
             # hash it got
@@ -986,15 +986,12 @@ selenium==2.53.1 \
             'version': '0.10',
             'hashes': [
                 {
-                    'url': 'https://pypi.org/packages/2.7/p/hashin/hashin-0.10-py2-none-any.whl',
                     'hash': 'aaaaa'
                 },
                 {
-                    'url': 'https://pypi.org/packages/3.3/p/hashin/hashin-0.10-py3-none-any.whl',
                     'hash': 'bbbbb'
                 },
                 {
-                    'url': 'https://pypi.org/packages/source/p/hashin/hashin-0.10.tar.gz',
                     'hash': 'ccccc'
                 }
             ]
@@ -1047,10 +1044,17 @@ selenium==2.53.1 \
 
         murlopen.side_effect = mocked_get
 
-        result = hashin.get_package_hashes(
-            package='hashin',
-            version='0.10',
-            algorithm='sha512',
+        my_stdout = StringIO()
+        with redirect_stdout(my_stdout):
+            result = hashin.get_package_hashes(
+                package='hashin',
+                version='0.10',
+                algorithm='sha512',
+                verbose=True,
+            )
+        out_lines = my_stdout.getvalue().splitlines()
+        self.assertTrue(
+            'Found URL https://pypi.org/packages/2.7/p/hashin/hashin-0.10-py2-none-any.whl' in out_lines[1]
         )
 
         expected = {
@@ -1058,15 +1062,12 @@ selenium==2.53.1 \
             'version': '0.10',
             'hashes': [
                 {
-                    'url': 'https://pypi.org/packages/3.3/p/hashin/hashin-0.10-py3-none-any.whl',
                     'hash': '0d63bf4c115154781846ecf573049324f06b021a1d4b92da4fae2bf491da2b83a13096b14d73e73cefad36855f4fa936bac4b2357dabf05a2b1e7329ff1e5455'
                 },
                 {
-                    'url': 'https://pypi.org/packages/2.7/p/hashin/hashin-0.10-py2-none-any.whl',
                     'hash': '45d1c5d2237a3b4f78b4198709fb2ecf1f781c8234ce3d94356f2100a36739433952c6c13b2843952f608949e6baa9f95055a314487cd8fb3f9d76522d8edb50'
                 },
                 {
-                    'url': 'https://pypi.org/packages/source/p/hashin/hashin-0.10.tar.gz',
                     'hash': 'c32e6d9fb09dc36ab9222c4606a1f43a2dcc183a8c64bdd9199421ef779072c174fa044b155babb12860cf000e36bc4d358694fa22420c997b1dd75b623d4daa'
                 }
             ]

pip install -e .
parse_log_pytest
requirements.txt
pytest mock
apt-get update apt-get install -y gcc
3.9
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
exceptiongroup==1.2.2
-e git+https://github.com/peterbe/hashin.git@a80c5efbb1630f75a9cfd4492627e9aff051c3e1#egg=hashin
iniconfig==2.1.0
mock==5.2.0
packaging==24.2
pip-api==0.0.34
pluggy==1.5.0
pytest==8.3.5
tomli==2.2.1

name: hashin
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - exceptiongroup==1.2.2
      - iniconfig==2.1.0
      - mock==5.2.0
      - packaging==24.2
      - pip-api==0.0.34
      - pluggy==1.5.0
      - pytest==8.3.5
      - tomli==2.2.1
prefix: /opt/conda/envs/hashin

tests/test_cli.py::Tests::test_get_package_hashes tests/test_cli.py::Tests::test_get_package_hashes_unknown_algorithm tests/test_cli.py::Tests::test_run
tests/test_cli.py::Tests::test_amend_requirements_content_new tests/test_cli.py::Tests::test_amend_requirements_content_new_similar_name tests/test_cli.py::Tests::test_amend_requirements_content_replacement tests/test_cli.py::Tests::test_amend_requirements_content_replacement_2 tests/test_cli.py::Tests::test_amend_requirements_content_replacement_amonst_others tests/test_cli.py::Tests::test_amend_requirements_content_replacement_amonst_others_2 tests/test_cli.py::Tests::test_amend_requirements_content_replacement_single_to_multi tests/test_cli.py::Tests::test_expand_python_version tests/test_cli.py::Tests::test_filter_releases tests/test_cli.py::Tests::test_get_hashes_error tests/test_cli.py::Tests::test_get_latest_version_non_pre_release tests/test_cli.py::Tests::test_get_latest_version_non_pre_release_leading_zeros tests/test_cli.py::Tests::test_get_latest_version_only_pre_release tests/test_cli.py::Tests::test_get_latest_version_simple tests/test_cli.py::Tests::test_get_package_hashes_without_version tests/test_cli.py::Tests::test_main_packageerrors_stderr tests/test_cli.py::Tests::test_main_version tests/test_cli.py::Tests::test_non_200_ok_download tests/test_cli.py::Tests::test_release_url_metadata_python tests/test_cli.py::Tests::test_run_case_insensitive tests/test_cli.py::Tests::test_run_contained_names tests/test_cli.py::Tests::test_run_pep_0496 tests/test_cli.py::Tests::test_run_without_specific_version
README.rst hashin.py
README.rst hashin.py