cfsa-antigravity 1.0.0
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.
- package/bin/cli.mjs +324 -0
- package/package.json +34 -0
- package/template/.agent/instructions/commands.md +48 -0
- package/template/.agent/instructions/patterns.md +61 -0
- package/template/.agent/instructions/structure.md +29 -0
- package/template/.agent/instructions/tech-stack.md +43 -0
- package/template/.agent/instructions/workflow.md +41 -0
- package/template/.agent/kit-sync.md +15 -0
- package/template/.agent/rules/boundary-not-placeholder.md +146 -0
- package/template/.agent/rules/completion-checklist.md +48 -0
- package/template/.agent/rules/decision-classification.md +103 -0
- package/template/.agent/rules/extensibility.md +47 -0
- package/template/.agent/rules/question-vs-command.md +81 -0
- package/template/.agent/rules/security-first.md +43 -0
- package/template/.agent/rules/specificity-standards.md +54 -0
- package/template/.agent/rules/tdd-contract-first.md +57 -0
- package/template/.agent/rules/vertical-slices.md +42 -0
- package/template/.agent/skill-library/MANIFEST.md +480 -0
- package/template/.agent/skill-library/README.md +38 -0
- package/template/.agent/skill-library/meta/brand-guidelines/SKILL.md +73 -0
- package/template/.agent/skill-library/meta/claude-code/README.md +9 -0
- package/template/.agent/skill-library/meta/claude-code/agent-development/SKILL.md +415 -0
- package/template/.agent/skill-library/meta/claude-code/hook-development/SKILL.md +712 -0
- package/template/.agent/skill-library/meta/claude-code/plugin-structure/SKILL.md +476 -0
- package/template/.agent/skill-library/meta/git-advanced/SKILL.md +972 -0
- package/template/.agent/skill-library/meta/mcp-builder/SKILL.md +236 -0
- package/template/.agent/skill-library/meta/product-marketing-context/SKILL.md +241 -0
- package/template/.agent/skill-library/meta/regex-patterns/SKILL.md +751 -0
- package/template/.agent/skill-library/meta/tmux-processes/SKILL.md +210 -0
- package/template/.agent/skill-library/meta/using-tmux-for-interactive-commands/SKILL.md +178 -0
- package/template/.agent/skill-library/stack/3d/threejs-pro/SKILL.md +300 -0
- package/template/.agent/skill-library/stack/ai/ai-sdk/SKILL.md +77 -0
- package/template/.agent/skill-library/stack/ai/langchain/SKILL.md +530 -0
- package/template/.agent/skill-library/stack/ai/ollama/SKILL.md +321 -0
- package/template/.agent/skill-library/stack/ai/openai-sdk/SKILL.md +549 -0
- package/template/.agent/skill-library/stack/analytics/google-analytics/SKILL.md +153 -0
- package/template/.agent/skill-library/stack/api/graphql/SKILL.md +1061 -0
- package/template/.agent/skill-library/stack/api/trpc/SKILL.md +576 -0
- package/template/.agent/skill-library/stack/auth/authjs/SKILL.md +569 -0
- package/template/.agent/skill-library/stack/auth/clerk/SKILL.md +590 -0
- package/template/.agent/skill-library/stack/auth/firebase-auth/SKILL.md +734 -0
- package/template/.agent/skill-library/stack/cms/payload-cms/SKILL.md +573 -0
- package/template/.agent/skill-library/stack/cms/shopify/SKILL.md +1193 -0
- package/template/.agent/skill-library/stack/cms/wordpress/SKILL.md +1104 -0
- package/template/.agent/skill-library/stack/css/sass-scss/SKILL.md +1121 -0
- package/template/.agent/skill-library/stack/css/tailwind-css-patterns/SKILL.md +863 -0
- package/template/.agent/skill-library/stack/css/tailwind-design-system/SKILL.md +490 -0
- package/template/.agent/skill-library/stack/css/vanilla-css/SKILL.md +1078 -0
- package/template/.agent/skill-library/stack/databases/clickhouse/SKILL.md +311 -0
- package/template/.agent/skill-library/stack/databases/influxdb/SKILL.md +280 -0
- package/template/.agent/skill-library/stack/databases/lancedb/SKILL.md +415 -0
- package/template/.agent/skill-library/stack/databases/mongodb/SKILL.md +1169 -0
- package/template/.agent/skill-library/stack/databases/neo4j/SKILL.md +839 -0
- package/template/.agent/skill-library/stack/databases/pgvector/SKILL.md +241 -0
- package/template/.agent/skill-library/stack/databases/pinecone/SKILL.md +212 -0
- package/template/.agent/skill-library/stack/databases/postgresql/SKILL.md +658 -0
- package/template/.agent/skill-library/stack/databases/qdrant/SKILL.md +312 -0
- package/template/.agent/skill-library/stack/databases/redis/SKILL.md +1079 -0
- package/template/.agent/skill-library/stack/databases/spacetimedb/SKILL.md +532 -0
- package/template/.agent/skill-library/stack/databases/sqlite/SKILL.md +1132 -0
- package/template/.agent/skill-library/stack/databases/supabase/SKILL.md +640 -0
- package/template/.agent/skill-library/stack/databases/surrealdb-expert/SKILL.md +945 -0
- package/template/.agent/skill-library/stack/databases/timescaledb/SKILL.md +745 -0
- package/template/.agent/skill-library/stack/databases/weaviate/SKILL.md +218 -0
- package/template/.agent/skill-library/stack/devops/github-actions/SKILL.md +554 -0
- package/template/.agent/skill-library/stack/devops/kubernetes/SKILL.md +950 -0
- package/template/.agent/skill-library/stack/devops/nginx/SKILL.md +841 -0
- package/template/.agent/skill-library/stack/devops/terraform/SKILL.md +860 -0
- package/template/.agent/skill-library/stack/email/resend/SKILL.md +391 -0
- package/template/.agent/skill-library/stack/engines/godot/SKILL.md +488 -0
- package/template/.agent/skill-library/stack/extensions/chrome-extension/SKILL.md +375 -0
- package/template/.agent/skill-library/stack/extensions/vscode-extension/SKILL.md +453 -0
- package/template/.agent/skill-library/stack/frameworks/astro-framework/SKILL.md +162 -0
- package/template/.agent/skill-library/stack/frameworks/electron/SKILL.md +1286 -0
- package/template/.agent/skill-library/stack/frameworks/fastapi/SKILL.md +650 -0
- package/template/.agent/skill-library/stack/frameworks/hono/SKILL.md +90 -0
- package/template/.agent/skill-library/stack/frameworks/nestjs/SKILL.md +878 -0
- package/template/.agent/skill-library/stack/frameworks/nextjs/SKILL.md +635 -0
- package/template/.agent/skill-library/stack/frameworks/nuxt/SKILL.md +564 -0
- package/template/.agent/skill-library/stack/frameworks/sveltekit/SKILL.md +614 -0
- package/template/.agent/skill-library/stack/frameworks/tauri/SKILL.md +920 -0
- package/template/.agent/skill-library/stack/gamedev/godot/SKILL.md +1032 -0
- package/template/.agent/skill-library/stack/gamedev/unity/SKILL.md +1175 -0
- package/template/.agent/skill-library/stack/hosting/aws/SKILL.md +467 -0
- package/template/.agent/skill-library/stack/hosting/cloudflare/SKILL.md +201 -0
- package/template/.agent/skill-library/stack/hosting/docker-expert/SKILL.md +409 -0
- package/template/.agent/skill-library/stack/hosting/vercel/SKILL.md +484 -0
- package/template/.agent/skill-library/stack/languages/bash-scripting/SKILL.md +773 -0
- package/template/.agent/skill-library/stack/languages/c-cpp/SKILL.md +712 -0
- package/template/.agent/skill-library/stack/languages/gdscript/SKILL.md +789 -0
- package/template/.agent/skill-library/stack/languages/go/SKILL.md +664 -0
- package/template/.agent/skill-library/stack/languages/java/SKILL.md +778 -0
- package/template/.agent/skill-library/stack/languages/kotlin/SKILL.md +665 -0
- package/template/.agent/skill-library/stack/languages/python/SKILL.md +678 -0
- package/template/.agent/skill-library/stack/languages/rust/SKILL.md +673 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/SKILL.md +141 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/advanced-generics.md +90 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/branded-types.md +57 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/builder-pattern.md +71 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/common-pitfalls.md +135 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/conditional-types.md +27 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/decorators.md +98 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/discriminated-unions.md +62 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/mapped-types.md +53 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/performance-best-practices.md +104 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/template-literal-types.md +49 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/testing-types.md +112 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/type-guards.md +70 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/type-inference.md +101 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/utility-types.md +98 -0
- package/template/.agent/skill-library/stack/languages/vanilla-javascript/SKILL.md +803 -0
- package/template/.agent/skill-library/stack/messaging/kafka/SKILL.md +235 -0
- package/template/.agent/skill-library/stack/mobile/expo-react-native/SKILL.md +665 -0
- package/template/.agent/skill-library/stack/mobile/flutter/SKILL.md +316 -0
- package/template/.agent/skill-library/stack/mobile/react-native/SKILL.md +337 -0
- package/template/.agent/skill-library/stack/monitoring/posthog/SKILL.md +396 -0
- package/template/.agent/skill-library/stack/monitoring/sentry/SKILL.md +509 -0
- package/template/.agent/skill-library/stack/observability/datadog/SKILL.md +179 -0
- package/template/.agent/skill-library/stack/observability/distributed-tracing/SKILL.md +140 -0
- package/template/.agent/skill-library/stack/observability/logging-best-practices/SKILL.md +168 -0
- package/template/.agent/skill-library/stack/observability/opentelemetry/SKILL.md +164 -0
- package/template/.agent/skill-library/stack/observability/prometheus-grafana/SKILL.md +246 -0
- package/template/.agent/skill-library/stack/observability/python-observability/SKILL.md +158 -0
- package/template/.agent/skill-library/stack/orm/drizzle-orm/SKILL.md +613 -0
- package/template/.agent/skill-library/stack/orm/prisma/SKILL.md +744 -0
- package/template/.agent/skill-library/stack/payments/lemonsqueezy/SKILL.md +393 -0
- package/template/.agent/skill-library/stack/payments/stripe-integration/SKILL.md +457 -0
- package/template/.agent/skill-library/stack/queue/bullmq/SKILL.md +385 -0
- package/template/.agent/skill-library/stack/queue/inngest/SKILL.md +438 -0
- package/template/.agent/skill-library/stack/realtime/socketio/SKILL.md +595 -0
- package/template/.agent/skill-library/stack/search/elasticsearch/SKILL.md +248 -0
- package/template/.agent/skill-library/stack/search/meilisearch/SKILL.md +385 -0
- package/template/.agent/skill-library/stack/security/crypto-patterns/SKILL.md +437 -0
- package/template/.agent/skill-library/stack/security/csp-cors-headers/SKILL.md +588 -0
- package/template/.agent/skill-library/stack/security/dependency-auditing/SKILL.md +560 -0
- package/template/.agent/skill-library/stack/security/input-sanitization/SKILL.md +430 -0
- package/template/.agent/skill-library/stack/security/owasp-web-security/SKILL.md +421 -0
- package/template/.agent/skill-library/stack/state/tanstack-query/SKILL.md +637 -0
- package/template/.agent/skill-library/stack/state/zustand/SKILL.md +483 -0
- package/template/.agent/skill-library/stack/storage/aws-s3/SKILL.md +415 -0
- package/template/.agent/skill-library/stack/testing/playwright/SKILL.md +641 -0
- package/template/.agent/skill-library/stack/testing/storybook/SKILL.md +923 -0
- package/template/.agent/skill-library/stack/testing/testing-library/SKILL.md +872 -0
- package/template/.agent/skill-library/stack/testing/vitest/SKILL.md +714 -0
- package/template/.agent/skill-library/stack/ui/react-best-practices/SKILL.md +877 -0
- package/template/.agent/skill-library/stack/ui/react-composition-patterns/SKILL.md +1107 -0
- package/template/.agent/skill-library/stack/ui/react-flow/SKILL.md +425 -0
- package/template/.agent/skill-library/stack/ui/shadcn-ui/SKILL.md +703 -0
- package/template/.agent/skill-library/surface/api/api-caching/SKILL.md +458 -0
- package/template/.agent/skill-library/surface/api/api-documentation-openapi/SKILL.md +697 -0
- package/template/.agent/skill-library/surface/api/api-error-handling/SKILL.md +478 -0
- package/template/.agent/skill-library/surface/api/api-security-checklist/SKILL.md +147 -0
- package/template/.agent/skill-library/surface/api/api-versioning/SKILL.md +420 -0
- package/template/.agent/skill-library/surface/api/email-best-practices/SKILL.md +59 -0
- package/template/.agent/skill-library/surface/api/rate-limiting-abuse-protection/SKILL.md +147 -0
- package/template/.agent/skill-library/surface/api/rest-api-design/SKILL.md +478 -0
- package/template/.agent/skill-library/surface/api/webhook-design/SKILL.md +752 -0
- package/template/.agent/skill-library/surface/cli/cli-configuration-management/SKILL.md +445 -0
- package/template/.agent/skill-library/surface/cli/cli-error-diagnostics/SKILL.md +515 -0
- package/template/.agent/skill-library/surface/cli/cli-shell-integration/SKILL.md +479 -0
- package/template/.agent/skill-library/surface/cli/cli-ux-design/SKILL.md +477 -0
- package/template/.agent/skill-library/surface/desktop/desktop-app-distribution/SKILL.md +416 -0
- package/template/.agent/skill-library/surface/desktop/desktop-security-sandboxing/SKILL.md +407 -0
- package/template/.agent/skill-library/surface/desktop/desktop-ux-conventions/SKILL.md +361 -0
- package/template/.agent/skill-library/surface/desktop/native-os-integration/SKILL.md +563 -0
- package/template/.agent/skill-library/surface/extension/browser-extension-patterns/SKILL.md +482 -0
- package/template/.agent/skill-library/surface/extension/plugin-architecture-design/SKILL.md +632 -0
- package/template/.agent/skill-library/surface/extension/vscode-extension-development/SKILL.md +728 -0
- package/template/.agent/skill-library/surface/mobile/app-store-submission/SKILL.md +304 -0
- package/template/.agent/skill-library/surface/mobile/mobile-offline-sync/SKILL.md +443 -0
- package/template/.agent/skill-library/surface/mobile/mobile-responsive-patterns/SKILL.md +432 -0
- package/template/.agent/skill-library/surface/mobile/push-notifications/SKILL.md +495 -0
- package/template/.agent/skill-library/surface/web/accessibility-compliance/SKILL.md +827 -0
- package/template/.agent/skill-library/surface/web/ai-seo/SKILL.md +398 -0
- package/template/.agent/skill-library/surface/web/ai-seo/references/content-patterns.md +285 -0
- package/template/.agent/skill-library/surface/web/ai-seo/references/platform-ranking-factors.md +152 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/SKILL.md +309 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/references/event-library.md +260 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/references/ga4-implementation.md +300 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/references/gtm-implementation.md +390 -0
- package/template/.agent/skill-library/surface/web/authentication-ui-flows/SKILL.md +530 -0
- package/template/.agent/skill-library/surface/web/dark-mode-theming/SKILL.md +516 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/SKILL.md +105 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/charts.csv +26 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/colors.csv +97 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/landing.csv +31 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/styles.csv +59 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/typography.csv +58 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/ux-guidelines.csv +100 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/scripts/core.py +258 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/scripts/design_system.py +1067 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/scripts/search.py +106 -0
- package/template/.agent/skill-library/surface/web/form-handling-validation/SKILL.md +675 -0
- package/template/.agent/skill-library/surface/web/frontend-design/SKILL.md +1393 -0
- package/template/.agent/skill-library/surface/web/frontend-design/templates/cppn-hero.tsx +299 -0
- package/template/.agent/skill-library/surface/web/frontend-design/templates/wave-hero.tsx +875 -0
- package/template/.agent/skill-library/surface/web/frontend-verification/SKILL.md +111 -0
- package/template/.agent/skill-library/surface/web/frontend-verification/scripts/ux_audit.py +739 -0
- package/template/.agent/skill-library/surface/web/i18n-localization/SKILL.md +154 -0
- package/template/.agent/skill-library/surface/web/offline-first-pwa/SKILL.md +657 -0
- package/template/.agent/skill-library/surface/web/page-cro/SKILL.md +182 -0
- package/template/.agent/skill-library/surface/web/page-cro/references/experiments.md +248 -0
- package/template/.agent/skill-library/surface/web/programmatic-seo/SKILL.md +238 -0
- package/template/.agent/skill-library/surface/web/programmatic-seo/references/playbooks.md +308 -0
- package/template/.agent/skill-library/surface/web/schema-markup/SKILL.md +179 -0
- package/template/.agent/skill-library/surface/web/schema-markup/references/schema-examples.md +398 -0
- package/template/.agent/skill-library/surface/web/seo-audit/SKILL.md +394 -0
- package/template/.agent/skill-library/surface/web/seo-audit/references/ai-writing-detection.md +200 -0
- package/template/.agent/skill-library/surface/web/web-performance-optimization/SKILL.md +646 -0
- package/template/.agent/skill-library/surface/web/web-scraping/SKILL.md +58 -0
- package/template/.agent/skills/accessibility/SKILL.md +522 -0
- package/template/.agent/skills/accessibility/references/WCAG.md +162 -0
- package/template/.agent/skills/adversarial-review/SKILL.md +90 -0
- package/template/.agent/skills/antigravity-workflows/SKILL.md +81 -0
- package/template/.agent/skills/antigravity-workflows/resources/implementation-playbook.md +36 -0
- package/template/.agent/skills/api-design-principles/SKILL.md +37 -0
- package/template/.agent/skills/api-design-principles/assets/api-design-checklist.md +155 -0
- package/template/.agent/skills/api-design-principles/assets/rest-api-template.py +182 -0
- package/template/.agent/skills/api-design-principles/references/graphql-schema-design.md +583 -0
- package/template/.agent/skills/api-design-principles/references/rest-best-practices.md +408 -0
- package/template/.agent/skills/api-design-principles/resources/implementation-playbook.md +513 -0
- package/template/.agent/skills/api-versioning/SKILL.md +420 -0
- package/template/.agent/skills/architecture-mapping/SKILL.md +219 -0
- package/template/.agent/skills/bootstrap-agents/SKILL.md +259 -0
- package/template/.agent/skills/brainstorming/SKILL.md +236 -0
- package/template/.agent/skills/brand-guidelines/SKILL.md +44 -0
- package/template/.agent/skills/clean-code/SKILL.md +94 -0
- package/template/.agent/skills/code-review-pro/SKILL.md +152 -0
- package/template/.agent/skills/concise-planning/SKILL.md +68 -0
- package/template/.agent/skills/cross-layer-consistency/SKILL.md +117 -0
- package/template/.agent/skills/database-schema-design/SKILL.md +429 -0
- package/template/.agent/skills/deployment-procedures/SKILL.md +241 -0
- package/template/.agent/skills/design-anti-cliche/SKILL.md +159 -0
- package/template/.agent/skills/design-direction/SKILL.md +45 -0
- package/template/.agent/skills/error-handling-patterns/SKILL.md +721 -0
- package/template/.agent/skills/find-skills/SKILL.md +145 -0
- package/template/.agent/skills/git-advanced/SKILL.md +972 -0
- package/template/.agent/skills/git-workflow/SKILL.md +420 -0
- package/template/.agent/skills/idea-extraction/SKILL.md +271 -0
- package/template/.agent/skills/logging-best-practices/SKILL.md +851 -0
- package/template/.agent/skills/migration-management/SKILL.md +384 -0
- package/template/.agent/skills/minimalist-surgical-development/SKILL.md +69 -0
- package/template/.agent/skills/parallel-agents/SKILL.md +165 -0
- package/template/.agent/skills/parallel-debugging/SKILL.md +135 -0
- package/template/.agent/skills/parallel-feature-development/SKILL.md +166 -0
- package/template/.agent/skills/performance-budgeting/SKILL.md +144 -0
- package/template/.agent/skills/pipeline-rubrics/SKILL.md +51 -0
- package/template/.agent/skills/pipeline-rubrics/references/architecture-rubric.md +19 -0
- package/template/.agent/skills/pipeline-rubrics/references/be-rubric.md +21 -0
- package/template/.agent/skills/pipeline-rubrics/references/fe-rubric.md +20 -0
- package/template/.agent/skills/pipeline-rubrics/references/ia-rubric.md +19 -0
- package/template/.agent/skills/pipeline-rubrics/references/scoring.md +28 -0
- package/template/.agent/skills/pipeline-rubrics/references/vision-rubric.md +11 -0
- package/template/.agent/skills/prd-templates/SKILL.md +88 -0
- package/template/.agent/skills/prd-templates/references/architecture-design-template.md +88 -0
- package/template/.agent/skills/prd-templates/references/be-spec-template.md +101 -0
- package/template/.agent/skills/prd-templates/references/data-placement-template.md +74 -0
- package/template/.agent/skills/prd-templates/references/decomposition-templates.md +211 -0
- package/template/.agent/skills/prd-templates/references/design-system-decisions.md +198 -0
- package/template/.agent/skills/prd-templates/references/engineering-standards-template.md +124 -0
- package/template/.agent/skills/prd-templates/references/fe-classification-procedures.md +47 -0
- package/template/.agent/skills/prd-templates/references/fe-spec-template.md +84 -0
- package/template/.agent/skills/prd-templates/references/infrastructure-report-template.md +71 -0
- package/template/.agent/skills/prd-templates/references/operational-templates.md +116 -0
- package/template/.agent/skills/prd-templates/references/placeholder-guard-template.md +21 -0
- package/template/.agent/skills/prd-templates/references/surface-model.md +61 -0
- package/template/.agent/skills/prd-templates/references/vision-template.md +66 -0
- package/template/.agent/skills/prompt-engineer/README.md +659 -0
- package/template/.agent/skills/prompt-engineer/SKILL.md +249 -0
- package/template/.agent/skills/regex-patterns/SKILL.md +751 -0
- package/template/.agent/skills/resolve-ambiguity/SKILL.md +278 -0
- package/template/.agent/skills/rest-api-design/SKILL.md +478 -0
- package/template/.agent/skills/security-scanning-security-hardening/SKILL.md +231 -0
- package/template/.agent/skills/session-continuity/SKILL.md +730 -0
- package/template/.agent/skills/session-continuity/protocols/01-session-resumption.md +38 -0
- package/template/.agent/skills/session-continuity/protocols/02-progress-generation.md +85 -0
- package/template/.agent/skills/session-continuity/protocols/03-progress-update.md +70 -0
- package/template/.agent/skills/session-continuity/protocols/04-pattern-extraction.md +60 -0
- package/template/.agent/skills/session-continuity/protocols/05-session-close.md +37 -0
- package/template/.agent/skills/session-continuity/protocols/06-decision-analysis.md +84 -0
- package/template/.agent/skills/session-continuity/protocols/07-spec-pipeline-generation.md +48 -0
- package/template/.agent/skills/session-continuity/protocols/08-spec-pipeline-update.md +43 -0
- package/template/.agent/skills/session-continuity/protocols/09-parallel-claim.md +122 -0
- package/template/.agent/skills/session-continuity/protocols/10-placeholder-verification-gate.md +104 -0
- package/template/.agent/skills/session-continuity/protocols/ambiguity-gates.md +48 -0
- package/template/.agent/skills/skill-creator/LICENSE.txt +202 -0
- package/template/.agent/skills/skill-creator/README.md +270 -0
- package/template/.agent/skills/skill-creator/SKILL.md +590 -0
- package/template/.agent/skills/skill-creator/references/output-patterns.md +82 -0
- package/template/.agent/skills/skill-creator/references/workflows.md +28 -0
- package/template/.agent/skills/skill-creator/scripts/init_skill.py +303 -0
- package/template/.agent/skills/skill-creator/scripts/package_skill.py +110 -0
- package/template/.agent/skills/skill-creator/scripts/quick_validate.py +95 -0
- package/template/.agent/skills/spec-writing/SKILL.md +110 -0
- package/template/.agent/skills/systematic-debugging/CREATION-LOG.md +119 -0
- package/template/.agent/skills/systematic-debugging/SKILL.md +297 -0
- package/template/.agent/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
- package/template/.agent/skills/systematic-debugging/condition-based-waiting.md +115 -0
- package/template/.agent/skills/systematic-debugging/defense-in-depth.md +122 -0
- package/template/.agent/skills/systematic-debugging/find-polluter.sh +63 -0
- package/template/.agent/skills/systematic-debugging/root-cause-tracing.md +169 -0
- package/template/.agent/skills/systematic-debugging/test-academic.md +14 -0
- package/template/.agent/skills/systematic-debugging/test-pressure-1.md +58 -0
- package/template/.agent/skills/systematic-debugging/test-pressure-2.md +68 -0
- package/template/.agent/skills/systematic-debugging/test-pressure-3.md +69 -0
- package/template/.agent/skills/tdd-workflow/SKILL.md +409 -0
- package/template/.agent/skills/tech-stack-catalog/SKILL.md +49 -0
- package/template/.agent/skills/tech-stack-catalog/references/constraint-questions.md +21 -0
- package/template/.agent/skills/tech-stack-catalog/references/dev-tooling-decisions.md +37 -0
- package/template/.agent/skills/tech-stack-catalog/references/surface-decision-tables.md +69 -0
- package/template/.agent/skills/technical-writer/SKILL.md +242 -0
- package/template/.agent/skills/testing-strategist/SKILL.md +932 -0
- package/template/.agent/skills/verification-before-completion/SKILL.md +145 -0
- package/template/.agent/skills/workflow-automation/SKILL.md +73 -0
- package/template/.agent/workflows/audit-ambiguity-execute.md +165 -0
- package/template/.agent/workflows/audit-ambiguity-rubrics.md +83 -0
- package/template/.agent/workflows/audit-ambiguity.md +64 -0
- package/template/.agent/workflows/bootstrap-agents-fill.md +201 -0
- package/template/.agent/workflows/bootstrap-agents-provision.md +197 -0
- package/template/.agent/workflows/bootstrap-agents.md +66 -0
- package/template/.agent/workflows/create-prd-architecture.md +119 -0
- package/template/.agent/workflows/create-prd-compile.md +138 -0
- package/template/.agent/workflows/create-prd-design-system.md +135 -0
- package/template/.agent/workflows/create-prd-security.md +113 -0
- package/template/.agent/workflows/create-prd-stack.md +91 -0
- package/template/.agent/workflows/create-prd.md +168 -0
- package/template/.agent/workflows/decompose-architecture-structure.md +82 -0
- package/template/.agent/workflows/decompose-architecture-validate.md +119 -0
- package/template/.agent/workflows/decompose-architecture.md +111 -0
- package/template/.agent/workflows/evolve-contract.md +98 -0
- package/template/.agent/workflows/evolve-feature-cascade.md +140 -0
- package/template/.agent/workflows/evolve-feature-classify.md +116 -0
- package/template/.agent/workflows/evolve-feature.md +56 -0
- package/template/.agent/workflows/ideate-discover.md +144 -0
- package/template/.agent/workflows/ideate-extract.md +129 -0
- package/template/.agent/workflows/ideate-validate.md +117 -0
- package/template/.agent/workflows/ideate.md +113 -0
- package/template/.agent/workflows/implement-slice-setup.md +113 -0
- package/template/.agent/workflows/implement-slice-tdd.md +198 -0
- package/template/.agent/workflows/implement-slice.md +50 -0
- package/template/.agent/workflows/plan-phase.md +202 -0
- package/template/.agent/workflows/propagate-decision-apply.md +135 -0
- package/template/.agent/workflows/propagate-decision-scan.md +147 -0
- package/template/.agent/workflows/propagate-decision.md +56 -0
- package/template/.agent/workflows/remediate-pipeline-assess.md +138 -0
- package/template/.agent/workflows/remediate-pipeline-execute.md +135 -0
- package/template/.agent/workflows/remediate-pipeline.md +55 -0
- package/template/.agent/workflows/resolve-ambiguity.md +82 -0
- package/template/.agent/workflows/sync-kit.md +209 -0
- package/template/.agent/workflows/update-architecture-map.md +74 -0
- package/template/.agent/workflows/validate-phase.md +219 -0
- package/template/.agent/workflows/verify-infrastructure.md +207 -0
- package/template/.agent/workflows/write-architecture-spec-deepen.md +139 -0
- package/template/.agent/workflows/write-architecture-spec-design.md +202 -0
- package/template/.agent/workflows/write-architecture-spec.md +63 -0
- package/template/.agent/workflows/write-be-spec-classify.md +165 -0
- package/template/.agent/workflows/write-be-spec-write.md +98 -0
- package/template/.agent/workflows/write-be-spec.md +76 -0
- package/template/.agent/workflows/write-fe-spec-classify.md +170 -0
- package/template/.agent/workflows/write-fe-spec-write.md +94 -0
- package/template/.agent/workflows/write-fe-spec.md +71 -0
- package/template/AGENTS.md +176 -0
- package/template/GEMINI.md +177 -0
- package/template/docs/README.md +187 -0
- package/template/docs/audits/.gitkeep +0 -0
- package/template/docs/audits/README.md +10 -0
- package/template/docs/plans/.gitkeep +0 -0
- package/template/docs/plans/README.md +21 -0
- package/template/docs/plans/be/.gitkeep +0 -0
- package/template/docs/plans/be/README.md +11 -0
- package/template/docs/plans/fe/.gitkeep +0 -0
- package/template/docs/plans/fe/README.md +11 -0
- package/template/docs/plans/ia/.gitkeep +0 -0
- package/template/docs/plans/ia/README.md +17 -0
- package/template/docs/plans/ia/deep-dives/.gitkeep +0 -0
- package/template/docs/plans/ia/deep-dives/README.md +5 -0
- package/template/docs/plans/phases/.gitkeep +0 -0
- package/template/docs/plans/phases/README.md +11 -0
|
@@ -0,0 +1,678 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: python
|
|
3
|
+
description: Python development patterns for modern, type-safe, production-grade code. Covers type hints (PEP 604+), dataclasses vs pydantic, async/await, virtual environments, pytest, packaging, and common pitfalls.
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Python Development Patterns
|
|
8
|
+
|
|
9
|
+
Expert guidance for writing modern, type-safe, production-grade Python code. Covers typing, data modeling, async patterns, testing, packaging, and the most common pitfalls that trip up developers at every level.
|
|
10
|
+
|
|
11
|
+
## When to Use This Skill
|
|
12
|
+
|
|
13
|
+
- Starting a new Python project and need modern best practices
|
|
14
|
+
- Adding type hints to an existing codebase
|
|
15
|
+
- Choosing between dataclasses, pydantic, and attrs for data modeling
|
|
16
|
+
- Writing async code with asyncio
|
|
17
|
+
- Setting up pytest with fixtures and parameterization
|
|
18
|
+
- Packaging a library for distribution
|
|
19
|
+
- Debugging common Python gotchas (mutable defaults, GIL, import cycles)
|
|
20
|
+
|
|
21
|
+
## Core Concepts
|
|
22
|
+
|
|
23
|
+
### 1. Modern Type Hints (PEP 604+)
|
|
24
|
+
|
|
25
|
+
Python 3.10+ union syntax and modern typing patterns.
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
# Modern union syntax (PEP 604) -- use this, not Union[]
|
|
29
|
+
def process(value: str | int | None) -> str:
|
|
30
|
+
if value is None:
|
|
31
|
+
return "empty"
|
|
32
|
+
return str(value)
|
|
33
|
+
|
|
34
|
+
# Built-in generics (PEP 585) -- use this, not typing.List etc.
|
|
35
|
+
def filter_items(items: list[str], predicate: Callable[[str], bool]) -> list[str]:
|
|
36
|
+
return [item for item in items if predicate(item)]
|
|
37
|
+
|
|
38
|
+
# TypeVar for generic functions
|
|
39
|
+
from typing import TypeVar
|
|
40
|
+
|
|
41
|
+
T = TypeVar("T")
|
|
42
|
+
|
|
43
|
+
def first(items: list[T]) -> T | None:
|
|
44
|
+
return items[0] if items else None
|
|
45
|
+
|
|
46
|
+
# ParamSpec for decorator typing (PEP 612)
|
|
47
|
+
from typing import ParamSpec, TypeVar
|
|
48
|
+
from functools import wraps
|
|
49
|
+
|
|
50
|
+
P = ParamSpec("P")
|
|
51
|
+
R = TypeVar("R")
|
|
52
|
+
|
|
53
|
+
def retry(attempts: int = 3) -> Callable[[Callable[P, R]], Callable[P, R]]:
|
|
54
|
+
def decorator(func: Callable[P, R]) -> Callable[P, R]:
|
|
55
|
+
@wraps(func)
|
|
56
|
+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
|
|
57
|
+
for i in range(attempts):
|
|
58
|
+
try:
|
|
59
|
+
return func(*args, **kwargs)
|
|
60
|
+
except Exception:
|
|
61
|
+
if i == attempts - 1:
|
|
62
|
+
raise
|
|
63
|
+
raise RuntimeError("unreachable")
|
|
64
|
+
return wrapper
|
|
65
|
+
return decorator
|
|
66
|
+
|
|
67
|
+
# TypedDict for structured dictionaries
|
|
68
|
+
from typing import TypedDict, NotRequired
|
|
69
|
+
|
|
70
|
+
class UserConfig(TypedDict):
|
|
71
|
+
name: str
|
|
72
|
+
email: str
|
|
73
|
+
theme: NotRequired[str] # Optional key
|
|
74
|
+
|
|
75
|
+
# Literal types for constrained values
|
|
76
|
+
from typing import Literal
|
|
77
|
+
|
|
78
|
+
def set_log_level(level: Literal["debug", "info", "warning", "error"]) -> None:
|
|
79
|
+
...
|
|
80
|
+
|
|
81
|
+
# Self type (PEP 673, Python 3.11+)
|
|
82
|
+
from typing import Self
|
|
83
|
+
|
|
84
|
+
class Builder:
|
|
85
|
+
def with_name(self, name: str) -> Self:
|
|
86
|
+
self._name = name
|
|
87
|
+
return self
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 2. Dataclasses vs Pydantic vs Attrs
|
|
91
|
+
|
|
92
|
+
Choose the right data modeling tool for your context.
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
# --- dataclasses: stdlib, no dependencies, compile-time typing only ---
|
|
96
|
+
from dataclasses import dataclass, field
|
|
97
|
+
|
|
98
|
+
@dataclass(frozen=True, slots=True)
|
|
99
|
+
class Point:
|
|
100
|
+
x: float
|
|
101
|
+
y: float
|
|
102
|
+
label: str = "origin"
|
|
103
|
+
|
|
104
|
+
def distance_to(self, other: "Point") -> float:
|
|
105
|
+
return ((self.x - other.x) ** 2 + (self.y - other.y) ** 2) ** 0.5
|
|
106
|
+
|
|
107
|
+
# Use frozen=True for immutability
|
|
108
|
+
# Use slots=True for memory efficiency and faster attribute access
|
|
109
|
+
|
|
110
|
+
# --- pydantic: runtime validation, serialization, settings ---
|
|
111
|
+
from pydantic import BaseModel, Field, field_validator
|
|
112
|
+
|
|
113
|
+
class User(BaseModel):
|
|
114
|
+
model_config = {"strict": True}
|
|
115
|
+
|
|
116
|
+
name: str = Field(min_length=1, max_length=100)
|
|
117
|
+
email: str
|
|
118
|
+
age: int = Field(ge=13, le=150)
|
|
119
|
+
|
|
120
|
+
@field_validator("email")
|
|
121
|
+
@classmethod
|
|
122
|
+
def validate_email(cls, v: str) -> str:
|
|
123
|
+
if "@" not in v:
|
|
124
|
+
raise ValueError("invalid email format")
|
|
125
|
+
return v.lower()
|
|
126
|
+
|
|
127
|
+
# Pydantic v2 uses model_config instead of class Config
|
|
128
|
+
# Use strict=True to prevent type coercion
|
|
129
|
+
|
|
130
|
+
# --- attrs: flexible, fast, no runtime validation by default ---
|
|
131
|
+
import attrs
|
|
132
|
+
|
|
133
|
+
@attrs.define(frozen=True)
|
|
134
|
+
class Config:
|
|
135
|
+
host: str
|
|
136
|
+
port: int = attrs.field(validator=attrs.validators.instance_of(int))
|
|
137
|
+
debug: bool = False
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**Decision matrix:**
|
|
141
|
+
|
|
142
|
+
| Need | Use |
|
|
143
|
+
|------|-----|
|
|
144
|
+
| Simple data container, no validation | `dataclass` |
|
|
145
|
+
| Runtime validation, API boundaries | `pydantic` |
|
|
146
|
+
| Complex validation, high performance | `attrs` |
|
|
147
|
+
| Config from env/files | `pydantic-settings` |
|
|
148
|
+
| Database ORM | `SQLAlchemy` or `pydantic` |
|
|
149
|
+
|
|
150
|
+
### 3. Async/Await with asyncio
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
import asyncio
|
|
154
|
+
from typing import AsyncIterator
|
|
155
|
+
|
|
156
|
+
# Basic async function
|
|
157
|
+
async def fetch_data(url: str) -> dict:
|
|
158
|
+
async with aiohttp.ClientSession() as session:
|
|
159
|
+
async with session.get(url) as response:
|
|
160
|
+
response.raise_for_status()
|
|
161
|
+
return await response.json()
|
|
162
|
+
|
|
163
|
+
# Gather for concurrent execution
|
|
164
|
+
async def fetch_all(urls: list[str]) -> list[dict]:
|
|
165
|
+
return await asyncio.gather(*(fetch_data(url) for url in urls))
|
|
166
|
+
|
|
167
|
+
# TaskGroup (Python 3.11+) -- preferred over gather
|
|
168
|
+
async def fetch_all_safe(urls: list[str]) -> list[dict]:
|
|
169
|
+
results: list[dict] = []
|
|
170
|
+
async with asyncio.TaskGroup() as tg:
|
|
171
|
+
for url in urls:
|
|
172
|
+
tg.create_task(fetch_and_append(url, results))
|
|
173
|
+
return results
|
|
174
|
+
|
|
175
|
+
# Async generators
|
|
176
|
+
async def stream_lines(path: str) -> AsyncIterator[str]:
|
|
177
|
+
async with aiofiles.open(path, "r") as f:
|
|
178
|
+
async for line in f:
|
|
179
|
+
yield line.strip()
|
|
180
|
+
|
|
181
|
+
# Semaphore for rate limiting
|
|
182
|
+
async def rate_limited_fetch(urls: list[str], max_concurrent: int = 10) -> list[dict]:
|
|
183
|
+
semaphore = asyncio.Semaphore(max_concurrent)
|
|
184
|
+
|
|
185
|
+
async def bounded_fetch(url: str) -> dict:
|
|
186
|
+
async with semaphore:
|
|
187
|
+
return await fetch_data(url)
|
|
188
|
+
|
|
189
|
+
return await asyncio.gather(*(bounded_fetch(url) for url in urls))
|
|
190
|
+
|
|
191
|
+
# Timeout handling
|
|
192
|
+
async def fetch_with_timeout(url: str, timeout_seconds: float = 5.0) -> dict:
|
|
193
|
+
async with asyncio.timeout(timeout_seconds): # Python 3.11+
|
|
194
|
+
return await fetch_data(url)
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
**Anti-pattern: mixing sync and async incorrectly.**
|
|
198
|
+
|
|
199
|
+
```python
|
|
200
|
+
# WRONG -- blocks the event loop
|
|
201
|
+
async def bad_example():
|
|
202
|
+
import requests # sync library in async context!
|
|
203
|
+
return requests.get("https://example.com")
|
|
204
|
+
|
|
205
|
+
# RIGHT -- use async libraries
|
|
206
|
+
async def good_example():
|
|
207
|
+
async with aiohttp.ClientSession() as session:
|
|
208
|
+
async with session.get("https://example.com") as resp:
|
|
209
|
+
return await resp.text()
|
|
210
|
+
|
|
211
|
+
# If you MUST call sync code from async:
|
|
212
|
+
async def call_sync_from_async():
|
|
213
|
+
loop = asyncio.get_running_loop()
|
|
214
|
+
result = await loop.run_in_executor(None, sync_heavy_function)
|
|
215
|
+
return result
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### 4. Virtual Environments
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
# venv (stdlib) -- always works, no extra tools
|
|
222
|
+
python -m venv .venv
|
|
223
|
+
source .venv/bin/activate
|
|
224
|
+
pip install -r requirements.txt
|
|
225
|
+
|
|
226
|
+
# uv (fast, modern) -- recommended for speed
|
|
227
|
+
uv venv
|
|
228
|
+
uv pip install -r requirements.txt
|
|
229
|
+
uv pip compile requirements.in -o requirements.txt
|
|
230
|
+
|
|
231
|
+
# poetry -- dependency resolution + packaging
|
|
232
|
+
poetry init
|
|
233
|
+
poetry add requests
|
|
234
|
+
poetry install
|
|
235
|
+
poetry build
|
|
236
|
+
|
|
237
|
+
# pip-tools -- lightweight lockfile approach
|
|
238
|
+
pip-compile requirements.in # Generate lockfile
|
|
239
|
+
pip-sync requirements.txt # Install exact versions
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
**Decision matrix:**
|
|
243
|
+
|
|
244
|
+
| Need | Use |
|
|
245
|
+
|------|-----|
|
|
246
|
+
| Quick scripts, CI | `uv` or `venv + pip` |
|
|
247
|
+
| Library packaging | `poetry` or `hatch` |
|
|
248
|
+
| Reproducible deployments | `uv pip compile` or `pip-tools` |
|
|
249
|
+
| Data science | `conda` or `mamba` |
|
|
250
|
+
|
|
251
|
+
### 5. Testing with pytest
|
|
252
|
+
|
|
253
|
+
```python
|
|
254
|
+
import pytest
|
|
255
|
+
from unittest.mock import AsyncMock, patch
|
|
256
|
+
|
|
257
|
+
# Basic test with descriptive naming
|
|
258
|
+
def test_user_creation_requires_valid_email():
|
|
259
|
+
with pytest.raises(ValueError, match="invalid email"):
|
|
260
|
+
User(name="test", email="not-an-email", age=25)
|
|
261
|
+
|
|
262
|
+
# Fixtures for shared setup
|
|
263
|
+
@pytest.fixture
|
|
264
|
+
def sample_user() -> User:
|
|
265
|
+
return User(name="Alice", email="alice@example.com", age=30)
|
|
266
|
+
|
|
267
|
+
@pytest.fixture
|
|
268
|
+
async def db_session() -> AsyncIterator[Session]:
|
|
269
|
+
session = await create_session()
|
|
270
|
+
yield session
|
|
271
|
+
await session.rollback()
|
|
272
|
+
await session.close()
|
|
273
|
+
|
|
274
|
+
# Parametrize for table-driven tests
|
|
275
|
+
@pytest.mark.parametrize(
|
|
276
|
+
"input_age, expected_valid",
|
|
277
|
+
[
|
|
278
|
+
(12, False), # Under minimum
|
|
279
|
+
(13, True), # Minimum boundary
|
|
280
|
+
(17, True), # Junior upper bound
|
|
281
|
+
(18, True), # Adult boundary
|
|
282
|
+
(150, True), # Maximum boundary
|
|
283
|
+
(151, False), # Over maximum
|
|
284
|
+
],
|
|
285
|
+
ids=["under-min", "min-boundary", "junior-upper", "adult-boundary", "max", "over-max"],
|
|
286
|
+
)
|
|
287
|
+
def test_age_validation(input_age: int, expected_valid: bool):
|
|
288
|
+
if expected_valid:
|
|
289
|
+
user = User(name="Test", email="t@t.com", age=input_age)
|
|
290
|
+
assert user.age == input_age
|
|
291
|
+
else:
|
|
292
|
+
with pytest.raises(ValueError):
|
|
293
|
+
User(name="Test", email="t@t.com", age=input_age)
|
|
294
|
+
|
|
295
|
+
# Async test
|
|
296
|
+
@pytest.mark.asyncio
|
|
297
|
+
async def test_fetch_returns_data():
|
|
298
|
+
result = await fetch_data("https://api.example.com/data")
|
|
299
|
+
assert "id" in result
|
|
300
|
+
|
|
301
|
+
# Mocking external services
|
|
302
|
+
async def test_fetch_handles_timeout():
|
|
303
|
+
with patch("module.aiohttp.ClientSession") as mock_session:
|
|
304
|
+
mock_session.return_value.__aenter__.return_value.get = AsyncMock(
|
|
305
|
+
side_effect=asyncio.TimeoutError()
|
|
306
|
+
)
|
|
307
|
+
with pytest.raises(asyncio.TimeoutError):
|
|
308
|
+
await fetch_data("https://slow.example.com")
|
|
309
|
+
|
|
310
|
+
# conftest.py for shared fixtures
|
|
311
|
+
# Place in tests/conftest.py -- pytest discovers it automatically
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
### 6. F-Strings and String Formatting
|
|
315
|
+
|
|
316
|
+
```python
|
|
317
|
+
# f-strings -- always preferred for interpolation
|
|
318
|
+
name = "world"
|
|
319
|
+
greeting = f"Hello, {name}!"
|
|
320
|
+
|
|
321
|
+
# Expressions inside f-strings
|
|
322
|
+
items = [1, 2, 3]
|
|
323
|
+
summary = f"Count: {len(items)}, Sum: {sum(items)}"
|
|
324
|
+
|
|
325
|
+
# Format specifiers
|
|
326
|
+
price = 49.99
|
|
327
|
+
formatted = f"Price: ${price:.2f}"
|
|
328
|
+
percentage = f"Rate: {0.156:.1%}" # "Rate: 15.6%"
|
|
329
|
+
|
|
330
|
+
# Debug format (Python 3.8+)
|
|
331
|
+
x = 42
|
|
332
|
+
print(f"{x = }") # prints "x = 42"
|
|
333
|
+
|
|
334
|
+
# Multiline f-strings
|
|
335
|
+
query = (
|
|
336
|
+
f"SELECT * FROM users "
|
|
337
|
+
f"WHERE age >= {min_age} "
|
|
338
|
+
f"AND status = '{status}'"
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
# NEVER use f-strings for SQL -- use parameterized queries!
|
|
342
|
+
# This is for illustration only. See anti-patterns below.
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
### 7. Context Managers
|
|
346
|
+
|
|
347
|
+
```python
|
|
348
|
+
from contextlib import contextmanager, asynccontextmanager
|
|
349
|
+
from typing import Iterator, AsyncIterator
|
|
350
|
+
|
|
351
|
+
# Class-based context manager
|
|
352
|
+
class DatabaseConnection:
|
|
353
|
+
def __init__(self, url: str) -> None:
|
|
354
|
+
self.url = url
|
|
355
|
+
self._conn: Connection | None = None
|
|
356
|
+
|
|
357
|
+
def __enter__(self) -> Connection:
|
|
358
|
+
self._conn = connect(self.url)
|
|
359
|
+
return self._conn
|
|
360
|
+
|
|
361
|
+
def __exit__(
|
|
362
|
+
self,
|
|
363
|
+
exc_type: type[BaseException] | None,
|
|
364
|
+
exc_val: BaseException | None,
|
|
365
|
+
exc_tb: TracebackType | None,
|
|
366
|
+
) -> bool:
|
|
367
|
+
if self._conn:
|
|
368
|
+
if exc_type:
|
|
369
|
+
self._conn.rollback()
|
|
370
|
+
else:
|
|
371
|
+
self._conn.commit()
|
|
372
|
+
self._conn.close()
|
|
373
|
+
return False # Do not suppress exceptions
|
|
374
|
+
|
|
375
|
+
# Generator-based context manager (simpler)
|
|
376
|
+
@contextmanager
|
|
377
|
+
def temp_directory() -> Iterator[Path]:
|
|
378
|
+
path = Path(tempfile.mkdtemp())
|
|
379
|
+
try:
|
|
380
|
+
yield path
|
|
381
|
+
finally:
|
|
382
|
+
shutil.rmtree(path)
|
|
383
|
+
|
|
384
|
+
# Async context manager
|
|
385
|
+
@asynccontextmanager
|
|
386
|
+
async def managed_session() -> AsyncIterator[Session]:
|
|
387
|
+
session = await create_session()
|
|
388
|
+
try:
|
|
389
|
+
yield session
|
|
390
|
+
await session.commit()
|
|
391
|
+
except Exception:
|
|
392
|
+
await session.rollback()
|
|
393
|
+
raise
|
|
394
|
+
finally:
|
|
395
|
+
await session.close()
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
### 8. Decorators
|
|
399
|
+
|
|
400
|
+
```python
|
|
401
|
+
from functools import wraps
|
|
402
|
+
import time
|
|
403
|
+
from typing import Callable, TypeVar, ParamSpec
|
|
404
|
+
|
|
405
|
+
P = ParamSpec("P")
|
|
406
|
+
R = TypeVar("R")
|
|
407
|
+
|
|
408
|
+
# Simple decorator with wraps
|
|
409
|
+
def log_calls(func: Callable[P, R]) -> Callable[P, R]:
|
|
410
|
+
@wraps(func)
|
|
411
|
+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
|
|
412
|
+
print(f"Calling {func.__name__}")
|
|
413
|
+
result = func(*args, **kwargs)
|
|
414
|
+
print(f"{func.__name__} returned {result!r}")
|
|
415
|
+
return result
|
|
416
|
+
return wrapper
|
|
417
|
+
|
|
418
|
+
# Decorator with arguments
|
|
419
|
+
def rate_limit(max_calls: int, period: float) -> Callable[[Callable[P, R]], Callable[P, R]]:
|
|
420
|
+
def decorator(func: Callable[P, R]) -> Callable[P, R]:
|
|
421
|
+
calls: list[float] = []
|
|
422
|
+
|
|
423
|
+
@wraps(func)
|
|
424
|
+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
|
|
425
|
+
now = time.monotonic()
|
|
426
|
+
calls[:] = [t for t in calls if now - t < period]
|
|
427
|
+
if len(calls) >= max_calls:
|
|
428
|
+
raise RuntimeError(f"Rate limit exceeded: {max_calls} calls per {period}s")
|
|
429
|
+
calls.append(now)
|
|
430
|
+
return func(*args, **kwargs)
|
|
431
|
+
return wrapper
|
|
432
|
+
return decorator
|
|
433
|
+
|
|
434
|
+
@rate_limit(max_calls=5, period=60.0)
|
|
435
|
+
def api_call(endpoint: str) -> dict:
|
|
436
|
+
...
|
|
437
|
+
|
|
438
|
+
# Class decorator
|
|
439
|
+
def singleton(cls: type[T]) -> type[T]:
|
|
440
|
+
instances: dict[type, T] = {}
|
|
441
|
+
original_new = cls.__new__
|
|
442
|
+
|
|
443
|
+
@wraps(cls.__new__)
|
|
444
|
+
def new_instance(klass: type[T], *args, **kwargs) -> T:
|
|
445
|
+
if klass not in instances:
|
|
446
|
+
instances[klass] = original_new(klass)
|
|
447
|
+
return instances[klass]
|
|
448
|
+
|
|
449
|
+
cls.__new__ = new_instance # type: ignore[assignment]
|
|
450
|
+
return cls
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
### 9. Generators and Iterators
|
|
454
|
+
|
|
455
|
+
```python
|
|
456
|
+
from typing import Generator, Iterator
|
|
457
|
+
|
|
458
|
+
# Generator function
|
|
459
|
+
def fibonacci() -> Generator[int, None, None]:
|
|
460
|
+
a, b = 0, 1
|
|
461
|
+
while True:
|
|
462
|
+
yield a
|
|
463
|
+
a, b = b, a + b
|
|
464
|
+
|
|
465
|
+
# Use itertools for composition
|
|
466
|
+
from itertools import islice, chain, groupby
|
|
467
|
+
|
|
468
|
+
first_10_fib = list(islice(fibonacci(), 10))
|
|
469
|
+
|
|
470
|
+
# Generator expression (lazy evaluation)
|
|
471
|
+
squares = (x ** 2 for x in range(1_000_000)) # No memory allocation
|
|
472
|
+
|
|
473
|
+
# Generator for processing large files
|
|
474
|
+
def read_large_file(path: str, chunk_size: int = 8192) -> Generator[str, None, None]:
|
|
475
|
+
with open(path, "r") as f:
|
|
476
|
+
while chunk := f.read(chunk_size):
|
|
477
|
+
yield chunk
|
|
478
|
+
|
|
479
|
+
# Send values into generators
|
|
480
|
+
def running_average() -> Generator[float, float, None]:
|
|
481
|
+
total = 0.0
|
|
482
|
+
count = 0
|
|
483
|
+
while True:
|
|
484
|
+
value = yield total / count if count else 0.0
|
|
485
|
+
total += value
|
|
486
|
+
count += 1
|
|
487
|
+
|
|
488
|
+
avg = running_average()
|
|
489
|
+
next(avg) # Prime the generator
|
|
490
|
+
avg.send(10.0) # 10.0
|
|
491
|
+
avg.send(20.0) # 15.0
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
### 10. pathlib Over os.path
|
|
495
|
+
|
|
496
|
+
```python
|
|
497
|
+
from pathlib import Path
|
|
498
|
+
|
|
499
|
+
# Path construction
|
|
500
|
+
config_dir = Path.home() / ".config" / "myapp"
|
|
501
|
+
config_file = config_dir / "settings.json"
|
|
502
|
+
|
|
503
|
+
# Common operations
|
|
504
|
+
config_dir.mkdir(parents=True, exist_ok=True)
|
|
505
|
+
|
|
506
|
+
if config_file.exists():
|
|
507
|
+
data = config_file.read_text(encoding="utf-8")
|
|
508
|
+
config = json.loads(data)
|
|
509
|
+
|
|
510
|
+
# Glob patterns
|
|
511
|
+
for py_file in Path("src").rglob("*.py"):
|
|
512
|
+
print(py_file.stem) # filename without extension
|
|
513
|
+
|
|
514
|
+
# File info
|
|
515
|
+
size = config_file.stat().st_size
|
|
516
|
+
suffix = config_file.suffix # ".json"
|
|
517
|
+
parent = config_file.parent # Path to directory
|
|
518
|
+
|
|
519
|
+
# Path manipulation
|
|
520
|
+
relative = config_file.relative_to(Path.home())
|
|
521
|
+
resolved = config_file.resolve() # Absolute, symlinks resolved
|
|
522
|
+
|
|
523
|
+
# Writing files
|
|
524
|
+
output = Path("output.txt")
|
|
525
|
+
output.write_text("Hello, world!", encoding="utf-8")
|
|
526
|
+
output.write_bytes(b"\x00\x01\x02")
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
## Common Pitfalls
|
|
530
|
+
|
|
531
|
+
### Mutable Default Arguments
|
|
532
|
+
|
|
533
|
+
```python
|
|
534
|
+
# WRONG -- list is shared across all calls
|
|
535
|
+
def append_to(item: str, target: list[str] = []) -> list[str]:
|
|
536
|
+
target.append(item)
|
|
537
|
+
return target
|
|
538
|
+
|
|
539
|
+
# RIGHT -- use None sentinel
|
|
540
|
+
def append_to(item: str, target: list[str] | None = None) -> list[str]:
|
|
541
|
+
if target is None:
|
|
542
|
+
target = []
|
|
543
|
+
target.append(item)
|
|
544
|
+
return target
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
### Late Binding Closures
|
|
548
|
+
|
|
549
|
+
```python
|
|
550
|
+
# WRONG -- all lambdas capture the final value of i
|
|
551
|
+
funcs = [lambda: i for i in range(5)]
|
|
552
|
+
[f() for f in funcs] # [4, 4, 4, 4, 4]
|
|
553
|
+
|
|
554
|
+
# RIGHT -- bind i as default argument
|
|
555
|
+
funcs = [lambda i=i: i for i in range(5)]
|
|
556
|
+
[f() for f in funcs] # [0, 1, 2, 3, 4]
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
### The GIL (Global Interpreter Lock)
|
|
560
|
+
|
|
561
|
+
```python
|
|
562
|
+
# CPU-bound work: use multiprocessing, NOT threading
|
|
563
|
+
from concurrent.futures import ProcessPoolExecutor
|
|
564
|
+
|
|
565
|
+
def cpu_heavy(n: int) -> int:
|
|
566
|
+
return sum(i * i for i in range(n))
|
|
567
|
+
|
|
568
|
+
with ProcessPoolExecutor() as executor:
|
|
569
|
+
results = list(executor.map(cpu_heavy, [10**6] * 4))
|
|
570
|
+
|
|
571
|
+
# I/O-bound work: threading or asyncio is fine
|
|
572
|
+
from concurrent.futures import ThreadPoolExecutor
|
|
573
|
+
|
|
574
|
+
def io_bound(url: str) -> str:
|
|
575
|
+
return requests.get(url).text
|
|
576
|
+
|
|
577
|
+
with ThreadPoolExecutor(max_workers=10) as executor:
|
|
578
|
+
results = list(executor.map(io_bound, urls))
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
### Import Cycles
|
|
582
|
+
|
|
583
|
+
```python
|
|
584
|
+
# WRONG -- circular import at module level
|
|
585
|
+
# file_a.py
|
|
586
|
+
from file_b import B # file_b tries to import from file_a
|
|
587
|
+
|
|
588
|
+
# RIGHT -- defer import or use TYPE_CHECKING
|
|
589
|
+
from __future__ import annotations
|
|
590
|
+
from typing import TYPE_CHECKING
|
|
591
|
+
|
|
592
|
+
if TYPE_CHECKING:
|
|
593
|
+
from file_b import B
|
|
594
|
+
|
|
595
|
+
def process(b: "B") -> None:
|
|
596
|
+
...
|
|
597
|
+
```
|
|
598
|
+
|
|
599
|
+
## Anti-Patterns
|
|
600
|
+
|
|
601
|
+
| Anti-Pattern | Why It Is Bad | Do This Instead |
|
|
602
|
+
|-------------|--------------|----------------|
|
|
603
|
+
| `except Exception: pass` | Silences all errors | Catch specific exceptions, log, re-raise |
|
|
604
|
+
| `from module import *` | Pollutes namespace, hides dependencies | Import specific names |
|
|
605
|
+
| `isinstance(x, str)` chains | Violates open/closed principle | Use `match` statement or polymorphism |
|
|
606
|
+
| `os.path.join(a, b)` | Verbose, stringly typed | Use `Path(a) / b` |
|
|
607
|
+
| `global` keyword | Hidden state, untestable | Pass state explicitly or use classes |
|
|
608
|
+
| Bare `assert` in production | Stripped with `-O` flag | Use `if not x: raise ValueError(...)` |
|
|
609
|
+
| `eval()` / `exec()` | Code injection vector | Never use with user input |
|
|
610
|
+
| String formatting for SQL | SQL injection | Use parameterized queries |
|
|
611
|
+
|
|
612
|
+
## Project Structure
|
|
613
|
+
|
|
614
|
+
```
|
|
615
|
+
my-project/
|
|
616
|
+
src/
|
|
617
|
+
my_package/
|
|
618
|
+
__init__.py
|
|
619
|
+
core.py
|
|
620
|
+
models.py
|
|
621
|
+
utils.py
|
|
622
|
+
tests/
|
|
623
|
+
conftest.py
|
|
624
|
+
test_core.py
|
|
625
|
+
test_models.py
|
|
626
|
+
pyproject.toml
|
|
627
|
+
README.md
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
### pyproject.toml (Modern Standard)
|
|
631
|
+
|
|
632
|
+
```toml
|
|
633
|
+
[build-system]
|
|
634
|
+
requires = ["hatchling"]
|
|
635
|
+
build-backend = "hatchling.build"
|
|
636
|
+
|
|
637
|
+
[project]
|
|
638
|
+
name = "my-package"
|
|
639
|
+
version = "0.1.0"
|
|
640
|
+
requires-python = ">=3.11"
|
|
641
|
+
dependencies = [
|
|
642
|
+
"pydantic>=2.0",
|
|
643
|
+
"aiohttp>=3.9",
|
|
644
|
+
]
|
|
645
|
+
|
|
646
|
+
[project.optional-dependencies]
|
|
647
|
+
dev = [
|
|
648
|
+
"pytest>=8.0",
|
|
649
|
+
"pytest-asyncio>=0.23",
|
|
650
|
+
"mypy>=1.8",
|
|
651
|
+
"ruff>=0.2",
|
|
652
|
+
]
|
|
653
|
+
|
|
654
|
+
[tool.pytest.ini_options]
|
|
655
|
+
asyncio_mode = "auto"
|
|
656
|
+
testpaths = ["tests"]
|
|
657
|
+
|
|
658
|
+
[tool.mypy]
|
|
659
|
+
strict = true
|
|
660
|
+
python_version = "3.11"
|
|
661
|
+
|
|
662
|
+
[tool.ruff]
|
|
663
|
+
target-version = "py311"
|
|
664
|
+
line-length = 100
|
|
665
|
+
|
|
666
|
+
[tool.ruff.lint]
|
|
667
|
+
select = ["E", "F", "I", "N", "W", "UP", "B", "SIM", "TCH"]
|
|
668
|
+
```
|
|
669
|
+
|
|
670
|
+
## Resources
|
|
671
|
+
|
|
672
|
+
- **Python Typing Docs**: https://docs.python.org/3/library/typing.html
|
|
673
|
+
- **PEP 604 (Union X | Y)**: https://peps.python.org/pep-0604/
|
|
674
|
+
- **Pydantic v2 Docs**: https://docs.pydantic.dev/latest/
|
|
675
|
+
- **pytest Docs**: https://docs.pytest.org/
|
|
676
|
+
- **Real Python**: https://realpython.com/
|
|
677
|
+
- **mypy Docs**: https://mypy.readthedocs.io/
|
|
678
|
+
- **Ruff Linter**: https://docs.astral.sh/ruff/
|