You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: .agents/skills/usethis-python-code/SKILL.md
+25-1Lines changed: 25 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,7 @@ description: Guidelines for Python code design decisions such as when to share v
4
4
compatibility: usethis, Python
5
5
license: MIT
6
6
metadata:
7
-
version: "1.0"
7
+
version: "1.2"
8
8
---
9
9
10
10
# Python Code Guidelines
@@ -35,3 +35,27 @@ If the answer to any of these is yes, duplication may be the right choice. If th
35
35
36
36
-**Duplicating when replacing a dependency.** If a single dependency provided shared functionality to multiple callers, the replacement should also be shared. The dependency was already proof that a unified implementation works.
37
37
-**Speculative divergence.** Do not duplicate code because the implementations "might need to diverge someday." Refactoring to split a shared implementation later is straightforward; discovering and reconciling divergent copies is not.
38
+
39
+
## Choosing where to place a function
40
+
41
+
Before adding a new function to a module, consider at least two candidate locations. Placement should be driven by the level of abstraction the function belongs to, not by proximity to the call site.
42
+
43
+
### Procedure
44
+
45
+
1. Identify the function's level of abstraction: is it a low-level utility, a mid-level integration helper, or a high-level orchestration step?
46
+
2. Consider at least two candidate modules at different abstraction levels before committing to a location.
47
+
3. Prefer the module whose abstraction level most closely matches the function's own level, even if that module is lower in the call stack than where the function will be used.
48
+
4. Verify that placing the function in the chosen module does not violate any Import Linter contracts (run the `usethis-qa-import-linter` skill). If it would, introduce a new shared lower-level module that both the chosen module and its callers can depend on, and declare it in the relevant contract.
49
+
50
+
### Key principle
51
+
52
+
A function that extends a lower-level utility module with follow-up logic belongs in that utility module, not in the higher-level module that happens to call it. Placing logic too high in the stack couples the lower-level module's behavior to the higher-level module's concerns.
53
+
54
+
### Example
55
+
56
+
If a function processes the output of a file-reading utility and belongs conceptually to the file layer, place it in the file module — even if the only current caller is an integration module. The integration module imports from the file module, so the direction of dependency is already correct.
57
+
58
+
### Common mistakes
59
+
60
+
-**Placing a function where it is first used.** The call site is not the right guide for placement; the function's own abstraction level is.
61
+
-**Ignoring import linter contracts.** Import Linter enforces the layer hierarchy. A placement that satisfies the architecture will naturally satisfy the contracts; if it does not, that is a signal that the chosen location is wrong.
0 commit comments