From 423f7069df77485be615ff739462243c5380afd8 Mon Sep 17 00:00:00 2001 From: Jose Salvatierra Date: Fri, 21 Oct 2022 11:47:53 +0100 Subject: [PATCH] feat(ebook): start ebook structure for this course --- .gitignore | 21 ++++ CONTRIBUTING.md | 38 ++++++ content.py | 117 ++++++++++++++++++ course_contents/10_advanced_python/README.md | 4 + course_contents/11_web_scraping/README.md | 4 + .../12_browser_automation_selenium/README.md | 4 + .../13_async_development/README.md | 4 + .../lectures/01_code_samples/README.md | 19 +++ .../02_async_terms_glossary/README.md | 27 ++++ .../14_managing_projects_pipenv/README.md | 4 + course_contents/15_flask/README.md | 4 + .../16_interacting_with_apis/README.md | 4 + course_contents/17_decorators/README.md | 4 + course_contents/18_advanced_oop/README.md | 4 + .../19_gui_development_tkinter/README.md | 5 + course_contents/1_intro/README.md | 5 + course_contents/20_unit_testing/README.md | 5 + .../21_algorithms_data_structures/README.md | 5 + .../22_popular_libraries/README.md | 5 + course_contents/2_intro_to_python/README.md | 4 + .../2_intro_to_python/notes/README.md | 60 --------- .../3_first_milestone_project/README.md | 4 + .../4_object_oriented_programming/README.md | 4 + course_contents/5_errors/README.md | 4 + course_contents/6_files/README.md | 4 + .../7_second_milestone_project/README.md | 4 + course_contents/8_type_hinting/README.md | 4 + .../9_advanced_built_in_functions/README.md | 4 + course_contents/Pipfile | 14 --- course_contents/Pipfile.lock | 74 ----------- mkdocs.yml | 25 ++++ requirements-docs.txt | 5 + requirements.txt | 0 33 files changed, 345 insertions(+), 148 deletions(-) create mode 100644 CONTRIBUTING.md create mode 100644 content.py create mode 100644 course_contents/13_async_development/lectures/01_code_samples/README.md create mode 100644 course_contents/13_async_development/lectures/02_async_terms_glossary/README.md delete mode 100644 course_contents/2_intro_to_python/notes/README.md delete mode 100644 course_contents/Pipfile delete mode 100644 course_contents/Pipfile.lock create mode 100644 mkdocs.yml create mode 100644 requirements-docs.txt create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore index e94bb07..a6fd53b 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,24 @@ videos/ **/old .venv .python-version + +# Dependencies +/node_modules + +# Production +/build + +# Generated files +.docusaurus +.cache-loader + +# Misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..1ae8e91 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,38 @@ +# Contributing + +## Building the docs + +Write your documentation inside `course_contents`. + +To build and serve the documentation, use this command: + +```bash +watchmedo shell-command --patterns="*.md" --recursive course_contents --command="cog -r mkdocs.yml" +``` + +This runs the `cog -r mkdocs.yml` command every time there is a markdown file change. + +**note**: at the moment there is [a bug](https://github.com/gorakhargosh/watchdog/issues/346) in `watchmedo` that triggers the shell command twice on file modification, or potentially a few times on file creation. It doesn't affect us majorly. + +### Why do we need to use `cog` to build the docs before serving? + +The documentation system we use for this e-book, `mkdocs`, has limitation regarding slugs: all slugs are calculated from the filesystem paths. + +This means that if we simply serve the docs from `course_contents`, all our slugs would be numbered (e.g. `1_intro/lectures/3_variables_printing/`). + +To avoid this, we first run a build step (in `content.py`, `build_and_get_yaml_contents()`) that copies all the non-hidden sections and lectures to a `build` folder, and then we can serve the documentation from there. + +This is a bit "hacky", and we must remember to run `cog` on the `mkdocs.yml` file if we want to see our updated documentation! + +## Writing documentation README files + +There are a few attributes for each `README.md` file that we can use. + +In section files: + +- `group: str` will try to place sections with the same group name inside a tabbed navigation. +- `hidden: true | false` will hide the section and its lectures, and not include any of them in the build. + +In lecture files: + +- `hidden: true | false` will hide the lecture and not include it in the build. Other lectures in the same section are unaffected. diff --git a/content.py b/content.py new file mode 100644 index 0000000..fa5062e --- /dev/null +++ b/content.py @@ -0,0 +1,117 @@ +import glob +import json +import pathlib +import shutil +import string +import markdown +from bs4 import BeautifulSoup + +def get_grouped_sections(root: str = "course_contents") -> dict[str, list]: + sections = get_all_sections_with_content(root) + grouped_sections = {} + for section in sections: + group = section["index"]["group"] + if not group: + raise RuntimeError("Not all sections part of a group.") + if group: + grouped_sections.setdefault(group, []).append(section) + else: + grouped_sections.setdefault("default", []).append(section) + return grouped_sections + +def get_all_sections_with_content(root: str = "course_contents"): + root_path = pathlib.Path(root) + section_folders = [folder.name for folder in root_path.iterdir() if folder.is_dir() and folder.name[0] in string.digits] + sections = sorted(section_folders, key=lambda e: int(str(e).split("_")[0])) + for section in sections: + section = root_path / section + section_index = get_lecture_content(section / "README.md") + if not section_index.get("title") or section_index.get("hidden"): + continue + lectures = get_section_lectures(section) + lecture_contents = [get_lecture_content(lecture) for lecture in lectures] + non_hidden_lectures = [lecture for lecture in lecture_contents if not lecture.get("hidden")] + yield {"index": section_index, "lectures": non_hidden_lectures} + + +def get_section_lectures(folder: pathlib.Path | str) -> list[str]: + """Return a list of pathlib.Path objects for all lectsures in a section folder""" + lecture_path = pathlib.Path(folder) / "lectures" + return sorted([folder for folder in lecture_path.glob("*/README.md")]) + + +def get_lecture_content(lecture_path: pathlib.Path, root_path: str | pathlib.Path = "course_contents") -> dict[str, str]: + """Return a dictionary of lecture content. + Return a dictionary with the following keys: + - title, the h1 from the markdown file + - summary from the markdown metadata + - group, to group sections together, optional + - hidden, to hide entire sections, optional + - filename, the name of the markdown file + - full_path, the full path to the markdown file + - order, the order of the lecture in the section (defaults to file name) + - path, the path to this file relative to the root""" + with open(lecture_path) as f: + content = f.read() + md = markdown.Markdown(extensions=["meta"]) + html = md.convert(content) + soup = BeautifulSoup(html, "html.parser") + return { + "title": soup.find("h1").text, + "summary": md.Meta.get("summary", ""), + "group": md.Meta.get("group", [""])[0], + "hidden": md.Meta.get("hidden", [""])[0] == "true", + "filename": lecture_path.name, + "full_path": lecture_path.absolute(), + "order": md.Meta.get("order", [lecture_path.name])[0], + "path": lecture_path.relative_to(root_path), + } + + +def get_grouped_build_sections(root: str = "build") -> dict[str, list]: + sections = build_and_get_yaml_contents(root) + grouped_sections = {} + for section in sections: + group = section["index"]["group"] + if not group: + raise RuntimeError("Not all sections part of a group.") + if group: + grouped_sections.setdefault(group, []).append(section) + else: + grouped_sections.setdefault("default", []).append(section) + return grouped_sections + + +def build_and_get_yaml_contents(build_path: str = "build"): + # Delete contents of the build directory + shutil.rmtree(build_path, ignore_errors=True) + sections = get_all_sections_with_content() + for section in sections: + # Strip the leading numbers of the section folder + old_section_name = section["index"]["full_path"].parent.name + section_name = "_".join(old_section_name.split("_")[1:]) + # Create a directory in the build folder matching the section_name + pathlib.Path(build_path, section_name).mkdir(parents=True, exist_ok=True) + # Copy the README.md file from the original section to the new directory + shutil.copyfile(section["index"]["full_path"], pathlib.Path(build_path, section_name, "README.md")) + # Copy the lecture folders to the new directory + section["lectures"] = list(copy_lectures_to_build_path(section, section_name, build_path=build_path)) + # Update the section index to point to the new path + section["index"]["full_path"] = pathlib.Path(build_path, section_name, "README.md").absolute() + section["index"]["path"] = pathlib.Path(build_path, section_name, "README.md").relative_to(build_path) + yield section + + +def copy_lectures_to_build_path(section: dict, new_section_name: str, build_path: str = "build"): + for lecture in section["lectures"]: + lecture_name = "_".join(lecture["full_path"].parent.name.split("_")[1:]) + pathlib.Path(build_path, new_section_name, lecture_name).mkdir(parents=True, exist_ok=True) + shutil.copyfile(lecture["full_path"], pathlib.Path(build_path, new_section_name, lecture_name, "README.md")) + lecture["full_path"] = pathlib.Path(build_path, new_section_name, lecture_name, "README.md").absolute() + lecture["path"] = pathlib.Path(build_path, new_section_name, lecture_name, "README.md").relative_to(build_path) + yield lecture + + +if __name__ == "__main__": + section_yaml = get_grouped_build_sections() + print(list(section_yaml)) \ No newline at end of file diff --git a/course_contents/10_advanced_python/README.md b/course_contents/10_advanced_python/README.md index c10bdab..8ca3de4 100644 --- a/course_contents/10_advanced_python/README.md +++ b/course_contents/10_advanced_python/README.md @@ -1,3 +1,7 @@ +--- +group: Intermediate +hidden: true +--- # Advanced Python Development In this section of the course we look at some advanced Python features, such as: diff --git a/course_contents/11_web_scraping/README.md b/course_contents/11_web_scraping/README.md index 7589ed2..c0de55d 100644 --- a/course_contents/11_web_scraping/README.md +++ b/course_contents/11_web_scraping/README.md @@ -1,3 +1,7 @@ +--- +group: Practical Python +hidden: true +--- # Web Scraping In this section we look at web scraping using Python and the `requests` library. diff --git a/course_contents/12_browser_automation_selenium/README.md b/course_contents/12_browser_automation_selenium/README.md index 79899dd..7c7cdc2 100644 --- a/course_contents/12_browser_automation_selenium/README.md +++ b/course_contents/12_browser_automation_selenium/README.md @@ -1,3 +1,7 @@ +--- +group: Practical Python +hidden: true +--- # Browser automation with Selenium The code is very similar to last section, but now we're launching a browser instead of requesting the page with Python. We will be controlling the browser, instead of just getting HTML. diff --git a/course_contents/13_async_development/README.md b/course_contents/13_async_development/README.md index 4bd0213..4a13976 100644 --- a/course_contents/13_async_development/README.md +++ b/course_contents/13_async_development/README.md @@ -1,3 +1,7 @@ +--- +group: Practical Python +hidden: false +--- # Async Development with Python Python is a single-threaded language, which means that asynchronous development can sometimes be tricky. diff --git a/course_contents/13_async_development/lectures/01_code_samples/README.md b/course_contents/13_async_development/lectures/01_code_samples/README.md new file mode 100644 index 0000000..b9e822b --- /dev/null +++ b/course_contents/13_async_development/lectures/01_code_samples/README.md @@ -0,0 +1,19 @@ +--- +hidden: false +--- + +# Code samples for this section + +Hey, welcome back! + +This section won't have code available on our online editor, but instead all the code we'll write here is available on the GitHub page. + +Again, don't read through the code before going through some of the videos. The code is here for you to check as you progress through the section. Otherwise, it could get a bit confusing! + +Here's a link to the code in this section: https://github.com/tecladocode/complete-python-course/tree/master/course_contents/13_async_development/sample_code + +As always, if you have any questions please ask away in the Course Q&A. + +Happy coding! + +Jose—your instructor \ No newline at end of file diff --git a/course_contents/13_async_development/lectures/02_async_terms_glossary/README.md b/course_contents/13_async_development/lectures/02_async_terms_glossary/README.md new file mode 100644 index 0000000..a2f75fe --- /dev/null +++ b/course_contents/13_async_development/lectures/02_async_terms_glossary/README.md @@ -0,0 +1,27 @@ +--- +hidden: true +--- + +# Glossary of terms used in concurrency + +Hey there! Welcome to one of the most advanced topics in Python. A lot of developers are scared of what we're going to learn in this section. + +You shouldn't be scared! + +We'll start at the fundamentals, and build out our knowledge of asynchronous development from the ground up. + +Throughout the section we'll learn more about what these terms mean, but it can be helpful to have a short glossary of terms just in case you want to come back and remind yourself. + +- **Synchronous**: actions that happen one after another. Programming as we've seen it until now is synchronous, because each line executes after the previous one. +- **Asynchronous**: actions that don't necessary happen after one another, or that can happen in arbitrary order ("without synchrony"). +- **Concurrency**: The ability of our programs to run things in different order every time the program runs, without affecting the final outcome. +- **Parallelism**: Running two or more things at the same time. +- **Thread**: A line of code execution that can run in one of your computer's cores. +- **Process**: One of more threads and the resources they need (e.g. network connection, mouse pointer, hard drive access, or even the core(s) in which the thread(s) run). +- **GIL**: A key, critical, important resource in any Python program. Only one is created per Python process, so it's unique in each. + +Take it slowly through this section, and ask questions in the Course Q&A as required. We're here to help! + +Kind regards, + +Jose \ No newline at end of file diff --git a/course_contents/14_managing_projects_pipenv/README.md b/course_contents/14_managing_projects_pipenv/README.md index 60e8b89..9cd5d71 100644 --- a/course_contents/14_managing_projects_pipenv/README.md +++ b/course_contents/14_managing_projects_pipenv/README.md @@ -1,3 +1,7 @@ +--- +group: Practical Python +hidden: true +--- # Managing projects with Pipenv In this section we briefly look at managing your project dependencies using Pipenv. diff --git a/course_contents/15_flask/README.md b/course_contents/15_flask/README.md index a768549..4e3a075 100644 --- a/course_contents/15_flask/README.md +++ b/course_contents/15_flask/README.md @@ -1,3 +1,7 @@ +--- +group: Practical Python +hidden: true +--- # Web Development with Flask In this section we learn about making websites using the Flask framework, HTML, and Jinja. diff --git a/course_contents/16_interacting_with_apis/README.md b/course_contents/16_interacting_with_apis/README.md index dc66afc..a9bbd32 100644 --- a/course_contents/16_interacting_with_apis/README.md +++ b/course_contents/16_interacting_with_apis/README.md @@ -1,3 +1,7 @@ +--- +group: Practical Python +hidden: true +--- # Interacting with APIs ## Requirements diff --git a/course_contents/17_decorators/README.md b/course_contents/17_decorators/README.md index 7bac0b0..424d6ef 100644 --- a/course_contents/17_decorators/README.md +++ b/course_contents/17_decorators/README.md @@ -1,3 +1,7 @@ +--- +group: Advanced +hidden: true +--- # Decorators in Python Decorators allow us to extend another function without modifying it directly. diff --git a/course_contents/18_advanced_oop/README.md b/course_contents/18_advanced_oop/README.md index 716f7b6..47ecb5b 100644 --- a/course_contents/18_advanced_oop/README.md +++ b/course_contents/18_advanced_oop/README.md @@ -1,3 +1,7 @@ +--- +group: Advanced +hidden: true +--- # Advanced Object-Oriented Programming with Python In this section we look at some more advanced OOP concepts, such as multiple inheritance, abstract classes, interfaces, and properties. diff --git a/course_contents/19_gui_development_tkinter/README.md b/course_contents/19_gui_development_tkinter/README.md index c4e9342..ffcd61d 100644 --- a/course_contents/19_gui_development_tkinter/README.md +++ b/course_contents/19_gui_development_tkinter/README.md @@ -1,3 +1,8 @@ +--- +group: Advanced +hidden: true +--- + # GUI Development with Tkinter In this section we learn about making desktop applications using Python's `tkinter` library. diff --git a/course_contents/1_intro/README.md b/course_contents/1_intro/README.md index 6c6e50e..e720ad2 100644 --- a/course_contents/1_intro/README.md +++ b/course_contents/1_intro/README.md @@ -1,3 +1,8 @@ +--- +group: Introduction +hidden: true +--- + # Course Introduction In this section we assume you are at the very starting point of coding. diff --git a/course_contents/20_unit_testing/README.md b/course_contents/20_unit_testing/README.md index e0b39cf..e785ad5 100644 --- a/course_contents/20_unit_testing/README.md +++ b/course_contents/20_unit_testing/README.md @@ -1,3 +1,8 @@ +--- +group: Advanced +hidden: true +--- + # Unit testing with Python Unit testing means writing some code that checks other code you've written, to make sure it works as intended. diff --git a/course_contents/21_algorithms_data_structures/README.md b/course_contents/21_algorithms_data_structures/README.md index fb221c5..f15a23c 100644 --- a/course_contents/21_algorithms_data_structures/README.md +++ b/course_contents/21_algorithms_data_structures/README.md @@ -1,3 +1,8 @@ +--- +group: Advanced +hidden: true +--- + # Algorithms and Data Structures with Python In this section we learn about algorithms and data structures, two topics that are essential when finding a software development job. diff --git a/course_contents/22_popular_libraries/README.md b/course_contents/22_popular_libraries/README.md index 4ff0ab0..d53f714 100644 --- a/course_contents/22_popular_libraries/README.md +++ b/course_contents/22_popular_libraries/README.md @@ -1,3 +1,8 @@ +--- +group: Advanced +hidden: true +--- + # Python Libraries and Tools In this section I'll show you some popular Python libraries and tools that you can use to make your project development easier, or to extend your projects. diff --git a/course_contents/2_intro_to_python/README.md b/course_contents/2_intro_to_python/README.md index 63443c4..90b448b 100644 --- a/course_contents/2_intro_to_python/README.md +++ b/course_contents/2_intro_to_python/README.md @@ -1,3 +1,7 @@ +--- +group: Introduction +hidden: true +--- # Python Fundamentals This section goes deeper into Python, covering many essential features. diff --git a/course_contents/2_intro_to_python/notes/README.md b/course_contents/2_intro_to_python/notes/README.md deleted file mode 100644 index a3ba7f2..0000000 --- a/course_contents/2_intro_to_python/notes/README.md +++ /dev/null @@ -1,60 +0,0 @@ -# Python Conditions - -## `if` statements - -## `elif` statements - -## `else` statements - - -# Python Loops - -## `for` loops - -### looping through a dictionary - -### the `range()` function - -### the `break` keyword - -### the `continue` keyword - -### the `pass` keyword - -### the `else` keyword - -### nested `for` loops - -## `while` loops - -### the `break` keyword - -### the `continue` keyword - -### the `else` keyword - - -# Python comprehensions - -## list comprehensions - -## set comprehensions - -## dictionary comprehensions - -## comprehensions with conditions - -## the `map()` function - -## the `filter()` function - - -# Python Destructuring - -## list slicing - -## the `enumerate()` function - -## the `zip()` function - -## unpacking \ No newline at end of file diff --git a/course_contents/3_first_milestone_project/README.md b/course_contents/3_first_milestone_project/README.md index 4b1dc10..28bb4ef 100644 --- a/course_contents/3_first_milestone_project/README.md +++ b/course_contents/3_first_milestone_project/README.md @@ -1,3 +1,7 @@ +--- +group: Introduction +hidden: true +--- # First Milestone Project In this section we build the first project of the course. Please see the [project brief](milestone_project_brief.pdf) for information on what the project should do. \ No newline at end of file diff --git a/course_contents/4_object_oriented_programming/README.md b/course_contents/4_object_oriented_programming/README.md index de247eb..3595821 100644 --- a/course_contents/4_object_oriented_programming/README.md +++ b/course_contents/4_object_oriented_programming/README.md @@ -1,3 +1,7 @@ +--- +group: Introduction +hidden: true +--- # Object-Oriented Programming in Python This section talks about object-oriented programming in Python. We start off by looking at dictionaries, and how dictionaries are similar to objects--but limited in certain ways. diff --git a/course_contents/5_errors/README.md b/course_contents/5_errors/README.md index ec2887c..59c77c2 100644 --- a/course_contents/5_errors/README.md +++ b/course_contents/5_errors/README.md @@ -1,3 +1,7 @@ +--- +group: Introduction +hidden: true +--- # Errors in Python In this section we'll learn about errors and exceptions in Python. We can use them for flow control by following the "ask for forgiveness rather than permission" part of the Python ethos. diff --git a/course_contents/6_files/README.md b/course_contents/6_files/README.md index ed6a32b..2068da7 100644 --- a/course_contents/6_files/README.md +++ b/course_contents/6_files/README.md @@ -1,3 +1,7 @@ +--- +group: Intermediate +hidden: true +--- # Working with Files in Python In this section we build a project that stores data in two types of file: CSV and JSON. diff --git a/course_contents/7_second_milestone_project/README.md b/course_contents/7_second_milestone_project/README.md index 95a1d66..47ef117 100644 --- a/course_contents/7_second_milestone_project/README.md +++ b/course_contents/7_second_milestone_project/README.md @@ -1,3 +1,7 @@ +--- +group: Intermediate +hidden: true +--- # Milestone Project 2 In this section we build the second project of the course. Please see the [project brief](Milestone%20Project%202%20Brief.pdf) for information on what the project should do. \ No newline at end of file diff --git a/course_contents/8_type_hinting/README.md b/course_contents/8_type_hinting/README.md index d528e7b..3758338 100644 --- a/course_contents/8_type_hinting/README.md +++ b/course_contents/8_type_hinting/README.md @@ -1,3 +1,7 @@ +--- +group: Intermediate +hidden: true +--- # Type hinting in Python This is a short section in the video course which covers an introduction to type hinting in Python by adding type hints to Milestone Project 2. diff --git a/course_contents/9_advanced_built_in_functions/README.md b/course_contents/9_advanced_built_in_functions/README.md index e954eaa..524af54 100644 --- a/course_contents/9_advanced_built_in_functions/README.md +++ b/course_contents/9_advanced_built_in_functions/README.md @@ -1,3 +1,7 @@ +--- +group: Intermediate +hidden: true +--- # Advanced built-in functions in Python In this section we will learn about generators, iterators, and iterables. Then we'll look at some advanced built-in functions that can come in very handy: `filter`, `map`, `any`, `all`, and `enumerate`. \ No newline at end of file diff --git a/course_contents/Pipfile b/course_contents/Pipfile deleted file mode 100644 index c10cf2e..0000000 --- a/course_contents/Pipfile +++ /dev/null @@ -1,14 +0,0 @@ -[[source]] -name = "pypi" -url = "https://pypi.org/simple" -verify_ssl = true - -[dev-packages] - -[packages] -requests = "*" -cachetools = "*" -selenium = "*" - -[requires] -python_version = "3.7" diff --git a/course_contents/Pipfile.lock b/course_contents/Pipfile.lock deleted file mode 100644 index ca89ebf..0000000 --- a/course_contents/Pipfile.lock +++ /dev/null @@ -1,74 +0,0 @@ -{ - "_meta": { - "hash": { - "sha256": "58413ec4d9d0c2557c657aad80762bfce4f49f4396f939ab67cff3a7972eb9c1" - }, - "pipfile-spec": 6, - "requires": { - "python_version": "3.7" - }, - "sources": [ - { - "name": "pypi", - "url": "https://pypi.org/simple", - "verify_ssl": true - } - ] - }, - "default": { - "cachetools": { - "hashes": [ - "sha256:428266a1c0d36dc5aca63a2d7c5942e88c2c898d72139fca0e97fdd2380517ae", - "sha256:8ea2d3ce97850f31e4a08b0e2b5e6c34997d7216a9d2c98e0f3978630d4da69a" - ], - "index": "pypi", - "version": "==3.1.1" - }, - "certifi": { - "hashes": [ - "sha256:1a4995114262bffbc2413b159f2a1a480c969de6e6eb13ee966d470af86af59c", - "sha256:719a74fb9e33b9bd44cc7f3a8d94bc35e4049deebe19ba7d8e108280cfd59830" - ], - "version": "==2020.12.5" - }, - "chardet": { - "hashes": [ - "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", - "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" - ], - "version": "==3.0.4" - }, - "idna": { - "hashes": [ - "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", - "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c" - ], - "version": "==2.8" - }, - "requests": { - "hashes": [ - "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4", - "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31" - ], - "index": "pypi", - "version": "==2.22.0" - }, - "selenium": { - "hashes": [ - "sha256:2d7131d7bc5a5b99a2d9b04aaf2612c411b03b8ca1b1ee8d3de5845a9be2cb3c", - "sha256:deaf32b60ad91a4611b98d8002757f29e6f2c2d5fcaf202e1c9ad06d6772300d" - ], - "index": "pypi", - "version": "==3.141.0" - }, - "urllib3": { - "hashes": [ - "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc", - "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc" - ], - "index": "pypi", - "version": "==1.25.8" - } - }, - "develop": {} -} diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..047a176 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,25 @@ +site_name: Teclado +docs_dir: build +theme: + name: material + features: + - navigation.sections + - navigation.tabs +nav: + #[[[cog + #from content import get_grouped_build_sections + #groups = get_grouped_build_sections() + #for group in groups: + # cog.outl(f"- {group}:") + # for section in groups[group]: + # cog.outl(f" - {section['index']['title']}:") + # cog.outl(f" - Section Introduction: {section['index']['path']}") + # for lecture in section['lectures']: + # if not lecture["hidden"]: + # cog.outl(f" - {lecture['title']}: {lecture['path']}") + #]]] + - Practical Python: + - Async Development with Python: + - Section Introduction: async_development/README.md + - Code samples for this section: async_development/code_samples/README.md + #[[[end]]] diff --git a/requirements-docs.txt b/requirements-docs.txt new file mode 100644 index 0000000..2280428 --- /dev/null +++ b/requirements-docs.txt @@ -0,0 +1,5 @@ +mkdocs +mkdocs-material +cogapp +markdown +watchdog[watchmedo] \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..e69de29