Principal Software Engineer
Course Description
Learn modern Python fundamentals by building a real application from scratch. Get hands-on with the professional workflows behind shipping backend services with data access, robust testing, and containerized deployments. Learn the language powering AI, automation, and infrastructure all over the world.
Prerequisite: Basic programming experience in any language and comfort with the command line. Familiarity with HTTP, REST APIs, and SQL is helpful but not required.
Preview
Course Details
Published: July 23, 2026
Learn Straight from the Experts Who Shape the Modern Web
Your Path to Senior Developer and Beyond
- 300+ In-depth courses
- 24 Learning Paths
- Industry Leading Experts
- Live Interactive Workshops
Table of Contents
Introduction
Section Duration: 10 minutes
Nina Zakharenko introduces the course by emphasizing the importance of writing idiomatic, tested, production-quality Python code, with a focus on modern features like type hints and data classes. She then walks students through setting up a development environment using Python 3.14, Docker, VS Code, and Git.
Nina explains why Python appears across web development, data science, AI, and infrastructure, and covers PyPI, readability, rapid development, and performance tradeoffs. She warns about unreliable LLM-generated Python and guides students through evaluating AI output critically, configuring coding agents, and understanding code before using it.
Project Setup
Section Duration: 17 minutes
Nina walks students through creating a new Python project with UV, setting a Python 3.14 requirement, and reviewing the generated files and project metadata. She also explains how UV creates and uses a virtual environment, shows uv sync and uv run, and answers a question about project-specific Python versions.
Nina walks through setting up the course tools, verifying Docker, Git, VS Code, UV, and Python 3.14. She also demonstrates installing the Python, MyPy Type Checker, and Ruff extensions, and explains VS Code settings for formatting and workspace setup.
Python Overview
Section Duration: 58 minutes
Nina covers Python fundamentals including functions, conditionals, classes, and running code from files and the REPL. She also demonstrates core features like strings, arithmetic, booleans, and the none keyword.
Nina explains dynamic typing in Python and how type hints can be used alongside it. She also covers type conversions, built-in comparisons, and standard library tools like DateTime, PathLib, and collections.
Nina explains the benefits of string enums in Python, showing how they prevent typos and improve readability through auto-completion. She also covers int enums for numerical statuses and demonstrates how specifying enum types enables type safety and data validation.
Nina walks through defining functions in Python using the def keyword, parameters, and indentation, demonstrating a slugify method built without regular expressions. She also covers best practices like keeping methods small, returning values for easier debugging, and avoiding mutable default parameters.
Nina explains how to use type hints in Python to specify expected argument and return types, noting they are not enforced at runtime. She also covers stars and double stars in function parameters for keyword-only arguments and collecting extra keyword arguments into a dictionary.
Nina explains conditional syntax using if, elif, and else statements, demonstrating how Python evaluates values as truthy or falsy. She also covers how booleans are handled under the hood and shows examples in a method like isOverdue.
Nina explains the benefits of data classes in Python, showing how they simplify data storage, validation, printing, and equality checking compared to regular classes. She contrasts them with regular classes to highlight the additional manual setup required for similar functionality.
Nina demonstrates how to work with enums in Python, defining a string enum and writing a method to check if a task is overdue based on due dates. She also covers time zone considerations when working with dates and introduces match case syntax as a shortcut for enum-based conditionals.
Data Structures
Section Duration: 1 hour, 15 minutes
Nina covers Python data structures including lists, tuples, sets, and dictionaries, explaining their syntax, use cases, and common methods. She also demonstrates exceptions, context managers, decorators, and string-list interactions like splitting and joining.
Nina explains how tuples can serve as dictionary keys due to their immutability and demonstrates looping over lists, tuples, sets, and dictionaries. She also covers list comprehensions for transforming and filtering data, and distinguishes them from generator comprehensions for large datasets.
Nina explains how exceptions work in Python and demonstrates using specific try and except blocks to handle different scenarios. She also shows how to create custom exceptions by subclassing the base exception class.
Nina demonstrates using context managers to handle resources like files and database connections, covering both built-in options and custom ones via contextlib. She also introduces decorators, showing how they wrap functions to add extra behavior, with examples like @app.get and @field_validator.
Nina gives students an exercise on comprehensions, exceptions, and data classes. She then walks through a solution covering rewriting loops as comprehensions, raising and catching exceptions, and defining a typed data class with default values.
Nina covers type hints, generics, and the union operator in Python, demonstrating mypy for static type checking and introducing Pydantic for runtime validation. She also covers pytest for unit testing and mentions emerging tools like UV's tie and pyrefly as faster alternatives to mypy.
Nina explores data validation with Pydantic, showing how it uses Python type hints for runtime enforcement. She demonstrates defining models with constraints using Pydantic fields and highlights how Pydantic surfaces detailed validation errors at the API boundary.
Nina explains string constraints in Pydantic, demonstrating how to enforce rules like min and max length, whitespace stripping, and reusable custom annotations. She also compares validation approaches, highlighting when built-in constraints are the most practical choice.
Testing
Section Duration: 11 minutes
Nina explains the benefits of pytest as a testing framework and walks through installing it, organizing tests, and writing test functions following naming conventions. She also demonstrates using assertions and interpreting test results to verify code functionality.
Nina gives students an exercise on adding type hints, writing tests, and defining a Pydantic model for a computer with attributes like brand and RAM. She then walks through a solution using pytest.raises for validation testing and troubleshoots import issues by adding an __init__.py file.
FastAPI Core
Section Duration: 36 minutes
Nina explains the rise of FastAPI, highlighting its speed, validation features, and OpenAPI integration for automatic documentation. She then walks through setting up a FastAPI project, adding dependencies, creating endpoints, and running the server with live reloading.
Nina demonstrates using Pydantic to validate data and build endpoints that interact with projects, using a Python dictionary to simulate a data store. She walks through creating a project model, setting up routes to retrieve data by ID, and configuring response models for consistent JSON output and automatic API documentation.
Nina demonstrates setting up testing for new endpoints using FastAPI's test client, walking through writing a test to verify response logic. She then outlines the steps to pull down a working branch for exercises, covering dependency syncing and committing changes beforehand.
Nina gives students an exercise on adding a 404 error and a slug-based search endpoint to a project. She then walks through updating a test to match the new endpoint, covering status codes and basic FastAPI routing patterns.
Data Layer Foundations
Section Duration: 31 minutes
Nina explains how to connect a FastAPI app to a PostgreSQL database using Docker, covering Docker Compose configuration, environment variables, and running the container. She also walks through defining data schemas, setting up SQLModel as an ORM, configuring Alembic for migrations, and seeding the database with sample records.
Nina demonstrates setting up a database model using SQLModel by inheriting from it and setting the table flag to true. She walks through defining fields like ID, slug, and created date with specific constraints, covering imports from SQLAlchemy and the use of SQLModel's field over Pydantic's.
Nina explains how to set up Alembic by adding it as a dependency, initializing it, and configuring env.py. She then demonstrates generating migration revisions and applying them with alembic upgrade head to keep the database schema in sync with Python models.
Nina guides students through configuring Alembic, generating a projects table, and populating it with seed data. She also demonstrates troubleshooting port conflicts, running initial migrations, and querying the database to verify data insertion.
Build Release Tracker v1
Section Duration: 35 minutes
Nina demonstrates wiring a FastAPI app to PostgreSQL, implementing CRUD operations, and replacing mock dictionaries with real database queries. She covers creating endpoints, generating slugs, using dependency injection for database sessions, and refactoring route handlers into a dedicated crud.py file.
Nina explains CRUD route implementation in FastAPI, covering create, update, delete, and read operations using POST, PATCH, and DELETE methods. She also covers data validation, database session management, and the importance of separating concerns to keep route handlers from becoming bloated.
Nina guides students through refactoring database logic into a dedicated CRUD module, separating HTTP routing in main.py from database operations in crud.py. She walks through implementing functions for listing, getting, creating, updating, and deleting projects while keeping API behavior unchanged.
Dependency Injection & Exceptions
Section Duration: 37 minutes
Nina covers annotated syntax for dependencies in FastAPI, demonstrating how to create a custom dependency to reduce repeated patterns in routing. She also demonstrates centralizing exception handling and reorganizing endpoints using API routers to manage growing models more efficiently.
Nina demonstrates refactoring repetitive route logic by creating a get_project_or_404 method in dependencies.py using dependency injection. She also covers nested dependencies and how FastAPI resolves them automatically, highlighting opportunities for further generalization in larger APIs.
Nina demonstrates handling exceptions in FastAPI using the app.exception_handler decorator, showing how to return a JSON response when a SQLAlchemy IntegrityError occurs. She also covers keeping route-specific errors separate from shared exceptions, emphasizing a clean separation between the data layer and HTTP responses.
Nina explains how to use APIRouter in FastAPI to organize endpoints into separate modules, demonstrating how to define routes in separate files and import them into main.py. She also highlights syntax differences between APIRouter and the traditional app.get method and covers the use of route prefixes.
Nina gives students an exercise on refactoring code into an API router, covering dependencies.py setup, registering a global integrity error handler, and moving project endpoints into their own router file. She also recommends the FastAPI tutorial for further guidance on structuring larger projects.
Logging, Middleware & Schema Evolution
Section Duration: 48 minutes
Nina covers logging configuration using the standard library, middleware for timing requests in FastAPI, and schema evolution by adding a task model with migrations. She also compares middleware to exception handlers and discusses running migrations without data loss.
Nina explains how to enhance logging by adding timestamps, source module info, and environment-variable-based log level control. She also explores alternative logging libraries Structlog and Loguru, highlighting their features compared to the standard library.
Nina explains the role of middleware in web applications, showing how to set it up using async functions and the app.middleware decorator. She also covers the order of execution for multiple middlewares and why async handling is necessary in FastAPI.
Nina explains how to use string enums to define task status and priority in Python, then guides students through creating a task base model with fields like title, status, priority, and due date. She also demonstrates setting up a relationship between tasks and projects using SQLModel's relationship feature.
Nina walks through creating task models with constraints like title, status, priority, and due date, emphasizing inheritance and database relationships. She then demonstrates using Alembic to generate and apply migrations for the tasks table and guides students through running the dev server to observe logging behavior.
Task API & Querying
Section Duration: 1 hour, 4 minutes
Nina explains how to build the task API using relational queries, query parameter filters, and eager loading. She then gives students an exercise on implementing filtering in the list tasks method and writing tests to validate the new task endpoints.
Nina explains how to structure endpoints in FastAPI, covering response models, CRUD methods, and import syntax conventions. She also walks through creating task routers with CRUD operations including delete, update, and retrieve, and covers filtering tasks by various parameters.
Nina explains how to represent SQL queries using SQLModel, covering predicates, joins, select, and load for managing relationships efficiently. She also demonstrates the N+1 query problem and how to solve it using selectinload to fetch related data eagerly.
Nina demonstrates setting up test fixtures using SQLite for speed and isolation, explaining the session fixture for building an in-memory database. She also covers the client fixture to ensure each test uses a per-test session rather than the real database.
Nina gives students an exercise on building a task API with conditional filter logic and CRUD operations, including determining overdue status with complex SQL statements. She then walks through writing endpoint tests to verify task filtering by status and project slug.
Authentication
Section Duration: 1 hour, 3 minutes
Nina explains password-based authentication, covering the concepts of authentication vs. authorization and the trade-offs between SSO and first-party email/password systems. She also discusses the responsibility of securely storing passwords when building a first-party auth system.
Nina explains password hashing, emphasizing the risks of storing plain text passwords and recommending the argon2 ID algorithm via the pwlib library. She demonstrates implementing hashing and verification helper methods in a Python project.
Nina explains JSON Web Tokens, breaking down the header, payload, and signature structure and the importance of keeping the secret key private. She then demonstrates generating tokens using pyjwt with specific arguments like subject and expiration time.
Nina explains how to protect endpoints by verifying JWTs and retrieving user data using FastAPI's OAuth2 password bearer. She demonstrates decoding tokens, setting up a current_user dependency for route handlers, and distinguishes between authentication and authorization in project routes.
Nina gives students an exercise on building a registration endpoint, generating a secret key, applying migrations, and testing user registration and login. She then walks through common errors like missing secret keys, incorrect request formats, and database conflicts, providing troubleshooting tips for each.
Deployment Best Practices
Section Duration: 36 minutes
Nina covers deployment best practices including Docker, secrets management, GitHub Actions, and quality tooling like Ruff, mypy, pytest, and coverage. She demonstrates adding dev dependencies, configuring linting and formatting, setting up coverage reporting, and using pre-commit hooks for automated checks.
Nina walks through Dockerizing a FastAPI app, covering the Dockerfile setup for the Python interpreter, dependencies, and environment variables. She also covers pinning image versions, optimizing startup flags, and creating a .dockerignore file to exclude unnecessary files from the build.
Nina explains managing environment variables using a .env file for development, emphasizing the importance of keeping sensitive data out of version control. She also covers production secrets best practices, recommending platform-native environment variables or managed services like AWS Secrets Manager.
Nina gives students a final exercise on implementing a health endpoint and Dockerizing the app. She then walks through building a Docker image, running the full stack, and troubleshooting issues like missing JWT secret keys and premature web container startup.
Nina walks through modern Python best practices including type annotations, tooling, and recent language additions. She also covers a codebase walkthrough highlighting fields like created_at and updated_at, default factory methods, cascading relationships, and configuring logging using FastAPI's startup and shutdown hooks.
Wrapping Up
Section Duration: 3 minutes
Nina wraps up the course by covering tools used on modern Python teams including UV, Ruff, MyPy, Alembic, and PyTest, emphasizing pinning tools for reproducible builds. She also encourages clear API contracts, running checks locally before pushing, and suggests adding features like authorization and background tasks for further learning.
Earn a Completion Certificate
After completing this course, you'll receive a certificate of completion that serves as proof of your achievement, showcasing your expertise, and commitment to professional development. You can easily share this certificate on your LinkedIn profile to highlight your new skills and demonstrate continuous learning to potential employers and professional connections.
