diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
index 35acb9c..10cfe31 100644
--- a/.devcontainer/Dockerfile
+++ b/.devcontainer/Dockerfile
@@ -32,7 +32,8 @@ RUN apt -qq update && \
RUN python3 -m pip install -q --retries 10000 --timeout 60 --no-cache-dir \
click==8.1.3 \
ipykernel==6.27.1 \
- requests==2.31.0
+ requests==2.31.0 \
+ Flask==3.0.0
# Create User
RUN \
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..c1458b2
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2025 Benjamin Yde
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
index 03df6e4..cbd836a 100644
--- a/README.md
+++ b/README.md
@@ -1,81 +1,164 @@
-# Welcome to the Python Guide π
-
-This repository is a Python guide designed which is designed to be easily opened using VS Code or Github. It contains extensive documentation, code examples, and best practices to help you become a proficient Python programmer.
-The guide intends to be **to the point** so you can continue what really matters, programming.
-
-# Execute Code Examples π
-
-Explore the `examples` directory for **interactive Python** code examples, easily executable in **Jupyter Notebooks** using a **Docker DevContainer** within **Visual Studio Code**. This setup ensures a consistent and streamlined coding environment, ideal for learning and experimentation.
-
-# Guide Index ποΈ
-
-**The following index contains categories with topics that are ready for visibility or completed.**
-There is **more content incoming** so the categories will **not be visible here** until it is completed.
-Want to see what topics are in todo? See the **index per category**.
-
-- [About Python](guide/about/_index.md)
- - [About Python](guide/about/about_python.md)
- - [A Compiler vs an Interpreter](guide/about/compiler_vs_interpreter.md)
- - [The Python Interpreter](guide/about/python_interpreter.md)
-- [General Python](guide/general/_index.md)
- - [Strings](guide/general/strings.md)
- - [Flow Control](guide/general/flow_control.md)
- - [Creating Functions](guide/general/creating_functions.md)
- - [Typing](guide/general/typing.md)
- - [Scopes and References](guide/general/scopes_and_references.md)
- - [Exeptions](guide/general/exceptions.md)
- - [Lambdas](guide/general/lambdas.md)
- - [Callable](guide/general/callable.md)
- - [Generics](guide/general/generics.md)
-- [Containers](guide/containers/_index.md)
- - [Lists](guide/containers/lists.md)
- - [Sequence](guide/containers/sequence.md)
- - [Iterating](guide/containers/iterating.md)
- - [Tuples](guide/containers/tuples.md)
- - [Dictionaries](guide/containers/dictionaries.md)
- - [Mapping](guide/containers/mapping.md)
- - [Sets](guide/containers/sets.md)
- - [Comprehensions](guide/containers/comprehensions.md)
- - [Unpacking](guide/containers/unpacking.md)
- - [Generators and Iterators](guide/containers/iterators_and_generators.md)
- - [Array](guide/containers/array.md)
-- [Object Oriented Programming (OOP)](guide/oop/_index.md)
- - [About Classes](guide/oop/classes.md)
- - [Creating Classes](guide/oop/creating_classes.md)
- - [Magic Methods](guide/oop/magic_methods.md)
- - [Properties](guide/oop/properties.md)
- - [Naming Conventions](guide/oop/naming_conventions.md)
- - [Static Methods](guide/oop/static_methods.md)
- - [Class Methods](guide/oop/class_methods.md)
- - [Data Classes](guide/oop/dataclasses.md)
- - [Inheritance](guide/oop/inheritance.md)
- - [Abstract](guide/oop/abstract.md)
- - [Final](guide/oop/final.md)
-- [Packages](guide/packages/_index.md)
- - [Namespaces](guide/packages/namespaces.md)
- - [Modules](guide/packages/modules.md)
- - [Creating Packages](guide/packages/packages.md)
-- [Scripting](guide/scripting/_index.md)
- - [About](guide/scripting/about.md)
- - [File Handling](guide/scripting/file_handling.md)
- - [Logging](guide/scripting/logging.md)
- - [Subprocesses](guide/scripting/subprocess.md)
- - [Executing Python](guide/scripting/shebang.md)
- - [Custom CLI (click)](guide/scripting/click.md)
- - [Environment Variables](guide/scripting/env_variables.md)
-- [Concurrency](guide/concurrency/_index.md)
- - [Introduction To Concurrency](guide/concurrency/introduction.md)
- - [Global Interpreter Lock (GIL)](guide/concurrency/gil.md)
- - [Threading Module](guide/concurrency/threading.md)
- - [Asyncio Module](guide/concurrency/asyncio.md)
- - [Multiprocessing Module](guide/concurrency/multiprocessing.md)
- - [Concurrent Module](guide/concurrency/concurrent.md)
-- [Networking](guide/networking/_index.md)
- - [Introduction To Networking](guide/networking/introduction.md)
- - [Sockets](guide/networking/sockets.md)
-- TODO
- - Data Handling
- - Extentions
- - Networking
- - Testing
- - Tooling
+# The Python Guide π
+
+
+
+
+### π Welcome!
+
+This repository is a practical, **to-the-point guide** for developers looking to master modern Python. Whether you're a beginner taking your first steps or an experienced programmer leveling up, you'll find extensive documentation, best practices and runnable code.
+
+The core philosophy is simple: **learn by doing**. I get straight to the point so you can spend less time reading and more time programming.
+
+This guide is **Markdown**, so it is easily opened using **Visual Studio Code** or **Github**. It contains extensive documentation, code examples and best practices to help you become a proficient Python programmer.
+
+
+
+
+
+### π Execute Code Examples
+
+Explore the `π examples` directory for **interactive Python** code examples, easily executable in **Jupyter Notebooks** using a **Docker DevContainer** within **Visual Studio Code**.
+
+This setup ensures a consistent and streamlined coding environment, ideal for learning and experimentation.
+
+
+
+
+## ποΈ Table of Contents
+
+
+
+
+
+#### π― About Python
+
+- [About Python](guide/about/about_python.md)
+- [A Compiler vs an Interpreter](guide/about/compiler_vs_interpreter.md)
+- [The Python Interpreter](guide/about/python_interpreter.md)
+
+
+
+
+#### β¨ Python Basics
+
+- [Strings](guide/general/strings.md)
+- [Flow Control](guide/general/flow_control.md)
+- [Creating Functions](guide/general/creating_functions.md)
+- [Typing](guide/general/typing.md)
+- [Scopes and References](guide/general/scopes_and_references.md)
+- [Exeptions](guide/general/exceptions.md)
+- [Enums](guide/general/enum.md)
+- [Lambdas](guide/general/lambdas.md)
+- [Callable](guide/general/callable.md)
+- [Generics](guide/general/generics.md)
+
+
+
+
+#### π Strings
+
+- [Strings](guide/general/strings.md)
+- [Flow Control](guide/general/flow_control.md)
+- [Creating Functions](guide/general/creating_functions.md)
+- [Typing](guide/general/typing.md)
+- [Scopes and References](guide/general/scopes_and_references.md)
+- [Exeptions](guide/general/exceptions.md)
+- [Enums](guide/general/enum.md)
+- [Lambdas](guide/general/lambdas.md)
+- [Callable](guide/general/callable.md)
+- [Generics](guide/general/generics.md)
+
+
+
++
+
+#### π¦ Containers
+
+- [Lists](guide/containers/lists.md)
+- [Sequence](guide/containers/sequence.md)
+- [Iterating](guide/containers/iterating.md)
+- [Tuples](guide/containers/tuples.md)
+- [Dictionaries](guide/containers/dictionaries.md)
+- [Mapping](guide/containers/mapping.md)
+- [Sets](guide/containers/sets.md)
+- [Comprehensions](guide/containers/comprehensions.md)
+- [Unpacking](guide/containers/unpacking.md)
+- [Generators and Iterators](guide/containers/iterators_and_generators.md)
+- [Array](guide/containers/array.md)
+
+
+
+
+#### ποΈ Object Oriented Programming (OOP)
+
+- [About Classes](guide/oop/classes.md)
+- [Creating Classes](guide/oop/creating_classes.md)
+- [Magic Methods](guide/oop/magic_methods.md)
+- [Properties](guide/oop/properties.md)
+- [Naming Conventions](guide/oop/naming_conventions.md)
+- [Static Methods](guide/oop/static_methods.md)
+- [Class Methods](guide/oop/class_methods.md)
+- [Data Classes](guide/oop/dataclasses.md)
+- [Inheritance](guide/oop/inheritance.md)
+- [Abstract](guide/oop/abstract.md)
+- [Final](guide/oop/final.md)
+
+
+
+
+#### ποΈ Packages
+
+- [Namespaces](guide/packages/namespaces.md)
+- [Modules](guide/packages/modules.md)
+- [Creating Packages](guide/packages/packages.md)
+
+
+
+
++
+
+#### π οΈ Scripting
+
+- [About](guide/scripting/about.md)
+- [File Handling](guide/scripting/file_handling.md)
+- [Logging](guide/scripting/logging.md)
+- [Subprocesses](guide/scripting/subprocess.md)
+- [Executing Python](guide/scripting/shebang.md)
+- [Custom CLI (click)](guide/scripting/click.md)
+- [Environment Variables](guide/scripting/env_variables.md)
+
+
+
+
+#### β‘ Concurrency
+
+- [Introduction To Concurrency](guide/concurrency/introduction.md)
+- [Global Interpreter Lock (GIL)](guide/concurrency/gil.md)
+- [Threading Module](guide/concurrency/threading.md)
+- [Asyncio Module](guide/concurrency/asyncio.md)
+- [Multiprocessing Module](guide/concurrency/multiprocessing.md)
+- [Concurrent Module](guide/concurrency/concurrent.md)
+
+
+
+
+#### π Networking
+
+- [Introduction To Networking](guide/networking/introduction.md)
+- [Sockets](guide/networking/sockets.md)
+- [HTTP Requests](guide/networking/http_requests.md)
+
+
+
++
+
+#### π Data
+
+- [Working with Bytes](guide/data/bytes.md)
+- [Numpy](guide/data/numpy.md)
+
+
+
\ No newline at end of file
diff --git a/examples/networking/http_requests/01_get_post_put_path_delete.ipynb b/examples/networking/http_requests/01_get_post_put_path_delete.ipynb
new file mode 100644
index 0000000..b740d21
--- /dev/null
+++ b/examples/networking/http_requests/01_get_post_put_path_delete.ipynb
@@ -0,0 +1,197 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Creating a GET Request"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import requests\n",
+ "import json\n",
+ "\n",
+ "response = requests.get('http://127.0.0.1:5000/users')\n",
+ "if response.status_code == 200:\n",
+ " data = response.json()\n",
+ " formatted_json = json.dumps(data, indent=4) \n",
+ " print(\"Users:\", formatted_json)\n",
+ "else:\n",
+ " print(\"Failed to fetch users\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Creating a POST Request"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 34,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "User added: {\n",
+ " \"8\": {\n",
+ " \"email\": \"jane@example.com\",\n",
+ " \"name\": \"Jane Doe\"\n",
+ " }\n",
+ "}\n"
+ ]
+ }
+ ],
+ "source": [
+ "import requests\n",
+ "\n",
+ "new_user = {\"name\": \"Jane Doe\", \"email\": \"jane@example.com\"}\n",
+ "\n",
+ "response = requests.post('http://127.0.0.1:5000/users', json=new_user)\n",
+ "if response.status_code == 201:\n",
+ " data = response.json()\n",
+ " formatted_json = json.dumps(data, indent=4) \n",
+ " print(\"User added:\", formatted_json)\n",
+ "else:\n",
+ " print(\"Failed to add user\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Creating a PUT Request"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 35,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "User updated: {\n",
+ " \"1\": {\n",
+ " \"email\": \"john.smith@example.com\",\n",
+ " \"name\": \"John Smith\"\n",
+ " }\n",
+ "}\n"
+ ]
+ }
+ ],
+ "source": [
+ "import requests\n",
+ "\n",
+ "user_update = {\"name\": \"John Smith\", \"email\": \"john.smith@example.com\"}\n",
+ "response = requests.put('http://127.0.0.1:5000/users/1', json=user_update)\n",
+ "if response.status_code == 200:\n",
+ " data = response.json()\n",
+ " formatted_json = json.dumps(data, indent=4) \n",
+ " print(\"User updated:\", formatted_json)\n",
+ "else:\n",
+ " print(\"Failed to update user\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Creating a PATCH Request"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 36,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "User partially updated: {\n",
+ " \"1\": {\n",
+ " \"email\": \"new.john@example.com\",\n",
+ " \"name\": \"John Smith\"\n",
+ " }\n",
+ "}\n"
+ ]
+ }
+ ],
+ "source": [
+ "import requests\n",
+ "\n",
+ "user_partial_update = {\"email\": \"new.john@example.com\"}\n",
+ "response = requests.patch('http://127.0.0.1:5000/users/1', json=user_partial_update)\n",
+ "if response.status_code == 200:\n",
+ " data = response.json()\n",
+ " formatted_json = json.dumps(data, indent=4) \n",
+ " print(\"User partially updated:\", formatted_json)\n",
+ "else:\n",
+ " print(\"Failed to partially update user\")"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## Creating a DELETE Request"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Failed to delete user\n"
+ ]
+ }
+ ],
+ "source": [
+ "import requests\n",
+ "\n",
+ "response = requests.delete('http://127.0.0.1:5000/users/1')\n",
+ "if response.status_code == 200:\n",
+ " data = response.json()\n",
+ " formatted_json = json.dumps(data, indent=4) \n",
+ " print(formatted_json)\n",
+ "else:\n",
+ " print(\"Failed to delete user\")"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3 (ipykernel)",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.10.12"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/examples/networking/http_requests/01_start_server.py b/examples/networking/http_requests/01_start_server.py
new file mode 100755
index 0000000..58b0861
--- /dev/null
+++ b/examples/networking/http_requests/01_start_server.py
@@ -0,0 +1,46 @@
+#!/usr/bin/python3
+
+from flask import Flask, jsonify, request
+
+app = Flask(__name__)
+
+# Example data store
+users = {"1": {"name": "John Doe", "email": "john@example.com"}}
+
+@app.route('/users', methods=['GET'])
+def get_users():
+ return jsonify(users)
+
+@app.route('/users', methods=['POST'])
+def add_user():
+ user_id = str(len(users) + 1)
+ users[user_id] = request.json
+ return jsonify({user_id: users[user_id]}), 201
+
+@app.route('/users/', methods=['PUT'])
+def update_user(user_id):
+ if user_id in users:
+ users[user_id] = request.json
+ return jsonify({user_id: users[user_id]})
+ else:
+ return jsonify({"error": "User not found"}), 404
+
+@app.route('/users/', methods=['PATCH'])
+def patch_user(user_id):
+ if user_id in users:
+ for key, value in request.json.items():
+ users[user_id][key] = value
+ return jsonify({user_id: users[user_id]})
+ else:
+ return jsonify({"error": "User not found"}), 404
+
+@app.route('/users/', methods=['DELETE'])
+def delete_user(user_id):
+ if user_id in users:
+ del users[user_id]
+ return jsonify({"success": "User deleted"})
+ else:
+ return jsonify({"error": "User not found"}), 404
+
+if __name__ == '__main__':
+ app.run(debug=True)
diff --git a/guide/_index.md b/guide/_index.md
deleted file mode 100644
index baed0fb..0000000
--- a/guide/_index.md
+++ /dev/null
@@ -1,12 +0,0 @@
-# Index
-
-- [About Python](about/_index.md)
-- [Containers](containers/_index.md)
-- [Functions](functions/_index.md)
-- [Object Oriented Programming (OOP)](oop/_index.md)
-- [Data Handling](data/_index.md)
-- [Tesing](testing/_index.md)
-- [Tooling](tooling/_index.md)
-- [Libraries](extention/_index.md)
-- [Concurrency](extention/_index.md)
-- [Extention Modules](extention/_index.md)
\ No newline at end of file
diff --git a/guide/about/_index.md b/guide/about/_index.md
deleted file mode 100644
index 0450f20..0000000
--- a/guide/about/_index.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# Index
-
-- [About Python](about_python.md)
-- [A Compiler vs an Interpreter](compiler_vs_interpreter.md)
-- [The Python Interpreter](python_interpreter.md)
\ No newline at end of file
diff --git a/guide/concurrency/_index.md b/guide/concurrency/_index.md
deleted file mode 100644
index d745fc5..0000000
--- a/guide/concurrency/_index.md
+++ /dev/null
@@ -1,8 +0,0 @@
-# Index
-
-- [Introduction To Concurrency](introduction.md)
-- [Global Interpreter Lock (GIL)](gil.md)
-- [Threading Module](threading.md)
-- [Asyncio Module](asyncio.md)
-- [Multiprocessing Module](multiprocessing.md)
-- [Concurrent Module](concurrent.md)
diff --git a/guide/containers/_index.md b/guide/containers/_index.md
deleted file mode 100644
index 863f9a5..0000000
--- a/guide/containers/_index.md
+++ /dev/null
@@ -1,13 +0,0 @@
-# Index
-
-- [Lists](lists.md)
-- [Iterating](iterating.md)
-- [Tuples](tuples.md)
-- [Dictionaries](dictionaries.md)
-- [Sets](sets.md)
-- [Mapping](mapping.md)
-- [Sequence](sequence.md)
-- [Comprehensions](comprehensions.md)
-- [Unpacking](unpacking.md)
-- [Generators and Iterators](iterators_and_generators.md)
-- [Array](array.md)
\ No newline at end of file
diff --git a/guide/data/_index.md b/guide/data/_index.md
deleted file mode 100644
index 780b47f..0000000
--- a/guide/data/_index.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# Index
-
-todo
-
-- json
-- pydantic
-- xml
-- pandas
-- numpy
\ No newline at end of file
diff --git a/guide/data/bytes.md b/guide/data/bytes.md
new file mode 100644
index 0000000..82e0fce
--- /dev/null
+++ b/guide/data/bytes.md
@@ -0,0 +1,235 @@
+# Bytes
+
+## What are bytes?
+
+### Definition
+
+- A byte is a unit of digital information in computing and telecommunications.
+- It typically consists of eight bits, where a bit is the smallest unit of data in a computer, represented as either 0 or 1.
+- The byte is a common unit of measurement for data size and storage.
+
+### Bytes and Characters
+
+In computer systems, a byte can represent a character such as a letter, number, or typographic symbol. For example, in the ASCII (American Standard Code for Information Interchange) character encoding, each character is represented by a specific byte value.
+
+### How Bytes Work
+
+#### Binary Representation
+
+- Each bit in a byte can be in one of two states, 0 or 1. This binary system is the foundation of all modern computing.
+- The combination of eight bits (or one byte) allows for 256 different combinations (2^8), ranging from 00000000 to 11111111 in binary, which can represent 256 different values or symbols.
+
+#### Encoding
+
+- To represent characters, bytes must be interpreted through a character encoding. ASCII is one of the simplest forms of encoding, where each character is assigned a specific byte value. For example, the ASCII code for 'A' is 65 (or 01000001 in binary).
+- Other encodings, like UTF-8, use one or more bytes to represent a single character, allowing them to cover a much wider range of characters, including those from non-Latin scripts.
+
+### Usage of Bytes
+
+#### Data Storage and Transmission
+
+- Bytes are the fundamental building blocks of data storage. Files on a computer, for instance, are measured in bytes, as well as kilobytes (1024 bytes), megabytes (1024^2 bytes), and so on.
+- In data transmission, such as over the internet, the speed is often measured in bits per second or bytes per second.
+
+#### Memory Representation
+
+- In computer memory, bytes are used to store data. Each byte has a specific address that the computer's processor can use to access its value.
+- Programming languages provide various ways to manipulate bytes, often through data types and structures that abstract away the binary complexity.
+
+#### Networking
+- Network protocols, like TCP/IP, structure data into packets consisting of bytes. Each byte in a packet can represent part of a header, payload, or footer, as defined by the protocol.
+
+## Creating Bytes Objects
+
+### Literal Byte Sequences
+
+- Syntax: `b'Hello World'` creates a byte object directly.
+- Each character in the literal is converted to its corresponding ASCII value.
+
+### Using the `bytes()` constructor
+
+- The bytes() function creates a new bytes object.
+- `bytes([72, 101, 108, 108, 111])` which is equivalent to `b'Hello'`
+
+## Converting Between Bytes and Strings
+
+### Encoding a String to Bytes
+
+- Strings in Python are sequences of Unicode characters.
+- Encoding is the process of converting these characters into a sequence of bytes.
+- Use the `encode()` method on a string, specifying the encoding (like 'utf-8', 'ascii', 'latin1').
+- Example: `'Hello'.encode('utf-8')` converts `'Hello'` to its UTF-8 encoded byte representation.
+- Encoding is crucial for storing text in files, sending over networks, or processing in binary formats.
+
+```python
+data_str = "Hello, World!"
+data_bytes = data_str.encode('utf-8')
+print(data_bytes)
+```
+
+### Decoding Bytes to a String
+
+- Decoding is the reverse process of encoding, converting bytes back into a string.
+- Use the `decode()` method on a bytes object, specifying the encoding.
+- Example: `b'Hello'.decode('utf-8')` converts the bytes back to the string `'Hello'`.
+- Incorrect decoding (using the wrong encoding) can lead to errors or garbled text.
+- Important for reading text from binary files, network responses, or processing any data that comes in a byte format.
+
+```python
+data_bytes = b"Hello, Bytes!"
+data_str = data_bytes.decode('utf-8')
+print(data_str)
+```
+
+## Byte Manipulation
+
+Byte manipulation refers to the process of modifying or interpreting bytes at the bit level. This is often done using bitwise operators, which operate on individual bits within a byte or group of bytes.
+
+### AND Operator `&`
+
+Each bit of the output is 1 if the corresponding bits of both operands are 1, else 0.
+
+```python
+a = 0b1100 # 12 in binary
+b = 0b1010 # 10 in binary
+result = a & b # 0b1000 (8 in decimal)
+```
+
+### OR Operator `|`
+
+Each bit of the output is 1 if at least one of the corresponding bits of either operand is 1.
+
+```python
+a = 0b1100 # 12 in binary
+b = 0b1010 # 10 in binary
+result = a | b # 0b1110 (14 in decimal)
+```
+
+### XOR Operator `^`
+
+Each bit of the output is 1 if the corresponding bits of the operands are different.
+
+```python
+a = 0b1100 # 12 in binary
+b = 0b1010 # 10 in binary
+result = a ^ b # 0b0110 (6 in decimal)
+```
+
+### NOT Operator `~`
+
+Inverts the bits of the operand.
+
+```python
+a = 0b1100 # 12 in binary
+result = ~a # Inverts all bits
+```
+
+### Bit Shifts
+
+- **Left Shift (<<)**: Shifts the bits to the left, padding with zeros. + - Multiplies the number by 2 for each shift. + - **Example**: a << 2 shifts a two bits to the left. + +- **Right Shift (>>)**: Shifts the bits to the right.
+ - Divides the number by 2 for each shift, discarding fractions.
+ - For signed integers, the sign bit (leftmost bit) is used to fill the vacancies.
+ - **Example**: a>> 2 shifts a two bits to the right.
+
+## `struct` module
+
+The `struct` module in Python is used for converting between Python values and C structs represented as Python bytes objects. This is particularly useful for reading and writing binary data, or for interfacing with C code. It's a key tool for handling binary data in Python, especially when dealing with files, network protocols, or other binary formats.
+
+### Packing and Unpacking Data
+
+#### Format strings
+
+- Used to specify the layout of the data being packed/unpacked.
+- Consist of format characters, which indicate the data type and size.
+- Common format characters include:
+ - `i`: Represents an integer. Size: 4 bytes.
+ - `f`: Represents a floating-point number. Size: 4 bytes.
+ - `d`: Represents a double precision floating-point number. Size: 8 bytes.
+ - `c`: Represents a single byte character. Size: 1 byte.
+ - `s`: Represents a sequence of characters (string). Size: 1 byte per character.
+ - `b`: Represents a signed byte. Size: 1 byte.
+ - `B`: Represents an unsigned byte. Size: 1 byte.
+ - `h`: Represents a short integer. Size: 2 bytes.
+ - `H`: Represents an unsigned short integer. Size: 2 bytes.
+ - `l`: Represents a long integer. Size: 4 bytes. (Note: On some platforms, it might be 8 bytes).
+ - `L`: Represents an unsigned long integer. Size: 4 bytes. (Note: On some platforms, it might be 8 bytes).
+ - `q`: Represents a long long integer. Size: 8 bytes.
+ - `Q`: Represents an unsigned long long integer. Size: 8 bytes.
+ - `?`: Represents a boolean value. Size: 1 byte.
+
+In the format strings used with Python's struct module, whitespace characters between format specifiers are indeed ignored. This means you can include spaces for readability without affecting the functionality.
+
+#### Count Numbers
+
+A number preceding a format character indicates a sequence or array of that type.
+For example:
+
+- `4i` represents four integers
+- `10s` represents a string of 10 characters.
+
+#### Packing
+
+Converts Python objects to bytes (binary data).
+
+```python
+import struct
+
+# Pack an integer and a float into bytes
+packed_data = struct.pack('if', 123, 45.67)
+```
+
+#### Unpacking
+
+Converts bytes (binary data) back into Python objects.
+
+```python
+import struct
+
+# Whitespace for readability is allowed between format characters
+packed_data = struct.pack('i f', 123, 45.67)
+
+# Unpacking the data
+unpacked_data = struct.unpack('i f', packed_data)
+
+# Accessing the unpacked data
+unpacked_integer = unpacked_data[0] # 123
+unpacked_float = unpacked_data[1] # 45.67
+```
+
+### Combining with Data Classes
+
+Python's `dataclasses` module, introduced in Python 3.7, is designed for classes that are mainly used to store data. By combining data classes with struct, you can create a more readable and maintainable structure for handling binary data.
+
+Example:
+
+```python
+from dataclasses import dataclass
+import struct
+
+@dataclass
+class MyData:
+ value1: int
+ value2: float
+ value3: int
+
+ def pack(self):
+ return struct.pack('ifi', self.value1, self.value2, self.value3)
+
+ @staticmethod
+ def unpack(data):
+ values = struct.unpack('ifi', data)
+ return MyData(*values)
+
+# Create an instance of MyData
+data_instance = MyData(100, 25.75, 200)
+
+# Pack the data into bytes
+packed_data = data_instance.pack()
+
+# Unpack the data back into a dataclass instance
+unpacked_instance = MyData.unpack(packed_data)
+```
\ No newline at end of file
diff --git a/guide/data/numpy.md b/guide/data/numpy.md
new file mode 100644
index 0000000..3617011
--- /dev/null
+++ b/guide/data/numpy.md
@@ -0,0 +1,664 @@
+# NumPy
+
+## Introduction to NumPy
+
+NumPy, short for Numerical Python, is a powerful library in Python for numerical computing. It provides support for large multidimensional arrays and matrices, along with a wide variety of mathematical functions to operate on these arrays. NumPy is essential for scientific computing and is the foundation of many other libraries, including SciPy, Matplotlib, and pandas.
+
+At the core of the NumPy package, is the `ndarray` object. This encapsulates n-dimensional arrays of homogeneous data types, with many operations being performed in compiled code for performance.
+
+### Installation
+
+To install NumPy, you can use pip:
+
+```bash
+pip install numpy
+```
+
+Website: https://numpy.org/
+
+## Basics of NumPy Arrays
+
+### Creating Arrays
+
+NumPy arrays can be created in several ways. The most common method is to use the `numpy.array()` function:
+
+```python
+import numpy as np
+
+# Creating a 1D array
+arr1 = np.array([1, 2, 3, 4, 5])
+
+# Creating a 2D array
+arr2 = np.array([[1, 2, 3], [4, 5, 6]])
+
+# Creating an array with a specified data type
+arr3 = np.array([1, 2, 3], dtype=float)
+```
+
+### Array Attributes
+
+NumPy arrays have several attributes that provide information about the array:
+
+```python
+arr = np.array([[1, 2, 3], [4, 5, 6]])
+
+print("Shape:", arr.shape) # Output: (2, 3)
+print("Number of dimensions:", arr.ndim) # Output: 2
+print("Size:", arr.size) # Output: 6
+print("Data type:", arr.dtype) # Output: int64 (or int32 depending on the system)
+print("Item size:", arr.itemsize) # Output: 8 (or 4 depending on the system)
+```
+
+### Creating a Function With NumPy Array Return Value
+
+```python
+def create_array() -> np.ndarray:
+ return np.array([[1, 2, 3], [4, 5, 6]])
+```
+
+### More On Array Shape
+
+In the context of a NumPy array's shape, this tuple contains integers that represent the size of the array along each dimension.
+
+```python
+import numpy as np
+
+arr1 = np.array([1, 2, 3, 4, 5])
+print(arr1.shape) # Output: (5,)
+
+arr2 = np.array([[1, 2, 3], [4, 5, 6]])
+print(arr2.shape) # Output: (2, 3)
+
+arr3 = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
+print(arr3.shape) # Output: (2, 2, 2)
+```
+
+### Array Initialization
+
+NumPy provides functions to create arrays with initial placeholder content:
+
+```python
+# Array of zeros
+zeros = np.zeros((2, 3))
+
+# Array of ones
+ones = np.ones((3, 2))
+
+# Arrange
+np.arange(10) # array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
+np.arange(2, 10, dtype=float) # array([2., 3., 4., 5., 6., 7., 8., 9.])
+np.arange(2, 3, 0.1) # array([2. , 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9])
+
+# Equally space elements in range
+np.linspace(1., 4., 6) # array([1. , 1.6, 2.2, 2.8, 3.4, 4. ])
+
+# Array of a constant value
+full = np.full((2, 2), 7)
+
+# Identity matrix
+identity = np.eye(3)
+#array([[1., 0., 0.],
+# [0., 1., 0.],
+# [0., 0., 1.]])
+
+# Array of random values
+random = np.random.random((2, 2))
+
+# Diagonal
+np.diag([1, 2, 3])
+#array([[1, 0, 0],
+# [0, 2, 0],
+# [0, 0, 3]])
+```
+
+## Indexing, Slicing and Views
+
+### Accessing Array Elements
+
+Array elements can be accessed using square brackets, similar to Python lists:
+
+```python
+# Accessing elements
+print(arr1[0]) # First element of arr1
+print(arr2[1, 2]) # Element at row 1, column 2 of arr2
+```
+
+### Slicing Arrays
+
+You can extract a subset of an array using slicing:
+
+```python
+# Slicing a 1D array
+slice1 = arr1[1:4] # Elements from index 1 to 3
+
+# Slicing a 2D array
+slice2 = arr2[:, 1:3] # All rows, columns 1 and 2
+```
+
+### Boolean Indexing
+
+Boolean indexing allows you to select elements based on a condition:
+
+```python
+bool_idx = arr1> 2
+print(arr1[bool_idx]) # Elements greater than 2
+```
+
+### Views
+
+A view in NumPy is a way of looking at the same data stored in an array from different perspectives. Views are created using slicing or other functions and do not copy the underlying data. Instead, they create a new array object that shares the same data buffer as the original array.
+
+```python
+arr = np.array([[1, 2], [3, 4], [5, 6]])
+view = arr.view()
+print(view)
+# Output:
+# [[1 2]
+# [3 4]
+# [5 6]]
+```
+
+#### Assignment vs View
+
+Assignment:
+
+```python
+import numpy as np
+
+arr = np.array([[1, 2], [3, 4], [5, 6]])
+assigned = arr
+print(arr is assigned) # Output: True
+```
+
+View:
+
+```python
+view = arr.view()
+print(arr is view) # Output: False
+print(view.base is arr) # Output: True
+```
+
+- **Assignment**: Simply references the same object.
+- **.view()**: Creates a new array object that views the same data.
+
+#### Making a view read-only
+
+A view in NumPy is not read-only. Modifying the view will modify the original array since they share the same data buffer. If you need a read-only version of the array, you can use the flags attribute to set the WRITEABLE flag to False.
+
+```python
+import numpy as np
+
+arr = np.array([[1, 2], [3, 4], [5, 6]])
+view = arr.view()
+view.flags.writeable = False
+
+try:
+ view[0, 0] = 10
+except ValueError as e:
+ print(e) # Output: assignment destination is read-only
+```
+
+## Operations on Arrays
+
+### Basic Arithmetic
+
+NumPy supports element-wise arithmetic operations:
+
+```python
+# Element-wise addition
+sum_arr = arr1 + 1
+
+# Element-wise subtraction
+diff_arr = arr1 - 1
+
+# Element-wise multiplication
+prod_arr = arr1 * 2
+
+# Element-wise division
+quot_arr = arr1 / 2
+```
+
+Once you have created arrays, you can replicate, join, or mutate those existing arrays to create new arrays. When you assign an array or its elements to a new variable, you have to explicitly numpy.copy the array, otherwise the variable is a view into the original array. Consider the following example:
+
+```python
+a = np.array([1, 2, 3, 4, 5, 6])
+b = a[:2]
+b += 1
+print('a =', a, '; b =', b) # a = [2 3 3 4 5 6] ; b = [2 3]
+```
+
+### Universal Functions (ufuncs)
+
+NumPy provides many mathematical functions, called ufuncs, that operate element-wise on arrays:
+
+```python
+# Square root
+sqrt_arr = np.sqrt(arr1)
+
+# Exponential
+exp_arr = np.exp(arr1)
+
+# Sine
+sin_arr = np.sin(arr1)
+
+# Logarithm
+log_arr = np.log(arr1)
+```
+
+### Aggregation Functions
+
+NumPy provides functions to perform various aggregations:
+
+```python
+print(np.sum(arr1)) # Sum of all elements
+print(np.mean(arr1)) # Mean of all elements
+print(np.std(arr1)) # Standard deviation of all elements
+print(np.min(arr1)) # Minimum element
+print(np.max(arr1)) # Maximum element
+print(np.prod(arr1)) # Product of all elements
+```
+
+### Dot Product and Matrix Multiplication
+
+NumPy supports both element-wise multiplication and matrix multiplication:
+
+```python
+# Element-wise multiplication
+elem_mult = arr1 * arr1
+
+# Dot product
+dot_prod = np.dot(arr1, arr1)
+
+# Matrix multiplication
+mat_mult = np.matmul(arr2, arr2.T)
+```
+
+## Reshaping and Flattening Arrays
+
+### Reshaping Arrays
+
+You can change the shape of an array using the reshape method:
+
+```python
+arr = np.array([1, 2, 3, 4, 5, 6])
+reshaped = arr.reshape((2, 3))
+print(reshaped)
+```
+
+Output:
+```
+[[1 2 3]
+ [4 5 6]]
+```
+
+### Flattening Arrays
+
+Flattening an array converts it to a 1D array:
+
+```python
+flattened = arr2.flatten()
+```
+
+## Advanced Topics
+
+### Vectorization
+
+Vectorization is the process of converting iterative operations to array operations, which are much faster:
+
+```python
+# Without vectorization
+result = np.zeros_like(arr1)
+for i in range(len(arr1)):
+ result[i] = arr1[i] + 1
+
+# With vectorization
+result = arr1 + 1
+```
+
+## Data Types in NumPy
+
+### Importance of Data Types
+
+Choosing the correct data type for your arrays can impact both performance and memory usage. NumPy supports a wide range of data types, allowing you to optimize for specific needs.
+
+### Common Data Types
+
+- `int8, int16, int32, int64`: Signed integer types with different bit-widths.
+- `uint8, uint16, uint32, uint64`: Unsigned integer types with different bit-widths.
+- `float16, float32, float64`: Floating-point types with different precision.
+
+### Specifying Data Types
+
+You can specify the data type when creating an array:
+
+```python
+arr_int = np.array([1, 2, 3], dtype=np.int32)
+arr_float = np.array([1.0, 2.0, 3.0], dtype=np.float64)
+```
+
+### Type Conversion
+
+You can convert between data types using the astype method:
+
+```python
+arr = np.array([1, 2, 3], dtype=np.int32)
+arr_float = arr.astype(np.float64)
+print(arr_float)
+```
+
+### Errors
+
+When you use numpy.array to define a new array, you should consider the dtype of the elements in the array, which can be specified explicitly. This feature gives you more control over the underlying data structures and how the elements are handled in C/C++ functions. When values do not fit and you are using a dtype, NumPy may raise an error:
+
+```python
+np.array([127, 128, 129], dtype=np.int8)
+# OverflowError: Python integer 128 out of bounds for int8
+```
+
+## Iterating
+
+### Basic Iteration
+
+```python
+import numpy as np
+
+arr = np.array([1, 2, 3, 4])
+for element in arr:
+ print(element)
+```
+
+Or using indexes:
+
+```python
+for i in range(arr.shape[0]):
+ for j in range(arr.shape[1]):
+ for k in range(arr.shape[2]):
+ print(arr[i, j, k])
+```
+
+### Using `np.nditer()`
+
+`np.nditer()` provides an efficient way to iterate over all elements in a multi-dimensional array:
+
+```python
+arr = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
+for x in np.nditer(arr):
+ print(x)
+```
+
+### Using `np.ndenumerate()`
+
+`np.ndenumerate()` is another method that provides both the index and the value:
+
+```python
+for index, value in np.ndenumerate(arr):
+ print(index, value)
+```
+
+## Searching for Items
+
+## Using `np.all()`
+
+`np.all()` checks if all elements along a given axis evaluate to `True`:
+
+```python
+arr2 = np.array([[1, 2, 3], [4, 5, 6]])
+result = np.all(arr2> 0)
+print(result) # Output: True
+```
+
+### Using `np.any()`
+
+`np.any()` checks if any elements along a given axis evaluate to `True`:
+
+```python
+import numpy as np
+
+arr = np.array([1, 2, 3, -4])
+result = np.any(arr < 0) +print(result) # Output: True +``` + +### Using `np.where()` + +`np.where()` returns the indices of elements that meet a condition: + +```python +arr = np.array([1, 2, 3, 4]) +indices = np.where(arr> 2)
+print(indices)
+# Output: (array([2, 3]),)
+```
+
+Using np.where to choose elements:
+
+```
+result = np.where(arr> 2, arr, -1)
+print(result)
+# Output: [-1 -1 3 4]
+```
+
+- **Condition: arr> 2**
+ - This creates a boolean array where each element is True if the corresponding element in arr is greater than 2, and - False otherwise.
+- **Selection: np.where(arr> 2, arr, -1)**
+ - If the condition is True, the element from arr is selected.
+ - If the condition is False, -1 is selected
+
+### Using `np.argwhere()`
+
+`np.argwhere()` returns the indices of elements that meet a condition, but the output is formatted as a 2D array with each row being the index of an element.
+
+```python
+import numpy as np
+
+arr = np.array([[1, 2, 3],
+ [4, 5, 6],
+ [7, 8, 9]])
+
+indices = np.argwhere(arr> 5)
+print(indices)
+# Output: [[1, 2]
+# [2, 0]
+# [2, 1]
+# [2, 2]]
+```
+
+- The element at index [2, 0] (7) is greater than 5.
+- The element at index [1, 2] (6) is greater than 5.
+- The element at index [2, 1] (8) is greater than 5.
+- The element at index [2, 2] (9) is greater than 5.
+
+## Joining Arrays
+
+### Using `np.concatenate()`
+
+`np.concatenate()` joins a sequence of arrays along an existing axis.
+
+Example: Concatenating 1D Arrays
+
+```python
+import numpy as np
+
+arr1 = np.array([1, 2, 3])
+arr2 = np.array([4, 5, 6])
+result = np.concatenate((arr1, arr2))
+print(result) # Output: [1 2 3 4 5 6]
+```
+
+Example: Concatenating 2D Arrays
+
+```python
+arr1 = np.array([[1, 2], [3, 4]])
+arr2 = np.array([[5, 6]])
+
+concat_axis0 = np.concatenate((arr1, arr2), axis=0)
+print(concat_axis0)
+# Output:
+# [[1 2]
+# [3 4]
+# [5 6]]
+
+concat_axis1 = np.concatenate((arr1, arr2.T), axis=1)
+print(concat_axis1)
+# Output:
+# [[1 2 5]
+# [3 4 6]]
+```
+
+The axis parameter is used in many NumPy functions to specify the dimension along which the operation should be performed. It helps control whether the operation is applied across rows, columns, or other dimensions in a multi-dimensional array.
+
+- `Axis 0`: Refers to the vertical direction (down the rows).
+- `Axis 1`: Refers to the horizontal direction (across the columns).
+
+```python
+sum_axis0 = np.sum(arr, axis=0)
+print(sum_axis0) # Output: [12 15 18]
+```
+
+
+### Using `np.stack()`
+
+`np.stack()` joins a sequence of arrays along a new axis.
+
+```python
+arr1 = np.array([1, 2, 3])
+arr2 = np.array([4, 5, 6])
+result = np.stack((arr1, arr2), axis=1)
+print(result)
+# Output:
+# [[1 4]
+# [2 5]
+# [3 6]]
+```
+
+### Using `np.hstack()` and `np.vstack()`
+
+`np.hstack()` stacks arrays in sequence horizontally (column-wise) and `np.vstack()` stacks arrays in sequence vertically (row-wise).
+
+Example: Horizontal Stacking
+
+```python
+arr1 = np.array([1, 2, 3])
+arr2 = np.array([4, 5, 6])
+result = np.hstack((arr1, arr2))
+print(result) # Output: [1 2 3 4 5 6]
+```
+
+Example: Vertical Stacking
+
+```python
+result = np.vstack((arr1, arr2))
+print(result)
+# Output:
+# [[1 2 3]
+# [4 5 6]]
+```
+
+## Copying Arrays
+
+### Using `np.copy()`
+
+Creates a deep copy of the array. Modifying the copy does not affect the original array.
+
+```python
+arr = np.array([1, 2, 3])
+arr_copy = np.copy(arr)
+arr_copy[0] = 10
+print(arr) # Output: [1 2 3]
+print(arr_copy) # Output: [10 2 3]
+```
+
+### Using `.copy()`
+
+Another method to create a deep copy is using the copy method of the array object.
+
+```python
+arr = np.array([1, 2, 3])
+arr_copy = arr.copy()
+arr_copy[0] = 10
+print(arr) # Output: [1 2 3]
+print(arr_copy) # Output: [10 2 3]
+```
+
+### Shallow Copy
+
+A shallow copy creates a new array object but does not copy the elements, instead, it references the original array's elements. This is typically done via assignment.
+
+```python
+arr = np.array([1, 2, 3])
+arr_shallow_copy = arr
+arr_shallow_copy[0] = 10
+print(arr) # Output: [10 2 3]
+print(arr_shallow_copy) # Output: [10 2 3]
+```
+
+## Sorting
+
+### Using `np.sort()`
+
+`np.sort()` returns a sorted copy of an array.
+
+```python
+import numpy as np
+
+arr = np.array([3, 1, 2])
+sorted_arr = np.sort(arr)
+print(sorted_arr) # Output: [1 2 3]
+```
+
+or
+
+```python
+arr.sort()
+print(arr) # Output: [1 2 3]
+```
+
+### Sorting Along an Axis
+
+You can specify the axis along which to sort.
+Axis=0:
+
+```python
+arr2 = np.array([[3, 2, 1], [6, 5, 4], [2, 3, 9]])
+sorted_arr2 = np.sort(arr2, axis=0)
+print(sorted_arr2)
+# Output:
+# [[2 2 1]
+# [3 3 4]
+# [6 5 9]]
+```
+
+Axis=1:
+
+```python
+arr2 = np.array([[3, 2, 1], [6, 5, 4]])
+sorted_arr2 = np.sort(arr2, axis=1)
+print(sorted_arr2)
+# Output:
+# [[1 2 3]
+# [4 5 6]]
+```
+
+### Indirect Sorting Using `np.argsort()`
+
+`np.argsort()` returns the indices that would sort an array. Useful for sorting based on another array.
+
+```python
+arr = np.array([3, 1, 2])
+indices = np.argsort(arr)
+print(indices) # Output: [1 2 0]
+sorted_arr = arr[indices]
+print(sorted_arr) # Output: [1 2 3]
+```
+
+### Sorting with a Key Using `np.lexsort()`
+
+np.lexsort() performs an indirect sort using a sequence of keys.
+
+```python
+names = np.array(['John', 'Paul', 'George', 'Ringo'])
+heights = np.array([180, 175, 178, 172])
+indices = np.lexsort((heights, names))
+print(names[indices])
+# Output: ['George' 'John' 'Paul' 'Ringo']
+```
\ No newline at end of file
diff --git a/guide/extentions/_index.md b/guide/extentions/_index.md
deleted file mode 100644
index 92f8b6f..0000000
--- a/guide/extentions/_index.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Index
-
-todo
\ No newline at end of file
diff --git a/guide/general/_index.md b/guide/general/_index.md
deleted file mode 100644
index 39ed39f..0000000
--- a/guide/general/_index.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# Index
-
-- [Strings](strings.md)
-- [Creating Functions](creating_functions.md)
-- [Typing](typing.md)
-- [Scopes and References](scopes_and_references.md)
-- [Flow Control](flow_control.md)
-- [Exceptions](exceptions.md)
-- [Lambdas](lambdas.md)
-- [Generics](generics.md)
-- [Callable](callable.md)
\ No newline at end of file
diff --git a/guide/general/enum.md b/guide/general/enum.md
new file mode 100644
index 0000000..0ed6984
--- /dev/null
+++ b/guide/general/enum.md
@@ -0,0 +1,276 @@
+# Enum
+
+## Introduction
+
+Enum, short for enumeration, is a data type in Python that enables the creation of named constant values. Introduced in Python 3.4 with the enum module, it allows for the creation of symbolically named values which are immutable and unique.
+
+## Why Use Enum?
+
+- **Readability**: Enums make code more readable and expressive by using meaningful names instead of magic numbers or strings.
+- **Uniqueness**: Each Enum member is distinct and cannot be duplicated, reducing errors from using identical values for different constants.
+- **Immutable**: Enum members are immutable, ensuring consistency throughout the code.
+
+## Basic Usage
+
+### Creating an Enum:
+
+```python
+from enum import Enum
+
+class Color(Enum):
+ RED = 1
+ GREEN = 2
+ BLUE = 3
+```
+
+### Accessing Enum Members:
+
+```python
+my_color = Color.RED
+print(my_color) # Output: Color.RED
+```
+
+### Comparison:
+
+```python
+if favorite_color is Color.RED:
+ print("It's red!")
+```
+
+### Iteration:
+
+```python
+for color in Color:
+ print(color)
+```
+
+### name & value Property
+
+- The `name` property of an Enum member returns the name of the member as it is defined in the Enum class.
+- The `value` property returns the value assigned to the enum member.
+
+```python
+from enum import Enum
+
+class Color(Enum):
+ RED = 1
+ GREEN = 2
+ BLUE = 3
+
+print(Color.RED.name) # Output: 'RED'
+print(Color.RED.value) # Output: 1
+```
+
+The Enum class provides a special method `__getitem__` that allows you to access the members of the enum by passing the name of the member as a string inside square brackets `[]`. This is similar to how you would access the value of a dictionary by key.
+
+```python
+print(Color['RED']) # This is valid and returns Color.RED
+print(Color['red']) # This raises KeyError
+```
+
+## Basic Customization
+
+In the simplest form, customizing values in an Enum involves directly assigning unique values to each member. These values can be of any data type β numbers, strings, tuples, objects, etc.
+
+Using strings:
+
+```python
+from enum import Enum
+
+class Color(Enum):
+ RED = 'red'
+ GREEN = 'green'
+ BLUE = 'blue'
+```
+
+Using dictionary:
+
+```python
+from enum import Enum
+
+class Status(Enum):
+ ACTIVE = {'my_cool_id': 1, 'description': 'The entity is active'}
+ INACTIVE = {'my_cool_id': 2, 'description': 'The entity is inactive'}
+
+status_code = Status.ACTIVE.value['my_cool_id']
+status_description = Status.ACTIVE.value['description']
+
+print(f"Code: {status_code}, Description: {status_description}")
+# Output: Code: 1, Description: The entity is active
+```
+
+Using Functions:
+
+```python
+class Weekday(Enum):
+ MONDAY = (lambda x: x**2)(1)
+ TUESDAY = (lambda x: x**2)(2)
+ # And so on...
+```
+
+## Custom Value Methods
+
+You can define methods in the Enum class to interact with the custom values. For instance, if you have complex data types as values, you might want methods to access or manipulate these data.
+
+```python
+class Planet(Enum):
+ MERCURY = (1, 'Mercury')
+ VENUS = (2, 'Venus')
+ EARTH = (3, 'Earth')
+
+ def __init__(self, planet_id, name):
+ self.planet_id = planet_id
+ self.name = name
+
+ def get_info(self):
+ return f"{self.name} (ID: {self.planet_id})"
+```
+
+## Auto-Assigning Values:
+
+Python's `auto()` function can be used to automatically generate values for each Enum member. This is useful when the specific values are not important, and you just need unique identifiers for each member.
+
+```python
+from enum import Enum, auto
+
+class Color(Enum):
+ RED = auto()
+ GREEN = auto()
+ BLUE = auto()
+```
+
+## All Enum Types
+
+### Enum
+
+This is the basic Enum type. It's used to create enumerations, which are sets of symbolic names bound to unique, constant values.
+
+```python
+from enum import Enum
+
+class Color(Enum):
+ RED = 1
+ GREEN = 2
+ BLUE = 3
+```
+
+### IntEnum
+
+This is a specialized enumeration that inherits from both Enum and int. The members of an `IntEnum` are also instances of int. It's useful when you need integer constants that should behave as enumeration members.
+
+```python
+from enum import IntEnum
+
+class Priority(IntEnum):
+ LOW = 1
+ MEDIUM = 2
+ HIGH = 3
+```
+
+### IntFlag
+
+An extension of `IntEnum`, used for creating enumerations that can be combined using bitwise operations. It's particularly useful for sets of integer flags.
+
+```python
+from enum import IntFlag
+
+class Permissions(IntFlag):
+ READ = 1
+ WRITE = 2
+ EXECUTE = 4
+```
+
+
+#### Flag
+
+Similar to `IntFlag`, but not limited to integers. `Flag` members can be combined using bitwise operations and do not have to be integers.
+
+```python
+from enum import Flag, auto
+
+class Color(Flag):
+ RED = auto()
+ GREEN = auto()
+ BLUE = auto()
+ MAGENTA = RED | BLUE
+```
+
+### StrEnum (Python 3.11+)
+
+`StrEnum` is a variant of Enum where members are also instances of str. This is useful when the members need to behave as strings.
+
+```python
+from enum import StrEnum
+
+class Mood(StrEnum):
+ HAPPY = 'happy'
+ SAD = 'sad'
+ ANGRY = 'angry'
+```
+
+## `_missing_` Function
+
+Enum member names are always case-sensitive, which is by design to avoid confusion and to ensure that each member is distinctly identifiable. If you need to be able to access enum members without worrying about case sensitivity, you can implement the `_missing_` method for looking up values not found in `cls`. By default it does nothing, but can be overridden to implement custom search behavior:
+
+```python
+from enum import Enum
+
+class Color(Enum):
+ RED = 1
+ GREEN = 2
+ BLUE = 3
+
+ @classmethod
+ def _missing_(cls, name):
+ for member in cls:
+ if member.name.lower() == name.lower():
+ return member
+ # Raise a ValueError to indicate that there is no member with the given name.
+ raise ValueError(f"No member found for {name}")
+
+# Now you can access enum members case-insensitively:
+print(Color("RED")) # Color.RED
+print(Color("red")) # Color.RED
+print(Color("Green")) # Color.GREEN
+print(Color("blue")) # Color.BLUE
+```
+
+## Enum Decorators
+
+### The @unique Decorator
+
+The `@unique` decorator is used to ensure that all the values in an enumeration are unique; it will raise a ValueError if any value is repeated.
+
+```python
+from enum import Enum, unique
+
+@unique
+class Color(Enum):
+ RED = 1
+ GREEN = 2
+ BLUE = 3
+ # REPEAT = 1 # Uncommenting this line will raise a ValueError.
+```
+
+### Custom Verification Decorator (Python 3.11+)
+
+While Python's enum doesn't provide a `@verify` decorator, you could create your own custom decorator to verify other properties of the enum members. For instance, you might want to ensure that all enum values adhere to a certain format or constraint.
+
+Here's an example of how you might create a custom decorator to verify that all enum values are uppercase:
+
+```python
+from enum import Enum
+
+def verify_uppercase(enum_class):
+ for name, member in enum_class.__members__.items():
+ if name.upper() != name:
+ raise ValueError(f"Enum name {name} must be uppercase!")
+ return enum_class
+
+@verify_uppercase
+class Color(Enum):
+ RED = 1
+ GREEN = 2
+ BLUE = 3
+ # lowercase = 4 # Uncommenting this line will raise a ValueError.
+```
\ No newline at end of file
diff --git a/guide/networking/_index.md b/guide/networking/_index.md
deleted file mode 100644
index fc3a6cb..0000000
--- a/guide/networking/_index.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# Index
-
-- [Introduction To Networking](introduction.md)
-
-- sockets
- - Socket programming basics (TCP/UDP sockets).
- - Creating a socket server and client.
- - Handling multiple connections with select or selectors module.
-- http
- - requests
- - rest api
-- websockets
- - Introduction to WebSockets and how they differ from HTTP.
- - Creating WebSocket clients and servers.
-- working with network protocols
- - Overview of common network protocols (HTTP, FTP, SMTP, SSH).
- - Using Python libraries for protocol-specific tasks (e.g., ftplib, smtplib, paramiko for SSH).
-- network automation (netmiko, napalm, ansible, ...)
-- network security (ssl)
\ No newline at end of file
diff --git a/guide/networking/grpc.md b/guide/networking/grpc.md
new file mode 100644
index 0000000..b5b8649
--- /dev/null
+++ b/guide/networking/grpc.md
@@ -0,0 +1,3 @@
+# gRPC
+
+todo
\ No newline at end of file
diff --git a/guide/networking/http_requests.md b/guide/networking/http_requests.md
new file mode 100644
index 0000000..15afc2d
--- /dev/null
+++ b/guide/networking/http_requests.md
@@ -0,0 +1,360 @@
+# HTTP Requests
+
+## Introduction to HTTP Requests
+
+### Overview of HTTP
+
+HTTP (Hypertext Transfer Protocol) is the foundational protocol used by the World Wide Web. It defines how messages are formatted and transmitted, and what actions web servers and browsers should take in response to various commands. HTTP uses a client-server model where the client (usually a web browser) requests resources (like HTML documents, images, etc.), and the server provides these resources, often interacting with backend systems to deliver dynamic content.
+
+### HTTP Request Basics
+
+An HTTP request is made by a client to request an action on a resource (identified by a URL) on a server. Each request consists of the following parts:
+
+- **Method**: An HTTP method, often called a verb, indicates the desired action to be performed on the resource. The common methods include GET, POST, PUT, DELETE, PATCH, etc.
+
+- **URL** (Uniform Resource Locator): The address of the resource on the server.
+
+- **Headers**: Provide additional information (metadata) about the request or about the client itself. For example, Content-Type header tells the server about the format of the data in the request body.
+
+- **Body (optional)**: Contains data sent to the server. This part is optional and usually used with methods like POST or PUT.
+
+#### Example:
+
+- The following request creates a new user with the provided name and email.
+- The Content-Type: application/json header indicates that the data being sent is in JSON format.
+
+Request line (Method + URL):
+
+```
+POST /api/users HTTP/1.1
+```
+
+Header:
+
+```
+Host: exampleapi.com
+Content-Type: application/json
+```
+
+Body:
+
+```
+{
+ "name": "Jane Doe",
+ "email": "jane.doe@example.com"
+}
+```
+
+## Types of HTTP Requests
+
+HTTP methods are used to specify the desired action to be performed on a given resource. Each method has a specific, defined purpose and plays a crucial role in the interaction between the client and the server. Here's a more detailed look at the key HTTP methods:
+
+- **GET**: Requests data from a specified resource. GET requests should only retrieve data and have no other effect.
+- **POST**: Sends data to the server to create a new resource. Data is included in the body of the request.
+- **PUT**: Sends data to update an existing resource. The PUT method is idempotent, meaning that sending the same request multiple times will not have different effects.
+- **DELETE**: Removes the specified resource.
+- **PATCH**: Applies partial modifications to a resource.
+
+### Response to an HTTP Request
+
+After the server processes an HTTP request, it returns an HTTP response. The response typically contains:
+
+- **Status Code**: Indicates the outcome of the request. For example, 200 OK for success, 404 Not Found for an invalid URL, and 500 Internal Server Error for server errors.
+
+- **Response Headers**: Similar to request headers, these headers provide information about the server and about the response.
+
+- **Response Body**: Contains the resource data requested by the client or a message body.
+
+### About HTTP Methods:
+
+#### GET
+
+- **Purpose**: The GET method is used to retrieve data from a server at a specified resource.
+- **Usage**: When you make a GET request, you are asking the server to send back the data for the specified resource. This is the most common HTTP method.
+- **Characteristics**:
+ - **Safe**: It does not alter the state of the resource (read-only).
+ - **Idempotent**: Multiple identical requests will have the same effect as a single request.
+- **Example**: Get a list of books from a bookstore API: `GET /api/books`.
+- **Response**:
+ ```json
+ [
+ {"id": 1, "title": "1984", "author": "George Orwell"},
+ {"id": 2, "title": "To Kill a Mockingbird", "author": "Harper Lee"}
+ ]
+ ```
+
+#### POST
+
+- **Purpose**: The POST method is used to send data to the server to create a new resource.
+- **Usage**: It's commonly used when submitting form data or uploading a file. POST requests usually carry payload data in the request body.
+- **Characteristics**:
+ - **Not Safe**: It changes the server state by creating a new resource.
+ - **Not Idempotent**: Making several identical POST requests will result in multiple resources being created.
+- **Example**: Add a new book to the bookstore.
+ ```json
+ POST /api/books
+ Content-Type: application/json
+ {
+ "title": "The Great Gatsby",
+ "author": "F. Scott Fitzgerald"
+ }
+ ```
+- **Respone**:
+ ```python
+ {
+ "id": 3,
+ "title": "The Great Gatsby",
+ "author": "F. Scott Fitzgerald"
+ }
+ ```
+
+#### PUT
+
+- **Purpose**: PUT is used to update an existing resource or create a new resource if it does not exist. It usually includes the full data of the resource.
+- **Usage**: The client sends data that updates the entire resource at the specified URI.
+- **Characteristics**:
+ - **Not Safe**: It modifies the server state.
+ **Idempotent**: Repeated requests with the same data will result in the same state of the resource (e.g., updating a user's details).
+- **Example**: Update information about a book.
+ ```json
+ PUT /api/books/3
+ Content-Type: application/json
+ {
+ "title": "The Great Gatsby",
+ "author": "F. Scott Fitzgerald",
+ "year": 1925
+ }
+ ```
+- **Response**:
+```json
+{
+ "id": 3,
+ "title": "The Great Gatsby",
+ "author": "F. Scott Fitzgerald",
+ "year": 1925
+}
+```
+
+#### PATCH
+
+- **Purpose**: PATCH is used for modifying an existing resource, but it updates only the specified parts of the resource, not the entire resource.
+- **Usage**: This is particularly useful for large resources, where you may want to update just a part of the resource.
+- **Characteristics**:
+ - **Not Safe**: It modifies the server state.
+ - **Idempotent**: Applying the same PATCH request multiple times will result in the same resource state.
+- **Example**: Update the year of a particular book.
+ ```json
+ PATCH /api/books/3
+ Content-Type: application/json
+ {
+ "year": 2023
+ }
+ ```
+- **Response**:
+ ```json
+ {
+ "id": 3,
+ "title": "The Great Gatsby",
+ "author": "F. Scott Fitzgerald",
+ "year": 2023
+ }
+ ```
+
+#### DELETE
+
+- **Purpose**: DELETE is used to remove a resource from the server.
+- **Usage**: It is a straightforward method used when you want to delete the resource identified by the request URI.
+- **Characteristics**:
+ - **Not Safe**: It changes the server state by removing the resource.
+ - **Idempotent**: Deleting the same resource multiple times results in the same outcome, the resource is removed.
+- **Example**: Delete a book from the bookstore. `DELETE /api/books/3`
+- **Response**: Response: Usually, DELETE requests might not return a body. Instead, they might return a status code like 204 No Content to indicate successful deletion.
+
+## REST API and RESTful API
+
+### What is REST?
+
+REST (Representational State Transfer) API is a set of guidelines and best practices for creating scalable web services. REST APIs are designed around the use of standard HTTP protocols and methods to make requests and receive responses. In a RESTful system, resources (like data or objects) are represented and manipulated using these standard HTTP methods.
+
+### RESTful API
+
+A RESTful API adheres to the REST architectural style and constraints. These APIs are characterized by their use of standard HTTP methods, ability to operate over any protocol that provides standard HTTP semantics (like HTTPS), and their stateless nature.
+
+### Principles of REST
+
+- **Resource-Based**: In REST, everything is a resource, and each resource is accessed via a unique URI (Uniform Resource Identifier).
+
+- **Stateless Operations**: Each HTTP request from a client to a server must contain all the information needed to understand the request. The server does not store any client context between requests.
+
+- **Use of HTTP Methods**: REST APIs primarily use HTTP methods (GET, POST, PUT, PATCH, DELETE) to perform CRUD operations.
+
+- **Representation of Resources**: Resources are typically represented in formats like JSON or XML. When a client requests a resource, it receives the representation, not the resource itself.
+
+### How REST APIs Differ from HTTP
+
+While REST APIs use HTTP as a transport protocol, they are not merely a collection of HTTP requests. The difference lies in their architectural style and guiding principles:
+
+- **HTTP is the Protocol**: HTTP defines how messages are formatted and transmitted over the web, and how web servers and browsers should respond to various commands.
+
+- **REST is an Architectural Style**: REST is a set of constraints and principles applied to the design of web services, using HTTP for communication. It is a way of leveraging HTTP actions to make them meaningful in terms of CRUD operations.
+
+- **REST APIs are Designed for Resource Manipulation**: RESTful services are characterized by their approach to resource handling, adhering to a set of principles that make the web services scalable, simple, and modular.
+
+## Creating HTTP Requests in Python
+
+### Creating an Endpoint Server with Flask
+
+To handle HTTP requests in a RESTful manner, we need to create an endpoint server. This server will listen for HTTP requests (like GET and POST) and respond appropriately. The Flask module in Python is an excellent tool for this purpose because it's lightweight and easy to use, yet powerful enough for complex tasks.
+
+Installing Flask Library:
+
+```python
+pip install Flask
+```
+
+Create the Flask App:
+
+```python
+from flask import Flask, jsonify, request
+
+app = Flask(__name__)
+
+data: str = "value"
+
+@app.route('/data', methods=['GET'])
+def get_data():
+ return jsonify({'data': data})
+
+@app.route('/data', methods=['POST'])
+def post_data():
+ global data
+ request_data = request.get_json() # Get JSON data from request
+ if 'data' in request_data:
+ data = request_data['data'] # Update the global data variable
+ return jsonify({'message': 'Data updated successfully', 'new_data': data})
+ else:
+ return jsonify({'message': 'No data field in request'}), 400
+
+if __name__ == '__main__':
+ app.run(debug=True)
+```
+
+In this application:
+- The GET /users endpoint returns a list of users.
+- The POST /users endpoint adds a new user to the users dictionary.
+
+Running the Flask Application:
+- Execute the script to start the Flask server.
+- By default, Flask will run on http://127.0.0.1:5000/.
+
+### Creating HTTP Requests in Python Using requests Module
+
+Python's `requests` library is a popular choice for HTTP requests due to its simplicity and ease of use.
+
+Installing Requests Library:
+
+```python
+pip install requests
+```
+
+#### Making a GET Request
+
+To retrieve data (users) from your Flask server:
+
+```python
+import requests
+
+response = requests.get('http://127.0.0.1:5000/users')
+if response.status_code == 200:
+ print("Users:", response.json())
+else:
+ print("Failed to fetch users")
+```
+
+### Making a POST Request
+
+To add a new user:
+
+```python
+new_user = {"name": "Jane Doe", "email": "jane@example.com"}
+
+response = requests.post('http://127.0.0.1:5000/users', json=new_user)
+if response.status_code == 201:
+ print("User added:", response.json())
+else:
+ print("Failed to add user")
+```
+
+## Common Status Codes
+
+HTTP status codes are standardized responses in the Hypertext Transfer Protocol (HTTP) used to indicate the result of a client's request to a server. These status codes are part of the HTTP response sent by the server in response to a request made by the client. They are grouped into several classes, indicated by the first digit, and can provide quick insight into the outcome of the request. Here's an overview of the most common HTTP status codes:
+
+### 1xx: Informational Responses
+
+- **100 Continue**: The initial part of a request has been received, and the client should continue with the request or ignore it if it is already finished.
+
+### 2xx: Success
+
+- **200 OK**: The standard response for successful requests. The actual response will depend on the request method used.
+- **201 Created**: The request has been fulfilled, and a new resource has been created.
+- **202 Accepted**: The request has been accepted for processing, but the processing has not been completed.
+- **204 No Content**: The server successfully processed the request, but is not returning any content.
+
+### 3xx: Redirection
+
+- **301 Moved Permanently**: The requested resource has been permanently moved to a new URL provided by the Location header.
+- **302 Found**: The requested resource resides temporarily under a different URL.
+- **304 Not Modified**: Indicates that the resource has not been modified since the last request.
+
+### 4xx: Client Errors
+
+- **400 Bad Request**: The server cannot or will not process the request due to a client error (e.g., malformed request syntax).
+- **401 Unauthorized**: Authentication is required, and the client has failed to provide it.
+- **403 Forbidden**: The client does not have permission to access the requested resource.
+- **404 Not Found**: The requested resource could not be found.
+- **405 Method Not Allowed**: The request method is not supported for the requested resource.
+
+### 5xx: Server Errors
+
+- **500 Internal Server Error**: A generic error message indicating an unexpected condition encountered by the server.
+- **501 Not Implemented**: The server does not support the functionality required to fulfill the request.
+- **503 Service Unavailable**: The server is currently unable to handle the request due to temporary overloading or maintenance.
+
+## Error Handling in RESTful APIs
+
+TODO
+TODO
+TODO
+
+## Authentication and Authorization
+
+TODO
+TODO
+TODO
+
+- Basic Authentication
+- Token-Based Authentication (JWT)
+
+## HTTPS Security Practices
+
+TODO
+TODO
+TODO
+
+## API Versioning
+
+TODO
+TODO
+TODO
+
+## Rate Limiting
+
+TODO
+TODO
+TODO
+
+## Representational State Transfer (REST) vs. Other Architectures
+
+TODO
+TODO
+TODO
\ No newline at end of file
diff --git a/guide/oop/_index.md b/guide/oop/_index.md
deleted file mode 100644
index d51a2aa..0000000
--- a/guide/oop/_index.md
+++ /dev/null
@@ -1,14 +0,0 @@
-# Index
-
-- [About Classes](classes.md)
-- [Creating Classes](creating_classes.md)
-- [Magic Methods](magic_methods.md)
-- [Properties](properties.md)
-- [Naming Conventions](naming_conventions.md)
-- [Static Methods](static_methods.md)
-- [Class Methods](class_methods.md)
-- [Data Classes](dataclasses.md)
-- [Decorators](decorators.md)
-- [Inheritance](inheritance.md)
-- [Abstract](abstract.md)
-- [Final](final.md)
\ No newline at end of file
diff --git a/guide/packages/_index.md b/guide/packages/_index.md
deleted file mode 100644
index c4afe5a..0000000
--- a/guide/packages/_index.md
+++ /dev/null
@@ -1,9 +0,0 @@
-# Index
-
-- [Namespaces](namespaces.md)
-- [Modules](modules.md)
-- [Creating Packages](packages.md)
-- [Packaging](packaging.md)
-- [Package Data](package_data.md)
-- [Versioning](versioning.md)
-- [Environments](environments.md)
diff --git a/guide/scripting/_index.md b/guide/scripting/_index.md
deleted file mode 100644
index 207f759..0000000
--- a/guide/scripting/_index.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# Index
-
-- [About Scripting](about.md)
-- [File Handling](file_handling.md)
-- [Logging](logging.md)
-- [Subprocesses](subprocess.md)
-- [Environment Variables](env_variables.md)
-- [Shebang](shebang.md)
-- [Click](click.md)
-- [Security](security.md)
-- [Cross Platform](cross_platform.md)
diff --git a/guide/testing/_index.md b/guide/testing/_index.md
deleted file mode 100644
index 1d54cdb..0000000
--- a/guide/testing/_index.md
+++ /dev/null
@@ -1,6 +0,0 @@
-# Index
-
-todo
-
-- unittest
-- pytest
\ No newline at end of file
diff --git a/guide/tooling/_index.md b/guide/tooling/_index.md
deleted file mode 100644
index 649c9b9..0000000
--- a/guide/tooling/_index.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# Index
-
-todo
-
-- mypy
-- ruff
- - vs isort
- - vs flake8
- - vs black
- - vs pylint
- - https://docs.astral.sh/ruff/faq/#how-does-ruff-determine-which-of-my-imports-are-first-party-third-party-etc
-- bandit
-- pyarmor
-- pydocstyle
-- sphinx
\ No newline at end of file