Skip to content

Conversation

ashupednekar
Copy link

Description

This PR fixes #969

Summary

PR: Add Structured Scaffold Option to Robyn's Create Command

Description:

This PR introduces a new feature to Robyn's create command, allowing users to choose between two scaffold options:

  1. Simple Starter Kit – Ideal for minimal, quick-start projects.
  2. Structured Scaffold – A more opinionated setup, providing separation of concerns and enhanced organization for scaling projects.

Changes:

  • Updated the create command to prompt users with a new option:
    • Would you like the scaffold to be a simple starter kit or an opinionated structure?
  • The simple scaffold remains the same as before with options like Mongo, Postgres, SQLite, etc.
  • Added a structured scaffold with the following structure:
    • api/handlers (for route handlers)
    • middlewares (for middleware definitions)
    • adaptors (with models, selectors, mutators)
    • utils (helper functions like db.py)
    • devops (including Dockerfile, docker-compose)
    • Improved configuration management (e.g., conf.py, config.env).

Example Structured Scaffold:

├── no-db
│   ├── api
│   │   ├── handlers
│   │   │   ├── __init__.py
│   │   │   ├── probes.py
│   │   │   └── sample.py
│   │   └── middlewares
│   │       └── __init__.py
│   ├── conf.py
│   ├── config.env
│   ├── devops
│   │   ├── Dockerfile
│   │   ├── Dockerfile.src
│   │   └── docker-compose.yaml
│   ├── requirements.txt
│   ├── server.py
│   └── utils
│       └── __init__.py
└── sqlalchemy
    ├── adaptors
    │   ├── __init__.py
    │   ├── models.py
    │   ├── mutators
    │   │   └── __init__.py
    │   ├── schema.py
    │   └── selectors
    │       └── __init__.py
    ├── api
    │   ├── handlers
    │   │   ├── __init__.py
    │   │   ├── probes.py
    │   │   └── sample.py
    │   └── middlewares
    │       └── __init__.py
    ├── conf.py
    ├── config.env
    ├── devops
    │   ├── Dockerfile
    │   ├── Dockerfile.src
    │   └── docker-compose.yaml
    ├── requirements.txt
    ├── server.py
    └── utils
        ├── __init__.py
        └── db.py

PR Checklist

Please ensure that:

  • [*] The PR contains a descriptive title
  • [*] The PR contains a descriptive summary of the changes
  • [*] You build and test your changes before submitting a PR.
  • You have added relevant documentation
  • You have added relevant tests. We prefer integration tests wherever possible

Pre-Commit Instructions:

Copy link

vercel bot commented Sep 25, 2024

@pre-commit-ci[bot] is attempting to deploy a commit to the sparckles Team on Vercel.

A member of the Team first needs to authorize it.

@ashupednekar ashupednekar marked this pull request as draft September 25, 2024 17:29
Copy link

codspeed-hq bot commented Sep 25, 2024

CodSpeed Performance Report

Merging #970 will not alter performance

Comparing ashupednekar:feat_structured_scaffold (662c009) with main (06c487d)

Summary

✅ 116 untouched benchmarks

@ashupednekar ashupednekar changed the title Feat structured scaffold feat: support for structured scaffold in create command Sep 26, 2024
@ashupednekar ashupednekar marked this pull request as ready for review September 26, 2024 05:00
@sansyrox sansyrox mentioned this pull request Oct 28, 2024
1 task
@dave42w
Copy link
Contributor

dave42w commented Oct 28, 2024

Hi,
Can you help me understand a couple of things in this scaffold structure?

Multiple SubRoutes.

For example, if we take the crimes example as one subrouter within a Gotham application.

If we look at the web based Gotham application we might have multiple subrouters eg crime, finance, planning, licenses, housing

where do these go in the scaffold directory structure? Are they:

\no-db\api\handlers\crime.py
\no-db\api\handlers\finance.py

Template and Static files

Where do the Jinja templates go?
Where do the static files go?

For both templates and static files I'm assuming that there will be some that are shared right across Gotham and some that are specific to crime or finance ...

Thanks

@ashupednekar
Copy link
Author

