├── .github ├── ISSUE_TEMPLATE │ └── new-course.md └── workflows │ ├── push-courses.yml │ └── run-tests.yml ├── .gitignore ├── Makefile ├── README.md ├── build ├── __init__.py ├── api.py ├── cli.py ├── image.py ├── nav.py └── workspace.py ├── courses ├── assets │ ├── codemirror │ │ ├── LICENSE │ │ ├── README.txt │ │ ├── addon │ │ │ ├── comment │ │ │ │ ├── comment.js │ │ │ │ └── continuecomment.js │ │ │ ├── edit │ │ │ │ ├── closebrackets.js │ │ │ │ ├── closetag.js │ │ │ │ ├── continuelist.js │ │ │ │ ├── matchbrackets.js │ │ │ │ ├── matchtags.js │ │ │ │ └── trailingspace.js │ │ │ └── mode │ │ │ │ ├── loadmode.js │ │ │ │ ├── multiplex.js │ │ │ │ ├── multiplex_test.js │ │ │ │ ├── overlay.js │ │ │ │ └── simple.js │ │ ├── keymap │ │ │ ├── emacs.js │ │ │ ├── sublime.js │ │ │ └── vim.js │ │ ├── lib │ │ │ ├── codemirror.css │ │ │ └── codemirror.js │ │ └── mode │ │ │ ├── css │ │ │ ├── css.js │ │ │ ├── gss.html │ │ │ ├── gss_test.js │ │ │ ├── index.html │ │ │ ├── less.html │ │ │ ├── less_test.js │ │ │ ├── scss.html │ │ │ ├── scss_test.js │ │ │ └── test.js │ │ │ ├── go │ │ │ ├── go.js │ │ │ └── index.html │ │ │ ├── htmlmixed │ │ │ ├── htmlmixed.js │ │ │ └── index.html │ │ │ ├── javascript │ │ │ ├── index.html │ │ │ ├── javascript.js │ │ │ ├── json-ld.html │ │ │ ├── test.js │ │ │ └── typescript.html │ │ │ ├── python │ │ │ ├── index.html │ │ │ ├── python.js │ │ │ └── test.js │ │ │ ├── rust │ │ │ ├── index.html │ │ │ ├── rust.js │ │ │ └── test.js │ │ │ └── xml │ │ │ ├── index.html │ │ │ ├── test.js │ │ │ └── xml.js │ ├── livecode.js │ └── style.css ├── authoring-courses-on-mon-school │ ├── content │ │ ├── examples.md │ │ ├── exercises.md │ │ ├── generating-files.md │ │ ├── lessons.md │ │ ├── outline.md │ │ └── preview-image.md │ ├── course.yml │ └── welcome │ │ └── monschool.md ├── building-online-games-with-python │ ├── adding-characters │ │ ├── getting-points.md │ │ └── losing-lives.md │ ├── collision │ │ ├── basic-collision-math.md │ │ ├── bounds-check.md │ │ └── hit-check.md │ ├── control │ │ ├── key-controls.md │ │ ├── key-up-vs-down.md │ │ └── mouse-controls.md │ ├── course.yml │ ├── interface │ │ ├── display.md │ │ ├── start-and-end-screens.md │ │ └── state-machines.md │ ├── introduction │ │ ├── audience.md │ │ ├── canvas.md │ │ └── setting-up.md │ ├── movement │ │ ├── animation-basics.md │ │ ├── bouncing-ball.md │ │ ├── draw-update-loop.md │ │ ├── drawing-primitives.md │ │ └── illusion-of-movement.md │ └── publish │ │ ├── share-with-friends.md │ │ └── whats-next.md ├── building-web-apps-with-python │ ├── basic-html │ │ ├── handling-text.md │ │ ├── head-body.md │ │ ├── html-document-introduction.md │ │ ├── images.md │ │ ├── links.md │ │ ├── lists.md │ │ └── tables.md │ ├── capstone-project │ │ ├── approach.md │ │ └── problem.md │ ├── course.js │ ├── course.yml │ ├── dynamic-html-using-jinja │ │ ├── build-static-site.md │ │ ├── conditions-and-loops.md │ │ ├── creating-tables.md │ │ ├── formatting-in-python.md │ │ ├── jinja2.md │ │ └── simple-jinja2-template.md │ ├── getting-started-with-flask │ │ ├── build-a-simple-site.md │ │ ├── introduction.md │ │ ├── responding-to-users.md │ │ ├── return-html-using-jinja.md │ │ ├── return-html.md │ │ └── routing-controllers.md │ ├── interacting-with-users │ │ ├── build-a-guestbook.md │ │ ├── forms.md │ │ ├── responsing-to-user-submission.md │ │ └── submitting-form.md │ ├── next │ │ └── what-to-do.md │ ├── preview-image.png │ └── styling │ │ ├── applying-style-to-html.md │ │ ├── introduction.md │ │ ├── style-tag.md │ │ └── using-bootstrap.md ├── git-github-for-beginners │ ├── _images │ │ ├── git-clone-box-snapshot.png │ │ ├── git-clone-operation-snapshot.png │ │ ├── git-push-operation-snapshot.png │ │ ├── git-repository-add-icon.png │ │ ├── git-repository-form.png │ │ ├── monschool-calculator-collaborator-page.png │ │ ├── monschool-calculator-html-snap.png │ │ ├── monschool-calculator-pull-request-review-1.png │ │ ├── monschool-calculator-pull-request-review-2.png │ │ ├── monschool-calculator-pull-request-review.png │ │ ├── monschool-calculator-pull-request-snap-1.png │ │ ├── monschool-calculator-pull-request-snap-2.png │ │ ├── monschool-calculator-pull-request-snap-3.png │ │ ├── monschool-calculator-pull-request-snap.png │ │ ├── monschool-calculator-repository-aspects.png │ │ ├── monschool-calculator-repository.png │ │ ├── monschool-merge-conflict-snap.png │ │ ├── monschool-resolved-merge-conflict.png │ │ └── rotten-scripts-collaborators-page.png │ ├── collaborative-development │ │ ├── managing-collaborators.md │ │ ├── merging.md │ │ ├── parallel-development.md │ │ ├── pull-requests.md │ │ ├── pulling-changes.md │ │ └── resolving-merge-conflicts.md │ ├── course.yml │ ├── getting-started │ │ ├── best-practises.md │ │ ├── git-cloning.md │ │ ├── git-committing.md │ │ ├── git-repository.md │ │ ├── pushing-commits.md │ │ └── time-travelling-with-git.md │ ├── github-flow │ │ ├── fork-cloning.md │ │ ├── fork-updating.md │ │ ├── git-rebasing.md │ │ ├── git-stashing.md │ │ └── managing-remote-repositories.md │ ├── introduction-to-git │ │ ├── git-github.md │ │ ├── git-objects.md │ │ ├── git-workflow.md │ │ ├── installing-configuring-git.md │ │ ├── what-is-git.md │ │ └── why-version-control-system.md │ └── open-source │ │ ├── automated-tests.md │ │ ├── fixing-issues-with-pull-requests.md │ │ ├── good-first-issues.md │ │ ├── leveraging-documentation.md │ │ ├── open-source-etiquette.md │ │ └── open-source-software.md ├── index.md ├── let-us-go │ ├── course.yml │ ├── exploring │ │ └── control-flow.md │ ├── explorng │ │ └── functions.md │ ├── getting-to-go │ │ ├── data-types.md │ │ ├── hello-world.md │ │ └── variables.md │ ├── go-in-parallel │ │ ├── card-game.md │ │ ├── concurrency.md │ │ └── goroutines-and-channels.md │ ├── go-out-in-style │ │ ├── coding-style.md │ │ ├── gofmt.md │ │ └── packaging.md │ ├── going-deep │ │ ├── arrays-maps.md │ │ ├── methods.md │ │ └── structures.md │ └── practical-go │ │ ├── error-handling.md │ │ ├── streams-files.md │ │ └── text-file-game.md ├── mypy-primer │ ├── _images │ │ ├── pycharm.png │ │ ├── typescript1.png │ │ ├── typescript2.png │ │ └── vscode.png │ ├── advanced-type-checking │ │ ├── the-type-type.md │ │ ├── type-checking-exercises.md │ │ ├── typing-decorators.md │ │ └── typing-generators.md │ ├── conclusion │ │ ├── integrating-mypy.md │ │ └── type-checking-or-tests.md │ ├── course.js │ ├── course.yml │ ├── introduction │ │ ├── installing-mypy.md │ │ ├── intro-to-type-annotations.md │ │ ├── using-mypy.md │ │ └── what-is-mypy.md │ ├── mypy-errors │ │ ├── mypy-configuration.md │ │ ├── type-checking-examples.md │ │ ├── using-reveal-type.md │ │ └── why-mypy-doesnt-error-here.md │ ├── mypy-image.png │ ├── the-typing-module │ │ ├── any-type.md │ │ ├── lists-dictionaries-collections.md │ │ ├── reading-mypy-error-messages.md │ │ ├── type-checking-classes.md │ │ ├── typing-args-kwargs.md │ │ └── union-optional.md │ └── typing-module-deep-dive │ │ ├── function-overloading.md │ │ ├── generics.md │ │ ├── static-duck-typing.md │ │ ├── the-namedtuple-class.md │ │ └── the-typeddict-class.md ├── python-primer │ ├── classes │ │ ├── classes.md │ │ ├── designing-with-classes.md │ │ └── exceptions.md │ ├── course.yml │ ├── getting-started │ │ ├── control-flow.md │ │ ├── datatypes.md │ │ ├── hello-python.md │ │ ├── reading-errors.md │ │ └── variables.md │ ├── next-steps │ │ └── next-steps.md │ ├── program-structure │ │ ├── functions.md │ │ └── modules.md │ ├── python-logo.png │ └── working-with-data │ │ ├── dictionaries.md │ │ ├── lists.md │ │ └── working-with-files.md ├── rust-for-beginners │ ├── control-flow │ │ ├── conditionals.md │ │ ├── functions-closures.md │ │ ├── iteration.md │ │ ├── macros.md │ │ └── pattern-matching.md │ ├── course.yml │ ├── data-flow │ │ ├── borrowing-ownership.md │ │ ├── structs-and-enums.md │ │ ├── traits-and-generics.md │ │ └── types.md │ ├── introduction │ │ ├── first-rust-program.md │ │ ├── rustup.md │ │ ├── welcome.md │ │ └── why-rust.md │ ├── package-management │ │ ├── cargo-manifest.md │ │ ├── crates-and-docs.md │ │ └── dependencies.md │ └── project │ │ ├── inputs.md │ │ ├── intro.md │ │ ├── logic.md │ │ ├── publish.md │ │ └── riir.md └── self-hosting-101 │ ├── _images │ ├── create_droplet_form.png │ ├── create_droplet_toggle.png │ ├── create_user.png │ ├── do_console.png │ ├── do_project.png │ ├── nano_bashrc.png │ ├── nano_input.png │ ├── nano_non_root.png │ ├── nginx-blue-site.png │ ├── nginx-index-edit.png │ ├── nginx-monschool-index.png │ ├── nginx-request-headers.png │ ├── nginx-route.png │ ├── nginx_welcome.png │ └── tmux.png │ ├── course.yml │ ├── selfhosting-logo.png │ ├── week0 │ ├── course-outline.md │ ├── what-things-can-you-self-host.md │ └── why-self-host.md │ ├── week1 │ ├── creating-droplet.md │ ├── creating-users.md │ ├── installing-packages.md │ ├── overview.md │ ├── setting-up-ssh.md │ ├── using-tmux.md │ └── working-with-files-directories.md │ └── week2 │ ├── creating-a-site.md │ ├── customising-index.md │ ├── installing-nginx.md │ ├── overview.md │ └── setup-using-git.md ├── dev-requirements.txt ├── macro.py ├── make-image.py ├── manage.py ├── mkdocs.yml ├── overrides └── main.html ├── requirements.txt ├── runtests.sh └── tests ├── __init__.py └── test_workspace.py /.github/ISSUE_TEMPLATE/new-course.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Propose a New Course 3 | about: Propose a new course on mon.school (even if you want someone else to author the course) 4 | title: 'New Course: ' 5 | labels: 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | 12 | 15 | 16 | 19 | 20 | ## About the course 21 | 22 | **Title** 23 | 24 | 25 | **Subtitle** 26 | 27 | 28 | 29 | **Description** 30 | 31 | 32 | ## Course Outline 33 | 34 | 35 | 36 | **1. Chapter 1** 37 | 38 | Description of this chapter. 39 | 40 | * Lesson 1 41 | * Lesson 2 42 | 43 | **2. Chapter 2** 44 | 45 | Description of this chapter. 46 | 47 | * Lesson 1 48 | * Lesson 2 49 | 50 | ## References 51 | 52 | 54 | 55 | ## Notes 56 | 57 | 58 | -------------------------------------------------------------------------------- /.github/workflows/push-courses.yml: -------------------------------------------------------------------------------- 1 | name: Push Courses 2 | on: 3 | push: 4 | paths: 5 | - "courses/**" 6 | branches: 7 | - main 8 | jobs: 9 | tests: 10 | name: Push Courses 11 | runs-on: ubuntu-20.04 12 | steps: 13 | - uses: actions/checkout@v2 14 | - name: setup python 15 | uses: actions/setup-python@v2 16 | with: 17 | python-version: 3.9 18 | - name: Install dependencies 19 | run: pip install -r requirements.txt 20 | - name: Push courses 21 | run: python manage.py push 22 | env: 23 | MON_SCHOOL_URL: ${{secrets.MON_SCHOOL_URL}} 24 | MON_SCHOOL_API_KEY: ${{secrets.MON_SCHOOL_API_KEY}} 25 | MON_SCHOOL_API_SECRET: ${{secrets.MON_SCHOOL_API_SECRET}} 26 | -------------------------------------------------------------------------------- /.github/workflows/run-tests.yml: -------------------------------------------------------------------------------- 1 | name: Run tests 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: {} 7 | jobs: 8 | tests: 9 | name: Run Tests 10 | runs-on: ubuntu-20.04 11 | steps: 12 | - uses: actions/checkout@v2 13 | - name: setup python 14 | uses: actions/setup-python@v2 15 | with: 16 | python-version: 3.9 17 | - name: install dependencies 18 | run: pip install -r requirements.txt -r dev-requirements.txt 19 | - name: run tests 20 | run: ./runtests.sh 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | __pycache__/ 3 | venv/ 4 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | .PHONY: serve 3 | serve: 4 | PYTHONPATH=. mkdocs serve 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mon School 2 | 3 | This repository maintains all the courses published on [Mon School][]. 4 | 5 | [Mon School]: (https://mon.school/). 6 | 7 | NOTE: This repository is no longer used to submit changes to mon.school. Please use the web interface on https://mon.school/ make updates to the courses. 8 | 9 | ## Setup 10 | 11 | To make it easier to author courses, [Material for MkDocs][mkdocs] is used to serve the website as HTML. Even though there will be differences the layout of this and the final website, this is a convenient interface to author courses for [Mon School][]. 12 | 13 | [mkdocs]: https://squidfunk.github.io/mkdocs-material/ 14 | 15 | ## Dev Instance 16 | 17 | To setup a dev instance: 18 | 19 | Step 1: Clone the Repository 20 | 21 | ``` 22 | $ git clone https://github.com/fossunited/monschool-website 23 | ``` 24 | 25 | Step 2: Install dependencies 26 | 27 | ``` 28 | $ pip install -r requirements.txt 29 | ``` 30 | 31 | You can also do this in a virtualenv. 32 | 33 | Step 3: Run dev server to serve the courses 34 | 35 | ``` 36 | $ make 37 | ... 38 | INFO - [08:58:56] Serving on http://127.0.0.1:8000/ 39 | ``` 40 | 41 | Open to see the courses. Pick the course on the nav bar to see the contents of the course. 42 | 43 | Make changes to lesson files and see them reflected in the site live. 44 | 45 | # Docs 46 | 47 | Coming soon! 48 | -------------------------------------------------------------------------------- /build/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | monctl 3 | ~~~~~~ 4 | 5 | Tools to control mon.school website. 6 | """ 7 | -------------------------------------------------------------------------------- /build/cli.py: -------------------------------------------------------------------------------- 1 | import click 2 | from pathlib import Path 3 | from .api import API 4 | from .workspace import Workspace 5 | 6 | @click.group() 7 | def cli(): 8 | """The CLI tool to manage courses on Mon School. 9 | """ 10 | pass 11 | 12 | @cli.command() 13 | @click.option("--course", "course_name", help="course to push") 14 | def push(course_name=None): 15 | """Push the courses to Mon School. 16 | 17 | If no course is specified, all courses are pushed. 18 | """ 19 | api = API() 20 | w = Workspace() 21 | if course_name: 22 | names = [course_name] 23 | else: 24 | names = w.list_courses() 25 | 26 | for name in names: 27 | course = w.read_course(name) 28 | if not course.draft: 29 | api.update_course(course) 30 | 31 | @cli.command() 32 | @click.argument("filenames", type=click.Path(exists=True), nargs=-1, required=True) 33 | def push_lesson(filenames): 34 | """Push on or more lessons to Mon School. 35 | """ 36 | api = API() 37 | w = Workspace() 38 | for f in filenames: 39 | lesson = w.read_lesson(Path(f)) 40 | api.update_lesson(lesson) 41 | 42 | @cli.command() 43 | @click.argument("filenames", type=click.Path(exists=True), nargs=-1, required=True) 44 | def push_lesson(filenames): 45 | """Push on or more lessons to Mon School. 46 | """ 47 | api = API() 48 | w = Workspace() 49 | for f in filenames: 50 | lesson = w.read_lesson(Path(f)) 51 | api.update_lesson(lesson) 52 | 53 | @cli.command() 54 | @click.option("--course", "course_name", help="course to generate", required=True) 55 | def generate(course_name): 56 | """Generates all lesson files for the course from course.yml 57 | """ 58 | w = Workspace() 59 | course = w.read_course(course_name) 60 | course.generate_lesson_stubs() 61 | 62 | @cli.command() 63 | @click.argument("source_path", type=click.Path(exists=True)) 64 | @click.argument("dest_path", type=click.Path()) 65 | def prepare_image(source_path, dest_path): 66 | """Takes an image and resizes it as suitable for course preview on mon.school. 67 | """ 68 | from . import image 69 | image.prepare_image(source_path, dest_path) 70 | 71 | def main(): 72 | cli() 73 | -------------------------------------------------------------------------------- /build/image.py: -------------------------------------------------------------------------------- 1 | """ 2 | Utility to prepare the course image to fit into mon.school. 3 | 4 | The mon.school course images are displyed in two different sizes and often 5 | getting cropped if not enough care is taken. 6 | 7 | The `prepare_image` function takes any image and generates a new image that works for both of those 8 | sizes. 9 | 10 | The sizes that are used in the mon school app are 348x168 and 350x200. 11 | 12 | To make the image work for both sizes, the image is resized to 340x170 and placed 13 | in the center of 350x200 image. 14 | """ 15 | from PIL import Image 16 | import sys 17 | 18 | def prepare_image(source_path, dest_path): 19 | """Takes the image provides at the `source_path` and resizes it as suitable for 20 | mon.school and saves it to the `dest_path`.""" 21 | # resize the given image to 340x170 22 | im = Image.open(source_path) 23 | im.thumbnail((340, 170)) 24 | 25 | # and paste it in the center of a 350x200 image 26 | im2 = Image.new(mode="RGBA", size=(350, 200), color=(0, 0, 0, 0)) 27 | offset = (im2.width-im.width) // 2, (im2.height-im.height)//2 28 | im2.paste(im, offset) 29 | im2.save(dest_path) 30 | print("created", dest_path) 31 | -------------------------------------------------------------------------------- /build/nav.py: -------------------------------------------------------------------------------- 1 | """ 2 | monctl.nav 3 | ~~~~~~~~~~ 4 | 5 | Hooks for injecting navigation to mkdocs. 6 | """ 7 | import yaml 8 | from pathlib import Path 9 | 10 | class Course: 11 | def __init__(self, root, name): 12 | self.root = root / "courses" / name 13 | self.name = name 14 | self.data = self.read_course_yaml() 15 | 16 | def read_course_yaml(self): 17 | path = self.root / "course.yml" 18 | return yaml.safe_load(path.open()) 19 | 20 | def make_nav(self): 21 | title = self.data['title'] 22 | nav_chapters = [self.make_chapter_nav(chapter) for chapter in self.data['chapters']] 23 | return {title: nav_chapters} 24 | 25 | def make_chapter_nav(self, chapter): 26 | title = chapter['title'] 27 | nav_lessons = [self.make_lesson_nav(lesson) for lesson in chapter['lessons']] 28 | return {title: nav_lessons} 29 | 30 | def make_lesson_nav(self, lesson): 31 | return f"{self.name}/{lesson}" 32 | 33 | def list_courses(): 34 | root = Path(".") 35 | for p in root.joinpath("courses").iterdir(): 36 | if p.is_dir() and p.joinpath("course.yml").exists(): 37 | yield Course(root, p.name) 38 | 39 | def on_files(files, config): 40 | """This is called by mkdocs and is used to dynamically generate navigation for the website. 41 | """ 42 | courses = list_courses() 43 | config['nav'] = [course.make_nav() for course in courses] 44 | -------------------------------------------------------------------------------- /courses/assets/codemirror/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (C) 2017 by Marijn Haverbeke and others 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /courses/assets/codemirror/README.txt: -------------------------------------------------------------------------------- 1 | 2 | codemirror-5.63.3 3 | https://codemirror.net/ 4 | 5 | Only the files required for this project are included. 6 | -------------------------------------------------------------------------------- /courses/assets/codemirror/addon/edit/matchtags.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: https://codemirror.net/LICENSE 3 | 4 | (function(mod) { 5 | if (typeof exports == "object" && typeof module == "object") // CommonJS 6 | mod(require("../../lib/codemirror"), require("../fold/xml-fold")); 7 | else if (typeof define == "function" && define.amd) // AMD 8 | define(["../../lib/codemirror", "../fold/xml-fold"], mod); 9 | else // Plain browser env 10 | mod(CodeMirror); 11 | })(function(CodeMirror) { 12 | "use strict"; 13 | 14 | CodeMirror.defineOption("matchTags", false, function(cm, val, old) { 15 | if (old && old != CodeMirror.Init) { 16 | cm.off("cursorActivity", doMatchTags); 17 | cm.off("viewportChange", maybeUpdateMatch); 18 | clear(cm); 19 | } 20 | if (val) { 21 | cm.state.matchBothTags = typeof val == "object" && val.bothTags; 22 | cm.on("cursorActivity", doMatchTags); 23 | cm.on("viewportChange", maybeUpdateMatch); 24 | doMatchTags(cm); 25 | } 26 | }); 27 | 28 | function clear(cm) { 29 | if (cm.state.tagHit) cm.state.tagHit.clear(); 30 | if (cm.state.tagOther) cm.state.tagOther.clear(); 31 | cm.state.tagHit = cm.state.tagOther = null; 32 | } 33 | 34 | function doMatchTags(cm) { 35 | cm.state.failedTagMatch = false; 36 | cm.operation(function() { 37 | clear(cm); 38 | if (cm.somethingSelected()) return; 39 | var cur = cm.getCursor(), range = cm.getViewport(); 40 | range.from = Math.min(range.from, cur.line); range.to = Math.max(cur.line + 1, range.to); 41 | var match = CodeMirror.findMatchingTag(cm, cur, range); 42 | if (!match) return; 43 | if (cm.state.matchBothTags) { 44 | var hit = match.at == "open" ? match.open : match.close; 45 | if (hit) cm.state.tagHit = cm.markText(hit.from, hit.to, {className: "CodeMirror-matchingtag"}); 46 | } 47 | var other = match.at == "close" ? match.open : match.close; 48 | if (other) 49 | cm.state.tagOther = cm.markText(other.from, other.to, {className: "CodeMirror-matchingtag"}); 50 | else 51 | cm.state.failedTagMatch = true; 52 | }); 53 | } 54 | 55 | function maybeUpdateMatch(cm) { 56 | if (cm.state.failedTagMatch) doMatchTags(cm); 57 | } 58 | 59 | CodeMirror.commands.toMatchingTag = function(cm) { 60 | var found = CodeMirror.findMatchingTag(cm, cm.getCursor()); 61 | if (found) { 62 | var other = found.at == "close" ? found.open : found.close; 63 | if (other) cm.extendSelection(other.to, other.from); 64 | } 65 | }; 66 | }); 67 | -------------------------------------------------------------------------------- /courses/assets/codemirror/addon/edit/trailingspace.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: https://codemirror.net/LICENSE 3 | 4 | (function(mod) { 5 | if (typeof exports == "object" && typeof module == "object") // CommonJS 6 | mod(require("../../lib/codemirror")); 7 | else if (typeof define == "function" && define.amd) // AMD 8 | define(["../../lib/codemirror"], mod); 9 | else // Plain browser env 10 | mod(CodeMirror); 11 | })(function(CodeMirror) { 12 | CodeMirror.defineOption("showTrailingSpace", false, function(cm, val, prev) { 13 | if (prev == CodeMirror.Init) prev = false; 14 | if (prev && !val) 15 | cm.removeOverlay("trailingspace"); 16 | else if (!prev && val) 17 | cm.addOverlay({ 18 | token: function(stream) { 19 | for (var l = stream.string.length, i = l; i && /\s/.test(stream.string.charAt(i - 1)); --i) {} 20 | if (i > stream.pos) { stream.pos = i; return null; } 21 | stream.pos = l; 22 | return "trailingspace"; 23 | }, 24 | name: "trailingspace" 25 | }); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /courses/assets/codemirror/addon/mode/loadmode.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: https://codemirror.net/LICENSE 3 | 4 | (function(mod) { 5 | if (typeof exports == "object" && typeof module == "object") // CommonJS 6 | mod(require("../../lib/codemirror"), "cjs"); 7 | else if (typeof define == "function" && define.amd) // AMD 8 | define(["../../lib/codemirror"], function(CM) { mod(CM, "amd"); }); 9 | else // Plain browser env 10 | mod(CodeMirror, "plain"); 11 | })(function(CodeMirror, env) { 12 | if (!CodeMirror.modeURL) CodeMirror.modeURL = "../mode/%N/%N.js"; 13 | 14 | var loading = {}; 15 | function splitCallback(cont, n) { 16 | var countDown = n; 17 | return function() { if (--countDown == 0) cont(); }; 18 | } 19 | function ensureDeps(mode, cont, options) { 20 | var modeObj = CodeMirror.modes[mode], deps = modeObj && modeObj.dependencies; 21 | if (!deps) return cont(); 22 | var missing = []; 23 | for (var i = 0; i < deps.length; ++i) { 24 | if (!CodeMirror.modes.hasOwnProperty(deps[i])) 25 | missing.push(deps[i]); 26 | } 27 | if (!missing.length) return cont(); 28 | var split = splitCallback(cont, missing.length); 29 | for (var i = 0; i < missing.length; ++i) 30 | CodeMirror.requireMode(missing[i], split, options); 31 | } 32 | 33 | CodeMirror.requireMode = function(mode, cont, options) { 34 | if (typeof mode != "string") mode = mode.name; 35 | if (CodeMirror.modes.hasOwnProperty(mode)) return ensureDeps(mode, cont, options); 36 | if (loading.hasOwnProperty(mode)) return loading[mode].push(cont); 37 | 38 | var file = options && options.path ? options.path(mode) : CodeMirror.modeURL.replace(/%N/g, mode); 39 | if (options && options.loadMode) { 40 | options.loadMode(file, function() { ensureDeps(mode, cont, options) }) 41 | } else if (env == "plain") { 42 | var script = document.createElement("script"); 43 | script.src = file; 44 | var others = document.getElementsByTagName("script")[0]; 45 | var list = loading[mode] = [cont]; 46 | CodeMirror.on(script, "load", function() { 47 | ensureDeps(mode, function() { 48 | for (var i = 0; i < list.length; ++i) list[i](); 49 | }, options); 50 | }); 51 | others.parentNode.insertBefore(script, others); 52 | } else if (env == "cjs") { 53 | require(file); 54 | cont(); 55 | } else if (env == "amd") { 56 | requirejs([file], cont); 57 | } 58 | }; 59 | 60 | CodeMirror.autoLoadMode = function(instance, mode, options) { 61 | if (!CodeMirror.modes.hasOwnProperty(mode)) 62 | CodeMirror.requireMode(mode, function() { 63 | instance.setOption("mode", instance.getOption("mode")); 64 | }, options); 65 | }; 66 | }); 67 | -------------------------------------------------------------------------------- /courses/assets/codemirror/addon/mode/multiplex_test.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: https://codemirror.net/LICENSE 3 | 4 | (function() { 5 | CodeMirror.defineMode("markdown_with_stex", function(){ 6 | var inner = CodeMirror.getMode({}, "stex"); 7 | var outer = CodeMirror.getMode({}, "markdown"); 8 | 9 | var innerOptions = { 10 | open: '$', 11 | close: '$', 12 | mode: inner, 13 | delimStyle: 'delim', 14 | innerStyle: 'inner' 15 | }; 16 | 17 | return CodeMirror.multiplexingMode(outer, innerOptions); 18 | }); 19 | 20 | var mode = CodeMirror.getMode({}, "markdown_with_stex"); 21 | 22 | function MT(name) { 23 | test.mode( 24 | name, 25 | mode, 26 | Array.prototype.slice.call(arguments, 1), 27 | 'multiplexing'); 28 | } 29 | 30 | MT( 31 | "stexInsideMarkdown", 32 | "[strong **Equation:**] [delim&delim-open $][inner&tag \\pi][delim&delim-close $]"); 33 | 34 | CodeMirror.defineMode("identical_delim_multiplex", function() { 35 | return CodeMirror.multiplexingMode(CodeMirror.getMode({indentUnit: 2}, "javascript"), { 36 | open: "#", 37 | close: "#", 38 | mode: CodeMirror.getMode({}, "markdown"), 39 | parseDelimiters: true, 40 | innerStyle: "q" 41 | }); 42 | }); 43 | 44 | var mode2 = CodeMirror.getMode({}, "identical_delim_multiplex"); 45 | 46 | test.mode("identical_delimiters_with_parseDelimiters", mode2, [ 47 | "[keyword let] [def x] [operator =] [q #foo][q&em *bar*][q #];" 48 | ], "multiplexing") 49 | })(); 50 | -------------------------------------------------------------------------------- /courses/assets/codemirror/addon/mode/overlay.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: https://codemirror.net/LICENSE 3 | 4 | // Utility function that allows modes to be combined. The mode given 5 | // as the base argument takes care of most of the normal mode 6 | // functionality, but a second (typically simple) mode is used, which 7 | // can override the style of text. Both modes get to parse all of the 8 | // text, but when both assign a non-null style to a piece of code, the 9 | // overlay wins, unless the combine argument was true and not overridden, 10 | // or state.overlay.combineTokens was true, in which case the styles are 11 | // combined. 12 | 13 | (function(mod) { 14 | if (typeof exports == "object" && typeof module == "object") // CommonJS 15 | mod(require("../../lib/codemirror")); 16 | else if (typeof define == "function" && define.amd) // AMD 17 | define(["../../lib/codemirror"], mod); 18 | else // Plain browser env 19 | mod(CodeMirror); 20 | })(function(CodeMirror) { 21 | "use strict"; 22 | 23 | CodeMirror.overlayMode = function(base, overlay, combine) { 24 | return { 25 | startState: function() { 26 | return { 27 | base: CodeMirror.startState(base), 28 | overlay: CodeMirror.startState(overlay), 29 | basePos: 0, baseCur: null, 30 | overlayPos: 0, overlayCur: null, 31 | streamSeen: null 32 | }; 33 | }, 34 | copyState: function(state) { 35 | return { 36 | base: CodeMirror.copyState(base, state.base), 37 | overlay: CodeMirror.copyState(overlay, state.overlay), 38 | basePos: state.basePos, baseCur: null, 39 | overlayPos: state.overlayPos, overlayCur: null 40 | }; 41 | }, 42 | 43 | token: function(stream, state) { 44 | if (stream != state.streamSeen || 45 | Math.min(state.basePos, state.overlayPos) < stream.start) { 46 | state.streamSeen = stream; 47 | state.basePos = state.overlayPos = stream.start; 48 | } 49 | 50 | if (stream.start == state.basePos) { 51 | state.baseCur = base.token(stream, state.base); 52 | state.basePos = stream.pos; 53 | } 54 | if (stream.start == state.overlayPos) { 55 | stream.pos = stream.start; 56 | state.overlayCur = overlay.token(stream, state.overlay); 57 | state.overlayPos = stream.pos; 58 | } 59 | stream.pos = Math.min(state.basePos, state.overlayPos); 60 | 61 | // state.overlay.combineTokens always takes precedence over combine, 62 | // unless set to null 63 | if (state.overlayCur == null) return state.baseCur; 64 | else if (state.baseCur != null && 65 | state.overlay.combineTokens || 66 | combine && state.overlay.combineTokens == null) 67 | return state.baseCur + " " + state.overlayCur; 68 | else return state.overlayCur; 69 | }, 70 | 71 | indent: base.indent && function(state, textAfter, line) { 72 | return base.indent(state.base, textAfter, line); 73 | }, 74 | electricChars: base.electricChars, 75 | 76 | innerMode: function(state) { return {state: state.base, mode: base}; }, 77 | 78 | blankLine: function(state) { 79 | var baseToken, overlayToken; 80 | if (base.blankLine) baseToken = base.blankLine(state.base); 81 | if (overlay.blankLine) overlayToken = overlay.blankLine(state.overlay); 82 | 83 | return overlayToken == null ? 84 | baseToken : 85 | (combine && baseToken != null ? baseToken + " " + overlayToken : overlayToken); 86 | } 87 | }; 88 | }; 89 | 90 | }); 91 | -------------------------------------------------------------------------------- /courses/assets/codemirror/mode/css/gss.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | CodeMirror: Closure Stylesheets (GSS) mode 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 28 | 29 |
30 |

