Syntax/Undefined error in my framework

Sorry to bother but I was trying to add syntax but it’s not working. I get this error →

Traceback (most recent call last):
File "/home/runner/Vial/app.py", line 5, i n ‹module>
from sre import App, route
File "/home/runner/Vial/src/__init__.py",
Line 3, in <module>
from . framework import App, route
ImportError: cannot import name 'route' from
' src.framework' (/home/runner/Vial/src/fram
ework.py 

This is my code

__init__.py

# src/__init__.py

from .framework import App, route

__all__ = ['App', 'route'] 

framework.py

# framework.py

from werkzeug.wrappers import Request, Response
from werkzeug.serving import run_simple

class Request(Request):
    pass

class Response(Response):
    pass

class App:
    def __init__(self):
        self.routes = {}

    def route(self, path):
        def decorator(view_func):
            self.routes[path] = view_func
            return view_func
        return decorator

    def dispatch_request(self, request):
        view_func = self.routes.get(request.path)
        if view_func is not None:
            return view_func(request)
        return Response('Not Found', status=404)

    def __call__(self, environ, start_response):
        request = Request(environ)
        response = self.dispatch_request(request)
        return response(environ, start_response)
      
    def route(self, rule, **kwargs):
        def decorator(f):
            kwargs['endpoint'] = f.__name__
            self.url_map.add(Rule(rule, **kwargs))
            return f
        return decorator 

app.py

# app.py

from werkzeug.wrappers import Request, Response
from werkzeug.serving import run_simple
from src import App, route

class MyApp(App):  # Inherit from the App class you're importing
    def __call__(self, environ, start_response):
        request = Request(environ)

        # Create a paragraph with a div inside using the HTML generator classes
        p = P().attribute("class", "paragraph").child(Div())

        # Convert the Tag object to a string to get the HTML markup
        html_content = str(p)

        # Set the content type header to text/html
        response = Response(html_content, mimetype='text/html')

        return response(environ, start_response)

if __name__ == '__main__':
    app = MyApp()
    run_simple('0.0.0.0',  5000, app)
1 Like

I think this is because:

route() is within the class.

You may need to expose a global route FN.

Ok that worked, now I have an error that P isn’t defined, I have that in html_generator.py I don’t know how to add it to my framework.py

# html_generator.py

class Tag:
    def __init__(self, name):
        self.name = name
        self.attributes = []
        self.children = []

    def attribute(self, key, value):
        self.attributes.append((key, value))
        return self

    def child(self, tag):
        self.children.append(tag)
        return self

    def __str__(self):
        attrs = " ".join([f'{k}="{v}"' for k, v in self.attributes])
        children = "".join(map(str, self.children))
        return f"<{self.name} {attrs}>{children}</{self.name}>"

class Div(Tag):
    def __init__(self):
        super().__init__("div")

class P(Tag):
    def __init__(self):
        super().__init__("p")

# Usage
p = P().attribute("class", "paragraph").child(Div().child(P()))
print(p)
1 Like

You would import it into framework.py as well, which brings it into the module scope, and then you include it in the file you want to use with the new path.

1 Like

@Spcfork I did this (I don’t know if it is correct) and I still get the same error →

# framework.py

from werkzeug.wrappers import Request, Response
from werkzeug.serving import run_simple
from src import html_generator # <- here

class Request(Request):
    pass

class Response(Response):
    pass

class App:
    def __init__(self):
        self.routes = {}

    def route(self, path):
        def decorator(view_func):
            self.routes[path] = view_func
            return view_func
        return decorator

    def dispatch_request(self, request):
        view_func = self.routes.get(request.path)
        if view_func is not None:
            return view_func(request)
        return Response('Not Found', status=404)

    def __call__(self, environ, start_response):
        request = Request(environ)
        response = self.dispatch_request(request)
        return response(environ, start_response)
      
def route(self, rule, **kwargs):
    def decorator(f):
        kwargs['endpoint'] = f.__name__
        self.url_map.add(Rule(rule, **kwargs))
        return f
    return decorator 
1 Like

Try:

# framework.py

from werkzeug.wrappers import Request, Response
from werkzeug.serving import run_simple
from **!!!PATH TO FILE!!!**.html_generator import P, Div  # <- here

class Request(Request):
    pass

class Response(Response):
    pass

class App:
    def __init__(self):
        self.routes = {}

    def route(self, path):
        def decorator(view_func):
            self.routes[path] = view_func
            return view_func
        return decorator

    def dispatch_request(self, request):
        view_func = self.routes.get(request.path)
        if view_func is not None:
            return view_func(request)
        return Response('Not Found', status=404)

    def __call__(self, environ, start_response):
        request = Request(environ)
        response = self.dispatch_request(request)
        return response(environ, start_response)
      
def route(self, rule, **kwargs):
    def decorator(f):
        kwargs['endpoint'] = f.__name__
        self.url_map.add(Rule(rule, **kwargs))
        return f
    return decorator

I think just:

from .html_generator import P, Div

should work since it’s in the same directory.

3 Likes

@Firepup650 I get this error →

File "/home/runner/Vial/app.py", line 12, in __call
ーー
p = P() attribute("class", "paragraph").
child(Div( ))
NameError: name 'p' is not defined 172.31.196.30 - - [06/Feb/2024 01:32:42] "GE
Т / HTTP/1.1" 500 -
Error on request:
Traceback (most recent call last):
File "/home/runner/Vial/.pythonlibs/lib/py thon3. 10/site-packages/werkzeug/serving.py", line 362, in run_wsgi
execute( self.server.app)
File "/home/runner/Vial/.pythonlibs/lib/py thon3. 10/site-packages/werkzeug/serving.py", line 323, in execute
application_iter = app(environ, start_re
sponse)
File "/home/runner/Vial/app.py", line 12, in __call
p = P(). attribute("class", "paragraph").
child(Div( ))
NameError: name 'p' is not defined 
1 Like

That’s the lowercase p, where is that assignment?

1 Like

@Firepup650 it is normally P, but I assign it to p in app.py

# app.py

from werkzeug.wrappers import Request, Response
from werkzeug.serving import run_simple
from src import App, route

class MyApp(App):  # Inherit from the App class you're importing
    def __call__(self, environ, start_response):
        request = Request(environ)

        # Create a paragraph with a div inside using the HTML generator classes
        p = P().attribute("class", "paragraph").child(Div()) # <- HERE

        # Convert the Tag object to a string to get the HTML markup
        html_content = str(p)

        # Set the content type header to text/html
        response = Response(html_content, mimetype='text/html')

        return response(environ, start_response)

if __name__ == '__main__':
    app = MyApp()
    run_simple('0.0.0.0',  5000, app)
1 Like

Wouldn’t P be undefined there since it’s not imported? (Which would then cause the other errors once you try to call a function such as attribute on it)

3 Likes

@Firepup650 I imported it into __init__.py since it doesn’t get imported from framework.py to __init__.py

# src/__init__.py

from .framework import App, route
from .html_generator import __all__

__all__ = ['App', 'route'] 

I then get this error →

<p class="paragraph"><div ><p ></p></div></p>
Traceback (most recent call last):
File "/home/runner/Vial/app.py", line 5, i n <module>
from sre import App, route
File "/home/runner/Vial/src/__init__.py", line 4, in ‹module>
from .html_generator import
ImportError: cannot import name all
' from 'src.html_generator' (/home/runner/Vial/src/html_generator.py) 
1 Like

Seems like you can’t import __all__.

@Spcfork what should I use instead of __all__ I tried using from .html_generator import * and it still gives me this error →

Error on request:
Traceback (most recent call last):
File "/home/runner/Vial/.pythonlibs/lib/py thon3.10/site-packages/werkzeug/serving.py", line 362, in run_wsgi
execute(self.server.app)
File "/home/runner/Vial/.pythonlibs/lib/py thon3. 10/site-packages/werkzeug/serving•py", line 323, in execute
application_iter = app(environ, start_re
sponse)
File "/home/runner/Vial/app-py", line 12, in call
p = P() .attribute( "class"
, "paragraph").
child(Div())
NameError: name 'P' is not defined 
1 Like

Try just doing the import without the from,
If that doesn’t work, try including P, or making an object to hold these in.

This probably isn’t the best way, but it’s all I could think of, JS wise.

@Spcfork I tried both options (without the from, it throws an error for the syntax from .html_generator import * (without the . it says it can’t find the module, and from .html_geneator import P says P isn’t defined), but it still gives the same error for some reason.

1 Like

Hello, in the repl it seems like changing line 5 in app.py to from src import App, route, P, Div should work fine. Did you just forget to import the symbols, in app?

3 Likes

@NuclearPasta0 thank you, it worked!

@not-ethan sorry to ping you, but can you move the posts about my problem after my original solved one. I forgot to make a new topic.

2 Likes

@NuclearPasta0 I was adding more tags in my html_generator.py file and it throws this error →

Error on request:
Traceback (most recent call last):
File "/home/runner/VIAL/. pythonlibs/lib/py thon3. 10/site-packages/werkzeug/serving.py",
Line 362, in run_wsgi
execute (self.server.app)
File "/home/runner/VIAL/. pythonlibs/lib/py thon3. 10/site-packages/werkzeug/serving.py",
Line 323, in execute
application_ iter = app(environ, start_re
sponse
File "/home/runner/VIAL/app.py", line 43, in __call
return response(environ, start_response)
TypeError: 'NoneType' object is not callable

app.py

# app.py

from werkzeug.wrappers import Request, Response
from werkzeug.serving import run_simple
from werkzeug.routing import Map, Rule
from src import App, route, tags

class MyApp(App):
    def __init__(self):
        self.url_map = Map([
            Rule('/', endpoint='index')
        ])

    def dispatch_request(self, request):
        adapter = self.url_map.bind_to_environ(request.environ)
        try:
            endpoint, args = adapter.match()
            return getattr(self, endpoint)(request, **args)
        except Exception as e:
            # Handle exceptions here
            pass

    def index(self, request):
        # Example usage of various tags
        list_items = [
            tags.li("Item   1"),
            tags.li("Item   2"),
            tags.li("Item   3")
        ]
        unordered_list = tags.ul().children(*list_items)

        # Convert the Tag objects to strings to get the HTML markup
        html_content = str(unordered_list)

        # Set the content type header to text/html
        response = Response(html_content, mimetype='text/html')

        return response

    def __call__(self, environ, start_response):
        request = Request(environ)
        response = self.dispatch_request(request)
        return response(environ, start_response)

if __name__ == '__main__':
    app = MyApp()
    run_simple('0.0.0.0',   5000, app)

html_generator.py

# html_generator.py

class Tag:
    def __init__(self, name, text=""):
        self.name = name
        self.attributes = []
        self.children = []
        self.text = text

    def attribute(self, key, value):
        self.attributes.append((key, value))
        return self

    def id(self, value):
        self.attributes.append(('id', value))
        return self

    def child(self, tag):
        self.children.append(tag)
        return self

    def __str__(self):
        attrs = " ".join([f'{k}="{v}"' for k, v in self.attributes])
        children = "".join(map(str, self.children))
        return f"<{self.name} {attrs}>{self.text}{children}</{self.name}>"

class tags:

    class div(Tag):
        def __init__(self, text=""):
            super().__init__("div", text)

    class p(Tag):
        def __init__(self, text=""):
            super().__init__("p", text)
            
    class span(Tag):
        def __init__(self, text=""):
            super().__init__("span", text)

    class h1(Tag):
        def __init__(self, text=""):
            super().__init__("h1", text)

    class ul(Tag):
        def __init__(self, text=""):
            super().__init__("ul", text)

    class li(Tag):
        def __init__(self, text=""):
            super().__init__("li", text)

    class a(Tag):
        def __init__(self, text="", href="#"):
            super().__init__("a", text)
            self.attribute("href", href)

    class img(Tag):
        def __init__(self, src="", alt=""):
            super().__init__("img")
            self.attribute("src", src)
            self.attribute("alt", alt)
1 Like

Using some logic and only the app.py file, I can infer that the line endpoint, args = adapter.match() in MyApp.dispatch_request raises some sort of Exception that is not handled. (You should also be able to make this inference yourself.) Another possible case is that getattr(self, endpoint)(request, **args), in the same method, returns None. (It’s also a bit weird that you named a dict-unpacked variable args instead of kwargs.)
(I do not have experience with stuff like this though.)
Therefore, you should probably implement exception handling in MyApp.dispatch_request or check the call in the return in dispatch_request.

3 Likes