<commit_before># -*- coding: utf-8 -*-
import http.server
import socketserver

from shutil import copyfile
from urllib.parse import unquote, urlparse

from logya.core import Logya
from logya.content import read, write_collection, write_page
from logya.template import env
from logya.util import filepath


class HTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
    """SimpleHTTPRequestHandler based class to return resources."""

    L = None

    def __init__(self, *args):
        super(HTTPRequestHandler, self).__init__(*args, directory=self.L.paths.public.as_posix())

    def do_GET(self):
        update_resource(self.path, self.L)
        super(HTTPRequestHandler, self).do_GET()


def get_collection_name(path, settings):
    for name, coll in settings['collections'].items():
        if path == coll['path']:
            return name


def update_resource(path, L):
    """Update resource corresponding to given url.

    Resources that exist in the `static` directory are updated if they are newer than the destination file.
    For other HTML resources the whole `L.index` is updated and the destination is newly written."""

    # Use only the actual path and ignore possible query params (see issue #3).
    url = unquote(urlparse(path).path)
    url_rel = path.lstrip('/')
    path_dst = filepath(L.paths.public, url)

    # If a static file is requested update it and return.
    src_static = L.paths.static.joinpath(url_rel)
    if src_static.is_file():
        dst_static = L.paths.public.joinpath(url_rel)
        dst_static.parent.mkdir(exist_ok=True)
        if not dst_static.exists() or src_static.stat().st_mtime > dst_static.stat().st_mtime:
            L.info(f'Update static resource: {dst_static}')
            copyfile(src_static, dst_static)
        return

    # Update content page.
    if content := L.index.get(url):
        content['doc'] = read(content['path'], content['path'].relative_to(L.paths.content))
        if L.collections:
            L.update_collections(content['doc'])
        # Always write doc because of possible template changes.
        write_page(path_dst, content, L.settings)
        L.info(f'Refreshed doc: {path}')

    # Update collection page.
    elif coll := L.collections.get(get_collection_name(url.split('/')[1], L.settings)):
        if content := coll['index'].get(url):
            write_collection(path_dst, content, L.settings)
            L.info(f'Refreshed collection: {path}')

    # Rebuild index for other HTML file requests.
    # elif url.endswith(('/', '.html', '.htm')):
    #     L.info(f'Rebuild site for request URL: {path}')
    #     L.build()


def serve(options):
    L = Logya(options)
    L.build()
    # Make Logya object accessible to server.
    HTTPRequestHandler.L = L

    # Make sure absolute links work.
    base_url = f'http://{options.host}:{options.port}'
    env.globals['base_url'] = base_url

    # Avoid "OSError: [Errno 98] Address already in use"
    socketserver.TCPServer.allow_reuse_address = True
    with socketserver.TCPServer((options.host, options.port), HTTPRequestHandler) as httpd:
        print(f'Serving on {base_url}')
        httpd.serve_forever()<commit_msg>Create update_page function and rebuild site for requests HTML requests not found in any index.<commit_after># -*- coding: utf-8 -*-
import http.server
import socketserver

from shutil import copyfile
from urllib.parse import unquote, urlparse

from logya.core import Logya
from logya.content import read, write_collection, write_page
from logya.template import env
from logya.util import filepath


class HTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
    """SimpleHTTPRequestHandler based class to return resources."""

    L = None

    def __init__(self, *args):
        super(HTTPRequestHandler, self).__init__(*args, directory=self.L.paths.public.as_posix())

    def do_GET(self):
        update_resource(self.path, self.L)
        super(HTTPRequestHandler, self).do_GET()


def get_collection_name(path, settings):
    for name, coll in settings['collections'].items():
        if path == coll['path']:
            return name


def update_page(url: str, L):
    """Update content or collection page."""

    path_dst = filepath(L.paths.public, url)

    if content := L.index.get(url):
        content['doc'] = read(content['path'], content['path'].relative_to(L.paths.content))
        if L.collections:
            L.update_collections(content['doc'])
        # Always write doc because of possible template changes.
        write_page(path_dst, content, L.settings)
        L.info(f'Refreshed doc: {url}')
        return True

    if coll := L.collections.get(get_collection_name(url.split('/')[1], L.settings)):
        if content := coll['index'].get(url):
            write_collection(path_dst, content, L.settings)
            L.info(f'Refreshed collection: {url}')
            return True


def update_resource(path, L):
    """Update resource corresponding to given url.

    Resources that exist in the `static` directory are updated if they are newer than the destination file.
    For other HTML resources the whole `L.index` is updated and the destination is newly written."""

    # Use only the actual path and ignore possible query params (see issue #3).
    url = unquote(urlparse(path).path)
    url_rel = url.lstrip('/')

    # If a static file is requested update it and return.
    src_static = L.paths.static.joinpath(url_rel)
    if src_static.is_file():
        dst_static = L.paths.public.joinpath(url_rel)
        dst_static.parent.mkdir(exist_ok=True)
        if not dst_static.exists() or src_static.stat().st_mtime > dst_static.stat().st_mtime:
            L.info(f'Update static resource: {dst_static}')
            copyfile(src_static, dst_static)
        return

    # Update content or collection existing in respective index.
    if update_page(url, L):
        return

    # Rebuild indexes for other HTML file requests and try again to update page in case of new content.
    if url.endswith(('/', '.html', '.htm')):
        L.info(f'Rebuild site for request URL: {url}')
        L.build()
        update_page(url, L)


def serve(options):
    L = Logya(options)
    L.build()
    # Make Logya object accessible to server.
    HTTPRequestHandler.L = L

    # Make sure absolute links work.
    base_url = f'http://{options.host}:{options.port}'
    env.globals['base_url'] = base_url

    # Avoid "OSError: [Errno 98] Address already in use"
    socketserver.TCPServer.allow_reuse_address = True
    with socketserver.TCPServer((options.host, options.port), HTTPRequestHandler) as httpd:
        print(f'Serving on {base_url}')
        httpd.serve_forever()
{'fraction_non_alphanumeric': 0.11265293942106834, 'fraction_numerical': 0.0014920919128618322, 'mean_word_length': 3.2531725888324874, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3776268', 'n_tokens_mistral': 2006, 'n_tokens_neox': 1960, 'n_words': 569}