Yes, each handler.py would be a collection of routes in a sub route, akin to viewsets in DRF

@ashupednekar
Copy link
Author

@sansyrox any updates/suggestions ?

@sansyrox
Copy link
Member

Thanks for the nudge @ashupednekar 😄

I will complete the review by tomorrow eve! @dave42w , do you have any more suggestions/feedback?

@dave42w
Copy link
Contributor

dave42w commented Dec 13, 2024

Thanks for the nudge @ashupednekar 😄

I will complete the review by tomorrow eve! @dave42w , do you have any more suggestions/feedback?

I don't have anything yet as I haven't built a large app yet in Robyn. I've found this article interesting and it covers a few things the scaffold doesn't. https://dev.nando.audio/2014/04/01/large_apps_with_sqlalchemy__architecture.html

I also suspect that using an event queue will be a key part of larger apps rather than a big transition (eg in an ordering process)

As the scaffolding is described as opinionated whether it might be possible to support plugging in different opinions eg if a corporate has a standard they already use and want robyn to support.

@dave42w
Copy link
Contributor

dave42w commented Dec 13, 2024

Although I think we do need to get the CI builds sorted before we merge anything

Copy link

recurseml bot commented May 27, 2025

⚠️ Only 5 files will be analyzed due to processing limits.

1 similar comment
Copy link

recurseml bot commented May 27, 2025

⚠️ Only 5 files will be analyzed due to processing limits.

os.makedirs(final_project_dir_path, exist_ok=True)

selected_project_template = (SCAFFOLD_DIR / Path(project_type)).resolve()
selected_project_template = (SCAFFOLD_DIR / Path(scaffold_type) / Path(project_type)).resolve()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing directory structure validation. The code attempts to access a new directory structure that includes scaffold types (simple/structured), but based on the project tree, the 'structured' directory doesn't exist in the scaffold folder. This will raise a FileNotFoundError when users select the 'structured' scaffold type.


React with 👍 to tell me that this comment was useful, or 👎 if not (and I'll stop posting more comments like this in the future)


def discover_routes(handler_path: str = "api.handlers") -> Robyn:
mux: Robyn = Robyn(__file__)
package = importlib.import_module(handler_path)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dynamic module import lacks error handling. importlib.import_module() can raise ModuleNotFoundError or other import-related exceptions if the module cannot be found or loaded. This could crash the application. Should be wrapped in a try-except block to handle potential import failures gracefully.

📚 Relevant Docs


React with 👍 to tell me that this comment was useful, or 👎 if not (and I'll stop posting more comments like this in the future)

def discover_routes(handler_path: str = "api.handlers") -> Robyn:
mux: Robyn = Robyn(__file__)
package = importlib.import_module(handler_path)
for _, module_name, _ in pkgutil.iter_modules(package.__path__, package.__name__ + "."):
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unsafe access to package.path without checking if it exists. If package is not a package but a module, path attribute will not exist, leading to an AttributeError. Should check if hasattr(package, 'path') before accessing.


React with 👍 to tell me that this comment was useful, or 👎 if not (and I'll stop posting more comments like this in the future)



@router.post("/one")
def one(): ...
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The route handler 'one()' has an empty implementation using ellipsis (...). Without a proper implementation or return value, this endpoint will cause runtime errors when called. In Robyn, route handlers should return a response value. Consider returning a proper response object or JSON value like the 'three()' handler does.


React with 👍 to tell me that this comment was useful, or 👎 if not (and I'll stop posting more comments like this in the future)



@router.get("/two")
def two(): ...
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The route handler 'two()' has an empty implementation using ellipsis (...). Without a proper implementation or return value, this endpoint will cause runtime errors when called. In Robyn, route handlers should return a response value. Consider returning a proper response object or JSON value like the 'three()' handler does.


React with 👍 to tell me that this comment was useful, or 👎 if not (and I'll stop posting more comments like this in the future)

Copy link

recurseml bot commented May 27, 2025

😱 Found 5 issues. Time to roll up your sleeves! 😱

@ashupednekar ashupednekar closed this by deleting the head repository Sep 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support for structured scaffolding in create command, retaining current templates
5 participants