├── .github ├── ISSUE_TEMPLATE │ ├── feature-request.md │ ├── bug-report.md │ └── add-resource.md └── workflows │ └── validate-links.yml ├── LICENSE ├── .gitignore ├── scripts └── validate_links.py ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md └── README.md /.github/ISSUE_TEMPLATE/feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature Request 3 | about: Suggest an improvement for the awesome list 4 | title: '[FEATURE] ' 5 | labels: 'enhancement' 6 | assignees: '' 7 | --- 8 | 9 | ## Feature Description 10 | 11 | 12 | 13 | ## Motivation 14 | 15 | 16 | 17 | ## Proposed Solution 18 | 19 | 20 | 21 | ## Alternatives Considered 22 | 23 | 24 | 25 | ## Additional context 26 | 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug Report 3 | about: Report an issue with the awesome list 4 | title: '[BUG] ' 5 | labels: 'bug' 6 | assignees: '' 7 | --- 8 | 9 | ## Description 10 | 11 | 12 | 13 | ## Type of Issue 14 | 15 | - [ ] Broken link 16 | - [ ] Outdated information 17 | - [ ] Incorrect categorization 18 | - [ ] Formatting issue 19 | - [ ] Other (please specify) 20 | 21 | ## Details 22 | 23 | **Affected Resource:** 24 | **Section:** 25 | 26 | ## Expected vs Actual 27 | 28 | **Expected:** 29 | **Actual:** 30 | 31 | ## Suggested Fix 32 | 33 | 34 | 35 | ## Additional context 36 | 37 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/add-resource.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Add Resource 3 | about: Suggest a new resource for the awesome list 4 | title: '[ADD] ' 5 | labels: 'new-resource' 6 | assignees: '' 7 | --- 8 | 9 | ## Resource Information 10 | 11 | **Resource Name:** 12 | **Resource URL:** 13 | **Category:** (e.g., Libraries, Tools, Tutorials, etc.) 14 | 15 | ## Description 16 | 17 | 18 | 19 | ## Why should this be included? 20 | 21 | 22 | 23 | ## Checklist 24 | 25 | - [ ] I've read the [contribution guidelines](../../CONTRIBUTING.md) 26 | - [ ] This resource is specifically about Python t-strings (PEP 750) 27 | - [ ] The resource is actively maintained (if applicable) 28 | - [ ] The link is working and accessible 29 | - [ ] This is not a duplicate of an existing entry 30 | - [ ] The resource provides value to the community 31 | 32 | ## Additional context 33 | 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 t-strings 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.github/workflows/validate-links.yml: -------------------------------------------------------------------------------- 1 | name: Validate Links 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | schedule: 9 | # Run every Sunday at 00:00 UTC 10 | - cron: '0 0 * * 0' 11 | workflow_dispatch: 12 | 13 | permissions: 14 | contents: read 15 | issues: write 16 | 17 | jobs: 18 | validate: 19 | runs-on: ubuntu-latest 20 | 21 | steps: 22 | - uses: actions/checkout@v4 23 | 24 | - name: Link Checker 25 | uses: lycheeverse/lychee-action@v2.0.2 26 | with: 27 | # Check all markdown files 28 | args: | 29 | --verbose 30 | --no-progress 31 | --accept=200,201,202,203,204,205,206,429 32 | --timeout 20 33 | --max-retries 3 34 | --user-agent="Mozilla/5.0 (compatible; awesome-t-strings/1.0)" 35 | '**/*.md' 36 | fail: true 37 | jobSummary: true 38 | 39 | - name: Create Issue on Failure 40 | if: failure() && github.event_name == 'schedule' 41 | uses: actions/github-script@v7 42 | with: 43 | script: | 44 | const title = 'Broken links detected'; 45 | const body = `The scheduled link validation check found broken links. 46 | 47 | Please check the [workflow run](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) for details. 48 | 49 | This issue was automatically created by the link validation workflow.`; 50 | 51 | await github.rest.issues.create({ 52 | owner: context.repo.owner, 53 | repo: context.repo.repo, 54 | title: title, 55 | body: body, 56 | labels: ['bug', 'automated'] 57 | }); -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # UV 98 | # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | #uv.lock 102 | 103 | # poetry 104 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 105 | # This is especially recommended for binary packages to ensure reproducibility, and is more 106 | # commonly ignored for libraries. 107 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 108 | #poetry.lock 109 | 110 | # pdm 111 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 112 | #pdm.lock 113 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 114 | # in version control. 115 | # https://pdm.fming.dev/latest/usage/project/#working-with-version-control 116 | .pdm.toml 117 | .pdm-python 118 | .pdm-build/ 119 | 120 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 121 | __pypackages__/ 122 | 123 | # Celery stuff 124 | celerybeat-schedule 125 | celerybeat.pid 126 | 127 | # SageMath parsed files 128 | *.sage.py 129 | 130 | # Environments 131 | .env 132 | .venv 133 | env/ 134 | venv/ 135 | ENV/ 136 | env.bak/ 137 | venv.bak/ 138 | 139 | # Spyder project settings 140 | .spyderproject 141 | .spyproject 142 | 143 | # Rope project settings 144 | .ropeproject 145 | 146 | # mkdocs documentation 147 | /site 148 | 149 | # mypy 150 | .mypy_cache/ 151 | .dmypy.json 152 | dmypy.json 153 | 154 | # Pyre type checker 155 | .pyre/ 156 | 157 | # pytype static type analyzer 158 | .pytype/ 159 | 160 | # Cython debug symbols 161 | cython_debug/ 162 | 163 | # PyCharm 164 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 165 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 166 | # and can be added to the global gitignore or merged into this file. For a more nuclear 167 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 168 | #.idea/ 169 | 170 | # Abstra 171 | # Abstra is an AI-powered process automation framework. 172 | # Ignore directories containing user credentials, local state, and settings. 173 | # Learn more at https://abstra.io/docs 174 | .abstra/ 175 | 176 | # Visual Studio Code 177 | # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore 178 | # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore 179 | # and can be added to the global gitignore or merged into this file. However, if you prefer, 180 | # you could uncomment the following to ignore the enitre vscode folder 181 | # .vscode/ 182 | 183 | # Ruff stuff: 184 | .ruff_cache/ 185 | 186 | # PyPI configuration file 187 | .pypirc 188 | 189 | # Cursor 190 | # Cursor is an AI-powered code editor. `.cursorignore` specifies files/directories to 191 | # exclude from AI features like autocomplete and code analysis. Recommended for sensitive data 192 | # refer to https://docs.cursor.com/context/ignore-files 193 | .cursorignore 194 | .cursorindexingignore -------------------------------------------------------------------------------- /scripts/validate_links.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | Link validation script for Awesome T-Strings. 4 | Checks all links in markdown files for accessibility. 5 | """ 6 | 7 | import re 8 | import sys 9 | import time 10 | import urllib.request 11 | import urllib.error 12 | from pathlib import Path 13 | from typing import List, Tuple 14 | from concurrent.futures import ThreadPoolExecutor, as_completed 15 | 16 | # Regular expression to find markdown links 17 | LINK_PATTERN = re.compile(r'\[([^\]]+)\]\(([^)]+)\)') 18 | 19 | # User agent to avoid being blocked 20 | USER_AGENT = 'Mozilla/5.0 (compatible; awesome-t-strings-link-checker/1.0)' 21 | 22 | # Timeout for requests (seconds) 23 | TIMEOUT = 20 24 | 25 | # Number of concurrent requests 26 | MAX_WORKERS = 3 27 | 28 | # Rate limiting delay (seconds) 29 | RATE_LIMIT_DELAY = 0.5 30 | 31 | 32 | def find_links(file_path: Path) -> List[Tuple[str, str, int]]: 33 | """Extract all links from a markdown file.""" 34 | links = [] 35 | 36 | with open(file_path, 'r', encoding='utf-8') as f: 37 | for line_num, line in enumerate(f, 1): 38 | for match in LINK_PATTERN.finditer(line): 39 | text, url = match.groups() 40 | # Skip anchor links and relative paths 41 | if not url.startswith(('#', '/', '..')): 42 | links.append((text, url, line_num)) 43 | 44 | return links 45 | 46 | 47 | def check_link(url: str) -> Tuple[str, bool, str]: 48 | """Check if a URL is accessible.""" 49 | # Skip non-HTTP(S) URLs 50 | if not url.startswith(('http://', 'https://')): 51 | return url, True, "Skipped (not HTTP/HTTPS)" 52 | 53 | try: 54 | request = urllib.request.Request(url, headers={'User-Agent': USER_AGENT}) 55 | with urllib.request.urlopen(request, timeout=TIMEOUT) as response: 56 | if response.status == 200: 57 | return url, True, f"OK ({response.status})" 58 | else: 59 | return url, False, f"HTTP {response.status}" 60 | except urllib.error.HTTPError as e: 61 | return url, False, f"HTTP {e.code}" 62 | except urllib.error.URLError as e: 63 | return url, False, f"URL Error: {e.reason}" 64 | except Exception as e: 65 | return url, False, f"Error: {str(e)}" 66 | 67 | 68 | def validate_markdown_file(file_path: Path) -> List[dict]: 69 | """Validate all links in a markdown file.""" 70 | print(f"\nChecking {file_path}...") 71 | links = find_links(file_path) 72 | 73 | if not links: 74 | print(f" No links found.") 75 | return [] 76 | 77 | print(f" Found {len(links)} links to check.") 78 | 79 | results = [] 80 | with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor: 81 | # Submit all link checks 82 | future_to_link = { 83 | executor.submit(check_link, url): (text, url, line_num) 84 | for text, url, line_num in links 85 | } 86 | 87 | # Process results as they complete 88 | for future in as_completed(future_to_link): 89 | text, url, line_num = future_to_link[future] 90 | checked_url, is_valid, message = future.result() 91 | 92 | result = { 93 | 'file': str(file_path), 94 | 'line': line_num, 95 | 'text': text, 96 | 'url': url, 97 | 'valid': is_valid, 98 | 'message': message 99 | } 100 | results.append(result) 101 | 102 | # Print progress 103 | status = "✓" if is_valid else "✗" 104 | print(f" {status} Line {line_num}: {text} - {message}") 105 | 106 | # Rate limiting to be respectful 107 | time.sleep(RATE_LIMIT_DELAY) 108 | 109 | return results 110 | 111 | 112 | def main(): 113 | """Main function to validate all markdown files.""" 114 | # Find all markdown files 115 | repo_root = Path(__file__).parent.parent 116 | markdown_files = list(repo_root.glob('**/*.md')) 117 | 118 | # Exclude some directories 119 | exclude_dirs = {'.git', 'node_modules', 'venv', '.venv'} 120 | markdown_files = [ 121 | f for f in markdown_files 122 | if not any(excluded in f.parts for excluded in exclude_dirs) 123 | ] 124 | 125 | print(f"Found {len(markdown_files)} markdown files to check.") 126 | 127 | # Check all files 128 | all_results = [] 129 | for file_path in markdown_files: 130 | results = validate_markdown_file(file_path) 131 | all_results.extend(results) 132 | 133 | # Summary 134 | print("\n" + "="*50) 135 | print("SUMMARY") 136 | print("="*50) 137 | 138 | total_links = len(all_results) 139 | broken_links = [r for r in all_results if not r['valid']] 140 | 141 | print(f"Total links checked: {total_links}") 142 | print(f"Valid links: {total_links - len(broken_links)}") 143 | print(f"Broken links: {len(broken_links)}") 144 | 145 | if broken_links: 146 | print("\nBROKEN LINKS:") 147 | for result in broken_links: 148 | print(f" {result['file']}:{result['line']} - {result['text']} ({result['url']})") 149 | print(f" Error: {result['message']}") 150 | 151 | return 1 # Exit with error 152 | else: 153 | print("\nAll links are valid! ✨") 154 | return 0 155 | 156 | 157 | if __name__ == '__main__': 158 | sys.exit(main()) -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | . 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Awesome T-Strings 2 | 3 | First off, thank you for considering contributing to Awesome T-Strings! This curated list thrives on community contributions, and we appreciate your help in making it a comprehensive resource for Python's template strings. 4 | 5 | ## Table of Contents 6 | 7 | - [Code of Conduct](#code-of-conduct) 8 | - [How Can I Contribute?](#how-can-i-contribute) 9 | - [Suggesting New Resources](#suggesting-new-resources) 10 | - [Improving Existing Content](#improving-existing-content) 11 | - [Reporting Issues](#reporting-issues) 12 | - [Contribution Guidelines](#contribution-guidelines) 13 | - [Quality Standards](#quality-standards) 14 | - [Formatting Requirements](#formatting-requirements) 15 | - [Categories](#categories) 16 | - [Submission Process](#submission-process) 17 | - [Review Process](#review-process) 18 | 19 | ## Code of Conduct 20 | 21 | By participating in this project, you agree to abide by our [Code of Conduct](CODE_OF_CONDUCT.md). Please read it before contributing. 22 | 23 | ## How Can I Contribute? 24 | 25 | ### Suggesting New Resources 26 | 27 | We welcome suggestions for: 28 | - Libraries and tools that use t-strings 29 | - Tutorials and learning materials 30 | - Blog posts and articles 31 | - Conference talks and videos 32 | - Real-world examples and use cases 33 | - IDE plugins and extensions 34 | 35 | ### Improving Existing Content 36 | 37 | You can help by: 38 | - Fixing broken links 39 | - Updating outdated information 40 | - Improving descriptions 41 | - Adding missing context 42 | - Correcting technical inaccuracies 43 | 44 | ### Reporting Issues 45 | 46 | If you find problems, please [open an issue](https://github.com/t-strings/awesome-t-strings/issues) with: 47 | - A clear title and description 48 | - Links to the problematic content 49 | - Suggestions for improvement 50 | 51 | ## Contribution Guidelines 52 | 53 | ### Quality Standards 54 | 55 | Before submitting a resource, ensure it meets these criteria: 56 | 57 | #### For Libraries/Tools 58 | - ✅ **Python 3.14+ compatible** - Must work with template strings 59 | - ✅ **Actively maintained** - Recent commits (within 6 months) 60 | - ✅ **Well documented** - Clear README and usage examples 61 | - ✅ **Properly tested** - Has test suite or examples 62 | - ✅ **Adds value** - Solves a real problem or demonstrates best practices 63 | 64 | #### For Articles/Tutorials 65 | - ✅ **Technically accurate** - Information is correct and up-to-date 66 | - ✅ **Well written** - Clear, concise, and easy to understand 67 | - ✅ **Includes examples** - Working code demonstrating concepts 68 | - ✅ **Recent** - Published within the last 2 years (unless historically significant) 69 | 70 | #### For Videos/Talks 71 | - ✅ **Good quality** - Clear audio and video 72 | - ✅ **Educational value** - Teaches concepts effectively 73 | - ✅ **Accessible** - Available without paywall 74 | 75 | ### Formatting Requirements 76 | 77 | Follow this format exactly: 78 | 79 | ```markdown 80 | - [Resource Name](https://example.com) - Brief description ending with a period. 81 | ``` 82 | 83 | #### Examples 84 | 85 | ✅ **Good:** 86 | ```markdown 87 | - [sql-tstring](https://github.com/pgjones/sql-tstring) - Safe SQL query building with t-strings, preventing SQL injection. 88 | - [t-linter](https://github.com/koxudaxi/t-linter) - Comprehensive linting tool for template strings with IDE integrations. 89 | ``` 90 | 91 | ❌ **Bad:** 92 | ```markdown 93 | - [sql-tstring](https://github.com/pgjones/sql-tstring) - sql library (missing detail, no period) 94 | - sql-tstring - https://github.com/pgjones/sql-tstring (wrong format) 95 | - [SQL TString](github.com/pgjones/sql-tstring) - Library for SQL. (inconsistent naming, incomplete URL) 96 | - [Tool Name](https://example.com) - A tool for t-strings (vague description) 97 | ``` 98 | 99 | ### Categories 100 | 101 | Place your contribution in the appropriate section: 102 | 103 | 1. **Official Resources** - PEPs, Python docs, official tools 104 | 2. **Development Tools** - Linters, formatters, IDE extensions 105 | 3. **Libraries & Frameworks** - Packages that use or support t-strings 106 | 4. **Learning Resources** - Tutorials, courses, documentation 107 | 5. **Community** - Discussions, forums, social media 108 | 109 | If unsure about categorization, mention it in your PR description. 110 | 111 | ## Submission Process 112 | 113 | 1. **Fork the repository** 114 | - Click the "Fork" button on the [repository page](https://github.com/t-strings/awesome-t-strings) 115 | - Clone your fork: 116 | ```bash 117 | git clone https://github.com//awesome-t-strings.git 118 | cd awesome-t-strings 119 | ``` 120 | 121 | 2. **Create a feature branch** 122 | ```bash 123 | git checkout -b add-amazing-resource 124 | ``` 125 | 126 | 3. **Make your changes** 127 | - Add your resource in the appropriate section 128 | - Maintain alphabetical order within sections 129 | - Ensure proper formatting 130 | 131 | 4. **Test your changes** 132 | - Check all links work (use `python scripts/validate_links.py`) 133 | - Verify markdown renders correctly 134 | - Preview your changes locally 135 | - Ensure no broken formatting 136 | 137 | 5. **Commit your changes** 138 | ```bash 139 | git add README.md 140 | git commit -m "feat: add amazing-t-string-library for HTML templating" 141 | ``` 142 | 143 | Use these commit prefixes: 144 | - `feat:` - Adding new resources 145 | - `fix:` - Fixing links or errors 146 | - `docs:` - Updating documentation 147 | - `style:` - Formatting changes 148 | 149 | 6. **Push to your fork** 150 | ```bash 151 | git push origin add-amazing-resource 152 | ``` 153 | 154 | 7. **Submit a Pull Request** 155 | - Go to your fork on GitHub 156 | - Click "New pull request" 157 | - Use a clear, descriptive title 158 | - Describe what you're adding and why it's valuable 159 | - Link to relevant issues if any 160 | - Review the diff to ensure accuracy 161 | 162 | ## Review Process 163 | 164 | ### What to Expect 165 | 166 | 1. **Automated checks** - Links validation, format checking 167 | 2. **Maintainer review** - Usually within 3-5 days 168 | 3. **Community feedback** - Others may comment 169 | 4. **Revisions** - You may be asked to make changes 170 | 171 | ### Review Criteria 172 | 173 | Maintainers will check: 174 | - ✅ Meets quality standards 175 | - ✅ Properly formatted 176 | - ✅ Adds value to the list 177 | - ✅ No duplicates 178 | - ✅ Appropriate category 179 | 180 | ### After Acceptance 181 | 182 | Once merged: 183 | - Your contribution will be live 184 | - You'll be added to contributors 185 | - The community benefits from your addition! 186 | 187 | ## Additional Notes 188 | 189 | ### For Maintainers 190 | 191 | If you're interested in becoming a maintainer: 192 | - Contribute regularly 193 | - Help review PRs 194 | - Engage with the community 195 | - Contact current maintainers 196 | 197 | ### Questions? 198 | 199 | If you have questions: 200 | - Check existing issues first 201 | - Join community discussions 202 | - Open a new issue with the "question" label 203 | 204 | Thank you for helping make Awesome T-Strings better! -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Awesome T-Strings [![Awesome](https://awesome.re/badge.svg)](https://awesome.re) [![License: CC0-1.0](https://img.shields.io/badge/License-CC0_1.0-lightgrey.svg)](http://creativecommons.org/publicdomain/zero/1.0/) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](CONTRIBUTING.md) 2 | 3 | > A curated list of resources, tools, libraries, and examples for Python's Template Strings (t-strings) introduced in Python 3.14 4 | 5 | > [!WARNING] 6 | > Template strings are **accepted** for Python 3.14 and available in release candidates. As of **3.14.0rc3 (2025-09-18)** the syntax is stable; some ecosystem tools are still catching up. The Python 3.14.0 GA is scheduled for **2025-10-07**, so verify against the 3.14 RCs before adopting broadly. 7 | 8 | Template strings (t-strings) are a powerful new Python feature defined in [PEP 750](https://peps.python.org/pep-0750/) that extends f-strings with programmable string processing capabilities. They enable safer string interpolation, prevent injection attacks, and allow for custom domain-specific languages. 9 | 10 | ## Contents 11 | 12 | - [What are T-Strings?](#what-are-t-strings) 13 | - [Official Resources](#official-resources) 14 | - [Development Tools](#development-tools) 15 | - [Linting & Static Analysis](#linting--static-analysis) 16 | - [Type Checking](#type-checking) 17 | - [IDE Extensions](#ide-extensions) 18 | - [Environment & Installation](#environment--installation) 19 | - [Libraries & Frameworks](#libraries--frameworks) 20 | - [Database & SQL](#database--sql) 21 | - [Utilities](#utilities) 22 | - [Learning Resources](#learning-resources) 23 | - [Tutorials & Videos](#tutorials--videos) 24 | - [Community Discussions](#community-discussions) 25 | - [Getting Started](#getting-started) 26 | - [Related](#related) 27 | - [Contributing](#contributing) 28 | 29 | ## What are T-Strings? 30 | 31 | Template strings (t-strings) are a new Python feature that provide programmable string interpolation. Unlike f-strings which immediately produce a string, t-strings return a structured template object that can be processed by custom functions. This enables: 32 | 33 | - **Security**: Prevent injection attacks through controlled processing 34 | - **Flexibility**: Create custom DSLs for any domain (SQL, HTML, logging, etc.) 35 | - **Rendering control**: Interpolations evaluate eagerly, and `Template` objects keep literal segments plus evaluated values separate via `.strings`, `.interpolations`, and `.values` so downstream renderers can combine them explicitly and safely 36 | - **Type checking**: Growing support in type checkers 37 | 38 | ### Basic Examples (from PEP 750) 39 | 40 | ```python 41 | # Template strings use 't' prefix instead of 'f' 42 | template: Template = t"Hello {name}" 43 | 44 | # HTML auto-escaping example 45 | evil = "" 46 | template = t"

