{"id":473471,"date":"2025-09-02T16:37:10","date_gmt":"2025-09-02T16:37:10","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=473471"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=473471","title":{"rendered":"<span>\u0420\u0435\u0448\u0438\u043b \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043d\u0430 Python \u0438 \u043d\u0435 \u043f\u043e\u0436\u0430\u043b\u0435\u043b<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/221\/dfd\/858\/221dfd858d37f8721de69462e0672962.jpg\" width=\"1400\" height=\"836\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/221\/dfd\/858\/221dfd858d37f8721de69462e0672962.jpg 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/221\/dfd\/858\/221dfd858d37f8721de69462e0672962.jpg 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u0421 \u043f\u043e\u043b\u0433\u043e\u0434\u0430 \u043d\u0430\u0437\u0430\u0434 \u044f \u043d\u0430\u0447\u0430\u043b \u0447\u0430\u0449\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f <a href=\"https:\/\/www.python.org\/\" rel=\"noopener noreferrer nofollow\">Python<\/a>. \u041f\u043e\u0447\u0435\u043c\u0443? \u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u0438\u0437-\u0437\u0430 \u0418\u0418. \u041b\u0438\u0447\u043d\u043e \u0434\u043b\u044f \u043c\u0435\u043d\u044f \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u044d\u0442\u0430 \u0441\u0444\u0435\u0440\u0430 \u0441\u0432\u044f\u0437\u0430\u043d\u0430 \u0441 \u043e\u0447\u0435\u043d\u044c \u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 <s>\u0434\u0435\u043d\u044c\u0433\u0430\u043c\u0438<\/s> \u043f\u0435\u0440\u0441\u043f\u0435\u043a\u0442\u0438\u0432\u0430\u043c\u0438 \u0432\u043e \u0432\u0441\u0435\u0445 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f\u0445. \u0410 \u043a\u0430\u043a\u043e\u0439 \u044f\u0437\u044b\u043a \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0430\u043c\u044b\u043c \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u043c \u0434\u043b\u044f \u0418\u0418? \u0414\u0430-\u0434\u0430, \u044d\u0442\u043e\u0442 \u0441\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u043d\u044b\u0440\u0430. <\/p>\n<p>\u042f \u0443\u0436\u0435 \u043f\u0438\u0441\u0430\u043b \u043d\u0430 Python, \u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u044b. \u041a \u043f\u0440\u0438\u043c\u0435\u0440\u0443, <a href=\"https:\/\/github.com\/cesarsotovalero\/cesarsotovalero.github.io\/blob\/1fb2efe0577719a72fdf7d5bdf2a8d4d51ee58c5\/scripts\/fetch_all_youtube_videos.py\" rel=\"noopener noreferrer nofollow\">\u0432\u043e\u0442 \u044d\u0442\u043e\u0442<\/a> \u0441\u043a\u0440\u0435\u0439\u043f\u0438\u0442 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0432\u0441\u0435\u0445 \u0432\u0438\u0434\u0435\u043e \u0441 <a href=\"https:\/\/www.youtube.com\/channel\/UCR4rI98w6-MqYoCS6jR9LGg\" rel=\"noopener noreferrer nofollow\">\u043c\u043e\u0435\u0433\u043e \u043a\u0430\u043d\u0430\u043b\u0430 \u043d\u0430 YouTube<\/a>. \u0421\u043e\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0432\u044b\u0432\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u0432\u0438\u0434\u0435 <a href=\"https:\/\/github.com\/cesarsotovalero\/cesarsotovalero.github.io\/blob\/1fb2efe0577719a72fdf7d5bdf2a8d4d51ee58c5\/_data\/youtube-videos.json\" rel=\"noopener noreferrer nofollow\">\u0444\u0430\u0439\u043b\u0430 JSON<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u0434\u043b\u044f \u043f\u043e\u043a\u0430\u0437\u0430 \u043a\u0440\u0430\u0441\u0438\u0432\u043e\u0439 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 \u0440\u043e\u043b\u0438\u043a\u043e\u0432 \u043d\u0430 <a href=\"https:\/\/www.cesarsotovalero.net\/youtube\" rel=\"noopener noreferrer nofollow\">\u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u0438\u0447\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435<\/a>. \u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0432\u0438\u0434\u0435\u0442\u044c \u0437\u0434\u0435\u0441\u044c, \u044d\u0442\u043e\u0442 \u0441\u043a\u0440\u043e\u043c\u043d\u044b\u0439 \u0441\u043a\u0440\u0438\u043f\u0442 \u0447\u0435\u0440\u0435\u0437 GitHub Actions \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u0441\u043e\u043b\u043e-\u0440\u0435\u0436\u0438\u043c\u0435 \u043a\u0430\u0436\u0434\u044b\u0439 \u043f\u043e\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u0438\u043a. \u041f\u0440\u043e\u0441\u0442\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0451 \u044d\u0442\u043e \u043d\u0430 Python \u043a\u0443\u0434\u0430 \u043f\u0440\u043e\u0449\u0435, \u0447\u0435\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0442\u043e\u0433\u043e \u0436\u0435 Bash. \u0418 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u0437-\u0437\u0430 \u0431\u043e\u043b\u0435\u0435 \u0434\u0440\u0443\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0430, \u043d\u043e \u0438 \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0435\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u043d\u0430\u0442\u0438\u0432\u043d\u043e \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u043d \u0432\u043e \u0432\u0441\u0435 \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0442\u0438\u0432\u044b Unix. \u0420\u0430\u0437\u0432\u0435 \u043d\u0435 \u043a\u0440\u0443\u0442\u043e?<\/p>\n<p><a class=\"anchor\" name=\"id11\" id=\"id11\"><\/a><\/p>\n<p>\u0422\u0430\u043a \u0447\u0442\u043e, \u0434\u0430, Python \u0441\u0438\u043b\u0451\u043d \u0438 \u043e\u0442\u043b\u0438\u0447\u043d\u043e \u0441\u043e\u0447\u0435\u0442\u0430\u0435\u0442\u0441\u044f \u0441 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u043c \u0441\u0435\u0433\u043e\u0434\u043d\u044f <a href=\"https:\/\/code.visualstudio.com\/\" rel=\"noopener noreferrer nofollow\">VSCode<\/a>. \u041d\u043e \u0432\u0441\u0435\u0440\u044c\u0451\u0437 \u044f \u043d\u0430\u0447\u0430\u043b \u043a \u043d\u0435\u043c\u0443 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u044c\u0441\u044f \u043b\u0438\u0448\u044c \u043d\u0435\u0434\u0430\u0432\u043d\u043e<a href=\"#id1\" rel=\"noopener noreferrer nofollow\"><sup>1<\/sup><\/a>, \u043a\u043e\u0433\u0434\u0430 \u0440\u0435\u0448\u0438\u043b \u0437\u0430\u043d\u044f\u0442\u044c\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043d\u0430 \u0431\u0430\u0437\u0435 \u0418\u0418 (RAG, \u0430\u0433\u0435\u043d\u0442\u043e\u0432, \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0438 \u043f\u0440\u043e\u0447\u0435\u0433\u043e) \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447. \u0422\u043e\u0433\u0434\u0430 \u044f \u043f\u043e\u043d\u044f\u043b, \u0447\u0442\u043e \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 \u0442\u043e\u0433\u043e, \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u043e\u043d \u0432\u0430\u043c \u0438\u043b\u0438 \u043d\u0435\u0442, \u0434\u043b\u044f \u0432\u0441\u0435\u0433\u043e \u044d\u0442\u043e\u0433\u043e \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c \u0432\u044b\u0431\u043e\u0440\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u0438\u043c\u0435\u043d\u043d\u043e Python.<\/p>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u044f \u0440\u0435\u0448\u0438\u043b \u0432\u0437\u044f\u0442\u044c\u0441\u044f \u0437\u0430 \u043d\u0435\u0433\u043e \u0432\u0441\u0435\u0440\u044c\u0451\u0437 \u0438 \u043a \u0441\u0432\u043e\u0435\u043c\u0443 \u0443\u0434\u0438\u0432\u043b\u0435\u043d\u0438\u044e \u0432\u044b\u044f\u0441\u043d\u0438\u043b, \u0447\u0442\u043e Python \u0432\u043c\u0435\u0441\u0442\u0435 \u0441\u043e \u0432\u0441\u0435\u0439 \u043e\u043a\u0440\u0443\u0436\u0430\u044e\u0449\u0435\u0439 \u0435\u0433\u043e \u0441\u0440\u0435\u0434\u043e\u0439 \u0437\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0434\u0435\u0441\u044f\u0442\u0438\u043b\u0435\u0442\u0438\u044f \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0440\u0430\u0437\u0432\u0438\u043b\u0441\u044f. <\/p>\n<p>\u0412\u043e\u0442 \u043b\u0438\u0448\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0439 \u0442\u043e\u043c\u0443:<\/p>\n<p><a class=\"anchor\" name=\"id12\" id=\"id12\"><\/a><\/p>\n<ol>\n<li>\n<p>\u0412\u043e\u043a\u0440\u0443\u0433 \u044d\u0442\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430 \u0432\u044b\u0441\u0442\u0440\u043e\u0438\u043b\u0430\u0441\u044c \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u0430\u044f \u044d\u043a\u043e\u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a \u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438\/\u0430\u043d\u0430\u043b\u0438\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445.<a href=\"#id2\" rel=\"noopener noreferrer nofollow\"><sup>2<\/sup><\/a><\/p>\n<\/li>\n<li>\n<p>Python \u0441\u0442\u0430\u043b \u0431\u044b\u0441\u0442\u0440\u0435\u0435, \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u043e\u0432 \u0432\u0440\u043e\u0434\u0435 Cython.<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 Python \u043f\u0440\u043e\u0434\u0435\u043b\u0430\u043b\u0438 \u0441\u0442\u0430\u0440\u0430\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443, \u0441\u043a\u0440\u044b\u0432 \u0435\u0433\u043e \u043b\u0435\u0433\u0430\u0441\u0438-\u0443\u0440\u043e\u0434\u0441\u0442\u0432\u043e (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>__init__<\/code>,\u00a0<code>__new__<\/code> \u0438 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0435 \u0438\u0441\u043a\u0430\u0436\u0435\u043d\u0438\u044f), \u0441\u0434\u0435\u043b\u0430\u0432 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 \u0431\u043e\u043b\u0435\u0435 \u0443\u0434\u043e\u0431\u043d\u044b\u043c \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 <s>\u0441 \u0445\u043e\u0440\u043e\u0448\u0438\u043c \u0432\u043a\u0443\u0441\u043e\u043c<\/s>.<\/p>\n<\/li>\n<\/ol>\n<p>\u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0432\u0441\u0435\u043c \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u043c \u0438 \u043c\u043d\u043e\u0433\u0438\u043c \u0434\u0440\u0443\u0433\u0438\u043c \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u043a\u0430\u043c, \u0442\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u044d\u0442\u0438\u043c \u044f\u0437\u044b\u043a\u043e\u043c \u043c\u043d\u0435 \u0441\u0442\u0430\u043b\u043e \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043f\u0440\u0438\u044f\u0442\u043d\u043e.<\/p>\n<p><a class=\"anchor\" name=\"id13\" id=\"id13\"><\/a><\/p>\n<p>\u0422\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435 \u0437\u0430 \u044d\u0442\u0438 \u043f\u043e\u043b\u0433\u043e\u0434\u0430 \u044f \u0442\u0430\u043a\u0436\u0435 \u0443\u0437\u043d\u0430\u043b, \u0447\u0442\u043e \u043f\u043e-\u043f\u0440\u0435\u0436\u043d\u0435\u043c\u0443 \u0432\u0435\u043b\u0438\u043a\u0430 \u0440\u0430\u0437\u043d\u0438\u0446\u0430 \u043c\u0435\u0436\u0434\u0443 \u043f\u0440\u0438\u0433\u043e\u0434\u043d\u043e\u0441\u0442\u044c\u044e Python \u0434\u043b\u044f \u043e\u0431\u044b\u0447\u043d\u044b\u0445 \u0440\u0430\u0431\u043e\u0447\u0438\u0445 \u043f\u043e\u0442\u043e\u043a\u043e\u0432 \u043d\u0430 \u0431\u0430\u0437\u0435 \u0431\u043b\u043e\u043a\u043d\u043e\u0442\u043e\u0432 Jupyter \u0438\u043b\u0438 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 \u0438 \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u043a \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d\u0443<a href=\"#id3\" rel=\"noopener noreferrer nofollow\"><sup>3<\/sup><\/a> \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439.<\/p>\n<p>\u0422\u0430\u043a \u0447\u0442\u043e \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043e\u0431 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u0445, \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u0445, \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f\u0445 \u0438 \u043f\u0440\u043e\u0447\u0438\u0445 \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f\u0445 \u0434\u043b\u044f \u044f\u0437\u044b\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u0430\u0440\u044f\u0442 \u043c\u043d\u0435 \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u043e, \u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439.<\/p>\n<p>\u26a0\ufe0f \u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u043d\u0430 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u044e \u043b\u0438\u0447\u043d\u043e \u044f. \u0415\u0441\u043b\u0438 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u0442\u044c \u043c\u043d\u0435 \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u0434\u0440\u0443\u0433\u0438\u0435 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f, \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u0435\u0441\u044c \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445. <\/p>\n<blockquote>\n<p><em>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/em><strong>:<\/strong>\u00a0\u0442\u0430\u043a \u0432\u044b\u0448\u043b\u043e, \u0447\u0442\u043e \u043c\u043e\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u043d\u0430\u0431\u0440\u0430\u043b\u0430 \u043d\u0430 Hacker News <a href=\"https:\/\/news.ycombinator.com\/item?id=44579717\" rel=\"noopener noreferrer nofollow\">\u0431\u043e\u043b\u0435\u0435 680 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0435\u0432<\/a>. \u0415\u0449\u0451 \u0440\u0430\u0437 \u0443\u0431\u0435\u0436\u0434\u0430\u044e\u0441\u044c \u0432 \u043d\u0435\u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0443\u0435\u043c\u043e\u0441\u0442\u0438 \u0436\u0438\u0437\u043d\u0438.<\/p>\n<\/blockquote>\n<h2>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h2>\n<p><a class=\"anchor\" name=\"id14\" id=\"id14\"><\/a><\/p>\n<p>\u042f \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u044e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0441\u0432\u043e\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 Python \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043c\u043e\u043d\u043e\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0432 \u043d\u0435\u0433\u043e \u0438 \u0431\u044d\u043a\u0435\u043d\u0434, \u0438 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434.<a href=\"#id4\" rel=\"noopener noreferrer nofollow\"><sup>4<\/sup><\/a><\/p>\n<p>\u041f\u043e\u0447\u0435\u043c\u0443?<\/p>\n<ol>\n<li>\n<p>\u0418\u0437-\u0437\u0430 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 \u0441 \u0437\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u043d\u0438\u0435\u043c: \u043c\u043d\u0435 \u043d\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f, \u043a\u043e\u0433\u0434\u0430 \u0447\u0430\u0441\u0442\u0438 \u043a\u043e\u0434\u0430 \u0440\u0430\u0437\u0431\u0440\u043e\u0441\u0430\u043d\u044b \u043f\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f\u043c (\u044d\u0442\u043e \u044f\u0432\u043d\u043e \u043d\u0435 \u043e\u0431\u043b\u0435\u0433\u0447\u0430\u0435\u0442 \u043f\u043e\u0438\u0441\u043a). <\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u043b\u0438\u0447\u0438\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0435\u0432 \u0437\u0430\u0447\u0430\u0441\u0442\u0443\u044e \u0438\u0437\u043b\u0438\u0448\u043d\u0435. \u042f \u0440\u0430\u0431\u043e\u0442\u0430\u044e \u043e\u0434\u0438\u043d \u0438 \u0441\u0447\u0438\u0442\u0430\u044e, \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u043f\u0440\u043e\u0435\u043a\u0442 \u0434\u043e\u0440\u0430\u0441\u0442\u0451\u0442 \u0434\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u0438 \u0435\u0433\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0435 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438, \u044d\u0442\u043e \u0443\u0436\u0435 \u0431\u0443\u0434\u0435\u0442 \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u043e \u0447\u0440\u0435\u0437\u043c\u0435\u0440\u043d\u043e\u043c \u0443\u0441\u043b\u043e\u0436\u043d\u0435\u043d\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0443 \u0438 \u044f \u0431\u0430\u043d\u0430\u043b\u044c\u043d\u043e \u043b\u0435\u043d\u0438\u0432\u044b\u0439, \u0441\u0442\u0430\u0440\u0430\u044e\u0441\u044c \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0443\u0441\u043b\u043e\u0436\u043d\u044f\u0442\u044c \u2014 \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u044e, \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u044e, \u043f\u0430\u043a\u0443\u044e \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b \u0438 \u0440\u0430\u0437\u0432\u0451\u0440\u0442\u044b\u0432\u0430\u044e \u0438\u0437 \u043e\u0434\u043d\u043e\u0433\u043e \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<a href=\"#id5\" rel=\"noopener noreferrer nofollow\"><sup>5<\/sup><\/a><\/p>\n<\/li>\n<\/ol>\n<p>\u041c\u043d\u0435 \u0431\u044b \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0438\u043c\u0435\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u044b \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043b \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u043d\u043e \u043f\u043e\u043a\u0430 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u044f \u043d\u0435 \u043d\u0430\u0448\u0451\u043b. \u0420\u0430\u043d\u044c\u0448\u0435 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b <a href=\"https:\/\/cookiecutter-data-science.drivendata.org\/\" rel=\"noopener noreferrer nofollow\">CCDS<\/a> \u2014 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043b\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432 \u0441\u0444\u0435\u0440\u0435 \u0434\u0430\u0442\u0430-\u0441\u0430\u0439\u0435\u043d\u0441. \u041e\u043d \u043e\u0447\u0435\u043d\u044c \u0445\u043e\u0440\u043e\u0448, \u043d\u043e \u043d\u0435 \u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d \u043d\u0430 \u0444\u0443\u043b\u0441\u0442\u0435\u043a \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432.<\/p>\n<p>\u0412\u043e\u0442 \u0442\u0438\u043f\u0438\u0447\u043d\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0441 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043e\u0439 \u0444\u0440\u043e\u043d\u0442-\u0431\u044d\u043a (\u0447\u0443\u0442\u044c \u043f\u043e\u0437\u0436\u0435 \u044f \u043f\u0440\u043e\u0431\u0435\u0433\u0443\u0441\u044c \u043f\u043e \u043a\u0430\u0436\u0434\u043e\u0439 \u0435\u0451 \u0447\u0430\u0441\u0442\u0438):<\/p>\n<pre><code>project\/ \u2502 \u251c\u2500\u2500 .github\/ # \u0420\u0430\u0431\u043e\u0447\u0438\u0435 \u043f\u043e\u0442\u043e\u043a\u0438 GitHub Actions \u0434\u043b\u044f \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u043e\u0432 CI\/CD. \u2502\u00a0\u00a0 \u251c\u2500\u2500 workflows\/ # \u041a\u0430\u0442\u0430\u043b\u043e\u0433 \u0441 \u0444\u0430\u0439\u043b\u0430\u043c\u0438 YAML \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0440\u0430\u0431\u043e\u0447\u0438\u0445 \u043f\u043e\u0442\u043e\u043a\u043e\u0432. \u2502\u00a0\u00a0 \u2514\u2500\u2500 dependabot.yml # \u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f Dependabot \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438. \u2502 \u251c\u2500\u2500 .vscode\/ # \u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f VSCode \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u2502\u00a0\u00a0 \u251c\u2500\u2500 launch.json # \u041e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0434\u043b\u044f VSCode. \u2502\u00a0\u00a0 \u2514\u2500\u2500 settings.json # \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0434\u043b\u044f VSCode. \u2502 \u251c\u2500\u2500 docs\/ # \u0421\u0430\u0439\u0442 \u0438 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f (\u0441\u0442\u0430\u0442\u0438\u0447\u043d\u044b\u0439 SPA \u0441 MkDocs). \u2502 \u251c\u2500\u2500 project-api\/ # API \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0438 \u0438 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447. \u2502\u00a0\u00a0 \u251c\u2500\u2500 data\/ # \u041a\u0430\u0442\u0430\u043b\u043e\u0433 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u0442\u0430\u0441\u0435\u0442\u043e\u0432 \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u0441\u0442\u0430\u0442\u0438\u0447\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432. \u2502\u00a0\u00a0 \u251c\u2500\u2500 notebooks\/ # \u0411\u043b\u043e\u043a\u043d\u043e\u0442\u044b Jupyter \u0434\u043b\u044f \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u0445 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432 \u0438 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u2502\u00a0\u00a0 \u251c\u2500\u2500 tools\/ # \u0412\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0440\u0430\u0437\u0432\u0451\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f. \u2502\u00a0\u00a0 \u251c\u2500\u2500 src\/ # \u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u0434\u043b\u044f \u0431\u044d\u043a\u0435\u043d\u0434-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 app\/ # \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043a\u043e\u0434 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 tests\/ # \u041c\u043e\u0434\u0443\u043b\u044c\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b \u0434\u043b\u044f \u0431\u044d\u043a\u0435\u043d\u0434\u0430. \u2502\u00a0\u00a0 \u2502 \u2502\u00a0\u00a0 \u251c\u2500\u2500 .dockerignore # \u0423\u043a\u0430\u0437\u0430\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u043e\u0432, \u0438\u0441\u043a\u043b\u044e\u0447\u0430\u0435\u043c\u044b\u0445 \u0438\u0437 \u0441\u0431\u043e\u0440\u043e\u043a Docker. \u2502\u00a0\u00a0 \u251c\u2500\u2500 .python-version # \u0423\u043a\u0430\u0437\u0430\u043d\u0438\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 Python \u0434\u043b\u044f pyenv. \u2502\u00a0\u00a0 \u251c\u2500\u2500 Dockerfile # \u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f Docker \u0434\u043b\u044f \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0431\u044d\u043a\u0435\u043d\u0434\u0430. \u2502\u00a0\u00a0 \u251c\u2500\u2500 Makefile # \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438, \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0440\u0430\u0437\u0432\u0451\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f. \u2502\u00a0\u00a0 \u251c\u2500\u2500 pyproject.toml # \u0424\u0430\u0439\u043b \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 Python. \u2502\u00a0\u00a0 \u251c\u2500\u2500 README.md # \u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0434\u043b\u044f API \u0431\u044d\u043a\u0435\u043d\u0434\u0430. \u2502\u00a0\u00a0 \u2514\u2500\u2500 uv.lock # Lockfile, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439, \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0445 UV. \u2502 \u251c\u2500\u2500 project-ui\/ # UI \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430 \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 (Next.js, React \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435). \u2502 \u251c\u2500\u2500 .gitignore # \u0413\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b gitignore \u0434\u043b\u044f \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f. \u251c\u2500\u2500 .pre-commit-config.yaml # \u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0434\u043b\u044f pre-commit \u0445\u0443\u043a\u043e\u0432. \u251c\u2500\u2500 CONTRIBUTING.md # \u0420\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u0430 \u0434\u043b\u044f \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u043e\u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u251c\u2500\u2500 docker-compose.yml # \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 Docker Compose \u0434\u043b\u044f \u043c\u0443\u043b\u044c\u0442\u0438-\u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043d\u044b\u0445 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0439. \u251c\u2500\u2500 LICENSE # \u041b\u0438\u0446\u0435\u043d\u0437\u0438\u043e\u043d\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 (\u044f \u0432\u0441\u0435\u0433\u0434\u0430 \u0432\u044b\u0431\u0438\u0440\u0430\u044e MIT). \u251c\u2500\u2500 Makefile # \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438, \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0434\u0435\u043f\u043b\u043e\u044f. \u2514\u2500\u2500 README.md # \u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 (\u0435\u0433\u043e \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e).<\/code><\/pre>\n<p>\u041c\u043e\u0439 <code>project<\/code> \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0430\u0434\u0440\u0435\u0441\u043e\u043c \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0433\u043e \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430 \u0438 \u0438\u043c\u0435\u043d\u0435\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f GitHub. \u041c\u043d\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u0434\u0430\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u043c \u043a\u043e\u0440\u043e\u0442\u043a\u0438\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u0434\u043b\u0438\u043d\u043e\u0439 \u0434\u043e 10 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432, \u0431\u0435\u0437 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f <code>snake_case<\/code> \u2014 \u043c\u0435\u043d\u044f \u0432\u043f\u043e\u043b\u043d\u0435 \u0443\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0434\u0435\u0444\u0438\u0441\u0430\u043c\u0438. \u0417\u0430\u043c\u0435\u0442\u044c\u0442\u0435, \u0447\u0442\u043e \u043f\u0440\u043e\u0435\u043a\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0441\u0430\u043c\u043e\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u044b\u043c, \u0442\u043e \u0435\u0441\u0442\u044c \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e, \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0441\u0431\u043e\u0440\u043a\u0438\/\u0434\u0435\u043f\u043b\u043e\u044f \u0438 \u043b\u044e\u0431\u044b\u0435 \u0434\u0440\u0443\u0433\u0438\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0434\u043b\u044f \u0435\u0433\u043e \u0430\u0432\u0442\u043e\u043d\u043e\u043c\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u0432\u0451\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>\u0412\u0430\u0436\u043d\u043e \u043d\u0435 \u043f\u0440\u043e\u0434\u0435\u043b\u044b\u0432\u0430\u0442\u044c \u0432 <code>project-ui<\/code> \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u044d\u0442\u0430\u043f\u043e\u0432 \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445, \u0442\u0430\u043a \u043a\u0430\u043a \u044f \u0441\u0442\u0430\u0440\u0430\u044e\u0441\u044c \u043e\u0442\u0434\u0435\u043b\u044f\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430 \u043e\u0442 \u0437\u0430\u0434\u0430\u0447 \u0431\u044d\u043a\u0435\u043d\u0434\u0430. \u0412\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u043e\u0433\u043e \u044f \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0443 <code>project-api<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 Python-\u043a\u043e\u0434. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043c\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043b\u0451\u0433\u043a\u0438\u043c, \u0434\u0435\u043b\u0435\u0433\u0438\u0440\u0443\u044f \u0432\u0441\u044e \u043e\u0441\u043d\u043e\u0432\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u0438 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u0443.<\/p>\n<p>\u0412 <code>project-api\/src\/app<\/code> \u0435\u0441\u0442\u044c \u0444\u0430\u0439\u043b\u00a0<code>__init__.py<\/code>, \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0439, \u0447\u0442\u043e <code>app<\/code> \u2014 \u044d\u0442\u043e \u043c\u043e\u0434\u0443\u043b\u044c Python (\u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0437 \u0434\u0440\u0443\u0433\u0438\u0445 \u043c\u043e\u0434\u0443\u043b\u0435\u0439).<\/p>\n<h2>\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b Python<\/h2>\n<h3>uv<\/h3>\n<p>\u0414\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0430\u043a\u0435\u0442\u0430\u043c\u0438 \u0438 \u0441\u0431\u043e\u0440\u043a\u0438 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u00a0<a href=\"https:\/\/github.com\/astral-sh\/uv\" rel=\"noopener noreferrer nofollow\">uv<\/a>. \u042d\u0442\u043e\u0433\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430 \u043c\u043d\u0435 \u0432\u043f\u043e\u043b\u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u0434\u043b\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0438\u043c\u0438. <\/p>\n<p>\u0412\u043e\u0442 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u043b\u044f \u0435\u0433\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438:<\/p>\n<pre><code># \u0413\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u0430\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 uv, \u0435\u0441\u043b\u0438 \u043e\u043d \u0435\u0449\u0451 \u043d\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d.\u00a0  curl -sSfL &lt;https:\/\/astral.sh\/install.sh&gt; | sh  # \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 (\u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 .gitignore, .python-version, pyproject.toml \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435).  uv init   project-api  # \u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 pyproject.toml.  uv add --dev pytest ruff pre-commit mkdocs gitleaks   fastapi pydantic  # \u0423\u043a\u0430\u0437\u0430\u043d\u0438\u0435 \u0432 Lockfile \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0445 \u0432\u0435\u0440\u0441\u0438\u0439 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 (\u0441\u043e\u0437\u0434\u0430\u0451\u0442 .venv, \u0435\u0441\u043b\u0438 \u0435\u0449\u0451 \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u043d).  uv sync  # \u0410\u043a\u0442\u0438\u0432\u0430\u0446\u0438\u044f .venv.  uv venv   activate<\/code><\/pre>\n<p><a class=\"anchor\" name=\"id16\" id=\"id16\"><\/a><\/p>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u0441\u0430\u043c\u044b\u043c \u0432\u0430\u0436\u043d\u044b\u043c \u0434\u043b\u044f <code>uv<\/code> \u0444\u0430\u0439\u043b\u043e\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f\u00a0<code>pyproject.toml<\/code>.<a href=\"#id6\" rel=\"noopener noreferrer nofollow\"><sup>6<\/sup><\/a>\u00a0\u041e\u043d \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0445 \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430.<\/p>\n<h3>Ruff<\/h3>\n<p><a href=\"https:\/\/github.com\/astral-sh\/ruff\" rel=\"noopener noreferrer nofollow\">Ruff<\/a> \u043c\u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f. \u042d\u0442\u043e \u0441\u0443\u043f\u0435\u0440\u0431\u044b\u0441\u0442\u0440\u044b\u0439 \u043b\u0438\u043d\u0442\u0435\u0440 \u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u0435\u0440 \u043a\u043e\u0434\u0430 \u0434\u043b\u044f Python, \u043f\u043e\u043c\u043e\u0433\u0430\u044e\u0449\u0438\u0439 \u043b\u0435\u043d\u0438\u0432\u044b\u043c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c \u0432\u0440\u043e\u0434\u0435 \u043c\u0435\u043d\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u043a\u043e\u0434\u043e\u0432\u044b\u0435 \u0431\u0430\u0437\u044b \u0432 \u0447\u0438\u0441\u0442\u043e\u043c \u0438 \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u0435\u043c\u043e\u043c \u0432\u0438\u0434\u0435. \u041e\u043d \u0441\u043e\u0432\u043c\u0435\u0449\u0430\u0435\u0442 \u0432 \u0441\u0435\u0431\u0435 <code>isort<\/code>,\u00a0<code>flake8<\/code>,\u00a0<code>autoflake<\/code> \u0438 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0447\u0435\u0440\u0435\u0437 \u0435\u0434\u0438\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438:<\/p>\n<pre><code># \u041b\u0438\u043d\u0442\u0438\u043d\u0433 \u0432\u0441\u0435\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u0432 \/path\/to\/code (\u0438 \u0432\u0441\u0435\u0445 \u043f\u043e\u0434\u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430\u0445).  ruff check   path\/to\/code\/\u00a0  # \u0424\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u0441\u0435\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u0432 \/path\/to\/code (\u0438 \u0432\u0441\u0435\u0445 \u043f\u043e\u0434\u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430\u0445).  ruff   format path\/to\/code\/<\/code><\/pre>\n<p>Ruff \u0448\u0442\u0430\u0442\u043d\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u043f\u043e \u0441\u0442\u0438\u043b\u044e <a href=\"https:\/\/pep8.org\/\" rel=\"noopener noreferrer nofollow\">PEP 8<\/a>.<\/p>\n<h3>ty<\/h3>\n<p><a href=\"https:\/\/github.com\/astral-sh\/ty\" rel=\"noopener noreferrer nofollow\">ty<\/a>\u00a0\u2014 \u044d\u0442\u043e \u043c\u043e\u0434\u0443\u043b\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0442\u0438\u043f\u043e\u0432 \u0434\u043b\u044f Python. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043e\u043d \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e \u0441\u043e\u0447\u0435\u0442\u0430\u0435\u0442\u0441\u044f \u0441 <a href=\"https:\/\/docs.python.org\/3\/library\/typing.html\" rel=\"noopener noreferrer nofollow\">typing<\/a>, \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u043c \u043c\u043e\u0434\u0443\u043b\u0435\u043c \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0442\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u0438. \u0414\u0443\u043c\u0430\u044e, \u0447\u0442\u043e \u0442\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u044f \u0440\u0435\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u043c\u043d\u0435 \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0438 \u0442\u0438\u043f\u043e\u0432 \u043d\u0430 \u0440\u0430\u043d\u043d\u0438\u0445 \u0441\u0442\u0430\u0434\u0438\u044f\u0445 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438. \u042f \u043d\u0435 \u0431\u043e\u044e\u0441\u044c \u043f\u0438\u0441\u0430\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434 \u0438 \u0441 \u0433\u043e\u0442\u043e\u0432\u043d\u043e\u0441\u0442\u044c\u044e \u0438\u0434\u0443 \u043d\u0430 \u044d\u0442\u043e, \u0435\u0441\u043b\u0438 \u0442\u0430\u043a\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043f\u043e\u0432\u044b\u0448\u0430\u0435\u0442 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b, \u043f\u043e\u043f\u0443\u0442\u043d\u043e \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u044f \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u044c \u043e\u0448\u0438\u0431\u043e\u043a \u0432 \u0441\u0440\u0435\u0434\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f. <\/p>\n<blockquote>\n<p><em>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/em>: \u043d\u0430 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u044c\u0438 <code>ty<\/code> \u0435\u0449\u0451 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430 \u0440\u0430\u043d\u043d\u0435\u0439 \u0441\u0442\u0430\u0434\u0438\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u043d\u043e \u0437\u0430 \u0432\u0440\u0435\u043c\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u044d\u0442\u043e\u0439 \u0443\u0442\u0438\u043b\u0438\u0442\u044b \u044f \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u043e\u0449\u0443\u0442\u0438\u043c\u044b\u0445 \u043d\u0435\u0434\u043e\u0447\u0451\u0442\u043e\u0432 \u043d\u0435 \u0437\u0430\u043c\u0435\u0442\u0438\u043b. \u041a\u0441\u0442\u0430\u0442\u0438, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043d\u0430\u0434 \u043d\u0435\u0439 \u0440\u0435\u0431\u044f\u0442\u0430 \u0438\u0437 Astral, \u0442\u043e\u0439 \u0436\u0435 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u0437\u0434\u0430\u043b\u0430 <code>uv<\/code> \u0438 <code>ruff<\/code>.<\/p>\n<\/blockquote>\n<p><strong>pytest<\/strong><\/p>\n<p><a href=\"https:\/\/docs.pytest.org\/en\/stable\/\" rel=\"noopener noreferrer nofollow\">pytest<\/a>\u00a0\u2014 \u044d\u0442\u043e \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043b\u044f Python, \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043e\u0431\u043b\u0435\u0433\u0447\u0430\u044e\u0449\u0430\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432. \u041e\u043d\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0444\u0438\u043a\u0441\u0442\u0443\u0440\u044b, \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0438\u043c\u0435\u0435\u0442 \u0431\u043e\u0433\u0430\u0442\u0443\u044e \u044d\u043a\u043e\u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432. \u041f\u0440\u043e\u0441\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u0432\u00a0<code>project-api\/src\/app\/tests\/<\/code> \u0444\u0430\u0439\u043b \u0441 \u0438\u043c\u0435\u043d\u0435\u043c <code>test_&lt;unit_or_module&gt;.py<\/code>\u00a0\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u0435:<\/p>\n<pre><code>uv run pytest<\/code><\/pre>\n<p>\u0413\u043e\u0442\u043e\u0432\u043e!<\/p>\n<h3>Pydantic<\/h3>\n<p><a href=\"https:\/\/pydantic-docs.helpmanual.io\/\" rel=\"noopener noreferrer nofollow\">Pydantic<\/a>\u00a0\u2014 \u044d\u0442\u043e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438. \u041e\u043d\u0430 \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0432\u0441\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u0434\u0435\u0442\u0430\u043b\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a \u043a\u043b\u044e\u0447\u0438 API, \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u043b\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043c\u043e\u0434\u0435\u043b\u0438 (\u0436\u0451\u0441\u0442\u043a\u043e\u0435 \u043f\u0440\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u043d\u0438\u0435 \u044d\u0442\u0438\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u2014 \u043e\u0447\u0435\u043d\u044c \u043f\u043b\u043e\u0445\u0430\u044f \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430, \u0435\u0441\u043b\u0438 \u0447\u0442\u043e).<\/p>\n<p>\u0412 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438, <a href=\"https:\/\/docs.pydantic.dev\/latest\/concepts\/pydantic_settings\/\" rel=\"noopener noreferrer nofollow\">Pydantic Settings<\/a>\u00a0\u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u043e\u0434\u0435\u043b\u0435\u0439 Pydantic. \u042d\u0442\u0430 \u0443\u0442\u0438\u043b\u0438\u0442\u0430 \u043c\u043e\u0436\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0438\u0437 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0441\u0440\u0435\u0434\u044b \u0438\u043b\u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 .env, \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0438\u0445 \u0442\u0438\u043f\u044b \u0438 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0442\u044c \u0443\u0434\u043e\u0431\u043d\u044b\u0439 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043d\u0438\u043c \u0432 \u043a\u043e\u0434\u0435.<\/p>\n<p>\u0412\u043e\u0442 \u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"python\">from   pydantic import BaseSettings  class Settings(BaseSettings): \u00a0\u00a0\u00a0 api_key: str \u00a0\u00a0\u00a0 db_url: str      \u00a0\u00a0\u00a0 class Config: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 env_file = \".env\"  settings =   Settings()<\/code><\/pre>\n<p>\u041f\u0440\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u044d\u0442\u043e\u0433\u043e \u043a\u043e\u0434\u0430 Pydantic \u0431\u0443\u0434\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f <code>api_key<\/code>\u00a0\u0438\u00a0<code>db_url<\/code>\u00a0\u0438\u0437 \u0444\u0430\u0439\u043b\u0430\u00a0<code>.env<\/code>\u00a0\u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0441\u0440\u0435\u0434\u044b. \u0412 \u0438\u0442\u043e\u0433\u0435 \u044d\u0442\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0434\u043b\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c\u0441\u044f \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u0442\u0438\u043f\u0430\u043c\u0438 \u0438\u0437 \u043c\u043e\u0434\u0435\u043b\u0438 <code>Settings<\/code>. \u041f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e! <\/p>\n<h3>MkDocs<\/h3>\n<p><a class=\"anchor\" name=\"id17\" id=\"id17\"><\/a><\/p>\n<p>\u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <a href=\"https:\/\/www.mkdocs.org\/\" rel=\"noopener noreferrer nofollow\">MkDocs<\/a>\u00a0\u044f \u0441\u043e\u0437\u0434\u0430\u044e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e \u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u044e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0441\u0430\u0439\u0442 \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430.<a href=\"#id7\" rel=\"noopener noreferrer nofollow\"><sup>7<\/sup><\/a> \u0421\u0430\u043c \u044f \u043d\u0435 \u0434\u0438\u0437\u0430\u0439\u043d\u0435\u0440, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u044e \u043f\u0440\u043e\u0441\u0442\u043e \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0435 \u044d\u0441\u043a\u0438\u0437\u044b \u0438\u0437 \u0434\u0440\u0443\u0433\u0438\u0445 \u043e\u043f\u0435\u043d\u0441\u043e\u0440\u0441\u043d\u044b\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u0438 \u0432\u043d\u043e\u0441\u0438\u0442\u044c \u0432 \u0438\u0445 CSS \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u043a\u0438 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u044c \u0448\u0440\u0438\u0444\u0442\u044b \u0438 \u0446\u0432\u0435\u0442\u0430).<\/p>\n<h3>FastAPI<\/h3>\n<p><a href=\"https:\/\/fastapi.tiangolo.com\/\" rel=\"noopener noreferrer nofollow\">FastAPI<\/a>\u00a0\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f API. \u041b\u0438\u0447\u043d\u043e \u043c\u043d\u0435 \u044d\u0442\u043e\u0442 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0441\u0438\u043b\u044c\u043d\u043e \u043e\u0431\u043b\u0435\u0433\u0447\u0438\u043b \u0436\u0438\u0437\u043d\u044c. \u041e\u043d \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043b\u0435\u0433\u043a\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c RESTful API \u0441 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0435\u0439, \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439 \u0438 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0435\u0439. FastAPI \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d \u043d\u0430 \u0431\u0430\u0437\u0435 Starlette \u0438 Pydantic, \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0447\u0435\u043c\u0443 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u043f\u0440\u0435\u0432\u043e\u0441\u0445\u043e\u0434\u043d\u043e\u0435 \u0431\u044b\u0441\u0442\u0440\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0438 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c \u0442\u0438\u043f\u043e\u0432. \u041e\u043d \u0431\u044b\u0441\u0442\u0440, \u043f\u0440\u043e\u0441\u0442 \u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0438 \u043b\u0435\u0433\u043a\u043e \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0441 Pydantic \u0434\u043b\u044f \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<h3>Dataclasses<\/h3>\n<p><a href=\"https:\/\/docs.python.org\/3\/library\/dataclasses.html\" rel=\"noopener noreferrer nofollow\">Dataclasses<\/a>\u00a0\u2014 \u044d\u0442\u043e \u043d\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430, \u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0441\u0430\u043c\u043e\u0433\u043e Python, \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044e\u0449\u0430\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043a\u043b\u0430\u0441\u0441\u043e\u0432, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0445 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445. \u041e\u043d\u0430 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043a\u043b\u0430\u0441\u0441\u043e\u0432, \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u0443\u044e\u0449\u0438\u0445 \u043e\u0441\u043e\u0431\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0432\u0440\u043e\u0434\u0435\u00a0<code>__init__()<\/code>,\u00a0<code>__repr__()<\/code> \u0438\u00a0<code>__eq__()<\/code>.<\/p>\n<p>\u042d\u0442\u043e \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0441\u043e\u043a\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0431\u044a\u0451\u043c \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u043e\u0433\u043e \u043a\u043e\u0434\u0430 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>\u0412\u043e\u0442 \u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"python\">from dataclasses   import dataclass  @dataclass class Point: \u00a0\u00a0\u00a0 x: int \u00a0\u00a0\u00a0 y: int  p =   Point(1,   2) print(p)\u00a0 # \u0412\u044b\u0432\u043e\u0434: Point(x=1, y=2)<\/code><\/pre>\n<p>\u0422\u0430\u043a \u0447\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043f\u0440\u043e\u0449\u0430\u0442\u044c\u0441\u044f \u0441 \u0431\u043e\u0439\u043b\u0435\u0440\u043f\u043b\u0435\u0439\u0442\u043e\u043c \u0438 \u0437\u0430\u0433\u0430\u0434\u043e\u0447\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c!<\/p>\n<h2>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u044c \u0432\u0435\u0440\u0441\u0438\u0439<\/h2>\n<h3>GitHub Actions<\/h3>\n<p>\u042f \u043b\u044e\u0431\u043b\u044e\u00a0<a href=\"https:\/\/github.com\/features\/actions\" rel=\"noopener noreferrer nofollow\">GitHub Actions<\/a>, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0437\u0430 \u0442\u043e, \u0447\u0442\u043e \u044d\u0442\u0430 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u043d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u0443\u044e \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044e \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u041e\u0421. \u0420\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0451 \u0434\u043b\u044f \u043d\u0430\u043b\u0430\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u043e\u0432 API \u0438 UI.<\/p>\n<p>\u0412\u043e\u0442 \u0442\u0438\u043f\u0438\u0447\u043d\u044b\u0439 \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u043f\u043e\u0442\u043e\u043a <code>project-api<\/code>:<\/p>\n<pre><code class=\"python\">name: CI-API  on: \u00a0 push: \u00a0\u00a0\u00a0 branches: \u00a0\u00a0\u00a0\u00a0\u00a0 - main \u00a0 pull_request: \u00a0\u00a0\u00a0 branches: \u00a0\u00a0\u00a0\u00a0\u00a0 - main  jobs: \u00a0 build-and-test: \u00a0\u00a0\u00a0 runs-on: ubuntu-latest \u00a0\u00a0\u00a0 steps: \u00a0\u00a0\u00a0\u00a0\u00a0 - name:   Checkout code \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 uses:   actions\/checkout@v3 \u00a0\u00a0\u00a0\u00a0\u00a0 - name:   Build Docker image \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 run: docker build -t project-api:ci .\/project-api \u00a0\u00a0\u00a0\u00a0\u00a0 - name:   Run tests \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 run: docker run --rm project-api:ci pytest<\/code><\/pre>\n<p><a class=\"anchor\" name=\"id18\" id=\"id18\"><\/a><\/p>\n<p>\u0417\u0430\u043c\u0435\u0442\u044c\u0442\u0435, \u0447\u0442\u043e \u0437\u0434\u0435\u0441\u044c \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u043e\u0432 \u0432 \u0438\u0437\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0441\u0440\u0435\u0434\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f Docker.<a href=\"#id8\" rel=\"noopener noreferrer nofollow\"><sup>8<\/sup><\/a> \u0418\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u041e\u0421 \u043c\u043e\u0436\u043d\u043e \u0447\u0435\u0440\u0435\u0437 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0443 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u00a0<code>runs-on<\/code>\u00a0\u043d\u0430\u00a0<code>windows-latest<\/code>\u00a0\u0438\u043b\u0438\u00a0<code>macos-latest<\/code>.<\/p>\n<h3>Dependabot<\/h3>\n<p>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u2014 \u044d\u0442\u043e \u0432\u0441\u0435\u0433\u0434\u0430 \u0431\u043e\u043b\u044c, \u043d\u043e Dependabot \u0435\u0451 \u043e\u0431\u043b\u0435\u0433\u0447\u0430\u0435\u0442. \u041e\u043d \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0438 \u0441\u043e\u0437\u0434\u0430\u0451\u0442 \u043f\u0443\u043b-\u0440\u0435\u043a\u0432\u0435\u0441\u0442\u044b \u0434\u043b\u044f \u0438\u0445 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f.<\/p>\n<p>\u0412\u043e\u0442 \u043e\u0431\u0440\u0430\u0437\u0435\u0446 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u044d\u0442\u043e\u0433\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430 \u0438\u0437 \u0444\u0430\u0439\u043b\u0430\u00a0<code>.github\/dependabot.yml<\/code>:<\/p>\n<pre><code class=\"python\">version: 2 updates:  - package-ecosystem: \"uv\" \u00a0\u00a0\u00a0 directory: \"\/\" \u00a0\u00a0\u00a0   schedule: \u00a0\u00a0\u00a0\u00a0\u00a0 interval:   \"weekly\"<\/code><\/pre>\n<h3>Gitleaks<\/h3>\n<p>\u0414\u0443\u043c\u0430\u044e, \u0447\u0442\u043e \u043e\u0434\u043d\u0438\u043c \u0438\u0437 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u043d\u0435\u0434\u043e\u0447\u0451\u0442\u043e\u0432, \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u044b\u0445 \u043f\u043e\u0432\u0440\u0435\u0434\u0438\u0442\u044c \u043d\u0430\u0448\u0435\u0439 \u0440\u0435\u043f\u0443\u0442\u0430\u0446\u0438\u0438, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0447\u0443\u0432\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432\u0440\u043e\u0434\u0435 \u043a\u043b\u044e\u0447\u0435\u0439 API \u0438\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u0435\u0439 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438. \u041a \u0441\u0447\u0430\u0441\u0442\u044c\u044e, <a href=\"https:\/\/github.com\/gitleaks\/gitleaks\" rel=\"noopener noreferrer nofollow\">Gitleaks<\/a> \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u043e\u0434\u043e\u0431\u043d\u044b\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b. \u041d\u0435 \u0432\u0438\u0436\u0443 \u043f\u0440\u0438\u0447\u0438\u043d \u0435\u0451 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c.<\/p>\n<h3>Pre-commit \u0445\u0443\u043a\u0438<\/h3>\n<p>\u042f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e <a href=\"https:\/\/pre-commit.com\/\" rel=\"noopener noreferrer nofollow\">pre-commit<\/a> \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a \u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u0434\u0430 \u043f\u0435\u0440\u0435\u0434 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u043e\u0439 \u043a\u043e\u043c\u043c\u0438\u0442\u0430. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u043a\u043e\u0434 \u0432 \u043e\u043f\u0440\u044f\u0442\u043d\u043e\u0439 \u0444\u043e\u0440\u043c\u0435 \u0438 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0442\u044c \u0441\u043e\u0431\u043b\u044e\u0434\u0435\u043d\u0438\u0435 \u0438\u043c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043e\u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u041a \u043f\u0440\u0438\u043c\u0435\u0440\u0443, \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u0432\u043e\u0442 \u044d\u0442\u043e\u0442 \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f\u00a0<a href=\"https:\/\/github.com\/astral-sh\/ruff-pre-commit\" rel=\"noopener noreferrer nofollow\">ruff-pre-commit<\/a>\u00a0\u0438\u00a0<code>gitleaks<\/code>\u00a0\u043f\u0435\u0440\u0435\u0434 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u043e\u0439 \u043a\u043e\u0434\u0430 \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439.<\/p>\n<p>\u0412\u043e\u0442 \u043e\u0431\u0440\u0430\u0437\u0435\u0446 \u043c\u043e\u0435\u0433\u043e \u0444\u0430\u0439\u043b\u0430\u00a0<code>.pre-commit-config.yaml<\/code>:<\/p>\n<pre><code class=\"python\">repos:  - repo: &lt;https:\/\/github.com\/astral-sh\/ruff-pre-commit&gt; \u00a0\u00a0\u00a0 rev: v0.12.3\u00a0 # \u0412\u0435\u0440\u0441\u0438\u044f Ruff. \u00a0\u00a0\u00a0 hooks: \u00a0 - id: ruff-check # \u0417\u0430\u043f\u0443\u0441\u043a \u043b\u0438\u043d\u0442\u0435\u0440\u0430. \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 args:   [ --fix ] \u00a0 - id: ruff-format\u00a0   # \u0417\u0430\u043f\u0443\u0441\u043a \u0444\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. - repo: &lt;https:\/\/github.com\/gitleaks\/gitleaks&gt; \u00a0\u00a0\u00a0 rev: v8.27.2 \u00a0\u00a0\u00a0   hooks: \u00a0   - id: gitleaks<\/code><\/pre>\n<h2>\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043e\u0439<\/h2>\n<p><strong>Make<\/strong><\/p>\n<p><a href=\"https:\/\/www.gnu.org\/software\/make\/\" rel=\"noopener noreferrer nofollow\">Make<\/a>\u00a0\u2014 \u044d\u0442\u043e \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0443\u0442\u0438\u043b\u0438\u0442\u0430 \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u0438 \u0437\u0430\u0434\u0430\u0447, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u043e\u0436\u043d\u043e \u043f\u043e \u043f\u0440\u0430\u0432\u0443 \u043d\u0430\u0437\u0432\u0430\u0442\u044c \u043c\u0443\u043b\u044c\u0442\u0438\u0442\u0443\u043b\u043e\u043c. \u042f \u0441 \u0435\u0433\u043e \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u043e\u0437\u0434\u0430\u044e \u043f\u0440\u043e\u0441\u0442\u044b\u0435 \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0447\u0430\u0441\u0442\u044b\u0445 \u043a\u043e\u043c\u0430\u043d\u0434 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438. \u0412\u043c\u0435\u0441\u0442\u043e \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0442\u044c \u0438 \u0432\u0432\u043e\u0434\u0438\u0442\u044c \u0434\u043b\u0438\u043d\u043d\u044b\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0442\u0435\u0441\u0442\u043e\u0432, \u0441\u0431\u043e\u0440\u043a\u0438 \u043e\u0431\u0440\u0430\u0437\u043e\u0432 Docker \u0438\u043b\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432, \u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e \u0432\u0441\u0435 \u044d\u0442\u0438 \u0437\u0430\u0434\u0430\u0447\u0438 \u0432 <code>Makefile<\/code>. \u041f\u043e\u0442\u043e\u043c \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0432\u0440\u043e\u0434\u0435\u00a0<code>make test<\/code>\u00a0\u0438\u043b\u0438\u00a0<code>make infrastructure-up<\/code>.<\/p>\n<p>\u041a\u0430\u043a \u0432\u044b \u043c\u043e\u0433\u043b\u0438 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, <code>Makefile<\/code>\u00a0\u0435\u0441\u0442\u044c \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435 <code>project-api<\/code>\u00a0\u0438 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u043c\u00a0\u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435 <code>project<\/code>:<\/p>\n<p>1.\u00a0\u00a0\u00a0<code>project\/project-api\/Makefile<\/code>: \u0434\u043b\u044f \u043b\u0438\u043d\u0442\u0438\u043d\u0433\u0430, \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f API.<\/p>\n<p>2.\u00a0\u00a0 <code>project\/Makefile<\/code>: \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b (\u0447\u0435\u0440\u0435\u0437\u00a0<code>docker-compose<\/code>).<\/p>\n<p>\u0412\u043e\u0442 \u043e\u0447\u0435\u043d\u044c \u0443\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 <code>Makefile<\/code> \u0434\u043b\u044f\u00a0<code>project-api<\/code>:<\/p>\n<pre><code class=\"python\">DIR := . #   project\/project-api\/Makefile  test: \u00a0uv run pytest  format-fix: \u00a0uv run ruff format $(DIR) \u00a0uv run ruff check --select I --fix  lint-fix: \u00a0uv run ruff check --fix<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c, \u0435\u0441\u043b\u0438 \u044f \u0437\u0430\u0445\u043e\u0447\u0443 \u043f\u0440\u043e\u0433\u043d\u0430\u0442\u044c \u0442\u0435\u0441\u0442\u044b, \u0442\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044e <code>make test<\/code>, \u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0430 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442 <code>uv run<\/code> <code>pytest\u00a0<\/code>\u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0435.<\/p>\n<p>\u0414\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0432 \u0446\u0435\u043b\u043e\u043c \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u0442\u0430\u043a\u043e\u0439\u00a0<code>Makefile<\/code>:<\/p>\n<pre><code class=\"python\">infrastructure-build: \u00a0docker compose build  infrastructure-up: \u00a0docker compose up --build -d  infrastructure-stop: \u00a0docker compose stop<\/code><\/pre>\n<p><code>make<\/code>\u00a0\u2014 \u044d\u0442\u043e \u043c\u043e\u0449\u043d\u044b\u0439 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442, \u043f\u043e\u043c\u043e\u0433\u0430\u044e\u0449\u0438\u0439 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u043f\u043e\u0442\u043e\u043a\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u0441\u0451. \u0418 \u0445\u043e\u0442\u044f \u0432\u044b\u0448\u0435 \u044f \u043f\u0440\u0438\u0432\u0451\u043b \u0432\u0435\u0441\u044c\u043c\u0430 \u0443\u043f\u0440\u043e\u0449\u0451\u043d\u043d\u044b\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u044b, \u0432\u0441\u0435\u0433\u0434\u0430 \u0435\u0441\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043b\u044e\u0431\u044b\u0435 \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u0437\u0430\u0434\u0430\u0447\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u044b.<\/p>\n<h3>Docker<\/h3>\n<p><a href=\"https:\/\/www.docker.com\/\" rel=\"noopener noreferrer nofollow\">Docker<\/a>\u00a0\u2014 \u044d\u0442\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0443\u043f\u0430\u043a\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441 \u0435\u0433\u043e \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438 \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0432\u0441\u0451 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0435 \u0434\u043b\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f: \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438, \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b, \u043a\u043e\u0434 \u0438 \u0441\u0440\u0435\u0434\u0443 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f. \u0420\u0430\u0431\u043e\u0442\u0430\u044f \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e, \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e <a href=\"https:\/\/docs.docker.com\/compose\/\" rel=\"noopener noreferrer nofollow\">Docker Compose<\/a> \u0434\u043b\u044f \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u043e\u0431\u0440\u0430\u0437\u043e\u0432 Docker \u0432 \u0435\u0434\u0438\u043d\u043e\u0439 \u0441\u0435\u0442\u0438. \u041f\u043e \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0438 \u0441 Docker, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u043c \u0441 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438, Docker Compose \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0435\u0441\u044c \u0441\u0442\u0435\u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0438 \u043e\u0442\u0434\u0435\u043b\u0438\u0442\u044c \u0435\u0433\u043e \u043e\u0442 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u0441\u0440\u0435\u0434\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043b\u0443\u0447\u0448\u0435 \u043f\u043e\u043d\u044f\u0442\u044c \u044d\u0442\u043e\u0442 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c, \u0432\u0437\u0433\u043b\u044f\u043d\u0435\u043c \u043d\u0430 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0444\u0430\u0439\u043b <code>docker-compose.yml<\/code>:<\/p>\n<pre><code class=\"python\">version: '3.8' services: \u00a0 project-api: \u00a0\u00a0\u00a0 build: \u00a0\u00a0\u00a0\u00a0\u00a0 context:   .\/project-api \u00a0\u00a0\u00a0\u00a0\u00a0 dockerfile:   Dockerfile \u00a0\u00a0\u00a0 ports: \u00a0\u00a0\u00a0\u00a0\u00a0 - \"8000:8000\" \u00a0\u00a0\u00a0 volumes: \u00a0\u00a0\u00a0\u00a0\u00a0 - .\/project-api:\/app \u00a0\u00a0\u00a0 environment: \u00a0\u00a0\u00a0\u00a0\u00a0 - ENV_VAR=value \u00a0\u00a0\u00a0 networks: \u00a0\u00a0\u00a0\u00a0\u00a0 - project-network  \u00a0 project-ui: \u00a0\u00a0\u00a0 build: \u00a0\u00a0\u00a0\u00a0\u00a0 context:   .\/project-ui \u00a0\u00a0\u00a0\u00a0\u00a0 dockerfile:   Dockerfile \u00a0\u00a0\u00a0 ports: \u00a0\u00a0\u00a0\u00a0\u00a0 - \"3000:3000\" \u00a0\u00a0\u00a0 networks: \u00a0\u00a0\u00a0\u00a0\u00a0 - project-network  networks: \u00a0 project-network: \u00a0\u00a0\u00a0   driver: bridge<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u043c\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u0434\u0432\u0430 \u0441\u0435\u0440\u0432\u0438\u0441\u0430:\u00a0<code>project-api<\/code>\u00a0\u0438\u00a0<code>project-ui<\/code>. \u041a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043d\u0438\u0445 \u0438\u043c\u0435\u0435\u0442 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0441\u0431\u043e\u0440\u043a\u0438 (<code>Dockerfile<\/code>), \u043f\u043e\u0440\u0442\u044b, \u0442\u043e\u043c\u0430 \u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u0441\u0440\u0435\u0434\u044b.<\/p>\n<p>\u0412\u043e\u0442 \u043e\u0431\u0440\u0430\u0437\u0435\u0446\u00a0<code>Dockerfile<\/code>\u00a0\u0434\u043b\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u0430\u00a0<code>project-api<\/code>:<\/p>\n<pre><code class=\"python\">FROM python:3.11-slim  # \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0445 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439.  COPY --from=ghcr.io\/astral-sh\/uv:latest \/uv \/uvx \/bin\/  WORKDIR \/app  COPY uv.lock pyproject.toml README.md .\/ RUN uv sync --frozen --no-cache  # \u0412\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a\u043e\u0434\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.  COPY src\/app app\/ COPY tools tools\/  # \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.  CMD [\"\/app\/.venv\/bin\/fastapi\", \"run\",   \"project\/infrastructure\/api.py\", \"--port\",   \"8000\", \"--host\", \"0.0.0.0\"]<\/code><\/pre>\n<p>\u041a\u0430\u043a \u0432\u0438\u0434\u0438\u0442\u0435, Dockerfile \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441 \u0431\u0430\u0437\u043e\u0432\u043e\u0433\u043e \u043e\u0431\u0440\u0430\u0437\u0430 Python, \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438, \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u0442 \u0444\u0430\u0439\u043b\u044b \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f FastAPI.<\/p>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0432\u0435\u0441\u044c \u0441\u0442\u0435\u043a \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043e\u0434\u043d\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439:<\/p>\n<pre><code>docker compose up --build -d<\/code><\/pre>\n<h2>\u0421\u043d\u043e\u0441\u043a\u0438<\/h2>\n<p><a class=\"anchor\" name=\"id1\" id=\"id1\"><\/a><\/p>\n<p>1.\u00a0\u00a0 \u041a\u0442\u043e \u043c\u0435\u043d\u044f \u0437\u043d\u0430\u0435\u0442, \u0442\u043e\u0442 \u043f\u043e\u043c\u043d\u0438\u0442, \u0447\u0442\u043e \u0440\u0430\u043d\u044c\u0448\u0435 \u044f \u0440\u0430\u0431\u043e\u0442\u0430\u043b \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043d\u0430 Java\/JavaScript\/R.\u00a0<a href=\"#id11\" rel=\"noopener noreferrer nofollow\">\u21a9<\/a><\/p>\n<p><a class=\"anchor\" name=\"id2\" id=\"id2\"><\/a><\/p>\n<p>2.\u00a0\u00a0 \u041a \u043f\u0440\u0438\u043c\u0435\u0440\u0443, \u0441\u0435\u0433\u043e\u0434\u043d\u044f\u00a0<a href=\"https:\/\/jupyter.org\/\" rel=\"noopener noreferrer nofollow\">Jupyter<\/a>\u00a0\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0432\u0441\u0435\u043c\u0438 \u0432\u0435\u0434\u0443\u0449\u0438\u043c\u0438 \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u043c\u0438 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430\u043c\u0438 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0448\u0442\u0430\u0442\u043d\u043e\u0433\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430 \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0440\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u043d\u0430\u0443\u0447\u043d\u044b\u0445 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439.\u00a0<a href=\"#id12\" rel=\"noopener noreferrer nofollow\">\u21a9<\/a><\/p>\n<p><a class=\"anchor\" name=\"id3\" id=\"id3\"><\/a><\/p>\n<p>3.\u00a0\u00a0 \u041f\u043e\u0434 \u00ab\u0433\u043e\u0442\u043e\u0432\u044b\u043c\u0438 \u043a \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d\u0443\u00bb \u044f \u043f\u043e\u0434\u0440\u0430\u0437\u0443\u043c\u0435\u0432\u0430\u044e, \u0447\u0442\u043e \u043c\u043e\u0433\u0443 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u043e\u0431\u043b\u0430\u043a\u0435 \u043a\u0430\u043a \u0435\u0441\u0442\u044c \u0431\u0435\u0437 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0432\u043d\u043e\u0441\u0438\u0442\u044c \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443.\u00a0<a href=\"#id13\" rel=\"noopener noreferrer nofollow\">\u21a9<\/a><\/p>\n<p><a class=\"anchor\" name=\"id4\" id=\"id4\"><\/a><\/p>\n<p>4.\u00a0\u00a0 \u0414\u0430, \u044f \u0437\u043d\u0430\u044e, \u0447\u0442\u043e \u043f\u043e\u0440\u043e\u0439 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430, \u0432\u043a\u043b\u044e\u0447\u0430\u044e\u0449\u0430\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0435\u0432 \u2014 \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0440\u0430\u0437\u043d\u044b\u0445 \u043a\u043e\u043c\u0430\u043d\u0434 \u043d\u0430\u0434 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 \u0447\u0430\u0441\u0442\u044f\u043c\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438\u043b\u0438 \u0434\u043b\u044f \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u043c\u0435\u0436\u0434\u0443 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u043c\u0438.\u00a0<a href=\"#id14\" rel=\"noopener noreferrer nofollow\">\u21a9<\/a><\/p>\n<p><a class=\"anchor\" name=\"id5\" id=\"id5\"><\/a><\/p>\n<p>5.\u00a0\u00a0 \u042f \u0441\u0447\u0438\u0442\u0430\u044e, \u0447\u0442\u043e \u043b\u0443\u0447\u0448\u0435 \u0438\u0437\u0431\u0435\u0433\u0430\u0442\u044c \u043f\u0440\u0435\u0436\u0434\u0435\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u044f. \u0415\u0441\u043b\u0438 \u043a\u043e\u0434\u043e\u0432\u0430\u044f \u0431\u0430\u0437\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442, \u0441\u043a\u0430\u0436\u0435\u043c, 1\/2 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u0430 \u0441\u0442\u0440\u043e\u043a \u043a\u043e\u0434\u0430, \u0442\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0441\u0435\u0442\u0435\u0432\u043e\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u044b\u0437\u043e\u0432\u043e\u0432 API) \u0441\u043e\u0437\u0434\u0430\u0441\u0442 \u0434\u043b\u044f \u0437\u0434\u0440\u0430\u0432\u043e\u043c\u044b\u0441\u043b\u044f\u0449\u0438\u0445 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u0442\u043e\u043b\u044c\u043a\u043e \u043b\u0438\u0448\u043d\u0438\u0435 \u0445\u043b\u043e\u043f\u043e\u0442\u044b.\u00a0<a href=\"#id15\" rel=\"noopener noreferrer nofollow\">\u21a9<\/a><\/p>\n<p><a class=\"anchor\" name=\"id6\" id=\"id6\"><\/a><\/p>\n<p>6.\u00a0\u00a0 \u0424\u0430\u0439\u043b\u00a0<code>pyproject.toml<\/code>\u00a0\u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u0435\u043d\u00a0<code>package.json<\/code>\u00a0\u0432 Node.js \u0438\u043b\u0438\u00a0<code>pom.xml<\/code>\u00a0\u0432 Java.\u00a0<a href=\"#id16\" rel=\"noopener noreferrer nofollow\">\u21a9<\/a><\/p>\n<p><a class=\"anchor\" name=\"id7\" id=\"id7\"><\/a><\/p>\n<p>7.\u00a0\u00a0 \u041a\u0441\u0442\u0430\u0442\u0438, \u044f \u0434\u0443\u043c\u0430\u044e, \u0447\u0442\u043e \u043a\u0430\u0436\u0434\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430 GitHub \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u043c\u0435\u0442\u044c \u0441\u0432\u043e\u0439 \u0441\u0430\u0439\u0442 (\u044d\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u043b\u0435\u0433\u043a\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437\u00a0<a href=\"https:\/\/pages.github.com\/\" rel=\"noopener noreferrer nofollow\">GitHub Pages<\/a>), \u0442\u0430\u043a \u0447\u0442\u043e \u043e\u043f\u0440\u0430\u0432\u0434\u0430\u043d\u0438\u044f \u043d\u0435 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0442\u0441\u044f.\u00a0<a href=\"#id17\" rel=\"noopener noreferrer nofollow\">\u21a9<\/a><\/p>\n<p><a class=\"anchor\" name=\"id8\" id=\"id8\"><\/a><\/p>\n<p>8.   \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 Docker \u0434\u043b\u044f \u043d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u043e\u0439 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c \u043f\u0430\u0440\u0438\u0442\u0435\u0442 \u0441 \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d-\u0441\u0440\u0435\u0434\u0430\u043c\u0438, \u0445\u043e\u0442\u044f \u043c\u043e\u0436\u0435\u0442 \u0432\u043d\u043e\u0441\u0438\u0442\u044c \u0438\u0437\u0434\u0435\u0440\u0436\u043a\u0438 \u043d\u0430 \u0441\u0442\u0430\u0440\u0442\u0435. \u041a\u043e\u043c\u043f\u0440\u043e\u043c\u0438\u0441\u0441\u044b, \u043a\u0443\u0434\u0430 \u0431\u0435\u0437 \u043d\u0438\u0445.\u00a0<a href=\"#id18\" rel=\"noopener noreferrer nofollow\">\u21a9<\/a><\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/930234\/\"> https:\/\/habr.com\/ru\/articles\/930234\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><\/figure>\n<p>\u0421 \u043f\u043e\u043b\u0433\u043e\u0434\u0430 \u043d\u0430\u0437\u0430\u0434 \u044f \u043d\u0430\u0447\u0430\u043b \u0447\u0430\u0449\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f <a href=\"https:\/\/www.python.org\/\" rel=\"noopener noreferrer nofollow\">Python<\/a>. \u041f\u043e\u0447\u0435\u043c\u0443? \u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u0438\u0437-\u0437\u0430 \u0418\u0418. \u041b\u0438\u0447\u043d\u043e \u0434\u043b\u044f \u043c\u0435\u043d\u044f \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u044d\u0442\u0430 \u0441\u0444\u0435\u0440\u0430 \u0441\u0432\u044f\u0437\u0430\u043d\u0430 \u0441 \u043e\u0447\u0435\u043d\u044c \u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 <s>\u0434\u0435\u043d\u044c\u0433\u0430\u043c\u0438<\/s> \u043f\u0435\u0440\u0441\u043f\u0435\u043a\u0442\u0438\u0432\u0430\u043c\u0438 \u0432\u043e \u0432\u0441\u0435\u0445 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f\u0445. \u0410 \u043a\u0430\u043a\u043e\u0439 \u044f\u0437\u044b\u043a \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u0430\u043c\u044b\u043c \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u043c \u0434\u043b\u044f \u0418\u0418? \u0414\u0430-\u0434\u0430, \u044d\u0442\u043e\u0442 \u0441\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u043d\u044b\u0440\u0430. <\/p>\n<p>\u042f \u0443\u0436\u0435 \u043f\u0438\u0441\u0430\u043b \u043d\u0430 Python, \u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u044b. \u041a \u043f\u0440\u0438\u043c\u0435\u0440\u0443, <a href=\"https:\/\/github.com\/cesarsotovalero\/cesarsotovalero.github.io\/blob\/1fb2efe0577719a72fdf7d5bdf2a8d4d51ee58c5\/scripts\/fetch_all_youtube_videos.py\" rel=\"noopener noreferrer nofollow\">\u0432\u043e\u0442 \u044d\u0442\u043e\u0442<\/a> \u0441\u043a\u0440\u0435\u0439\u043f\u0438\u0442 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0432\u0441\u0435\u0445 \u0432\u0438\u0434\u0435\u043e \u0441 <a href=\"https:\/\/www.youtube.com\/channel\/UCR4rI98w6-MqYoCS6jR9LGg\" rel=\"noopener noreferrer nofollow\">\u043c\u043e\u0435\u0433\u043e \u043a\u0430\u043d\u0430\u043b\u0430 \u043d\u0430 YouTube<\/a>. \u0421\u043e\u0431\u0440\u0430\u043d\u043d\u044b\u0435 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0432\u044b\u0432\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u0432\u0438\u0434\u0435 <a href=\"https:\/\/github.com\/cesarsotovalero\/cesarsotovalero.github.io\/blob\/1fb2efe0577719a72fdf7d5bdf2a8d4d51ee58c5\/_data\/youtube-videos.json\" rel=\"noopener noreferrer nofollow\">\u0444\u0430\u0439\u043b\u0430 JSON<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u0434\u043b\u044f \u043f\u043e\u043a\u0430\u0437\u0430 \u043a\u0440\u0430\u0441\u0438\u0432\u043e\u0439 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 \u0440\u043e\u043b\u0438\u043a\u043e\u0432 \u043d\u0430 <a href=\"https:\/\/www.cesarsotovalero.net\/youtube\" rel=\"noopener noreferrer nofollow\">\u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u0438\u0447\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0435<\/a>. \u041a\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0432\u0438\u0434\u0435\u0442\u044c \u0437\u0434\u0435\u0441\u044c, \u044d\u0442\u043e\u0442 \u0441\u043a\u0440\u043e\u043c\u043d\u044b\u0439 \u0441\u043a\u0440\u0438\u043f\u0442 \u0447\u0435\u0440\u0435\u0437 GitHub Actions \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u0441\u043e\u043b\u043e-\u0440\u0435\u0436\u0438\u043c\u0435 \u043a\u0430\u0436\u0434\u044b\u0439 \u043f\u043e\u043d\u0435\u0434\u0435\u043b\u044c\u043d\u0438\u043a. \u041f\u0440\u043e\u0441\u0442\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0451 \u044d\u0442\u043e \u043d\u0430 Python \u043a\u0443\u0434\u0430 \u043f\u0440\u043e\u0449\u0435, \u0447\u0435\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0442\u043e\u0433\u043e \u0436\u0435 Bash. \u0418 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0438\u0437-\u0437\u0430 \u0431\u043e\u043b\u0435\u0435 \u0434\u0440\u0443\u0436\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0433\u043e \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441\u0430, \u043d\u043e \u0438 \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0435\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0430\u0442\u043e\u0440 \u043d\u0430\u0442\u0438\u0432\u043d\u043e \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u043d \u0432\u043e \u0432\u0441\u0435 \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0442\u0438\u0432\u044b Unix. \u0420\u0430\u0437\u0432\u0435 \u043d\u0435 \u043a\u0440\u0443\u0442\u043e?<\/p>\n<p><a class=\"anchor\" name=\"id11\" id=\"id11\"><\/a><\/p>\n<p>\u0422\u0430\u043a \u0447\u0442\u043e, \u0434\u0430, Python \u0441\u0438\u043b\u0451\u043d \u0438 \u043e\u0442\u043b\u0438\u0447\u043d\u043e \u0441\u043e\u0447\u0435\u0442\u0430\u0435\u0442\u0441\u044f \u0441 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0451\u043d\u043d\u044b\u043c \u0441\u0435\u0433\u043e\u0434\u043d\u044f <a href=\"https:\/\/code.visualstudio.com\/\" rel=\"noopener noreferrer nofollow\">VSCode<\/a>. \u041d\u043e \u0432\u0441\u0435\u0440\u044c\u0451\u0437 \u044f \u043d\u0430\u0447\u0430\u043b \u043a \u043d\u0435\u043c\u0443 \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u044c\u0441\u044f \u043b\u0438\u0448\u044c \u043d\u0435\u0434\u0430\u0432\u043d\u043e<a href=\"#id1\" rel=\"noopener noreferrer nofollow\"><sup>1<\/sup><\/a>, \u043a\u043e\u0433\u0434\u0430 \u0440\u0435\u0448\u0438\u043b \u0437\u0430\u043d\u044f\u0442\u044c\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u043d\u0430 \u0431\u0430\u0437\u0435 \u0418\u0418 (RAG, \u0430\u0433\u0435\u043d\u0442\u043e\u0432, \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u0445 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0438 \u043f\u0440\u043e\u0447\u0435\u0433\u043e) \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447. \u0422\u043e\u0433\u0434\u0430 \u044f \u043f\u043e\u043d\u044f\u043b, \u0447\u0442\u043e \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e \u043e\u0442 \u0442\u043e\u0433\u043e, \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u043e\u043d \u0432\u0430\u043c \u0438\u043b\u0438 \u043d\u0435\u0442, \u0434\u043b\u044f \u0432\u0441\u0435\u0433\u043e \u044d\u0442\u043e\u0433\u043e \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c \u0432\u044b\u0431\u043e\u0440\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u0438\u043c\u0435\u043d\u043d\u043e Python.<\/p>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u044f \u0440\u0435\u0448\u0438\u043b \u0432\u0437\u044f\u0442\u044c\u0441\u044f \u0437\u0430 \u043d\u0435\u0433\u043e \u0432\u0441\u0435\u0440\u044c\u0451\u0437 \u0438 \u043a \u0441\u0432\u043e\u0435\u043c\u0443 \u0443\u0434\u0438\u0432\u043b\u0435\u043d\u0438\u044e \u0432\u044b\u044f\u0441\u043d\u0438\u043b, \u0447\u0442\u043e Python \u0432\u043c\u0435\u0441\u0442\u0435 \u0441\u043e \u0432\u0441\u0435\u0439 \u043e\u043a\u0440\u0443\u0436\u0430\u044e\u0449\u0435\u0439 \u0435\u0433\u043e \u0441\u0440\u0435\u0434\u043e\u0439 \u0437\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0434\u0435\u0441\u044f\u0442\u0438\u043b\u0435\u0442\u0438\u044f \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0440\u0430\u0437\u0432\u0438\u043b\u0441\u044f. <\/p>\n<p>\u0412\u043e\u0442 \u043b\u0438\u0448\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0439 \u0442\u043e\u043c\u0443:<\/p>\n<p><a class=\"anchor\" name=\"id12\" id=\"id12\"><\/a><\/p>\n<ol>\n<li>\n<p>\u0412\u043e\u043a\u0440\u0443\u0433 \u044d\u0442\u043e\u0433\u043e \u044f\u0437\u044b\u043a\u0430 \u0432\u044b\u0441\u0442\u0440\u043e\u0438\u043b\u0430\u0441\u044c \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u0430\u044f \u044d\u043a\u043e\u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a \u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438\/\u0430\u043d\u0430\u043b\u0438\u0437\u0430 \u0434\u0430\u043d\u043d\u044b\u0445.<a href=\"#id2\" rel=\"noopener noreferrer nofollow\"><sup>2<\/sup><\/a><\/p>\n<\/li>\n<li>\n<p>Python \u0441\u0442\u0430\u043b \u0431\u044b\u0441\u0442\u0440\u0435\u0435, \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440\u043e\u0432 \u0432\u0440\u043e\u0434\u0435 Cython.<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 Python \u043f\u0440\u043e\u0434\u0435\u043b\u0430\u043b\u0438 \u0441\u0442\u0430\u0440\u0430\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443, \u0441\u043a\u0440\u044b\u0432 \u0435\u0433\u043e \u043b\u0435\u0433\u0430\u0441\u0438-\u0443\u0440\u043e\u0434\u0441\u0442\u0432\u043e (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>__init__<\/code>,\u00a0<code>__new__<\/code> \u0438 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0435 \u0438\u0441\u043a\u0430\u0436\u0435\u043d\u0438\u044f), \u0441\u0434\u0435\u043b\u0430\u0432 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 \u0431\u043e\u043b\u0435\u0435 \u0443\u0434\u043e\u0431\u043d\u044b\u043c \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 <s>\u0441 \u0445\u043e\u0440\u043e\u0448\u0438\u043c \u0432\u043a\u0443\u0441\u043e\u043c<\/s>.<\/p>\n<\/li>\n<\/ol>\n<p>\u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0432\u0441\u0435\u043c \u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u044b\u043c \u0438 \u043c\u043d\u043e\u0433\u0438\u043c \u0434\u0440\u0443\u0433\u0438\u043c \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u043a\u0430\u043c, \u0442\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u044d\u0442\u0438\u043c \u044f\u0437\u044b\u043a\u043e\u043c \u043c\u043d\u0435 \u0441\u0442\u0430\u043b\u043e \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u043f\u0440\u0438\u044f\u0442\u043d\u043e.<\/p>\n<p><a class=\"anchor\" name=\"id13\" id=\"id13\"><\/a><\/p>\n<p>\u0422\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435 \u0437\u0430 \u044d\u0442\u0438 \u043f\u043e\u043b\u0433\u043e\u0434\u0430 \u044f \u0442\u0430\u043a\u0436\u0435 \u0443\u0437\u043d\u0430\u043b, \u0447\u0442\u043e \u043f\u043e-\u043f\u0440\u0435\u0436\u043d\u0435\u043c\u0443 \u0432\u0435\u043b\u0438\u043a\u0430 \u0440\u0430\u0437\u043d\u0438\u0446\u0430 \u043c\u0435\u0436\u0434\u0443 \u043f\u0440\u0438\u0433\u043e\u0434\u043d\u043e\u0441\u0442\u044c\u044e Python \u0434\u043b\u044f \u043e\u0431\u044b\u0447\u043d\u044b\u0445 \u0440\u0430\u0431\u043e\u0447\u0438\u0445 \u043f\u043e\u0442\u043e\u043a\u043e\u0432 \u043d\u0430 \u0431\u0430\u0437\u0435 \u0431\u043b\u043e\u043a\u043d\u043e\u0442\u043e\u0432 Jupyter \u0438\u043b\u0438 \u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432 \u0438 \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0433\u043e\u0442\u043e\u0432\u044b\u0445 \u043a \u043f\u0440\u043e\u0434\u0430\u043a\u0448\u043d\u0443<a href=\"#id3\" rel=\"noopener noreferrer nofollow\"><sup>3<\/sup><\/a> \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439.<\/p>\n<p>\u0422\u0430\u043a \u0447\u0442\u043e \u0432 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043e\u0431 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u0445, \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u0445, \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f\u0445 \u0438 \u043f\u0440\u043e\u0447\u0438\u0445 \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f\u0445 \u0434\u043b\u044f \u044f\u0437\u044b\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u0430\u0440\u044f\u0442 \u043c\u043d\u0435 \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u043e, \u0438 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439.<\/p>\n<p>\u26a0\ufe0f \u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u043d\u0430 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u044e \u043b\u0438\u0447\u043d\u043e \u044f. \u0415\u0441\u043b\u0438 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u043e\u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u043e\u0432\u0430\u0442\u044c \u043c\u043d\u0435 \u043a\u0430\u043a\u0438\u0435-\u0442\u043e \u0434\u0440\u0443\u0433\u0438\u0435 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f, \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u0435\u0441\u044c \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445. <\/p>\n<blockquote>\n<p><em>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/em><strong>:<\/strong>\u00a0\u0442\u0430\u043a \u0432\u044b\u0448\u043b\u043e, \u0447\u0442\u043e \u043c\u043e\u044f \u0441\u0442\u0430\u0442\u044c\u044f \u043d\u0430\u0431\u0440\u0430\u043b\u0430 \u043d\u0430 Hacker News <a href=\"https:\/\/news.ycombinator.com\/item?id=44579717\" rel=\"noopener noreferrer nofollow\">\u0431\u043e\u043b\u0435\u0435 680 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0435\u0432<\/a>. \u0415\u0449\u0451 \u0440\u0430\u0437 \u0443\u0431\u0435\u0436\u0434\u0430\u044e\u0441\u044c \u0432 \u043d\u0435\u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0443\u0435\u043c\u043e\u0441\u0442\u0438 \u0436\u0438\u0437\u043d\u0438.<\/p>\n<\/blockquote>\n<h2>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/h2>\n<p><a class=\"anchor\" name=\"id14\" id=\"id14\"><\/a><\/p>\n<p>\u042f \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u044e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0441\u0432\u043e\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 Python \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043c\u043e\u043d\u043e\u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0432 \u043d\u0435\u0433\u043e \u0438 \u0431\u044d\u043a\u0435\u043d\u0434, \u0438 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434.<a href=\"#id4\" rel=\"noopener noreferrer nofollow\"><sup>4<\/sup><\/a><\/p>\n<p>\u041f\u043e\u0447\u0435\u043c\u0443?<\/p>\n<ol>\n<li>\n<p>\u0418\u0437-\u0437\u0430 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0435\u0439 \u0441 \u0437\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u043d\u0438\u0435\u043c: \u043c\u043d\u0435 \u043d\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f, \u043a\u043e\u0433\u0434\u0430 \u0447\u0430\u0441\u0442\u0438 \u043a\u043e\u0434\u0430 \u0440\u0430\u0437\u0431\u0440\u043e\u0441\u0430\u043d\u044b \u043f\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f\u043c (\u044d\u0442\u043e \u044f\u0432\u043d\u043e \u043d\u0435 \u043e\u0431\u043b\u0435\u0433\u0447\u0430\u0435\u0442 \u043f\u043e\u0438\u0441\u043a). <\/p>\n<\/li>\n<li>\n<p>\u041d\u0430\u043b\u0438\u0447\u0438\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0435\u0432 \u0437\u0430\u0447\u0430\u0441\u0442\u0443\u044e \u0438\u0437\u043b\u0438\u0448\u043d\u0435. \u042f \u0440\u0430\u0431\u043e\u0442\u0430\u044e \u043e\u0434\u0438\u043d \u0438 \u0441\u0447\u0438\u0442\u0430\u044e, \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u043f\u0440\u043e\u0435\u043a\u0442 \u0434\u043e\u0440\u0430\u0441\u0442\u0451\u0442 \u0434\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u0438 \u0435\u0433\u043e \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043d\u0430 \u0440\u0430\u0437\u043d\u044b\u0435 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438, \u044d\u0442\u043e \u0443\u0436\u0435 \u0431\u0443\u0434\u0435\u0442 \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u043e \u0447\u0440\u0435\u0437\u043c\u0435\u0440\u043d\u043e\u043c \u0443\u0441\u043b\u043e\u0436\u043d\u0435\u043d\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0443 \u0438 \u044f \u0431\u0430\u043d\u0430\u043b\u044c\u043d\u043e \u043b\u0435\u043d\u0438\u0432\u044b\u0439, \u0441\u0442\u0430\u0440\u0430\u044e\u0441\u044c \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0443\u0441\u043b\u043e\u0436\u043d\u044f\u0442\u044c \u2014 \u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u0443\u044e, \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u044e, \u043f\u0430\u043a\u0443\u044e \u0432 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b \u0438 \u0440\u0430\u0437\u0432\u0451\u0440\u0442\u044b\u0432\u0430\u044e \u0438\u0437 \u043e\u0434\u043d\u043e\u0433\u043e \u0440\u0430\u0441\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<a href=\"#id5\" rel=\"noopener noreferrer nofollow\"><sup>5<\/sup><\/a><\/p>\n<\/li>\n<\/ol>\n<p>\u041c\u043d\u0435 \u0431\u044b \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u0438\u043c\u0435\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u044b \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043b \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u043d\u043e \u043f\u043e\u043a\u0430 \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u044f \u043d\u0435 \u043d\u0430\u0448\u0451\u043b. \u0420\u0430\u043d\u044c\u0448\u0435 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b <a href=\"https:\/\/cookiecutter-data-science.drivendata.org\/\" rel=\"noopener noreferrer nofollow\">CCDS<\/a> \u2014 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442 \u0434\u043b\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432 \u0441\u0444\u0435\u0440\u0435 \u0434\u0430\u0442\u0430-\u0441\u0430\u0439\u0435\u043d\u0441. \u041e\u043d \u043e\u0447\u0435\u043d\u044c \u0445\u043e\u0440\u043e\u0448, \u043d\u043e \u043d\u0435 \u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d \u043d\u0430 \u0444\u0443\u043b\u0441\u0442\u0435\u043a \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432.<\/p>\n<p>\u0412\u043e\u0442 \u0442\u0438\u043f\u0438\u0447\u043d\u0430\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0441 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u043e\u0439 \u0444\u0440\u043e\u043d\u0442-\u0431\u044d\u043a (\u0447\u0443\u0442\u044c \u043f\u043e\u0437\u0436\u0435 \u044f \u043f\u0440\u043e\u0431\u0435\u0433\u0443\u0441\u044c \u043f\u043e \u043a\u0430\u0436\u0434\u043e\u0439 \u0435\u0451 \u0447\u0430\u0441\u0442\u0438):<\/p>\n<pre><code>project\/ \u2502 \u251c\u2500\u2500 .github\/ # \u0420\u0430\u0431\u043e\u0447\u0438\u0435 \u043f\u043e\u0442\u043e\u043a\u0438 GitHub Actions \u0434\u043b\u044f \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u043e\u0432 CI\/CD. \u2502\u00a0\u00a0 \u251c\u2500\u2500 workflows\/ # \u041a\u0430\u0442\u0430\u043b\u043e\u0433 \u0441 \u0444\u0430\u0439\u043b\u0430\u043c\u0438 YAML \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0440\u0430\u0431\u043e\u0447\u0438\u0445 \u043f\u043e\u0442\u043e\u043a\u043e\u0432. \u2502\u00a0\u00a0 \u2514\u2500\u2500 dependabot.yml # \u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f Dependabot \u0434\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438. \u2502 \u251c\u2500\u2500 .vscode\/ # \u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f VSCode \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u2502\u00a0\u00a0 \u251c\u2500\u2500 launch.json # \u041e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u044b\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0434\u043b\u044f VSCode. \u2502\u00a0\u00a0 \u2514\u2500\u2500 settings.json # \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0434\u043b\u044f VSCode. \u2502 \u251c\u2500\u2500 docs\/ # \u0421\u0430\u0439\u0442 \u0438 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f (\u0441\u0442\u0430\u0442\u0438\u0447\u043d\u044b\u0439 SPA \u0441 MkDocs). \u2502 \u251c\u2500\u2500 project-api\/ # API \u0431\u044d\u043a\u0435\u043d\u0434\u0430 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0438 \u0438 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447. \u2502\u00a0\u00a0 \u251c\u2500\u2500 data\/ # \u041a\u0430\u0442\u0430\u043b\u043e\u0433 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u0442\u0430\u0441\u0435\u0442\u043e\u0432 \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u0441\u0442\u0430\u0442\u0438\u0447\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432. \u2502\u00a0\u00a0 \u251c\u2500\u2500 notebooks\/ # \u0411\u043b\u043e\u043a\u043d\u043e\u0442\u044b Jupyter \u0434\u043b\u044f \u043e\u043f\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u044b\u0445 \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u043e\u0432 \u0438 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u2502\u00a0\u00a0 \u251c\u2500\u2500 tools\/ # \u0412\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0440\u0430\u0437\u0432\u0451\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f. \u2502\u00a0\u00a0 \u251c\u2500\u2500 src\/ # \u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u0434\u043b\u044f \u0431\u044d\u043a\u0435\u043d\u0434-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 app\/ # \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043a\u043e\u0434 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 tests\/ # \u041c\u043e\u0434\u0443\u043b\u044c\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b \u0434\u043b\u044f \u0431\u044d\u043a\u0435\u043d\u0434\u0430. \u2502\u00a0\u00a0 \u2502 \u2502\u00a0\u00a0 \u251c\u2500\u2500 .dockerignore # \u0423\u043a\u0430\u0437\u0430\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u043e\u0432, \u0438\u0441\u043a\u043b\u044e\u0447\u0430\u0435\u043c\u044b\u0445 \u0438\u0437 \u0441\u0431\u043e\u0440\u043e\u043a Docker. \u2502\u00a0\u00a0 \u251c\u2500\u2500 .python-version # \u0423\u043a\u0430\u0437\u0430\u043d\u0438\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 Python \u0434\u043b\u044f pyenv. \u2502\u00a0\u00a0 \u251c\u2500\u2500 Dockerfile # \u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f Docker \u0434\u043b\u044f \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u0431\u044d\u043a\u0435\u043d\u0434\u0430. \u2502\u00a0\u00a0 \u251c\u2500\u2500 Makefile # \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438, \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0440\u0430\u0437\u0432\u0451\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f. \u2502\u00a0\u00a0 \u251c\u2500\u2500 pyproject.toml # \u0424\u0430\u0439\u043b \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 Python. \u2502\u00a0\u00a0 \u251c\u2500\u2500 README.md # \u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0434\u043b\u044f API \u0431\u044d\u043a\u0435\u043d\u0434\u0430. \u2502\u00a0\u00a0 \u2514\u2500\u2500 uv.lock # Lockfile, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439, \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0445 UV. \u2502 \u251c\u2500\u2500 project-ui\/ # UI \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430 \u0434\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 (Next.js, React \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435). \u2502 \u251c\u2500\u2500 .gitignore # \u0413\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b gitignore \u0434\u043b\u044f \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f. \u251c\u2500\u2500 .pre-commit-config.yaml # \u041a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u0434\u043b\u044f pre-commit \u0445\u0443\u043a\u043e\u0432. \u251c\u2500\u2500 CONTRIBUTING.md # \u0420\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u0430 \u0434\u043b\u044f \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u043e\u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0430. \u251c\u2500\u2500 docker-compose.yml # \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 Docker Compose \u0434\u043b\u044f \u043c\u0443\u043b\u044c\u0442\u0438-\u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u043d\u044b\u0445 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0439. \u251c\u2500\u2500 LICENSE # \u041b\u0438\u0446\u0435\u043d\u0437\u0438\u043e\u043d\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 (\u044f \u0432\u0441\u0435\u0433\u0434\u0430 \u0432\u044b\u0431\u0438\u0440\u0430\u044e MIT). \u251c\u2500\u2500 Makefile # \u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0437\u0430\u0434\u0430\u0447\u0438 \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438, \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438 \u0434\u0435\u043f\u043b\u043e\u044f. \u2514\u2500\u2500 README.md # \u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430 (\u0435\u0433\u043e \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e).<\/code><\/pre>\n<p>\u041c\u043e\u0439 <code>project<\/code> \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u0430\u0434\u0440\u0435\u0441\u043e\u043c \u043a\u043e\u0440\u043d\u0435\u0432\u043e\u0433\u043e \u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430 \u0438 \u0438\u043c\u0435\u043d\u0435\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f GitHub. \u041c\u043d\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u0434\u0430\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u043c \u043a\u043e\u0440\u043e\u0442\u043a\u0438\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u0434\u043b\u0438\u043d\u043e\u0439 \u0434\u043e 10 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432, \u0431\u0435\u0437 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f <code>snake_case<\/code> \u2014 \u043c\u0435\u043d\u044f \u0432\u043f\u043e\u043b\u043d\u0435 \u0443\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442 \u0440\u0430\u0437\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0434\u0435\u0444\u0438\u0441\u0430\u043c\u0438. \u0417\u0430\u043c\u0435\u0442\u044c\u0442\u0435, \u0447\u0442\u043e \u043f\u0440\u043e\u0435\u043a\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0441\u0430\u043c\u043e\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u044b\u043c, \u0442\u043e \u0435\u0441\u0442\u044c \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044e, \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u0441\u0431\u043e\u0440\u043a\u0438\/\u0434\u0435\u043f\u043b\u043e\u044f \u0438 \u043b\u044e\u0431\u044b\u0435 \u0434\u0440\u0443\u0433\u0438\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0434\u043b\u044f \u0435\u0433\u043e \u0430\u0432\u0442\u043e\u043d\u043e\u043c\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u0432\u0451\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>\u0412\u0430\u0436\u043d\u043e \u043d\u0435 \u043f\u0440\u043e\u0434\u0435\u043b\u044b\u0432\u0430\u0442\u044c \u0432 <code>project-ui<\/code> \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u044d\u0442\u0430\u043f\u043e\u0432 \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445, \u0442\u0430\u043a \u043a\u0430\u043a \u044f \u0441\u0442\u0430\u0440\u0430\u044e\u0441\u044c \u043e\u0442\u0434\u0435\u043b\u044f\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443 \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0430 \u043e\u0442 \u0437\u0430\u0434\u0430\u0447 \u0431\u044d\u043a\u0435\u043d\u0434\u0430. \u0412\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u043e\u0433\u043e \u044f \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a \u0441\u0435\u0440\u0432\u0435\u0440\u0443 <code>project-api<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 Python-\u043a\u043e\u0434. \u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043c\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043b\u0451\u0433\u043a\u0438\u043c, \u0434\u0435\u043b\u0435\u0433\u0438\u0440\u0443\u044f \u0432\u0441\u044e \u043e\u0441\u043d\u043e\u0432\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u0438 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0443 \u0441\u0435\u0440\u0432\u0435\u0440\u0443.<\/p>\n<p>\u0412 <code>project-api\/src\/app<\/code> \u0435\u0441\u0442\u044c \u0444\u0430\u0439\u043b\u00a0<code>__init__.py<\/code>, \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u0439, \u0447\u0442\u043e <code>app<\/code> \u2014 \u044d\u0442\u043e \u043c\u043e\u0434\u0443\u043b\u044c Python (\u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0437 \u0434\u0440\u0443\u0433\u0438\u0445 \u043c\u043e\u0434\u0443\u043b\u0435\u0439).<\/p>\n<h2>\u0418\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b Python<\/h2>\n<h3>uv<\/h3>\n<p>\u0414\u043b\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0430\u043a\u0435\u0442\u0430\u043c\u0438 \u0438 \u0441\u0431\u043e\u0440\u043a\u0438 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u00a0<a href=\"https:\/\/github.com\/astral-sh\/uv\" rel=\"noopener noreferrer nofollow\">uv<\/a>. \u042d\u0442\u043e\u0433\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430 \u043c\u043d\u0435 \u0432\u043f\u043e\u043b\u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u0434\u043b\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0438\u043c\u0438. <\/p>\n<p>\u0412\u043e\u0442 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u043b\u044f \u0435\u0433\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438:<\/p>\n<pre><code># \u0413\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u0430\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 uv, \u0435\u0441\u043b\u0438 \u043e\u043d \u0435\u0449\u0451 \u043d\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d.\u00a0  curl -sSfL &lt;https:\/\/astral.sh\/install.sh&gt; | sh  # \u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u043f\u0440\u043e\u0435\u043a\u0442\u0430 (\u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 .gitignore, .python-version, pyproject.toml \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435).  uv init   project-api  # \u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0432 \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 pyproject.toml.  uv add --dev pytest ruff pre-commit mkdocs gitleaks   fastapi pydantic  # \u0423\u043a\u0430\u0437\u0430\u043d\u0438\u0435 \u0432 Lockfile \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0445 \u0432\u0435\u0440\u0441\u0438\u0439 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 (\u0441\u043e\u0437\u0434\u0430\u0451\u0442 .venv, \u0435\u0441\u043b\u0438 \u0435\u0449\u0451 \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u043d).  uv sync  # \u0410\u043a\u0442\u0438\u0432\u0430\u0446\u0438\u044f .venv.  uv venv   activate<\/code><\/pre>\n<p><a class=\"anchor\" name=\"id16\" id=\"id16\"><\/a><\/p>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u0441\u0430\u043c\u044b\u043c \u0432\u0430\u0436\u043d\u044b\u043c \u0434\u043b\u044f <code>uv<\/code> \u0444\u0430\u0439\u043b\u043e\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f\u00a0<code>pyproject.toml<\/code>.<a href=\"#id6\" rel=\"noopener noreferrer nofollow\"><sup>6<\/sup><\/a>\u00a0\u041e\u043d \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043c\u0435\u0442\u0430\u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0445 \u0434\u043b\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u0430.<\/p>\n<h3>Ruff<\/h3>\n<p><a href=\"https:\/\/github.com\/astral-sh\/ruff\" rel=\"noopener noreferrer nofollow\">Ruff<\/a> \u043c\u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f. \u042d\u0442\u043e \u0441\u0443\u043f\u0435\u0440\u0431\u044b\u0441\u0442\u0440\u044b\u0439 \u043b\u0438\u043d\u0442\u0435\u0440 \u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u0435\u0440 \u043a\u043e\u0434\u0430 \u0434\u043b\u044f Python, \u043f\u043e\u043c\u043e\u0433\u0430\u044e\u0449\u0438\u0439 \u043b\u0435\u043d\u0438\u0432\u044b\u043c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c \u0432\u0440\u043e\u0434\u0435 \u043c\u0435\u043d\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u044c \u043a\u043e\u0434\u043e\u0432\u044b\u0435 \u0431\u0430\u0437\u044b \u0432 \u0447\u0438\u0441\u0442\u043e\u043c \u0438 \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u0435\u043c\u043e\u043c \u0432\u0438\u0434\u0435. \u041e\u043d \u0441\u043e\u0432\u043c\u0435\u0449\u0430\u0435\u0442 \u0432 \u0441\u0435\u0431\u0435 <code>isort<\/code>,\u00a0<code>flake8<\/code>,\u00a0<code>autoflake<\/code> \u0438 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0435 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0435 \u0447\u0435\u0440\u0435\u0437 \u0435\u0434\u0438\u043d\u044b\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043a\u043e\u043c\u0430\u043d\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438:<\/p>\n<pre><code># \u041b\u0438\u043d\u0442\u0438\u043d\u0433 \u0432\u0441\u0435\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u0432 \/path\/to\/code (\u0438 \u0432\u0441\u0435\u0445 \u043f\u043e\u0434\u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430\u0445).  ruff check   path\/to\/code\/\u00a0  # \u0424\u043e\u0440\u043c\u0430\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u0441\u0435\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u0432 \/path\/to\/code (\u0438 \u0432\u0441\u0435\u0445 \u043f\u043e\u0434\u043a\u0430\u0442\u0430\u043b\u043e\u0433\u0430\u0445).  ruff   format path\/to\/code\/<\/code><\/pre>\n<p>Ruff \u0448\u0442\u0430\u0442\u043d\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0440\u0443\u043a\u043e\u0432\u043e\u0434\u0441\u0442\u0432\u043e \u043f\u043e \u0441\u0442\u0438\u043b\u044e <a href=\"https:\/\/pep8.org\/\" rel=\"noopener noreferrer nofollow\">PEP 8<\/a>.<\/p>\n<h3>ty<\/h3>\n<p><a href=\"https:\/\/github.com\/astral-sh\/ty\" rel=\"noopener noreferrer nofollow\">ty<\/a>\u00a0\u2014 \u044d\u0442\u043e \u043c\u043e\u0434\u0443\u043b\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0442\u0438\u043f\u043e\u0432 \u0434\u043b\u044f Python. \u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043e\u043d \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e \u0441\u043e\u0447\u0435\u0442\u0430\u0435\u0442\u0441\u044f \u0441 <a href=\"https:\/\/docs.python.org\/3\/library\/typing.html\" rel=\"noopener noreferrer nofollow\">typing<\/a>, \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u043c \u043c\u043e\u0434\u0443\u043b\u0435\u043c \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0442\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u0438. \u0414\u0443\u043c\u0430\u044e, \u0447\u0442\u043e \u0442\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u044f \u0440\u0435\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u043c\u043d\u0435 \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0438 \u0442\u0438\u043f\u043e\u0432 \u043d\u0430 \u0440\u0430\u043d\u043d\u0438\u0445 \u0441\u0442\u0430\u0434\u0438\u044f\u0445 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438. \u042f \u043d\u0435 \u0431\u043e\u044e\u0441\u044c \u043f\u0438\u0441\u0430\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434 \u0438 \u0441 \u0433\u043e\u0442\u043e\u0432\u043d\u043e\u0441\u0442\u044c\u044e \u0438\u0434\u0443 \u043d\u0430 \u044d\u0442\u043e, \u0435\u0441\u043b\u0438 \u0442\u0430\u043a\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043f\u043e\u0432\u044b\u0448\u0430\u0435\u0442 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b, \u043f\u043e\u043f\u0443\u0442\u043d\u043e \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u044f \u0432\u0435\u0440\u043e\u044f\u0442\u043d\u043e\u0441\u0442\u044c \u043e\u0448\u0438\u0431\u043e\u043a \u0432 \u0441\u0440\u0435\u0434\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f. <\/p>\n<blockquote>\n<p><em>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u0435<\/em>: \u043d\u0430 \u043c\u043e\u043c\u0435\u043d\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0442\u0430\u0442\u044c\u0438 <code>ty<\/code> \u0435\u0449\u0451 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430 \u0440\u0430\u043d\u043d\u0435\u0439 \u0441\u0442\u0430\u0434\u0438\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u043d\u043e \u0437\u0430 \u0432\u0440\u0435\u043c\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u044d\u0442\u043e\u0439 \u0443\u0442\u0438\u043b\u0438\u0442\u044b \u044f \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u043e\u0449\u0443\u0442\u0438\u043c\u044b\u0445 \u043d\u0435\u0434\u043e\u0447\u0451\u0442\u043e\u0432 \u043d\u0435 \u0437\u0430\u043c\u0435\u0442\u0438\u043b. \u041a\u0441\u0442\u0430\u0442\u0438, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043d\u0430\u0434 \u043d\u0435\u0439 \u0440\u0435\u0431\u044f\u0442\u0430 \u0438\u0437 Astral, \u0442\u043e\u0439 \u0436\u0435 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0441\u043e\u0437\u0434\u0430\u043b\u0430 <code>uv<\/code> \u0438 <code>ruff<\/code>.<\/p>\n<\/blockquote>\n<p><strong>pytest<\/strong><\/p>\n<p><a href=\"https:\/\/docs.pytest.org\/en\/stable\/\" rel=\"noopener noreferrer nofollow\">pytest<\/a>\u00a0\u2014 \u044d\u0442\u043e \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043b\u044f Python, \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043e\u0431\u043b\u0435\u0433\u0447\u0430\u044e\u0449\u0430\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0438 \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u044b\u0445 \u0442\u0435\u0441\u0442\u043e\u0432. \u041e\u043d\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0444\u0438\u043a\u0441\u0442\u0443\u0440\u044b, \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0438\u043c\u0435\u0435\u0442 \u0431\u043e\u0433\u0430\u0442\u0443\u044e \u044d\u043a\u043e\u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432. \u041f\u0440\u043e\u0441\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u0432\u00a0<code>project-api\/src\/app\/tests\/<\/code> \u0444\u0430\u0439\u043b \u0441 \u0438\u043c\u0435\u043d\u0435\u043c <code>test_&lt;unit_or_module&gt;.py<\/code>\u00a0\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u0435:<\/p>\n<pre><code>uv run pytest<\/code><\/pre>\n<p>\u0413\u043e\u0442\u043e\u0432\u043e!<\/p>\n<h3>Pydantic<\/h3>\n<p><a href=\"https:\/\/pydantic-docs.helpmanual.io\/\" rel=\"noopener noreferrer nofollow\">Pydantic<\/a>\u00a0\u2014 \u044d\u0442\u043e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0434\u043b\u044f \u0432\u0430\u043b\u0438\u0434\u0430\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438. \u041e\u043d\u0430 \u043f\u043e\u043c\u043e\u0433\u0430\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0432\u0441\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0435 \u0434\u0435\u0442\u0430\u043b\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a \u043a\u043b\u044e\u0447\u0438 API, \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u043b\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043c\u043e\u0434\u0435\u043b\u0438 (\u0436\u0451\u0441\u0442\u043a\u043e\u0435 \u043f\u0440\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u043d\u0438\u0435 \u044d\u0442\u0438\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u2014 \u043e\u0447\u0435\u043d\u044c \u043f\u043b\u043e\u0445\u0430\u044f \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430, \u0435\u0441\u043b\u0438 \u0447\u0442\u043e).<\/p>\n<p>\u0412 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438, <a href=\"https:\/\/docs.pydantic.dev\/latest\/concepts\/pydantic_settings\/\" rel=\"noopener noreferrer nofollow\">Pydantic Settings<\/a>\u00a0\u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u043e\u0434\u0435\u043b\u0435\u0439 Pydantic. \u042d\u0442\u0430 \u0443\u0442\u0438\u043b\u0438\u0442\u0430 \u043c\u043e\u0436\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0438\u0437 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0441\u0440\u0435\u0434\u044b \u0438\u043b\u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 .env, \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0438\u0445 \u0442\u0438\u043f\u044b \u0438 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0442\u044c \u0443\u0434\u043e\u0431\u043d\u044b\u0439 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043d\u0438\u043c \u0432 \u043a\u043e\u0434\u0435.<\/p>\n<p>\u0412\u043e\u0442 \u043f\u0440\u0438\u043c\u0435\u0440:<\/p>\n<pre><code class=\"python\">from   pydantic import BaseSettings  class Settings(BaseSettings): \u00a0\u00a0\u00a0 api_key: str \u00a0\u00a0\u00a0 db_url: str      \u00a0\u00a0\u00a0 class Config: \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 env_file = \".env\"  settings =   Settings()<\/code><\/pre>\n<p>\u041f\u0440\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0438 \u044d\u0442\u043e\u0433\u043e \u043a\u043e\u0434\u0430 Pydantic \u0431\u0443\u0434\u0435\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f <code>api_key<\/code>\u00a0\u0438\u00a0<code>db_url<\/code>\u00a0\u0438\u0437 \u0444\u0430\u0439\u043b\u0430\u00a0<code>.env<\/code>\u00a0\u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u0441\u0440\u0435\u0434\u044b. \u0412 \u0438\u0442\u043e\u0433\u0435 \u044d\u0442\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0434\u043b\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c\u0441\u044f \u0432 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0438 \u0441 \u0442\u0438\u043f\u0430\u043c\u0438 \u0438\u0437 \u043c\u043e\u0434\u0435\u043b\u0438 <code>Settings<\/code>. \u041f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e! <\/p>\n<h3>MkDocs<\/h3>\n<p><a class=\"anchor\" name=\"id17\" id=\"id17\"><\/a><\/p>\n<p>\u0421<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-473471","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/473471","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=473471"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/473471\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=473471"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=473471"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=473471"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}