From a191af7d89c082a0cd1120d94bda5b270fa0342f Mon Sep 17 00:00:00 2001 From: Ben Boonstra Date: Tue, 22 Oct 2024 15:14:50 -0500 Subject: [PATCH] Add technicals to [docs] --- docs/docs/advanced-usage.html | 94 ++++------- docs/docs/index.html | 19 ++- docs/docs/technical/config.html | 151 +++++++++++++++++ docs/docs/technical/db.html | 265 ++++++++++++++++++++++++++++++ docs/docs/technical/fields.html | 36 ++++ docs/docs/technical/technical.css | 143 ++++++++++++++++ docs/docs/technical/technical.js | 47 ++++++ 7 files changed, 693 insertions(+), 62 deletions(-) create mode 100644 docs/docs/technical/config.html create mode 100644 docs/docs/technical/db.html create mode 100644 docs/docs/technical/fields.html create mode 100644 docs/docs/technical/technical.css create mode 100644 docs/docs/technical/technical.js diff --git a/docs/docs/advanced-usage.html b/docs/docs/advanced-usage.html index 0a31292..76793a4 100644 --- a/docs/docs/advanced-usage.html +++ b/docs/docs/advanced-usage.html @@ -15,35 +15,44 @@

Advanced Usage

For those who want more control and advanced features, - Effortless offers powerful capabilities. Here's how to use + Effortless offers powerful capabilities. You should have a + strong understanding of Python for this! Here's how to use Effortless with advanced features:

-

Importing Advanced Components

-

- Start by importing the necessary advanced components from - Effortless: -

+

You'll Need These

from effortless import EffortlessDB, EffortlessConfig, Field, Query

Creating a Custom Database Instance

-

Create a new Effortless instance with a custom directory:

+

+ You can create a Effortless instances with custom directories + and filenames. +

db = EffortlessDB("advanced_db") db.set_directory("/path/to/custom/directory")
-

- Change "/path/to/custom/directory" to the path of where you'd - like the db to be stored. -

+

Configuring the Database

+

You can futher customize the database with a configuration:

+ +
+ config = EffortlessConfig() + config.readonly = True + db.configure(config) + # The database contents are now read-only + db.add({"Anything": "will not work"}) # Raises an error +
-

Adding Multiple Entries

-

Add multiple entries with more complex data structures:

+

Adding Entries

+

+ You can put pretty much anything in an entry, and Effortless + will interperet structures like dates, lists, etc. +

db.add({"id": 1, "name": "Eve", "skills": ["Python", "JavaScript"], "joined": "2023-01-15"}) @@ -52,70 +61,41 @@

Adding Multiple Entries

Complex Filtering

-

Use advanced filtering techniques to find specific entries:

+

+ Use advanced filtering techniques with Fields to find specific + entries. For example, to find anyone who knows Python and joined + in Jan/Feb: +

