Skip to content

Commit

Permalink
Added serving and automatic rendering functionallity
Browse files Browse the repository at this point in the history
  • Loading branch information
dahlo committed Oct 25, 2024
1 parent 9e7af71 commit 6476194
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ to-do.md
/.quarto/
.DS_Store
[0-9]*/
venv/
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@ RUN apt-get update -y \
libopenblas-base \
libgdal-dev \
curl \
python3-pip \
&& wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb \
&& apt-get install -y ./google-chrome-stable_current_amd64.deb \
&& rm -rf ./google-chrome-stable_current_amd64.deb \
&& curl -o quarto-linux-amd64.deb -L https://github.com/quarto-dev/quarto-cli/releases/download/v${QUARTO_VERSION}/quarto-${QUARTO_VERSION}-linux-amd64.deb \
&& apt-get install -y ./quarto-linux-amd64.deb \
&& rm -rf ./quarto-linux-amd64.deb \
&& Rscript -e 'install.packages(c("remotes","fontawesome","here","htmlTable","leaflet","readxl","writexl"),repos = "http://cran.us.r-project.org");' \
&& pip3 install --no-cache-dir Flask==2.2.2 Werkzeug==2.2.2 PyYAML==6.0.2 watchdog==5.0.3 \
&& rm -rf /var/lib/apt/lists/* \
&& mkdir /qmd /.cache \
&& chmod 777 /qmd /.cache
Expand Down
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,15 @@ docker run --rm --platform linux/amd64 -u $(id -u):$(id -g) -v ${PWD}:/qmd ghcr.
docker run --rm --platform linux/amd64 -u $(id -u):$(id -g) -v ${PWD}:/qmd ghcr.io/nbisweden/workshop-ngsintro:latest quarto render index.qmd
```

## Serving and automatic rendering

You can use a Flask server to serve the site, and handle automatic rebuilding of pages when any `.qmd` file is changed. The browser has to be refreshed manually though.

```bash
# serve the site
docker run --rm --platform linux/amd64 -u $(id -u):$(id -g) -v ${PWD}:/qmd -p 5000:5000 ghcr.io/nbisweden/workshop-ngsintro:latest python3 serve_quarto.py
```

## Test scripts

This is regarding the directory **scripts**. This directory contains shell scripts for reseq (variant-calling) and rnaseq parts of the workshop. These are intended to be run on UPPMAX. Further instructions on using them are available within the scripts.
Expand Down
66 changes: 66 additions & 0 deletions serve_quarto.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
from flask import Flask, send_from_directory
import os
import subprocess
import yaml
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
import time

app = Flask(__name__)
quarto_yml_path = '_quarto.yml'
watched_folder = '.'

# Function to read the output directory from _quarto.yml
def read_output_dir_from_quarto_yml(quarto_yml_path):
with open(quarto_yml_path, 'r') as file:
quarto_config = yaml.safe_load(file)
return quarto_config.get('project', {}).get('output-dir', 'default-output-folder')

output_folder = read_output_dir_from_quarto_yml(quarto_yml_path)

class QuartoHandler(FileSystemEventHandler):
def __init__(self):
self.last_modified_time = {}

def should_process(self, file_path, cooldown=2):
# Check the time of the last modification for the given file
last_time = self.last_modified_time.get(file_path, 0)
# Get the current time
current_time = time.time()
# If the last modification was more recent than the cooldown, skip processing
if current_time - last_time < cooldown:
return False
# Update the last modification time and proceed
self.last_modified_time[file_path] = current_time
return True

def on_modified(self, event):
if not event.is_directory and event.src_path.endswith('.qmd'):
if self.should_process(event.src_path):
print(f"Detected changes in {event.src_path}. Rendering...")
# Run the Quarto render command for the specific file
subprocess.run(['quarto', 'render', event.src_path])


# Set up file watcher
event_handler = QuartoHandler()
observer = Observer()
observer.schedule(event_handler, watched_folder, recursive=True)
observer.start()


@app.route('/')
def index():
# Serve the index.html file
return send_from_directory(output_folder, 'index.html')

@app.route('/<path:filename>')
def serve_file(filename):
# Serve the rendered file
return send_from_directory(output_folder, filename)


if __name__ == '__main__':
output_folder = read_output_dir_from_quarto_yml(quarto_yml_path) # Update the output folder on the startup
app.run(host='0.0.0.0', port=5000, debug=True)

0 comments on commit 6476194

Please sign in to comment.