Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions python-314/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Python 3.14: Cool New Features for You to Try

The materials contained in this folder are designed to complement the Real Python tutorial [Python 3.14: Cool New Features for You to Try](https://realpython.com/python314-new-features/).
3 changes: 3 additions & 0 deletions python-314/fib.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
def fib(n):
print(f"Calculating fib({n})...")
return n if n < 2 else fib(n - 2) + fib(n - 1)
8 changes: 8 additions & 0 deletions python-314/jit_status.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
try:
from sys import _jit
except ImportError:
print("Module sys._jit unavailable")
else:
print("Python compiled with JIT support:", _jit.is_available())
print("JIT enabled for this process:", _jit.is_enabled())
print("JIT currently running:", _jit.is_active())
15 changes: 15 additions & 0 deletions python-314/linked_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Uncomment for Python 3.14
#
# from dataclasses import dataclass
# from typing import Any, Optional
#
#
# @dataclass
# class LinkedList:
# head: Node
#
#
# @dataclass
# class Node:
# value: Any
# next: Optional[Node] = None
5 changes: 5 additions & 0 deletions python-314/repl/cli_script.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import argparse

parser = argparse.ArgumentParser("Command-Line Interface")
parser.add_argument("path", help="Path to a file")
parser.parse_args()
38 changes: 38 additions & 0 deletions python-314/repl/pythonrc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Set a custom color theme in Python 3.14
try:
from _colorize import ANSIColors, default_theme, set_theme
except ImportError:
pass
else:
custom_theme = default_theme.copy_with(
syntax=default_theme.syntax.copy_with(
prompt=ANSIColors.GREY,
builtin="\x1b[38;2;189;147;249m",
comment="\x1b[38;2;98;114;164m",
definition="\x1b[38;2;139;233;253m",
keyword="\x1b[38;2;255;121;198m",
keyword_constant="\x1b[38;2;255;121;198m",
soft_keyword="\x1b[38;2;255;121;198m",
number="\x1b[38;2;189;147;249m",
op="\x1b[38;2;249;152;204m",
string="\x1b[38;2;241;250;140m",
),
traceback=default_theme.traceback.copy_with(
error_highlight=ANSIColors.BOLD_YELLOW,
error_range=ANSIColors.YELLOW,
filename=ANSIColors.BACKGROUND_RED,
frame=ANSIColors.BACKGROUND_RED,
line_no=ANSIColors.BACKGROUND_RED,
message=ANSIColors.RED,
type=ANSIColors.BOLD_RED,
),
)
set_theme(custom_theme)

# Set a custom shell prompt
import platform
import sys

version = platform.python_version()
sys.ps1 = f"{version} \N{SNAKE} "
sys.ps2 = "." * len(sys.ps1)
6 changes: 6 additions & 0 deletions python-314/repl/test_dummy.py
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the tutorial, we could mention that the sample files used to showcase the REPL's syntax highlighting features are available in the materials repo?

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import unittest


class TestDummy(unittest.TestCase):
def test_dummy(self):
self.assertEqual(2 + 2, 22)
1 change: 1 addition & 0 deletions python-314/repl/todo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"Shopping List": [{"title": "eggs", "details": null, "quantity": 12, "completed": true}, {"title": "bacon", "details": "smoke, 500g pack", "quantity": 1, "completed": false}, {"title": "ghee", "details": null, "quantity": 1, "completed": false}]}
28 changes: 28 additions & 0 deletions python-314/subinterpreters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from concurrent.futures import (
InterpreterPoolExecutor,
ProcessPoolExecutor,
ThreadPoolExecutor,
)
from time import perf_counter

MAX_VALUE = 35
NUM_VALUES = 4
NUM_WORKERS = 4


def fib(n):
return n if n < 2 else fib(n - 2) + fib(n - 1)


def compute(Pool):
t1 = perf_counter()
with Pool(max_workers=NUM_WORKERS) as pool:
list(pool.map(fib, [MAX_VALUE] * NUM_VALUES))
t2 = perf_counter()
print(f"{Pool.__name__}: {(t2 - t1):.2f}s")


if __name__ == "__main__":
compute(InterpreterPoolExecutor)
compute(ProcessPoolExecutor)
compute(ThreadPoolExecutor)
64 changes: 64 additions & 0 deletions python-314/tstrings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
from dataclasses import dataclass
from string.templatelib import Interpolation, Template, convert
from typing import Any


@dataclass(frozen=True)
class SQLQuery:
statement: str
params: list[Any]

def __init__(self, template: Template) -> None:
items, params = [], []
for item in template:
match item:
case str():
items.append(item)
case Interpolation(value, _, conversion, format_spec):
converted = convert(value, conversion)
if format_spec:
converted = format(converted, format_spec)
params.append(converted)
items.append("?")
object.__setattr__(self, "statement", "".join(items))
object.__setattr__(self, "params", params)


def find_users_query_v1(name: str) -> str:
"""Return a SQL query to find users by name."""
return f"SELECT * FROM users WHERE name = '{name}'"


# Uncomment for Python 3.14:
#
# def find_users_query_v2(name: str) -> Template:
# """Return a SQL query to find users by name."""
# return t"SELECT * FROM users WHERE name = '{name}'"
#
#
# def find_users(name: str) -> SQLQuery:
# """Return a SQL query to find users by name."""
# return SQLQuery(t"SELECT * FROM users WHERE name = {name}")


def render(template: Template) -> str:
return "".join(
f"{text}{value}"
for text, value in zip(template.strings, template.values)
)


if __name__ == "__main__":
# Insecure f-strings
print(find_users_query_v1("' OR '1'='1"))

# Uncomment for Python 3.14:
#
# # More secure t-strings
# print(find_users_query_v2("' OR '1'='1"))
#
# # Insecure way of rendering t-strings into plain strings
# print(render(find_users_query_v2("' OR '1'='1")))
#
# # Rendering t-strings into an alternative representation
# print(find_users("' OR '1'='1"))
25 changes: 25 additions & 0 deletions python-314/web_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import os
import sys
from http.server import BaseHTTPRequestHandler, HTTPServer

HOSTNAME = "localhost"
PORT = 8000


class Handler(BaseHTTPRequestHandler):
def do_GET(self):
user_agent = self.headers.get("User-Agent")
self.send_response(200)
self.end_headers()
self.wfile.write(f"Hello, {user_agent}".encode())


def main():
print(f"Starting the server on: http://{HOSTNAME}:{PORT}")
print("Run this command as a superuser to attach the debugger:")
print(f"{sys.executable} -m pdb -p {os.getpid()}")
HTTPServer((HOSTNAME, PORT), Handler).serve_forever()


if __name__ == "__main__":
main()