- python_devs = db.filter( + db.filter( ‎ Field("skills").contains("Python") & ‎ Field("joined").between_dates("2023-01-01", "2023-02-28") ) - print(python_devs)

Batch Updates

-

- Use db.batch() to update multiple entries that - match a condition: -

+

You can update multiple entries that match a condition:

- updated_count = db.batch( + db.batch( ‎ {"status": "experienced"}, ‎ Field("skills").contains("Python") & Field("joined").less_than("2023-03-01") ) - print(f"Updated {updated_count} entries")

Erasing Multiple Entries

- Use db.erase() to remove multiple entries that + You can also erase to remove multiple entries that match a condition:

- removed_count = db.erase(Field("skills").contains("Java")) - print(f"Removed {removed_count} entries") -
- -

Custom Queries

-

Create custom queries using the Query class:

- -
- custom_query = Query(lambda entry: len(entry["skills"]) > 1 and "Python" in entry["skills"]) - multi_skill_python_devs = db.filter(custom_query) - print(multi_skill_python_devs) -
- -

Configuring the Database

-

Update the database configuration for advanced settings:

- -
- db.configure(EffortlessConfig({"readonly": True})) - # The database contents are now read-only - db.add({"Anything": "will not work"}) # Raises an error + db.erase(Field("skills").contains("Java"))
-

Advanced Filtering Capabilities

-

Effortless 1.1 introduces powerful filtering capabilities:

- -
- result = db.filter( - ‎ (Field("age").greater_than(25) & Field("skills").contains("Python")) | - ‎ Field("name").startswith("A") - ) -
- -

You can also use custom functions with the `passes` method:

+

Custom conditions

+

You can write your own complex checks and use them in Field.passes().

def is_experienced(skills): @@ -124,12 +104,6 @@

Advanced Filtering Capabilities

result = db.filter(Field("skills").passes(is_experienced))
-

Check the type of a field:

- -
- result = db.filter(Field("age").is_type(int)) -
-

These advanced features allow you to create more complex database structures, perform intricate queries, and have finer diff --git a/docs/docs/index.html b/docs/docs/index.html index a5c74df..156fe06 100644 --- a/docs/docs/index.html +++ b/docs/docs/index.html @@ -16,12 +16,15 @@

Effortless Documentation

Welcome to the Effortless documentation. Here you'll find everything you need to know about using Effortless.

+

Never used Effortless?

Quickstart
- +

Done installing?

- Effortless Usage Effortless Documentation >Advanced Usage
+

Looking for technicals?

+
+ EffortlessDB + EffortlessConfig + Fields / Queries +
diff --git a/docs/docs/technical/config.html b/docs/docs/technical/config.html new file mode 100644 index 0000000..bd176a6 --- /dev/null +++ b/docs/docs/technical/config.html @@ -0,0 +1,151 @@ + + + + + + Effortless - Technical + + + + + + + + + +
+

EffortlessConfig

+

+ EffortlessConfig is the configuration class for EffortlessDB. It + holds various configuration options for an EffortlessDB + instance. +

+

Properties

+
+
+

debug

+

+ Enable debug mode. Defaults to False. +

+
+
+

requires

+

+ List of required fields for each entry. Defaults to an empty + list. +

+
+
+

+ max_size +

+

+ Maximum size of the database in MB. Defaults to None (no + limit). +

+
+
+

v

+

+ Version of the configuration. Always 1 for now. +

+
+
+

backup

+

+ Path to backup location. Defaults to None (no backup). +

+
+
+

backup_interval

+

+ Number of operations between backups. Defaults to 1. +

+
+
+

encrypted

+

+ Whether the database should be encrypted. Defaults to False. +

+
+
+

compressed

+

+ Whether the database should be compressed. Defaults to + False. +

+
+
+

readonly

+

+ Whether the database is in read-only mode. Defaults to + False. +

+
+
+

Methods

+
+
+

+ __init__ +

+

+ Initializes an EffortlessConfig instance with the given + configuration options. +

+ +
+ config = EffortlessConfig({"debug": True, "max_size": 100}) +
+
+
+

_validate

+

+ Validates the configuration values. Raises ValueError if any + configuration value is invalid. +

+
+
+

+ to_dict +

+

+ Converts the configuration to a dictionary representation. +

+ +
+ config_dict = config.to_dict() +
+
+
+

+ default_headers +

+

+ Creates a dictionary with default headers. Mainly used for + internal unit testing. +

+ +
+ default_headers = EffortlessConfig.default_headers() +
+
+
+ +
+ + diff --git a/docs/docs/technical/db.html b/docs/docs/technical/db.html new file mode 100644 index 0000000..0867967 --- /dev/null +++ b/docs/docs/technical/db.html @@ -0,0 +1,265 @@ + + + + + + Effortless - Technical + + + + + + + + + +
+

EffortlessDB

+

+ EffortlessDB is the main class for interacting with the + Effortless database. It provides methods for initializing, + configuring, and performing operations on the database. +

+

Properties

+
+
+

+ config +

+

+ An instance of EffortlessConfig that holds the configuration + settings for the database. +

+ +
db.config
+
+
+

Methods

+
+
+

+ __init__ +

+

+ Initializes an EffortlessDB instance with the given database + name. If no name is provided, it defaults to "db". +

+ +
+ db = EffortlessDB("my_database") +
+
+
+

+ set_directory +

+

+ Sets the directory for the database file. Raises TypeError + if the directory is not a string, and ValueError if the + directory is empty or does not exist. +

+ +
+ db.set_directory("/path/to/database/directory") +
+
+
+

+ set_storage +

+

+ Sets the storage file for the database. The actual file will + be named '{db_name}.effortless'. Raises TypeError if db_name + is not a string, and ValueError if it's empty or contains + invalid characters. +

+ +
+ db.set_storage("my_database") +
+
+
+

+ configure +

+

+ Updates the database configuration with a new + EffortlessConfig object. Raises TypeError if new_config is + not an EffortlessConfig object. +

+ +
+ db.configure(new_config) +
+
+
+

+ get_all +

+

+ Retrieves all records from the database, returning a list + where each entry is a record in the database. +

+ +
+ all_records = db.get_all() +
+
+
+

+ filter +

+

+ Filters the database records based on a given Query object, + returning a list of records that match the query criteria. +

+ +
+ filtered_records = db.filter(query) +
+
+
+

+ add +

+

+ Adds a new entry to the database. Raises TypeError if the + entry is not a dictionary, ValueError if a required field is + missing, if the entry is not JSON-serializable, or if adding + the entry would exceed the max size limit. +

+ +
+ db.add({"name": "John", "age": 30}) +
+
+
+

+ wipe +

+

+ Clears all data from the database, resetting it to its + initial state. If wipe_readonly is True, it allows wiping + even if the database is in read-only mode. +

+ +
db.wipe()
+
+
+

+ finish_backup +

+

+ Waits for any ongoing backup operation to complete. Returns + True if the backup completed (or there was no backup + running), False if the timeout was reached before the backup + completed. +

+ +
+ backup_completed = db.finish_backup(timeout=30) +
+
+
+

+ update +

+ +

+ Updates a single entry in the database that matches the + given condition. Returns True if an entry was updated, False + if no matching entry was found. Raises ValueError if more + than one entry matches the condition. +

+
+ updated = db.update({"age": 31}, Query().name == "John") +
+
+
+

+ batch +

+

+ Updates all entries in the database that match the given + condition. Returns the number of entries that were updated. +

+ +
+ updated_count = db.batch({"status": "active"}, Query().age > 18) +
+
+
+

+ remove +

+

+ Removes a single entry from the database that matches the + given condition. Returns True if an entry was removed, False + if no matching entry was found. Raises ValueError if more + than one entry matches the condition. +

+ +
+ removed = db.remove(Query().name == "John") +
+
+
+

+ erase +

+

+ Erases all entries from the database that match the given + condition. Returns the number of entries that were removed. +

+ +
+ erased_count = db.erase(Query().age < 18) +
+
+
+ +
+ + diff --git a/docs/docs/technical/fields.html b/docs/docs/technical/fields.html new file mode 100644 index 0000000..47b727e --- /dev/null +++ b/docs/docs/technical/fields.html @@ -0,0 +1,36 @@ + + + + + + Effortless - Technical + + + + + + + + + +
+

Fields

+

+ This page is currently under construction. Check back soon for detailed information about Fields in EffortlessDB. +

+

Properties

+
+

Properties information will be available soon.

+
+

Methods

+
+

Methods information will be available soon.

+
+ +
+ + + diff --git a/docs/docs/technical/technical.css b/docs/docs/technical/technical.css new file mode 100644 index 0000000..10e7e51 --- /dev/null +++ b/docs/docs/technical/technical.css @@ -0,0 +1,143 @@ +.technical-title { + color: var(--primary-color); + font-size: 2.5rem; + margin-bottom: 1.5rem; +} + +.prop-header, +.method-header { + color: var(--text-color); + font-size: 1.8rem; + margin-top: 2rem; + margin-bottom: 1rem; +} + +.prop-subheader, +.method-subheader { + color: var(--primary-color); + font-size: 1.4rem; + margin-top: 1.5rem; + margin-bottom: 0.5rem; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + width: fit-content; +} + +.prop-description, +.method-description { + margin-bottom: 1rem; + word-wrap: break-word; + max-width: 300px; + overflow-wrap: break-word; +} + +.property, +.method { + margin: 0px; + background-color: rgba(255, 255, 255, 0.05); + border-radius: 8px; + padding: 1rem; + margin-bottom: 1.5rem; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + border-left: 4px solid var(--tertiary-color); + transition: all 0.3s ease; + max-width: fit-content; +} + +.properties-container, +.methods-container { + display: flex; + flex-wrap: wrap; + gap: 1rem; + justify-content: center; + width: 100%; +} + +.property, +.method { + background-color: rgba(255, 255, 255, 0.05); + border-radius: 8px; + padding: 1rem; + margin-bottom: 0; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + border-left: 4px solid var(--tertiary-color); + transition: all 0.3s ease; + display: flexbox; + flex: auto; + max-width: 100%; + min-width: fit-content; + box-sizing: border-box; +} + +.property > *, +.method > * { + flex: 1 0 auto; + min-width: 0; +} + +.prop-subheader, +.method-subheader { + margin-top: 0; +} + +.example-usage { + margin-top: 10px; + border-left: 4px solid var(--primary-color); + word-break: break-word; +} + +.formatted-attr { + display: inline-block; + font-size: 0.8em; + margin-right: 10px; + padding: 2px 5px; + border-radius: 3px; +} + +.prop-type { + background-color: var(--primary-color); + color: var(--background-color); +} + +.method-parameters { + background-color: var(--primary-color); + color: var(--background-color); +} + +.method-returns { + background-color: var(--tertiary-color); + color: var(--background-color); +} + +@media (max-width: 768px) { + .technical-title { + font-size: 2rem; + } + + .prop-header, + .method-header { + font-size: 1.5rem; + } + + .prop-subheader, + .method-subheader { + font-size: 1.2rem; + } + + .property, + .method { + flex: 1 1 100%; + max-width: 100%; + } + + .example-usage { + font-size: 0.8rem; + } +} + +.property:hover, +.method:hover { + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); + transform: translateY(-2px); +} diff --git a/docs/docs/technical/technical.js b/docs/docs/technical/technical.js new file mode 100644 index 0000000..9cbe2e4 --- /dev/null +++ b/docs/docs/technical/technical.js @@ -0,0 +1,47 @@ +document.addEventListener("DOMContentLoaded", function () { + // Function to create formatted attribute display + function createFormattedAttribute(element, attrName, content) { + const formattedAttr = document.createElement("span"); + formattedAttr.className = `formatted-attr ${attrName}`; + formattedAttr.textContent = content; + if (attrName === "prop-type") { + element.insertBefore(formattedAttr, element.firstChild); + } else { + element.appendChild(formattedAttr); + } + } + + // Add formatted attributes for prop-type + document.querySelectorAll(".prop-subheader[prop-type]").forEach((prop) => { + const propType = prop.getAttribute("prop-type"); + createFormattedAttribute(prop, "prop-type", propType); + }); + + // Add formatted attributes for method-parameters + document + .querySelectorAll(".method-subheader[method-parameters]") + .forEach((method) => { + const params = method.getAttribute("method-parameters"); + if (params && params.trim() !== "") { + createFormattedAttribute( + method, + "method-parameters", + `(${params})` + ); + } + }); + + // Add formatted attributes for method-returns + document + .querySelectorAll(".method-subheader[method-returns]") + .forEach((method) => { + const returns = method.getAttribute("method-returns"); + if (returns && returns.trim() !== "") { + createFormattedAttribute( + method, + "method-returns", + `→ ${returns}` + ); + } + }); +});