Spaces:
Running
Running
# CosmicApp.py | |
import streamlit as st | |
from azure.cosmos import CosmosClient, exceptions | |
import os | |
import pandas as pd | |
import json | |
from datetime import datetime | |
import shutil | |
from github import Github | |
from git import Repo | |
import base64 | |
from dotenv import load_dotenv | |
# Load environment variables | |
load_dotenv() | |
# Cosmos DB configuration | |
ENDPOINT = os.getenv("ENDPOINT") | |
PRIMARY_KEY = os.getenv("PRIMARY_KEY") | |
# GitHub configuration | |
GITHUB_TOKEN = os.getenv("GITHUB_TOKEN") | |
# 🌟 Helper Functions Galore 🌟 | |
def download_github_repo(url, local_path): | |
""" | |
🌀 Clone a GitHub repo faster than a swirling vortex! | |
""" | |
if os.path.exists(local_path): | |
shutil.rmtree(local_path) | |
Repo.clone_from(url, local_path) | |
def create_repo(github_token, repo_name): | |
""" | |
🐣 Hatch a new GitHub repo like a pro! | |
""" | |
g = Github(github_token) | |
user = g.get_user() | |
return user.create_repo(repo_name) | |
def push_to_github(local_path, repo, github_token): | |
""" | |
🚀 Push your changes to GitHub at warp speed! | |
""" | |
repo_url = f"https://{github_token}@github.com/{repo.full_name}.git" | |
local_repo = Repo(local_path) | |
if 'origin' in [remote.name for remote in local_repo.remotes]: | |
origin = local_repo.remote('origin') | |
origin.set_url(repo_url) | |
else: | |
origin = local_repo.create_remote('origin', repo_url) | |
local_repo.git.add(A=True) | |
if local_repo.is_dirty(): | |
local_repo.git.commit('-m', 'Initial commit') | |
origin.push(refspec=f"{local_repo.active_branch.name}:{local_repo.active_branch.name}") | |
def get_base64_download_link(file_path, file_name): | |
""" | |
🔗 Get a base64 download link for instant gratification! | |
""" | |
with open(file_path, "rb") as file: | |
contents = file.read() | |
base64_encoded = base64.b64encode(contents).decode() | |
return f'<a href="data:application/zip;base64,{base64_encoded}" download="{file_name}">🛸 Download {file_name} 🛸</a>' | |
def fetch_db_structure(client): | |
""" | |
📂 Fetch the cosmic database structure—no telescope needed! | |
""" | |
structure = {} | |
for database in client.list_databases(): | |
db_name = database['id'] | |
structure[db_name] = [] | |
db_client = client.get_database_client(db_name) | |
for container in db_client.list_containers(): | |
structure[db_name].append(container['id']) | |
return structure | |
def fetch_items(client, db_name, container_name): | |
""" | |
🛰️ Fetch items from a container—beep boop! | |
""" | |
container = client.get_database_client(db_name).get_container_client(container_name) | |
items = list(container.read_all_items()) | |
return items | |
def create_item(client, db_name, container_name): | |
""" | |
🌱 Create a new cosmic item—let it grow! | |
""" | |
st.subheader("🌱 Create New Item") | |
item_id = st.text_input("🆔 Item ID") | |
item_data = st.text_area("📝 Item Data (in JSON format)") | |
if st.button("💾 Save New Item"): | |
try: | |
container = client.get_database_client(db_name).get_container_client(container_name) | |
json_data = json.loads(item_data) | |
json_data['id'] = item_id | |
container.create_item(body=json_data) | |
st.success("🎉 New item created successfully!") | |
st.json(json_data) | |
st.experimental_rerun() | |
except Exception as e: | |
st.error(f"🚨 Error creating item: {str(e)}") | |
def edit_item(client, db_name, container_name, item_id): | |
""" | |
✏️ Edit an existing item—because change is the only constant! | |
""" | |
container = client.get_database_client(db_name).get_container_client(container_name) | |
item = container.read_item(item=item_id, partition_key=item_id) | |
st.subheader(f"✏️ Editing Item: {item_id}") | |
edited_item = st.text_area("📝 Edit Item Data (in JSON format)", value=json.dumps(item, indent=2)) | |
if st.button("💾 Save Changes"): | |
try: | |
json_data = json.loads(edited_item) | |
container.upsert_item(body=json_data) | |
st.success("✨ Item updated successfully!") | |
st.json(json_data) | |
st.experimental_rerun() | |
except Exception as e: | |
st.error(f"🚨 Error updating item: {str(e)}") | |
def delete_item(client, db_name, container_name, item_id): | |
""" | |
🗑️ Delete an item—because sometimes less is more! | |
""" | |
st.subheader(f"🗑️ Delete Item: {item_id}") | |
if st.button("⚠️ Confirm Delete"): | |
try: | |
container = client.get_database_client(db_name).get_container_client(container_name) | |
container.delete_item(item=item_id, partition_key=item_id) | |
st.success(f"🔥 Item {item_id} deleted successfully!") | |
st.experimental_rerun() | |
except Exception as e: | |
st.error(f"🚨 Error deleting item: {str(e)}") | |
def archive_all_data(client): | |
""" | |
📦 Archive all your data—pack it up, pack it in! | |
""" | |
try: | |
base_dir = "./cosmos_archive" | |
if os.path.exists(base_dir): | |
shutil.rmtree(base_dir) | |
os.makedirs(base_dir) | |
for database in client.list_databases(): | |
db_name = database['id'] | |
db_dir = os.path.join(base_dir, db_name) | |
os.makedirs(db_dir) | |
db_client = client.get_database_client(db_name) | |
for container in db_client.list_containers(): | |
container_name = container['id'] | |
container_dir = os.path.join(db_dir, container_name) | |
os.makedirs(container_dir) | |
container_client = db_client.get_container_client(container_name) | |
items = list(container_client.read_all_items()) | |
with open(os.path.join(container_dir, f"{container_name}.json"), 'w') as f: | |
json.dump(items, f, indent=2) | |
archive_name = f"cosmos_archive_{datetime.now().strftime('%Y%m%d_%H%M%S')}" | |
shutil.make_archive(archive_name, 'zip', base_dir) | |
return get_base64_download_link(f"{archive_name}.zip", f"{archive_name}.zip") | |
except Exception as e: | |
st.error(f"🚨 An error occurred while archiving data: {str(e)}") | |
def download_all_code(): | |
""" | |
💾 Download all the code—because sharing is caring! | |
""" | |
try: | |
base_dir = "." | |
exclude_dirs = ['.git', '__pycache__', 'cosmos_archive'] | |
exclude_files = ['.env', '.gitignore', 'cosmos_archive.zip'] | |
zip_filename = f"CosmosDBAICode_{datetime.now().strftime('%Y%m%d_%H%M%S')}.zip" | |
shutil.make_archive(zip_filename[:-4], 'zip', base_dir) | |
return get_base64_download_link(zip_filename, zip_filename) | |
except Exception as e: | |
st.error(f"🚨 An error occurred while creating the code archive: {str(e)}") | |
def render_sidebar(client, structure): | |
""" | |
🎛️ Render the cosmic sidebar—control your destiny! | |
""" | |
st.sidebar.title("🌌 Cosmic Control Panel") | |
# 🚦 Navigation | |
app_mode = st.sidebar.radio("🚀 Choose Your Adventure", ["App Mode 🌟", "Tutorial Mode 📖"]) | |
if app_mode == "App Mode 🌟": | |
# 🗄️ Database and Container selection | |
selected_db = st.sidebar.selectbox("🗄️ Select Database", list(structure.keys())) | |
selected_container = st.sidebar.selectbox("📦 Select Container", structure[selected_db]) | |
# 📝 Fetch items for the selected container | |
items = fetch_items(client, selected_db, selected_container) | |
# 📄 Item selection | |
item_ids = [item['id'] for item in items] | |
selected_item = st.sidebar.selectbox("📄 Select Item", ["Create New Item"] + item_ids) | |
# 🎬 Action buttons | |
if selected_item != "Create New Item": | |
if st.sidebar.button("✏️ Edit Item"): | |
st.session_state.action = "edit" | |
st.session_state.selected_item = selected_item | |
if st.sidebar.button("🗑️ Delete Item"): | |
st.session_state.action = "delete" | |
st.session_state.selected_item = selected_item | |
else: | |
if st.sidebar.button("🌱 Create New Item"): | |
st.session_state.action = "create" | |
# 🐙 GitHub Operations | |
st.sidebar.subheader("🐙 GitHub Operations") | |
source_repo = st.sidebar.text_input("🔗 Source Repo URL") | |
new_repo_name = st.sidebar.text_input("🆕 New Repo Name", value=f"Clone-{datetime.now().strftime('%Y%m%d_%H%M%S')}") | |
if st.sidebar.button("📥 Clone Repository"): | |
clone_github_repo(source_repo, new_repo_name) | |
if st.sidebar.button("📤 Push to New Repository"): | |
push_to_new_repo(source_repo, new_repo_name) | |
# 📦 Archive data button | |
if st.sidebar.button("📦 Archive All Data"): | |
download_link = archive_all_data(client) | |
st.sidebar.markdown(download_link, unsafe_allow_html=True) | |
# 💾 Download All Code button | |
if st.sidebar.button("💾 Download All Code"): | |
download_link = download_all_code() | |
st.sidebar.markdown(download_link, unsafe_allow_html=True) | |
# 🚪 Logout button | |
if st.sidebar.button("🚪 Logout"): | |
st.session_state.logged_in = False | |
st.session_state.action = None | |
st.session_state.selected_item = None | |
st.experimental_rerun() | |
return selected_db, selected_container, selected_item, app_mode | |
else: | |
# For tutorial mode | |
return None, None, None, app_mode | |
def clone_github_repo(source_repo, new_repo_name): | |
""" | |
📥 Clone a GitHub repo—it's like magic! | |
""" | |
if GITHUB_TOKEN and source_repo: | |
try: | |
local_path = f"./temp_repo_{datetime.now().strftime('%Y%m%d_%H%M%S')}" | |
download_github_repo(source_repo, local_path) | |
zip_filename = f"{new_repo_name}.zip" | |
shutil.make_archive(zip_filename[:-4], 'zip', local_path) | |
st.sidebar.markdown(get_base64_download_link(zip_filename, zip_filename), unsafe_allow_html=True) | |
st.sidebar.success("🎉 Repository cloned successfully!") | |
except Exception as e: | |
st.sidebar.error(f"🚨 An error occurred: {str(e)}") | |
finally: | |
if os.path.exists(local_path): | |
shutil.rmtree(local_path) | |
if os.path.exists(zip_filename): | |
os.remove(zip_filename) | |
else: | |
st.sidebar.error("🚨 Please ensure GitHub token is set and source repository URL is provided.") | |
def push_to_new_repo(source_repo, new_repo_name): | |
""" | |
📤 Push to a new GitHub repo—reach for the stars! | |
""" | |
if GITHUB_TOKEN and source_repo: | |
try: | |
new_repo = create_repo(GITHUB_TOKEN, new_repo_name) | |
local_path = f"./temp_repo_{datetime.now().strftime('%Y%m%d_%H%M%S')}" | |
download_github_repo(source_repo, local_path) | |
push_to_github(local_path, new_repo, GITHUB_TOKEN) | |
st.sidebar.success(f"🚀 Repository pushed successfully to {new_repo.html_url}") | |
except Exception as e: | |
st.sidebar.error(f"🚨 An error occurred: {str(e)}") | |
finally: | |
if os.path.exists(local_path): | |
shutil.rmtree(local_path) | |
else: | |
st.sidebar.error("🚨 Please ensure GitHub token is set and source repository URL is provided.") | |
def main(): | |
""" | |
🛸 Main function—where all the magic happens! | |
""" | |
st.set_page_config(layout="wide") | |
st.title("🚀 Cosmos DB & GitHub Integration App with Streamlit 🎉") | |
# Initialize session state | |
if 'logged_in' not in st.session_state: | |
st.session_state.logged_in = False | |
if 'action' not in st.session_state: | |
st.session_state.action = None | |
if 'selected_item' not in st.session_state: | |
st.session_state.selected_item = None | |
# Login section | |
if not st.session_state.logged_in: | |
st.subheader("🔐 Login to Your Cosmic Account") | |
if st.button("🚀 Launch"): | |
if PRIMARY_KEY: | |
st.session_state.primary_key = PRIMARY_KEY | |
st.session_state.logged_in = True | |
st.experimental_rerun() | |
else: | |
st.error("🚨 Invalid key. Please check your environment variables.") | |
else: | |
# Initialize Cosmos DB client | |
try: | |
client = CosmosClient(ENDPOINT, credential=st.session_state.primary_key) | |
# Fetch database structure | |
structure = fetch_db_structure(client) | |
# Render sidebar and get selections | |
selected_db, selected_container, selected_item, app_mode = render_sidebar(client, structure) | |
if app_mode == "App Mode 🌟": | |
# Main area | |
if st.session_state.action == "create": | |
create_item(client, selected_db, selected_container) | |
elif st.session_state.action == "edit": | |
edit_item(client, selected_db, selected_container, st.session_state.selected_item) | |
elif st.session_state.action == "delete": | |
delete_item(client, selected_db, selected_container, st.session_state.selected_item) | |
else: | |
st.write("🌟 Select an action from the sidebar to get started.") | |
elif app_mode == "Tutorial Mode 📖": | |
display_tutorial() | |
except exceptions.CosmosHttpResponseError as e: | |
st.error(f"🚨 Failed to connect to Cosmos DB: {str(e)}") | |
except Exception as e: | |
st.error(f"🚨 An unexpected error occurred: {str(e)}") | |
def display_tutorial(): | |
""" | |
📖 Display the in-app tutorial—knowledge is power! | |
""" | |
st.header("📖 Welcome to the Cosmic Tutorial!") | |
st.markdown(""" | |
### 🚀 Introduction | |
**Greetings, Earthling!** 👽 Ready to embark on a cosmic journey through the universe of Azure Cosmos DB and GitHub? Buckle up! This tutorial is not just informative—it's a blast! 🎆 | |
**What You'll Learn:** | |
- 🌌 Connecting to **Azure Cosmos DB** using Python—no rocket science degree required! | |
- 🛠️ Performing **CRUD operations** on Cosmos DB containers—because you can! | |
- 🐙 Integrating **GitHub functionalities** within the app—unleash the octopus! | |
- 🎨 Building an interactive UI with **Streamlit**—your canvas awaits! | |
--- | |
### 🌟 Prerequisites | |
Before we launch into space, make sure you've got: | |
- 🛰️ An **Azure Cosmos DB** account—your mission control. | |
- 🐙 A **GitHub** account with a personal access token—tentacles not included. | |
- 🐍 **Python 3.7+** installed—because snakes are cool. | |
- 🧠 Basic knowledge of Python and Streamlit—you've got this! | |
--- | |
### 🛠️ Setting Up the Environment | |
**1. Clone the Repository** | |
Open your terminal and run: | |
""") | |
st.code(""" | |
git clone https://github.com/yourusername/cosmosdb-streamlit-app.git | |
cd cosmosdb-streamlit-app | |
""", language='bash') | |
st.markdown(""" | |
**2. Create a Virtual Environment** | |
Let's keep things tidy: | |
""") | |
st.code(""" | |
python -m venv venv | |
# On Windows | |
venv\\Scripts\\activate | |
# On macOS/Linux | |
source venv/bin/activate | |
""", language='bash') | |
st.markdown(""" | |
**3. Install Dependencies** | |
Time to get those packages: | |
""") | |
st.code(""" | |
pip install -r requirements.txt | |
""", language='bash') | |
st.markdown(""" | |
**4. Set Up Environment Variables** | |
Create a `.env` file and add: | |
""") | |
st.code(""" | |
ENDPOINT=https://your-cosmos-db-account.documents.azure.com:443/ | |
PRIMARY_KEY=your_cosmos_db_primary_key | |
GITHUB_TOKEN=your_github_personal_access_token | |
""", language='text') | |
st.warning("⚠️ **Note:** Keep your `.env` file secret—just like your secret stash of cookies! 🍪") | |
st.markdown("---") | |
st.markdown(""" | |
### 🔧 Application Architecture | |
**Components:** | |
- 🗄️ **Cosmos DB Operations**: Functions to connect and interact with Azure Cosmos DB. | |
- 🐙 **GitHub Integration**: Clone, create, and push repositories like a boss. | |
- 🎨 **Streamlit Interface**: The front-end that brings it all together. | |
**Data Flow:** | |
1. 🎛️ **User Interaction**: Users make choices in the app. | |
2. 🗄️ **Database Operations**: App performs actions on Cosmos DB. | |
3. 🐙 **GitHub Actions**: Clone and push repositories. | |
4. 📦 **Archiving Data**: Archive and download database contents. | |
--- | |
### 🧩 Implementing the Application | |
**Importing Libraries** | |
""") | |
st.code(""" | |
import streamlit as st | |
from azure.cosmos import CosmosClient, exceptions | |
import os | |
import json | |
from datetime import datetime | |
import shutil | |
from github import Github | |
from git import Repo | |
import base64 | |
from dotenv import load_dotenv | |
load_dotenv() | |
""", language='python') | |
st.markdown(""" | |
**Configuring Cosmos DB and GitHub** | |
""") | |
st.code(""" | |
# Cosmos DB configuration | |
ENDPOINT = os.getenv("ENDPOINT") | |
PRIMARY_KEY = os.getenv("PRIMARY_KEY") | |
# GitHub configuration | |
GITHUB_TOKEN = os.getenv("GITHUB_TOKEN") | |
""", language='python') | |
st.markdown(""" | |
**Helper Functions** | |
Here's where the magic happens! ✨ | |
*GitHub Operations* | |
""") | |
st.code(""" | |
def download_github_repo(url, local_path): | |
# Function implementation | |
def create_repo(github_token, repo_name): | |
# Function implementation | |
def push_to_github(local_path, repo, github_token): | |
# Function implementation | |
""", language='python') | |
st.markdown(""" | |
*Base64 Download Link* | |
""") | |
st.code(""" | |
def get_base64_download_link(file_path, file_name): | |
# Function implementation | |
""", language='python') | |
st.markdown(""" | |
**Cosmos DB Operations** | |
*Fetching Database Structure* | |
""") | |
st.code(""" | |
def fetch_db_structure(client): | |
# Function implementation | |
""", language='python') | |
st.markdown(""" | |
*CRUD Operations* | |
**Create Item** | |
""") | |
st.code(""" | |
def create_item(client, db_name, container_name): | |
# Function implementation | |
""", language='python') | |
st.markdown(""" | |
**Edit Item** | |
""") | |
st.code(""" | |
def edit_item(client, db_name, container_name, item_id): | |
# Function implementation | |
""", language='python') | |
st.markdown(""" | |
**Delete Item** | |
""") | |
st.code(""" | |
def delete_item(client, db_name, container_name, item_id): | |
# Function implementation | |
""", language='python') | |
st.markdown(""" | |
**Archiving Data** | |
""") | |
st.code(""" | |
def archive_all_data(client): | |
# Function implementation | |
""", language='python') | |
st.markdown(""" | |
**Streamlit Interface** | |
*Rendering the Sidebar* | |
""") | |
st.code(""" | |
def render_sidebar(client, structure): | |
# Function implementation | |
""", language='python') | |
st.markdown(""" | |
*Main Function* | |
""") | |
st.code(""" | |
def main(): | |
# Function implementation | |
if __name__ == "__main__": | |
main() | |
""", language='python') | |
st.markdown("---") | |
st.markdown(""" | |
### 🚀 Running the Application | |
**Start the Streamlit App** | |
""") | |
st.code(""" | |
streamlit run CosmicApp.py | |
""", language='bash') | |
st.markdown(""" | |
**Login** | |
- Open your browser and go to `http://localhost:8501`. | |
- Click **Launch** to enter the app. | |
**Using the App** | |
- **Database Selection**: Choose your database and container from the sidebar. | |
- **Item Operations**: | |
- 🌱 **Create New Item** | |
- ✏️ **Edit Item** | |
- 🗑️ **Delete Item** | |
- **GitHub Operations**: | |
- 📥 **Clone Repository** | |
- 📤 **Push to New Repository** | |
- **Archive Data**: Click **📦 Archive All Data** to download a ZIP file. | |
- **Download Code**: Click **💾 Download All Code** to get the app's source code. | |
--- | |
### 🌠 Conclusion | |
You've reached the end of our cosmic tutorial! 🚀 We hope you had a stellar time learning and exploring the universe of Cosmos DB and GitHub integration. | |
**Keep Reaching for the Stars!** 🌟 | |
--- | |
""") | |
if __name__ == "__main__": | |
main() | |