From 67f9b19850f61dd0b9136fe8ac1e532b0c53d2ab Mon Sep 17 00:00:00 2001 From: David Saldubehere Date: Mon, 30 Dec 2024 00:17:55 -0500 Subject: [PATCH 1/3] added context for jinja templates --- eel/__init__.py | 51 ++++++++++++++++++- examples/06 - jinja_templates/hello.py | 5 ++ .../web/templates/hello.html | 46 ++++++++--------- 3 files changed, 75 insertions(+), 27 deletions(-) diff --git a/eel/__init__.py b/eel/__init__.py index e1ab255b..e2d5fdaa 100644 --- a/eel/__init__.py +++ b/eel/__init__.py @@ -447,7 +447,8 @@ def _static(path: str) -> btl.Response: if path.startswith(template_prefix): n = len(template_prefix) template = _start_args['jinja_env'].get_template(path[n:]) - response = btl.HTTPResponse(template.render()) + # Pass the context variables to the template + response = btl.HTTPResponse(template.render(**_context.get_all())) if response is None: response = btl.static_file(path, root=root_path) @@ -646,3 +647,51 @@ def _set_response_headers(response: btl.Response) -> None: if _start_args['disable_cache']: # https://stackoverflow.com/a/24748094/280852 response.set_header('Cache-Control', 'no-store') + + +# Add this new class after the imports +class Context: + """Class to manage variables that will be passed to Jinja templates.""" + + def __init__(self): + self._variables: Dict[str, Any] = {} + + def set(self, name: str, value: Any) -> None: + """Set a variable that will be available in Jinja templates. + + Args: + name: Name of the variable to be used in templates + value: Value to associate with the variable name + """ + self._variables[name] = value + + def get(self, name: str) -> Any: + """Get a variable value by name. + + Args: + name: Name of the variable to retrieve + + Returns: + The value associated with the variable name + """ + return self._variables.get(name) + + def get_all(self) -> Dict[str, Any]: + """Get all variables as a dictionary. + + Returns: + Dictionary of all variable names and values + """ + return self._variables.copy() + +# Add after the existing global variables +_context: Context = Context() + +# Add this function to get access to the context +def get_context() -> Context: + """Get the global Context instance for setting template variables. + + Returns: + The global Context instance + """ + return _context diff --git a/examples/06 - jinja_templates/hello.py b/examples/06 - jinja_templates/hello.py index 3f096b76..27246722 100644 --- a/examples/06 - jinja_templates/hello.py +++ b/examples/06 - jinja_templates/hello.py @@ -4,6 +4,11 @@ eel.init('web') # Give folder containing web files +# Get the context and set some variables +context = eel.get_context() +context.set('users', ['Alice', 'Bob', 'Charlie']) +context.set('title', 'Hello from Eel!') + @eel.expose def py_random(): return random.random() diff --git a/examples/06 - jinja_templates/web/templates/hello.html b/examples/06 - jinja_templates/web/templates/hello.html index fefcf6d8..0a0ae78d 100644 --- a/examples/06 - jinja_templates/web/templates/hello.html +++ b/examples/06 - jinja_templates/web/templates/hello.html @@ -1,27 +1,21 @@ -{% extends 'base.html' %} -{% block title %}Hello, World!{% endblock %} -{% block head_scripts %} - eel.expose(say_hello_js); // Expose this function to Python - function say_hello_js(x) { - console.log("Hello from " + x); - } + + + + {{ title }} + + +

{{ title }}

+ +

Users:

