
рдХрдВрд╕реЛрд▓ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдкрд╛рдпрдерди рдПрдХ рдорд╣рд╛рди рднрд╛рд╖рд╛ рд╣реИ, рдФрд░ рдпрд╣ рдЗрди рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдмрдбрд╝реА рд╕рдВрдЦреНрдпрд╛ рдореЗрдВ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреЛ рдЙрдЬрд╛рдЧрд░ рдХрд░рддрд╛ рд╣реИред
рд▓реЗрдХрд┐рди рдХреНрдпрд╛ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдореМрдЬреВрдж рд╣реИрдВ? рдФрд░ рдХреМрди рд╕рд╛ рд▓реЗрдирд╛ рдмреЗрд╣рддрд░ рд╣реИ? рдпрд╣ рд╕рд╛рдордЧреНрд░реА рдХрдВрд╕реЛрд▓ рдХреА рджреБрдирд┐рдпрд╛ рдХреЗ рд▓рд┐рдП рд▓реЛрдХрдкреНрд░рд┐рдп рдФрд░ рдмрд╣реБрдд рдЙрдкрдХрд░рдг рдХреА рддреБрд▓рдирд╛ рдирд╣реАрдВ рдХрд░рддреА рд╣реИ рдФрд░ рджреВрд╕рд░реЗ рдкреНрд░рд╢реНрди рдХрд╛ рдЙрддреНрддрд░ рджреЗрдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреА рд╣реИред
рдкрдврд╝рдиреЗ рдореЗрдВ рдЖрд╕рд╛рдиреА рдХреЗ рд▓рд┐рдП, рд╕рдореАрдХреНрд╖рд╛ рдХреЛ рджреЛ рдкрджреЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ: рдкрд╣рд▓рд╛ рдЫрд╣ рд╕рдмрд╕реЗ рд▓реЛрдХрдкреНрд░рд┐рдп рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреА рддреБрд▓рдирд╛ рдХрд░рддрд╛ рд╣реИ, рджреВрд╕рд░рд╛ - рдХрдо рд▓реЛрдХрдкреНрд░рд┐рдп рдФрд░ рдЕрдзрд┐рдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ, рд▓реЗрдХрд┐рди рдЕрднреА рднреА рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реИред
рдкреНрд░рддреНрдпреЗрдХ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ,
рдЯреЙрдбреЛрд▓рд┐рдм рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рд▓рд┐рдП рдПрдХ рдХрдВрд╕реЛрд▓ рдЙрдкрдпреЛрдЧрд┐рддрд╛ рдкрд╛рдпрдерди 3.7 рдореЗрдВ рд▓рд┐рдЦреА рдЬрд╛рдПрдЧреА, рдЬрд┐рд╕рдХреЗ рд╕рд╛рде рдЖрдк рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ, рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдЯреИрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рд╣рдЯрд╛ рд╕рдХрддреЗ рд╣реИрдВред рдмрд╛рдХреА рдХреЛ рдПрдХ рд╡рд┐рд╢реЗрд╖ рдврд╛рдВрдЪреЗ рдкрд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреА рд╕рд╛рджрдЧреА рдХреЗ рдЕрдзреАрди рдЬреЛрдбрд╝рд╛ рдЬрд╛рдПрдЧрд╛ред рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд╕реНрд╡рдпрдВ рдПрдХ json рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рдПрдХ рдЕрд▓рдЧ рдХреЙрд▓ рдореЗрдВ рд╕рд╣реЗрдЬрд╛ рдЬрд╛рдПрдЧрд╛ - рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрддрд┐рд░рд┐рдХреНрдд рд╕реНрдерд┐рддрд┐ред
рдЗрд╕рдХреЗ рдЕрддрд┐рд░рд┐рдХреНрдд, рдкреНрд░рддреНрдпреЗрдХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд▓рд┐рдП рдПрдХ рддреБрдЪреНрдЫ рдкрд░реАрдХреНрд╖рдг рд▓рд┐рдЦрд╛ рдЬрд╛рдПрдЧрд╛ред рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдлрд┐рдХреНрд╕реНрдЪрд░ рдХреЗ рд╕рд╛рде рдкрд╛рдЗрд╕реНрдЯ рдХреЛ рдкрд░реАрдХреНрд╖рдг рдврд╛рдВрдЪреЗ рдХреЗ рд░реВрдк рдореЗрдВ рд▓рд┐рдпрд╛ рдЧрдпрд╛ рдерд╛:
@pytest.fixture(autouse=True) def db(monkeypatch): """ monkeypatch , """ value = {"tasks": []} monkeypatch.setattr(todolib.TodoApp, "get_db", lambda _: value) return value @pytest.yield_fixture(autouse=True) def check(db): """ """ yield assert db["tasks"] and db["tasks"][0]["title"] == "test" # , EXPECTED = "Task 'test' created with number 1.\n"
рд╕рд┐рджреНрдзрд╛рдВрдд рд░реВрдк рдореЗрдВ, рдЙрдкрд░реЛрдХреНрдд рд╕рднреА рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рдкреНрдд рд╣реЛрдЧрд╛ред
рдЗрд╕ рд░рд┐рдкреЙрдЬрд┐рдЯрд░реА рдореЗрдВ рдлреБрд▓ рд╕реЛрд░реНрд╕ рдХреЛрдб рдЙрдкрд▓рдмреНрдз рд╣реИред
argparse
рдЕрд░реНрдЧрдкрд░реНрд╕ рдХреЗ рдкрд╛рд╕ рдПрдХ рдирд┐рд░реНрд╡рд┐рд╡рд╛рдж рд▓рд╛рдн рд╣реИ - рдпрд╣ рдорд╛рдирдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдореЗрдВ рд╣реИ рдФрд░ рдЗрд╕рдХреЗ рдПрдкреАрдЖрдИ рдХреЛ рд╕реАрдЦрдирд╛ рдореБрд╢реНрдХрд┐рд▓ рдирд╣реАрдВ рд╣реИ: рдПрдХ рдкрд╛рд░реНрд╕рд░ рд╣реИ, рддрд░реНрдХ рд╣реИрдВ, рддрд░реНрдХ рдореЗрдВ
рдкреНрд░рдХрд╛рд░ ,
рдХрд╛рд░реНрд░рд╡рд╛рдИ ,
рднрд╛рдЧреНрдп ,
рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдФрд░
рдорджрдж рд╣реИ ред рдФрд░
рд╕рдмрдкрд░ рд╣реИ - рддрд░реНрдХ рдФрд░ рддрд░реНрдХ рдХреЗ рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╣рд┐рд╕реНрд╕реЗ рдХреЛ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдХрдорд╛рдВрдб рдореЗрдВ рд░рдЦрдиреЗ рдХреА рдХреНрд╖рдорддрд╛ред
рдкрд╛рд░реНрд╕рд░
рдкрд╣рд▓реА рдирдЬрд╝рд░ рдореЗрдВ - рдХреБрдЫ рднреА рдЕрд╕рд╛рдорд╛рдиреНрдп рдирд╣реАрдВ рд╣реИ, рдкрд╛рд░реНрд╕рд░ рдПрдХ рдкрд╛рд░реНрд╕рд░ рдХреА рддрд░рд╣ рд╣реИред рд▓реЗрдХрд┐рди - рдореЗрд░реА рд░рд╛рдп рдореЗрдВ - рдЕрдиреНрдп рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреЗ рд╕рд╛рде рддреБрд▓рдирд╛ рдХрд░рдиреЗ рдкрд░ рдкрдардиреАрдпрддрд╛ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫреА рдирд╣реАрдВ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рд╡рд┐рднрд┐рдиреНрди рдЖрджреЗрд╢реЛрдВ рдХреЗ рддрд░реНрдХ рдПрдХ рд╣реА рд╕реНрдерд╛рди рдкрд░ рд╡рд░реНрдгрд┐рдд рд╣реИрдВред
рд╕реНрд░реЛрдд рдХреЛрдб def get_parser(): parser = argparse.ArgumentParser("Todo notes - argparse version") parser.add_argument( "--verbose", "-v", action="store_true", help="Enable verbose mode" ) parser.add_argument("--version", "-V", action="store_true", help="Show version") subparsers = parser.add_subparsers(title="Commands", dest="cmd") add = subparsers.add_parser("add", help="Add new task") add.add_argument("title", help="Todo title") show = subparsers.add_parser("show", help="Show tasks") show.add_argument( "--show-done", action="store_true", help="Include done tasks in the output" ) done = subparsers.add_parser("done", help="Mark task as done") done.add_argument("number", type=int, help="Task number") remove = subparsers.add_parser("remove", help="Remove task") remove.add_argument("number", type=int, help="Task number") return parser
рдореБрдЦреНрдп
рдФрд░ рдпрд╣рд╛рдБ рдПрдХ рд╣реА рдмрд╛рдд рд╣реИ - рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рддрд░реНрдХреЛрдВ рдХреЛ рдЫреЛрдбрд╝рдХрд░ рдФрд░ рдЕрдзрд┐рдХ рдХреБрдЫ рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗ, рдЗрд╕рд▓рд┐рдП рддрд░реНрдХ рдХреЛ рд╕реНрд╡рддрдВрддреНрд░ рд░реВрдк рд╕реЗ рдФрд░ рдПрдХ рд╕реНрдерд╛рди рдкрд░ рд▓рд┐рдЦрдирд╛ рд╣реЛрдЧрд╛ред рдПрдХ рддрд░рдл - рдпрд╣ рдЬреАрд╡рд┐рдд рд░рд╣рдирд╛ рд╕рдВрднрд╡ рд╣реИ, рджреВрд╕рд░реЗ рдкрд░ - рдпрд╣ рдмреЗрд╣рддрд░ рд╕рдВрднрд╡ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рдЕрднреА рддрдХ рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдХреИрд╕реЗред
UPD: рдЬреИрд╕рд╛ рдХрд┐ рдиреЛрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, subparsers set_defaults (func = foo) рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдлрд╝рдВрдХреНрд╢рдВрд╕ рд╕реЗрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЕрд░реНрдерд╛рдд, argparse рдЖрдкрдХреЛ рдЫреЛрдЯреЗ рдЖрдХрд╛рд░реЛрдВ рдореЗрдВ рдореБрдЦреНрдп рдХреЛ рдЫреЛрдЯрд╛ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдЬрд┐рдпреЛ рдФрд░ рд╕реАрдЦреЛредрд╕реНрд░реЛрдд рдХреЛрдб def main(raw_args=None): """ Argparse example entrypoint """ parser = get_parser() args = parser.parse_args(raw_args) logging.basicConfig() if args.verbose: logging.getLogger("todolib").setLevel(logging.INFO) if args.version: print(lib_version) exit(0) cmd = args.cmd if not cmd: parser.print_help() exit(1) with TodoApp.fromenv() as app: if cmd == "add": task = app.add_task(args.title) print(task, "created with number", task.number, end=".\n") elif cmd == "show": app.print_tasks(args.show_done) elif cmd == "done": task = app.task_done(args.number) print(task, "marked as done.") elif cmd == "remove": task = app.remove_task(args.number) print(task, "removed from list.")
рдкрд░реАрдХреНрд╖рдг
рдЙрдкрдпреЛрдЧрд┐рддрд╛ рдХреЗ рдЖрдЙрдЯрдкреБрдЯ рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП,
рдХреИрдкреНрд╕рд┐рд╕ рд╕реНрдерд┐рд░рддрд╛ рдХрд╛
рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ , рдЬреЛ
рд╕реНрдЯрдбрдЖрдЙрдЯ рдФрд░
рд╕реНрдЯреЗрдбрд░ рд╕реЗ рдкрд╛рда рддрдХ рдкрд╣реБрдВрдЪ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИред
def test_argparse(capsys): todo_argparse.main(["add", "test"]) out, _ = capsys.readouterr() assert out == EXPECTED
рдкрд░рд┐рдгрд╛рдо
рдлрд╛рдпрджреЗ рдХреА - рдкрд╛рд░реНрд╕рд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХрд╛ рдПрдХ рдЕрдЪреНрдЫрд╛ рд╕реЗрдЯ, рдорд╛рдирдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдореЗрдВ рдПрдХ рдореЙрдбреНрдпреВрд▓ рдХреА рдЙрдкрд╕реНрдерд┐рддрд┐ред
рд╡рд┐рдкрдХреНрд╖ - рддрд░реНрдХ рдХреЗрд╡рд▓ рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рддрд░реНрдХреЛрдВ рдореЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реИ, рдореБрдЦреНрдп рддрд░реНрдХ рдореЗрдВ рд╕реЗ рдЕрдзрд┐рдХрд╛рдВрд╢ рдХреЛ рд╕реНрд╡рдпрдВ рджреНрд╡рд╛рд░рд╛ рд▓рд┐рдЦрд╛ рдЬрд╛рдирд╛ рдерд╛ред рдФрд░ рдпрд╣ рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реИ рдХрд┐ рдкрд░реАрдХреНрд╖рдгреЛрдВ рдореЗрдВ рдирд┐рдХрд╛рд╕ рдХреЛрдб рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХреИрд╕реЗ рдХрд┐рдпрд╛ рдЬрд╛рдПред
docopt
docopt рдПрдХ рдЫреЛрдЯреА (<600 рд▓рд╛рдЗрдиреЗрдВ, argparse рдХреЗ рд╕рд╛рде 2500 рдХреА рддреБрд▓рдирд╛ рдореЗрдВ) рдкрд╛рд░реНрд╕рд░ рд╣реИ, рдЬреЛ рдЖрдкрдХреЛ GitHub рдкрд░ рдПрдХ рд╡рд┐рд╡рд░рдг рдЙрджреНрдзреГрдд рдХрд░рддреЗ рд╣реБрдП, рдореБрд╕реНрдХрд╛рди рджреЗрдЧрд╛ред рдбреЙрдХреЙрдкреНрдЯ рдХрд╛ рдореБрдЦреНрдп рд╡рд┐рдЪрд╛рд░ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХрд╛ рд╢рд╛рдмреНрджрд┐рдХ рд░реВрдк рд╕реЗ рдкрд╛рда рдХреЗ рд╕рд╛рде рд╡рд░реНрдгрди рдХрд░рдирд╛ рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдбреЙрдХрд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВред
рдЗрд╕реА рдЧрд┐рддреБрдм рдкрд░, рдбреЙрдХрдЯреЙрдк> 6700 рд╕реНрдЯрд╛рд░, рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрдо рд╕реЗ рдХрдо 22 рд╣рдЬрд╛рд░ рдЕрдиреНрдп рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдФрд░ рдпрд╣ рдХреЗрд╡рд▓ рдЕрдЬрдЧрд░ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рд╕рд╛рде рд╣реИ! рдбреЙрдХреЙрдкреНрдЯ рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдкреЗрдЬ рдореЗрдВ рд╡рд┐рднрд┐рдиреНрди рднрд╛рд╖рд╛рдУрдВ рдХреЗ рд▓рд┐рдП C рдФрд░ PHP рд╕реЗ рд▓реЗрдХрд░ рдХреЙрдлрд╝реАрд╕реНрдХреНрд░рд┐рдкреНрдЯ рдФрд░ рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ R. рдХреЗ рд▓рд┐рдП рдХрдИ рд╡рд┐рдХрд▓реНрдк рд╣реИрдВред рдЗрд╕ рддрд░рд╣ рдХреЗ рдХреНрд░реЙрд╕-рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдХреЛ рдХреЗрд╡рд▓ рдХреЛрдб рдХреА рдХреЙрдореНрдкреИрдХреНрдЯрдиреЗрд╕ рдФрд░ рд╕рд░рд▓рддрд╛ рджреНрд╡рд╛рд░рд╛ рд╕рдордЭрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред
рдкрд╛рд░реНрд╕рд░
рдЭрдЧрдбрд╝реЗ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ, рдпрд╣ рдкрд╛рд░реНрд╕рд░ рдПрдХ рдмрдбрд╝рд╛ рдХрджрдо рд╣реИред
"""Todo notes on docopt. Usage: todo_docopt [-v | -vv ] add <task> todo_docopt [-v | -vv ] show --show-done todo_docopt [-v | -vv ] done <number> todo_docopt [-v | -vv ] remove <number> todo_docopt -h | --help todo_docopt --version Options: -h --help Show help. -v --verbose Enable verbose mode. """
рдореБрдЦреНрдп
рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рд╕рдм рдХреБрдЫ argparse рдХреЗ рд╕рд╛рде рд╣реА рд╣реЛрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдЕрдм
рд╡рд░реНрдмреЛрдЬрд╝ рдореЗрдВ рдХрдИ рдорд╛рди (0-2) рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ, рдФрд░ рддрд░реНрдХреЛрдВ рддрдХ рдкрд╣реБрдВрдЪ рдЕрд▓рдЧ-рдЕрд▓рдЧ рд╣реИ: docopt рд░рд┐рдЯрд░реНрди рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдирд╛рдо рд╕реНрдерд╛рди рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рд┐рд░реНрдл рдПрдХ рд╢рдмреНрджрдХреЛрд╢ рд╣реИ, рдЬрд╣рд╛рдВ рдПрдХ рдХрдорд╛рдВрдб рдХрд╛ рд╡рд┐рдХрд▓реНрдк рдЗрдВрдЧрд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдЙрд╕рдХреЗ рдмреВрд▓рд┐рдпрди рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ, рдЬреИрд╕рд╛ рдХрд┐ рджреЗрдЦрд╛ рдЧрдпрд╛
рд╣реИ :
рд╕реНрд░реЛрдд рдХреЛрдб def main(argv=None): args = docopt(__doc__, argv=argv, version=lib_version) log.setLevel(levels[args["--verbose"]]) logging.basicConfig() log.debug("Arguments: %s", args) with TodoApp.fromenv() as app: if args["add"]: task = app.add_task(args["<task>"]) print(task, "created with number", task.number, end=".\n") elif args["show"]: app.print_tasks(args["--show-done"]) elif args["done"]: task = app.task_done(args["<number>"]) print(task, "marked as done.") elif args["remove"]: task = app.remove_task(args["<number>"]) print(task, "removed from list.")
рдкрд░реАрдХреНрд╖рдг
рдЖрд░реНрдЧрди рдкрд░реАрдХреНрд╖рдг рдХреЗ рд╕рдорд╛рди:
def test_docopt(capsys): todo_docopt.main(["add", "test"]) out, _ = capsys.readouterr() assert out == EXPECTED
рдкрд░рд┐рдгрд╛рдо
рд▓рд╛рднреЛрдВ рдореЗрдВ рд╕реЗ - рдкрд╛рд░реНрд╕рд░ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рдХрдо рдХреЛрдб, рдЖрджреЗрд╢реЛрдВ рдФрд░ рддрд░реНрдХреЛрдВ рдХреЗ рд╡рд┐рд╡рд░рдг рдФрд░ рдкрдврд╝рдиреЗ рдореЗрдВ рдЖрд╕рд╛рдиреА, рдЕрдВрддрд░реНрдирд┐рд╣рд┐рдд рд╕рдВрд╕реНрдХрд░рдгред
рд╡рд┐рдкрдХреНрд╖, рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╕рдорд╛рди рд░реВрдк рд╕реЗ рд╕рдорд╛рди -
рдореБрдЦреНрдп рдореЗрдВ рдмрд╣реБрдд рд╕рд╛рд░реЗ рддрд░реНрдХ, рдЖрдк рдмрд╛рд╣рд░ рдирд┐рдХрд▓рдиреЗ рдХреЗ рдХреЛрдб рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдбреЙрдХрдЯреЙрдк рдХрд╛ рд╡рд░реНрддрдорд╛рди рд╕рдВрд╕реНрдХрд░рдг (0.6.2) рдЕрднреА рддрдХ рд╕реНрдерд┐рд░ рдирд╣реАрдВ рд╣реИ рдФрд░ рд╣рдореЗрд╢рд╛ рдХреЗ рд▓рд┐рдП рд╣реЛрдиреЗ рдХреА рд╕рдВрднрд╛рд╡рдирд╛ рдирд╣реАрдВ рд╣реИ - рдкрд░рд┐рдпреЛрдЬрдирд╛ 2012 рд╕реЗ 2013 рдХреЗ рдЕрдВрдд рддрдХ
рд╕рдХреНрд░рд┐рдп рд░реВрдк рд╕реЗ рд╡рд┐рдХрд╕рд┐рдд рд╣реЛ рд░рд╣реА рдереА, рдЖрдЦрд┐рд░реА рдкреНрд░рддрд┐рдмрджреНрдз рджрд┐рд╕рдВрдмрд░ 17 рдореЗрдВ рдерд╛ред рдФрд░ рдЗрд╕ рд╕рдордп рд╕рдмрд╕реЗ рдЕрдкреНрд░рд┐рдп рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ рдХреБрдЫ рдбреЙрдХрдЯреЙрдк рдирд┐рдпрдорд┐рдд рдкрд░реАрдХреНрд╖рдг рдХрд░рддреЗ рд╕рдордп DeprecationWarning рдХреЛ рдЙрддреНрддреЗрдЬрд┐рдд рдХрд░рддреЗ рд╣реИрдВред
рдХреНрд▓рд┐рдХ рдХрд░реЗрдВ
рдХреНрд▓рд┐рдХ, рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдФрд░ рд╕рдЬреНрдЬрд╛рдХрд╛рд░реЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЖрджреЗрд╢реЛрдВ рдФрд░ рдорд╛рдкрджрдВрдбреЛрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХреЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╕реЗ рд╕рдВрдЦреНрдпрд╛ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдореВрд▓ рд░реВрдк рд╕реЗ рдЕрд▓рдЧ рд╣реИ, рдФрд░ рддрд░реНрдХ рдХреЛ рдПрдХ рдмрдбрд╝реЗ
рдореБрдЦреНрдп рдХреЗ рдмрдЬрд╛рдп рдЕрд▓рдЧ-рдЕрд▓рдЧ рдХрд╛рд░реНрдпреЛрдВ рдореЗрдВ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рд╕реНрддрд╛рд╡ рд╣реИред рд▓реЗрдЦрдХреЛрдВ рдХрд╛ рджрд╛рд╡рд╛ рд╣реИ рдХрд┐ рдХреНрд▓рд┐рдХ рдореЗрдВ рдмрд╣реБрдд рд╕рд╛рд░реА рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдорд╛рдирдХ рдкреИрд░рд╛рдореАрдЯрд░ рдкрд░реНрдпрд╛рдкреНрдд рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХреЗ рдмреАрдЪ, рдиреЗрд╕реНрдЯреЗрдб рдХрдорд╛рдВрдб рдФрд░ рдЙрдирдХреЗ рдЖрд▓рд╕реА рд▓реЛрдбрд┐рдВрдЧ рдкрд░ рдЬреЛрд░ рджрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
рдпрд╣ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдЕрддреНрдпрдВрдд рд▓реЛрдХрдкреНрд░рд┐рдп рд╣реИ:> 8100 рд╕рд┐рддрд╛рд░реЗ рд╣реЛрдиреЗ рдФрд░ рдХрдо рд╕реЗ рдХрдо 174 рд╣рдЬрд╛рд░ (!) рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдореЗрдВ рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрд╣ рдЕрднреА рднреА рд╡рд┐рдХрд╕рд┐рдд рд╣реЛ рд░рд╣рд╛ рд╣реИ: рд╕рдВрд╕реНрдХрд░рдг 7.0 рд╢рд░рдж рдЛрддреБ 2018 рдореЗрдВ рдЬрд╛рд░реА рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рдФрд░ рдЗрд╕ рджрд┐рди рдХреЗ рд▓рд┐рдП рдирдП рдХрдорд┐рдЯ рдФрд░ рдорд░реНрдЬ рдЕрдиреБрд░реЛрдз рджрд┐рдЦрд╛рдИ рджреЗрддреЗ рд╣реИрдВ рджрд┐рдиред
рдкрд╛рд░реНрд╕рд░
рджрд╕реНрддрд╛рд╡реЗрдЬрд╝реАрдХрд░рдг рдкреГрд╖реНрда рдкрд░, рдореБрдЭреЗ
рдкреБрд╖реНрдЯрд┐рдХрд░рдг_ рджрд╛рдпрдХ рдбреЗрдХреЛрд░реЗрдЯрд░ рдорд┐рд▓рд╛, рдЬреЛ рдХрдорд╛рдВрдб рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реЗ рдкреБрд╖реНрдЯрд┐ рдХреЗ рд▓рд┐рдП рдХрд╣рддрд╛ рд╣реИред рдЗрд╕реЗ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╡рд╛рдЗрдк рдХрдорд╛рдВрдб рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛, рдЬреЛ рдХрд╛рд░реНрдпреЛрдВ рдХреА рдкреВрд░реА рд╕реВрдЪреА рдХреЛ рд╕рд╛рдл рдХрд░рддрд╛ рд╣реИред
рд╕реНрд░реЛрдд рдХреЛрдб levels = [logging.WARN, logging.INFO, logging.DEBUG] pass_app = click.make_pass_decorator(TodoApp) @click.group() @click.version_option(lib_version, prog_name="todo_click") @click.option("-v", "--verbose", count=True)
рдореБрдЦреНрдп
рдФрд░ рдпрд╣рд╛рдВ рд╣рдо рдХреНрд▓рд┐рдХ рдХреЗ рдореБрдЦреНрдп рд▓рд╛рдн рдХреЗ рд╕рд╛рде рдорд┐рд▓рддреЗ рд╣реИрдВ - рдЗрд╕ рддрдереНрдп рдХреЗ рдХрд╛рд░рдг рдХрд┐ рдХрдорд╛рдВрдб рдХреЗ рддрд░реНрдХ рдХреЛ рдЙрдирдХреЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдмрд╛рд╣рд░ рд░рдЦрд╛ рдЧрдпрд╛ рд╣реИ, рд▓рдЧрднрдЧ рдХреБрдЫ рднреА рдореБрдЦреНрдп рдирд╣реАрдВ рд░рд╣рддрд╛ рд╣реИред рдпрд╣ рднреА рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рдкрд░реНрдпрд╛рд╡рд░рдг рдЪрд░ рд╕реЗ рддрд░реНрдХ рдФрд░ рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреА рдХреНрд╖рдорддрд╛ рд╣реИред
if __name__ == "__main__": cli(auto_envvar_prefix="TODO")
рдкрд░реАрдХреНрд╖рдг
рдХреНрд▓рд┐рдХ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, sys.stdout рдХреЛ рдЗрдВрдЯрд░рд╕реЗрдкреНрдЯ рдХрд░рдиреЗ рдХреА рдХреЛрдИ рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕ рддрд░рд╣ рдХреА рдЪреАрдЬреЛрдВ рдХреЗ рд▓рд┐рдП рд░рдирд░ рдХреЗ рд╕рд╛рде
рдХреНрд▓рд┐рдХрд┐рдВрдЧ рдореЙрдбреНрдпреВрд▓ рд╣реИред рдФрд░ рди рдХреЗрд╡рд▓
CliRunner рд╣реА рдЖрдЙрдЯрдкреБрдЯ рдХреЛ рдЗрдВрдЯрд░рд╕реЗрдкреНрдЯ рдХрд░рддрд╛ рд╣реИ, рдмрд▓реНрдХрд┐ рдпрд╣ рдЖрдкрдХреЛ рдПрдХреНрдЬрд╝рд┐рдЯ рдХреЛрдб рдХреА рдЬрд╛рдБрдЪ рдХрд░рдиреЗ рдХреА рднреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдЬреЛ рдардВрдбрд╛ рднреА рд╣реИред рдпрд╣ рд╕рдм pytest рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдмрд┐рдирд╛ рдХреНрд▓рд┐рдХ-рдпреВрдЯрд┐рд▓рд┐рдЯреАрдЬ рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдФрд░ рдорд╛рдирдХ
unittest рдореЙрдбреНрдпреВрд▓ рдХреЛ рдмрд╛рдпрдкрд╛рд╕ рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред
import click.testing def test_click(): runner = click.testing.CliRunner() result = runner.invoke(todo_click.cli, ["add", "test"]) assert result.exit_code == 0 assert result.output == EXPECTED
рдкрд░рд┐рдгрд╛рдо
рдпрд╣ рдХреЗрд╡рд▓ рдПрдХ рдЫреЛрдЯрд╛ рд╕рд╛ рд╣рд┐рд╕реНрд╕рд╛ рд╣реИ рдЬреЛ рдХреНрд▓рд┐рдХ рдХрд░ рд╕рдХрддрд╛ рд╣реИред рдПрдкреАрдЖрдИ рдХреЗ рдмрд╛рдХреА рд╣рд┐рд╕реНрд╕реЛрдВ рд╕реЗ - рдореВрд▓реНрдпреЛрдВ рдХрд╛ рд╕рддреНрдпрд╛рдкрди, рдЯрд░реНрдорд┐рдирд▓ рдХреЗ рд╕рд╛рде рдПрдХреАрдХрд░рдг (рд░рдВрдЧ, рдкреЗрдЬрд░ рдП рд▓рд╛ рдХрдо, рдкреНрд░рдЧрддрд┐ рдмрд╛рд░, рдЖрджрд┐), рдкрд░рд┐рдгрд╛рдо рдХреЙрд▓рдмреИрдХ, рдСрдЯреЛ-рдкреВрд░рд╛ рдФрд░ рдмрд╣реБрдд рдХреБрдЫред рдЖрдк рдЙрдирдХреЗ рдЙрджрд╛рд╣рд░рдг
рдпрд╣рд╛рдВ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред
рдкреЗрд╢реЗрд╡рд░реЛрдВ: рдХрд┐рд╕реА рднреА рдЕрд╡рд╕рд░ рдХреЗ рд▓рд┐рдП рдмрд╣реБрдд рд╕рд╛рд░реЗ рдЙрдкрдХрд░рдг, рдПрдХ рдореВрд▓, рд▓реЗрдХрд┐рди рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ рдЯреАрдореЛрдВ рдХрд╛ рд╡рд░реНрдгрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рджреГрд╖реНрдЯрд┐рдХреЛрдг, рдкрд░реАрдХреНрд╖рдг рдореЗрдВ рдЖрд╕рд╛рдиреА рдФрд░ рд╕рдХреНрд░рд┐рдп рдкрд░рд┐рдпреЛрдЬрдирд╛ рдЬреАрд╡рдиред
рд╡рд┐рдкрдХреНрд╖: "рдХреНрд▓рд┐рдХ" рдХреЗ рдиреБрдХрд╕рд╛рди рдХреНрдпрд╛ рд╣реИрдВ - рдпрд╣ рдПрдХ рдореБрд╢реНрдХрд┐рд▓ рд╕рд╡рд╛рд▓ рд╣реИред рд╣реЛ рд╕рдХрддрд╛ рд╣реИ рдХрд┐ рд╡рд╣ рдХреБрдЫ рдирд╣реАрдВ рдЬрд╛рдирддрд╛ рд╣реЛ рдХрд┐ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреНрдпрд╛ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реИрдВ?
рдЖрдЧ
рдЖрдЧ Google рд╕реЗ рдХрдВрд╕реЛрд▓ рдЗрдВрдЯрд░рдлреЗрд╕ рдХреЗ рд▓рд┐рдП рд╕рд┐рд░реНрдл рдПрдХ рдпреБрд╡рд╛ (2017 рдореЗрдВ рджрд┐рдЦрд╛рдИ рдЧрдИ) рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдирд╣реАрдВ рд╣реИ, рдпрд╣ рд╢рд╛рдмреНрджрд┐рдХ рд░реВрдк рд╕реЗ рдХрдВрд╕реЛрд▓ рдЗрдВрдЯрд░рдлреЗрд╕ рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рд╣реИ, рдЬрд┐рд╕рдХрд╛ рд╢рд╛рдмреНрджрд┐рдХ рд░реВрдк рд╕реЗ
рдХреЛрдИ рднреА рдкрд╛рдпрдерди
рдСрдмреНрдЬреЗрдХреНрдЯ рд╣реИ ред
рдЕрдиреНрдп рдмрд╛рддреЛрдВ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрд╣ рдХрд╣рд╛ рдЧрдпрд╛ рд╣реИ рдХрд┐ рдЖрдЧ рдХреЛрдб рдХреЗ рд╡рд┐рдХрд╛рд╕ рдФрд░ рдбрд┐рдмрдЧрд┐рдВрдЧ рдореЗрдВ рдорджрдж рдХрд░рддреА рд╣реИ, рд╕реАрдПрд▓рдЖрдИ рдореЗрдВ рдореМрдЬреВрджрд╛ рдХреЛрдб рдХреЛ рдЕрдиреБрдХреВрд▓рд┐рдд рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░рддреА рд╣реИ, рдмреИрд╢ рд╕реЗ рдкрд╛рдпрдерди рдореЗрдВ рд╕рдВрдХреНрд░рдордг рдХреА рд╕реБрд╡рд┐рдзрд╛ рдкреНрд░рджрд╛рди рдХрд░рддреА рд╣реИ, рдФрд░ рдЗрдВрдЯрд░реИрдХреНрдЯрд┐рд╡ рдХрд╛рдо рдХреЗ рд▓рд┐рдП рдЗрд╕рдХрд╛ рдЕрдкрдирд╛ REPL рд╣реИред рдХреНрдпрд╛ рд╣рдо рджреЗрдЦреЗрдВрдЧреЗ?
рдкрд╛рд░реНрд╕рд░ рдФрд░ рдореБрдЦреНрдп
рдлрд╛рдпрд░.рдлреЗрдпрд░ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдХрд┐рд╕реА рднреА рд╡рд╕реНрддреБ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рдиреЗ рдореЗрдВ рд╕рдХреНрд╖рдо рд╣реИ: рдПрдХ рдореЙрдбреНрдпреВрд▓, рдПрдХ рд╢реНрд░реЗрдгреА рдЙрджрд╛рд╣рд░рдг, рдХрдорд╛рдВрдб рдирд╛рдо рдФрд░ рд╕рдВрдмрдВрдзрд┐рдд рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рд╢рдмреНрджрдХреЛрд╢, рдФрд░ рдЗрд╕реА рддрд░рд╣ред
рд╣рдорд╛рд░реЗ рд▓рд┐рдП рдЬреЛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИ рд╡рд╣ рдпрд╣ рд╣реИ рдХрд┐ рдлрд╛рдпрд░ рдПрдХ рд╡рд░реНрдЧ рд╡рд╕реНрддреБ рдХреЗ рд╣рд╕реНрддрд╛рдВрддрд░рдг рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдХреНрд▓рд╛рд╕ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рд╕рднреА рдЖрджреЗрд╢реЛрдВ рдХреЗ рд▓рд┐рдП рддрд░реНрдХ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИ, рдФрд░ рдЗрд╕рдХреЗ рддрд░реАрдХреЗ рдФрд░ рдЧреБрдг рдЕрд▓рдЧ-рдЕрд▓рдЧ рдХрдорд╛рдВрдб рд╣реЛрддреЗ рд╣реИрдВред рд╣рдо рдЗрд╕рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ:
рд╕реНрд░реЛрдд рдХреЛрдб class Commands: def __init__(self, db=None, verbose=False): level = logging.INFO if verbose else logging.WARNING logging.basicConfig(level=level) logging.getLogger("todolib").setLevel(level) self._app = todolib.TodoApp.fromenv(db) atexit.register(self._app.save) def version(self): return todolib.__version__ def add(self, task): """Add new task.""" task = self._app.add_task(task) print(task, "created with number", task.number, end=".\n") def show(self, show_done=False): """ Show current tasks. """ self._app.print_tasks(show_done) def done(self, number): """ Mark task as done. """ task = self._app.task_done(number) print(task, "marked as done.") def remove(self, number): """ Removes task from the list. """ task = self._app.remove_task(number) print(task, "removed from the list.") def main(args=None): fire.Fire(Commands, command=args)
рдЗрдирд▓рд╛рдЗрди рдЭрдВрдбреЗ
рд╡рд┐рд╢реЗрд╖ рд╕рд┐рдВрдЯреИрдХреНрд╕ рдХреЗ рд╕рд╛рде рдЖрдЧ рдХреЗ рдЕрдкрдиреЗ рдЭрдВрдбреЗ рд╣реЛрддреЗ рд╣реИрдВ (рдЙрдиреНрд╣реЗрдВ "-" рдХреЗ рдмрд╛рдж рдкрд╛рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП), рдЬреЛ рдЖрдкрдХреЛ рдкрд╛рд░реНрд╕рд░ рдХреЗ рд╣реБрдб рдХреЗ рдиреАрдЪреЗ рджреЗрдЦрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ рдФрд░ рдПрдХ рдкреВрд░реЗ рдХреЗ рд░реВрдк рдореЗрдВ рдЖрд╡реЗрджрди:
рдХреЙрд▓ рдЙрджрд╛рд╣рд░рдг $ ./todo_fire.py show -- --trace Fire trace: 1. Initial component 2. Instantiated class "Commands" (todo_fire.py:9) 3. Accessed property "show" (todo_fire.py:25) $ ./todo_fire.py -- --verbose | head -n 12
рдкрд░реАрдХреНрд╖рдг
рдореБрдЦреНрдп рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдирд╛ argparse рдФрд░ docopt рдХреЗ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд╕рдорд╛рди рд╣реИ, рдЗрд╕рд▓рд┐рдП рдореИрдВ рдпрд╣рд╛рдВ рдмрд┐рдВрджреБ рдирд╣реАрдВ рджреЗрдЦрддрд╛ред
рдЗрд╕реА рд╕рдордп, рдпрд╣ рдзреНрдпрд╛рди рджреЗрдиреЗ рдпреЛрдЧреНрдп рд╣реИ рдХрд┐, рдЖрдЧ рдХреА рдЖрддреНрдордирд┐рд░реАрдХреНрд╖рдг рдкреНрд░рдХреГрддрд┐ рдХреЗ рдХрд╛рд░рдг, рдЖрдк рдХрдорд╛рдВрдбрд░ рд╡рд░реНрдЧ рдХреЛ рджреВрд░ рд╕реЗ рднреА рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред
рдкрд░рд┐рдгрд╛рдо
рдЖрдЧ рдПрдХ рдЙрдкрдХрд░рдг рд╣реИ рдЬреЛ рдХреНрд▓рд┐рдХ рд╕реЗ рдХрдо рд░реЛрдЪрдХ рдирд╣реАрдВ рд╣реИред рдпрд╣ рдкрд╛рд░реНрд╕рд░ рдореЗрдВ рдХрдИ рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреЛ рд╕реВрдЪреАрдмрджреНрдз рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рдиреНрдпреВрдирддрдо рд╣реИ, рдбрд┐рдмрдЧрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рд╡рд┐рдХрд▓реНрдк рд╣реИрдВ, рдФрд░ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдЦреБрдж рд╣реА
рд░рд╣рддреА рд╣реИ рдФрд░ рдХреНрд▓рд┐рдХ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ
рдФрд░ рднреА рдЕрдзрд┐рдХ рд╕рдХреНрд░рд┐рдп рд░реВрдк рд╕реЗ
рд╡рд┐рдХрд╕рд┐рдд рд╣реЛрддреА рд╣реИ (60 рдЗрд╕ рдЧрд░реНрдореА рдХреЛ рдкреВрд░рд╛ рдХрд░рддреА рд╣реИ)ред
рд╡рд┐рдкрдХреНрд╖: рдХреНрд▓рд┐рдХ рдФрд░ рдЕрдиреНрдп рдкрд╛рд░реНрд╕рд░ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдХрд╛рдлреА рдХрдо рд╣реЛ рд╕рдХрддрд╛ рд╣реИ; рдЕрд╕реНрдерд┐рд░ рдПрдкреАрдЖрдИ (рд╡рд░реНрддрдорд╛рди рд╕рдВрд╕реНрдХрд░рдг 0.2.1 рд╣реИ)ред
рд╕реАрдореЗрдВрдЯ
рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ,
рд╕реАрдореЗрдВрдЯ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдПрдХ рд╕реАрдПрд▓рдЖрдИ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдирд╣реАрдВ рд╣реИ, рдмрд▓реНрдХрд┐ рдХрдВрд╕реЛрд▓ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рд░реВрдкрд░реЗрдЦрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣ рджрд╛рд╡рд╛ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдФрд░ рд╡рд┐рднрд┐рдиреНрди рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЗ рд╕рд╛рде рдЬрдЯрд┐рд▓ рдЕрдиреБрдкреНрд░рдпреЛрдЧреЛрдВ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреБрдХреНрдд рд╣реИред
рдкрд╛рд░реНрд╕рд░
рд╕реАрдореЗрдВрдЯ рдореЗрдВ рдкрд╛рд░реНрд╕рд░ рдЕрд╕рд╛рдорд╛рдиреНрдп рджрд┐рдЦрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдпрджрд┐ рдЖрдк рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдХрд░реАрдм рд╕реЗ рджреЗрдЦрддреЗ рд╣реИрдВ, рддреЛ рдпрд╣ рдЕрдиреБрдорд╛рди рд▓рдЧрд╛рдирд╛ рдЖрд╕рд╛рди рд╣реИ рдХрд┐ рдкрд░рд┐рдЪрд┐рдд рдЕрд░рдЧрд░реНрд╕ рд╣реБрдб рдХреЗ рдиреАрдЪреЗ рд╣реИред рд▓реЗрдХрд┐рди рд╢рд╛рдпрдж рдпрд╣ рд╕рдмрд╕реЗ рдЕрдЪреНрдЫрд╛ рдХреЗ рд▓рд┐рдП рд╣реИ - рдирдП рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рд╕реАрдЦрдиреЗ рдХреА рдХреЛрдИ рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИред
рд╕реНрд░реЛрдд рдХреЛрдб from cement import Controller, ex class Base(Controller): class Meta: label = "base" arguments = [ ( ["-v", "--version"], {"action": "version", "version": f"todo_cement v{todolib.__version__}"}, ) ] def _default(self): """Default action if no sub-command is passed.""" self.app.args.print_help() @ex(help="Add new task", arguments=[(["task"], {"help": "Task title"})]) def add(self): title = self.app.pargs.task self.app.log.debug(f"Task title: {title!r}") task = self.app.todoobj.add_task(title) print(task, "created with number", task.number, end=".\n") @ex( help="Show current tasks", arguments=[ (["--show-done"], dict(action="store_true", help="Include done tasks")) ], ) def show(self): self.app.todoobj.print_tasks(self.app.pargs.show_done) @ex(help="Mark task as done", arguments=[(["number"], {"type": int})]) def done(self): task = self.app.todoobj.task_done(self.app.pargs.number) print(task, "marked as done.") @ex(help="Remove task from the list", arguments=[(["number"], {"type": int})]) def remove(self): task = self.app.todoobj.remove_task(self.app.pargs.number) print(task, "removed from the list.")
рдРрдк рдФрд░ рдореБрдЦреНрдп
рд╕реАрдореЗрдВрдЯ, рдЕрдиреНрдп рдЪреАрдЬреЛрдВ рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЕрднреА рднреА рдЕрдкрд╡рд╛рджреЛрдВ рдореЗрдВ рд╕рдВрдХреЗрддреЛрдВ рдХреЛ рд▓рдкреЗрдЯрддрд╛ рд╣реИред рдпрд╣ рдпрд╣рд╛рдБ SIGINT / SIGTERM рдХреЗ рд╕рд╛рде рд╢реВрдиреНрдп-рдХреЛрдб рдЖрдЙрдЯрдкреБрдЯ рдкрд░ рдкреНрд░рджрд░реНрд╢рд┐рдд рд╣реЛрддрд╛ рд╣реИред
рд╕реНрд░реЛрдд рдХреЛрдб class TodoApp(App): def __init__(self, argv=None): super().__init__(argv=argv) self.todoobj = None def load_db(self): self.todoobj = todolib.TodoApp.fromenv() def save(self): self.todoobj.save() class Meta:
рдпрджрд┐ рдЖрдкрдХреЛ рдореБрдЦреНрдп рдХреА рд╕рдордЭ рдорд┐рд▓рддреА рд╣реИ, рддреЛ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рд▓реЛрдбрд┐рдВрдЧ рдФрд░ рдмрдЪрдд todolib.TodoApp рдХреЛ рдУрд╡рд░рд░рд╛рдЗрдб __enter __ / __ рдПрдХреНрдЬрд┐рдЯ__ рдореЗрдВ рднреА рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рд╕реАрдореЗрдВрдЯ рд╣реБрдХ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрди рдЪрд░рдгреЛрдВ рдХреЛ рдЕрдВрддрддрдГ рдЕрд▓рдЧ-рдЕрд▓рдЧ рддрд░реАрдХреЛрдВ рд╕реЗ рдЕрд▓рдЧ рдХрд┐рдпрд╛ рдЧрдпрд╛ред
рдкрд░реАрдХреНрд╖рдг
рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП, рдЖрдк рдЙрд╕реА рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╡рд░реНрдЧ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
def test_cement(capsys): with todo_cement.TodoApp(argv=["add", "test"]) as app: app.run() out, _ = capsys.readouterr() assert out == EXPECTED
рдкрд░рд┐рдгрд╛рдо
рдкреЗрд╢реЗрд╡рд░реЛрдВ: рдПрдкреАрдЖрдИ рдХрд╛ рд╕реЗрдЯ рд╕реНрд╡рд┐рд╕ рдЪрд╛рдХреВ рдХреЗ рдПрдХ рд╕реЗрдЯ рдХреА рддрд░рд╣ рд╣реИ, рд╣реБрдХ рдФрд░ рдкреНрд▓рдЧрдЗрдиреНрд╕ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╡рд┐рд╕реНрддрд╛рд░, рдПрдХ рд╕реНрдерд┐рд░ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдФрд░ рд╕рдХреНрд░рд┐рдп рд╡рд┐рдХрд╛рд╕ред
рд╡рд┐рдкрдХреНрд╖: рдЦрд╛рд▓реА рдкреНрд░рд▓реЗрдЦрди рд╕реНрдерд╛рдиреЛрдВ рдореЗрдВ; рдЫреЛрдЯреА рд╕реАрдореЗрдВрдЯ-рдЖрдзрд╛рд░рд┐рдд рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдереЛрдбрд╝реА рдЬрдЯрд┐рд▓ рд▓рдЧ рд╕рдХрддреА рд╣реИрдВред
рдХреНрд▓рд┐рдпреЛ
рдХреНрд▓рд┐рдпреЛ рдЗрд╕ рддрд░рд╣ рдХреЗ рдПрдХ рд▓реЛрдХрдкреНрд░рд┐рдп рдврд╛рдВрдЪреЗ рдХреЗ рд░реВрдк рдореЗрдВ рджреВрд░ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣рд╛рдВ рд╕реВрдЪреАрдмрджреНрдз рдЕрдиреНрдп (рдХреБрд▓ рдорд┐рд▓рд╛рдХрд░ рдЧреАрдерд╣рдм рдкрд░ рд▓рдЧрднрдЧ 400 рд╕рд┐рддрд╛рд░реЗ) рд╣реИрдВ, рдФрд░ рдлрд┐рд░ рднреА рдореИрдВ рдпрд╣ рдЬрд╛рдирдиреЗ рдореЗрдВ рдХрд╛рдордпрд╛рдм рд░рд╣рд╛ рдХрд┐ рдЬрдм рдореИрдВрдиреЗ рдЕрдзреНрдпрдпрди рдХрд┐рдпрд╛ рдХрд┐ рдкреЛрдПрдЯреНрд░реА рдХреИрд╕реЗ рдЖрдЙрдЯрдкреБрдЯ рд╣реИред
рддреЛ, рдХреНрд▓рд┐рдпреЛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╡рд░реНрдгрд┐рдд рдХрд╡рд┐рддрд╛ рдХреЗ рд▓реЗрдЦрдХ рдХреА рдкрд░рд┐рдпреЛрдЬрдирд╛рдУрдВ рдореЗрдВ рд╕реЗ рдПрдХ рд╣реИ, рдЬреЛ рдирд┐рд░реНрднрд░рддрд╛, рд╡рд░реНрдЪреБрдЕрд▓реНрд╕ рдФрд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрд┐рд▓реНрдб рдХрд╛ рдкреНрд░рдмрдВрдзрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЙрдкрдХрд░рдг рд╣реИред рдХрд╡рд┐рддрд╛ рдкрд░ рдХрд╡рд┐рддрд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдПрдХ рд╕реЗ рдЕрдзрд┐рдХ рдмрд╛рд░ рд▓рд┐рдЦрд╛ рд╣реИ, рдФрд░ рдЗрд╕рдХреЗ рдХрдВрд╕реЛрд▓ рднрд╛рдЧ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ - рдирд╣реАрдВред
рдкрд╛рд░реНрд╕рд░
рдХреНрд▓рд┐рдпреЛ, рдЬреИрд╕реЗ рд╕реАрдореЗрдВрдЯ, рд╡рд╕реНрддреБ рд╕рд┐рджреНрдзрд╛рдВрддреЛрдВ рдкрд░ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдЕрд░реНрдерд╛рддреНред рдХрдорд╛рдВрдб рдХреНрд▓рд╛рд╕ рдФрд░ рдЙрд╕рдХреЗ рдбреЙрдХрд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдХрдорд╛рдВрдб рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рд╡рд┐рдХрд▓реНрдк () рд╡рд┐рдзрд┐, рдФрд░ рдЗрд╕реА рддрд░рд╣ рдПрдХреНрд╕реЗрд╕ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рд▓рд╛рдЗрди () рд╡рд┐рдзрд┐, рдЬреЛ рдкрд╛рда рдХреЛ рдЖрдЙрдЯрдкреБрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХреА рдЬрд╛рддреА рд╣реИ, рдмреЙрдХреНрд╕ рд╕реЗ рдмрд╛рд╣рд░ рд╡рд░реНрдмреЛрдЬрд╝ рдлрд╝реНрд▓реИрдЧ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд╢реИрд▓рд┐рдпреЛрдВ (рдпрд╛рдиреА рд░рдВрдЧ) рдФрд░ рдЖрдЙрдЯрдкреБрдЯ рдлрд╝рд┐рд▓реНрдЯрд░рд┐рдВрдЧ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддреА рд╣реИред рдХреНрд▓рд┐рдпреЛ рдореЗрдВ рдЯреЗрдмрд▓ рдЖрдЙрдЯрдкреБрдЯ рднреА рд╣реИред рдФрд░ рд╕рд▓рд╛рдЦреЛрдВ рдХреА рдкреНрд░рдЧрддрд┐ рднреАред рдФрд░ рдлрд┐рд░ рднреА ... рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░, рджреЗрдЦреЗрдВ:
рд╕реНрд░реЛрдд рдХреЛрдб from cleo import Command as BaseCommand
рдореБрдЦреНрдп
рд╕рднреА рдХреА рдЬрд░реВрд░рдд рд╣реИ рдХрд┐ рдПрдХ
cleo.Application рдСрдмреНрдЬреЗрдХреНрдЯ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдФрд░ рдлрд┐рд░ рдЗрд╕реЗ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП add_commands рдХреЛ рдХрдорд╛рдВрдб рдкрд╛рд╕ рдХрд░реЗрдВред рдкрд░реАрдХреНрд╖рдг рдХреЗ рджреМрд░рд╛рди рджреЛрд╣рд░рд╛рдирд╛ рдирд╣реАрдВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдпрд╣ рд╕рдм рдореБрдЦреНрдп рд╕реЗ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛:
from cleo import Application as BaseApplication class TodoApp(BaseApplication): def __init__(self): super().__init__(name="ToDo app - cleo version", version=todolib.__version__) self.add_commands(AddCommand(), ShowCommand(), DoneCommand(), RemoveCommand()) def main(args=None): TodoApp().run(args=args)
рдкрд░реАрдХреНрд╖рдг
рдХреНрд▓рд┐рдпреЛ рдореЗрдВ рдХрдорд╛рдВрдб рдХрд╛ рдкрд░реАрдХреНрд╖рдг рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП,
рдХрдорд╛рдВрдбрдЯреЗрд╕реНрдЯрд░ рд╣реИ , рдЬреЛ рдлреНрд░реЗрдорд╡рд░реНрдХ рдХреЗ рд╕рднреА рд╡рдпрд╕реНрдХ
рдЪрд╛рдЪрд╛рдУрдВ рдХреА рддрд░рд╣, I / O рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИ рдФрд░ рдмрд╛рд╣рд░ рдирд┐рдХрд▓рддрд╛ рд╣реИ:
def test_cleo(): app = todo_cleo.TodoApp() command = app.find("add") tester = cleo.CommandTester(command) tester.execute("test") assert tester.status_code == 0 assert tester.io.fetch_output() == "Task test created with number 0.\n"
рдкрд░рд┐рдгрд╛рдо
рдкреЗрд╢реЗрд╡рд░реЛрдВ: рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рдВрдХреЗрдд рдХреЗ рд╕рд╛рде рд╡рд╕реНрддреБ рд╕рдВрд░рдЪрдирд╛, рдЬреЛ рд╡рд┐рдХрд╛рд╕ рдХреЛ рд╕рд░рд▓ рдмрдирд╛рддрд╛ рд╣реИ (рдЪреВрдВрдХрд┐ рдХрдИ рдЖрдИрдбреАрдИ рдФрд░ рд╕рдВрдкрд╛рджрдХреЛрдВ рдХреЛ рдУрдУрдкреА рдХреЛрдб рдФрд░ рдЯрд╛рдЗрдкрд┐рдВрдЧ рдореЙрдбреНрдпреВрд▓ рдХреЗ рд▓рд┐рдП рдЕрдЪреНрдЫрд╛ рд╕рдорд░реНрдерди рд╣реИ); рди рдХреЗрд╡рд▓ рддрд░реНрдХреЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреА рдПрдХ рдЕрдЪреНрдЫреА рдорд╛рддреНрд░рд╛, рдмрд▓реНрдХрд┐ I / O рднреАред
рдкреНрд▓рд╕ рдпрд╛ рдорд╛рдЗрдирд╕: рдЗрд╕рдХрд╛ рд╡рд░реНрдмреЛрд╕рд┐рдЯреА рдкреИрд░рд╛рдореАрдЯрд░, рдЬреЛ рдХреЗрд╡рд▓ I / O рдХреНрд▓рд┐рдпреЛ / рдХреНрд▓рд┐рдЯ рдХреЗ рд╕рд╛рде рд╕рдВрдЧрдд рд╣реИред рдпрджреНрдпрдкрд┐ рдЖрдк рд▓реЙрдЧрд┐рдВрдЧ рдореЙрдбреНрдпреВрд▓ рдХреЗ рд▓рд┐рдП рдПрдХ рдХрд╕реНрдЯрдо рд╣реИрдВрдбрд▓рд░ рд▓рд┐рдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдпрд╣ рдХреНрд▓рд┐рдпреЛ рдХреЗ рд╡рд┐рдХрд╛рд╕ рдХреЗ рд╕рд╛рде рдмрдирд╛рдП рд░рдЦрдирд╛ рдореБрд╢реНрдХрд┐рд▓ рд╣реЛ рд╕рдХрддрд╛ рд╣реИред
рд╡рд┐рдкрдХреНрд╖: рд╕реНрдкрд╖реНрдЯ рд░реВрдк рд╕реЗ - рдПрдХ рд╡реНрдпрдХреНрддрд┐рдЧрдд рд░рд╛рдп - рдПрдХ рдпреБрд╡рд╛ рдПрдкреАрдЖрдИ: рдврд╛рдВрдЪреЗ рдореЗрдВ рдкреЛрдПрдЯреНрд░реА рдХреЛ рдЫреЛрдбрд╝рдХрд░ рдПрдХ рдФрд░ "рдмрдбрд╝реЗ" рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХрд╛ рдЕрднрд╛рд╡ рд╣реИ, рдФрд░ рдХреНрд▓рд┐рдпреЛ рд╡рд┐рдХрд╛рд╕ рдХреЗ рд╕рдорд╛рдирд╛рдВрддрд░ рдФрд░ рдПрдХ рдХреА рдЬрд░реВрд░рддреЛрдВ рдХреЗ рд▓рд┐рдП рд╡рд┐рдХрд╕рд┐рдд рд╣реЛ рд░рд╣рд╛ рд╣реИ; рдХрднреА-рдХрднреА рджрд╕реНрддрд╛рд╡реЗрдЬрд╝реАрдХрд░рдг рдкреБрд░рд╛рдирд╛ рд╣реЛрддрд╛ рд╣реИ (рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд▓реЙрдЧрд┐рдВрдЧ рд╕реНрддрд░ рдЕрдм рдХреНрд▓рд┐рдЯ рдореЙрдбреНрдпреВрд▓ рдореЗрдВ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди clikit.api.io.flags рдореЗрдВ рд╣реИ), рдФрд░ рд╕рд╛рдорд╛рдиреНрдп рддреМрд░ рдкрд░ рдпрд╣ рдЦрд░рд╛рдм рд╣реИ рдФрд░ рд╕рдВрдкреВрд░реНрдг API рдХреЛ рдкреНрд░рддрд┐рдмрд┐рдВрдмрд┐рдд рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред
рд╕реАрдореЗрдВрдЯ рдХреА рддреБрд▓рдирд╛ рдореЗрдВ рдХреНрд▓рд┐рдпреЛ, рд╕реАрдПрд▓рдЖрдИ рдкрд░ рдЕрдзрд┐рдХ рдХреЗрдВрджреНрд░рд┐рдд рд╣реИ, рдФрд░ рд╡рд╣ рдПрдХрдорд╛рддреНрд░ рдРрд╕рд╛ рд╡реНрдпрдХреНрддрд┐ рд╣реИ рдЬрд┐рд╕рдиреЗ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдЖрдЙрдЯрдкреБрдЯ рдореЗрдВ рдЕрдкрд╡рд╛рджреЛрдВ рдХреЗ рдкреНрд░рд╛рд░реВрдкрдг (рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд╕реНрдЯреИрдХ рдЯреНрд░реЗрд╕ рдХреЛ рдЫрд┐рдкрд╛рдиреЗ) рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪрд╛ рд╣реИред рд▓реЗрдХрд┐рди рд╡рд╣ - рдлрд┐рд░ рд╕реЗ рдПрдХ рд╡реНрдпрдХреНрддрд┐рдЧрдд рд░рд╛рдп - рдЕрдкрдиреА рдпреБрд╡рд╛рд╡рд╕реНрдерд╛ рдФрд░ рдПрдкреАрдЖрдИ рд╕реНрдерд┐рд░рддрд╛ рдореЗрдВ рд╕реАрдореЗрдВрдЯ рдХреЛ рдЦреЛ рджреЗрддрд╛ рд╣реИред
рдирд┐рд╖реНрдХрд░реНрд╖ рдореЗрдВ
рдЗрд╕ рдмрд┐рдВрджреБ рдкрд░, рд╣рд░ рдХрд┐рд╕реА рдХреЗ рдкрд╛рд╕ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЕрдкрдиреА рд░рд╛рдп рд╣реИ, рдЬреЛ рдмреЗрд╣рддрд░ рд╣реИ, рд▓реЗрдХрд┐рди рдирд┐рд╖реНрдХрд░реНрд╖ рдпрд╣ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП: рдореБрдЭреЗ рд╕рдмрд╕реЗ рдЕрдзрд┐рдХ рдкрд╕рдВрдж рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЗрд╕рдореЗрдВ рдмрд╣реБрдд рд╕рд╛рд░реА рдЪреАрдЬреЗрдВ рд╣реИрдВ рдФрд░ рдЗрд╕рдХреЗ рд╕рд╛рде рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдирд╛ рдФрд░ рдкрд░реАрдХреНрд╖рдг рдХрд░рдирд╛ рдХрд╛рдлреА рдЖрд╕рд╛рди рд╣реИред рдпрджрд┐ рдЖрдк рдХреЛрдб рдХреЛ рдиреНрдпреВрдирддрдо рд▓рд┐рдЦрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░рддреЗ рд╣реИрдВ - рдЖрдЧ рд╕реЗ рд╢реБрд░реВ рдХрд░реЗрдВред рдЖрдкрдХреА рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ рдореЗрдореНрдиреЗрдЪреНрдб рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдЬрд┐рдиреНрдЬрд╛ рдФрд░ рдПрдХреНрд╕реНрдЯреЗрдВрд╕рд┐рдмрд┐рд▓рд┐рдЯреА рдХреЗ рд╕рд╛рде рдкреНрд░рд╛рд░реВрдкрдг - рд╕реАрдореЗрдВрдЯ рд▓реЗ рд▓реЛ рдФрд░ рдЖрдкрдХреЛ рдЗрд╕рдХрд╛ рдЕрдлрд╕реЛрд╕ рдирд╣реАрдВ рд╣реЛрдЧрд╛ред рдЖрдкрдХреЗ рдкрд╛рд╕ рдПрдХ рдкрд╛рд▓рддреВ рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╣реИ рдпрд╛ рдХреБрдЫ рдФрд░ рдХреЛрд╢рд┐рд╢ рдХрд░рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ - рдХреНрд▓рд┐рдпреЛ рдХреЛ рджреЗрдЦреЗрдВред