{evil}

" 47 | assert html(template) == "

<script>alert('evil')</script>

" 48 | 49 | # HTML attributes from dictionary 50 | attributes = {"src": "shrubbery.jpg", "alt": "looks nice"} 51 | template = t"" 52 | assert html(template) == 'looks nice' 53 | 54 | # Accessing template components 55 | name = "World" 56 | template = t"Hello {name}" 57 | assert template.strings == ("Hello ", "") 58 | assert template.interpolations[0].value == "World" 59 | assert template.interpolations[0].expression == "name" 60 | ``` 61 | 62 | Learn more in [PEP 750](https://peps.python.org/pep-0750/). 63 | 64 | ## Official Resources 65 | 66 | - [PEP 750: Template Strings](https://peps.python.org/pep-0750/) - The official specification defining t-strings syntax and semantics 67 | - [Template strings docs (`string.templatelib`)](https://docs.python.org/3.14/library/string.templatelib.html) - Canonical documentation for the `Template` API in 3.14 68 | - [Python 3.14.0rc3](https://www.python.org/downloads/release/python-3140rc3/) - Final release candidate with template string support (syntax is stable) 69 | - [PEP 745: Python 3.14 Release Schedule](https://peps.python.org/pep-0745/) - Official timeline for 3.14.0, targeting October 7, 2025 70 | - [Python 3.14 documentation](https://docs.python.org/3.14/) - Latest docs covering template strings and `string.templatelib` 71 | - [t-strings.help](https://t-strings.help/) - Documentation and help site maintained by the PEP 750 author 72 | 73 | ## Development Tools 74 | 75 | ### Linting & Static Analysis 76 | 77 | - [t-linter](https://github.com/koxudaxi/t-linter) - Comprehensive linting tool for t-strings with IDE integrations 78 | - [PyPI Package](https://pypi.org/project/t-linter/) - `pip install t-linter` 79 | 80 | ### Type Checking 81 | 82 | - [Pyright 1.1.402](https://github.com/microsoft/pyright/releases/tag/1.1.402) - Upstream release with first-class PEP 750 template string analysis (no fork required) 83 | - [mypy 1.18.2 release notes](https://mypy.readthedocs.io/en/stable/changelog.html) - Fails gracefully on unsupported template strings while full checking support is developed 84 | 85 | ### IDE Extensions 86 | 87 | - [VS Code T-Linter](https://marketplace.visualstudio.com/items?itemName=koxudaxi.t-linter) - Syntax highlighting, linting, and IntelliSense for t-strings 88 | - [PyCharm T-Linter Plugin](https://plugins.jetbrains.com/plugin/27541-tlinter) - Full IDE support for JetBrains products ([Source](https://github.com/koxudaxi/t-linter-pycharm-plugin)) 89 | 90 | ### Environment & Installation 91 | 92 | - [uv](https://github.com/astral-sh/uv) - Fast Python package manager with built-in Python version management 93 | - [Python Docker Images](https://hub.docker.com/_/python) - Official Python images (3.14-rc tags available) 94 | - [CPython Source](https://github.com/python/cpython/tree/v3.14.0rc3) - Build Python 3.14 release candidate from source 95 | 96 | ## Libraries & Frameworks 97 | 98 | ### Database & SQL 99 | 100 | - [sql-tstring](https://github.com/pgjones/sql-tstring) - Safe SQL query building with t-strings, including optional clause rewriting and dialect support (`pip install sql-tstring`) 101 | - [t-sql](https://pypi.org/project/t-sql/) - Lightweight SQL templating that turns t-strings into parameterized queries, supporting qmark, numeric, named, format, and pyformat styles on Python 3.14+ 102 | - [psycopg 3 template string queries](https://www.psycopg.org/psycopg3/docs/basic/tstrings.html) - Experimental template string execution in psycopg 3.3 preview builds (installable from Test PyPI as `psycopg[binary]==3.3.0.dev1`) tested with Python 3.14 RC builds 103 | 104 | ### Utilities 105 | 106 | - [better-dedent](https://github.com/treyhunner/better-dedent) - Enhanced string dedenting for cleaner template formatting 107 | - [tdom](https://github.com/t-strings/tdom) - A 🤘 rockin' t-string HTML templating system for Python 3.14 by co-author team. 108 | - [tstr](https://github.com/ilotoki0804/tstr) - Cross-version compatible t-strings with backport support for older Python versions, plus utilities for rendering, interpolation handling, and extensions for HTML escaping, SQL, and logging. 109 | - [tstring-util](https://pypi.org/project/tstring-util/) - Rendering helpers for `Template` objects, including lazy `!fn` handlers plus safe splitting and path utilities 110 | - [regex-template](https://github.com/treyhunner/regex-template) - Auto-escapes regular expression interpolations 111 | 112 | ## Learning Resources 113 | 114 | ### Tutorials & Videos 115 | 116 | - [Python Template Strings Introduction](https://www.youtube.com/watch?v=yx1QPm4aXeA) - Video tutorial on t-strings basics 117 | - [Template Strings Advanced Usage](https://www.youtube.com/watch?v=WCWNeZ_rE68) - Advanced patterns and use cases 118 | 119 | ### Community Discussions 120 | 121 | - [Language hints for PEP 750](https://discuss.python.org/t/language-hints-for-pep-750-template-strings/94311/) - Discussion on syntax highlighting and language detection 122 | - [PEP 750 template strings new updates](https://discuss.python.org/t/pep750-template-strings-new-updates/71594) - Latest updates and changes to the specification 123 | - [Template strings in stdlib logging](https://discuss.python.org/t/add-support-for-t-strings-in-the-stdlib-logging-library/92776/23) - Integration with Python's logging module 124 | - [Original PEP 750 discussion](https://discuss.python.org/t/pep-750-tag-strings-for-writing-domain-specific-languages/60408) - Initial proposal and community feedback 125 | - [Convert function for string.Template](https://discuss.python.org/t/add-convert-function-to-string-templatelib/94569) - Bridging classic templates with t-strings 126 | 127 | 128 | ## Getting Started 129 | 130 | ### Installation 131 | 132 | To start using t-strings, you'll need Python 3.14 or later: 133 | 134 | ```bash 135 | # Using uv package manager 136 | uv python install 3.14.0rc3 137 | 138 | # Using Docker 139 | docker run -it python:3.14-rc 140 | 141 | # Build from source 142 | git clone https://github.com/python/cpython.git 143 | cd cpython 144 | git checkout v3.14.0rc3 145 | ./configure --enable-optimizations 146 | make -j4 # Or use $(nproc) on Linux, $(sysctl -n hw.ncpu) on macOS 147 | sudo make altinstall 148 | ``` 149 | 150 | 151 | ## Related 152 | 153 | - [PEP 787: Safer Subprocess Usage](https://peps.python.org/pep-0787/) - **Deferred to Python 3.15**; proposes t-strings support for `subprocess`/`shlex` 154 | - [Python f-strings](https://peps.python.org/pep-0498/) - The predecessor to t-strings 155 | - [Template Literal (JavaScript)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) - Similar concept in JavaScript 156 | - [Tagged Template Literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates) - JavaScript's equivalent feature 157 | 158 | ## Contributing 159 | 160 | Contributions are welcome! Please read our [Contributing Guidelines](CONTRIBUTING.md) before submitting PRs. 161 | 162 | ### How to Contribute 163 | 164 | 1. Check for existing entries before adding new ones 165 | 2. Test all code examples with Python 3.14+ 166 | 3. Verify all links are working 167 | 4. Follow the established format 168 | 5. Add meaningful descriptions 169 | 170 | See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed guidelines. 171 | 172 | ## License 173 | 174 | [![CC0](https://licensebuttons.net/p/zero/1.0/88x31.png)](https://creativecommons.org/publicdomain/zero/1.0/) 175 | 176 | This work is licensed under a [Creative Commons Zero v1.0 Universal License](LICENSE). 177 | --------------------------------------------------------------------------------