Closure Stylesheets (GSS) mode

31 |
90 | 98 | 99 |

A mode for Closure Stylesheets (GSS).

100 |

MIME type defined: text/x-gss.

101 | 102 |

Parsing/Highlighting Tests: normal, verbose.

103 | 104 |
105 | -------------------------------------------------------------------------------- /courses/assets/codemirror/mode/css/gss_test.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: https://codemirror.net/LICENSE 3 | 4 | (function() { 5 | "use strict"; 6 | 7 | var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-gss"); 8 | function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "gss"); } 9 | 10 | MT("atComponent", 11 | "[def @component] {", 12 | "[tag foo] {", 13 | " [property color]: [keyword black];", 14 | "}", 15 | "}"); 16 | 17 | })(); 18 | -------------------------------------------------------------------------------- /courses/assets/codemirror/mode/css/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | CodeMirror: CSS mode 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 27 | 28 |
29 |

CSS mode

30 |
65 | 70 | 71 |

CSS mode supports this option:

72 | 73 |
highlightNonStandardPropertyKeywords: boolean
74 |
Whether to highlight non-standard CSS property keywords such as margin-inline or zoom (default: true).
75 |
76 | 77 |

MIME types defined: text/css, text/x-scss (demo), text/x-less (demo).

78 | 79 |

Parsing/Highlighting Tests: normal, verbose.

80 | 81 |
82 | -------------------------------------------------------------------------------- /courses/assets/codemirror/mode/css/less_test.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: https://codemirror.net/LICENSE 3 | 4 | (function() { 5 | "use strict"; 6 | 7 | var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-less"); 8 | function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "less"); } 9 | 10 | MT("variable", 11 | "[variable-2 @base]: [atom #f04615];", 12 | "[qualifier .class] {", 13 | " [property width]: [variable&callee percentage]([number 0.5]); [comment // returns `50%`]", 14 | " [property color]: [variable&callee saturate]([variable-2 @base], [number 5%]);", 15 | "}"); 16 | 17 | MT("amp", 18 | "[qualifier .child], [qualifier .sibling] {", 19 | " [qualifier .parent] [atom &] {", 20 | " [property color]: [keyword black];", 21 | " }", 22 | " [atom &] + [atom &] {", 23 | " [property color]: [keyword red];", 24 | " }", 25 | "}"); 26 | 27 | MT("mixin", 28 | "[qualifier .mixin] ([variable dark]; [variable-2 @color]) {", 29 | " [property color]: [variable&callee darken]([variable-2 @color], [number 10%]);", 30 | "}", 31 | "[qualifier .mixin] ([variable light]; [variable-2 @color]) {", 32 | " [property color]: [variable&callee lighten]([variable-2 @color], [number 10%]);", 33 | "}", 34 | "[qualifier .mixin] ([variable-2 @_]; [variable-2 @color]) {", 35 | " [property display]: [atom block];", 36 | "}", 37 | "[variable-2 @switch]: [variable light];", 38 | "[qualifier .class] {", 39 | " [qualifier .mixin]([variable-2 @switch]; [atom #888]);", 40 | "}"); 41 | 42 | MT("nest", 43 | "[qualifier .one] {", 44 | " [def @media] ([property width]: [number 400px]) {", 45 | " [property font-size]: [number 1.2em];", 46 | " [def @media] [attribute print] [keyword and] [property color] {", 47 | " [property color]: [keyword blue];", 48 | " }", 49 | " }", 50 | "}"); 51 | 52 | 53 | MT("interpolation", ".@{[variable foo]} { [property font-weight]: [atom bold]; }"); 54 | })(); 55 | -------------------------------------------------------------------------------- /courses/assets/codemirror/mode/css/scss.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | CodeMirror: SCSS mode 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 25 | 26 |
27 |

SCSS mode

28 |
146 | 153 | 154 |

The SCSS mode is a sub-mode of the CSS mode (defined in css.js).

155 | 156 |

Parsing/Highlighting Tests: normal, verbose.

157 | 158 |
159 | -------------------------------------------------------------------------------- /courses/assets/codemirror/mode/css/scss_test.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: https://codemirror.net/LICENSE 3 | 4 | (function() { 5 | var mode = CodeMirror.getMode({indentUnit: 2}, "text/x-scss"); 6 | function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), "scss"); } 7 | 8 | MT('url_with_quotation', 9 | "[tag foo] { [property background]:[variable&callee url]([string test.jpg]) }"); 10 | 11 | MT('url_with_double_quotes', 12 | "[tag foo] { [property background]:[variable&callee url]([string \"test.jpg\"]) }"); 13 | 14 | MT('url_with_single_quotes', 15 | "[tag foo] { [property background]:[variable&callee url]([string \'test.jpg\']) }"); 16 | 17 | MT('string', 18 | "[def @import] [string \"compass/css3\"]"); 19 | 20 | MT('important_keyword', 21 | "[tag foo] { [property background]:[variable&callee url]([string \'test.jpg\']) [keyword !important] }"); 22 | 23 | MT('variable', 24 | "[variable-2 $blue]:[atom #333]"); 25 | 26 | MT('variable_as_attribute', 27 | "[tag foo] { [property color]:[variable-2 $blue] }"); 28 | 29 | MT('numbers', 30 | "[tag foo] { [property padding]:[number 10px] [number 10] [number 10em] [number 8in] }"); 31 | 32 | MT('number_percentage', 33 | "[tag foo] { [property width]:[number 80%] }"); 34 | 35 | MT('selector', 36 | "[builtin #hello][qualifier .world]{}"); 37 | 38 | MT('singleline_comment', 39 | "[comment // this is a comment]"); 40 | 41 | MT('multiline_comment', 42 | "[comment /*foobar*/]"); 43 | 44 | MT('attribute_with_hyphen', 45 | "[tag foo] { [property font-size]:[number 10px] }"); 46 | 47 | MT('string_after_attribute', 48 | "[tag foo] { [property content]:[string \"::\"] }"); 49 | 50 | MT('directives', 51 | "[def @include] [qualifier .mixin]"); 52 | 53 | MT('basic_structure', 54 | "[tag p] { [property background]:[keyword red]; }"); 55 | 56 | MT('nested_structure', 57 | "[tag p] { [tag a] { [property color]:[keyword red]; } }"); 58 | 59 | MT('mixin', 60 | "[def @mixin] [tag table-base] {}"); 61 | 62 | MT('number_without_semicolon', 63 | "[tag p] {[property width]:[number 12]}", 64 | "[tag a] {[property color]:[keyword red];}"); 65 | 66 | MT('atom_in_nested_block', 67 | "[tag p] { [tag a] { [property color]:[atom #000]; } }"); 68 | 69 | MT('interpolation_in_property', 70 | "[tag foo] { #{[variable-2 $hello]}:[number 2]; }"); 71 | 72 | MT('interpolation_in_selector', 73 | "[tag foo]#{[variable-2 $hello]} { [property color]:[atom #000]; }"); 74 | 75 | MT('interpolation_error', 76 | "[tag foo]#{[variable foo]} { [property color]:[atom #000]; }"); 77 | 78 | MT("divide_operator", 79 | "[tag foo] { [property width]:[number 4] [operator /] [number 2] }"); 80 | 81 | MT('nested_structure_with_id_selector', 82 | "[tag p] { [builtin #hello] { [property color]:[keyword red]; } }"); 83 | 84 | MT('indent_mixin', 85 | "[def @mixin] [tag container] (", 86 | " [variable-2 $a]: [number 10],", 87 | " [variable-2 $b]: [number 10])", 88 | "{}"); 89 | 90 | MT('indent_nested', 91 | "[tag foo] {", 92 | " [tag bar] {", 93 | " }", 94 | "}"); 95 | 96 | MT('indent_parentheses', 97 | "[tag foo] {", 98 | " [property color]: [variable&callee darken]([variable-2 $blue],", 99 | " [number 9%]);", 100 | "}"); 101 | 102 | MT('indent_vardef', 103 | "[variable-2 $name]:", 104 | " [string 'val'];", 105 | "[tag tag] {", 106 | " [tag inner] {", 107 | " [property margin]: [number 3px];", 108 | " }", 109 | "}"); 110 | })(); 111 | -------------------------------------------------------------------------------- /courses/assets/codemirror/mode/go/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | CodeMirror: Go mode 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 26 | 27 |
28 |

Go mode

29 |
72 | 73 | 83 | 84 |

MIME type: text/x-go

85 |
86 | -------------------------------------------------------------------------------- /courses/assets/codemirror/mode/htmlmixed/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | CodeMirror: HTML mixed mode 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 29 | 30 |
31 |

HTML mixed mode

32 |
56 | 71 | 72 |

The HTML mixed mode depends on the XML, JavaScript, and CSS modes.

73 | 74 |

It takes an optional mode configuration 75 | option, tags, which can be used to add custom 76 | behavior for specific tags. When given, it should be an object 77 | mapping tag names (for example script) to arrays or 78 | three-element arrays. Those inner arrays indicate [attributeName, 79 | valueRegexp, modeSpec] 80 | specifications. For example, you could use ["type", /^foo$/, 81 | "foo"] to map the attribute type="foo" to 82 | the foo mode. When the first two fields are null 83 | ([null, null, "mode"]), the given mode is used for 84 | any such tag that doesn't match any of the previously given 85 | attributes. For example:

86 | 87 |
var myModeSpec = {
 88 |   name: "htmlmixed",
 89 |   tags: {
 90 |     style: [["type", /^text\/(x-)?scss$/, "text/x-scss"],
 91 |             [null, null, "css"]],
 92 |     custom: [[null, null, "customMode"]]
 93 |   }
 94 | }
95 | 96 |

MIME types defined: text/html 97 | (redefined, only takes effect if you load this parser after the 98 | XML parser).

99 | 100 |
101 | -------------------------------------------------------------------------------- /courses/assets/codemirror/mode/javascript/json-ld.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | CodeMirror: JSON-LD mode 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 27 | 28 |
29 |

JSON-LD mode

30 | 31 | 32 |
61 | 62 | 70 | 71 |

This is a specialization of the JavaScript mode.

72 |
73 | -------------------------------------------------------------------------------- /courses/assets/codemirror/mode/javascript/typescript.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | CodeMirror: TypeScript mode 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 25 | 26 |
27 |

TypeScript mode

28 | 29 | 30 |
52 | 53 | 60 | 61 |

This is a specialization of the JavaScript mode.

