{"assignment":{"_schema_version":2,"course_id":37,"date_created":"2022-06-28T19:00:00+00:00","date_modified":"2026-03-18T14:20:44.475901+00:00","extra_instructor_files":"","extra_starting_files":"","forked_id":null,"forked_version":null,"hidden":false,"id":1013,"instructions":"## Why External Functions\n\n```python try-randint\nfrom random import randint\n\n# Each of these prints a random number!\nprint(randint(0, 100))\nprint(randint(0, 100))\nprint(randint(0, 100))\nprint(randint(0, 100))\n```\n\nWe have previously used `import` statements to load variables defined in another module.\nBut even more common is to use `import` statements to load functions defined in another module.\nIn fact, Python has a large number of modules available through it's built-in \"standard library\".\nFor instance, the `random` module has many useful functions for producing random numbers, such as in the code shown here.\nUsing externally defined functions, we greatly increase the capabilities available to us.\n\n## Using External Functions\n\n```python try-math\nfrom math import floor, pi\n\ndef calculate_area(radius: int) -> int:\n    return floor(pi * radius ** 2)\n\nprint(calculate_area(5))\n```\n\nImported functions are just like any functions built into Python, or defined in your own code.\nOnce they're imported, you can use them inside of existing functions.\nWe can also use variables from other modules in the same way.\nIn this example, we import a function and variable from the `math` module to calculate the area of a circle and floor the result.\nFlooring means to remove any decimals, and is also known as trunctation.\n\n## Third Party Libraries\n\n![The official PyPi logo](bakery_functions_external_pypi.png)\n\nSome modules are not built into the regular Python distribution, but are available through other services.\nThe most popular repository of Python modules is named PyPi, which stands for the Python Package Index.\nAnyone is free to upload code to PyPi, which is both good and bad.\nAs long as you can trust a package to not act maliciously, you can get access to a huge set of powerful tools.\nUnfortunately, there have been cases where people have uploaded bad packages with names similar to well-known packages.\nThe bad actors took advantage of the fact that people are not always careful when writing out names, and sometimes make typos, to have them accidentally install their evil library instead.\nYou must be very careful when installing software from the internet, thinking critically and paying close attention to what you agree to do.\n\n## Drafter\n\n* Drafter: A Python library for creating web applications\n\nBlockPy has some popular libraries already pre-installed.\nOne library that we can use is named `Drafter`, meant for making simple web applications.\nThere are many Python libraries for making web applications, but Drafter is a lightweight and easy-to-use option.\n\n## Drafter Example\n\n```python drafter-basic\nfrom drafter import *\n\nstart_server()\n```\n\nThe example code here shows the simplest, most boring Drafter program.\nAfter importing the `drafter` module, we can start a web server.\nThis will create a new window that just says \"Hello world! Welcome to Drafter.\"\nThis will be our web application.\nThere is also a lot of debug information displayed below the website, but we can ignore that for now.\n\nNormally you would deploy a web application through a web server, so that other users can access it over the internet.\nWe will eventually see how to deploy Drafter applications, but for now we will just run them locally in BlockPy.\n\n## Simple Drafter Site\n\n```python simple-site\nfrom drafter import *\n\n@route\ndef index() -> Page:\n    return Page(\"Welcome to my Drafter site!\")\n\nstart_server()\n```\n\nInstead of returning the default message, we can customize the page content by defining a **route**.\nIn Drafter, a `route` is a function that returns a `Page`, and requires a special Python feature called a **decorator** (the `@route` syntax above the function definition). The `Page` function creates a new web page with the specified content. We will learn more about decorators and the reason why we capitalize `Page` when we learn about Dataclasses. For now, we will ignore these details and focus on writing the content.\n\n## Bolder Text\n\n```python drafter-bolder-text\nfrom drafter import *\n\n@route\ndef index() -> Page:\n    return Page(bold(\"This is exciting!\"))\n\nstart_server()\n```\n\nDrafter has a large number of functions to let us style our text and create more complex layouts.\nOne of the simpler functions is `bold`, which makes its argument bolded (the text with thicker lettering).\nHere, we have passed the string `\"This is exciting!\"` to the `bold` function, which we in turn pass to the `Page` function as we did before.\n\n## Composing Functions\n\n```python drafter-composing-functions\nfrom drafter import *\n\n@route\ndef index() -> Page:\n    original_text = \"This is exciting!\"\n    content = bold(italic(change_color(original_text, \"blue\")))\n    return Page(content)\n\nstart_server()\n```\n\nDrafter's large collection of functions also include `italic`, which makes its argument italicized (the text slanted to the right), and `change_color`, which changes the color of the text.\nSince these are just regular Python functions, we can compose them together to create more complex styles.\nThe code shown here will make the text `This is exciting!` bold, italicized, and blue.\n\nTo help you see how we can compose these functions, we broke it down into separate lines.\nFirst, we assigned the original text to a variable. Then, we applied each function one at a time, passing the result of each function to the next one.\nThen, we returned the final result wrapped in a `Page`.\nWe could have done this all as a single expression.\n\n## Multiple Lines of Content\n\n```python drafter-multiple-lines\nfrom drafter import *\n\n@route\ndef index() -> Page:\n    return Page(Div(\n        italic(\"This\"),\n        \" is \",\n        bold(\"exciting!\"),\n    ))\n\nstart_server()\n```\n\nIn addition to functions for styling and formatting text, Drafter also has functions for \"components\". These will always begin with a capital letter, kind of like `Page`. The `Div` component (which stands for \"Division\") is used to arrange its children in a line.\nHere, we create a single sentence that is composed of three parts: an italicized word, a regular word, and a bold word.\nThere are quite a few components, which are usually used for getting user input or displaying data in a structured way.\n\n## Drafter Tests\n\n```python drafter-tests\nfrom bakery import assert_equal\nfrom drafter import *\n\n@route\ndef index() -> Page:\n    return Page(Div(\n        italic(\"This\"),\n        \" is \",\n        bold(\"exciting!\"),\n    ))\n\nassert_equal(index(), Page(Div(\n    italic(\"This\"),\n    \" is \",\n    bold(\"exciting!\"),\n)))\n```\n\nA useful feature of Drafter is that we can write tests for our routes. This allows us to verify that our web application behaves as expected.\nFor now, the tests will not be very exciting, since the output is always the same.\nOnce we start incorporating user input and dynamic content, the tests will become more interesting.\n\nObserve that we call the `index()` function in our test, and then compare the result to the result of calling the `Page` function with the same content. Usually, you would write tests that compare against a literal value, but testing functions like `Div` and `Page` can be a bit more complex.\nWe will eventually learn how to make Drafter generate these kinds of tests automatically.\nFor now, it is enough to simply know that we can use the `assert_equal` function to compare the output of our route to an expected value.\n\n## More About Drafter\n\n-   For more information, check out the Drafter website!\n\nThe Drafter library has a ton of functions and features that you can use to make fully interactive, rich applications.\nWe'll be revisiting the library more throughout this semester, as we learn new code constructs and abilities.\nHowever, if you're excited about Drafter, and wish to learn more, you can visit the link shown to start reading over the [Drafter documentation and quick start guides](https://drafter-edu.github.io/drafter/quickstart/quickstart.html).\n\n## Summary\n\n-   Functions can be defined in third-party libraries, and then imported into your application.\n-   Drafter is a powerful library for creating web applications with rich text formatting and layout components.\n-   The key building block of Drafter is creating **route** functions (using the `@route` decorator), which are functions that return `Page` components.\n-   Drafter provides a variety of functions for styling text, such as `bold`, `italic`, and `change_color`.\n-   You can compose Drafter functions to create complex styles and layouts.\n-   Drafter also includes components like `Div` for structuring your content.\n-   Testing your routes is easy with the `assert_equal` function, allowing you to verify the output of your application.\n","ip_ranges":"","name":"2B4) External Functions Reading","on_change":"","on_eval":"","on_run":"","owner_id":1,"owner_id__email":"acbart@udel.edu","points":0,"public":true,"reviewed":false,"sample_submissions":[],"settings":"{\n  \"small_layout\": true,\n  \"header\": \"External Functions\",\n  \"slides\": \"bakery_functions_external.pdf\"\n}","starting_code":"","subordinate":true,"tags":[],"type":"reading","url":"bakery_functions_external_read","version":17},"ip":"216.73.216.157","submission":{"_schema_version":3,"assignment_id":1013,"assignment_version":17,"attempts":0,"code":"","correct":false,"course_id":37,"date_created":"2026-05-20T14:01:57.538003+00:00","date_due":"","date_graded":"","date_locked":"","date_modified":"2026-05-20T14:01:57.538003+00:00","date_started":"","date_submitted":"","endpoint":"","extra_files":"","feedback":"","grading_status":"NotReady","id":2036937,"score":0.0,"submission_status":"Started","time_limit":"","url":"submission_url-36abe30d-ac04-4297-951e-c1637e7b2d65","user_id":2044668,"user_id__email":"","version":0},"success":true}
