ezhpcy 0.4.2__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.
Files changed (55) hide show
  1. ezhpcy-0.4.2/PKG-INFO +168 -0
  2. ezhpcy-0.4.2/README.md +148 -0
  3. ezhpcy-0.4.2/pyproject.toml +99 -0
  4. ezhpcy-0.4.2/pyproject.toml.orig +123 -0
  5. ezhpcy-0.4.2/src/ezhpcy/__init__.py +0 -0
  6. ezhpcy-0.4.2/src/ezhpcy/cli/__init__.py +245 -0
  7. ezhpcy-0.4.2/src/ezhpcy/cli/__main__.py +3 -0
  8. ezhpcy-0.4.2/src/ezhpcy/cli/_errors.py +67 -0
  9. ezhpcy-0.4.2/src/ezhpcy/cli/_options.py +408 -0
  10. ezhpcy-0.4.2/src/ezhpcy/cli/_password.py +117 -0
  11. ezhpcy-0.4.2/src/ezhpcy/cli/_resolve.py +214 -0
  12. ezhpcy-0.4.2/src/ezhpcy/cli/_tunnel_status.py +222 -0
  13. ezhpcy-0.4.2/src/ezhpcy/cli/config/__init__.py +1 -0
  14. ezhpcy-0.4.2/src/ezhpcy/cli/config/edit.py +100 -0
  15. ezhpcy-0.4.2/src/ezhpcy/cli/config/load.py +156 -0
  16. ezhpcy-0.4.2/src/ezhpcy/cli/config/show.py +167 -0
  17. ezhpcy-0.4.2/src/ezhpcy/cli/doctor.py +258 -0
  18. ezhpcy-0.4.2/src/ezhpcy/cli/info.py +88 -0
  19. ezhpcy-0.4.2/src/ezhpcy/cli/keyring.py +30 -0
  20. ezhpcy-0.4.2/src/ezhpcy/cli/list_profiles.py +22 -0
  21. ezhpcy-0.4.2/src/ezhpcy/cli/provision.py +59 -0
  22. ezhpcy-0.4.2/src/ezhpcy/cli/prune.py +65 -0
  23. ezhpcy-0.4.2/src/ezhpcy/cli/tunnel.py +323 -0
  24. ezhpcy-0.4.2/src/ezhpcy/cli/utils/__init__.py +0 -0
  25. ezhpcy-0.4.2/src/ezhpcy/cli/utils/interrupts.py +26 -0
  26. ezhpcy-0.4.2/src/ezhpcy/cli/utils/prompt.py +34 -0
  27. ezhpcy-0.4.2/src/ezhpcy/cli/utils/ssh.py +308 -0
  28. ezhpcy-0.4.2/src/ezhpcy/cli/version.py +21 -0
  29. ezhpcy-0.4.2/src/ezhpcy/config.py +273 -0
  30. ezhpcy-0.4.2/src/ezhpcy/console.py +230 -0
  31. ezhpcy-0.4.2/src/ezhpcy/constants.py +26 -0
  32. ezhpcy-0.4.2/src/ezhpcy/logging.py +423 -0
  33. ezhpcy-0.4.2/src/ezhpcy/messages.py +196 -0
  34. ezhpcy-0.4.2/src/ezhpcy/permissions.py +100 -0
  35. ezhpcy-0.4.2/src/ezhpcy/provision_host.py +214 -0
  36. ezhpcy-0.4.2/src/ezhpcy/provision_local.py +169 -0
  37. ezhpcy-0.4.2/src/ezhpcy/scheduler/__init__.py +22 -0
  38. ezhpcy-0.4.2/src/ezhpcy/scheduler/base.py +239 -0
  39. ezhpcy-0.4.2/src/ezhpcy/scheduler/lsf.py +147 -0
  40. ezhpcy-0.4.2/src/ezhpcy/scheduler/pbs.py +180 -0
  41. ezhpcy-0.4.2/src/ezhpcy/scheduler/types.py +6 -0
  42. ezhpcy-0.4.2/src/ezhpcy/ssh.py +371 -0
  43. ezhpcy-0.4.2/src/ezhpcy/static/config/presets/DTU.toml.j2 +93 -0
  44. ezhpcy-0.4.2/src/ezhpcy/static/config/presets/generic.toml.j2 +31 -0
  45. ezhpcy-0.4.2/src/ezhpcy/tunnel/__init__.py +16 -0
  46. ezhpcy-0.4.2/src/ezhpcy/tunnel/lock.py +78 -0
  47. ezhpcy-0.4.2/src/ezhpcy/tunnel/session.py +856 -0
  48. ezhpcy-0.4.2/src/ezhpcy/tunnel/ssh_config.py +290 -0
  49. ezhpcy-0.4.2/src/ezhpcy/tunnel/status.py +57 -0
  50. ezhpcy-0.4.2/src/ezhpcy/types.py +340 -0
  51. ezhpcy-0.4.2/src/ezhpcy/utils.py +26 -0
  52. ezhpcy-0.4.2/src/ezhpcy/worker/__init__.py +29 -0
  53. ezhpcy-0.4.2/src/ezhpcy/worker/control.py +140 -0
  54. ezhpcy-0.4.2/src/ezhpcy/worker/job.py +207 -0
  55. ezhpcy-0.4.2/src/ezhpcy/worker/sshd.py +115 -0
