hackerrank-cli 2026.10.1.1__tar.gz → 2026.10.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/CHANGELOG.rst +11 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/MANIFEST.in +3 -1
- {hackerrank_cli-2026.10.1.1/src/hackerrank_cli.egg-info → hackerrank_cli-2026.10.7}/PKG-INFO +32 -5
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/README.rst +31 -4
- hackerrank_cli-2026.10.7/VERSION +1 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/docs/source/development.rst +2 -3
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/docs/source/migration.rst +23 -2
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/pyproject.toml +7 -3
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/src/hackerrank_cli/__init__.py +84 -29
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/src/hackerrank_cli/_version.py +3 -3
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7/src/hackerrank_cli.egg-info}/PKG-INFO +32 -5
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/src/hackerrank_cli.egg-info/SOURCES.txt +2 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/src/hackerrank_cli.egg-info/scm_file_list.json +2 -0
- hackerrank_cli-2026.10.7/src/hackerrank_cli.egg-info/scm_version.json +8 -0
- hackerrank_cli-2026.10.7/tests/test_archive.py +145 -0
- hackerrank_cli-2026.10.7/tests/test_help/test_help_archive_.txt +11 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/tests/test_help/test_help_questions_.txt +2 -1
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/tests/test_help.py +7 -2
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/uv.lock +53 -37
- hackerrank_cli-2026.10.1.1/VERSION +0 -1
- hackerrank_cli-2026.10.1.1/src/hackerrank_cli.egg-info/scm_version.json +0 -8
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/.dockerignore +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/.gitattributes +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/.github/dependabot.yml +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/.github/workflows/autofix.yml +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/.github/workflows/binaries.yml +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/.github/workflows/ci.yml +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/.github/workflows/dependabot-merge.yml +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/.github/workflows/docs.yml +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/.github/workflows/lint.yml +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/.github/workflows/nix.yml +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/.github/workflows/publish-site.yml +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/.github/workflows/release.yml +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/.gitignore +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/.vale.ini +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/Dockerfile +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/LICENSE +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/bin/__init__.py +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/bin/hackerrank_wrapper.py +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/docs/__init__.py +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/docs/source/__init__.py +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/docs/source/changelog.rst +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/docs/source/cli.rst +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/docs/source/conf.py +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/docs/source/index.rst +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/docs/source/macos-releases.rst +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/docs/source/usage.rst +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/flake.lock +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/flake.nix +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/newsfragments/.gitkeep +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/prek.toml +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/setup.cfg +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/spelling_private_dict.txt +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/src/hackerrank_cli/__main__.py +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/src/hackerrank_cli/_sources.py +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/src/hackerrank_cli/py.typed +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/src/hackerrank_cli.egg-info/dependency_links.txt +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/src/hackerrank_cli.egg-info/entry_points.txt +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/src/hackerrank_cli.egg-info/not-zip-safe +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/src/hackerrank_cli.egg-info/requires.txt +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/src/hackerrank_cli.egg-info/top_level.txt +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/styles/snapper/LongProseLine.yml +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/styles/snapper/SemanticLineBreaks.yml +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/tests/__init__.py +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/tests/test_cli.py +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/tests/test_help/test_help_root_.txt +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/tests/test_help/test_help_upload_.txt +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/tests/test_http.py +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/tests/test_sources.py +0 -0
- {hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/zizmor.yml +0 -0
|
@@ -5,6 +5,17 @@ Releases are assembled from ``newsfragments/`` using Towncrier.
|
|
|
5
5
|
|
|
6
6
|
.. towncrier release notes start
|
|
7
7
|
|
|
8
|
+
2026.10.7 (2026-10-07)
|
|
9
|
+
----------------------
|
|
10
|
+
|
|
11
|
+
Features
|
|
12
|
+
~~~~~~~~
|
|
13
|
+
|
|
14
|
+
- Export project ZIP archives offline with ``hackerrank questions archive``,
|
|
15
|
+
using the same file selection and packaging as uploads.
|
|
16
|
+
(#6)
|
|
17
|
+
|
|
18
|
+
|
|
8
19
|
2026.10.1.1 (2026-10-01)
|
|
9
20
|
------------------------
|
|
10
21
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
include LICENSE README.rst CHANGELOG.rst
|
|
1
|
+
include LICENSE README.rst CHANGELOG.rst
|
|
2
2
|
recursive-include src *.py *.typed
|
|
3
3
|
recursive-include docs *.rst *.py
|
|
4
4
|
recursive-include newsfragments *
|
|
@@ -11,3 +11,5 @@ recursive-include bin *.py
|
|
|
11
11
|
recursive-include tests *.py *.txt
|
|
12
12
|
include .dockerignore
|
|
13
13
|
include .gitattributes
|
|
14
|
+
|
|
15
|
+
include VERSION
|
{hackerrank_cli-2026.10.1.1/src/hackerrank_cli.egg-info → hackerrank_cli-2026.10.7}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hackerrank-cli
|
|
3
|
-
Version: 2026.10.
|
|
3
|
+
Version: 2026.10.7
|
|
4
4
|
Summary: Upload starter files to existing HackerRank project questions.
|
|
5
5
|
Author-email: Adam Dangoor <adamdangoor@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -44,9 +44,16 @@ Install from PyPI:
|
|
|
44
44
|
|
|
45
45
|
uv tool install hackerrank-cli
|
|
46
46
|
hackerrank --help
|
|
47
|
-
hackerrank --version
|
|
48
47
|
|
|
49
|
-
|
|
48
|
+
Or install the checkout for development:
|
|
49
|
+
|
|
50
|
+
.. code-block:: console
|
|
51
|
+
|
|
52
|
+
uv sync --locked
|
|
53
|
+
uv run hackerrank --help
|
|
54
|
+
uv run python -m hackerrank_cli --version
|
|
55
|
+
|
|
56
|
+
``pip install hackerrank-cli`` is also supported.
|
|
50
57
|
|
|
51
58
|
Usage
|
|
52
59
|
-----
|
|
@@ -86,6 +93,27 @@ repeatable upload.
|
|
|
86
93
|
The CLI adds no separate retry loop.
|
|
87
94
|
Each attempt uses the same prepared archive bytes.
|
|
88
95
|
|
|
96
|
+
Offline archives
|
|
97
|
+
----------------
|
|
98
|
+
|
|
99
|
+
Export the same project ZIP locally without a question ID, credentials, or
|
|
100
|
+
network access:
|
|
101
|
+
|
|
102
|
+
.. code-block:: console
|
|
103
|
+
|
|
104
|
+
hackerrank questions archive --directory ./starter --exclude '*.zip' --output ./starter.zip
|
|
105
|
+
hackerrank questions archive --file ./starter.py --output - > ./starter.zip
|
|
106
|
+
|
|
107
|
+
``--output`` is required.
|
|
108
|
+
A file destination must not already exist; ``-`` writes only ZIP bytes to
|
|
109
|
+
standard output.
|
|
110
|
+
Shell redirection controls whether its destination is overwritten.
|
|
111
|
+
Source validation and packaging finish before the output is opened.
|
|
112
|
+
The source options, ignore rules, file contents, and executable permissions
|
|
113
|
+
match ``questions upload``.
|
|
114
|
+
Consumers can extract this archive for local checks, then send its bytes with
|
|
115
|
+
the SDK's ``questions.upload_project_zip`` method.
|
|
116
|
+
|
|
89
117
|
Directory selection
|
|
90
118
|
-------------------
|
|
91
119
|
|
|
@@ -136,8 +164,7 @@ Development and distribution
|
|
|
136
164
|
Development checks, release setup, and build instructions for Docker, Nix, and
|
|
137
165
|
standalone binaries are in ``docs/source/development.rst``.
|
|
138
166
|
The generated CLI reference is in ``docs/source/cli.rst``.
|
|
139
|
-
|
|
140
|
-
`GitHub Releases <https://github.com/adamtheturtle/hackerrank-cli/releases>`_.
|
|
167
|
+
There are no prebuilt artifacts yet.
|
|
141
168
|
|
|
142
169
|
See ``docs/source/migration.rst`` for migrating an existing shell uploader and
|
|
143
170
|
keeping repository-specific snippet preparation outside this CLI.
|
|
@@ -18,9 +18,16 @@ Install from PyPI:
|
|
|
18
18
|
|
|
19
19
|
uv tool install hackerrank-cli
|
|
20
20
|
hackerrank --help
|
|
21
|
-
hackerrank --version
|
|
22
21
|
|
|
23
|
-
|
|
22
|
+
Or install the checkout for development:
|
|
23
|
+
|
|
24
|
+
.. code-block:: console
|
|
25
|
+
|
|
26
|
+
uv sync --locked
|
|
27
|
+
uv run hackerrank --help
|
|
28
|
+
uv run python -m hackerrank_cli --version
|
|
29
|
+
|
|
30
|
+
``pip install hackerrank-cli`` is also supported.
|
|
24
31
|
|
|
25
32
|
Usage
|
|
26
33
|
-----
|
|
@@ -60,6 +67,27 @@ repeatable upload.
|
|
|
60
67
|
The CLI adds no separate retry loop.
|
|
61
68
|
Each attempt uses the same prepared archive bytes.
|
|
62
69
|
|
|
70
|
+
Offline archives
|
|
71
|
+
----------------
|
|
72
|
+
|
|
73
|
+
Export the same project ZIP locally without a question ID, credentials, or
|
|
74
|
+
network access:
|
|
75
|
+
|
|
76
|
+
.. code-block:: console
|
|
77
|
+
|
|
78
|
+
hackerrank questions archive --directory ./starter --exclude '*.zip' --output ./starter.zip
|
|
79
|
+
hackerrank questions archive --file ./starter.py --output - > ./starter.zip
|
|
80
|
+
|
|
81
|
+
``--output`` is required.
|
|
82
|
+
A file destination must not already exist; ``-`` writes only ZIP bytes to
|
|
83
|
+
standard output.
|
|
84
|
+
Shell redirection controls whether its destination is overwritten.
|
|
85
|
+
Source validation and packaging finish before the output is opened.
|
|
86
|
+
The source options, ignore rules, file contents, and executable permissions
|
|
87
|
+
match ``questions upload``.
|
|
88
|
+
Consumers can extract this archive for local checks, then send its bytes with
|
|
89
|
+
the SDK's ``questions.upload_project_zip`` method.
|
|
90
|
+
|
|
63
91
|
Directory selection
|
|
64
92
|
-------------------
|
|
65
93
|
|
|
@@ -110,8 +138,7 @@ Development and distribution
|
|
|
110
138
|
Development checks, release setup, and build instructions for Docker, Nix, and
|
|
111
139
|
standalone binaries are in ``docs/source/development.rst``.
|
|
112
140
|
The generated CLI reference is in ``docs/source/cli.rst``.
|
|
113
|
-
|
|
114
|
-
`GitHub Releases <https://github.com/adamtheturtle/hackerrank-cli/releases>`_.
|
|
141
|
+
There are no prebuilt artifacts yet.
|
|
115
142
|
|
|
116
143
|
See ``docs/source/migration.rst`` for migrating an existing shell uploader and
|
|
117
144
|
keeping repository-specific snippet preparation outside this CLI.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
2026.10.7
|
|
@@ -43,9 +43,8 @@ No separate mock-spec repository is needed for this scope.
|
|
|
43
43
|
Add a Towncrier feature or bugfix fragment for each user-visible change.
|
|
44
44
|
|
|
45
45
|
Versions derive from Git tags using setuptools-scm.
|
|
46
|
-
Untagged
|
|
47
|
-
Use date-based tags such as ``2026.10.
|
|
48
|
-
created as part of repository initialization.
|
|
46
|
+
Untagged builds have a development version.
|
|
47
|
+
Use date-based tags such as ``2026.10.7`` for releases.
|
|
49
48
|
Before tagging a release, assemble notes with
|
|
50
49
|
``uv run towncrier build --yes --version VERSION``, commit the changelog, then
|
|
51
50
|
write the same version to ``VERSION``, commit it, then tag the commit.
|
|
@@ -7,8 +7,7 @@ repository that owns the questions.
|
|
|
7
7
|
This CLI uploads starter files to an existing project question.
|
|
8
8
|
It never creates questions or updates metadata.
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
repository.
|
|
10
|
+
Pin a released ``hackerrank-cli`` version in that repository.
|
|
12
11
|
Replace each project archive upload with:
|
|
13
12
|
|
|
14
13
|
.. code-block:: shell
|
|
@@ -27,3 +26,25 @@ The default is zero, matching the released SDK.
|
|
|
27
26
|
Uploads use immutable archive bytes so retries send the same content.
|
|
28
27
|
Do not enable live uploads until the file list and project behavior have been
|
|
29
28
|
reviewed in the owning repository.
|
|
29
|
+
|
|
30
|
+
Local validation
|
|
31
|
+
----------------
|
|
32
|
+
|
|
33
|
+
Use ``hackerrank questions archive`` when local checks need the exact project
|
|
34
|
+
layout candidates receive:
|
|
35
|
+
|
|
36
|
+
.. code-block:: shell
|
|
37
|
+
|
|
38
|
+
hackerrank questions archive --directory ./starter --exclude '*.zip' --output ./starter.zip
|
|
39
|
+
|
|
40
|
+
Extract the archive in a temporary directory to run project checks.
|
|
41
|
+
An uploader that already uses the SDK can send the exported bytes with
|
|
42
|
+
``questions.upload_project_zip`` instead of maintaining another ZIP builder.
|
|
43
|
+
The export command shares source selection and packaging with CLI uploads.
|
|
44
|
+
It makes no network requests and requires no API token.
|
|
45
|
+
|
|
46
|
+
Gitignore patterns match directories as well as files.
|
|
47
|
+
When translating a file-only exclusion such as ``app``, add ``!app/`` after it
|
|
48
|
+
if source directories of that name must remain included.
|
|
49
|
+
Inherited ``.gitignore`` rules still apply, so compare the exported file list
|
|
50
|
+
and contents before replacing an existing packager.
|
|
@@ -37,7 +37,8 @@ dev = [
|
|
|
37
37
|
"doccmd==2026.9.16.1",
|
|
38
38
|
"furo==2025.12.19",
|
|
39
39
|
"interrogate==1.7.0",
|
|
40
|
-
"mypy==2.
|
|
40
|
+
"mypy==2.4.0",
|
|
41
|
+
"mypy-pytest-parametrize==2026.10.5",
|
|
41
42
|
"mypy-strict-kwargs==2026.8.25.1",
|
|
42
43
|
"no-defaults==2026.9.1",
|
|
43
44
|
"prek==0.5.4",
|
|
@@ -198,7 +199,8 @@ exclude_gitignore = true
|
|
|
198
199
|
follow_untyped_imports = true
|
|
199
200
|
python_version = "3.13"
|
|
200
201
|
strict = true
|
|
201
|
-
plugins = [ "mypy_strict_kwargs" ]
|
|
202
|
+
plugins = [ "mypy_pytest_parametrize", "mypy_strict_kwargs" ]
|
|
203
|
+
num_workers = "auto"
|
|
202
204
|
|
|
203
205
|
[tool.pyrefly]
|
|
204
206
|
project-excludes = [ "src/hackerrank_cli/_version.py" ]
|
|
@@ -224,15 +226,17 @@ analysis.strict-generic-narrowing = true
|
|
|
224
226
|
|
|
225
227
|
[tool.pytest]
|
|
226
228
|
ini_options.testpaths = [ "tests" ]
|
|
227
|
-
ini_options.addopts = "-n auto --cov
|
|
229
|
+
ini_options.addopts = "-n auto --cov --cov-config=pyproject.toml"
|
|
228
230
|
ini_options.xfail_strict = true
|
|
229
231
|
ini_options.beartype_packages = [ "hackerrank_cli" ]
|
|
230
232
|
ini_options.beartype_test_fixtures = true
|
|
231
233
|
ini_options.beartype_tests = true
|
|
232
234
|
|
|
233
235
|
[tool.coverage]
|
|
236
|
+
run.source = [ "hackerrank_cli" ]
|
|
234
237
|
run.omit = [ "src/hackerrank_cli/__main__.py", "src/hackerrank_cli/_version.py" ]
|
|
235
238
|
run.branch = true
|
|
239
|
+
report.fail_under = 100
|
|
236
240
|
report.show_missing = true
|
|
237
241
|
|
|
238
242
|
[tool.towncrier]
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"""Upload project starter code using the released HackerRank SDK."""
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
|
+
from collections.abc import Generator
|
|
5
|
+
from contextlib import contextmanager
|
|
4
6
|
from importlib.metadata import version
|
|
5
7
|
from io import BytesIO
|
|
6
8
|
from pathlib import Path
|
|
@@ -84,27 +86,65 @@ def create_cli(*, transport: Transport | None = None) -> click.Group:
|
|
|
84
86
|
transport=transport,
|
|
85
87
|
)
|
|
86
88
|
|
|
89
|
+
@click.option(
|
|
90
|
+
"--directory",
|
|
91
|
+
type=click.Path(path_type=Path, readable=False),
|
|
92
|
+
help="Project directory.",
|
|
93
|
+
)
|
|
94
|
+
@click.option(
|
|
95
|
+
"--file",
|
|
96
|
+
"source_file",
|
|
97
|
+
type=click.Path(path_type=Path, readable=False),
|
|
98
|
+
help="One starter file, packaged as a single-file project archive.",
|
|
99
|
+
)
|
|
100
|
+
@click.option(
|
|
101
|
+
"--exclude",
|
|
102
|
+
multiple=True,
|
|
103
|
+
help="Additional Gitignore pattern at the upload root. Repeatable.",
|
|
104
|
+
)
|
|
105
|
+
@click.option(
|
|
106
|
+
"--output",
|
|
107
|
+
type=click.Path(dir_okay=False, allow_dash=True),
|
|
108
|
+
required=True,
|
|
109
|
+
help=(
|
|
110
|
+
"New ZIP file, or - for binary standard output. "
|
|
111
|
+
"Never overwrites files."
|
|
112
|
+
),
|
|
113
|
+
)
|
|
114
|
+
def archive(
|
|
115
|
+
directory: Path | None,
|
|
116
|
+
source_file: Path | None,
|
|
117
|
+
exclude: tuple[str, ...],
|
|
118
|
+
output: str,
|
|
119
|
+
) -> None:
|
|
120
|
+
"""Export a project ZIP without credentials or network access."""
|
|
121
|
+
_validate_source(
|
|
122
|
+
directory=directory, source_file=source_file, exclude=exclude
|
|
123
|
+
)
|
|
124
|
+
with (
|
|
125
|
+
_preparation_errors(),
|
|
126
|
+
prepare_source(
|
|
127
|
+
directory=directory, file=source_file, excludes=exclude
|
|
128
|
+
) as source,
|
|
129
|
+
):
|
|
130
|
+
contents = _project_zip(source=source)
|
|
131
|
+
with click.open_file(filename=output, mode="xb") as destination:
|
|
132
|
+
_ = destination.write(contents)
|
|
133
|
+
|
|
134
|
+
_ = questions.command()(archive)
|
|
87
135
|
_ = questions.command()(upload)
|
|
88
136
|
return cli
|
|
89
137
|
|
|
90
138
|
|
|
91
|
-
def
|
|
92
|
-
question_id: str,
|
|
139
|
+
def _validate_source(
|
|
93
140
|
directory: Path | None,
|
|
94
141
|
source_file: Path | None,
|
|
95
142
|
exclude: tuple[str, ...],
|
|
96
143
|
) -> None:
|
|
97
|
-
"""Validate
|
|
144
|
+
"""Validate the shared archive and upload source options."""
|
|
98
145
|
if (directory is None) == (source_file is None):
|
|
99
146
|
msg = "Provide exactly one of --directory or --file."
|
|
100
147
|
raise click.UsageError(message=msg)
|
|
101
|
-
if (
|
|
102
|
-
not question_id.isascii()
|
|
103
|
-
or not question_id.isdecimal()
|
|
104
|
-
or int(question_id) < 1
|
|
105
|
-
):
|
|
106
|
-
msg = "QUESTION_ID must be a positive decimal integer."
|
|
107
|
-
raise click.BadParameter(message=msg, param_hint="QUESTION_ID")
|
|
108
148
|
if len(exclude) > 0 and directory is None:
|
|
109
149
|
msg = "--exclude requires --directory."
|
|
110
150
|
raise click.UsageError(message=msg)
|
|
@@ -187,30 +227,45 @@ def _upload( # noqa: PLR0913 - Click options plus the SDK transport boundary.
|
|
|
187
227
|
transport: Transport | None,
|
|
188
228
|
) -> None:
|
|
189
229
|
"""Prepare every byte before credentials or a network mutation."""
|
|
190
|
-
|
|
191
|
-
question_id=question_id,
|
|
230
|
+
_validate_source(
|
|
192
231
|
directory=directory,
|
|
193
232
|
source_file=source_file,
|
|
194
233
|
exclude=exclude,
|
|
195
234
|
)
|
|
196
|
-
|
|
197
|
-
|
|
235
|
+
if (
|
|
236
|
+
not question_id.isascii()
|
|
237
|
+
or not question_id.isdecimal()
|
|
238
|
+
or int(question_id) < 1
|
|
239
|
+
):
|
|
240
|
+
msg = "QUESTION_ID must be a positive decimal integer."
|
|
241
|
+
raise click.BadParameter(message=msg, param_hint="QUESTION_ID")
|
|
242
|
+
with (
|
|
243
|
+
_preparation_errors(),
|
|
244
|
+
prepare_source(
|
|
198
245
|
directory=directory, file=source_file, excludes=exclude
|
|
199
|
-
) as source
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
246
|
+
) as source,
|
|
247
|
+
):
|
|
248
|
+
archive = _project_zip(source=source)
|
|
249
|
+
target = f"HackerRank project question {question_id}"
|
|
250
|
+
if dry_run:
|
|
251
|
+
click.echo(message=f"Would update {target}")
|
|
252
|
+
for path in source.files:
|
|
253
|
+
click.echo(message=f" {path}")
|
|
254
|
+
return
|
|
255
|
+
_send_upload(
|
|
256
|
+
question_id=question_id,
|
|
257
|
+
archive=archive,
|
|
258
|
+
retries=retries,
|
|
259
|
+
transport=transport,
|
|
260
|
+
)
|
|
261
|
+
click.echo(message=f"Updated {target}")
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
@contextmanager
|
|
265
|
+
def _preparation_errors() -> Generator[None]:
|
|
266
|
+
"""Report source and archive errors consistently for both commands."""
|
|
267
|
+
try:
|
|
268
|
+
yield
|
|
214
269
|
except UnicodeError:
|
|
215
270
|
msg = ".gitignore files must be valid UTF-8."
|
|
216
271
|
raise click.ClickException(message=msg) from None
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '2026.10.
|
|
22
|
-
__version_tuple__ = version_tuple = (2026, 10,
|
|
21
|
+
__version__ = version = '2026.10.7'
|
|
22
|
+
__version_tuple__ = version_tuple = (2026, 10, 7)
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'g3aa79e260'
|
{hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7/src/hackerrank_cli.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hackerrank-cli
|
|
3
|
-
Version: 2026.10.
|
|
3
|
+
Version: 2026.10.7
|
|
4
4
|
Summary: Upload starter files to existing HackerRank project questions.
|
|
5
5
|
Author-email: Adam Dangoor <adamdangoor@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -44,9 +44,16 @@ Install from PyPI:
|
|
|
44
44
|
|
|
45
45
|
uv tool install hackerrank-cli
|
|
46
46
|
hackerrank --help
|
|
47
|
-
hackerrank --version
|
|
48
47
|
|
|
49
|
-
|
|
48
|
+
Or install the checkout for development:
|
|
49
|
+
|
|
50
|
+
.. code-block:: console
|
|
51
|
+
|
|
52
|
+
uv sync --locked
|
|
53
|
+
uv run hackerrank --help
|
|
54
|
+
uv run python -m hackerrank_cli --version
|
|
55
|
+
|
|
56
|
+
``pip install hackerrank-cli`` is also supported.
|
|
50
57
|
|
|
51
58
|
Usage
|
|
52
59
|
-----
|
|
@@ -86,6 +93,27 @@ repeatable upload.
|
|
|
86
93
|
The CLI adds no separate retry loop.
|
|
87
94
|
Each attempt uses the same prepared archive bytes.
|
|
88
95
|
|
|
96
|
+
Offline archives
|
|
97
|
+
----------------
|
|
98
|
+
|
|
99
|
+
Export the same project ZIP locally without a question ID, credentials, or
|
|
100
|
+
network access:
|
|
101
|
+
|
|
102
|
+
.. code-block:: console
|
|
103
|
+
|
|
104
|
+
hackerrank questions archive --directory ./starter --exclude '*.zip' --output ./starter.zip
|
|
105
|
+
hackerrank questions archive --file ./starter.py --output - > ./starter.zip
|
|
106
|
+
|
|
107
|
+
``--output`` is required.
|
|
108
|
+
A file destination must not already exist; ``-`` writes only ZIP bytes to
|
|
109
|
+
standard output.
|
|
110
|
+
Shell redirection controls whether its destination is overwritten.
|
|
111
|
+
Source validation and packaging finish before the output is opened.
|
|
112
|
+
The source options, ignore rules, file contents, and executable permissions
|
|
113
|
+
match ``questions upload``.
|
|
114
|
+
Consumers can extract this archive for local checks, then send its bytes with
|
|
115
|
+
the SDK's ``questions.upload_project_zip`` method.
|
|
116
|
+
|
|
89
117
|
Directory selection
|
|
90
118
|
-------------------
|
|
91
119
|
|
|
@@ -136,8 +164,7 @@ Development and distribution
|
|
|
136
164
|
Development checks, release setup, and build instructions for Docker, Nix, and
|
|
137
165
|
standalone binaries are in ``docs/source/development.rst``.
|
|
138
166
|
The generated CLI reference is in ``docs/source/cli.rst``.
|
|
139
|
-
|
|
140
|
-
`GitHub Releases <https://github.com/adamtheturtle/hackerrank-cli/releases>`_.
|
|
167
|
+
There are no prebuilt artifacts yet.
|
|
141
168
|
|
|
142
169
|
See ``docs/source/migration.rst`` for migrating an existing shell uploader and
|
|
143
170
|
keeping repository-specific snippet preparation outside this CLI.
|
{hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/src/hackerrank_cli.egg-info/SOURCES.txt
RENAMED
|
@@ -55,10 +55,12 @@ src/hackerrank_cli.egg-info/top_level.txt
|
|
|
55
55
|
styles/snapper/LongProseLine.yml
|
|
56
56
|
styles/snapper/SemanticLineBreaks.yml
|
|
57
57
|
tests/__init__.py
|
|
58
|
+
tests/test_archive.py
|
|
58
59
|
tests/test_cli.py
|
|
59
60
|
tests/test_help.py
|
|
60
61
|
tests/test_http.py
|
|
61
62
|
tests/test_sources.py
|
|
63
|
+
tests/test_help/test_help_archive_.txt
|
|
62
64
|
tests/test_help/test_help_questions_.txt
|
|
63
65
|
tests/test_help/test_help_root_.txt
|
|
64
66
|
tests/test_help/test_help_upload_.txt
|
|
@@ -45,8 +45,10 @@
|
|
|
45
45
|
"styles/snapper/LongProseLine.yml",
|
|
46
46
|
"styles/snapper/SemanticLineBreaks.yml",
|
|
47
47
|
"tests/__init__.py",
|
|
48
|
+
"tests/test_archive.py",
|
|
48
49
|
"tests/test_cli.py",
|
|
49
50
|
"tests/test_help.py",
|
|
51
|
+
"tests/test_help/test_help_archive_.txt",
|
|
50
52
|
"tests/test_help/test_help_questions_.txt",
|
|
51
53
|
"tests/test_help/test_help_root_.txt",
|
|
52
54
|
"tests/test_help/test_help_upload_.txt",
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"""Validate offline archives against the bytes sent through the SDK."""
|
|
2
|
+
|
|
3
|
+
from io import BytesIO
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from zipfile import ZipFile
|
|
6
|
+
|
|
7
|
+
import pytest
|
|
8
|
+
from click.testing import CliRunner
|
|
9
|
+
|
|
10
|
+
from hackerrank_cli import create_cli
|
|
11
|
+
from tests.test_cli import USAGE_ERROR, recording_transport
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def _entries(contents: bytes) -> dict[str, tuple[bytes, int]]:
|
|
15
|
+
"""Read file contents and stored permissions from a project ZIP."""
|
|
16
|
+
with ZipFile(file=BytesIO(initial_bytes=contents)) as archive:
|
|
17
|
+
return {
|
|
18
|
+
info.filename: (archive.read(name=info), info.external_attr >> 16)
|
|
19
|
+
for info in archive.infolist()
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@pytest.mark.parametrize(argnames="single_file", argvalues=[False, True])
|
|
24
|
+
@pytest.mark.parametrize(argnames="stdout", argvalues=[False, True])
|
|
25
|
+
def test_export_matches_upload(
|
|
26
|
+
tmp_path: Path, *, single_file: bool, stdout: bool
|
|
27
|
+
) -> None:
|
|
28
|
+
"""Export the same bytes and permissions as an upload, without a
|
|
29
|
+
key.
|
|
30
|
+
"""
|
|
31
|
+
source = tmp_path / "starter"
|
|
32
|
+
source.mkdir()
|
|
33
|
+
script = source / "run.sh"
|
|
34
|
+
contents = b"#!/bin/sh\r\n# input-begin\r\n\x00\xff \r\n"
|
|
35
|
+
_ = script.write_bytes(data=contents)
|
|
36
|
+
script.chmod(mode=0o755)
|
|
37
|
+
if single_file:
|
|
38
|
+
options = ["--file", str(object=script)]
|
|
39
|
+
else:
|
|
40
|
+
_ = (source / ".gitignore").write_text(data="ignored.txt\n")
|
|
41
|
+
_ = (source / "ignored.txt").write_text(data="ignored")
|
|
42
|
+
_ = (source / "metadata.yml").write_text(data="excluded")
|
|
43
|
+
options = [
|
|
44
|
+
"--directory",
|
|
45
|
+
str(object=source),
|
|
46
|
+
"--exclude",
|
|
47
|
+
"metadata.yml",
|
|
48
|
+
"--exclude",
|
|
49
|
+
".gitignore",
|
|
50
|
+
]
|
|
51
|
+
destination = tmp_path / "starter.zip"
|
|
52
|
+
output = "-" if stdout else str(object=destination)
|
|
53
|
+
transport = recording_transport(status=200, failure=None)
|
|
54
|
+
cli = create_cli(transport=transport)
|
|
55
|
+
result = CliRunner().invoke(
|
|
56
|
+
cli=cli,
|
|
57
|
+
args=["questions", "archive", *options, "--output", output],
|
|
58
|
+
env={"HACKERRANK_API_TOKEN": None},
|
|
59
|
+
)
|
|
60
|
+
assert result.exit_code == 0, result.stderr
|
|
61
|
+
assert result.stderr == ""
|
|
62
|
+
assert transport.requests == []
|
|
63
|
+
exported = result.stdout_bytes if stdout else destination.read_bytes()
|
|
64
|
+
assert _entries(contents=exported) == {
|
|
65
|
+
"run.sh": (contents, script.stat().st_mode)
|
|
66
|
+
}
|
|
67
|
+
uploaded = CliRunner().invoke(
|
|
68
|
+
cli=cli,
|
|
69
|
+
args=["questions", "upload", "123456", *options],
|
|
70
|
+
env={"HACKERRANK_API_TOKEN": "synthetic-secret"},
|
|
71
|
+
)
|
|
72
|
+
assert uploaded.exit_code == 0, uploaded.output
|
|
73
|
+
[(_, _, _, files)] = transport.requests
|
|
74
|
+
assert files is not None
|
|
75
|
+
assert _entries(contents=files["file"][1]) == _entries(contents=exported)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@pytest.mark.parametrize(
|
|
79
|
+
argnames="options",
|
|
80
|
+
argvalues=[
|
|
81
|
+
[],
|
|
82
|
+
["--directory", ".", "--file", "example.py"],
|
|
83
|
+
["--file", "example.py", "--exclude", "*.zip"],
|
|
84
|
+
],
|
|
85
|
+
)
|
|
86
|
+
def test_invalid_source_options(tmp_path: Path, options: list[str]) -> None:
|
|
87
|
+
"""Reject ambiguous sources before creating an output file."""
|
|
88
|
+
output = tmp_path / "archive.zip"
|
|
89
|
+
result = CliRunner().invoke(
|
|
90
|
+
cli=create_cli(),
|
|
91
|
+
args=[
|
|
92
|
+
"questions",
|
|
93
|
+
"archive",
|
|
94
|
+
*options,
|
|
95
|
+
"--output",
|
|
96
|
+
str(object=output),
|
|
97
|
+
],
|
|
98
|
+
)
|
|
99
|
+
assert result.exit_code == USAGE_ERROR
|
|
100
|
+
assert output.exists() is False
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
@pytest.mark.parametrize(argnames="existing", argvalues=[False, True])
|
|
104
|
+
def test_output_errors(tmp_path: Path, *, existing: bool) -> None:
|
|
105
|
+
"""Do not overwrite an existing file, and report missing parents."""
|
|
106
|
+
source = tmp_path / "starter.py"
|
|
107
|
+
_ = source.write_bytes(data=b"pass\n")
|
|
108
|
+
output = source if existing else tmp_path / "missing" / "archive.zip"
|
|
109
|
+
result = CliRunner().invoke(
|
|
110
|
+
cli=create_cli(),
|
|
111
|
+
args=[
|
|
112
|
+
"questions",
|
|
113
|
+
"archive",
|
|
114
|
+
"--file",
|
|
115
|
+
str(object=source),
|
|
116
|
+
"--output",
|
|
117
|
+
str(object=output),
|
|
118
|
+
],
|
|
119
|
+
env={"HACKERRANK_API_TOKEN": None},
|
|
120
|
+
)
|
|
121
|
+
assert result.exit_code == 1
|
|
122
|
+
assert source.read_bytes() == b"pass\n"
|
|
123
|
+
assert "Error:" in result.stderr
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def test_preparation_failure(tmp_path: Path) -> None:
|
|
127
|
+
"""An empty selection leaves no archive behind."""
|
|
128
|
+
source = tmp_path / "empty"
|
|
129
|
+
source.mkdir()
|
|
130
|
+
output = tmp_path / "archive.zip"
|
|
131
|
+
result = CliRunner().invoke(
|
|
132
|
+
cli=create_cli(),
|
|
133
|
+
args=[
|
|
134
|
+
"questions",
|
|
135
|
+
"archive",
|
|
136
|
+
"--directory",
|
|
137
|
+
str(object=source),
|
|
138
|
+
"--output",
|
|
139
|
+
str(object=output),
|
|
140
|
+
],
|
|
141
|
+
env={"HACKERRANK_API_TOKEN": None},
|
|
142
|
+
)
|
|
143
|
+
assert result.exit_code == 1
|
|
144
|
+
assert result.stderr == "Error: No files selected for upload.\n"
|
|
145
|
+
assert output.exists() is False
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Usage: hackerrank questions archive [OPTIONS]
|
|
2
|
+
|
|
3
|
+
Export a project ZIP without credentials or network access.
|
|
4
|
+
|
|
5
|
+
Options:
|
|
6
|
+
--directory PATH Project directory.
|
|
7
|
+
--file PATH One starter file, packaged as a single-file project archive.
|
|
8
|
+
--exclude TEXT Additional Gitignore pattern at the upload root. Repeatable.
|
|
9
|
+
--output FILE New ZIP file, or - for binary standard output. Never
|
|
10
|
+
overwrites files. [required]
|
|
11
|
+
--help Show this message and exit.
|
{hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/tests/test_help/test_help_questions_.txt
RENAMED
|
@@ -6,4 +6,5 @@ Options:
|
|
|
6
6
|
--help Show this message and exit.
|
|
7
7
|
|
|
8
8
|
Commands:
|
|
9
|
-
|
|
9
|
+
archive Export a project ZIP without credentials or network access.
|
|
10
|
+
upload Replace project starter files while preserving question metadata.
|
|
@@ -12,8 +12,13 @@ from hackerrank_cli import main
|
|
|
12
12
|
|
|
13
13
|
@pytest.mark.parametrize(
|
|
14
14
|
argnames="arguments",
|
|
15
|
-
argvalues=[
|
|
16
|
-
|
|
15
|
+
argvalues=[
|
|
16
|
+
[],
|
|
17
|
+
["questions"],
|
|
18
|
+
["questions", "upload"],
|
|
19
|
+
["questions", "archive"],
|
|
20
|
+
],
|
|
21
|
+
ids=["root", "questions", "upload", "archive"],
|
|
17
22
|
)
|
|
18
23
|
def test_help(
|
|
19
24
|
arguments: list[str], file_regression: FileRegressionFixture
|
|
@@ -773,6 +773,7 @@ dev = [
|
|
|
773
773
|
{ name = "furo" },
|
|
774
774
|
{ name = "interrogate" },
|
|
775
775
|
{ name = "mypy" },
|
|
776
|
+
{ name = "mypy-pytest-parametrize" },
|
|
776
777
|
{ name = "mypy-strict-kwargs" },
|
|
777
778
|
{ name = "no-defaults" },
|
|
778
779
|
{ name = "prek" },
|
|
@@ -830,7 +831,8 @@ dev = [
|
|
|
830
831
|
{ name = "doccmd", specifier = "==2026.9.16.1" },
|
|
831
832
|
{ name = "furo", specifier = "==2025.12.19" },
|
|
832
833
|
{ name = "interrogate", specifier = "==1.7.0" },
|
|
833
|
-
{ name = "mypy", specifier = "==2.
|
|
834
|
+
{ name = "mypy", specifier = "==2.4.0" },
|
|
835
|
+
{ name = "mypy-pytest-parametrize", specifier = "==2026.10.5" },
|
|
834
836
|
{ name = "mypy-strict-kwargs", specifier = "==2026.8.25.1" },
|
|
835
837
|
{ name = "no-defaults", specifier = "==2026.9.1" },
|
|
836
838
|
{ name = "prek", specifier = "==0.5.4" },
|
|
@@ -1325,7 +1327,7 @@ wheels = [
|
|
|
1325
1327
|
|
|
1326
1328
|
[[package]]
|
|
1327
1329
|
name = "mypy"
|
|
1328
|
-
version = "2.
|
|
1330
|
+
version = "2.4.0"
|
|
1329
1331
|
source = { registry = "https://pypi.org/simple" }
|
|
1330
1332
|
dependencies = [
|
|
1331
1333
|
{ name = "ast-serialize" },
|
|
@@ -1334,41 +1336,41 @@ dependencies = [
|
|
|
1334
1336
|
{ name = "pathspec" },
|
|
1335
1337
|
{ name = "typing-extensions" },
|
|
1336
1338
|
]
|
|
1337
|
-
sdist = { url = "https://files.pythonhosted.org/packages/
|
|
1338
|
-
wheels = [
|
|
1339
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1340
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1341
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1342
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1343
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1344
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1345
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1346
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1347
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1348
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1349
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1350
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1351
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1352
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1353
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1354
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1355
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1356
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1357
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1358
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1359
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1360
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1361
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1362
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1363
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1364
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1365
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1366
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1367
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1368
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1369
|
-
{ url = "https://files.pythonhosted.org/packages/c0/
|
|
1370
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1371
|
-
{ url = "https://files.pythonhosted.org/packages/
|
|
1339
|
+
sdist = { url = "https://files.pythonhosted.org/packages/34/4e/64300736cf0a0373a27b94a91b664ee7382e36f77b0621bae6381da3e180/mypy-2.4.0.tar.gz", hash = "sha256:77bdaebd452f43fcfc4cc3ba94352a3ea537cd01e3f2d0879f48673d2ec00d6e", size = 4064425, upload-time = "2026-10-01T20:40:39.229Z" }
|
|
1340
|
+
wheels = [
|
|
1341
|
+
{ url = "https://files.pythonhosted.org/packages/44/f2/eb15183c97c69d7cbfac990a6efd33a19ecfd97dab9e714c742fa78a784f/mypy-2.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7da85fbcff6dac1abcc636707bed38b45598131fb7a605d9719c70b5cc733af8", size = 14213395, upload-time = "2026-10-01T20:40:21.178Z" },
|
|
1342
|
+
{ url = "https://files.pythonhosted.org/packages/8c/b5/ba91b6ff65e4d6b6ff53b2b3b3ac5f1babf0c7c27d0b43a0196b1c967926/mypy-2.4.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4209da39d85cf240f762af622d8180fcdfcb4727d021f44ade62d613a1a43324", size = 14373009, upload-time = "2026-10-01T20:39:58.86Z" },
|
|
1343
|
+
{ url = "https://files.pythonhosted.org/packages/d5/c4/484275efc935c0003e55e4e8a33e4b8e99528ee956c12256ece4708f903f/mypy-2.4.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6be721bd4bd57576193653b75b4af3461c9d0bf7dd8b528f782e9be210dc75bb", size = 15465557, upload-time = "2026-10-01T20:39:01.794Z" },
|
|
1344
|
+
{ url = "https://files.pythonhosted.org/packages/50/30/66eb6fdd0875e3c9025a02f0bb0ea2e524b74274b658c37fde0068c4939d/mypy-2.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e1fde197ae65be856a034a91b70ed747a16562ca69577785f06c661548424bf1", size = 15728673, upload-time = "2026-10-01T20:38:43.724Z" },
|
|
1345
|
+
{ url = "https://files.pythonhosted.org/packages/58/bc/2aa98fd7f49c42dba8e9c065886fadffdd00f3c654cff3f2a7103a797ac8/mypy-2.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:295ecf2e57542cd836ca537486951289678c8c7d1ee6ad74ebe29b2168a003cf", size = 11389803, upload-time = "2026-10-01T20:39:37.547Z" },
|
|
1346
|
+
{ url = "https://files.pythonhosted.org/packages/49/41/17b60df2d946792ef6af43b89351f5c9ddabc69053206b2304945572a744/mypy-2.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:bc378bdad4e9f12b5bd96466083d1e71acf00594ec9c7b2bdb5e02816f77f303", size = 10951060, upload-time = "2026-10-01T20:39:04.015Z" },
|
|
1347
|
+
{ url = "https://files.pythonhosted.org/packages/e0/66/924be0b653372ed31ad5c48e26044cc00840e591943a56e61621cf05b60e/mypy-2.4.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:058165f564ccf559c68c70fec2091fca5891110480210c22594635e3f6683437", size = 14234230, upload-time = "2026-10-01T20:39:44.535Z" },
|
|
1348
|
+
{ url = "https://files.pythonhosted.org/packages/56/39/c4f176880a4177123576de6cec6309feea8f42fca2bf2f6584e88054f656/mypy-2.4.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9fa247e02b505a45a2775f69df38d360d197e3790bc60f717595db9eda358b6e", size = 14392944, upload-time = "2026-10-01T20:40:05.78Z" },
|
|
1349
|
+
{ url = "https://files.pythonhosted.org/packages/bc/1c/26e16977e25ef2494a74f8ffc872a76ec2c3aa43c3156057cbdf88f352c5/mypy-2.4.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:20e9a5cd875837520c43db98dea0b6d0c2197833d95c30127d8f570fb9b1f00b", size = 15441463, upload-time = "2026-10-01T20:40:32.412Z" },
|
|
1350
|
+
{ url = "https://files.pythonhosted.org/packages/31/9c/9e4b049f0ecefbfd6817ca2a16eea55dd74a07950268edc6cffd29ccfe98/mypy-2.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9f03a7828cca2b0adcd6662aee8f2711ff8830e1027641fdea3ab0b787483566", size = 15705406, upload-time = "2026-10-01T20:40:34.844Z" },
|
|
1351
|
+
{ url = "https://files.pythonhosted.org/packages/4a/5e/e861b5f6c5ef9ee6cd24683aed1edecf82a26dbd536049f9b7850b586267/mypy-2.4.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:9279488933040b638c0ab739084c0ca100efeea6db581bf5d7628d8e89de53fe", size = 7897523, upload-time = "2026-10-01T20:39:39.861Z" },
|
|
1352
|
+
{ url = "https://files.pythonhosted.org/packages/3a/87/61ffee58b25a956532a6006fae84918a2de849ed25f397492b2e815fe7b3/mypy-2.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:2106b55105ba5ea9be4f53a24517fc5fa927ff1585edc9bc1a975abb72caef89", size = 11576345, upload-time = "2026-10-01T20:39:41.553Z" },
|
|
1353
|
+
{ url = "https://files.pythonhosted.org/packages/a1/88/a331c20698971c2ce8d1c30f317fd61b5be13a85b1f053e12dfa22ac6568/mypy-2.4.0-cp314-cp314-win_arm64.whl", hash = "sha256:528c8744b8b5e3ecb8774f86af38d2376216816e9908317ad055f3c9c2d74799", size = 11172062, upload-time = "2026-10-01T20:38:59.534Z" },
|
|
1354
|
+
{ url = "https://files.pythonhosted.org/packages/47/c0/4f7daa73270dced8e86c6f4a911c68082d03a84e6c1ec9bd916028d66131/mypy-2.4.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0bb95cf34899e4619c61ab0a8667804e139e580b30d5df12af2102dfe44d0c97", size = 15711208, upload-time = "2026-10-01T20:39:30.597Z" },
|
|
1355
|
+
{ url = "https://files.pythonhosted.org/packages/2f/05/f1afa303c678be24cf7a266d38fb24b3de4599a024c2f9ba0d5905a3efa3/mypy-2.4.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:86d616fe84c6eab8026f8c50ab5bcb90db780d2ccd233d971e34e92bede9b359", size = 15935442, upload-time = "2026-10-01T20:39:22.781Z" },
|
|
1356
|
+
{ url = "https://files.pythonhosted.org/packages/9d/d6/6a1a45459b63716e0d035f4892a926d3054f0a8cbfa02551d228a9946083/mypy-2.4.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a3f86fd1313dd69d013e265f1fdcd12ea7a9d606f9875b2a3db946cd334555f3", size = 17240044, upload-time = "2026-10-01T20:39:32.95Z" },
|
|
1357
|
+
{ url = "https://files.pythonhosted.org/packages/87/85/ae33bee66c13f98d421964d87bf0888be941063bc75c1204a4cf142cf1cc/mypy-2.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:720434d48542ecfe84d32d287b727569d3fc8f5769acd39051130e490a5c295c", size = 17545856, upload-time = "2026-10-01T20:39:08.827Z" },
|
|
1358
|
+
{ url = "https://files.pythonhosted.org/packages/df/de/eeff209b65c3e267818d79333bb9f058da6e4e73761461bd94748a2eb628/mypy-2.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:a6e851b82c0661f69f1630fc16172c68787a6a9cf0991e7c6437d60976cdcd76", size = 12369342, upload-time = "2026-10-01T20:40:10.516Z" },
|
|
1359
|
+
{ url = "https://files.pythonhosted.org/packages/2b/43/e62d8d5c1dd737aa248968302ff7d6eabf997c3301773ed8bcb64932ca77/mypy-2.4.0-cp314-cp314t-win_arm64.whl", hash = "sha256:3bd0e340f0ebe65c548210f53be3fd8192e83964760caf0c28bef368e68b0d37", size = 11849099, upload-time = "2026-10-01T20:39:51.834Z" },
|
|
1360
|
+
{ url = "https://files.pythonhosted.org/packages/2e/5f/335b8980055118dc131355155883fb676bb2161a0d97e08658e479c776fb/mypy-2.4.0-cp315-cp315-macosx_11_0_arm64.whl", hash = "sha256:afa89837d9be67e0cadfa33bca3bb7efdda98c3b07e74dc3b635ebfb1c8a926a", size = 14241302, upload-time = "2026-10-01T20:39:13.227Z" },
|
|
1361
|
+
{ url = "https://files.pythonhosted.org/packages/18/37/1482fdc49332b145828912b15f16eee0c4ca70a8bce0f6514ece79b14680/mypy-2.4.0-cp315-cp315-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fb443e81057896132d3642d6be219e6efd158691ac7883e3ba8fcb469865f05d", size = 14408200, upload-time = "2026-10-01T20:38:52.576Z" },
|
|
1362
|
+
{ url = "https://files.pythonhosted.org/packages/04/09/dce2e8f6c1b31053c430ef6963f6f7a38ccb49b90c5e01e37ed0129b7d5a/mypy-2.4.0-cp315-cp315-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7f38f57d344f8b6accb40e01c3d83cfc590498231724d16c07ffb7940f157818", size = 15444409, upload-time = "2026-10-01T20:39:18.1Z" },
|
|
1363
|
+
{ url = "https://files.pythonhosted.org/packages/43/c5/91b68306da4cd280cb15be35dbb5ffc343cabd67c4b121b6625bf2d13177/mypy-2.4.0-cp315-cp315-musllinux_1_2_x86_64.whl", hash = "sha256:e76172710bd4e5eeae061abfd68347e5264632e02778be61784671ae3a2132f5", size = 15731186, upload-time = "2026-10-01T20:40:23.426Z" },
|
|
1364
|
+
{ url = "https://files.pythonhosted.org/packages/64/71/2d0340182a8f27352fb1e25531355951108b506097c433937e9eec452ffd/mypy-2.4.0-cp315-cp315-pyemscripten_2026_5_wasm32.whl", hash = "sha256:f83353e47ab520bf6fd4df8f5897d9fe081211f2fbc4b7d37736a3e3c166cbcf", size = 7897838, upload-time = "2026-10-01T20:38:50.779Z" },
|
|
1365
|
+
{ url = "https://files.pythonhosted.org/packages/3e/08/32703c117e134c02efa2a82705bb40cee91eaedea10b6530e20eba651b1f/mypy-2.4.0-cp315-cp315-win_amd64.whl", hash = "sha256:970b221ed5842213d98e3c480c08f795ace4b1f81fb21e1b126bd0476bce1c34", size = 11575700, upload-time = "2026-10-01T20:39:53.982Z" },
|
|
1366
|
+
{ url = "https://files.pythonhosted.org/packages/ab/08/08bb269feafdaad031046ee2d771528a64467e6a180f962afc28c4a3ccd8/mypy-2.4.0-cp315-cp315-win_arm64.whl", hash = "sha256:502b94b0b331f7dafe32fd6b151797ddbb4f32385b362e722c783a025e5954a3", size = 11172908, upload-time = "2026-10-01T20:40:12.91Z" },
|
|
1367
|
+
{ url = "https://files.pythonhosted.org/packages/fb/3f/c5c92626006ca92c7686adfbece47fc6a0daa0e54753952a9ad13ce0561c/mypy-2.4.0-cp315-cp315t-macosx_11_0_arm64.whl", hash = "sha256:c9de622fd397495695d0598ddc789222bfcfec9d7c9ec3a1e385c855e3bc5e01", size = 15705970, upload-time = "2026-10-01T20:40:17.79Z" },
|
|
1368
|
+
{ url = "https://files.pythonhosted.org/packages/10/f3/863365f7997a76a5a1dd42d7902ab05afa4124e8419089cbca1ce2554db1/mypy-2.4.0-cp315-cp315t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9f459f0b4f0596d9d51fe7716b404b35287b99e77da98a7af90a65dd5fd61141", size = 15942234, upload-time = "2026-10-01T20:40:37.243Z" },
|
|
1369
|
+
{ url = "https://files.pythonhosted.org/packages/f6/30/2f45b1f425a2c95dbe1a3f4d076bfd42b76e9615dba5906230703b14e4eb/mypy-2.4.0-cp315-cp315t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f9b028548b3af480e2b1ed8df14ccaac86f99c9f600d1580770ab7ba3dcd40f0", size = 17218364, upload-time = "2026-10-01T20:39:06.497Z" },
|
|
1370
|
+
{ url = "https://files.pythonhosted.org/packages/43/8b/5b2bbfc69e84800b78fa2dba16d995b003f93b573558e412c5490d6e6c37/mypy-2.4.0-cp315-cp315t-musllinux_1_2_x86_64.whl", hash = "sha256:cb734b2668c1f40d07ce093bbeb4407e9527c67901627b0e1679825be3f09975", size = 17557934, upload-time = "2026-10-01T20:38:46.077Z" },
|
|
1371
|
+
{ url = "https://files.pythonhosted.org/packages/df/c0/1a5dc601c22041a7bbfe1ff71cf097fbbd4fb49930867c6789baf5102106/mypy-2.4.0-cp315-cp315t-win_amd64.whl", hash = "sha256:172e30b8fea631fe310f0c665477f52d9ea40bb4e99e0c81dc30118563b13710", size = 12350955, upload-time = "2026-10-01T20:40:01.52Z" },
|
|
1372
|
+
{ url = "https://files.pythonhosted.org/packages/1c/bc/697e9e26fc2a86c094ad67ee1e419971b7f01ded66ee66231b09e9f3e12e/mypy-2.4.0-cp315-cp315t-win_arm64.whl", hash = "sha256:5786ef987b3767e51aaa53f20aec104c0252b42ecda7aef8e8b4cbae279b05c5", size = 11842738, upload-time = "2026-10-01T20:40:30.026Z" },
|
|
1373
|
+
{ url = "https://files.pythonhosted.org/packages/81/12/46ae8670c98a3cd0286ca5645c2f918f8f6be65edfed81b916010619f668/mypy-2.4.0-py3-none-any.whl", hash = "sha256:d01c5d26a352acc6d5cf3128225477e1e8465e8d3029d4c345807fbf7f3cf093", size = 2800734, upload-time = "2026-10-01T20:39:26.837Z" },
|
|
1372
1374
|
]
|
|
1373
1375
|
|
|
1374
1376
|
[[package]]
|
|
@@ -1380,6 +1382,20 @@ wheels = [
|
|
|
1380
1382
|
{ url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" },
|
|
1381
1383
|
]
|
|
1382
1384
|
|
|
1385
|
+
[[package]]
|
|
1386
|
+
name = "mypy-pytest-parametrize"
|
|
1387
|
+
version = "2026.10.5"
|
|
1388
|
+
source = { registry = "https://pypi.org/simple" }
|
|
1389
|
+
dependencies = [
|
|
1390
|
+
{ name = "mypy" },
|
|
1391
|
+
{ name = "pytest" },
|
|
1392
|
+
{ name = "typing-extensions" },
|
|
1393
|
+
]
|
|
1394
|
+
sdist = { url = "https://files.pythonhosted.org/packages/ae/14/5adf231330daad6ec6e5f1c3433ec181ac554d75b3e0d4bc51a54576a371/mypy_pytest_parametrize-2026.10.5.tar.gz", hash = "sha256:a4776e5b13816a40b7677b6e9d777d8fa75f49bc08e656731235b4e66071bb74", size = 27576, upload-time = "2026-10-05T11:59:42.493Z" }
|
|
1395
|
+
wheels = [
|
|
1396
|
+
{ url = "https://files.pythonhosted.org/packages/47/3e/78fc9b9351a6b0dcf398bab37467b043928927caf78481d9d0bcbe1c9700/mypy_pytest_parametrize-2026.10.5-py3-none-any.whl", hash = "sha256:b4ac6fbae8ee9b5b4d3200d45393d322ede45bdda677030612d64bff0dfb05c0", size = 8654, upload-time = "2026-10-05T11:59:41.282Z" },
|
|
1397
|
+
]
|
|
1398
|
+
|
|
1383
1399
|
[[package]]
|
|
1384
1400
|
name = "mypy-strict-kwargs"
|
|
1385
1401
|
version = "2026.8.25.1"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
2026.10.1.1
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/.github/workflows/dependabot-merge.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/src/hackerrank_cli.egg-info/entry_points.txt
RENAMED
|
File without changes
|
{hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/src/hackerrank_cli.egg-info/not-zip-safe
RENAMED
|
File without changes
|
{hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/src/hackerrank_cli.egg-info/requires.txt
RENAMED
|
File without changes
|
{hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/src/hackerrank_cli.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
{hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/styles/snapper/SemanticLineBreaks.yml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hackerrank_cli-2026.10.1.1 → hackerrank_cli-2026.10.7}/tests/test_help/test_help_upload_.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|