+ - eel.expose(js_random); - function js_random() { - return Math.random(); - } - - function print_num(n) { - console.log('Got this from Python: ' + n); - } - - eel.py_random()(print_num); - - say_hello_js("Javascript World!"); - eel.say_hello_py("Javascript World!"); // Call a Python function -{% endblock %} -{% block content %} - Hello, World! -
- Page 2 -{% endblock %} + + + + From 22aab3bfc739d595a1fa2214e5b6d799f940586f Mon Sep 17 00:00:00 2001 From: David Saldubehere Date: Mon, 30 Dec 2024 01:01:06 -0500 Subject: [PATCH 2/3] added test cases --- eel/__init__.py | 42 +++++++++---------- examples/06 - jinja_templates/hello.py | 1 - .../web/templates/hello.html | 37 ++++++++++------ tests/integration/test_examples.py | 15 ++++++- 4 files changed, 58 insertions(+), 37 deletions(-) diff --git a/eel/__init__.py b/eel/__init__.py index e2d5fdaa..3c532dd6 100644 --- a/eel/__init__.py +++ b/eel/__init__.py @@ -649,49 +649,45 @@ def _set_response_headers(response: btl.Response) -> None: response.set_header('Cache-Control', 'no-store') -# Add this new class after the imports class Context: - """Class to manage variables that will be passed to Jinja templates.""" + '''Class to manage variables that will be passed to Jinja templates. + + This class provides a way to store and retrieve variables that will be made + available to Jinja templates when they are rendered. + ''' def __init__(self): self._variables: Dict[str, Any] = {} def set(self, name: str, value: Any) -> None: - """Set a variable that will be available in Jinja templates. + '''Set a variable that will be available in Jinja templates. - Args: - name: Name of the variable to be used in templates - value: Value to associate with the variable name - """ + :param name: Name of the variable to be used in templates. + :param value: Value to associate with the variable name. + ''' self._variables[name] = value def get(self, name: str) -> Any: - """Get a variable value by name. + '''Get a variable value by name. - Args: - name: Name of the variable to retrieve - - Returns: - The value associated with the variable name - """ + :param name: Name of the variable to retrieve. + :returns: The value associated with the variable name. + ''' return self._variables.get(name) def get_all(self) -> Dict[str, Any]: - """Get all variables as a dictionary. + '''Get all variables as a dictionary. - Returns: - Dictionary of all variable names and values - """ + :returns: Dictionary of all variable names and values. + ''' return self._variables.copy() # Add after the existing global variables _context: Context = Context() -# Add this function to get access to the context def get_context() -> Context: - """Get the global Context instance for setting template variables. + '''Get the global Context instance for setting template variables. - Returns: - The global Context instance - """ + :returns: The global Context instance. + ''' return _context diff --git a/examples/06 - jinja_templates/hello.py b/examples/06 - jinja_templates/hello.py index 27246722..1e8adae1 100644 --- a/examples/06 - jinja_templates/hello.py +++ b/examples/06 - jinja_templates/hello.py @@ -4,7 +4,6 @@ eel.init('web') # Give folder containing web files -# Get the context and set some variables context = eel.get_context() context.set('users', ['Alice', 'Bob', 'Charlie']) context.set('title', 'Hello from Eel!') diff --git a/examples/06 - jinja_templates/web/templates/hello.html b/examples/06 - jinja_templates/web/templates/hello.html index 0a0ae78d..a929d053 100644 --- a/examples/06 - jinja_templates/web/templates/hello.html +++ b/examples/06 - jinja_templates/web/templates/hello.html @@ -1,9 +1,26 @@ - - - - {{ title }} - - +{% extends 'base.html' %} +{% block title %}Hello, World!{% endblock %} +{% block head_scripts %} + eel.expose(say_hello_js); // Expose this function to Python + function say_hello_js(x) { + console.log("Hello from " + x); + } + + eel.expose(js_random); + function js_random() { + return Math.random(); + } + + function print_num(n) { + console.log('Got this from Python: ' + n); + } + + eel.py_random()(print_num); + + say_hello_js("Javascript World!"); + eel.say_hello_py("Javascript World!"); // Call a Python function +{% endblock %} +{% block content %}

{{ title }}

Users:

@@ -13,9 +30,5 @@

Users:

{% endfor %} - - - - + Page 2 +{% endblock %} \ No newline at end of file diff --git a/tests/integration/test_examples.py b/tests/integration/test_examples.py index 53dff2a0..c5a5e9ff 100644 --- a/tests/integration/test_examples.py +++ b/tests/integration/test_examples.py @@ -59,8 +59,21 @@ def test_06_jinja_templates(driver: webdriver.Remote): driver.get(eel_url) assert driver.title == "Hello, World!" + h1_element = driver.find_element(By.CSS_SELECTOR, 'h1') + assert h1_element.text == "Hello from Eel!" + + user_elements = driver.find_elements(By.CSS_SELECTOR, 'ul li') + expected_users = ['Alice', 'Bob', 'Charlie'] + + assert len(user_elements) == len(expected_users), "Number of rendered users doesn't match expected" + + for user_elem, expected_user in zip(user_elements, expected_users): + assert user_elem.text == expected_user, f"Expected user {expected_user}, got {user_elem.text}" + driver.find_element(By.CSS_SELECTOR, 'a').click() - WebDriverWait(driver, 2.0).until(expected_conditions.presence_of_element_located((By.XPATH, '//h1[text()="This is page 2"]'))) + WebDriverWait(driver, 2.0).until( + expected_conditions.presence_of_element_located((By.XPATH, '//h1[text()="This is page 2"]')) + ) def test_10_custom_app(driver: webdriver.Remote): From fe72862e3e9206d2c7514c42e400dcbec08faf1e Mon Sep 17 00:00:00 2001 From: David Saldubehere Date: Mon, 30 Dec 2024 14:26:28 -0500 Subject: [PATCH 3/3] Added missing context --- eel/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eel/__init__.py b/eel/__init__.py index 3c532dd6..da8e482a 100644 --- a/eel/__init__.py +++ b/eel/__init__.py @@ -656,7 +656,7 @@ class Context: available to Jinja templates when they are rendered. ''' - def __init__(self): + def __init__(self) -> None: self._variables: Dict[str, Any] = {} def set(self, name: str, value: Any) -> None: