rms-picmaker 1.0.0__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 (219) hide show
  1. rms_picmaker-1.0.0/.cursor/rules/bug_report.mdc +79 -0
  2. rms_picmaker-1.0.0/.cursor/rules/dependency_management.mdc +53 -0
  3. rms_picmaker-1.0.0/.cursor/rules/documentation.mdc +65 -0
  4. rms_picmaker-1.0.0/.cursor/rules/environment_best_practices.mdc +40 -0
  5. rms_picmaker-1.0.0/.cursor/rules/git_workflow.mdc +66 -0
  6. rms_picmaker-1.0.0/.cursor/rules/how_to.mdc +74 -0
  7. rms_picmaker-1.0.0/.cursor/rules/pull_request.mdc +43 -0
  8. rms_picmaker-1.0.0/.cursor/rules/python_best_practices.mdc +145 -0
  9. rms_picmaker-1.0.0/.cursor/rules/security.mdc +48 -0
  10. rms_picmaker-1.0.0/.cursor/settings.json +9 -0
  11. rms_picmaker-1.0.0/.cursor/skills/critique-test-suite/SKILL.md +287 -0
  12. rms_picmaker-1.0.0/.cursor/skills/python-codebase-analysis/SKILL.md +189 -0
  13. rms_picmaker-1.0.0/.cursor/skills/python-codebase-analysis/reference.md +81 -0
  14. rms_picmaker-1.0.0/.cursor/skills/run-all-checks/SKILL.md +157 -0
  15. rms_picmaker-1.0.0/.github/ISSUE_TEMPLATE/bug_report.md +43 -0
  16. rms_picmaker-1.0.0/.github/ISSUE_TEMPLATE/config.yml +1 -0
  17. rms_picmaker-1.0.0/.github/ISSUE_TEMPLATE/feature_request.md +26 -0
  18. rms_picmaker-1.0.0/.github/ISSUE_TEMPLATE/other.md +24 -0
  19. rms_picmaker-1.0.0/.github/pull_request_template.md +53 -0
  20. rms_picmaker-1.0.0/.github/workflows/publish_to_pypi.yml +43 -0
  21. rms_picmaker-1.0.0/.github/workflows/publish_to_test_pypi.yml +43 -0
  22. rms_picmaker-1.0.0/.github/workflows/run-tests.yml +106 -0
  23. rms_picmaker-1.0.0/.gitignore +178 -0
  24. rms_picmaker-1.0.0/.readthedocs.yaml +33 -0
  25. rms_picmaker-1.0.0/.vscode/settings.json +9 -0
  26. rms_picmaker-1.0.0/CODE_OF_CONDUCT.md +132 -0
  27. rms_picmaker-1.0.0/CONTRIBUTING.md +146 -0
  28. rms_picmaker-1.0.0/LICENSE +201 -0
  29. rms_picmaker-1.0.0/PKG-INFO +159 -0
  30. rms_picmaker-1.0.0/README.md +103 -0
  31. rms_picmaker-1.0.0/codecov.yml +8 -0
  32. rms_picmaker-1.0.0/docs/Makefile +20 -0
  33. rms_picmaker-1.0.0/docs/code_of_conduct.md +6 -0
  34. rms_picmaker-1.0.0/docs/conf.py +145 -0
  35. rms_picmaker-1.0.0/docs/contributing.rst +13 -0
  36. rms_picmaker-1.0.0/docs/dev/adding_an_instrument.rst +193 -0
  37. rms_picmaker-1.0.0/docs/dev/module_layout.rst +168 -0
  38. rms_picmaker-1.0.0/docs/dev/pipeline.rst +293 -0
  39. rms_picmaker-1.0.0/docs/dev/releasing.rst +76 -0
  40. rms_picmaker-1.0.0/docs/dev/repository_overview.rst +85 -0
  41. rms_picmaker-1.0.0/docs/dev/running_tests.rst +28 -0
  42. rms_picmaker-1.0.0/docs/developer_guide.rst +31 -0
  43. rms_picmaker-1.0.0/docs/index.rst +25 -0
  44. rms_picmaker-1.0.0/docs/make.bat +35 -0
  45. rms_picmaker-1.0.0/docs/module.rst +216 -0
  46. rms_picmaker-1.0.0/docs/user_guide.rst +503 -0
  47. rms_picmaker-1.0.0/pyproject.toml +204 -0
  48. rms_picmaker-1.0.0/requirements.txt +5 -0
  49. rms_picmaker-1.0.0/scripts/read-docs.sh +71 -0
  50. rms_picmaker-1.0.0/scripts/run-all-checks.sh +647 -0
  51. rms_picmaker-1.0.0/setup.cfg +4 -0
  52. rms_picmaker-1.0.0/src/picmaker/__init__.py +95 -0
  53. rms_picmaker-1.0.0/src/picmaker/_filters.py +60 -0
  54. rms_picmaker-1.0.0/src/picmaker/_rgb.py +37 -0
  55. rms_picmaker-1.0.0/src/picmaker/_version.py +24 -0
  56. rms_picmaker-1.0.0/src/picmaker/cli.py +619 -0
  57. rms_picmaker-1.0.0/src/picmaker/color.py +73 -0
  58. rms_picmaker-1.0.0/src/picmaker/colornames.py +875 -0
  59. rms_picmaker-1.0.0/src/picmaker/enhance.py +388 -0
  60. rms_picmaker-1.0.0/src/picmaker/geometry.py +630 -0
  61. rms_picmaker-1.0.0/src/picmaker/instruments/__init__.py +49 -0
  62. rms_picmaker-1.0.0/src/picmaker/instruments/cassini.py +114 -0
  63. rms_picmaker-1.0.0/src/picmaker/instruments/galileo.py +118 -0
  64. rms_picmaker-1.0.0/src/picmaker/instruments/hst.py +154 -0
  65. rms_picmaker-1.0.0/src/picmaker/instruments/nh.py +96 -0
  66. rms_picmaker-1.0.0/src/picmaker/instruments/voyager.py +95 -0
  67. rms_picmaker-1.0.0/src/picmaker/io.py +578 -0
  68. rms_picmaker-1.0.0/src/picmaker/options.py +128 -0
  69. rms_picmaker-1.0.0/src/picmaker/picmaker.py +103 -0
  70. rms_picmaker-1.0.0/src/picmaker/pil_utils.py +163 -0
  71. rms_picmaker-1.0.0/src/picmaker/pipeline.py +580 -0
  72. rms_picmaker-1.0.0/src/picmaker/py.typed +0 -0
  73. rms_picmaker-1.0.0/src/picmaker/tiff16.py +479 -0
  74. rms_picmaker-1.0.0/src/rms_picmaker.egg-info/PKG-INFO +159 -0
  75. rms_picmaker-1.0.0/src/rms_picmaker.egg-info/SOURCES.txt +217 -0
  76. rms_picmaker-1.0.0/src/rms_picmaker.egg-info/dependency_links.txt +1 -0
  77. rms_picmaker-1.0.0/src/rms_picmaker.egg-info/entry_points.txt +2 -0
  78. rms_picmaker-1.0.0/src/rms_picmaker.egg-info/requires.txt +27 -0
  79. rms_picmaker-1.0.0/src/rms_picmaker.egg-info/top_level.txt +1 -0
  80. rms_picmaker-1.0.0/tests/conftest.py +28 -0
  81. rms_picmaker-1.0.0/tests/fixture_recipes/cassini_iss.recipe.py +35 -0
  82. rms_picmaker-1.0.0/tests/fixture_recipes/corrupt_fits.recipe.py +32 -0
  83. rms_picmaker-1.0.0/tests/fixture_recipes/corrupt_vicar.recipe.py +24 -0
  84. rms_picmaker-1.0.0/tests/fixture_recipes/galileo_ssi_a.recipe.py +36 -0
  85. rms_picmaker-1.0.0/tests/fixture_recipes/galileo_ssi_b.recipe.py +28 -0
  86. rms_picmaker-1.0.0/tests/fixture_recipes/generate_snapshots.py +127 -0
  87. rms_picmaker-1.0.0/tests/fixture_recipes/hst_acs.recipe.py +47 -0
  88. rms_picmaker-1.0.0/tests/fixture_recipes/hst_wfc3.recipe.py +31 -0
  89. rms_picmaker-1.0.0/tests/fixture_recipes/hst_wfpc2.recipe.py +35 -0
  90. rms_picmaker-1.0.0/tests/fixture_recipes/malformed_numpy.recipe.py +22 -0
  91. rms_picmaker-1.0.0/tests/fixture_recipes/malformed_pickle.recipe.py +29 -0
  92. rms_picmaker-1.0.0/tests/fixture_recipes/nh_mvic.recipe.py +31 -0
  93. rms_picmaker-1.0.0/tests/fixture_recipes/pds3_sample.recipe.py +48 -0
  94. rms_picmaker-1.0.0/tests/fixture_recipes/regenerate_all.py +40 -0
  95. rms_picmaker-1.0.0/tests/fixture_recipes/small_grayscale.recipe.py +29 -0
  96. rms_picmaker-1.0.0/tests/fixture_recipes/small_rgb.recipe.py +30 -0
  97. rms_picmaker-1.0.0/tests/fixture_recipes/small_tiff16.recipe.py +24 -0
  98. rms_picmaker-1.0.0/tests/fixture_recipes/voyager_iss.recipe.py +35 -0
  99. rms_picmaker-1.0.0/tests/fixtures/.baseline-flags.txt +60 -0
  100. rms_picmaker-1.0.0/tests/fixtures/.baseline-help.txt +209 -0
  101. rms_picmaker-1.0.0/tests/fixtures/cassini_iss.vic +0 -0
  102. rms_picmaker-1.0.0/tests/fixtures/corrupt_fits.fits +1 -0
  103. rms_picmaker-1.0.0/tests/fixtures/corrupt_vicar.vic +1 -0
  104. rms_picmaker-1.0.0/tests/fixtures/expected/cassini_iss--colormap_red_blue.jpg +0 -0
  105. rms_picmaker-1.0.0/tests/fixtures/expected/cassini_iss--default.jpg +0 -0
  106. rms_picmaker-1.0.0/tests/fixtures/expected/cassini_iss--frame_128_pad.jpg +0 -0
  107. rms_picmaker-1.0.0/tests/fixtures/expected/cassini_iss--frame_max_50.jpg +0 -0
  108. rms_picmaker-1.0.0/tests/fixtures/expected/cassini_iss--gamma2.jpg +0 -0
  109. rms_picmaker-1.0.0/tests/fixtures/expected/cassini_iss--pct5_95.jpg +0 -0
  110. rms_picmaker-1.0.0/tests/fixtures/expected/cassini_iss--rot90.jpg +0 -0
  111. rms_picmaker-1.0.0/tests/fixtures/expected/cassini_iss--tint.jpg +0 -0
  112. rms_picmaker-1.0.0/tests/fixtures/expected/cassini_iss--twobytes_tiff.tiff +0 -0
  113. rms_picmaker-1.0.0/tests/fixtures/expected/galileo_ssi_a--colormap_red_blue.jpg +0 -0
  114. rms_picmaker-1.0.0/tests/fixtures/expected/galileo_ssi_a--default.jpg +0 -0
  115. rms_picmaker-1.0.0/tests/fixtures/expected/galileo_ssi_a--frame_128_pad.jpg +0 -0
  116. rms_picmaker-1.0.0/tests/fixtures/expected/galileo_ssi_a--frame_max_50.jpg +0 -0
  117. rms_picmaker-1.0.0/tests/fixtures/expected/galileo_ssi_a--gamma2.jpg +0 -0
  118. rms_picmaker-1.0.0/tests/fixtures/expected/galileo_ssi_a--pct5_95.jpg +0 -0
  119. rms_picmaker-1.0.0/tests/fixtures/expected/galileo_ssi_a--rot90.jpg +0 -0
  120. rms_picmaker-1.0.0/tests/fixtures/expected/galileo_ssi_a--tint.jpg +0 -0
  121. rms_picmaker-1.0.0/tests/fixtures/expected/galileo_ssi_a--twobytes_tiff.tiff +0 -0
  122. rms_picmaker-1.0.0/tests/fixtures/expected/hst_acs--colormap_red_blue.jpg +0 -0
  123. rms_picmaker-1.0.0/tests/fixtures/expected/hst_acs--default.jpg +0 -0
  124. rms_picmaker-1.0.0/tests/fixtures/expected/hst_acs--frame_128_pad.jpg +0 -0
  125. rms_picmaker-1.0.0/tests/fixtures/expected/hst_acs--frame_max_50.jpg +0 -0
  126. rms_picmaker-1.0.0/tests/fixtures/expected/hst_acs--gamma2.jpg +0 -0
  127. rms_picmaker-1.0.0/tests/fixtures/expected/hst_acs--pct5_95.jpg +0 -0
  128. rms_picmaker-1.0.0/tests/fixtures/expected/hst_acs--rot90.jpg +0 -0
  129. rms_picmaker-1.0.0/tests/fixtures/expected/hst_acs--tint.jpg +0 -0
  130. rms_picmaker-1.0.0/tests/fixtures/expected/hst_acs--twobytes_tiff.tiff +0 -0
  131. rms_picmaker-1.0.0/tests/fixtures/expected/hst_wfc3--colormap_red_blue.jpg +0 -0
  132. rms_picmaker-1.0.0/tests/fixtures/expected/hst_wfc3--default.jpg +0 -0
  133. rms_picmaker-1.0.0/tests/fixtures/expected/hst_wfc3--frame_128_pad.jpg +0 -0
  134. rms_picmaker-1.0.0/tests/fixtures/expected/hst_wfc3--frame_max_50.jpg +0 -0
  135. rms_picmaker-1.0.0/tests/fixtures/expected/hst_wfc3--gamma2.jpg +0 -0
  136. rms_picmaker-1.0.0/tests/fixtures/expected/hst_wfc3--pct5_95.jpg +0 -0
  137. rms_picmaker-1.0.0/tests/fixtures/expected/hst_wfc3--rot90.jpg +0 -0
  138. rms_picmaker-1.0.0/tests/fixtures/expected/hst_wfc3--tint.jpg +0 -0
  139. rms_picmaker-1.0.0/tests/fixtures/expected/hst_wfc3--twobytes_tiff.tiff +0 -0
  140. rms_picmaker-1.0.0/tests/fixtures/expected/hst_wfpc2--colormap_red_blue.jpg +0 -0
  141. rms_picmaker-1.0.0/tests/fixtures/expected/hst_wfpc2--default.jpg +0 -0
  142. rms_picmaker-1.0.0/tests/fixtures/expected/hst_wfpc2--frame_128_pad.jpg +0 -0
  143. rms_picmaker-1.0.0/tests/fixtures/expected/hst_wfpc2--frame_max_50.jpg +0 -0
  144. rms_picmaker-1.0.0/tests/fixtures/expected/hst_wfpc2--gamma2.jpg +0 -0
  145. rms_picmaker-1.0.0/tests/fixtures/expected/hst_wfpc2--pct5_95.jpg +0 -0
  146. rms_picmaker-1.0.0/tests/fixtures/expected/hst_wfpc2--rot90.jpg +0 -0
  147. rms_picmaker-1.0.0/tests/fixtures/expected/hst_wfpc2--tint.jpg +0 -0
  148. rms_picmaker-1.0.0/tests/fixtures/expected/hst_wfpc2--twobytes_tiff.tiff +0 -0
  149. rms_picmaker-1.0.0/tests/fixtures/expected/nh_mvic--colormap_red_blue.jpg +0 -0
  150. rms_picmaker-1.0.0/tests/fixtures/expected/nh_mvic--default.jpg +0 -0
  151. rms_picmaker-1.0.0/tests/fixtures/expected/nh_mvic--frame_128_pad.jpg +0 -0
  152. rms_picmaker-1.0.0/tests/fixtures/expected/nh_mvic--frame_max_50.jpg +0 -0
  153. rms_picmaker-1.0.0/tests/fixtures/expected/nh_mvic--gamma2.jpg +0 -0
  154. rms_picmaker-1.0.0/tests/fixtures/expected/nh_mvic--pct5_95.jpg +0 -0
  155. rms_picmaker-1.0.0/tests/fixtures/expected/nh_mvic--rot90.jpg +0 -0
  156. rms_picmaker-1.0.0/tests/fixtures/expected/nh_mvic--tint.jpg +0 -0
  157. rms_picmaker-1.0.0/tests/fixtures/expected/nh_mvic--twobytes_tiff.tiff +0 -0
  158. rms_picmaker-1.0.0/tests/fixtures/expected/voyager_iss--colormap_red_blue.jpg +0 -0
  159. rms_picmaker-1.0.0/tests/fixtures/expected/voyager_iss--default.jpg +0 -0
  160. rms_picmaker-1.0.0/tests/fixtures/expected/voyager_iss--frame_128_pad.jpg +0 -0
  161. rms_picmaker-1.0.0/tests/fixtures/expected/voyager_iss--frame_max_50.jpg +0 -0
  162. rms_picmaker-1.0.0/tests/fixtures/expected/voyager_iss--gamma2.jpg +0 -0
  163. rms_picmaker-1.0.0/tests/fixtures/expected/voyager_iss--pct5_95.jpg +0 -0
  164. rms_picmaker-1.0.0/tests/fixtures/expected/voyager_iss--rot90.jpg +0 -0
  165. rms_picmaker-1.0.0/tests/fixtures/expected/voyager_iss--tint.jpg +0 -0
  166. rms_picmaker-1.0.0/tests/fixtures/expected/voyager_iss--twobytes_tiff.tiff +0 -0
  167. rms_picmaker-1.0.0/tests/fixtures/galileo_ssi_a.vic +0 -0
  168. rms_picmaker-1.0.0/tests/fixtures/galileo_ssi_b.vic +0 -0
  169. rms_picmaker-1.0.0/tests/fixtures/hst_acs.fits +0 -0
  170. rms_picmaker-1.0.0/tests/fixtures/hst_wfc3.fits +0 -0
  171. rms_picmaker-1.0.0/tests/fixtures/hst_wfpc2.fits +0 -0
  172. rms_picmaker-1.0.0/tests/fixtures/malformed_numpy.bin +0 -0
  173. rms_picmaker-1.0.0/tests/fixtures/malformed_pickle.bin +1 -0
  174. rms_picmaker-1.0.0/tests/fixtures/nh_mvic.fits +0 -0
  175. rms_picmaker-1.0.0/tests/fixtures/pds3_sample.IMG +0 -0
  176. rms_picmaker-1.0.0/tests/fixtures/small_grayscale.png +0 -0
  177. rms_picmaker-1.0.0/tests/fixtures/small_rgb.png +0 -0
  178. rms_picmaker-1.0.0/tests/fixtures/small_tiff16.tiff +0 -0
  179. rms_picmaker-1.0.0/tests/fixtures/two_versions.txt +2 -0
  180. rms_picmaker-1.0.0/tests/fixtures/voyager_iss.vic +0 -0
  181. rms_picmaker-1.0.0/tests/snapshots_index.py +81 -0
  182. rms_picmaker-1.0.0/tests/test_alt_strip_alias.py +65 -0
  183. rms_picmaker-1.0.0/tests/test_api_compat.py +159 -0
  184. rms_picmaker-1.0.0/tests/test_apply_gamma.py +55 -0
  185. rms_picmaker-1.0.0/tests/test_cli.py +106 -0
  186. rms_picmaker-1.0.0/tests/test_cli_unit.py +434 -0
  187. rms_picmaker-1.0.0/tests/test_color.py +83 -0
  188. rms_picmaker-1.0.0/tests/test_enhance.py +97 -0
  189. rms_picmaker-1.0.0/tests/test_enhance_branches.py +156 -0
  190. rms_picmaker-1.0.0/tests/test_filters_branches.py +27 -0
  191. rms_picmaker-1.0.0/tests/test_frame_max.py +24 -0
  192. rms_picmaker-1.0.0/tests/test_geometry.py +113 -0
  193. rms_picmaker-1.0.0/tests/test_geometry_branches.py +264 -0
  194. rms_picmaker-1.0.0/tests/test_geometry_extra.py +135 -0
  195. rms_picmaker-1.0.0/tests/test_happy_path_no_warnings.py +22 -0
  196. rms_picmaker-1.0.0/tests/test_hst_filter_tuple_normalization.py +43 -0
  197. rms_picmaker-1.0.0/tests/test_instruments_branches.py +211 -0
  198. rms_picmaker-1.0.0/tests/test_io.py +44 -0
  199. rms_picmaker-1.0.0/tests/test_io_cascade.py +228 -0
  200. rms_picmaker-1.0.0/tests/test_io_extra.py +77 -0
  201. rms_picmaker-1.0.0/tests/test_mutable_defaults.py +30 -0
  202. rms_picmaker-1.0.0/tests/test_overlap_vs_overlaps.py +58 -0
  203. rms_picmaker-1.0.0/tests/test_package_init.py +17 -0
  204. rms_picmaker-1.0.0/tests/test_paths.py +103 -0
  205. rms_picmaker-1.0.0/tests/test_pds3_reader.py +303 -0
  206. rms_picmaker-1.0.0/tests/test_pds3_reader_branches.py +50 -0
  207. rms_picmaker-1.0.0/tests/test_pickle_iolost_propagates_to_final_error.py +27 -0
  208. rms_picmaker-1.0.0/tests/test_pil_utils.py +47 -0
  209. rms_picmaker-1.0.0/tests/test_pil_utils_branches.py +86 -0
  210. rms_picmaker-1.0.0/tests/test_pipeline.py +138 -0
  211. rms_picmaker-1.0.0/tests/test_pipeline_branches.py +605 -0
  212. rms_picmaker-1.0.0/tests/test_snapshots.py +42 -0
  213. rms_picmaker-1.0.0/tests/test_tiff16.py +119 -0
  214. rms_picmaker-1.0.0/tests/test_tiff16_branches.py +74 -0
  215. rms_picmaker-1.0.0/tests/test_tinted_colormap.py +90 -0
  216. rms_picmaker-1.0.0/tests/test_unknown_filter_warning.py +36 -0
  217. rms_picmaker-1.0.0/tests/test_versions_override.py +85 -0
  218. rms_picmaker-1.0.0/tests/test_warning_elevation.py +24 -0
  219. rms_picmaker-1.0.0/tests/test_zebra.py +50 -0
@@ -0,0 +1,79 @@
1
+ ---
2
+ description: Standards for writing clear, reproducible bug reports with severity, evidence, and environment details.
3
+ alwaysApply: false
4
+ ---
5
+
6
+ # Bug Report Standards
7
+
8
+ ## 1. Core Components
9
+
10
+ Every bug report MUST include:
11
+
12
+ - **Clear title** — Describes the symptom and its location (e.g., "`Profile.from_file` raises KeyError on valid FITS header").
13
+ - **Reproduction steps** — Numbered, minimal steps (ideally a short script) anyone can follow.
14
+ - **Expected vs. actual behavior** — Side-by-side comparison.
15
+ - **Environment** — Python version, OS, package version, relevant dependency versions.
16
+ - **Severity** — Assessed per the scale below.
17
+ - **Evidence** — Tracebacks, log output, or screenshots of incorrect results.
18
+
19
+ ## 2. Severity Scale
20
+
21
+ | Level | Criteria |
22
+ |-------|----------|
23
+ | **Critical** | Crash, data corruption, silent wrong results, or security vulnerability. |
24
+ | **High** | Major feature broken or blocking for many users. |
25
+ | **Medium** | Non-critical feature broken or produces degraded results. |
26
+ | **Low** | Minor issue, documentation error, or cosmetic problem. |
27
+ | **Trivial** | Very minor issue with negligible user impact. |
28
+
29
+ ## 3. Report Template
30
+
31
+ ```markdown
32
+ # Bug Report: [Concise title]
33
+
34
+ ## Description
35
+ [1-2 sentences: what is broken and its impact.]
36
+
37
+ ## Environment
38
+ - **Python version**: [e.g., 3.12.4]
39
+ - **OS**: [e.g., Ubuntu 24.04, macOS 14.5, Windows 11]
40
+ - **Package version**: [e.g., rms-picmaker 0.3.1]
41
+ - **Key dependency versions**: [e.g., numpy 2.2.1, scipy 1.14.0]
42
+ - **Installation method**: [e.g., pip install rms-picmaker, editable install]
43
+
44
+ ## Severity
45
+ [Level] — [Brief justification]
46
+
47
+ ## Steps to Reproduce
48
+ 1. Install: `pip install rms-picmaker==0.3.1`
49
+ 2. Run:
50
+ (Example)
51
+ 3. Observe the error.
52
+
53
+ ## Expected Behavior
54
+ [What should happen.]
55
+
56
+ ## Actual Behavior
57
+ [What actually happens, including the full traceback.]
58
+
59
+ ## Traceback / Logs
60
+ [Paste full traceback or relevant log output here]
61
+
62
+ ## Additional Notes
63
+ [Workarounds, frequency, related issues.]
64
+
65
+ ## Possible Fix
66
+ [Optional: suspected root cause or fix direction.]
67
+ ```
68
+
69
+ ## 4. Writing Guidelines
70
+
71
+ 1. Be objective and factual — no blame or subjective language.
72
+ 2. One issue per report.
73
+ 3. Include exact version numbers and full tracebacks.
74
+ 4. Keep reproduction steps as short as possible while remaining unambiguous.
75
+ 5. Verify the bug is reproducible before submitting.
76
+
77
+ ## 5. Adaptation
78
+
79
+ Adjust the template for the project's GitHub Issues and add project-specific fields (e.g., affected data set, mission, instrument).
@@ -0,0 +1,53 @@
1
+ ---
2
+ alwaysApply: true
3
+ description: Standards for declaring, installing, and maintaining Python project dependencies.
4
+ ---
5
+
6
+ # Dependency Management
7
+
8
+ ## 1. Single Source of Truth
9
+
10
+ - Declare ALL dependencies in **`pyproject.toml`** under `[project]` (PEP 621).
11
+ - Do NOT maintain a separate hand-written `requirements.txt` for runtime dependencies. If a `requirements.txt` is kept, it should contain only `-e .` for backward compatibility.
12
+
13
+ ## 2. Dependency Groups
14
+
15
+ | Group | Section | Install command | Purpose |
16
+ |-------|---------|-----------------|---------|
17
+ | **Runtime** | `[project].dependencies` | `pip install .` | Required for the package to function. |
18
+ | **Dev** | `[project.optional-dependencies].dev` | `pip install -e ".[dev]"` | Testing, linting, type-checking, coverage. |
19
+ | **Docs** | `[project.optional-dependencies].docs` | `pip install -e ".[docs]"` | Sphinx and documentation extensions. |
20
+
21
+ ## 3. Version Constraints
22
+
23
+ - Specify **minimum** compatible versions for direct dependencies (e.g., `numpy>=2.2.0`).
24
+ - Do NOT pin exact versions (`==`) in library projects; exact pinning belongs in lock files or application deployments.
25
+ - For dev/docs dependencies, specify minimum versions to ensure consistent tool behavior across contributors.
26
+
27
+ ## 4. Adding or Updating Dependencies
28
+
29
+ 1. Add the dependency to the correct section in `pyproject.toml`.
30
+ 2. Run `pip install -e ".[dev]"` (or the relevant group) to verify installation.
31
+ 3. Run the full test suite and type-check to confirm compatibility.
32
+ 4. Commit the `pyproject.toml` change with a `build:` commit type.
33
+
34
+ ## 5. Security and Maintenance
35
+
36
+ - Run `pip audit` in CI to catch known vulnerabilities.
37
+ - Enable automated dependency update tooling (Dependabot, Renovate).
38
+ - Review update PRs for breaking changes before merging.
39
+ - Periodically remove unused dependencies to reduce attack surface.
40
+
41
+ ## 6. Tooling Configuration
42
+
43
+ Consolidate all tool configuration into `pyproject.toml` where supported:
44
+
45
+ | Tool | Section |
46
+ |------|---------|
47
+ | pytest | `[tool.pytest.ini_options]` |
48
+ | coverage | `[tool.coverage.run]`, `[tool.coverage.report]` |
49
+ | mypy | `[tool.mypy]`, `[[tool.mypy.overrides]]` |
50
+ | ruff | `[tool.ruff]`, `[tool.ruff.lint]` — use explicit `select = [...]` for E, F, W, I, UP, B, SIM, C4, A, N, PT, RUF (see python_best_practices) |
51
+ | setuptools_scm | `[tool.setuptools_scm]` |
52
+
53
+ Do NOT create separate config files (`.coveragerc`, `.mypy.ini`, `.flake8`, `setup.cfg`) when the tool supports `pyproject.toml`.
@@ -0,0 +1,65 @@
1
+ ---
2
+ alwaysApply: true
3
+ description: Standards for Python library documentation using Sphinx, ReadTheDocs, and docstrings.
4
+ ---
5
+
6
+ # Documentation Standards
7
+
8
+ ## 1. Documentation System
9
+
10
+ - Use **Sphinx** for all project documentation, hosted on **ReadTheDocs**.
11
+ - After any code or doc change, run `sphinx-build` on the full documentation tree and fix all warnings and errors before delivering.
12
+
13
+ ## 2. Documentation Standard
14
+
15
+ - Always use one space between the period at the end of a sentence and the next sentence.
16
+ - Always use American spelling instead of British spelling (e.g. color instead of colour).
17
+
18
+ ## 3. Required Documentation
19
+
20
+ | Document | Contents | Keep up-to-date? |
21
+ |----------|----------|-------------------|
22
+ | **Module index** | Every module that exists or is planned (placeholders for future modules). | Yes |
23
+ | **Architecture overview** | Class hierarchy, public API surface, and interface contracts. | Yes |
24
+ | **Install guide** | `pip install` instructions, supported Python versions, optional dependencies. | Yes |
25
+ | **Usage examples** | Common workflows with code snippets and expected output. | Yes |
26
+ | **README** | Project summary, PyPI/ReadTheDocs badges, quickstart, and links to full docs. | Yes |
27
+
28
+ ## 4. Docstrings
29
+
30
+ - EVERY class, method, function, and module MUST have a descriptive docstring.
31
+ - Follow **PEP 257** using **Google style** with `Parameters:` (not `Args:`).
32
+ - Include `Returns:` and `Raises:` only if there are return values or exceptions raised.
33
+ - Include behavioral notes sufficient to write a black-box test but do not reference the internal details of the code.
34
+ - Wrap docstring text to **90** characters.
35
+
36
+ ## 5. Cross-Reference Completeness
37
+
38
+ - EVERY mention of a class, method, function, module, attribute, or data
39
+ constant in narrative prose MUST use the appropriate Sphinx cross-reference
40
+ role:
41
+ - `:class:`~nav.path.module.Class``
42
+ - `:meth:`~nav.path.module.Class.method``
43
+ - `:func:`~nav.path.module.func``
44
+ - `:mod:`nav.path.module``
45
+ - `:attr:`~nav.path.module.Class.attr``
46
+ - `:data:`~nav.path.module.NAME``
47
+ - Bare CamelCase or `module.symbol` text in narrative prose is a violation,
48
+ even when wrapped in inline literals (`` `` ``). Inline literals are for
49
+ YAML/JSON keys, file paths, CLI tokens, and shell snippets — not for API
50
+ symbols.
51
+ - Cross-references are NOT required (and should be omitted) inside
52
+ `.. code-block::` directives, `::` literal blocks, Mermaid / other diagram
53
+ blocks, YAML examples, or section titles.
54
+ - When a class, method, function, module, attribute, or data constant is
55
+ added, removed, or renamed, every cross-reference to it across the docs
56
+ tree MUST be updated in the same change. A rename without ref updates is a
57
+ documentation regression.
58
+ - Validate by building with `sphinx-build -W -b html` (warnings as errors)
59
+ AND `sphinx-build -n -b html` (nitpicky mode); both MUST succeed with zero
60
+ warnings before delivering.
61
+
62
+ ## 6. Change Discipline
63
+
64
+ - Any code change MUST update the relevant docstrings and the README if affected.
65
+ - NEVER leave stale or contradictory documentation. If a feature is removed, remove its docs.
@@ -0,0 +1,40 @@
1
+ ---
2
+ description: Git, CI/CD (GitHub Actions), virtual environments, and tooling for development and publishing.
3
+ alwaysApply: true
4
+ ---
5
+
6
+ # Environment Best Practices
7
+
8
+ ## 1. Source Control
9
+
10
+ - ALWAYS use **git** for all source code.
11
+ - Commit early and often with meaningful messages (see `git_workflow.mdc`).
12
+
13
+ ## 2. CI/CD
14
+
15
+ - ALWAYS use **GitHub Actions** for continuous integration and publishing.
16
+ - Every PR MUST pass lint (`ruff`), type-check (`mypy`), test (`pytest`), Markdown lint (`PyMarkdown`), and documentation build (`sphinx-build`) jobs before merge.
17
+ - Pin action versions to a major tag (e.g., `actions/checkout@v6`) to balance stability and security updates.
18
+ - Publishing to PyPI is triggered by creating a GitHub Release from a version tag on `main`.
19
+
20
+ ## 3. Environment Isolation
21
+
22
+ - ALWAYS use `python -m venv` (or `virtualenv`) to create an isolated virtual environment. Activate it before any `pip install`.
23
+ - NEVER install project dependencies into the system Python.
24
+ - Record the supported Python version range in `pyproject.toml` via `requires-python` (e.g., `>=3.10`).
25
+ - Test across all supported Python versions in CI using a matrix strategy.
26
+
27
+ ## 4. Editor Settings (VSCode / Cursor)
28
+
29
+ The repository includes `.vscode/settings.json` so all contributors get consistent formatting:
30
+
31
+ - **Indent**: 4 spaces (no tabs).
32
+ - **Trailing whitespace**: Trimmed on save.
33
+ - **Final newline**: Exactly one newline at end of file; excess trailing blank lines removed on save.
34
+ - **Line length**: Rulers at 80, 90, and 100 characters (max 100 enforced by Ruff).
35
+
36
+ ## 5. Secrets and Configuration
37
+
38
+ - NEVER commit secrets, tokens, or credentials. Use environment variables or GitHub Secrets.
39
+ - Use `.env` files for local development only; ensure `.env` is in `.gitignore`.
40
+ - Validate required environment variables at startup with clear error messages.
@@ -0,0 +1,66 @@
1
+ ---
2
+ description: Conventional commits, branching, and PR workflow for source control and code review.
3
+ alwaysApply: false
4
+ ---
5
+
6
+ # Git Workflow
7
+
8
+ ## 1. Commit Messages
9
+
10
+ Use the **Conventional Commits** format:
11
+
12
+ ```
13
+ <type>[(<scope>)]: <imperative summary> (50 chars max for subject)
14
+
15
+ [Optional body — wrap at 72 chars. Explain *what* and *why*, not *how*.]
16
+
17
+ [Optional footer — e.g., Closes #123, BREAKING CHANGE: description]
18
+ ```
19
+
20
+ ### Allowed types
21
+
22
+ | Type | When to use |
23
+ |------|-------------|
24
+ | `feat` | New user-facing feature or public API addition. |
25
+ | `fix` | Bug fix. |
26
+ | `docs` | Documentation-only change. |
27
+ | `style` | Formatting, whitespace — no logic change. |
28
+ | `refactor` | Code restructure with no behavior change. |
29
+ | `perf` | Performance improvement. |
30
+ | `test` | Adding or updating tests only. |
31
+ | `build` | Build system or dependency change. |
32
+ | `ci` | CI/CD configuration change. |
33
+ | `chore` | Maintenance tasks that don't fit above. |
34
+
35
+ ### Rules
36
+
37
+ - Subject line MUST be imperative mood ("Add X", not "Added X" or "Adds X").
38
+ - Subject line MUST NOT exceed 50 characters.
39
+ - Do NOT end the subject line with a period.
40
+ - Separate subject from body with a blank line.
41
+ - Body lines MUST NOT exceed 72 characters.
42
+ - Reference related issues in the footer.
43
+ - Each commit MUST represent one logical change. Do NOT mix unrelated changes.
44
+
45
+ ## 2. Branching Strategy
46
+
47
+ This project uses a simple two-tier branching model:
48
+
49
+ - **`main`** — Always releasable. Protected; requires PR review and passing CI. Releases are created by tagging commits on `main`.
50
+ - **`feature/<name>`** — New features or enhancements, branched from `main`.
51
+ - **`bugfix/<name>`** — Bug fixes, branched from `main`.
52
+
53
+ There are NO separate release, hotfix, or develop branches. All work merges back to `main` via pull request.
54
+
55
+ ## 3. Pull Requests and Merging
56
+
57
+ - ALWAYS create a PR for merging into `main`; direct pushes are prohibited.
58
+ - PRs MUST pass all CI checks (lint, type-check, tests) before merge.
59
+ - Prefer **squash merge** to keep `main` history linear and readable.
60
+ - Delete the source branch after merge.
61
+
62
+ ## 4. Tagging and Releases
63
+
64
+ - Tag releases on `main` with semantic versioning: `v<MAJOR>.<MINOR>.<PATCH>`.
65
+ - Let `setuptools_scm` derive the package version from tags automatically.
66
+ - Creating a GitHub Release from the tag triggers the PyPI publish workflow.
@@ -0,0 +1,74 @@
1
+ ---
2
+ description: Guidelines for writing user-facing how-to documentation with steps, prerequisites, and troubleshooting.
3
+ alwaysApply: false
4
+ ---
5
+
6
+ # How-To Documentation
7
+
8
+ ## 1. Audience and Tone
9
+
10
+ - Write for **Python users** who are familiar with `pip` and the command line but may not know the library's internals.
11
+ - Use clear, direct language; define domain-specific terms on first use.
12
+ - Focus on what the user needs to do and what they should observe.
13
+
14
+ ## 2. Best Practices
15
+
16
+ 1. **Action-oriented title** — e.g., "How To Process a Cassini Image", not "Image Processing Overview".
17
+ 2. **Brief introduction** — 1-3 sentences explaining purpose and value.
18
+ 3. **Prerequisites** — Python version, package installation, required data or environment variables.
19
+ 4. **Numbered steps** — One action per step in logical order. Include code snippets for API usage or CLI commands.
20
+ 5. **Expected results** — State what the user should see after each significant step AND in a summary section at the end. Keep both consistent.
21
+ 6. **Troubleshooting** — Common failures (import errors, missing data, version mismatches) and their fixes.
22
+ 7. **Related features** — Mention next steps or related guides.
23
+
24
+ ## 3. Document Structure
25
+
26
+ ```markdown
27
+ # How To [Action]
28
+
29
+ [1-3 sentence introduction explaining purpose and value.]
30
+
31
+ ## Prerequisites
32
+
33
+ - Python >= 3.10
34
+ - `pip install rms-<package>`
35
+ - [Any required data, environment variables, or configuration]
36
+
37
+ ## Steps
38
+
39
+ 1. Import the module:
40
+ ```python
41
+ from package import SomeClass
42
+ ```
43
+ 2. [Action]. You should see [result].
44
+ 3. [Action].
45
+
46
+ ## Expected Results
47
+
48
+ [Summary of the successful end state — expected output, files created, etc.]
49
+
50
+ ## Troubleshooting
51
+
52
+ - **[Problem]**: [Solution].
53
+
54
+ ## Additional Information
55
+
56
+ [Tips, performance notes, or links to related guides.]
57
+ ```
58
+
59
+ ## 4. Converting Technical Content
60
+
61
+ When turning docstrings, test scripts, or internal notes into How-To guides:
62
+
63
+ 1. Identify the user-facing feature or workflow.
64
+ 2. Determine the target audience (library user, CLI user, contributor).
65
+ 3. Extract user actions from technical steps.
66
+ 4. Translate internal terminology to user-friendly language.
67
+ 5. Add code examples, expected output, and troubleshooting.
68
+
69
+ ## 5. Diagrams and Figures
70
+
71
+ - **When to use**: Multi-step workflows, data pipelines, or architecture that is clearer as a visual.
72
+ - **Placement**: Inline, immediately after the relevant step or section.
73
+ - **Format**: Prefer Mermaid diagrams (e.g., rendered by Sphinx via `sphinxcontrib-mermaid`) for process flows. Use PNG/SVG for screenshots or data visualizations.
74
+ - **Naming**: Descriptive filenames (e.g., `backplane-pipeline.svg`). Include alt text for accessibility.
@@ -0,0 +1,43 @@
1
+ ---
2
+ description: PR structure, purpose, implementation details, testing evidence, and review checklist.
3
+ alwaysApply: false
4
+ ---
5
+
6
+ # Pull Request Standards
7
+
8
+ ## Scope of review
9
+
10
+ Treat the PR as a **single unit of change**. The diff to review is the set of all commits on the current branch back to its **immediate root** (the merge-base with the target branch). Consider the net result of those commits together; do **not** comment on differences that exist only between commits within the PR (e.g. "you fixed X in a later commit" or "commit 2 undid part of commit 1"). Review the final state of the branch against the base. Do not explicitly word wrap lines.
11
+
12
+ ## Principles
13
+
14
+ 1. **Descriptive title** — Summarize the change in an imperative sentence (e.g., "Add caching to profile lookup").
15
+ 2. **Purpose first** — Explain *why* the change is needed before *how* it was done.
16
+ 3. **Scope** — One logical change per PR. Split unrelated changes into separate PRs.
17
+ 4. **Testing evidence** — Document automated and manual testing performed.
18
+ 5. **Impact assessment** — Note potential effects on the public API, performance, or dependent packages (Potential Impacts section).
19
+ 6. **Linked issues** — Reference related GitHub issues using `Closes #NNN` syntax.
20
+
21
+ ## Template
22
+
23
+ The PR template is in `.github/pull_request_template.md` and is applied automatically when a new PR is opened. Fill out every section:
24
+
25
+ - **Purpose** — Why the change is needed; link issue with `Closes #NNN`.
26
+ - **Changes / Implementation Details** — What changed and how it was implemented; technical approaches chosen and non-obvious design decisions.
27
+ - **Type of Change** — Check all that apply (bug fix, feature, breaking, refactor, docs, tests, CI/build).
28
+ - **Testing** — Check boxes for unit tests, integration tests, E2E tests run; describe new tests added and manual verification performed.
29
+ - **Potential Impacts** — Public API, backward compatibility, performance, downstream; write "None" if straightforward.
30
+ - **Checklist** — Style, mypy, docs, CHANGES.md, no debug code, no secrets/credentials, no warnings/errors, performance impact assessed, breaking changes flagged.
31
+ - **Notes** — Optional; delete only if not needed (tricky areas, follow-up work).
32
+
33
+ ## Guidance
34
+
35
+ - **Library-specific** — Call out public API changes, deprecations, and migration notes in Potential Impacts.
36
+ - **Required reviewers** — Tag maintainers for changes to core modules.
37
+ - **Brevity vs. completeness** — Short enough that authors fill everything out; detailed enough for a reviewer with no other context.
38
+ - **Format** - Do not explicitly wrap lines.
39
+
40
+ ## Action
41
+
42
+ - **Writing a PR description** - When asked to write a PR description, always output the result to a Markdown file called PR_DESCRIPTION.md in the repo root.
43
+ - **Opening a PR** - When asked to open a PR, write the description to a temporary file and then open the PR on GitHub using that description text.
@@ -0,0 +1,145 @@
1
+ ---
2
+ alwaysApply: true
3
+ description: Python coding standards for writing correct, readable, maintainable, and well-tested library code.
4
+ ---
5
+
6
+ # Python Best Practices
7
+
8
+ Apply these rules to ALL new and modified Python code. This project is a Python library published on PyPI and documented on ReadTheDocs. **Minimum Python version: 3.11.**
9
+
10
+ ## 1. Naming and Style
11
+
12
+ - **Maximum line length**: 100 characters. Enforce via Ruff; use editor rulers at 80 and 90 as visual guides.
13
+ - **Functions and local variables**: Use `lowercase_with_underscores`.
14
+ - **Class names**: Use `TitleCase`.
15
+ - **Module-level constants (global variables)**: Use `ALL_CAPS_WITH_UNDERSCORES`.
16
+ - **Private names**: Prepend a single underscore for names that are not part of the public API: private attributes (e.g. `_cache`), module-private global variables, and non-public helper functions (e.g. `_parse_header`). Public API names have no leading underscore.
17
+ - **Built-in names**: Do NOT use variable or function names that shadow Python built-ins (e.g. `float`, `filter`, `id`, `list`, `type`). If you must use such a name, append a single underscore (e.g. `filter_`, `type_`).
18
+ - **Falsy checks**: Be explicit about what you are testing. Do NOT rely on truthiness when the intent could be ambiguous. Prefer:
19
+ - `if x is None:` for None checks (not `if not x:` when 0 or [] could occur).
20
+ - `if len(seq) == 0:` when you explicitly mean "empty sequence" and other falsy values (0, None) are not possible.
21
+ - For dicts: `if key in d:` then use `d[key]`; avoid `d.get(key)` when you need to distinguish "missing" from "present with a falsy value" unless that is the intent.
22
+ - **Explicit checks over exceptions**: Prefer explicit membership or presence checks over catching exceptions for control flow. Example: use `if "a" in b: x = b["a"]` (or a clear `get` with a sentinel) rather than `try: x = b["a"]` / `except KeyError: ...` for normal flow. Use exceptions for genuinely exceptional conditions.
23
+
24
+ ## 2. General Coding
25
+
26
+ - NEVER include backwards-compatibility code unless explicitly requested.
27
+ - ALWAYS keep modules under 1000 lines. Split larger modules into a package with multiple files.
28
+ - ALWAYS write simple, clear code; avoid unnecessary complexity.
29
+ - NEVER hardcode magic constants. Define them as module-level constants, in a config module, or via environment variables.
30
+ - ALWAYS catch exceptions at the smallest granularity possible. Do NOT wrap large blocks in a single `try`/`except`.
31
+ - **Libraries:** Let exceptions propagate unless you are adding context, converting to a library-specific exception, or the exception represents a recoverable internal state. When re-raising, use `raise ... from` to preserve the full traceback for debugging.
32
+ - **Applications:** Do not allow uncaught exceptions to reach the top level; use a top-level handler (e.g. in the main loop or HTTP framework) so that failures are logged and the process stays predictable. In both cases, ALWAYS provide full exception information for debugging (e.g. traceback, `raise ... from` when re-raising).
33
+ - ALWAYS include meaningful, structured logging (use the `logging` module) that can be disabled or redirected. NEVER use bare `print()` for diagnostic output in library code.
34
+ - Avoid mutable global variables. If unavoidable, document purpose and limit scope. Prefer module-level constants (ALL_CAPS) or dependency injection.
35
+ - ALWAYS prefer comprehensions (list, dict, set, generator) over manual loops when the result is a new collection and the expression remains readable.
36
+ - ALWAYS make the minimal changes necessary. NEVER modify code outside the scope of the current task.
37
+ - ALWAYS apply DRY. NEVER duplicate code. Place reusable logic in a utility module. Search existing utilities before writing new functions. Parameterize utility functions to increase generality.
38
+ - ALWAYS place imports at the top of the file in three alphabetically-sorted groups separated by a blank line: (1) standard library, (2) third-party, (3) local project. When adding new code or tests, add new imports to the appropriate group at the top; do not place them adjacent to the new code. Inline imports are permitted only to avoid heavy optional dependencies (e.g., GUI libraries).
39
+ - Limit new functions to at most three positional parameters. Additional parameters MUST be keyword-only (after `*`). Choose a logical grouping of 0-3 positional parameters before enforcing keyword-only parameters. If there is no logical break within the first 3 parameters, make all parameters (after `self`) keyword-only.
40
+ - Use the Receive-an-Object, Return-an-Object (RORO) pattern when a function takes or returns more than a few related values: accept a dataclass or TypedDict and return one, rather than long positional tuples.
41
+ - NEVER use `getattr` just as a defensive measure if it is guaranteed that the object has the attribute. ALWAYS reference the attribute directly unless there is a specific reason to know the attribute may not be present. NEVER use getattr to reference the result of an `argparse` namespace when the argument name is a constant string.
42
+
43
+ ## 3. Public API Design
44
+
45
+ - Clearly separate public API from internal implementation. Prefix internal functions, classes, and modules with `_`.
46
+ - Use `__all__` in `__init__.py` to explicitly declare the public API surface.
47
+ - Design for stability: think carefully before adding to the public API, because removing it later is a breaking change.
48
+ - Include a `py.typed` marker file so downstream users get type-checking support.
49
+
50
+ ## 4. Comments
51
+
52
+ - ALWAYS write self-documenting code: meaningful names, simple structure, limited nesting.
53
+ - NEVER include comments that merely restate the code, reference user requests, or describe modification history.
54
+ - ALWAYS include comments that explain the **rationale** behind non-obvious or complex logic.
55
+ - ALWAYS preserve existing comments that are still accurate and relevant. Remove or update stale comments.
56
+
57
+ ## 5. Lint and Type Checking
58
+
59
+ ### Types
60
+
61
+ - ALWAYS annotate all function/method parameters and return values, including `-> None` for functions (and `__init__`) that return nothing.
62
+ - Use modern generic syntax (`list[str]`, `dict[str, int]`, `X | None`) for Python 3.11+.
63
+ - Do not include `from __future__ import annotations` unless actually needed.
64
+
65
+ ### Mypy
66
+
67
+ - ALWAYS run `mypy` on the full codebase (including tests) after changes. Fix all errors before delivering.
68
+ - NEVER add global type exclusions. "Global type exclusions" means:
69
+ - Module-level `# type: ignore` without a specific error code.
70
+ - `ignore_errors = True` in mypy config.
71
+ - Broad `exclude` patterns that skip entire packages.
72
+ - In exceptional, unfixable cases use a minimal line-level ignore: `# type: ignore[error-code] # <brief justification>`.
73
+
74
+ ### Ruff / Linting
75
+
76
+ - ALWAYS include `mypy` and `ruff` in the project's dev dependencies (e.g. in `pyproject.toml`).
77
+ - ALWAYS run `ruff check` and `ruff format` on the full codebase after changes. Fix all errors.
78
+ - Follow PEP 8 for all formatting and naming conventions.
79
+ - Use the project's explicit Ruff rule set in `pyproject.toml` (see **Ruff rule categories** below). Do not disable categories that enforce project conventions (e.g. **A** for no builtin shadowing, **N** for naming).
80
+
81
+ ## 6. Docstrings
82
+
83
+ - ALWAYS include a docstring for every module, class, function, and method.
84
+ - Follow **PEP 257** using **Google style**. Use `Parameters:` (not `Args:`).
85
+ - Include `Returns:`, `Raises:`, and any important behavioral notes.
86
+ - NEVER mention backwards compatibility or user requests in docstrings.
87
+ - Docstrings MUST be detailed enough to write a black-box test from the docstring alone.
88
+ - Wrap docstring text to **90** characters.
89
+ - ALWAYS update docstrings when the associated code changes.
90
+
91
+ ## 7. Testing
92
+
93
+ ### Test-driven development (TDD)
94
+
95
+ - Use **test-driven development**: write tests first, then implement. Red → green → refactor.
96
+ - Write tests BEFORE implementation based on stated requirements. If requirements are unclear, ask.
97
+ - Run tests to confirm they fail, then implement, re-run, and fix until green.
98
+ - After implementation, review tests to strengthen coverage.
99
+
100
+ ### Framework
101
+
102
+ - ALWAYS include type annotations on test functions.
103
+ - ALWAYS use `pytest` with `pytest-cov`.
104
+ - ALWAYS use `pytest` with `pytest-xdist` and run tests with "-n auto".
105
+ - ALWAYS write tests to be independent so that tests can be run in parallel.
106
+
107
+ ### Coverage and correctness
108
+
109
+ - Target at least **90%** line coverage measured over the entire test suite (not a subset). Skipping hard-to-hit exception paths is acceptable.
110
+ - NEVER write tests whose sole purpose is exercising code paths without asserting correctness.
111
+ - Each `assert` MUST test exactly one condition (no `and` in assertions).
112
+ - ALWAYS test for precise expected values, not ranges or existence checks. If the expected value is only known after implementation, update the test accordingly.
113
+ - When multiple tests call the same function, use distinct inputs to maximize branch coverage, including edge cases and boundary values.
114
+ - If two tests invoke the same code path but assert on different parts of the result, combine them into one test.
115
+ - When testing exceptions, ALWAYS use `pytest.raises` as a context manager and assert on the exception **message content**, not just the exception type.
116
+
117
+ ### Test hygiene
118
+
119
+ - If a test mutates a global, use a fixture or `try`/`finally` to restore the original value.
120
+ - NEVER write a test that passes by ignoring an incorrect result or swallowing an exception. If the code is wrong, leave the failing test and explain why.
121
+ - NEVER include line numbers, verbose rationale, or modification history in test comments. Keep comments to short (1-2 sentence) summaries useful for future maintainers.
122
+
123
+ ### Debugging
124
+
125
+ - NEVER guess at bug causes. Use logic, stack traces, and targeted logging. If stuck in a fix loop, revert and re-approach from first principles. When necessary, ask for help.
126
+
127
+ ## 8. Ruff Rule Categories (Default Set)
128
+
129
+ The template enables these Ruff lint categories in `pyproject.toml`. Use them as the default for new repos; add or ignore specific codes as needed.
130
+
131
+ | Code | Source | Purpose |
132
+ |------|--------|---------|
133
+ | **E**, **W** | pycodestyle | Style and formatting (indent, whitespace, line length). |
134
+ | **F** | Pyflakes | Unused imports, undefined names, syntax issues. |
135
+ | **I** | isort | Import sorting and grouping. |
136
+ | **UP** | pyupgrade | Prefer modern Python (e.g. 3.11+ syntax). |
137
+ | **B** | flake8-bugbear | Common bugs (mutable defaults, assert, loop vars). |
138
+ | **SIM** | flake8-simplify | Simpler alternatives (e.g. `in` instead of `not x == y`). |
139
+ | **C4** | flake8-comprehensions | Prefer comprehensions over loops where clear. |
140
+ | **A** | flake8-builtins | No shadowing of builtins (`id`, `filter`, `type`, etc.). |
141
+ | **N** | pep8-naming | Class = TitleCase, functions/variables = lowercase_with_underscores. |
142
+ | **PT** | flake8-pytest-style | Pytest best practices (fixtures, parametrize, raises). |
143
+ | **RUF** | Ruff | Ruff-specific (e.g. unused noqa, deprecated). |
144
+
145
+ Optional categories to consider adding later: **D** (pydocstyle) or **DOC** (pydoclint) for docstring linting; **PTH** (pathlib); **RET** (return simplification); **PERF** (perflint). Enable only if the team agrees to fix or ignore the resulting diagnostics.
@@ -0,0 +1,48 @@
1
+ ---
2
+ alwaysApply: true
3
+ description: Security best practices for Python library development — secrets, dependencies, and defensive coding.
4
+ ---
5
+
6
+ # Security Best Practices
7
+
8
+ ## 1. Secrets Management
9
+
10
+ - NEVER commit secrets, API keys, tokens, passwords, or private keys to the repository.
11
+ - Store secrets in environment variables or a dedicated secrets manager (e.g., GitHub Secrets, GCP Secret Manager).
12
+ - Use `.env` files for local development ONLY. Ensure `.env` is listed in `.gitignore`.
13
+ - If a secret is accidentally committed, rotate it immediately — deleting the commit is NOT sufficient.
14
+
15
+ ## 2. Dependency Security
16
+
17
+ - Specify minimum compatible versions for direct dependencies (e.g., `numpy>=2.2.0`) in `pyproject.toml`.
18
+ - Run `pip audit` regularly and in CI to detect known vulnerabilities.
19
+ - Enable GitHub Dependabot for automated dependency update PRs.
20
+ - Review changelogs and diffs before merging dependency updates.
21
+
22
+ ## 3. Input Validation
23
+
24
+ - NEVER trust external input (function arguments from callers, file contents, environment variables, data from remote URLs).
25
+ - Validate inputs at the public API boundary of the library. Raise clear `ValueError` or `TypeError` exceptions for invalid arguments.
26
+ - For file paths, resolve to absolute paths and verify they remain within the expected directory (prevent path traversal).
27
+
28
+ ## 4. Safe Defaults
29
+
30
+ - NEVER implement custom cryptography. Use standard algorithms via trusted libraries (`cryptography`, `hashlib`).
31
+ - When the library downloads or reads external data, verify integrity (checksums, expected schemas) where feasible.
32
+ - Do NOT embed credentials, default passwords, or example secrets in source code, tests, or documentation.
33
+
34
+ ## 5. Logging
35
+
36
+ - NEVER log secrets, tokens, passwords, or full stack traces containing sensitive data.
37
+ - Sanitize PII (personally identifiable information) before logging.
38
+ - Use the `logging` module with appropriate levels so callers can control verbosity.
39
+
40
+ ## 6. Code Review Security Checklist
41
+
42
+ When reviewing PRs, verify:
43
+
44
+ - [ ] No secrets or credentials in code, config, or comments.
45
+ - [ ] Public API inputs are validated with clear error messages.
46
+ - [ ] New dependencies are from reputable sources and have no known CVEs.
47
+ - [ ] File operations guard against path traversal.
48
+ - [ ] Error messages do not leak internal file paths or sensitive data.
@@ -0,0 +1,9 @@
1
+ {
2
+ "editor.tabSize": 4,
3
+ "editor.insertSpaces": true,
4
+ "editor.detectIndentation": false,
5
+ "files.trimTrailingWhitespace": true,
6
+ "files.insertFinalNewline": true,
7
+ "files.trimFinalNewlines": true,
8
+ "editor.rulers": [80, 90, 100]
9
+ }