62 |
63 | -------------------------------------------------------------------------------- /courses/assets/codemirror/mode/python/test.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: https://codemirror.net/LICENSE 3 | 4 | (function() { 5 | var mode = CodeMirror.getMode({indentUnit: 4}, 6 | {name: "python", 7 | version: 3, 8 | singleLineStringErrors: false}); 9 | function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1)); } 10 | 11 | // Error, because "foobarhello" is neither a known type or property, but 12 | // property was expected (after "and"), and it should be in parentheses. 13 | MT("decoratorStartOfLine", 14 | "[meta @dec]", 15 | "[keyword def] [def function]():", 16 | " [keyword pass]"); 17 | 18 | MT("decoratorIndented", 19 | "[keyword class] [def Foo]:", 20 | " [meta @dec]", 21 | " [keyword def] [def function]():", 22 | " [keyword pass]"); 23 | 24 | MT("matmulWithSpace:", "[variable a] [operator @] [variable b]"); 25 | MT("matmulWithoutSpace:", "[variable a][operator @][variable b]"); 26 | MT("matmulSpaceBefore:", "[variable a] [operator @][variable b]"); 27 | var before_equal_sign = ["+", "-", "*", "/", "=", "!", ">", "<"]; 28 | for (var i = 0; i < before_equal_sign.length; ++i) { 29 | var c = before_equal_sign[i] 30 | MT("before_equal_sign_" + c, "[variable a] [operator " + c + "=] [variable b]"); 31 | } 32 | 33 | MT("fValidStringPrefix", "[string f'this is a]{[variable formatted]}[string string']"); 34 | MT("fValidExpressionInFString", "[string f'expression ]{[number 100][operator *][number 5]}[string string']"); 35 | MT("fInvalidFString", "[error f'this is wrong}]"); 36 | MT("fNestedFString", "[string f'expression ]{[number 100] [operator +] [string f'inner]{[number 5]}[string ']}[string string']"); 37 | MT("uValidStringPrefix", "[string u'this is an unicode string']"); 38 | 39 | MT("nestedString", "[string f']{[variable b][[ [string \"c\"] ]]}[string f'] [comment # oops]") 40 | 41 | MT("bracesInFString", "[string f']{[variable x] [operator +] {}}[string !']") 42 | 43 | MT("nestedFString", "[string f']{[variable b][[ [string f\"c\"] ]]}[string f'] [comment # oops]") 44 | 45 | MT("dontIndentTypeDecl", 46 | "[variable i]: [builtin int] [operator =] [number 32]", 47 | "[builtin print]([variable i])") 48 | 49 | MT("dedentElse", 50 | "[keyword if] [variable x]:", 51 | " [variable foo]()", 52 | "[keyword elif] [variable y]:", 53 | " [variable bar]()", 54 | "[keyword else]:", 55 | " [variable baz]()") 56 | 57 | MT("dedentElsePass", 58 | "[keyword if] [variable x]:", 59 | " [keyword pass]", 60 | "[keyword elif] [variable y]:", 61 | " [keyword pass]", 62 | "[keyword else]:", 63 | " [keyword pass]") 64 | 65 | MT("dedentElseInFunction", 66 | "[keyword def] [def foo]():", 67 | " [keyword if] [variable x]:", 68 | " [variable foo]()", 69 | " [keyword elif] [variable y]:", 70 | " [variable bar]()", 71 | " [keyword pass]", 72 | " [keyword else]:", 73 | " [variable baz]()") 74 | })(); 75 | -------------------------------------------------------------------------------- /courses/assets/codemirror/mode/rust/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | CodeMirror: Rust mode 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 25 | 26 |
27 |

Rust mode

28 | 29 | 30 |
53 | 54 | 62 | 63 |

MIME types defined: text/x-rustsrc.

64 |
65 | -------------------------------------------------------------------------------- /courses/assets/codemirror/mode/rust/rust.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: https://codemirror.net/LICENSE 3 | 4 | (function(mod) { 5 | if (typeof exports == "object" && typeof module == "object") // CommonJS 6 | mod(require("../../lib/codemirror"), require("../../addon/mode/simple")); 7 | else if (typeof define == "function" && define.amd) // AMD 8 | define(["../../lib/codemirror", "../../addon/mode/simple"], mod); 9 | else // Plain browser env 10 | mod(CodeMirror); 11 | })(function(CodeMirror) { 12 | "use strict"; 13 | 14 | CodeMirror.defineSimpleMode("rust",{ 15 | start: [ 16 | // string and byte string 17 | {regex: /b?"/, token: "string", next: "string"}, 18 | // raw string and raw byte string 19 | {regex: /b?r"/, token: "string", next: "string_raw"}, 20 | {regex: /b?r#+"/, token: "string", next: "string_raw_hash"}, 21 | // character 22 | {regex: /'(?:[^'\\]|\\(?:[nrt0'"]|x[\da-fA-F]{2}|u\{[\da-fA-F]{6}\}))'/, token: "string-2"}, 23 | // byte 24 | {regex: /b'(?:[^']|\\(?:['\\nrt0]|x[\da-fA-F]{2}))'/, token: "string-2"}, 25 | 26 | {regex: /(?:(?:[0-9][0-9_]*)(?:(?:[Ee][+-]?[0-9_]+)|\.[0-9_]+(?:[Ee][+-]?[0-9_]+)?)(?:f32|f64)?)|(?:0(?:b[01_]+|(?:o[0-7_]+)|(?:x[0-9a-fA-F_]+))|(?:[0-9][0-9_]*))(?:u8|u16|u32|u64|i8|i16|i32|i64|isize|usize)?/, 27 | token: "number"}, 28 | {regex: /(let(?:\s+mut)?|fn|enum|mod|struct|type|union)(\s+)([a-zA-Z_][a-zA-Z0-9_]*)/, token: ["keyword", null, "def"]}, 29 | {regex: /(?:abstract|alignof|as|async|await|box|break|continue|const|crate|do|dyn|else|enum|extern|fn|for|final|if|impl|in|loop|macro|match|mod|move|offsetof|override|priv|proc|pub|pure|ref|return|self|sizeof|static|struct|super|trait|type|typeof|union|unsafe|unsized|use|virtual|where|while|yield)\b/, token: "keyword"}, 30 | {regex: /\b(?:Self|isize|usize|char|bool|u8|u16|u32|u64|f16|f32|f64|i8|i16|i32|i64|str|Option)\b/, token: "atom"}, 31 | {regex: /\b(?:true|false|Some|None|Ok|Err)\b/, token: "builtin"}, 32 | {regex: /\b(fn)(\s+)([a-zA-Z_][a-zA-Z0-9_]*)/, 33 | token: ["keyword", null ,"def"]}, 34 | {regex: /#!?\[.*\]/, token: "meta"}, 35 | {regex: /\/\/.*/, token: "comment"}, 36 | {regex: /\/\*/, token: "comment", next: "comment"}, 37 | {regex: /[-+\/*=<>!]+/, token: "operator"}, 38 | {regex: /[a-zA-Z_]\w*!/,token: "variable-3"}, 39 | {regex: /[a-zA-Z_]\w*/, token: "variable"}, 40 | {regex: /[\{\[\(]/, indent: true}, 41 | {regex: /[\}\]\)]/, dedent: true} 42 | ], 43 | string: [ 44 | {regex: /"/, token: "string", next: "start"}, 45 | {regex: /(?:[^\\"]|\\(?:.|$))*/, token: "string"} 46 | ], 47 | string_raw: [ 48 | {regex: /"/, token: "string", next: "start"}, 49 | {regex: /[^"]*/, token: "string"} 50 | ], 51 | string_raw_hash: [ 52 | {regex: /"#+/, token: "string", next: "start"}, 53 | {regex: /(?:[^"]|"(?!#))*/, token: "string"} 54 | ], 55 | comment: [ 56 | {regex: /.*?\*\//, token: "comment", next: "start"}, 57 | {regex: /.*/, token: "comment"} 58 | ], 59 | meta: { 60 | dontIndentStates: ["comment"], 61 | electricInput: /^\s*\}$/, 62 | blockCommentStart: "/*", 63 | blockCommentEnd: "*/", 64 | lineComment: "//", 65 | fold: "brace" 66 | } 67 | }); 68 | 69 | 70 | CodeMirror.defineMIME("text/x-rustsrc", "rust"); 71 | CodeMirror.defineMIME("text/rust", "rust"); 72 | }); 73 | -------------------------------------------------------------------------------- /courses/assets/codemirror/mode/rust/test.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: https://codemirror.net/LICENSE 3 | 4 | (function() { 5 | var mode = CodeMirror.getMode({indentUnit: 4}, "rust"); 6 | function MT(name) {test.mode(name, mode, Array.prototype.slice.call(arguments, 1));} 7 | 8 | MT('integer_test', 9 | '[number 123i32]', 10 | '[number 123u32]', 11 | '[number 123_u32]', 12 | '[number 0xff_u8]', 13 | '[number 0o70_i16]', 14 | '[number 0b1111_1111_1001_0000_i32]', 15 | '[number 0usize]'); 16 | 17 | MT('float_test', 18 | '[number 123.0f64]', 19 | '[number 0.1f64]', 20 | '[number 0.1f32]', 21 | '[number 12E+99_f64]'); 22 | 23 | MT('string-literals-test', 24 | '[string "foo"]', 25 | '[string r"foo"]', 26 | '[string "\\"foo\\""]', 27 | '[string r#""foo""#]', 28 | '[string "foo #\\"# bar"]', 29 | 30 | '[string b"foo"]', 31 | '[string br"foo"]', 32 | '[string b"\\"foo\\""]', 33 | '[string br#""foo""#]', 34 | '[string br##"foo #" bar"##]', 35 | 36 | "[string-2 'h']", 37 | "[string-2 b'h']"); 38 | 39 | })(); 40 | -------------------------------------------------------------------------------- /courses/assets/codemirror/mode/xml/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | CodeMirror: XML mode 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 24 | 25 |
26 |

XML mode

27 |
39 | 45 |

The XML mode supports these configuration parameters:

46 |
47 |
htmlMode (boolean)
48 |
This switches the mode to parse HTML instead of XML. This 49 | means attributes do not have to be quoted, and some elements 50 | (such as br) do not require a closing tag.
51 |
matchClosing (boolean)
52 |
Controls whether the mode checks that close tags match the 53 | corresponding opening tag, and highlights mismatches as errors. 54 | Defaults to true.
55 |
alignCDATA (boolean)
56 |
Setting this to true will force the opening tag of CDATA 57 | blocks to not be indented.
58 |
59 | 60 |

MIME types defined: application/xml, text/html.

