Let's start from the beginning. There are quite a few (local to buffer) options in Vim to work with indenting.
autoindent is the most basic setting; it simply makes a new line to have an equivalent number (influenced by
preserveindent options) of leading spaces/tabs as in a previous line;
smartindent is a "lightweight" thing for a C-like language. It indents/unindents braces and hashes, and also indents after a few keywords, such as "if", "while" etc. (See
:h 'cinwords') But it lacks an unindent for keywords, such as "else";
cindent option (and the corresponding VimScript function
cindent()) is a full-featured builtin C/C++ indenter; it's also used as a fallback by many C-like languages, such as Java, Rust and so on; however, it's of a little use for Python and such;
also, there's a builtin indenter for LISP language, but it's probably of a little interest now;
indentexpr is the most flexible option; it could be set to a VimScript expression (normally, a function call) to be evaluated in runtime;
So, as one may guess, for almost all programming languages Vim computes indents by re-evaluating an expression stored in
indentexpr. But, of course, an ordinary vimmer doesn't want to implement
function GetPythonIndent() himself, so it's written as a part of standard plugin shipped with Vim.
The core Vim command to enable this functionality is
:h filetype. If entered without arguments, it prints the current state:
filetype detection:ON plugin:ON indent:ON
So there are (at least) three subsystems designed to work together: filetype detection, filetype settings and indent settings. But let's focus only on
ftdetect it's enough to say that the file type must be somehow detected before a relevant indent subplugin can do its job.
indent:ON then Vim simply sources
$VIMRUNTIME/indent.vim which sets a trap for all subsequent
FileType events (see
:h :autocmd). Then if we got some
x.y.z filetype the code in
indent.vim sources all
indent/z.vim found on
:h 'runtimepath'. A standard implementation for
setlocal indentexpr=GetPythonIndent(v:lnum) is then found in
$VIMRUNTIME/defaults.vim (note: Vim8+ only) there's a line
filetype plugin indent on, so if you source the recommended defaults for Vim (e.g.
runtime defaults.vim on top of your vimrc), then you don't have to enable ftplugin functionality manually. In Neovim,
filetype plugin indent on is a builtin default setting.