ezhpcy-0.4.2/PKG-INFO ADDED
@@ -0,0 +1,168 @@
1
+ Metadata-Version: 2.4
2
+ Name: ezhpcy
3
+ Version: 0.4.2
4
+ Summary: A small tool to establish an SSH tunnel to an HPC compute node.
5
+ License-Expression: MIT
6
+ Requires-Dist: pydantic-extra-types>=2.11.1
7
+ Requires-Dist: pydantic-settings>=2.14.2
8
+ Requires-Dist: pydantic>=2.13.5
9
+ Requires-Dist: jinja2>=3.1.6
10
+ Requires-Dist: asyncssh>=2.24.1
11
+ Requires-Dist: rich>=15.0.0
12
+ Requires-Dist: cyclopts>=5.2.0
13
+ Requires-Dist: keyring>=25.7.0
14
+ Requires-Dist: secretstorage>=3.5.0 ; sys_platform == 'linux'
15
+ Requires-Dist: py-machineid>=1.0.0
16
+ Requires-Dist: platformdirs>=4.9.4
17
+ Requires-Dist: filelock>=4.2.0
18
+ Requires-Python: >=3.15
19
+ Description-Content-Type: text/markdown
20
+
21
+ # EzHPCy
22
+
23
+ EzHPCy is a small(ish) tool that makes it easy to establish an SSH connection directly
24
+ to a compute node on an HPC system such as the one(s) found at
25
+ Technical University of Denmark ([DTU]).
26
+
27
+ This allows the user to connect to the compute node using the remote server capabilities
28
+ of their favourite editor.
29
+
30
+ Key benefits:
31
+
32
+ - If you use **notebooks**, **debuggers**, and other such editor features, they now run on the compute node instead of login node.
33
+ - Any **terminals** you open in the connected editor are on the compute node.
34
+ - Any LLM extensions now run on the compute not, not login node. This reduces congestion on the login nodes significantly.
35
+ - Works with many editors and other tools (any compliant OpenSSH clients)
36
+
37
+ It works for networks that have the following properties:
38
+
39
+ - Compute nodes may or may not have OpenSSH server running
40
+ - User can expose (large, non-root) port on compute nodes
41
+ - Login node can be reached via SSH
42
+ - Login node can reach compute nodes over network
43
+ - Login node and compute node share a filesystem
44
+
45
+ Both batch jobs and interactive jobs are supported, though you should probably only
46
+ use interactive nodes to avoid invoking the ire of the HPC administrators and
47
+ wasting scarce resources on the shared facility.
48
+
49
+ Supported schedulers are:
50
+
51
+ - [IBM Spectrum LSF]: Batch and interactive
52
+ - [PBS Pro/OpenPBS]: Only interactive tested
53
+
54
+ **Please use EzHPCy responsibly!**
55
+ If you are not familiar with HPC systems, please familiarise yourself with their
56
+ operation and the guidelines of your local HPC system to avoid accidentally
57
+ abusing the resources that have kindly and generously been made available to you.
58
+
59
+ ## Coarse Overview
60
+
61
+ The operating principle of EzHPCy can be seen in the diagram below. In essence:
62
+
63
+ - Start an unprivileged, secure OpenSSH server on compute node
64
+ - Forward traffic to this through login node via SSH (`direct-tcpip`)
65
+
66
+ ```mermaid
67
+ sequenceDiagram
68
+ participant S as ssh ALIAS
69
+ participant T as ezhpcy tunnel PROFILE
70
+ participant L as HPC Login Node
71
+ participant W as HPC Compute Node
72
+
73
+ T->>L: Connect
74
+ T->>L: Submit job
75
+ L->>W: Start sshd
76
+ T->>T: Expose sshd as ALIAS
77
+
78
+ S->>T: Connect to ALIAS
79
+ T->>W: Forward via login node
80
+ S->>W: SSH session
81
+
82
+ T->>L: Ctrl+C: cancel job
83
+ ```
84
+
85
+ ## Security Considerations
86
+
87
+ Significant care has been given to the security of EzHPCy.
88
+ The networking setup is relatively simple with a small attack surface.
89
+ Industry standard implementations are used (OpenSSH, Python's `cryptography` library)
90
+ and only a standard, secure protocol is used (SSH).
91
+
92
+ Importantly, all traffic still goes through the login node and is authenticated using
93
+ the authentication scheme set up by the HPC administrators.
94
+ Nothing is circumvented or bypassed (see slight caveat below).
95
+
96
+ Because EzHPCy controls both the server and can instruct the client on which
97
+ authentication scheme to use for connections, it is able to harden the server
98
+ significantly:
99
+
100
+ - Generates a per-host key-pair (`ed25519`) and instructs clients to only trust this key
101
+ - Generates a per-profile key-pair (`ed25519`) and instructs server to only trust this key
102
+
103
+ This ensures that nobody else on the network can disguise themselves as a server to the
104
+ client, and similarly ensures that no one else on the HPC network can log in as a client.
105
+
106
+ Locally EzHPCy forwards all traffic on a chosen port to the remote server,
107
+ at which point authentication is done. This means that a local process on the client
108
+ system (such as a malicious user on the same system) can send traffic to the EzHPCy
109
+ managed OpenSSH server, though this would be immediately dropped as the malicious
110
+ user on the local client system would have no means with which to authenticate itself.
111
+
112
+ **Slight caveat:** EzHPCy allows you to securely store your password in the
113
+ keyring of your local operating system, if you so choose.
114
+ This does not weaken the security of the authentication scheme, but means
115
+ that if you leave your local PC unlocked and unattended,
116
+ someone could use this to access the HPC.
117
+ This is no different to the case where you had a regular connection to the HPC
118
+ open and left your PC unattended.
119
+ As such, this should not be a security concern to any reasonable security practitioner.
120
+ _This is disabled by default and somewhat a somewhat hidden feature to ensure
121
+ that users have some basic grasp of the terminal._
122
+
123
+ ## Implementation
124
+
125
+ EzHPCy is unapologetically modern and requires Python 3.15 to run.
126
+
127
+ ## License
128
+
129
+ EzHPCy is released under the [MIT License](LICENSE).
130
+
131
+ ## History
132
+
133
+ Previous, unreleased versions of EzHPCy used a proxy interface with an IPC protocol (see [Janelia] acknowledgement below).
134
+
135
+ A significant refactoring was done to switch to [`asyncssh`](https://github.com/ronf/asyncssh) from [`paramiko`](https://www.paramiko.org/) motivated by security, maintainance, and the desire to switch to an `async` implementation.
136
+
137
+ With this in mind, the CLI interface was first refactored to use the excellent [`cyclopts`](https://cyclopts.readthedocs.io/en/stable/) library by [Brian Pugh](https://github.com/BrianPugh) instead of [`typer`](https://typer.tiangolo.com/) in order to reduce the number of hacks required to achieve the interface I wanted and simultaneously getting native `async` functionality.
138
+
139
+ ## Acknowledgements
140
+
141
+ I had wondered for a while whether an easier instrumentation of the [DTU] HPC system
142
+ might be possible, in a way that would enable me to connect directly to a compute node
143
+ using my editor or other SSH-capable tools.
144
+
145
+ I stumbled upon [Janelia]'s configuration [found here](https://github.com/JaneliaSciComp/ssh_cluster_tunnel_for_vscode)
146
+ for their HPC system, which used OpenSSH's
147
+ `ProxyCommand` feature to tunnel through their HPC setup.
148
+ The first decent versions of EzHPCy (v0.1, v0.2) also used `ProxyCommand` and
149
+ a local TCP server in combination with a simple IPC protocol,
150
+ which worked quite well, but was overly complex and had a larger attack surface.
151
+
152
+ ## LLM Disclosure
153
+
154
+ **This README has been written entirely by a human; please read it!**
155
+
156
+ The very first versions of EzHPCy were made without the use of agentic programming.
157
+
158
+ Later refactoring and expansion of EzHPCy has made extensive use of LLMs, though
159
+ under somewhat careful review.
160
+ _I have found that even with the latest models,
161
+ they have to be kept on a relatively short leash,
162
+ lest they take over the project entirely and end up producing something
163
+ overly complex and entirely opaque._
164
+
165
+ [DTU]: https://www.dtu.dk/english
166
+ [Janelia]: https://www.hhmi.org/research/janelia
167
+ [PBS Pro/OpenPBS]: https://www.openpbs.org/
168
+ [IBM Spectrum LSF]: https://www.ibm.com/docs/en/spectrum-lsf
ezhpcy-0.4.2/README.md ADDED
@@ -0,0 +1,148 @@
1
+ # EzHPCy
2
+
3
+ EzHPCy is a small(ish) tool that makes it easy to establish an SSH connection directly
4
+ to a compute node on an HPC system such as the one(s) found at
5
+ Technical University of Denmark ([DTU]).
6
+
7
+ This allows the user to connect to the compute node using the remote server capabilities
8
+ of their favourite editor.
9
+
10
+ Key benefits:
11
+
12
+ - If you use **notebooks**, **debuggers**, and other such editor features, they now run on the compute node instead of login node.
13
+ - Any **terminals** you open in the connected editor are on the compute node.
14
+ - Any LLM extensions now run on the compute not, not login node. This reduces congestion on the login nodes significantly.
15
+ - Works with many editors and other tools (any compliant OpenSSH clients)
16
+
17
+ It works for networks that have the following properties:
18
+
19
+ - Compute nodes may or may not have OpenSSH server running
20
+ - User can expose (large, non-root) port on compute nodes
21
+ - Login node can be reached via SSH
22
+ - Login node can reach compute nodes over network
23
+ - Login node and compute node share a filesystem
24
+
25
+ Both batch jobs and interactive jobs are supported, though you should probably only
26
+ use interactive nodes to avoid invoking the ire of the HPC administrators and
27
+ wasting scarce resources on the shared facility.
28
+
29
+ Supported schedulers are:
30
+
31
+ - [IBM Spectrum LSF]: Batch and interactive
32
+ - [PBS Pro/OpenPBS]: Only interactive tested
33
+
34
+ **Please use EzHPCy responsibly!**
35
+ If you are not familiar with HPC systems, please familiarise yourself with their
36
+ operation and the guidelines of your local HPC system to avoid accidentally
37
+ abusing the resources that have kindly and generously been made available to you.
38
+
39
+ ## Coarse Overview
40
+
41
+ The operating principle of EzHPCy can be seen in the diagram below. In essence:
42
+
43
+ - Start an unprivileged, secure OpenSSH server on compute node
44
+ - Forward traffic to this through login node via SSH (`direct-tcpip`)
45
+
46
+ ```mermaid
47
+ sequenceDiagram
48
+ participant S as ssh ALIAS
49
+ participant T as ezhpcy tunnel PROFILE
50
+ participant L as HPC Login Node
51
+ participant W as HPC Compute Node
52
+
53
+ T->>L: Connect
54
+ T->>L: Submit job
55
+ L->>W: Start sshd
56
+ T->>T: Expose sshd as ALIAS
57
+
58
+ S->>T: Connect to ALIAS
59
+ T->>W: Forward via login node
60
+ S->>W: SSH session
61
+
62
+ T->>L: Ctrl+C: cancel job
63
+ ```
64
+
65
+ ## Security Considerations
66
+
67
+ Significant care has been given to the security of EzHPCy.
68
+ The networking setup is relatively simple with a small attack surface.
69
+ Industry standard implementations are used (OpenSSH, Python's `cryptography` library)
70
+ and only a standard, secure protocol is used (SSH).
71
+
72
+ Importantly, all traffic still goes through the login node and is authenticated using
73
+ the authentication scheme set up by the HPC administrators.
74
+ Nothing is circumvented or bypassed (see slight caveat below).
75
+
76
+ Because EzHPCy controls both the server and can instruct the client on which
77
+ authentication scheme to use for connections, it is able to harden the server
78
+ significantly:
79
+
80
+ - Generates a per-host key-pair (`ed25519`) and instructs clients to only trust this key
81
+ - Generates a per-profile key-pair (`ed25519`) and instructs server to only trust this key
82
+
83
+ This ensures that nobody else on the network can disguise themselves as a server to the
84
+ client, and similarly ensures that no one else on the HPC network can log in as a client.
85
+
86
+ Locally EzHPCy forwards all traffic on a chosen port to the remote server,
87
+ at which point authentication is done. This means that a local process on the client
88
+ system (such as a malicious user on the same system) can send traffic to the EzHPCy
89
+ managed OpenSSH server, though this would be immediately dropped as the malicious
90
+ user on the local client system would have no means with which to authenticate itself.
91
+
92
+ **Slight caveat:** EzHPCy allows you to securely store your password in the
93
+ keyring of your local operating system, if you so choose.
94
+ This does not weaken the security of the authentication scheme, but means
95
+ that if you leave your local PC unlocked and unattended,
96
+ someone could use this to access the HPC.
97
+ This is no different to the case where you had a regular connection to the HPC
98
+ open and left your PC unattended.
99
+ As such, this should not be a security concern to any reasonable security practitioner.
100
+ _This is disabled by default and somewhat a somewhat hidden feature to ensure
101
+ that users have some basic grasp of the terminal._
102
+
103
+ ## Implementation
104
+
105
+ EzHPCy is unapologetically modern and requires Python 3.15 to run.
106
+
107
+ ## License
108
+
109
+ EzHPCy is released under the [MIT License](LICENSE).
110
+
111
+ ## History
112
+
113
+ Previous, unreleased versions of EzHPCy used a proxy interface with an IPC protocol (see [Janelia] acknowledgement below).
114
+
115
+ A significant refactoring was done to switch to [`asyncssh`](https://github.com/ronf/asyncssh) from [`paramiko`](https://www.paramiko.org/) motivated by security, maintainance, and the desire to switch to an `async` implementation.
116
+
117
+ With this in mind, the CLI interface was first refactored to use the excellent [`cyclopts`](https://cyclopts.readthedocs.io/en/stable/) library by [Brian Pugh](https://github.com/BrianPugh) instead of [`typer`](https://typer.tiangolo.com/) in order to reduce the number of hacks required to achieve the interface I wanted and simultaneously getting native `async` functionality.
118
+
119
+ ## Acknowledgements
120
+
121
+ I had wondered for a while whether an easier instrumentation of the [DTU] HPC system
122
+ might be possible, in a way that would enable me to connect directly to a compute node
123
+ using my editor or other SSH-capable tools.
124
+
125
+ I stumbled upon [Janelia]'s configuration [found here](https://github.com/JaneliaSciComp/ssh_cluster_tunnel_for_vscode)
126
+ for their HPC system, which used OpenSSH's
127
+ `ProxyCommand` feature to tunnel through their HPC setup.
128
+ The first decent versions of EzHPCy (v0.1, v0.2) also used `ProxyCommand` and
129
+ a local TCP server in combination with a simple IPC protocol,
130
+ which worked quite well, but was overly complex and had a larger attack surface.
131
+
132
+ ## LLM Disclosure
133
+
134
+ **This README has been written entirely by a human; please read it!**
135
+
136
+ The very first versions of EzHPCy were made without the use of agentic programming.
137
+
138
+ Later refactoring and expansion of EzHPCy has made extensive use of LLMs, though
139
+ under somewhat careful review.
140
+ _I have found that even with the latest models,
141
+ they have to be kept on a relatively short leash,
142
+ lest they take over the project entirely and end up producing something
143
+ overly complex and entirely opaque._
144
+
145
+ [DTU]: https://www.dtu.dk/english
146
+ [Janelia]: https://www.hhmi.org/research/janelia
147
+ [PBS Pro/OpenPBS]: https://www.openpbs.org/
148
+ [IBM Spectrum LSF]: https://www.ibm.com/docs/en/spectrum-lsf
@@ -0,0 +1,99 @@
1
+ [project]
2
+ name = "ezhpcy"
3
+ version = "0.4.2"
4
+ license = "MIT"
5
+ readme = "README.md"
6
+ description = "A small tool to establish an SSH tunnel to an HPC compute node."
7
+ requires-python = ">=3.15"
8
+ dependencies = [
9
+ "pydantic-extra-types>=2.11.1",
10
+ "pydantic-settings>=2.14.2",
11
+ "pydantic>=2.13.5",
12
+ "jinja2>=3.1.6",
13
+ "asyncssh>=2.24.1",
14
+ "rich>=15.0.0",
15
+ "cyclopts>=5.2.0",
16
+ "keyring>=25.7.0",
17
+ "secretstorage>=3.5.0 ; sys_platform == 'linux'",
18
+ "py-machineid>=1.0.0",
19
+ "platformdirs>=4.9.4",
20
+ "filelock>=4.2.0",
21
+ ]
22
+
23
+ [project.scripts]
24
+ ezhpcy = "ezhpcy.cli:main"
25
+
26
+ [dependency-groups]
27
+ format = ["ruff==0.17.1"]
28
+ pre-commit = [
29
+ "prek==0.5.6",
30
+ { include-group = "typecheck" },
31
+ ]
32
+ test = [
33
+ "pytest>=9.1.1",
34
+ "pytest-asyncio>=1.4.0",
35
+ "pytest-cov>=7.1.0",
36
+ ]
37
+ typecheck = ["pyrefly==1.4.0"]
38
+
39
+ [[dependency-groups.dev]]
40
+ include-group = "format"
41
+
42
+ [[dependency-groups.dev]]
43
+ include-group = "pre-commit"
44
+
45
+ [[dependency-groups.dev]]
46
+ include-group = "test"
47
+
48
+ [[dependency-groups.dev]]
49
+ include-group = "typecheck"
50
+
51
+ [tool.pytest.ini_options]
52
+ asyncio_mode = "auto"
53
+ asyncio_default_fixture_loop_scope = "function"
54
+ markers = ["real_machine_id: read this machine's ID instead of the fixed one tests get"]
55
+
56
+ [tool.coverage.run]
57
+ source = ["ezhpcy"]
58
+ branch = true
59
+
60
+ [tool.coverage.report]
61
+ show_missing = true
62
+ skip_covered = true
63
+
64
+ [tool.ruff.lint]
65
+ preview = true
66
+ extend-select = [
67
+ "A",
68
+ "ASYNC",
69
+ "B",
70
+ "DTZ",
71
+ "EXE",
72
+ "FURB",
73
+ "I",
74
+ "INP",
75
+ "LOG",
76
+ "PTH",
77
+ "T10",
78
+ "TID",
79
+ "UP",
80
+ "YTT",
81
+ ]
82
+ ignore = ["RUF106"]
83
+
84
+ [tool.ruff.lint.isort]
85
+ combine-as-imports = true
86
+
87
+ [tool.ruff.lint.per-file-ignores]
88
+ "tests/**" = ["RUF069"]
89
+ "scripts/**" = ["INP"]
90
+
91
+ [tool.pyrefly]
92
+ project-includes = [
93
+ "src/**/*.py*",
94
+ "src/**/*.ipynb",
95
+ ]
96
+
97
+ [build-system]
98
+ requires = ["uv_build>=0.13.1,<0.14"]
99
+ build-backend = "uv_build"
@@ -0,0 +1,123 @@
1
+ [project]
2
+ name = "ezhpcy"
3
+ version = "0.4.2"
4
+
5
+ license = "MIT"
6
+ readme = "README.md"
7
+ description = "A small tool to establish an SSH tunnel to an HPC compute node."
8
+
9
+ requires-python = ">=3.15"
10
+ dependencies = [
11
+ # Pydantic
12
+ "pydantic-extra-types>=2.11.1",
13
+ "pydantic-settings>=2.14.2",
14
+ "pydantic>=2.13.5",
15
+ # Templates
16
+ "jinja2>=3.1.6",
17
+ # SSH
18
+ "asyncssh>=2.24.1",
19
+ # CLI
20
+ "rich>=15.0.0",
21
+ "cyclopts>=5.2.0",
22
+ # Keyring, secretstorage is for keyring on Linux
23
+ "keyring>=25.7.0",
24
+ "secretstorage>=3.5.0 ; sys_platform == 'linux'",
25
+ # Utils
26
+ "py-machineid>=1.0.0",
27
+ "platformdirs>=4.9.4",
28
+ "filelock>=4.2.0",
29
+ ]
30
+
31
+ [project.scripts]
32
+ ezhpcy = "ezhpcy.cli:main"
33
+
34
+ [dependency-groups]
35
+ dev = [
36
+ { include-group = "format" },
37
+ { include-group = "pre-commit" },
38
+ { include-group = "test" },
39
+ { include-group = "typecheck" },
40
+ ]
41
+
42
+ format = [
43
+ "ruff==0.17.1",
44
+ ]
45
+ pre-commit = [
46
+ "prek==0.5.6", # keep in sync with .github/workflows/pre-commit.yaml
47
+ { include-group = "typecheck" }, # For pyrefly that uses pyrefly from deps
48
+ ]
49
+ test = [
50
+ "pytest>=9.1.1",
51
+ "pytest-asyncio>=1.4.0",
52
+ "pytest-cov>=7.1.0",
53
+ ]
54
+ typecheck = [
55
+ "pyrefly==1.4.0",
56
+ ]
57
+
58
+ # Tests
59
+ [tool.pytest.ini_options]
60
+ # `async def` tests and fixtures run on asyncio without a marker
61
+ asyncio_mode = "auto"
62
+ asyncio_default_fixture_loop_scope = "function"
63
+ markers = [
64
+ "real_machine_id: read this machine's ID instead of the fixed one tests get",
65
+ ]
66
+
67
+ # Test coverage
68
+ [tool.coverage.run]
69
+ source = ["ezhpcy"]
70
+ branch = true
71
+
72
+ [tool.coverage.report]
73
+ show_missing = true
74
+ skip_covered = true
75
+
76
+ # Ruff - Linting
77
+ [tool.ruff.lint]
78
+ preview = true
79
+ extend-select = [
80
+ "A", # flake8-builtins
81
+ "ASYNC", # flake8-async
82
+ "B", # flake8-bugbear
83
+ "DTZ", # flake8-datetimetz
84
+ "EXE", # flake8-executable
85
+ "FURB", # refurb
86
+ "I", # isort
87
+ "INP", # flake8-no-pep420
88
+ "LOG", # flake8-logging
89
+ "PTH", # flake8-use-pathlib
90
+ "T10", # flake8-debugger
91
+ "TID", # flake8-tidy-imports
92
+ "UP", # pyupgrade
93
+ "YTT", # flake8-2020
94
+ ]
95
+ ignore = [
96
+ "RUF106", # rule-codecs-in-suppression-comments
97
+ ]
98
+ isort.combine-as-imports = true
99
+
100
+ [tool.ruff.lint.per-file-ignores]
101
+ # Tests
102
+ "tests/**" = [
103
+ "RUF069", # float-equality-comparison, in tests we sometimes want eq. check
104
+ ]
105
+
106
+ # Standalone scripts
107
+ "scripts/**" = [
108
+ "INP", # no-pep420, scripts are standalone and not part of a package
109
+ ]
110
+
111
+ # Pyrefly - Type checking
112
+ [tool.pyrefly]
113
+ project-includes = [
114
+ "src/**/*.py*",
115
+ "src/**/*.ipynb",
116
+ ]
117
+
118
+ # Build system
119
+ [build-system]
120
+ # Keep the lower bound in sync with the setup-uv `version` in .github/workflows/
121
+ # (pre-commit.yaml, tests.yml, publish.yml x2)
122
+ requires = ["uv_build>=0.13.1,<0.14"]
123
+ build-backend = "uv_build"
File without changes