61 |
62 | -------------------------------------------------------------------------------- /courses/assets/codemirror/mode/xml/test.js: -------------------------------------------------------------------------------- 1 | // CodeMirror, copyright (c) by Marijn Haverbeke and others 2 | // Distributed under an MIT license: https://codemirror.net/LICENSE 3 | 4 | (function() { 5 | var mode = CodeMirror.getMode({indentUnit: 2}, "xml"), mname = "xml"; 6 | function MT(name) { test.mode(name, mode, Array.prototype.slice.call(arguments, 1), mname); } 7 | 8 | MT("matching", 9 | "[tag&bracket <][tag top][tag&bracket >]", 10 | " text", 11 | " [tag&bracket <][tag inner][tag&bracket />]", 12 | "[tag&bracket ]"); 13 | 14 | MT("nonmatching", 15 | "[tag&bracket <][tag top][tag&bracket >]", 16 | " [tag&bracket <][tag inner][tag&bracket />]", 17 | " [tag&bracket ]"); 18 | 19 | MT("doctype", 20 | "[meta ]", 21 | "[tag&bracket <][tag top][tag&bracket />]"); 22 | 23 | MT("cdata", 24 | "[tag&bracket <][tag top][tag&bracket >]", 25 | " [atom ]", 27 | "[tag&bracket ]"); 28 | 29 | // HTML tests 30 | mode = CodeMirror.getMode({indentUnit: 2}, "text/html"); 31 | 32 | MT("selfclose", 33 | "[tag&bracket <][tag html][tag&bracket >]", 34 | " [tag&bracket <][tag link] [attribute rel]=[string stylesheet] [attribute href]=[string \"/foobar\"][tag&bracket >]", 35 | "[tag&bracket ]"); 36 | 37 | MT("list", 38 | "[tag&bracket <][tag ol][tag&bracket >]", 39 | " [tag&bracket <][tag li][tag&bracket >]one", 40 | " [tag&bracket <][tag li][tag&bracket >]two", 41 | "[tag&bracket ]"); 42 | 43 | MT("valueless", 44 | "[tag&bracket <][tag input] [attribute type]=[string checkbox] [attribute checked][tag&bracket />]"); 45 | 46 | MT("pThenArticle", 47 | "[tag&bracket <][tag p][tag&bracket >]", 48 | " foo", 49 | "[tag&bracket <][tag article][tag&bracket >]bar"); 50 | 51 | })(); 52 | -------------------------------------------------------------------------------- /courses/assets/style.css: -------------------------------------------------------------------------------- 1 | .CodeMirror { 2 | border: 1px solid #ddd; 3 | background: #ffe; 4 | height: auto; 5 | } 6 | .CodeMirror-scroll { 7 | /* max-height: 300px; */ 8 | /* min-height: 208px; */ 9 | } 10 | .controls { 11 | padding: 10px 0px; 12 | } 13 | .code-wrapper { 14 | /* min-height: 200px; */ 15 | } 16 | 17 | .clearfix { 18 | clear: both; 19 | } 20 | 21 | .livecode-editor { 22 | margin: 20px 0px; 23 | clear: both; 24 | } 25 | 26 | .code-wrapper { 27 | /* min-width: 300px; */ 28 | flex: 1; 29 | } 30 | .output-wrapper { 31 | padding: 5px 20px; 32 | border: 1px solid #eee; 33 | } 34 | 35 | button { 36 | cursor: pointer; 37 | background: #eee; 38 | border: 1px solid #ddd; 39 | padding: 5px 10px; 40 | } 41 | 42 | .output { 43 | overflow-x: auto; 44 | /* width: 200px; */ 45 | white-space: pre-wrap; 46 | word-wrap: break-word; 47 | font-size: 0.8em; 48 | } 49 | 50 | header { 51 | z-index: 10 !important; 52 | } 53 | 54 | .hidden { 55 | display: none; 56 | } 57 | 58 | .code-editor { 59 | clear: both; 60 | } 61 | .code-editor .preview-label { 62 | font-weight: bold; 63 | padding: 0px 10px; 64 | background: #eee; 65 | } 66 | .code-editor iframe { 67 | padding: 20px; 68 | border: 1px solid #eee; 69 | width: 100%; 70 | } 71 | 72 | .tabs { 73 | overflow: hidden; 74 | border: 1px solid #ccc; 75 | background-color: #f1f1f1; 76 | } 77 | 78 | .tabs button, .file-link { 79 | float: left; 80 | border: none; 81 | outline: none; 82 | cursor: pointer; 83 | padding: 5px 10px; 84 | transition: 0.3s; 85 | } 86 | 87 | .tabs button:hover, .file-link:hover { 88 | background-color: #ddd; 89 | } 90 | 91 | .tabs button.active, .file-link.active { 92 | background-color: #ccc; 93 | } 94 | 95 | .filenames { 96 | clear: both; 97 | } 98 | 99 | .livecode-editor .labels { 100 | float: right; 101 | padding: 2px 10px; 102 | border: 1px solid #ddd; 103 | border-radius: 20px; 104 | background: #ffe; 105 | } 106 | 107 | input.run-args { 108 | border: 1px solid #ddd; 109 | padding: 5px; 110 | width: 300px; 111 | } 112 | -------------------------------------------------------------------------------- /courses/authoring-courses-on-mon-school/content/examples.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Adding Examples 3 | include_in_preview: false 4 | --- 5 | 6 | Most courses on Mon School are very interactive and include many live examples. The platform supports adding live examples in many programming languages. 7 | 8 | To add an example, use the following format and replace the `` with the name of the programming language. 9 | 10 | ```{. .example} 11 | code comes here 12 | ``` 13 | 14 | The following sections show how to add examples in various programming languages. 15 | 16 | ## Python 17 | 18 | The following in the syntax for adding a Python example. 19 | 20 | ```{.python .example} 21 | print("hello, world!") 22 | ``` 23 | 24 | And the it be rendered as the following: 25 | 26 | ```{.python .example} 27 | print("hello, world!") 28 | ``` 29 | 30 | ## Rust 31 | 32 | The following in the syntax for adding a Rust example. 33 | 34 | ```{.rust .example} 35 | fn main() { 36 | println!("Hello World!"); 37 | } 38 | ``` 39 | 40 | And the it be rendered as the following: 41 | 42 | ```{.rust .example} 43 | fn main() { 44 | println!("Hello World!"); 45 | } 46 | ``` 47 | 48 | ## Go 49 | 50 | The following in the syntax for adding a Go example. 51 | 52 | ```{.golang .example} 53 | package main 54 | 55 | import "fmt" 56 | 57 | func main() { 58 | fmt.Println("hello world") 59 | } 60 | ``` 61 | 62 | And the it be rendered as the following: 63 | 64 | ```{.golang .example} 65 | package main 66 | 67 | import "fmt" 68 | 69 | func main() { 70 | fmt.Println("hello world") 71 | } 72 | ``` 73 | 74 | ## Supporting a new programming language 75 | 76 | If the programming language that you are using for your course is not supported for live examples, please create an issue in [fossunited/falcon](https://github.com/fossunited/falcon/issues) repository and mention the course issue in `monschool_website` repo. It would be something like `fossunited/monschool#29`. 77 | 78 | 79 | -------------------------------------------------------------------------------- /courses/authoring-courses-on-mon-school/content/exercises.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Adding Exercises 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/authoring-courses-on-mon-school/content/generating-files.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Generating Files for All Lessons 3 | include_in_preview: false 4 | --- 5 | 6 | Once you've created a `course.yml` with all the lesson files listed, you can use a command to generate the stub files all the lessons. 7 | 8 | ``` 9 | $ python manage.py generate --course rust-for-beginners 10 | generated courses/rust-for-beginners/introduction/welcome.md 11 | generated courses/rust-for-beginners/introduction/rustup.md 12 | generated courses/rust-for-beginners/introduction/first-rust-program.md 13 | generated courses/rust-for-beginners/introduction/why-rust.md 14 | generated courses/rust-for-beginners/control-flow/conditionals.md 15 | generated courses/rust-for-beginners/control-flow/iteration.md 16 | ... 17 | ``` 18 | 19 | You can replace `rust-for-beginners` with the name of the course that you are creating and it will create stub files for every lesson. 20 | 21 | If a file is already present, it won't overwrite it. So, you can use it whenever you add a new lesson to the course. 22 | 23 | The top-section of the file includes the title of the lesson. You can edit the title if required. More information about the format of the lesson is explained in the next section. 24 | 25 | Once you generate the files for all the lessons, you can send your first pull request. Make sure you include the `course.yml` file and one file for each lesson in the pull request. 26 | -------------------------------------------------------------------------------- /courses/authoring-courses-on-mon-school/content/lessons.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Adding Content to Lessons 3 | include_in_preview: false 4 | --- 5 | 6 | Now that you are the course outline and stubs for each of the lessons, it is the time to see how to add content to each lesson. The content of each lesson is formatted using Markdown. 7 | 8 | ## The Lesson Format 9 | 10 | The contents of each lesson file would be in the following format. 11 | 12 | ``` 13 | --- 14 | title: Functions Closures 15 | include_in_preview: false 16 | --- 17 | 18 | contents of the lesson. 19 | ``` 20 | 21 | The first part is called the _frontmatter_ and it include the title of the lesson and whether not this lesson is included in course preview. It is suggested to leave that to `false` when you are creating the course. 22 | 23 | The second part is the body of the lesson in markdown. 24 | 25 | While, you can use all the markdown features, it is recommended to follow the following guidelines to make the course look consistent. 26 | 27 | * Use second-level heading (`##`) for section headings in the lesson 28 | * Make sure you enclose variable names and other inline code snippets in backticks. 29 | 30 | For example: 31 | 32 | 33 | 34 | 39 | 42 | 43 |
35 | ``` 36 | The function `circle` draws a circle on the screen. 37 | ``` 38 | 40 | The function `circle` draws a circle on the screen. 41 |
44 | 45 | The system supports including examples and exercises in lessons. We'll how to do that in the next lessons. 46 | -------------------------------------------------------------------------------- /courses/authoring-courses-on-mon-school/content/outline.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Creating Course Outline 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/authoring-courses-on-mon-school/content/preview-image.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Adding Course Preview Image 3 | include_in_preview: false 4 | --- 5 | 6 | Every course on mon school has a preview image displaying in the course listing page and the course page. 7 | 8 | ## Preparing the image 9 | 10 | The Mon School platform requires the image to be of a specific size. A utility has been provided to make it easier to convert the image that you have into an image that is suitable for mon school. 11 | 12 | ``` 13 | $ python manage.py prepare-image source-image courses/my-course/preview-image.png 14 | created courses/my-course/preview-image.png 15 | ``` 16 | 17 | ## Specifying the Image in course.yml 18 | 19 | Once you're prepared the image, you can specify the image in the `course.yml` file. 20 | 21 | ``` 22 | name: my-course 23 | title: My course 24 | ... 25 | preview_image: preview-image.png 26 | ... 27 | ``` 28 | 29 | The path to the image relative to the course directory is specified as field `preview_image`. It is recommended to name the image file `preview-image.png`. 30 | -------------------------------------------------------------------------------- /courses/authoring-courses-on-mon-school/course.yml: -------------------------------------------------------------------------------- 1 | name: authoring-courses-on-mon-school 2 | suffix: ms 3 | is_published: false 4 | upcoming: false 5 | tags: 6 | - Mon School 7 | video_link: 8 | title: Authoring Courses on Mon School 9 | instructor: anand_chitipothu 10 | short_introduction: Learn the process, tools, and best practices for authoring courses on Mon School 11 | description: | 12 | This course is meant for people interested in creating courses on Mon School. 13 | It covers the process that we follow at Mon School to create courses, the tools that are available and 14 | the recommended approach for creating courses. 15 | 16 | chapters: 17 | - name: welcome 18 | title: Welcome to Mon School 19 | description: Introduction to the Mon School platform 20 | lessons: 21 | - welcome/monschool.md 22 | 23 | - name: what-makes-a-good-course 24 | title: What Makes a Good Course 25 | description: "" 26 | lessons: [] 27 | 28 | - name: proposing-a-new-course 29 | title: Proposing a New Course 30 | description: "How to propose a new course to be included in Mon School?" 31 | lessons: [] 32 | 33 | - name: creating 34 | title: Creating the Course 35 | description: Learn how to start creating the course and how to add each kind of ingredient that goes into it. 36 | lessons: 37 | - content/outline.md 38 | - content/generating-files.md 39 | - content/preview-image.md 40 | - content/lessons.md 41 | - content/examples.md 42 | - content/exercises.md 43 | -------------------------------------------------------------------------------- /courses/authoring-courses-on-mon-school/welcome/monschool.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Monschool 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/building-online-games-with-python/adding-characters/getting-points.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Getting Points 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | -------------------------------------------------------------------------------- /courses/building-online-games-with-python/adding-characters/losing-lives.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Losing Lives 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | -------------------------------------------------------------------------------- /courses/building-online-games-with-python/collision/basic-collision-math.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Basic Collision Math 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | -------------------------------------------------------------------------------- /courses/building-online-games-with-python/collision/bounds-check.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Bounds Check 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | -------------------------------------------------------------------------------- /courses/building-online-games-with-python/collision/hit-check.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Hit Check 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | -------------------------------------------------------------------------------- /courses/building-online-games-with-python/control/key-controls.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Key Controls 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | -------------------------------------------------------------------------------- /courses/building-online-games-with-python/control/key-up-vs-down.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Key Up Vs Down 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | -------------------------------------------------------------------------------- /courses/building-online-games-with-python/control/mouse-controls.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Mouse Controls 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | -------------------------------------------------------------------------------- /courses/building-online-games-with-python/course.yml: -------------------------------------------------------------------------------- 1 | name: building-online-games-with-python 2 | suffix: pg 3 | is_published: false 4 | upcoming: true 5 | tags: 6 | - python 7 | - games 8 | video_link: 9 | title: Building Online Games with Python 10 | instructor: arun_ravindran 11 | short_introduction: Build online games with Python and impress your friends 12 | description: | 13 | Have you ever wanted to write your own game? 14 | Ever wondered if your friends could enjoy a gaming experience that you crafted? 15 | Modern games are very complex pieces of software. But you could still learn 16 | the fundamentals of game development, if you are familiar with Python - one of 17 | the most beginner friendly programming languages. This course starts from 18 | the very basics of creating animations and progresses until you could build 19 | a fully interactive game. Unlike other Python based games, these games run 20 | completely in the browser and are easy to share with your friends. 21 | chapters: 22 | - name: introduction 23 | title: Introduction 24 | description: Introduction to the course. 25 | lessons: 26 | - introduction/audience.md 27 | - introduction/setting-up.md 28 | - introduction/canvas.md 29 | - name: movement 30 | title: Movement 31 | description: Learn how to draw shapes and move them on the screen. 32 | lessons: 33 | - movement/animation-basics.md 34 | - movement/draw-update-loop.md 35 | - movement/drawing-primitives.md 36 | - movement/illusion-of-movement.md 37 | - movement/bouncing-ball.md 38 | - name: collision 39 | title: Collision 40 | description: Learn how to detect collisions in the game. 41 | lessons: 42 | - collision/basic-collision-math.md 43 | - collision/bounds-check.md 44 | - collision/hit-check.md 45 | - name: control 46 | title: Control 47 | description: Learn how to control the game using keyboard and mouse. 48 | lessons: 49 | - control/key-controls.md 50 | - control/key-up-vs-down.md 51 | - control/mouse-controls.md 52 | - name: adding-characters 53 | title: Adding Characters 54 | description: Learn how to keep track of score and multiple lives in the game. 55 | lessons: 56 | - adding-characters/getting-points.md 57 | - adding-characters/losing-lives.md 58 | - name: interface 59 | title: Interface 60 | description: Learn how to keep track of score and multiple lives in the game. 61 | lessons: 62 | - interface/display.md 63 | - interface/state-machines.md 64 | - interface/start-and-end-screens.md 65 | - name: publish 66 | title: Publish 67 | description: Publish you game and share it your friends. 68 | lessons: 69 | - publish/share-with-friends.md 70 | - publish/whats-next.md 71 | -------------------------------------------------------------------------------- /courses/building-online-games-with-python/interface/display.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Display 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | -------------------------------------------------------------------------------- /courses/building-online-games-with-python/interface/start-and-end-screens.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Start And End Screens 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | -------------------------------------------------------------------------------- /courses/building-online-games-with-python/interface/state-machines.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: State Machines 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | -------------------------------------------------------------------------------- /courses/building-online-games-with-python/introduction/audience.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Audience 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | -------------------------------------------------------------------------------- /courses/building-online-games-with-python/introduction/canvas.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Canvas 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | -------------------------------------------------------------------------------- /courses/building-online-games-with-python/introduction/setting-up.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Setting Up 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | -------------------------------------------------------------------------------- /courses/building-online-games-with-python/movement/animation-basics.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Animation Basics 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | -------------------------------------------------------------------------------- /courses/building-online-games-with-python/movement/bouncing-ball.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Bouncing Ball 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | -------------------------------------------------------------------------------- /courses/building-online-games-with-python/movement/draw-update-loop.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Draw Update Loop 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | -------------------------------------------------------------------------------- /courses/building-online-games-with-python/movement/drawing-primitives.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Drawing Primitives 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | -------------------------------------------------------------------------------- /courses/building-online-games-with-python/movement/illusion-of-movement.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Illusion Of Movement 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | -------------------------------------------------------------------------------- /courses/building-online-games-with-python/publish/share-with-friends.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Share With Friends 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | -------------------------------------------------------------------------------- /courses/building-online-games-with-python/publish/whats-next.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Whats Next 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/basic-html/handling-text.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Handling Text 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | 8 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/basic-html/head-body.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: HTML head and body 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | 8 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/basic-html/html-document-introduction.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Introduction to HTML Document 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | 8 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/basic-html/images.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Adding Images 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | 8 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/basic-html/links.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Adding Links 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | 8 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/basic-html/lists.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Creating Lists 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | 8 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/basic-html/tables.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Creating Tables 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | 8 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/capstone-project/approach.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Approach 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | 8 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/capstone-project/problem.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Problem 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | 8 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/course.js: -------------------------------------------------------------------------------- 1 | 2 | livecode.setOptions("python", { 3 | "runtime": "python-webapps", 4 | }); 5 | 6 | livecode.setOptions("jinja", { 7 | "mode": "python", 8 | "runtime": "python-webapps", 9 | "outputPreview": true 10 | }); 11 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/course.yml: -------------------------------------------------------------------------------- 1 | name: building-web-apps-with-python 2 | suffix: webapp 3 | is_published: false 4 | upcoming: true 5 | tags: 6 | - Web 7 | video_link: 8 | preview_image: preview-image.png 9 | title: Build Web Applications with Python 10 | instructor: thejeshgn 11 | short_introduction: Build Web Applications with Python 12 | description: | 13 | The web is the ultimate platform to build applications. You don't need permission to make an application for the web, and it's the platform anyone can build an application and publish it without anyone's approval. The best part is web development is very beginner-friendly. In this course, we will learn to make websites that you can share with your friends and family. We will also create web applications that respond to users using Python - the friendliest programming language. 14 | chapters: 15 | - name: basic-html 16 | title: Basic HTML 17 | description: Learn how to create an HTML document. 18 | lessons: 19 | - basic-html/html-document-introduction.md 20 | - basic-html/head-body.md 21 | - basic-html/handling-text.md 22 | - basic-html/links.md 23 | - basic-html/lists.md 24 | - basic-html/tables.md 25 | - basic-html/images.md 26 | - name: dynamic-html-using-jinja 27 | title: Dynamic HTML Using Jinja 28 | description: Learn to create the HTML documents programmatically using templates. 29 | lessons: 30 | - dynamic-html-using-jinja/formatting-in-python.md 31 | - dynamic-html-using-jinja/jinja2.md 32 | - dynamic-html-using-jinja/simple-jinja2-template.md 33 | - dynamic-html-using-jinja/conditions-and-loops.md 34 | - dynamic-html-using-jinja/creating-tables.md 35 | - dynamic-html-using-jinja/build-static-site.md 36 | - name: getting-started-with-flask 37 | title: Getting Started with Flask 38 | description: Learn how to create and serve HTML documents from a server. 39 | lessons: 40 | - getting-started-with-flask/introduction.md 41 | - getting-started-with-flask/routing-controllers.md 42 | - getting-started-with-flask/responding-to-users.md 43 | - getting-started-with-flask/return-html.md 44 | - getting-started-with-flask/return-html-using-jinja.md 45 | - getting-started-with-flask/build-a-simple-site.md 46 | - name: interacting-with-users 47 | title: Interacting with Users 48 | description: Learn how to interact with your web application users. 49 | lessons: 50 | - interacting-with-users/forms.md 51 | - interacting-with-users/submitting-form.md 52 | - interacting-with-users/responsing-to-user-submission.md 53 | - interacting-with-users/build-a-guestbook.md 54 | - name: styling 55 | title: Styling 56 | description: Learn how to make your web application look good 57 | lessons: 58 | - styling/introduction.md 59 | - styling/style-tag.md 60 | - styling/applying-style-to-html.md 61 | - styling/using-bootstrap.md 62 | - name: capstone-project 63 | title: Capstone Project 64 | description: Build a full-fledged application with everything we have learnt until now. 65 | lessons: 66 | - capstone-project/problem.md 67 | - capstone-project/approach.md 68 | - name: next 69 | title: What next? 70 | description: What to do next? 71 | lessons: 72 | - next/what-to-do.md 73 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/dynamic-html-using-jinja/build-static-site.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Build a Static Website 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | 8 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/dynamic-html-using-jinja/conditions-and-loops.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Conditions and Loops 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | 8 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/dynamic-html-using-jinja/creating-tables.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Creating Tables from Data 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | 8 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/dynamic-html-using-jinja/formatting-in-python.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Formatting Text in Python 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | 8 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/dynamic-html-using-jinja/jinja2.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Jinja2 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | 8 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/dynamic-html-using-jinja/simple-jinja2-template.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Simple Jinja Template 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | 8 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/getting-started-with-flask/build-a-simple-site.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Build a Simple Website 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | 8 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/getting-started-with-flask/introduction.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Introduction to Flask 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | 8 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/getting-started-with-flask/responding-to-users.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Responding to Website Users 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | 8 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/getting-started-with-flask/return-html-using-jinja.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Return HTML Content generated using Jinja 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | 8 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/getting-started-with-flask/return-html.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Return HTML Content 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | 8 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/getting-started-with-flask/routing-controllers.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Routing and Controllers 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | 8 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/interacting-with-users/build-a-guestbook.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Build a Guest Book 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | 8 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/interacting-with-users/forms.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: HTML Forms and User Inputs 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | 8 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/interacting-with-users/responsing-to-user-submission.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Responding to User Form Submission 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | 8 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/interacting-with-users/submitting-form.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Submitting the Form to Server 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | 8 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/next/what-to-do.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: What to do next? 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | 8 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/preview-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/building-web-apps-with-python/preview-image.png -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/styling/applying-style-to-html.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Applying CSS style to HTML Document 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | 8 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/styling/introduction.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Introduction to Styling 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | 8 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/styling/style-tag.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Using Style Tag 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | 8 | -------------------------------------------------------------------------------- /courses/building-web-apps-with-python/styling/using-bootstrap.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Using Bootstrap 3 | include_in_preview: false 4 | --- 5 | 6 | - 7 | 8 | -------------------------------------------------------------------------------- /courses/git-github-for-beginners/_images/git-clone-box-snapshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/git-github-for-beginners/_images/git-clone-box-snapshot.png -------------------------------------------------------------------------------- /courses/git-github-for-beginners/_images/git-clone-operation-snapshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/git-github-for-beginners/_images/git-clone-operation-snapshot.png -------------------------------------------------------------------------------- /courses/git-github-for-beginners/_images/git-push-operation-snapshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/git-github-for-beginners/_images/git-push-operation-snapshot.png -------------------------------------------------------------------------------- /courses/git-github-for-beginners/_images/git-repository-add-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/git-github-for-beginners/_images/git-repository-add-icon.png -------------------------------------------------------------------------------- /courses/git-github-for-beginners/_images/git-repository-form.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/git-github-for-beginners/_images/git-repository-form.png -------------------------------------------------------------------------------- /courses/git-github-for-beginners/_images/monschool-calculator-collaborator-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/git-github-for-beginners/_images/monschool-calculator-collaborator-page.png -------------------------------------------------------------------------------- /courses/git-github-for-beginners/_images/monschool-calculator-html-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/git-github-for-beginners/_images/monschool-calculator-html-snap.png -------------------------------------------------------------------------------- /courses/git-github-for-beginners/_images/monschool-calculator-pull-request-review-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/git-github-for-beginners/_images/monschool-calculator-pull-request-review-1.png -------------------------------------------------------------------------------- /courses/git-github-for-beginners/_images/monschool-calculator-pull-request-review-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/git-github-for-beginners/_images/monschool-calculator-pull-request-review-2.png -------------------------------------------------------------------------------- /courses/git-github-for-beginners/_images/monschool-calculator-pull-request-review.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/git-github-for-beginners/_images/monschool-calculator-pull-request-review.png -------------------------------------------------------------------------------- /courses/git-github-for-beginners/_images/monschool-calculator-pull-request-snap-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/git-github-for-beginners/_images/monschool-calculator-pull-request-snap-1.png -------------------------------------------------------------------------------- /courses/git-github-for-beginners/_images/monschool-calculator-pull-request-snap-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/git-github-for-beginners/_images/monschool-calculator-pull-request-snap-2.png -------------------------------------------------------------------------------- /courses/git-github-for-beginners/_images/monschool-calculator-pull-request-snap-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/git-github-for-beginners/_images/monschool-calculator-pull-request-snap-3.png -------------------------------------------------------------------------------- /courses/git-github-for-beginners/_images/monschool-calculator-pull-request-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/git-github-for-beginners/_images/monschool-calculator-pull-request-snap.png -------------------------------------------------------------------------------- /courses/git-github-for-beginners/_images/monschool-calculator-repository-aspects.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/git-github-for-beginners/_images/monschool-calculator-repository-aspects.png -------------------------------------------------------------------------------- /courses/git-github-for-beginners/_images/monschool-calculator-repository.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/git-github-for-beginners/_images/monschool-calculator-repository.png -------------------------------------------------------------------------------- /courses/git-github-for-beginners/_images/monschool-merge-conflict-snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/git-github-for-beginners/_images/monschool-merge-conflict-snap.png -------------------------------------------------------------------------------- /courses/git-github-for-beginners/_images/monschool-resolved-merge-conflict.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/git-github-for-beginners/_images/monschool-resolved-merge-conflict.png -------------------------------------------------------------------------------- /courses/git-github-for-beginners/_images/rotten-scripts-collaborators-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/git-github-for-beginners/_images/rotten-scripts-collaborators-page.png -------------------------------------------------------------------------------- /courses/git-github-for-beginners/collaborative-development/pulling-changes.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Pulling Changes 3 | include_in_preview: false 4 | --- 5 | 6 | As we discussed in the previous section, a collaborator can push their work to your repository. It means that we need a workflow to pull their work every now and then to ensure that your local repository is always updated. To do that, we use a command called `git pull`. 7 | 8 | The Git pull operations, prompts Git to connect to GitHub, which acts as a remote repository, and ensure that all the changes are integrated into your local repository without any conflicts. 9 | 10 | The `git pull` command is also a combination of two other Git commands: `git fetch`, which fetches all the new commits from the remote repository, and `git merge`, which merges the fetched commits into your local repository. Through the Git pull operation: 11 | 12 | - Your local working branch is updated and all new commits from the remote repository are available locally. 13 | - Your remote tracking branch is updated as well and you can continue working on any of them. 14 | 15 | The syntax of the `git pull` command: 16 | 17 | ```sh 18 | git pull 19 | ``` 20 | 21 | The `remote-name` acts as the name of the remote repository. The `branch-name` acts as the name of the branch that you want to pull from the remote repository. 22 | 23 | Let's check out an example. We recently made a commit, directly through GitHub interface. Consider that this change has been made by your fellow collaborator. You need to pull those changes to ensure that your local repository is up to date. To do that, you can simply run the following command: 24 | 25 | ```sh 26 | $ git pull origin main 27 | 28 | remote: Enumerating objects: 5, done. 29 | remote: Counting objects: 100% (5/5), done. 30 | remote: Compressing objects: 100% (3/3), done. 31 | remote: Total 3 (delta 2), reused 0 (delta 0), pack-reused 0 32 | Unpacking objects: 100% (3/3), 802 bytes | 267.00 KiB/s, done. 33 | From github.com:HarshCasper/monschool-calculator 34 | * branch main -> FETCH_HEAD 35 | c3bd105..f3209e7 main -> origin/main 36 | Updating c3bd105..f3209e7 37 | Fast-forward 38 | index.html | 4 +++- 39 | 1 file changed, 3 insertions(+), 1 deletion(-) 40 | ``` 41 | 42 | If you do a `git log` command, you will see that the commit has been pulled from the remote repository: 43 | 44 | ```sh 45 | commit f3209e7b30e30998bb576118f1384082185838f3 (HEAD -> main, origin/main, origin/HEAD) 46 | Author: Harsh Mishra 47 | Date: Tue Mar 15 00:05:35 2022 +0530 48 | 49 | feat: add a text about the purpose of this project 50 | 51 | commit c3bd105c8db2845c3202e953b1103d99cd8c7668 52 | Author: HarshCasper 53 | Date: Mon Mar 14 17:34:17 2022 +0530 54 | 55 | feat: add a heading and a text to the index.html file 56 | ``` 57 | 58 | Using a combination of `git pull` and `git push`, you can ensure that you are pushing in small chunks of your work every now and then, and also that you are pulling in commits pushed by your collaborator. This is a very important feature of Git. With Git pull, we have covered all four network interactions in Git: 59 | 60 | - `git clone` 61 | - `git push` 62 | - `git fetch` 63 | - `git pull` 64 | 65 | The Git fetch operation ensures that all the remote branches are updated. However no changes are actually reflected on the local repository. Only the Git merge operation, can merge all the pulled changes and ensure that the local repository is up to date. 66 | 67 | Do note that if you have uncommitted changes, you will get a warning message. In case two commits are conflicting, a merge conflict would arise which we would need to fix. However, the goldern rule is that you should always commit your changes before pulling new commits to a remote repository. 68 | -------------------------------------------------------------------------------- /courses/git-github-for-beginners/getting-started/pushing-commits.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Pushing Commits 3 | include_in_preview: false 4 | --- 5 | 6 | In the previous chapter, we made changes to our repository and committed them. Now, let's push those changes to the remote repository. It would allow your collaborators to view the changes that you have made and would allow them to pull your changes to their local repository. 7 | 8 | For the purpose of this course, we are using GitHub as our Git-based service provider, but you can use the same procedure to push your changes to any Git-hosting service provider (like GitLab or BitBucket). 9 | 10 | In the `Git Repository` and `Git Cloning` chapters, we saw that we have created a repository on GitHub, cloned it and worked on it. To push your changes back to the remote repository, you can use the command `git push`. Let's try it out: 11 | 12 | ```sh 13 | $ git push 14 | 15 | Enumerating objects: 4, done. 16 | Counting objects: 100% (4/4), done. 17 | Delta compression using up to 10 threads 18 | Compressing objects: 100% (3/3), done. 19 | Writing objects: 100% (3/3), 427 bytes | 427.00 KiB/s, done. 20 | Total 3 (delta 1), reused 0 (delta 0), pack-reused 0 21 | remote: Resolving deltas: 100% (1/1), completed with 1 local object. 22 | To github.com:HarshCasper/monschool-calculator.git 23 | 57d21bb..ae4a133 main -> main 24 | ``` 25 | 26 | If you navigate to the GitHub repository, you will see that a new commit and a new file has been added to the repository. 27 | 28 | ![Snapshot of the push operation for the MonSchool Calculator repository](../_images/git-push-operation-snapshot.png) 29 | -------------------------------------------------------------------------------- /courses/git-github-for-beginners/getting-started/time-travelling-with-git.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Time Travelling With Git 3 | include_in_preview: false 4 | --- 5 | 6 | Git also provides you time travelling capabilities! Just joking, let's see how to use it. 7 | 8 | Using Git you can checkout any previous snapshot into the working directory. It allows you to go back in the history of your project, understand what has changed and how it has changed. It is especially useful when you are working on a project, and want to trace a bug or a feature that you would like to see the implementation for. 9 | 10 | To do that, we use the Git checkout operation. Checkout means that we are checking out a particular snapshot of the project. Checking out a past commit will result in a detached HEAD. A detached HEAD means that after checking out a particular commit, all the changes made to the project won't belong any more to the current branch. This is the reason why Git would suggest you to commit your changes before checking out a past commit, since your work might be lost. 11 | 12 | To checkout to a previous commit, we need to retrieve the hash of a previous version of the project. To do that, we use the `git log` command. 13 | 14 | ```sh 15 | Author: Harsh Mishra 16 | Date: Tue Mar 15 00:05:35 2022 +0530 17 | 18 | feat: add a text about the purpose of this project 19 | 20 | commit c3bd105c8db2845c3202e953b1103d99cd8c7668 21 | Author: HarshCasper 22 | Date: Mon Mar 14 17:34:17 2022 +0530 23 | 24 | feat: add a heading and a text to the index.html file 25 | 26 | commit ae4a133ae0fb235a0714718b36cb7cba5ee7028d 27 | Author: HarshCasper 28 | Date: Mon Mar 14 13:57:40 2022 +0530 29 | 30 | add a basic HTML template 31 | 32 | commit 57d21bb234802d20511cc4863c04f7bffea0d46b 33 | Author: Harsh Mishra 34 | Date: Tue Mar 8 13:01:05 2022 +0530 35 | ``` 36 | 37 | Every commit has a hash associated with it. The hash is a unique identifier for the commit. We can use the hash to checkout to a particular commit. For example, for the commit that has the message `feat: add a heading and a text to the index.html file`, the commit hash is `c3bd105c8db2845c3202e953b1103d99cd8c7668`. 38 | 39 | To checkout the commit `c3bd105c8db2845c3202e953b1103d99cd8c7668`, we can use the following command: 40 | 41 | ```sh 42 | git checkout c3bd105c8db2845c3202e953b1103d99cd8c7668 43 | ``` 44 | 45 | You will receive an output similar to this: 46 | 47 | ```sh 48 | Note: switching to 'c3bd105c8db2845c3202e953b1103d99cd8c7668'. 49 | 50 | You are in 'detached HEAD' state. You can look around, make experimental 51 | changes and commit them, and you can discard any commits you make in this 52 | state without impacting any branches by switching back to a branch. 53 | 54 | If you want to create a new branch to retain commits you create, you may 55 | do so (now or later) by using -c with the switch command. Example: 56 | 57 | git switch -c 58 | 59 | Or undo this operation with: 60 | 61 | git switch - 62 | 63 | Turn off this advice by setting config variable advice.detachedHead to false 64 | 65 | HEAD is now at c3bd105 feat: add a heading and a text to the index.html file 66 | ``` 67 | 68 | You can now quickly inspect an old version of your project. However be cautious of the fact that since there is no branch reference to the current `HEAD`, you are in the detached `HEAD` state. To get back to the latest commit and the current `HEAD`, you need to use the `git checkout` command: 69 | 70 | ```sh 71 | git switch - 72 | ``` 73 | -------------------------------------------------------------------------------- /courses/git-github-for-beginners/github-flow/fork-cloning.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Fork Cloning 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/git-github-for-beginners/github-flow/fork-updating.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Fork Updating 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/git-github-for-beginners/github-flow/git-rebasing.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Git Rebasing 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/git-github-for-beginners/github-flow/git-stashing.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Git Stashing 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/git-github-for-beginners/github-flow/managing-remote-repositories.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Managing Remote Repositories 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/git-github-for-beginners/introduction-to-git/git-objects.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Git Objects 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/git-github-for-beginners/introduction-to-git/git-workflow.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Git Workflow 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/git-github-for-beginners/open-source/automated-tests.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Automated Tests 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/git-github-for-beginners/open-source/fixing-issues-with-pull-requests.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Fixing Issues With Pull Requests 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/git-github-for-beginners/open-source/good-first-issues.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Good First Issues 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/git-github-for-beginners/open-source/leveraging-documentation.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Leveraging Documentation 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/git-github-for-beginners/open-source/open-source-etiquette.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Open Source Etiquette 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/git-github-for-beginners/open-source/open-source-software.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Open Source Software 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/index.md: -------------------------------------------------------------------------------- 1 | # List of Courses 2 | 3 | * [Authoring Courses on Mon School](authoring-courses-on-mon-school/welcome/monschool/) 4 | * [Building Online Games with Python](building-online-games-with-python/introduction/audience/) 5 | * [Building Web Apps with Python](building-web-apps-with-python/basic-html/html-document-introduction/) 6 | * [Git & Github for Beginners](git-github-for-beginners/introduction-to-git/why-version-control-system/) 7 | * [Mypy Primer](mypy-primer/introduction/what-is-mypy/) 8 | * [Rust for Beginners](rust-for-beginners/introduction/welcome/) 9 | * [Self Hosting 101](self-hosting-101/week0/why-self-host/) 10 | * [Python Primer](python-primer/getting-started/hello-python/) 11 | -------------------------------------------------------------------------------- /courses/let-us-go/course.yml: -------------------------------------------------------------------------------- 1 | name: let-us-go 2 | title: Let Us Go 3 | instructor: abpillai 4 | is_published: false 5 | upcoming: true 6 | tags: 7 | - golang 8 | video_link: 9 | suffix: go 10 | short_introduction: Getting started with the Go programming language 11 | description: | 12 | This course will teach the basics of Go and also cover a few advanced 13 | topics like concurrency with Go using channels and go-routines. 14 | 15 | chapters: 16 | - name: getting-to-go 17 | title: Getting to Go 18 | description: Let us get a taste of Go 19 | lessons: 20 | - getting-to-go/hello-world.md 21 | - getting-to-go/data-types.md 22 | - getting-to-go/variables.md 23 | - name: exploring 24 | title: Exploring Go 25 | description: We explore the fundamentals of Go 26 | lessons: 27 | - exploring/control-flow.md 28 | - explorng/functions.md 29 | - name: going-deep 30 | title: Going Deep 31 | description: We Go a bit deep to dig out the hidden gems of Go 32 | lessons: 33 | - going-deep/arrays-maps.md 34 | - going-deep/structures.md 35 | - going-deep/methods.md 36 | - name: practical-go 37 | title: Practial Go 38 | description: > 39 | We look at some real life practical examples such as handling files, 40 | URLs and how to manage errors in code. 41 | lessons: 42 | - practical-go/streams-files.md 43 | - practical-go/error-handling.md 44 | - practical-go/text-file-game.md 45 | - name: go-in-parallel 46 | title: Go in Parallel 47 | description: Let us see how we can get Going in parallel and write concurrent code 48 | lessons: 49 | - go-in-parallel/concurrency.md 50 | - go-in-parallel/goroutines-and-channels.md 51 | - go-in-parallel/card-game.md 52 | - name: go-out-in-style 53 | title: Go Out in Style 54 | description: How to package and write your Go code in style 55 | lessons: 56 | - go-out-in-style/coding-style.md 57 | - go-out-in-style/gofmt.md 58 | - go-out-in-style/packaging.md 59 | -------------------------------------------------------------------------------- /courses/let-us-go/exploring/control-flow.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Control Flow 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/let-us-go/explorng/functions.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Functions 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/let-us-go/getting-to-go/data-types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Data Types 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/let-us-go/getting-to-go/hello-world.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Hello World 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/let-us-go/getting-to-go/variables.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Variables 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/let-us-go/go-in-parallel/card-game.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Card Game 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/let-us-go/go-in-parallel/concurrency.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Concurrency 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/let-us-go/go-in-parallel/goroutines-and-channels.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Goroutines And Channels 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/let-us-go/go-out-in-style/coding-style.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Coding Style 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/let-us-go/go-out-in-style/gofmt.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Gofmt 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/let-us-go/go-out-in-style/packaging.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Packaging 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/let-us-go/going-deep/arrays-maps.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Arrays Maps 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/let-us-go/going-deep/methods.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Methods 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/let-us-go/going-deep/structures.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Structures 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/let-us-go/practical-go/error-handling.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Error Handling 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/let-us-go/practical-go/streams-files.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Streams Files 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/let-us-go/practical-go/text-file-game.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Text File Game 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/mypy-primer/_images/pycharm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/mypy-primer/_images/pycharm.png -------------------------------------------------------------------------------- /courses/mypy-primer/_images/typescript1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/mypy-primer/_images/typescript1.png -------------------------------------------------------------------------------- /courses/mypy-primer/_images/typescript2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/mypy-primer/_images/typescript2.png -------------------------------------------------------------------------------- /courses/mypy-primer/_images/vscode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/mypy-primer/_images/vscode.png -------------------------------------------------------------------------------- /courses/mypy-primer/advanced-type-checking/the-type-type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: The Type type 3 | include_in_preview: false 4 | --- 5 | 6 | `Type` is a type used to type classes. It derives from python's way of figuring 7 | out the type of an object at runtime: 8 | 9 | ```{.python .example .mypy-strict} 10 | a, b = 1, 2 11 | s = 'hello' 12 | 13 | print(type(a)) # 14 | print(type(b)) # 15 | print(type(a) == int) # True 16 | print(type(a) == type(b)) # True 17 | print(type(a) == type(s)) # False 18 | ``` 19 | 20 | Since `type(x)` returns the class of `x`, the type of a class `C` is `Type[C]`. 21 | 22 | ```{.python .example .mypy-strict} 23 | from typing import Any, Type, TypeVar 24 | 25 | class MyClass: 26 | def __init__(self, x: int) -> None: 27 | self.x = x 28 | 29 | def __repr__(self) -> str: 30 | return f'C(x={self.x})' 31 | 32 | 33 | T = TypeVar('T') 34 | 35 | def make_object(cls: Type[T], *args: Any) -> T: 36 | print('making object of', cls) 37 | obj = cls(*args) 38 | return obj 39 | 40 | 41 | c = make_object(MyClass, 42) 42 | 43 | print(c) 44 | print(c.x) 45 | ``` 46 | 47 | We have now made a function that can take in classes as arguments. Doing 48 | `reveal_type(c)` correctly tells us that it's an object of `MyClass`. 49 | -------------------------------------------------------------------------------- /courses/mypy-primer/advanced-type-checking/type-checking-exercises.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Typing exercises 3 | include_in_preview: false 4 | --- 5 | 6 | Some ideas: 7 | 8 | - using `contextlib.contextmanager` to write a typed context manager 9 | - making a simple type checked web server 10 | -------------------------------------------------------------------------------- /courses/mypy-primer/conclusion/integrating-mypy.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Integrating mypy into your software development lifecycle 3 | include_in_preview: false 4 | --- 5 | 6 | This is a video-only section. Video coming soon. 7 | -------------------------------------------------------------------------------- /courses/mypy-primer/conclusion/type-checking-or-tests.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Type checking, or writing tests? Why not both! 3 | include_in_preview: false 4 | --- 5 | 6 | Ever since static and dynamic typed languages have existed, there has existed an 7 | argument between them, one that argues what's better: type checking, or writing 8 | tests. 9 | 10 | The argument essentially boils down to these two sides: The dynamic side would 11 | say something like, "I've been writing python for so long without types, why 12 | should I care now?", or, "I don't need types in my code because I write tests". 13 | Conversely, people can think they don't need tests (at least not as much as 14 | dynamic languages) because their type checker catches their bugs for them. 15 | 16 | The truth is that both of these arguments are extreme, and this, both are wrong. 17 | The correct answer lies somewhere between them. I think both static types and 18 | tests are equally necessary in a large codebase, because *they both serve a 19 | different purpose*. 20 | 21 | ### Why types 22 | 23 | Type checking eliminate a whole class of bugs from your codebase: type errors. 24 | 25 | Writing good tests is hard, especially in a dynamically typed language. It's 26 | very easy to write tests that forget to check all the possible invalid types 27 | that you could pass to the function. For example: 28 | 29 | ```{.python .example .mypy-strict} 30 | def process(items): 31 | for item in items: 32 | print("Processing", item.value.id) 33 | ``` 34 | 35 | It is very easy to write 5 different passing tests for this code, but forget to 36 | write a test where `value` is `None`. If it is `None`, you'll get an attribute 37 | error raised at runtime. 38 | 39 | If the schema of each `item` object was well defined beforehand, the problem 40 | would've easily been caught beforehand: 41 | 42 | ```{.python .example .mypy-strict} 43 | from dataclasses import dataclass 44 | from typing import Iterable 45 | 46 | @dataclass 47 | class ItemDetails: 48 | id: int 49 | name: str 50 | 51 | @dataclass 52 | class Item: 53 | value: ItemDetails | None 54 | weight: int 55 | 56 | def process(items: Iterable[Item]) -> None: 57 | for item in items: 58 | print("Processing", item.value.id) 59 | ``` 60 | 61 | Now mypy will catch that problem for you. Same goes for if someone tries to pass 62 | something completely wrong to `process`, like a dictionary. Mypy has taken the 63 | burden of handling completely invalid usage of your code away from you, so that 64 | you can focus on the fine details. 65 | 66 | ### Why tests 67 | 68 | Tests are important, because they are necessary for checking your logic. 69 | Logical errors can't be possibly tested through type checking. For example, 70 | here's a perfectly type checked code: 71 | 72 | ```{.python .example .mypy-strict} 73 | def sum(a: int, b: int) -> int: 74 | return (a + b) // 2 75 | ``` 76 | 77 | This is a really obvious example, but real world scenarios can be much more 78 | complicated than this. You can't expect a code analysis tool to figure out 79 | problems like deadlocks, missing `else`-clauses, incomplete or invalid logic, 80 | etc. Thus, testing your code and all its possible outputs is an essential part 81 | of developing a big project. 82 | 83 | *Both type checkers and tests work in unison*: Type checking takes away the task 84 | of identifying and fixing inputs to your code that are obviously invalid, such 85 | as passing a `str` instead of `int`. Tests on the other hand, prevent more fine 86 | grained bugs, that can come from logical errors and the like. 87 | 88 | So my advice would be to use both tests and types -- so that you can be 89 | completely confident in your code's correctness. 90 | -------------------------------------------------------------------------------- /courses/mypy-primer/course.js: -------------------------------------------------------------------------------- 1 | 2 | livecode.setOptions("python", { 3 | "runtime": "mypy", 4 | "buttons": [{ 5 | "id": "validate", 6 | "label": "Validate", 7 | "args": { 8 | "mode": "mypy" 9 | } 10 | }], 11 | events: { 12 | created: function(editor) { 13 | if ($(editor.element).hasClass("mypy-strict")) { 14 | editor.options.env['MYPY_STRICT'] = "true"; 15 | editor.setLabel("mypy --strict") 16 | } 17 | else { 18 | editor.setLabel("mypy") 19 | } 20 | 21 | if (editor.options.stdin) { 22 | editor.options.env['FALCON_STDIN'] = editor.options.stdin; 23 | } 24 | } 25 | } 26 | }); 27 | 28 | -------------------------------------------------------------------------------- /courses/mypy-primer/introduction/installing-mypy.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Installing mypy on your machine, and in your code editor 3 | include_in_preview: true 4 | --- 5 | 6 | Before we move ahead with the rest of the course, I want to explain how you can 7 | install mypy on your machine and code editor. 8 | 9 | ## Installing mypy locally 10 | 11 | To run `mypy` locally, you need to have Python installed. 12 | 13 | - If you're running Windows 10, you can open Command Prompt, and type `python`, 14 | which should either start Python, or open up Windows Store, where you can 15 | install it. 16 | - On a Mac or linux machine, you probably already have Python installed, under 17 | the name `python3`. Simply open a terminal and type `python3` to confirm. 18 | 19 | Now to install mypy, you need to run `pip`, a package manager which comes with 20 | Python: 21 | 22 | ```console 23 | $ python -m pip install mypy 24 | Collecting mypy 25 | [...] 26 | Successfully installed mypy-0.x typing-extensions-4.x 27 | ``` 28 | 29 | Now you should have access to the `mypy` command: 30 | 31 | ```console 32 | $ mypy 33 | usage: mypy [-h] [-v] [-V] [more options; see below] 34 | [-m MODULE] [-p PACKAGE] [-c PROGRAM_TEXT] [files ...] 35 | mypy: error: Missing target module, package, files, or command. 36 | ``` 37 | 38 | To test it, pass it the name of any Python file: 39 | 40 | ```console 41 | $ mypy code.py 42 | Success: no issues found in 1 source file 43 | ``` 44 | 45 | ## Editor integration 46 | 47 | While mypy and the other type checkers can be used directly through the command line, it is a bit more convenient for IDE users if the type checking errors integrate directly with their editor. There are two popular editors for Python users which can do this, Visual Studio Code and PyCharm. Let’s take a look at them. 48 | 49 | ### Visual Studio Code 50 | 51 | VSCode has a Python extension that comes with an official language server called “Pylance”, which provides type information out of the box. 52 | 53 | You can however, enable mypy support in VSCode as well, by adding the following to your settings.json file: 54 | 55 | ```json 56 | ... 57 | "python.linting.mypyEnabled": true, 58 | "python.linting.mypyArgs": [ 59 | "--ignore-missing-imports", 60 | "--follow-imports=silent", 61 | "--show-column-numbers", 62 | "--strict" 63 | ], 64 | ... 65 | ``` 66 | 67 | You should then be able to see type checking issues directly in your code: 68 | 69 | {{ Image("vscode.png") }} 70 | 71 | If you don’t, restart your editor and that should resolve any issues. 72 | 73 | ### PyCharm 74 | 75 | PyCharm has created its own type inference and refactoring system that works quite well and provides things like attribute auto-completion in the IDE by default. If you want to integrate `mypy` however, a Plugin called “Mypy” made by Roberto Leinardi exists in the JetBrains Marketplace. Simply installing it should enable mypy checks for you: 76 | 77 | {{ Image("pycharm.png") }} 78 | -------------------------------------------------------------------------------- /courses/mypy-primer/introduction/using-mypy.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Using mypy to type-check your code 3 | include_in_preview: true 4 | --- 5 | 6 | Now that we have mypy set up, let's figure out how to use it for your files and 7 | projects. 8 | 9 | Running it on a single file is the most straightforward way. Let's make one and 10 | test it: 11 | 12 | 16 | 17 | ```{#mypy1 .python .example} 18 | def greet(name): 19 | print(f"Hello, {name}!") 20 | 21 | if __name__ == '__main__': 22 | name = input("Enter your name: ") 23 | age = input("Enter your age: ") 24 | 25 | greet(name) 26 | print(f"You will be {age + 1} years old next year.") 27 | ``` 28 | 29 | Saving it as a file named `code.py`. To type check it, just do: 30 | 31 | ```console 32 | $ mypy code.py 33 | code.py:9: error: Unsupported operand types for + ("str" and "int") 34 | Found 1 error in 1 file (checked 1 source file) 35 | ``` 36 | 37 | Mypy says there's a problem in line 9, and yeah, we forgot to cast `age` to an 38 | integer. So let's do that: 39 | 40 | 44 | 45 | ```{#mypy2 .python .example} 46 | def greet(name): 47 | print(f"Hello, {name}!") 48 | 49 | if __name__ == '__main__': 50 | name = input("Enter your name: ") 51 | age = int(input("Enter your age: ")) 52 | 53 | greet(name) 54 | print(f"You will be {age + 1} years old next year.") 55 | ``` 56 | 57 | Now let's see what mypy says: 58 | 59 | ```console 60 | $ mypy code.py 61 | Success: no issues found in 1 source file 62 | ``` 63 | 64 | You've already seen that `mypy` has a "strict mode", and a non-strict mode. Mypy 65 | by default won't complain about functions that don't have type annotations. To 66 | use mypy in strict mode, you just have to pass the `--strict` flag: 67 | 68 | ```console 69 | mypy --strict code.py 70 | code.py:1: error: Function is missing a type annotation 71 | code.py:8: error: Call to untyped function "greet" in typed context 72 | Found 2 errors in 1 file (checked 1 source file) 73 | ``` 74 | 75 | It says accordingly, that we are missing type annotations on `def greet()`. 76 | Let's fix that: 77 | 78 | 82 | 83 | ```{#mypy3 .python .example .mypy-strict} 84 | def greet(name: str) -> None: 85 | print(f"Hello, {name}!") 86 | 87 | if __name__ == '__main__': 88 | name = input("Enter your name: ") 89 | age = int(input("Enter your age: ")) 90 | 91 | greet(name) 92 | print(f"You will be {age + 1} years old next year.") 93 | ``` 94 | 95 | And now `mypy` is happy again. 96 | 97 | ### Using mypy on a project 98 | 99 | You can pass an entire folder for `mypy` to check, and it will find every single 100 | python file inside it and check it. 101 | 102 | Say you have a folder structure like this: 103 | 104 | ```console 105 | myproject 106 | ├── setup.py 107 | └── src/ 108 | ├── bar.py 109 | └── foo.py 110 | ``` 111 | 112 | Using the command `mypy ` will check all the 3 files: 113 | 114 | ```console 115 | $ mypy myproject 116 | Success: no issues found in 3 source files 117 | ``` 118 | 119 | Notice that it says "3 source files". Similarly, you can also do 120 | `mypy --strict myproject` to run it in strict-mode on all files. 121 | 122 | Now that you have mypy set-up and running locally, you can run and type check 123 | your code on your own machine as well. 124 | -------------------------------------------------------------------------------- /courses/mypy-primer/mypy-errors/type-checking-examples.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Simple type checking examples 3 | include_in_preview: false 4 | --- 5 | 6 | The most that you'll be doing with mypy is tweaking your code, fixing potential 7 | bugs, and changing your type annotations, to make mypy confident that your code 8 | is good. Let's look at a couple more code examples and see what mypy says about 9 | them. 10 | 11 | ## Colors? 12 | 13 | Let's write something to find a user's favorite color: 14 | 15 | ```{.python .example .mypy-strict} 16 | user_data = { 17 | 'name': 'Mike Tyson', 18 | 'color': 'red', 19 | 'city': 'New York', 20 | } 21 | 22 | def get_favorite_color() -> str: 23 | favorite_color = user_data.get('color') 24 | return favorite_color 25 | 26 | print("Tyson's favorite color is:", get_favorite_color()) 27 | ``` 28 | 29 | The code runs fine, but mypy isn't happy yet. Why is that? The message is a bit 30 | cryptic: 31 | 32 | ```console 33 | mycode.py:9: error: Incompatible return value type (got "Optional[str]", expected "str") 34 | ``` 35 | 36 | Here's what mypy is saying: `user_data.get(...)` returns an `Optional[str]`, but 37 | the function is supposed to return a `str`. What it's trying to say is: `.get()` 38 | can possibly return `None`. (We'll explore `Optional` in detail later.) 39 | 40 | Though `data` is defined with a `color` property in it, the code _could_ have 41 | changed the dictionary's contents, and removed the `color` property from inside 42 | it. Figuring out what value is and isn't inside a dictionary isn't possible 43 | without actually running the code, so mypy doesn't assume anything. 44 | 45 | Essentially, `mypy` is concerned that `user_data.get(...)` could return `None`, 46 | which goes against your annotation of `-> str`. 47 | 48 | To fix it, we can do multiple things, but for now, let's just assure mypy that 49 | we're always going to have `color` in the dictionary. 50 | 51 | For that, let's add a runtime assertion: 52 | 53 | ```{.python .example .mypy-strict} 54 | user_data = { 55 | 'name': 'Mike Tyson', 56 | 'color': 'red', 57 | 'city': 'New York', 58 | } 59 | 60 | def get_favorite_color() -> str: 61 | favorite_color = user_data.get('color') 62 | assert favorite_color is not None 63 | return favorite_color 64 | 65 | print("Tyson's favorite color is:", get_favorite_color()) 66 | ``` 67 | 68 | If `favorite_color` is ever `None`, Python will crash at runtime. So, mypy can 69 | guarantee that the color is a `str`. Mypy is convinced, and your types are 70 | perfectly valid. 71 | 72 | > There is another similar way to solve this, by not using `.get()`. I'll leave 73 | > that for you to figure out. 74 | 75 | ## An exercise 76 | 77 | Try adding types to this code, and figure out if this code has any bugs: 78 | 79 | ```{.python .example .mypy-strict} 80 | def average(a, b, c): 81 | return (a + b + c) / 3 82 | 83 | english, science, math = 75, 87, 90 84 | avg_score = average(english, science, math) 85 | 86 | def print_scorecard(score): 87 | print(f"Average score is: {score}") 88 | 89 | if avg_score.is_integer(): 90 | print_scorecard(int(avg_score)) 91 | else: 92 | print_scorecard(avg_score) 93 | ``` 94 | -------------------------------------------------------------------------------- /courses/mypy-primer/mypy-errors/using-reveal-type.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Using reveal_type() to debug types 3 | include_in_preview: false 4 | --- 5 | 6 | The last fundamental feature I want to introduce about mypy is the existence of 7 | the `reveal_type` function. 8 | 9 | This function doesn't actually exist in Python, in the `typing` module, or 10 | anywhere else. But mypy understands it. `reveal_type` is used to ask mypy 11 | about what it thinks the type of a variable is. 12 | 13 | Here's a quick demo: 14 | 15 | ```{.python .example .mypy-strict} 16 | string = "This is a string" 17 | length = len(string) 18 | reveal_type(length) 19 | ``` 20 | 21 | So we're able to know that mypy thinks that `length` is an integer. But if you 22 | try to run the code, it will immediately crash, saying `reveal_type` is not 23 | defined. 24 | 25 | And this is a feature -- this ensures you don't accidentally leave a 26 | `reveal_type` statement in your code after you're done debugging. Also When you 27 | use `reveal_type`, mypy exits with an error code, saying that the code isn't 28 | currently in working shape. 29 | 30 | But the important part is, now you can easily know what mypy is thinking about 31 | your code, and you can debug your types. 32 | 33 | ## An old friend 34 | 35 | Let's use `reveal_type` to debug an older code example that we saw and fixed: 36 | 37 | ```{.python .example .mypy-strict} 38 | import json 39 | from itertools import cycle 40 | 41 | items_json = """ 42 | { 43 | "items": [ 44 | "item 1", "item 2", "item 3", "item 4", "item 5", 45 | "item 6", "item 7", "item 8", "item 9", "item 10" 46 | ] 47 | } 48 | """ 49 | 50 | def get_worker_count(): return 4 51 | 52 | def run_processes() -> None: 53 | worker_count = get_worker_count() 54 | print("Running with " + worker_count + " workers") 55 | 56 | workers = range(worker_count) 57 | 58 | items = json.loads(items_json) 59 | reveal_type(items) 60 | for item, worker in zip(items, cycle(workers)): 61 | print(f"Processing {item} with worker {worker}") 62 | 63 | 64 | if __name__ == "__main__": 65 | run_processes() 66 | ``` 67 | 68 | > Remember to comment out the `reveal_type` lines when trying to run the code! 69 | 70 | Using reveal_type, we see a new result: it says the type of `items` is `Any`. 71 | 72 | We'll talk about `Any` type and its uses in detail in the next chapter, but you 73 | can understand it basically saying "`items` can be anything". Mypy has no idea 74 | what it can be. 75 | 76 | With the fixed code, mypy understands the types correctly: 77 | 78 | ```{.python .example .mypy-strict} 79 | import json 80 | from itertools import cycle 81 | from time import sleep 82 | 83 | items_json = """ 84 | { 85 | "items": [ 86 | "item 1", "item 2", "item 3", "item 4", "item 5", 87 | "item 6", "item 7", "item 8", "item 9", "item 10" 88 | ] 89 | } 90 | """ 91 | 92 | def get_worker_count() -> int: return 4 93 | 94 | def run_processes() -> None: 95 | worker_count = get_worker_count() 96 | print("Running with " + str(worker_count) + " workers") 97 | 98 | workers = range(worker_count) 99 | 100 | data = json.loads(items_json) 101 | items = data['items'] 102 | assert isinstance(items, list) 103 | reveal_type(items) 104 | 105 | for item, worker in zip(items, cycle(workers)): 106 | reveal_type(item) 107 | reveal_type(worker) 108 | print(f"Running {item} with worker {worker}") 109 | 110 | 111 | if __name__ == "__main__": 112 | run_processes() 113 | ``` 114 | 115 | Now mypy is confident that `items` is a list. But what does it contain? No idea. 116 | Could be anything. Similarly, checking the types of `item` and `worker`, we get 117 | `Any` and `int` respectively. Worker is definitely an integer, but item can still 118 | be anything. Which is alright: `print` can print anything out so mypy is okay 119 | with the code. 120 | 121 | Hopefully that explains a lot more about mypy's workings. Feel free to make 122 | changes to the code, and use `reveal_type` to figure out what mypy thinks. 123 | -------------------------------------------------------------------------------- /courses/mypy-primer/mypy-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/mypy-primer/mypy-image.png -------------------------------------------------------------------------------- /courses/mypy-primer/the-typing-module/typing-args-kwargs.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Typing *args and **kwargs 3 | include_in_preview: false 4 | --- 5 | 6 | `*args` and `**kwargs` is a feature of python that lets you pass any number of 7 | arguments and keyword arguments to a function (that's what the name `args` and 8 | `kwargs` stands for, but these names are just convention, you can name the 9 | variables anything). 10 | 11 | All the extra arguments passed to `*args` get turned into a tuple, and kewyord 12 | arguments turn into a dictionay, with the keys being the string keywords: 13 | 14 | ```{.python .example .mypy-strict} 15 | def i_can_take_any_values(first_arg, *args, **kwargs): 16 | print('got extra args:', args) 17 | print('got kwargs:', kwargs) 18 | 19 | i_can_take_any_values(1, 16, 'Hello', x=False, answer=42) 20 | ``` 21 | 22 | Since the `*args` will always be of type `Tuple[X]`, and `**kwargs` will always 23 | be of type `Dict[str, X]`, we only need to provide one type `X` to be able to 24 | define their type. Here's a practical example, that takes keywords of marks in a 25 | subject, and creates a `Scorecard`: 26 | 27 | ```{.python .example .mypy-strict} 28 | class Scorecard: 29 | def __init__( 30 | self, 31 | english: int | None, 32 | maths: int | None, 33 | physics: int | None 34 | ) -> None: 35 | self.english = english 36 | self.maths = maths 37 | self.physics = physics 38 | 39 | def build_scorecard(**marks: int) -> Scorecard: 40 | card = Scorecard( 41 | english=marks.get('english'), 42 | maths=marks.get('maths'), 43 | physics=marks.get('physics'), 44 | ) 45 | return card 46 | 47 | marks = {'english': 55, 'physics': 84} 48 | scorecard = build_scorecard(**marks) 49 | print(scorecard.physics) 50 | print(scorecard.maths) 51 | ``` 52 | 53 | To verify, you can use `reveal_type`: 54 | 55 | ```{.python .example .mypy-strict} 56 | def build_scorecard(**marks: int) -> None: 57 | reveal_type(marks) 58 | ``` 59 | 60 | `marks` is indeed `dict[str, int]`. 61 | -------------------------------------------------------------------------------- /courses/mypy-primer/typing-module-deep-dive/the-namedtuple-class.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: The NamedTuple class 3 | include_in_preview: false 4 | --- 5 | 6 | `namedtuple`s are a lot like tuples, except every index of their fields has a 7 | name, and they have some syntactic sugar which allow you to access its 8 | properties like attributes on an object: 9 | 10 | ```{.python .example .mypy-strict} 11 | from collections import namedtuple 12 | 13 | Person = namedtuple('Person', ('name', 'age', 'bio')) 14 | ishan = Person('Ishan', 31, 'Writer') 15 | 16 | print(ishan) 17 | print(ishan[1]) 18 | print(ishan.bio) 19 | ``` 20 | 21 | Since the underlying data structure is a tuple, and there's no real way to 22 | provide any type information to namedtuples, by default this will have a type of 23 | `Tuple[Any, Any, Any]`. 24 | 25 | To combat this, Python has added a `NamedTuple` class which you can extend to 26 | have the typed equivalent of the same. Their syntax allows adding types: 27 | 28 | ```{.python .example .mypy-strict} 29 | from typing import NamedTuple 30 | 31 | class Person(NamedTuple): 32 | name: str 33 | age: int 34 | bio: str 35 | 36 | ishan = Person('Ishan', 31, 'Writer') 37 | 38 | reveal_type(ishan) 39 | reveal_type(ishan[1]) 40 | reveal_type(ishan.bio) 41 | 42 | name, age, _ = ishan 43 | reveal_type(age) 44 | ``` 45 | 46 | Underneath the syntax, it's still a tuple. But this allows mypy to know the 47 | types of each element and their names as well. 48 | -------------------------------------------------------------------------------- /courses/mypy-primer/typing-module-deep-dive/the-typeddict-class.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: The TypedDict class 3 | include_in_preview: false 4 | --- 5 | 6 | When getting data from an API for example, it's fairly common to have data in a 7 | dictionary, like so: 8 | 9 | ```python 10 | user = { 11 | 'name': 'Mike', 12 | 'age': 21, 13 | } 14 | ``` 15 | 16 | The thing with such data is that it's usually well structured with string keys, 17 | but the values are of various different types. Often you can define a schema for 18 | the data type, i.e. you know that the dictionary will have a string `"name"`, 19 | and an integer `"age"`. But with normal dictionaries, it doesn't work that way: 20 | 21 | ```{.python .example .mypy-strict} 22 | user = { 23 | 'name': 'Mike', 24 | 'age': 21, 25 | } 26 | reveal_type(user['name']) 27 | reveal_type(user['age']) 28 | ``` 29 | 30 | Just like the case with `['Mike', 21]`, mypy defaults to assuming you're just 31 | making a `dict[str, object]`. And usually, that would be the right assumption. 32 | But not in this specific case. 33 | 34 | Maybe you can try to define a schema by making a dictionary with the types? If 35 | you try to do that you'll get weird errors, about `Type[int]` and `Type[str]`: 36 | 37 | ```{.python .example .mypy-strict} 38 | user = { 39 | 'name': str, 40 | 'age': int 41 | } 42 | d['name'] = 'Mike' 43 | d['age'] = 31 44 | ``` 45 | 46 | Mypy knows about this usecase, and it has a feature that allows making such dict 47 | types. The solution is to use `TypedDict` to define a `User` type first, and to 48 | tell mypy that we want the `user` dictionary to adhere to that shape: 49 | 50 | ```{.python .example .mypy-strict} 51 | from typing import TypedDict 52 | 53 | User = TypedDict('User', { 54 | 'name': str, 55 | 'age': int 56 | }) 57 | 58 | user: User = { 59 | 'name': 'Mike', 60 | 'age': 21, 61 | } 62 | 63 | reveal_type(user['name']) 64 | reveal_type(user['age']) 65 | ``` 66 | 67 | Another option is to use the same syntax as `NamedTuple`. But unlike NamedTuple, 68 | you don't need to instantiate the `User` class, a regular dictionary also works. 69 | 70 | ```{.python .example .mypy-strict} 71 | from typing import TypedDict 72 | 73 | class User(TypedDict): 74 | name: str 75 | age: int 76 | 77 | user: User = { 78 | 'name': 'Mike', 79 | 'age': 21, 80 | } 81 | 82 | reveal_type(user['name']) 83 | reveal_type(user['age']) 84 | ``` 85 | 86 | You can even define deeply nested data in this way: 87 | 88 | ```{.python .example .mypy-strict} 89 | from typing import TypedDict 90 | 91 | class UserDetails(TypedDict): 92 | name: str 93 | age: int 94 | 95 | class User(TypedDict): 96 | userid: int 97 | username: str 98 | details: UserDetails 99 | 100 | def get_user() -> User: 101 | return { 102 | "username": "miketyson", 103 | "userid": 123456, 104 | "details": { 105 | "name": "Mike Tyson", 106 | "age": 21, 107 | }, 108 | } 109 | ``` 110 | 111 | We can use TypedDicts inside TypedDicts to make this work. 112 | -------------------------------------------------------------------------------- /courses/python-primer/classes/classes.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Introduction to Classes 3 | include_in_preview: false 4 | --- 5 | 6 | In this lesson we'll learn about classes and creating objects. 7 | 8 | Object-oriented programming is a programming technique that organizes the code as classes and objects. 9 | 10 | An object contains some data and some behavior, defined by the methods on that object. Let's look at an example. 11 | 12 | ```{.python .example} 13 | filename = "hello.py" 14 | extension = filename.split(".")[1] 15 | print(extension) 16 | ``` 17 | 18 | In the above example, the value of variable `filename` is a string, in other words, it is an object of built-in class `str`. 19 | 20 | The `split` is a method defined in the `str` class and all the objects of that type can call it. 21 | 22 | ## The `class` statement 23 | 24 | The class statement is used to define our own classes. 25 | 26 | ```{.python .example} 27 | class Point: 28 | def __init__(self, x, y): 29 | self.x = x 30 | self.y = y 31 | 32 | p = Point(3, 4) 33 | print(p.x, p.y) 34 | ``` 35 | 36 | Calling `Point(3, 4)` creates a new instance of Point. Behind the scences, it does the following steps: 37 | 38 | * creates an empty object of class `Point` 39 | * initializes it by calling the `__init__` method 40 | * returns the initialized object 41 | 42 | ## Attributes and Methods 43 | 44 | If you look at the object `p`, it has two attributes `x` and `y`. They are accessed as `p.x` and `p.y`. It also has a method `__init__`, which is used to create a new instances of the class. 45 | 46 | Let's add a new method `move` to the `Point` class. 47 | 48 | 49 | ```{.python .example} 50 | class Point: 51 | def __init__(self, x, y): 52 | self.x = x 53 | self.y = y 54 | 55 | def move(self, dx, dy): 56 | """Moves the point by dx in the x-direction and 57 | dy in the y-direction. 58 | """ 59 | self.x += dx 60 | self.y += dy 61 | 62 | p = Point(3, 4) 63 | print(p.x, p.y) 64 | 65 | p.move(10, 20) # call the move method on Point p 66 | print(p.x, p.y) 67 | ``` 68 | 69 | When we call a method on an object, the object is passed as the first argument. That is why we see the first argument in methods as `self`. It could called with any name, but it is called `self` by convention. 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /courses/python-primer/course.yml: -------------------------------------------------------------------------------- 1 | name: python-primer 2 | suffix: py 3 | is_published: true 4 | upcoming: false 5 | tags: 6 | - python 7 | video_link: 8 | title: Python Primer 9 | instructor: anand 10 | image: python-logo.png 11 | short_introduction: Master the essentials of the Python programming language 12 | description: | 13 | Python Primer is a hands-on course for mastering the essentials of the Python programming language and using it to solve real-world problems. 14 | 15 | With many hands-on examples, this course covers many practical applications, demonstrating how to use Python programming language to solve day to day problems very effectively. 16 | 17 | Apart from introducing the elegant constructs of Python programming language, this course also teaches how to organize your code and how to write idomatic Python code that is easy to read and maintain. 18 | 19 | This course is an outcome of many trainings done by Anand at [Pipal Academy](https://pipal.in/) over a decade to his clients. 20 | 21 | Target Audience: 22 | 23 | This course is targeted at programmers who are new to Python. It is expected that the student knows about basic programming constructs like functions, loops etc.. Prior exposure to Python is not required. 24 | 25 | chapters: 26 | - name: getting-started 27 | title: Getting Started 28 | description: Introduction to the Python programming language 29 | lessons: 30 | - getting-started/hello-python.md 31 | - getting-started/datatypes.md 32 | - getting-started/control-flow.md 33 | 34 | - name: program-structure 35 | title: Program Structure 36 | description: Learn how to organize your code as functions, modules and scripts. 37 | lessons: 38 | - program-structure/functions.md 39 | - program-structure/modules.md 40 | 41 | - name: working-with-data 42 | title: Working with Data 43 | description: Introduction to lists, for loop and discussion on iteration patterns. 44 | lessons: 45 | - working-with-data/lists.md 46 | - working-with-data/dictionaries.md 47 | - working-with-data/working-with-files.md 48 | 49 | - name: classes 50 | title: Classes & Objects 51 | description: Learn how to model your code using classes. 52 | lessons: 53 | - classes/classes.md 54 | - classes/designing-with-classes.md 55 | - classes/exceptions.md 56 | - name: next-steps 57 | title: Next Steps 58 | description: Some tips to continue this learning journey 59 | lessons: 60 | - next-steps/next-steps.md 61 | -------------------------------------------------------------------------------- /courses/python-primer/getting-started/hello-python.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Hello Python 3 | include_in_preview: true 4 | --- 5 | 6 | ## Running the Python Interpreter 7 | 8 | Python comes with an interactive interpreter. When you type `python3` in your shell or command prompt, the python interpreter becomes active with a `>>>` prompt and waits for your commands. 9 | 10 | ``` 11 | $ python3 12 | Python 3.9.5 (default, May 19 2021, 11:32:47) 13 | [GCC 10.2.0] on linux 14 | Type "help", "copyright", "credits" or "license" for more information. 15 | >>> 16 | ``` 17 | 18 | Now you can type any valid python expression at the prompt. python reads the typed expression, evaluates it and prints the result. 19 | 20 | ``` 21 | >>> 1 + 2 22 | 3 23 | ``` 24 | 25 | Congratulations. You've written your first python program! 26 | 27 | The Python interpreter, or the Python REPL (Read-Eval-Print-Loop) is a quick way to use Python for doing simple computations. 28 | 29 | ## Running the Python Scripts 30 | 31 | Often, we write programs and run them mutliple times. Let's see how to do that with Python. 32 | 33 | Open your text editor and type the following text and save it as `hello.py`. 34 | 35 | ``` 36 | print("hello, world!") 37 | ``` 38 | 39 | And run the program from your terminal or command-prompt by typing `python hello.py`. 40 | 41 | ``` 42 | $ python hello.py 43 | hello, world! 44 | ``` 45 | 46 | The program calls a `print`, a function to display a message on screen and whatever we have between the double quotes is the input to the `print` function. 47 | 48 | Try changing the program to print your name instead of `hello, world!`. 49 | 50 | ## The Course Environment 51 | 52 | In this course we'll use a live coding environment where you can try the examples online. 53 | 54 | Run the following example, by clicking on the `Run` button. 55 | 56 | ```{.python .example} 57 | print("Hello, world!") 58 | ``` 59 | 60 | ## Variables 61 | 62 | 63 | It is very easy to use variables in Python. 64 | 65 | ```{.python .example} 66 | x = 10 67 | y = 20 68 | z = x + y 69 | print(z) 70 | ``` 71 | 72 | In the above example `x`, `y` and `z` are variables. 73 | 74 | Unlike other static typed languages like C or Java, variables in Python don't have any type associated with them. 75 | 76 | ```{.python .example} 77 | x = 10 78 | print(x) 79 | 80 | x = "hello" 81 | print(x) 82 | ``` 83 | 84 | As you can see, the value of x was intially an integer and then x was reassigned to a string value. This is prefectly valid in Python. 85 | 86 | Often, beginner programmers get confused about strings and variables. Strings are the text values that we enclose in quotes and variables are names that refer to some values. 87 | 88 | The following program is supposed to print `Python`, but it is printing text "name". Can you identify what is the mistake in this program? 89 | 90 | ```{.python .example} 91 | name = "Python" 92 | print("name") 93 | ``` 94 | 95 | ## Comments 96 | 97 | -------------------------------------------------------------------------------- /courses/python-primer/getting-started/reading-errors.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Reading Errors 3 | include_in_preview: false 4 | --- 5 | 6 | . 7 | -------------------------------------------------------------------------------- /courses/python-primer/getting-started/variables.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Variables 3 | include_in_preview: false 4 | --- 5 | 6 | It is very easy to use variables in Python. 7 | 8 | ``` 9 | x = 10 10 | y = 20 11 | z = x + y 12 | print(z) 13 | ``` 14 | 15 | In the above example `x`, `y` and `z` are variables. 16 | 17 | Unlike other static typed languages like C or Java, variables in Python don't have any type associated with them. 18 | 19 | ``` 20 | x = 10 21 | print(x) 22 | 23 | x = "hello" 24 | print(x) 25 | ``` 26 | 27 | As you can see, the value of x was intially an integer and then x was reassigned to a string value. This is prefectly valid in Python. 28 | 29 | Often, beginner programmers get confused about strings and variables. Strings are the text values that we enclose in quotes and variables are names that refer to some values. 30 | 31 | The following program is supposed to print `Python`, but it is printing text "name". Can you identify what is the mistake in this program? 32 | 33 | ``` 34 | name = "Python" 35 | print("name") 36 | ``` 37 | 38 | -------------------------------------------------------------------------------- /courses/python-primer/next-steps/next-steps.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Next Steps 3 | include_in_preview: false 4 | --- 5 | 6 | Congratulations! You've almost done with the Python Primer course. You've learnt enough Python to start doing interesting projects. Here are some tips to build great software. 7 | 8 | ## Practice, Practice, Practice 9 | 10 | There are no shortcuts to develop expertise in any field. It takes deliberate practice and lot of time to master any skill, including programming. 11 | 12 | The world is full of interesting challenges. Think of a problem that excites you and try to sovle it in your way. It is okay to reinvent the wheel. 13 | 14 | Not convinced? Read [Teach Yourself Programming in Ten Years][1] by Peter Norvig. 15 | 16 | [1]: https://www.norvig.com/21-days.html 17 | 18 | ## Programs are written for the people 19 | 20 | Young programmers often think, the purpose of writing a program is just to make the computer execute something. While it is important to make something a computer can execute, there is lot more to the craft of programming. 21 | 22 | Often a program lives for long time after it is written. It goes though many changes, often by different people. It is really hard to understand a piece of code unless it is written well. 23 | 24 | There are many simple techniques like picking right variable names, keeping functions small and independent, supressing the details into different functions etc. to make code a lot readable. 25 | 26 | When you are writing a program next time, think if a new person can read the code and understand what is going on? If not, make efforts to make your program easy to read, easy to understand and easy to make changes. 27 | 28 | Need more tips? Watch [Writing Beautiful Code][2]. 29 | 30 | [2]: https://www.youtube.com/watch?v=QIRyr6qvGrY 31 | 32 | ## Embrace the community 33 | 34 | The Python community is warm and welcoming. There are many Python user groups in India and other countries. 35 | 36 | There a lot to learn from other people. Participate in user group meetings and conferences. Connect with fellow Pythonistas. Learn from the interesting projects others are working on. Learn from their mistakes. Give a talk at user group meeting or a conference. Help other people who are just starting up. 37 | 38 | Conduct a Python workshop in your college or your organization.You are welcome to use the material from this course. 39 | 40 | Checkout the wonderful Python communities in India. 41 | 42 | * [Python India](https://in.pycon.org) 43 | * [BangPypers](https://bangalore.pythonindia.org/) 44 | * [ChennaiPy](http://chennaipy.org/) 45 | * [HydPy](https://www.meetup.com/HydPyGroup/) 46 | * [PyDelhi](https://pydelhi.org/) 47 | * [Python Pune](https://pythonpune.in/) 48 | 49 | ## Thank You! 50 | 51 | Thank you so much reading all the way till the end. Hope you found this course helpful and wish you all the best! 52 | 53 | -------------------------------------------------------------------------------- /courses/python-primer/program-structure/modules.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Modules 3 | include_in_preview: false 4 | --- 5 | 6 | Python comes with many built-in modules. 7 | 8 | A module is imported using the `import` statement. 9 | 10 | The following example imports the time module and prints the current time using the `asctime` function defined in that module. 11 | 12 | ```{.python .example} 13 | import time 14 | print(time.asctime()) 15 | ``` 16 | 17 | The `os` module provides functions related to files and processes. 18 | 19 | The following example prints the current working directory. 20 | 21 | ```{.python .example} 22 | import os 23 | print(os.getcwd()) 24 | ``` 25 | 26 | The `listdir` funtion lists all the files in a given directory. 27 | 28 | ```{.python .example} 29 | import os 30 | 31 | print(os.listdir(".")) 32 | ``` 33 | 34 | Python comes with many built-in modules. We'll explore lot more modules in the upcoming lessons. 35 | 36 | ## Reading Command-line arguments 37 | 38 | The `sys` module keeps trak of the command-line arguments passed to a program. 39 | 40 | 41 | 42 | ```{#args1 .python .example .show-args} 43 | import sys 44 | print(sys.argv) 45 | ``` 46 | 47 | The above example prints all the command-line arguments passed to the program. As you can see the `sys.argv` will always be a list with the program name as first argument, followed by all the arguments passed to it. 48 | 49 | Please note that the elements of `sys.argv` will always be strings. 50 | 51 | Try changing the arguments to something else. 52 | 53 | ### Example: echo 54 | 55 | Let's try to implement a simple version of the `echo` command of unix. 56 | 57 | The echo command prints the command-line arguments passed to it. 58 | 59 | ``` 60 | $ echo hello 61 | hello 62 | 63 | $ echo hello world 64 | hello world 65 | ``` 66 | 67 | We'll implement a simple version that just prints the first argument. 68 | 69 | 72 | 73 | ```{#args2 .python .example .show-args .multi-file} 74 | === echo.py 75 | import sys 76 | print(sys.argv[1]) 77 | ``` 78 | 79 | Command-line arguments are most common way to take user inputs. We are going to use this a lot more in the examples of upcoming lessons. 80 | 81 | **Problem:** Write a program `square.py` that takes a number as command-line argument and prints its square. 82 | 83 | ``` 84 | $ python square.py 2 85 | 4 86 | $ python square.py 5 87 | 25 88 | ``` 89 | -------------------------------------------------------------------------------- /courses/python-primer/python-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/python-primer/python-logo.png -------------------------------------------------------------------------------- /courses/rust-for-beginners/control-flow/conditionals.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Learning about `if`, `else` and ways to construct rust programs with them 3 | --- 4 | 5 | You could write programs that use `if`, `if else`, `else if` and nested `if` with rust. In this lesson, we will learn where you should be using them. 6 | -------------------------------------------------------------------------------- /courses/rust-for-beginners/control-flow/functions-closures.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Understanding how functions and closures work in rust-lang 3 | --- 4 | 5 | Rust programs can be written with functions and closures that simplify the code and enable composing programs that are `functional` in nature, in this chapter we will learn more about how. -------------------------------------------------------------------------------- /courses/rust-for-beginners/control-flow/iteration.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Discussing `for`, `while` and more about loops in rust 3 | --- 4 | 5 | Rust code can iterate with the help of `for`, `while` and `loop`, in this lesson we will also learn about `break` and `continue`. 6 | -------------------------------------------------------------------------------- /courses/rust-for-beginners/control-flow/macros.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Utilising macros to write less code and do more 3 | --- 4 | 5 | Rust gives you macros which enables you to replace repetitive, boilerplate code with simpler and much more elegant commands, let's learn a bit about them. 6 | -------------------------------------------------------------------------------- /courses/rust-for-beginners/control-flow/pattern-matching.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Write concise code with match and let patterns 3 | --- 4 | 5 | In this less we will learn about how rust enables you with quick pattern matching alternatives to convoluted `if else` control flow, so that you can write concise and semantic code. 6 | -------------------------------------------------------------------------------- /courses/rust-for-beginners/course.yml: -------------------------------------------------------------------------------- 1 | name: rust-for-beginners 2 | title: Rust for Beginners 3 | instructor: devdutt 4 | is_published: 0 5 | upcoming: true 6 | tags: 7 | - rust 8 | video_link: 9 | suffix: rs 10 | short_introduction: A gentle introduction to the Rust programming language 11 | description: | 12 | Rust has been voted the most loved programming language by participants in the 13 | Stack overflow Developer Survey for the last 5 years in a row. This has a lot 14 | to do with how the language helps developers write quick and clean programs that 15 | don't sacrifice much on performance, powered by a state of the art compiler and 16 | set of tools that help you make awesome software. 17 | 18 | In this course, we have curated learning resources and practice problems that will 19 | help you get started quickly and understand how to write, compile and optimise 20 | programs in rust-lang. 21 | 22 | chapters: 23 | - name: introduction 24 | title: fn main() -> IntroducingRust 25 | description: Writing and running your first Rust program. 26 | lessons: 27 | - introduction/welcome.md 28 | - introduction/rustup.md 29 | - introduction/first-rust-program.md 30 | - introduction/why-rust.md 31 | - name: control-flow 32 | title: Doing some control flow 33 | description: Learn conditional, iterative, pattern matching and functional programs 34 | lessons: 35 | - control-flow/conditionals.md 36 | - control-flow/iteration.md 37 | - control-flow/pattern-matching.md 38 | - control-flow/functions-closures.md 39 | - control-flow/macros.md 40 | - name: data-flow 41 | title: Data types, traits, borrowing and ownership 42 | description: Getting to know how rust handles data 43 | lessons: 44 | - data-flow/types.md 45 | - data-flow/structs-and-enums.md 46 | - data-flow/traits-and-generics.md 47 | - data-flow/borrowing-ownership.md 48 | - name: package-management 49 | title: Package Management 50 | description: Package management in rust-lang 51 | lessons: 52 | - package-management/dependencies.md 53 | - package-management/crates-and-docs.md 54 | - package-management/cargo-manifest.md 55 | - name: project 56 | title: Capstone Project 57 | description: Writing our first crate, a CLI game called twozero48, based on the popular game 2048. 58 | lessons: 59 | - project/intro.md 60 | - project/logic.md 61 | - project/inputs.md 62 | - project/riir.md 63 | - project/publish.md 64 | -------------------------------------------------------------------------------- /courses/rust-for-beginners/data-flow/borrowing-ownership.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Handling memory with ownership, borrowing and lifetimes 3 | --- 4 | 5 | The concepts of ownership, borrowing and lifetimes helps compilers elegantly translate your code into programs that handle runtime memory with care, not requiring any form of manual freeing or runtime garbage collectors to handle it for you. We will learn about how you can use these concepts to write memory safe software. 6 | 7 | - [Rust Ownership, Borrowing, and Lifetimes](https://www.integralist.co.uk/posts/rust-ownership/) 8 | -------------------------------------------------------------------------------- /courses/rust-for-beginners/data-flow/structs-and-enums.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Creating data structures in rust 3 | --- 4 | 5 | While we are familiar with how primitive types can be used to write programs that just work, at times it is much easier to manage related data in an encapsulated manner. Influenced by the concepts of Object Oriented Programming, rust enables you to write better code with structs and enums that also allow you to embed behaviour in the form of methods implemented on these structs. 6 | -------------------------------------------------------------------------------- /courses/rust-for-beginners/data-flow/traits-and-generics.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Rust Traits and Generics 3 | --- 4 | 5 | In this lesson we will be introduced to the concept of traits in rust, which enables you to write data structures that might be composed differently, but provide similar interfaces, enabling the implementation of generic types, which in turn allows for composing libraries that are easy to maintain and don't require complex rewrites to handle different forms of data that would otherwise have similar methods, i.e. behaviour. 6 | -------------------------------------------------------------------------------- /courses/rust-for-beginners/data-flow/types.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: An introduction to the concept of types in rust 3 | --- 4 | 5 | Rust is a statically typed language, in this lesson we will learn about how it uses the concept of types to help you write safe and easy to compose programs. 6 | -------------------------------------------------------------------------------- /courses/rust-for-beginners/introduction/first-rust-program.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Our First Rust Program 3 | --- 4 | 5 | Writing and compiling our first rust program. -------------------------------------------------------------------------------- /courses/rust-for-beginners/introduction/rustup.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: First spin, Playground and Rustup 3 | --- 4 | 5 | Test driving rust-lang with Playground and installing the rust compiler toolchain -rustc, cargo and more using Rustup. 6 | 7 | We have learnt a bit about how rust-lang came to be and it's community, in this lesson, let's explore the language and take it for a spin. Log onto https://play.rust-lang.org to checkout the Playground, a web-app that emulates a rust compiler and lets you compile simple rust programs, enough for a beginner to learn the syntax of the language. 8 | 9 | As you can see, we have a program that when we press "Run" will print "Hello, World!" to the adjoined output panel. Let's focus on the code for a minute. 10 | ```rust 11 | fn main() { 12 | println!("Hello, world!"); 13 | } 14 | ``` 15 | If you are familiar with a langue such as c, cpp or python, this might be something you could easily figure out. `fn` is the keyword to define functions with, similar to `def` in python or `func` in golang, `main` is the function's name, defined such that it takes no arguments `()`, and the body of the function is just a statement that looks like a function to print the given string "Hello, World!" to screen. Well, that statement is infact a macro and that's where we have to start unpacking a lot, pun intended :smirk: 16 | 17 | Now that I have thoroughly bored you with a write up, let's understand how we can tweak the playground to our liking from this [quick YouTube tutorial](https://www.youtube.com/watch?v=-lYeJeQ11OI&t=36s). 18 | 19 | ## Installing rust-lang with `rustup` 20 | 21 | Writing rust in the browser is cool and all, but a whole lot of the libraries and facilities within the langauge do not run properly in such an environment, which is why we need to install the compiler and other tools that come with it on a system of our own. This can be easily done by logging onto https://rustup.rs and following the instructions there, else you could also follow this [handy tutorial](https://www.youtube.com/watch?v=2hY7Uib2UDM). If you are using Windows or another non-linux OS, you may have to set PATH or do some other tweaking and fixing, please look-up a tutorial specific to your OS of choice in that case. 22 | 23 | ## Compiling programs locally with `rustc` 24 | 25 | If you have followed either of the above suggested steps, you will have installed the rust compiler called `rustc`, the rust package management utility `cargo` and a whole load of other tools that'll soon become very useful. To get started, let's print "Hello, World!" to screen by doing the following: 26 | 1. Create and open a file "hello.rs" and copy-paste the program from the playground example, save the file. 27 | 2. From within the same directory as the file, run the rust compiler with the file as input: 28 | ```bash 29 | rustc hello.rs 30 | ``` 31 | 3. Depending on the OS, you will endup having generated an executable, on linux it will be named "hello". Run it, this step might be different on other OSes: 32 | ```bash 33 | ./hello 34 | ``` 35 | 36 | ### Building rust crates with `cargo` 37 | 38 | We have experimented with writing, compiling and running rust-lang with help of the rust-compiler. Now there's a quicker and much more cleaner way to deal with bigger rust programs which may require more than one source file and even some dependencies outside of the standard library. That would be made possible by creating a rust crate, the term rustaceans use to refer to the source code that can be built into libraries and binaries with `cargo`. A walkthrough of the same is presented in the [video for installing rustup at 1:40](https://www.youtube.com/watch?v=2hY7Uib2UDM&t=100s). 39 | 40 | The differences with this approach are: 41 | - Writing crates can be a great way to manage external dependencies 42 | - Code is placed in `src/` and 43 | -------------------------------------------------------------------------------- /courses/rust-for-beginners/introduction/welcome.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Welcome to Rust 3 | --- 4 | 5 | An introduction to the language and a brief history lesson. 6 | 7 | Rust, aka rust-lang is a programming language that was thought out and first implemented at [Mozilla](https://research.mozilla.org/rust/), as an alternative to C/C++ for use in developing the Firefox browser and many other apps. The main aim of the language has been to make system programming safer and a tad bit easier, evolving into a state of the art tool that has now been adopted for use at some of the largest software engineering companies, including AWS, Google and Microsoft. Rust has also set a streak of 6 years being the [most loved programming language](https://insights.stackoverflow.com/survey/2021#section-most-loved-dreaded-and-wanted-programming-scripting-and-markup-languages) among developers surveyed by Stack Overflow and has gained quite a lot of mass appeal and a large pool of contributors as a result. 8 | 9 | Programmers who advocate for rust-lang call themselves "Rustaceans", a play on the words "Crustaceans" used to refer to hard-shelled amphibians such as crabs or lobsters and thus, the community adopted [Ferris the crab](https://rustacean.net/) as it's mascot. The community is pretty large and diverse, with a presence on various platforms such as [twitter](https://twitter.com/search?q=%23rustlang), [reddit](https://reddit.com/r/rust) and [more](https://www.rust-lang.org/community). 10 | 11 | Over the past 3 years, rust-lang has come a long way. From being dismissed as mere hogwash and "It is just a fad" to actually seeing immense interest among developers and engineering managers alike, to finally being in a position where critical computing infrastructure is being built and rewritten to make the best use of the growing capabilities of the language and the libraries written in it. 12 | 13 | In this course, I have curated content from across the interwebs to give you a primer on the language and to help you upskill yourself with knowledge of how and where it could become a great way to solve problems, so let us get started. 14 | -------------------------------------------------------------------------------- /courses/rust-for-beginners/introduction/why-rust.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Why Rust? 3 | --- 4 | 5 | Why Rust? How is Rust different from other programming languages? -------------------------------------------------------------------------------- /courses/rust-for-beginners/package-management/cargo-manifest.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Writing our own Cargo.toml 3 | --- 4 | 5 | When publishing your crate, it is important to know what the world will first notice about it. Here is a detailed walk-through for writing the perfect manifest. -------------------------------------------------------------------------------- /courses/rust-for-beginners/package-management/crates-and-docs.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Getting to know crates.io and docs.rs 3 | --- 4 | 5 | The rust crate ecosystem consists of two important places where you can get yourself up-to-date about the latest crates and their function API documentation. [crates.io](https://crates.io) is a directory of all published crates that you can download and use with cargo. 6 | 7 | Every crate that has been published has it's own landing page and a few informational graphs showing how popular the crate is or has been, on the same page you get to see what licenses it supports, when it was last updated, what version is current and links to where you can find the documentation or code for the crate. 8 | 9 | In this lesson, we will also learn about how you can write your own crate function/API documentation and publish it for the world to read. -------------------------------------------------------------------------------- /courses/rust-for-beginners/package-management/dependencies.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Handling dependencies in rust-lang 3 | --- 4 | 5 | Rust has seen growing adoption, leading to more libraries written in the language, which ofcourse lead to the creation of an entire ecosystem of packages, aka crates, being released on a dedicated platform called [crates.io](https://crates.io). While developing a crate of your own, you may import/depend on another by including it in `Cargo.toml`. This chapter will clarify a few informative facts about including dependencies in your project. -------------------------------------------------------------------------------- /courses/rust-for-beginners/project/inputs.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: How do we handle inputs? 3 | --- 4 | 5 | In this lesson, we will talk about what inputs to receive and how we can use the [termion](https://crates.io/termion) crate to receive it from the terminal. -------------------------------------------------------------------------------- /courses/rust-for-beginners/project/intro.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: What are we building? 3 | --- 4 | 5 | We will be building the game [2048](https://play2048.co) from scratch. First, let's install the game and try it out: 6 | ```sh 7 | cargo install twozero48 8 | twozero48 9 | ``` -------------------------------------------------------------------------------- /courses/rust-for-beginners/project/logic.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: How do we play 2048? 3 | --- 4 | 5 | The game of 2048 involves rules that make it what it is, in this lesson we will discuss the logic and how we plan to implement it, in a language agnostic manner. -------------------------------------------------------------------------------- /courses/rust-for-beginners/project/publish.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Publshing your first crate 3 | --- 4 | 5 | Here's a challenge, make your own crate and publish it. It could be tool to scratch your own itch, a game, a template meme creator, anything works! -------------------------------------------------------------------------------- /courses/rust-for-beginners/project/riir.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Let's Re-write it in Rust! 3 | --- 4 | 5 | We have written a working implementation of the 2048 game, but we can still make several improvements and write parts of it in elegant/idiomatic rust. -------------------------------------------------------------------------------- /courses/self-hosting-101/_images/create_droplet_form.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/self-hosting-101/_images/create_droplet_form.png -------------------------------------------------------------------------------- /courses/self-hosting-101/_images/create_droplet_toggle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/self-hosting-101/_images/create_droplet_toggle.png -------------------------------------------------------------------------------- /courses/self-hosting-101/_images/create_user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/self-hosting-101/_images/create_user.png -------------------------------------------------------------------------------- /courses/self-hosting-101/_images/do_console.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/self-hosting-101/_images/do_console.png -------------------------------------------------------------------------------- /courses/self-hosting-101/_images/do_project.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/self-hosting-101/_images/do_project.png -------------------------------------------------------------------------------- /courses/self-hosting-101/_images/nano_bashrc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/self-hosting-101/_images/nano_bashrc.png -------------------------------------------------------------------------------- /courses/self-hosting-101/_images/nano_input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/self-hosting-101/_images/nano_input.png -------------------------------------------------------------------------------- /courses/self-hosting-101/_images/nano_non_root.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/self-hosting-101/_images/nano_non_root.png -------------------------------------------------------------------------------- /courses/self-hosting-101/_images/nginx-blue-site.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/self-hosting-101/_images/nginx-blue-site.png -------------------------------------------------------------------------------- /courses/self-hosting-101/_images/nginx-index-edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/self-hosting-101/_images/nginx-index-edit.png -------------------------------------------------------------------------------- /courses/self-hosting-101/_images/nginx-monschool-index.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/self-hosting-101/_images/nginx-monschool-index.png -------------------------------------------------------------------------------- /courses/self-hosting-101/_images/nginx-request-headers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/self-hosting-101/_images/nginx-request-headers.png -------------------------------------------------------------------------------- /courses/self-hosting-101/_images/nginx-route.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/self-hosting-101/_images/nginx-route.png -------------------------------------------------------------------------------- /courses/self-hosting-101/_images/nginx_welcome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/self-hosting-101/_images/nginx_welcome.png -------------------------------------------------------------------------------- /courses/self-hosting-101/_images/tmux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/self-hosting-101/_images/tmux.png -------------------------------------------------------------------------------- /courses/self-hosting-101/course.yml: -------------------------------------------------------------------------------- 1 | name: self-hosting-101 2 | title: Self Hosting 101 3 | 4 | # XXX-Anand: to fix the build 5 | instructor: mrkaran 6 | 7 | instructors: 8 | - mrkaran 9 | - anand 10 | is_published: true 11 | upcoming: true 12 | tags: 13 | - Self Hosting 14 | image: selfhosting-logo.png 15 | video_link: 16 | suffix: sh 17 | short_introduction: Learn how to self host and manage applications on servers. 18 | description: | 19 | Have you ever wanted to host your website or your favorite app on your own server, 20 | but not sure how to get started? 21 | 22 | Welcome to _Self Hosting 101_, the beginners guide to self hosting. 23 | 24 | This course starts with fundamentals of setting up a new server, installing system packges and goes all the way to deploying static websites and deploying database backed web applications. It will also conver how to troubleshoot when things goes wrong. 25 | 26 | With step by step instructions and tasks, this hands-on course introduces you the complex world of self hosting in a very simple way. 27 | 28 | chapters: 29 | - name: week0 30 | title: "Week 0: Getting Started" 31 | description: Some reading material will be shared to ignite interest in Self Hosting. 32 | lessons: 33 | - week0/why-self-host.md 34 | - week0/what-things-can-you-self-host.md 35 | - week0/course-outline.md 36 | - name: week1 37 | title: "Week 1: Setup a VPS in the Cloud" 38 | description: Setup and configure a VPS. 39 | lessons: 40 | - week1/overview.md 41 | - week1/creating-droplet.md 42 | - week1/creating-users.md 43 | - week1/installing-packages.md 44 | - week1/working-with-files-directories.md 45 | - week1/setting-up-ssh.md 46 | - week1/using-tmux.md 47 | - name: week2 48 | title: "Week 2: Deploy a Static Website" 49 | description: Deploy a static website with HTML, CSS, JS 50 | lessons: 51 | - week2/overview.md 52 | - week2/installing-nginx.md 53 | - week2/customising-index.md 54 | - week2/creating-a-site.md 55 | - week2/setup-using-git.md 56 | - name: week3 57 | title: "Week 3: Deploy a Python application" 58 | description: Deploy a Python application 59 | lessons: [] 60 | - name: week4 61 | title: "Week 4: System Services" 62 | description: Understanding and setting up system services 63 | lessons: [] 64 | - name: week5 65 | title: "Week 5: Troubleshooting" 66 | description: Logs, Debugging and Fixing 67 | lessons: [] 68 | - name: week6 69 | title: "Week 6: Recap and Next Steps" 70 | description: Recap + Further Reads 71 | lessons: [] 72 | -------------------------------------------------------------------------------- /courses/self-hosting-101/selfhosting-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fossunited/monschool-website/09482988bc9b2cc580fdb65708f8988eafb70daf/courses/self-hosting-101/selfhosting-logo.png -------------------------------------------------------------------------------- /courses/self-hosting-101/week0/course-outline.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Course Outline 3 | include_in_preview: false 4 | --- 5 | 6 | So now that you have a basic idea of what self hosting means and the broad list of things that you can self host, it's a good time to go through the course outline. The course as mentions in it's title is _101 Level_ (Basic Level) and we'll gradually pace the course from learning basics of a Linux system, to hosting a webserver, deploying a Python based full stack application and finally learning a bit about debugging and monitoring these systems. 7 | 8 | ## Outline 9 | 10 | ## Course Outline 11 | 12 | # Mon School Self Hosting 101 13 | 14 | ## Course Outcomes 15 | 16 | At the end of this course, you should be able to: 17 | 18 | - Setup a personal server using major cloud providers. 19 | - Be confident in running off the shelves apps like NGINX/Redis/PostgreSQL. 20 | - Learn how to deploy and run Python applications. 21 | - Managing `Day 2` tasks like debugging using metrics and logs. 22 | 23 | ## Week 1 24 | 25 | **Objective**: Setup and configure a VPS. 26 | 27 | - Provision a droplet 28 | - Configure the droplet with users, SSH keys 29 | - Learn about package management 30 | - Learn about Files and Directories 31 | - Basics of `tmux` 32 | 33 | ## Week 2 34 | 35 | **Objective**: Deploy a static website with NGINX 36 | 37 | - Install a webserver `nginx`. 38 | - Configure NGINX to serve a hello world website. 39 | - Configure NGINX to deploy your personal blog. 40 | 41 | ## Week 3 42 | 43 | **Objective**: Deploy a Python application 44 | 45 | - Setup a database using `PostgreSQL` 46 | - Setup and configure the Python application. 47 | - Configure `gunicorn`/`uwsgi` to make it accessible via a webserver. 48 | - Configure NGINX to setup a reverse proxy 49 | 50 | ## Week 4 51 | 52 | **Objective**: Setting up system services 53 | 54 | - Learn about `systemd`, `supervisorctl` to setup background services. 55 | - Learn about `cron` to setup periodic jobs. 56 | 57 | ## Week 5 58 | 59 | **Objective**: Logs, Debugging and Fixing 60 | 61 | - Find critical information using system logs. 62 | - Basic Linux utilities to find about disk usage, resource usage, network I/O. 63 | 64 | ## Week 6 65 | 66 | **Objective**: Recap + Further Reads 67 | 68 | - Reflect upon the course so far/things learnt etc 69 | - Automate certain tasks 70 | 71 | **Optional**: Based on the interest in the course we can add a week on *Hosting apps using Docker/Containers* 72 | -------------------------------------------------------------------------------- /courses/self-hosting-101/week0/what-things-can-you-self-host.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: What Things Can You Self Host 3 | include_in_preview: false 4 | --- 5 | 6 | There's a wide variety of things that you can self-host, but here are some practical use case scenarios: 7 | 8 | ### Personal Website 9 | 10 | This arguably is one of the simplest to self-host if you are running a static website. You can deploy a Web Server (we'll learn more about that in [Week 2](./../week2/_overview.md) and serve static HTML/CSS files. There are many static site generators available as well (like Hugo, Jekyll etc) which generate static assets (HTML/CSS/JS) that can be served in a similar way. 11 | 12 | ### Personal Projects 13 | 14 | If you're a developer, you'll find the need to showcase your project to the world. There are some PAAS (_Platform as a Service_) providers like Heroku which help you deploy your projects but more often it's a black-box solution and sometimes limited as well. This course focusses on each aspect of hosting your projects so you get a deeper understanding and are able to deploy your projects without the need of any managed solutions. 15 | 16 | ### Version Control Software 17 | 18 | GitHub is a popular choice of tool for a VCS. But you can always set up a secondary backup tool for your `git` repos by self-hosting Gitlab, Gitea and the likes. 19 | 20 | ### Wikis 21 | 22 | If you want to write your wiki, there are many tools available - Bookstack, DokuWiki to name a few. You get full control over the data you enter in the wiki which is a nice benefit over using a SAAS tool. 23 | 24 | --- 25 | 26 | The list is long and there are just too many FOSS things you can self-host. You can explore [Awesome Self Hosted](https://github.com/awesome-selfhosted/awesome-selfhosted) list to indulge yourself more and prepare a small list of software that you want to deploy by the end of this course! :) 27 | -------------------------------------------------------------------------------- /courses/self-hosting-101/week0/why-self-host.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: What is Self Hosting? 3 | include_in_preview: false 4 | --- 5 | 6 | Self Hosting is a concept in which you are encouraged to _host_ your applications. You take full control of the data, the application lifecycle (installing/upgrading etc) and in this process, you learn to be _less_ dependent on paid SAAS (Software as a Service) providers. 7 | 8 | There are many different motivations to self-host software but generally speaking, they fall under 3 basic principles: 9 | 10 | - Freedom: The ability to own your data and not rely on a 3rd party provider allows you to be in better control of that software. You don't have to worry about a company going down under and you losing access to the said service. 11 | - Privacy: There are some software like a Chat group, a Notetaking tool, a Version control software access etc where you care more about the privacy/ownership of the data. You don't want to give away access to precious data to some random companies, so you want to self-host. 12 | - Learning: If you are motivated to learn about servers, networking, Linux systems and just like to tinker with stuff in general, Self Hosting is an excellent way to learn a lot of concepts while doing hands-on projects. 13 | 14 | Now that you know what is self-hosting and why people self-host, let's talk about a few things you can self-host in the [next lesson](./what-things-can-self-host.md). 15 | -------------------------------------------------------------------------------- /courses/self-hosting-101/week1/installing-packages.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Installing Software Packages 3 | include_in_preview: false 4 | --- 5 | 6 | In this lesson we'll learn about the package management system of Ubuntu. We'll learn how to keep packages updated and install new packages from the package manager. 7 | 8 | ### Refresher 9 | 10 | We'll use some concepts here that was learned in the previous lesson. You can take a quick look at them to refresh them: 11 | 12 | - `ssh user@ip` command to login from [Creating droplet lesson](./creating-droplet.md) 13 | 14 | --- 15 | 16 | In Linux, different distributions have different ways of managing software packages. These packages consist of Audio/Video drivers, Linux Kernel, System-level packages, and user-level software like media/games/editors/browsers etc. To manage these packages, we use something called _Package Managers_. They are small utilities that help in downloading software from _Repositories_ and regularly update them. 17 | 18 | In this course, we are using a Ubuntu-based droplet, which comes with an Advanced Packaging Tool (APT) package manager. With `apt` you can add/remove packages or update existing ones and even upgrade across Ubuntu versions. 19 | 20 | Our task for this lesson is to install a tool called `fortune`. `fortune` is a very old, popular and entertaining utility. The tool does exactly what the name says - it prints random fortune cookies to the terminal. 21 | 22 | ## Step 1: Update software repositories 23 | 24 | Before we install any package, we must ensure that our package repository is up-to-date. The APT package index is a database of all packages under each repository. 25 | 26 | When a package gets updated, we need to update our local index before we can install the latest package versions. To do that, run the following command: 27 | 28 | ```bash 29 | $ sudo apt-get update 30 | ``` 31 | 32 | After running the above command our package list got updated. However, our software packages haven't been _upgraded_, only the details of new versions present in the package index have been _updated_. We need to run `apt-get upgrade` which will upgrade all the older packages in our system to their latest versions as present in the package index. 33 | 34 | ## Step 2: Installing packages 35 | 36 | Now that we learnt how to keep our package repositories updated, it's time for us to install the package `fortune-mod` from the Ubuntu repository. 37 | 38 | **NOTE**: The name of the package is `fortune-mod` in the APT repository, however the actual name of the command is `fortune`. 39 | 40 | ```bash 41 | $ sudo apt-get install fortune-mod 42 | ``` 43 | 44 | We can verify that it's installed by running the command `fortune`: 45 | 46 | ```bash 47 | $ fortune 48 | Is this happening? 49 | ``` 50 | 51 | **NOTE**: Since `fortune` prints a random message every time you run, it's completely normal for you to see an output different than above. 52 | 53 | Congrats! You learnt how to update packages and even install one yourself. Here's an exercise for you: 54 | 55 | --- 56 | 57 | ## Task 58 | 59 | Install the famous utility `cowsay` and print this message "I like learning new things". The output would look something similar to: 60 | 61 | ``` 62 | $ cowsay I like learning new things 63 | ____________________________ 64 | < I like learning new things > 65 | ---------------------------- 66 | \ ^__^ 67 | \ (oo)\_______ 68 | (__)\ )\/\ 69 | ||----w | 70 | || || 71 | ``` 72 | -------------------------------------------------------------------------------- /courses/self-hosting-101/week1/overview.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Overview 3 | include_in_preview: false 4 | --- 5 | 6 | Welcome to Week 1. 7 | 8 | In the first week, we'll begin our self-hosting journey by starting with setting up a VPS(Virtual Private Server) and learning how to configure it. Self Hosting requires us to learn the basics of Linux, like navigating the file system, creating users, editing files, installing packages etc. We'll uncover each of these topics in separate lessons. 9 | 10 | The learning objectives for Week 1 are: 11 | 12 | - [Creating a droplet on DigitalOcean](./creating-droplet.md). 13 | - [Creating Users](./creating-users.md) 14 | - [Installing Packages](./installing-packages.md) 15 | - [Learning the filesystem](./working-with-files-directories.md) 16 | - [Setting up SSH](./setting-up-ssh.md) 17 | - [Using tmux](./using-tmux.md) 18 | 19 | After covering the objectives laid out this week and completing all exercises, we should be able to grasp a basic understanding of the tasks planned for the next upcoming weeks. 20 | -------------------------------------------------------------------------------- /courses/self-hosting-101/week1/using-tmux.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Using tmux 3 | include_in_preview: false 4 | --- 5 | 6 | In this lesson, we'll learn how to use `tmux` to run a long running command. 7 | 8 | ### Refresher 9 | 10 | We'll use some concepts here that was learned in the previous lesson. You can take a quick look at them to refresh them: 11 | 12 | - `ssh user@ip` command to login from [Creating droplet lesson](./creating-droplet.md) 13 | - `apt` commands from [Installing Packages lesson](./installing-packages.md) 14 | 15 | --- 16 | 17 | `tmux` is a terminal multiplexer, which allows you to create and persist "shell sessions" on the server. This is helpful if you have to run a long-running command and don't want the process to be killed if your SSH connection is interuppted for any reason. 18 | This is also helpful if you have more than 1 person logging in to your server and you together need to work on the same session. 19 | 20 | `tmux` allows you to _attach_ multiple shells to the same terminal session. That means you can open a `tmux` window, split it into multiple parts (_panes_) and run different commands on each of them. 21 | 22 | Our task for this lesson is to run a command `nano week1/hello.txt`. This command prints the message on the terminal but takes 60 seconds to complete. 23 | 24 | Let's create a new session with: 25 | 26 | ``` 27 | tmux 28 | ``` 29 | 30 | {{ Image("tmux.png") }} 31 | 32 | You'll be logged into your current user account. `tmux` is controlled using what is called as **Modifier Key** (Mod). The default hotkey for that is `Ctrl+b`. This combination will be referred to as `mod` from now onwards. 33 | 34 | ### Running Commands 35 | 36 | Let's run our command `nano week1/hello.txt`. You'll notice the editor is opened right now. 37 | 38 | ```bash 39 | $ nano week1/hello.txt 40 | ``` 41 | 42 | Let's _deattach_ from this session and return to our normal prompt. To do that, you'll need to use `mod d`. Once you do that, you'll be returned to the prompt from where you started the `tmux` session. 43 | 44 | #### Deattach a session 45 | 46 | ``` 47 | mod d 48 | ``` 49 | 50 | #### List sessions 51 | 52 | ```bash 53 | $ tmux ls 54 | 0: 1 windows (created Tue Dec 14 18:19:10 2021) 55 | ``` 56 | 57 | #### Attaching sessions 58 | 59 | ``` 60 | $ tmux a 61 | ``` 62 | 63 | Congrats! You completed the task for this lesson. We used `tmux` to run a long-running command and learnt how to attach/detach sessions. 64 | 65 | ## Additional Shortcuts 66 | 67 | ### Panes 68 | 69 | - `mod %`: To split a window vertically. 70 | - `mod "`: To split a window horizontally. 71 | - `mod [`: To add a scrollbar to the current pane. 72 | 73 | You can move around the panes with `mod + Right/Left/Up/Down` arrow keys. 74 | 75 | ### Windows 76 | 77 | - `mod c`: Create a new window. 78 | - `mod p`: Switch to previous window index. 79 | - `mod n`: Switch to next window index. 80 | 81 | You can explore some handy cheatsheets like [https://tmuxcheatsheet.com/](https://tmuxcheatsheet.com/) and [https://devhints.io/tmux](https://devhints.io/tmux) for more commands. 82 | -------------------------------------------------------------------------------- /courses/self-hosting-101/week2/customising-index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Customising Index Page 3 | include_in_preview: false 4 | --- 5 | 6 | Now that we have `nginx` running on our server, let's learn how to modify the default Welcome page. But before that, we need to understand how `nginx` is configured. 7 | The default place for `nginx` configuration is at the directory `/etc/nginx`. 8 | 9 | Let's visit the directory and explore around: 10 | 11 | ```bash 12 | $ cd /etc/nginx 13 | $ ls 14 | conf.d fastcgi_params koi-win modules-available nginx.conf scgi_params sites-enabled uwsgi_params 15 | fastcgi.conf koi-utf mime.types modules-enabled proxy_params sites-available snippets win-utf 16 | ``` 17 | 18 | Here, we can see a bunch of different config files and folders that come with `nginx`. We're interested in finding out how to configure the welcome page, so we should first find out where it's configured. There are 2 places where configuration for `nginx` sites can be stored: 19 | 20 | - Inside `conf.d` directory. 21 | - Inside `sites-enabled` directory. 22 | 23 | The `default` site is inside `sites-enabled`, so let's visit that. 24 | 25 | ```bash 26 | $ cd sites-enabled 27 | $ ls 28 | default 29 | ``` 30 | 31 | We can see the config file `default` located here. Since we're interested in customising the _Welcome_ page, we first need to find out where that page is located. 32 | 33 | Let's open this config file to see if it has any clues: 34 | 35 | ```bash 36 | $ nano default 37 | ``` 38 | 39 | On scrolling through, we see a `server` block. A `server` block represents a website and `nginx` config can contain multiple such blocks to represent multiple websites . The usual config when loaded in `nginx` looks like: 40 | 41 | ```bash 42 | http { 43 | server { 44 | ... 45 | } 46 | server { 47 | ... 48 | } 49 | } 50 | ``` 51 | 52 | The _Welcome_ page is also located in this `server` block. On scrolling down a bit, we see something that is relevant for us: 53 | 54 | ``` 55 | root /var/www/html; 56 | 57 | # Add index.php to the list if you are using PHP 58 | index index.html index.htm index.nginx-debian.html; 59 | ``` 60 | 61 | The [root](http://nginx.org/en/docs/http/ngx_http_core_module.html#root) directive is to specify where the assets are stored which is used to process the requests. We can see the directory `/var/www/html` mentioned in the config, which means our _Welcome_ page is present here. Let's visit that directory and find out! 62 | 63 | ```bash 64 | $ cd /var/www/html 65 | $ ls 66 | index.nginx-debian.html 67 | ``` 68 | 69 | We can see the `.html` file for the _Welcome_ page here. Let's edit the file and change the heading from _Welcome to NGINX_ to _Welcome to Monschool_: 70 | 71 | ```bash 72 | sudo nano index.nginx-debian.html 73 | ``` 74 | 75 | {{ Image("nginx-index-edit.png") }} 76 | 77 | Once the file is saved, we need to _reload_ nginx configuration for the changes to take place. We can use the following command to do that: 78 | 79 | ```bash 80 | $ sudo nginx -t 81 | nginx: the configuration file /etc/nginx/nginx.conf syntax is ok 82 | nginx: configuration file /etc/nginx/nginx.conf test is successful 83 | 84 | $ sudo nginx -s reload 85 | ``` 86 | 87 | `nginx -t` checks if your configuration is valid or not. It's a good practice to run this before reloading the configuration as any syntax errors in the configuration will cause `nginx` to not restart properly and cause a downtime of your website. 88 | 89 | Perfect! In this lesson we learnt how `nginx` stores it's configuration and how to modify the default _Welcome_ page. In the next lesson, we'll be setting up our own HTML/CSS website designed for this course. 90 | -------------------------------------------------------------------------------- /courses/self-hosting-101/week2/overview.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Overview 3 | include_in_preview: false 4 | --- 5 | 6 | Welcome to Week 2. 7 | 8 | In the second week, we'll learn how to self host a static website. A static website consists of assets like HTML, CSS and some Javascript. We'll learn how to configure a webserver which can serve these files over the internet. 9 | 10 | The learning objectives for Week 2 are: 11 | 12 | - [Installing NGINX](./installing-nginx.md). 13 | - [Customising Default Index ](./customising-index.md) 14 | - [Creating a new site](./creating-a-site.md) 15 | - [Setting up a site using `git`](./setup-using-git.md) 16 | 17 | After covering the objectives laid out this week and completing all exercises, we should be able to grasp a basic understanding of the tasks planned for the next upcoming weeks. 18 | -------------------------------------------------------------------------------- /courses/self-hosting-101/week2/setup-using-git.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Setup a site using git 3 | include_in_preview: false 4 | --- 5 | 6 | So far we've covered how to create our own site on the server and make it accessible. However in most real world cases, you'll want to _fetch_ the website from an external source and set it on your server. The most common usecases are personal websites/blogs etc where you store the content in a `git` repo and _build_ the website using a _Static Site Generator_. 7 | 8 | Let's clone a sample website from Monschool repo and set it up as `red..monschool.net`. 9 | 10 | ``` 11 | git clone <> ~/red..monschool.net 12 | ``` 13 | 14 | We are now going to introduce the concept of `symlink`. A symlink is a _redirect_ for a file. For example, consider we have a file `~/test.txt`. 15 | 16 | ``` 17 | touch ~/test.txt 18 | ``` 19 | 20 | To make it available at a different place, say `~/new.txt`, we can _symlink_ `test.txt`. The advantage here over copying the file as `new.txt` is that the underlying file exists only in one place (`~/test.txt`) but a new copy of it also exists in ~/new.txt. So whenever we have to change the original file, we just need to do it in one place. 21 | 22 | ``` 23 | ln -s ~/test.txt ~/new.txt 24 | ``` 25 | 26 | Using `ln -s` we can create the symlink. We can verify the symlink exists using `ls -l`: 27 | 28 | ``` 29 | $ ls -l new.txt 30 | lrwxrwxrwx 1 karan karan 20 Dec 22 12:39 new.txt -> /home/karan/test.txt 31 | ``` 32 | 33 | Now that we understand how symlink works, you must be wondering why we introduced this in this chapter. Well, that is because whenever we pull our website using `git pull` and get the latest changes, we don't really want to copy our changes inside `/var/www` directory where we expect the site assets. (It is possible to change the root directory to where your site is, it's just a general good practice to keep it under `/var/www` so that if you have a lot of different sites on the system, you can all see it under one folder). 34 | 35 | So, to achieve the above goal, we need to symlink `~/red..monschool.net to /var/www/`. Let's do that: 36 | 37 | ``` 38 | sudo ln -s ~/red..monschool.net to /var/www/ 39 | ``` 40 | 41 | Now, using the knowledge from previous lesson where we created a `blue.conf`, let's create a `red.conf` as well: 42 | 43 | ## Project: Setup a blog using Hugo 44 | 45 | Now that you understand how sites are setup, cloned etc, it's time that you setup your own website using a static site generator. For this course, we will use `hugo`. Hugo is a popular static site generator written in Golang. It's a single binary program that can be downloaded and used to create websites using Markdown content. For this exercise, your task is to install Hugo, build a basic website and host it via NGINX. 46 | 47 | You can refer to following links: 48 | 49 | - [https://gohugo.io/getting-started/installing/](https://gohugo.io/getting-started/installing/) 50 | - [https://gohugo.io/getting-started/quick-start/](https://gohugo.io/getting-started/quick-start/) 51 | -------------------------------------------------------------------------------- /dev-requirements.txt: -------------------------------------------------------------------------------- 1 | pytest 2 | -------------------------------------------------------------------------------- /macro.py: -------------------------------------------------------------------------------- 1 | 2 | def image_macro(name): 3 | return f'' 4 | -------------------------------------------------------------------------------- /make-image.py: -------------------------------------------------------------------------------- 1 | """ 2 | Script to prepare the course image to fit into mon.school. 3 | 4 | The mon.school course images are displyed in two different sizes and often 5 | getting cropped if not enough care is taken. 6 | 7 | This script takes any image and generates a new image that works for both of those 8 | sizes. 9 | 10 | The sizes that are used in the mon school app are 348x168 and 350x200. 11 | 12 | To make the image work for both sizes, the image is resized to 340x170 and placed 13 | in the center of 350x200 image. 14 | """ 15 | from PIL import Image 16 | import sys 17 | 18 | im = Image.open(sys.argv[1]) 19 | im.thumbnail((340, 170)) 20 | 21 | im2 = Image.new(mode="RGBA", size=(350, 200), color=(0, 0, 0, 0)) 22 | offset = (im2.width-im.width) // 2, (im2.height-im.height)//2 23 | im2.paste(im, offset) 24 | im2.save("a.png") 25 | print("saved the new image as a.png") 26 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | """Script to validate the contents and push it to mon.school. 2 | """ 3 | from build.cli import main 4 | 5 | if __name__ == "__main__": 6 | main() 7 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: Mon School Courses 2 | theme: 3 | name: material 4 | custom_dir: overrides 5 | features: 6 | - navigation.tabs 7 | - navigation.sections 8 | 9 | plugins: 10 | - mkdocs-simple-hooks: 11 | hooks: 12 | on_files: "build.nav:on_files" 13 | 14 | docs_dir: courses 15 | 16 | markdown_extensions: 17 | - meta 18 | - fenced_code 19 | - macros: 20 | registry: 21 | Image: "macro:image_macro" 22 | 23 | repo_url: https://github.com/fossunited/monschool-website 24 | 25 | 26 | extra_css: 27 | - assets/codemirror/lib/codemirror.css 28 | - assets/style.css 29 | 30 | extra_javascript: 31 | - /assets/codemirror/lib/codemirror.js 32 | - /assets/codemirror/addon/mode/simple.js 33 | - /assets/codemirror/mode/python/python.js 34 | - /assets/codemirror/mode/rust/rust.js 35 | - /assets/codemirror/mode/go/go.js 36 | - /assets/codemirror/mode/xml/xml.js 37 | - /assets/codemirror/mode/css/css.js 38 | - /assets/codemirror/mode/javascript/javascript.js 39 | - /assets/codemirror/mode/htmlmixed/htmlmixed.js 40 | - /assets/codemirror/keymap/sublime.js 41 | - /assets/codemirror/addon/edit/matchbrackets.js 42 | - /assets/codemirror/addon/comment/comment.js 43 | - https://code.jquery.com/jquery-3.6.0.min.js 44 | - /assets/livecode.js 45 | -------------------------------------------------------------------------------- /overrides/main.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block scripts %} 4 | 5 | 16 | 17 | {{ super() }} 18 | 19 | 20 | {% endblock %} 21 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | mkdocs-material 2 | mkdocs-simple-hooks 3 | click 4 | python-frontmatter 5 | git+https://github.com/frappe/frappe-client#egg=frappeclient 6 | git+https://github.com/fossunited/markdown-macros.git#egg=markdown-macros 7 | -------------------------------------------------------------------------------- /runtests.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | exec py.test tests 4 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | sys.path.append("..") -------------------------------------------------------------------------------- /tests/test_workspace.py: -------------------------------------------------------------------------------- 1 | from build import workspace 2 | import yaml 3 | 4 | COURSE_YML = """ 5 | name: python-primer 6 | title: Python Primer 7 | suffix: pp 8 | short_introduction: Introduction to Python 9 | description: Practical introduction to Python 10 | instructor: foobar 11 | draft: false, 12 | is_published: true 13 | upcoming: true 14 | preview_image: null 15 | tags: 16 | - python 17 | - beginner 18 | video_link: 19 | chapters: 20 | - name: introduction 21 | title: Introduction 22 | description: Introduction to Python 23 | lessons: 24 | - introduction/getting-started.md 25 | - introduction/hello-world.md 26 | - name: datatypes 27 | title: Datatypes 28 | description: Exploring Datatypes in Python 29 | lessons: [] 30 | """ 31 | 32 | LESSON_TEXT = """\ 33 | --- 34 | title: Getting Started 35 | include_in_preview: false 36 | --- 37 | 38 | Getting Started with Python 39 | """ 40 | 41 | class TestWorkspace: 42 | def test_read_course(self, tmp_path): 43 | path = tmp_path / "python-primer" / "course.yml" 44 | path.parent.mkdir() 45 | path.write_text(COURSE_YML) 46 | 47 | w = workspace.Workspace(str(tmp_path)) 48 | c = w.read_course("python-primer") 49 | assert c.dict() == yaml.safe_load(path.open()) 50 | 51 | assert c.get_doc() == { 52 | "name": "python-primer", 53 | "title": "Python Primer", 54 | "short_introduction": "Introduction to Python", 55 | "description": "Practical introduction to Python", 56 | "instructor": "foobar", 57 | "is_published": 1, 58 | "upcoming": 1, 59 | "tags": "python,beginner", 60 | "video_link": None, 61 | "chapters": [{"chapter": "introduction-pp"}, {"chapter": "datatypes-pp"}] 62 | } 63 | 64 | def test_chapter_doc(self, tmp_path): 65 | path = tmp_path / "python-primer" / "course.yml" 66 | path.parent.mkdir() 67 | path.write_text(COURSE_YML) 68 | 69 | w = workspace.Workspace(str(tmp_path)) 70 | c = w.read_course("python-primer") 71 | chapter = c.get_chapter("introduction") 72 | assert chapter.get_doc() == { 73 | "course": "python-primer", 74 | "name": "introduction-pp", 75 | "title": "Introduction", 76 | "description": "Introduction to Python", 77 | "lessons": [{"lesson": "getting-started-pp"}, {"lesson": "hello-world-pp"}] 78 | } 79 | 80 | def test_read_lesson(self, tmp_path): 81 | path = tmp_path / "python-primer" / "course.yml" 82 | path.parent.mkdir() 83 | path.write_text(COURSE_YML) 84 | 85 | path2 = path.parent.joinpath("introduction", "getting-started.md") 86 | path2.parent.mkdir() 87 | path2.write_text(LESSON_TEXT) 88 | 89 | w = workspace.Workspace(str(tmp_path)) 90 | lesson = w.read_lesson(path2) 91 | 92 | assert lesson.dict() == { 93 | "name": "getting-started", 94 | "title": "Getting Started", 95 | "include_in_preview": False, 96 | "body": "Getting Started with Python" 97 | } 98 | assert lesson.chapter.name == 'introduction' 99 | 100 | assert lesson.get_doc() == { 101 | "chapter": "introduction-pp", 102 | "name": "getting-started-pp", 103 | "title": "Getting Started", 104 | "include_in_preview": False, 105 | "body": "Getting Started with Python" 106 | } 107 | --------------------------------------------------------------------------------