Shopyo api#

Shopyo has some api which eases your life

api.assets#

shopyo.api.assets.get_static(boxormodule, filename)[source]#

Generates url for static file. In Shopyo 2.0, this is a thin wrapper around the standard Flask static handler.

In Development (DEBUG=True): The request is intercepted by register_shopyo_static. In Production (DEBUG=False): The file is served from the flattened /static/modules/ folder.

Parameters
  • boxormodule (String) – box or module name e.g. box__default/auth or someothermodule

  • filename (String) – path of the file inside the box or module

Return type

URL for static file

shopyo.api.assets.register_devstatic(app, modules_path)[source]#
shopyo.api.assets.register_shopyo_static(app, modules_path)[source]#

Registers a transparent interceptor for module static files in debug mode. This allows ‘url_for(‘static’, filename=’modules/…’)’ to work dynamically during development without running collectstatic.

Parameters
  • app (Flask app) –

  • modules_path (String) – path to the modules directory

api.constants#

api.database#

shopyo.api.database.autoload_models(verbose=False)[source]#

Auto imports models from modules/ in desired file. Used so that flask_migrate does not miss models when migrating

Return type

None

api.email#

This file email.py contains functions for sending text and html rendered emails asynchronously

shopyo.api.email.send_async_email(to, subject, template, from_email=None, **kwargs)[source]#

Sends email anachronously i.e the function is non blocking. Assume email template is valid i.e it can be rendered using flask’ render_template function and both .html and .txt email template files exits

Parameters
  • to (String) – recipient of the email

  • subject (String) – subject of the email

  • template (String) – template file path to be used in email body

  • from_email (String, optional) – sender of the email. If not set MAIL_DEFAULT_SENDER is used from config.

api.enhance#

shopyo.api.enhance.base_context()[source]#

Used to define global template values

Returns

copy of dictionary

Return type

dict

api.file#

shopyo.api.file.absdiroffile(filepath)[source]#

Gives absolute directory of file, normally expects __file__ as param

Parameters

filepath (str) – path of file

Returns

Absolute dir path of file

Return type

str

shopyo.api.file.delete_file(path)[source]#
shopyo.api.file.get_folders(path)[source]#
shopyo.api.file.last_part_of_path(path)[source]#
shopyo.api.file.path_exists(path)[source]#
shopyo.api.file.trycopy(source, dest, verbose=False)[source]#

Non-ecursive copy of folder

Parameters
  • source (str) – source folder path

  • dest (str) – destination folder path

Return type

None

shopyo.api.file.trycopytree(source, dest, verbose=False)[source]#

Recursive copy of folder

Parameters
  • source (str) – source folder path

  • dest (str) – destination folder path

Return type

None

shopyo.api.file.trymkdir(path, verbose=False)[source]#

Creates dir at destination

Parameters

path (str) – path with folder already in

Return type

None

shopyo.api.file.trymkfile(path, content, verbose=False)[source]#

Creates file

Parameters
  • path (str) – path to create file with filename included

  • content (str) – file content

Return type

None

shopyo.api.file.tryrmcache(dir_name, verbose=False)[source]#

removes all __pycache__ starting from directory dir_name all the way to leaf directory

Parameters

dir_name (string) – path from where to start removing pycache

shopyo.api.file.tryrmfile(path, verbose=False)[source]#

tries to remove file path and output message to stdin or stderr. Path must point to a file

Parameters

path (string) – path of the file to remove

Returns

returns true upon successful removal false otherwise

Return type

bool

shopyo.api.file.tryrmtree(path, verbose=False)[source]#

Tries to removes an entire directory tree. Path must point to a directory. Outputs message to stdin or stderr

Parameters

path (string) – directory path to be removed

Returns

returns true upon successful return false otherwise

Return type

bool

shopyo.api.file.unique_filename(fname)[source]#

api.forms#

shopyo.api.forms.flash_errors(form)[source]#

Auto flash errors from WKHtml forms Reqwires base module or similar notification mechanism

Parameters

form (WKHtml form) –

Return type

None

api.html#

shopyo.api.html.notify(message, alert_type='primary')[source]#
Used with flash

flash(notify(‘blabla’))

Parameters
  • message (str) – message to be displayed

  • alert_type (str) – bootstrap class

Return type

None

shopyo.api.html.notify_danger(message)[source]#
shopyo.api.html.notify_info(message)[source]#
shopyo.api.html.notify_success(message)[source]#
shopyo.api.html.notify_warning(message)[source]#

api.info#

shopyo.api.info.printinfo()[source]#

api.models#

Enhanced DB-related helper utilities for Flask applications. Provides powerful mixins and base classes for rapid development.

class shopyo.api.models.CRUDMixin[source]#

Bases: object

Mixin that adds convenience methods for CRUD (create, read, update, delete) operations.

classmethod bulk_create(items: List[Dict[str, Any]]) List[shopyo.api.models.T][source]#

Create multiple records at once.

Parameters

items (List[Dict[str, Any]]) – List of dictionaries containing record data

Returns

List of created records

Return type

List[T]

classmethod create(**kwargs) shopyo.api.models.T[source]#

Create a new record and save it in the database.

Returns

The created record

Return type

T

delete(commit: bool = True) Optional[shopyo.api.models.T][source]#

Remove the record from the database.

Parameters

commit (bool) – Whether to commit the changes

Returns

The deleted record if committed, None otherwise

Return type

Optional[T]

save(commit: bool = True) shopyo.api.models.T[source]#

Save the record.

Parameters

commit (bool) – Whether to commit the changes

Returns

The saved record

Return type

T

update(commit: bool = True, **kwargs) Optional[shopyo.api.models.T][source]#

Update specific fields of a record.

Parameters
  • commit (bool) – Whether to commit the changes

  • **kwargs – Fields to update

Returns

The updated record if committed, None otherwise

Return type

Optional[T]

class shopyo.api.models.PaginationMixin[source]#

Bases: object

Mixin that adds pagination functionality.

classmethod paginate(page: int = 1, per_page: int = 20) Dict[str, Any][source]#

Paginate records.

Parameters
  • page (int) – Page number

  • per_page (int) – Number of items per page

Returns

Dictionary containing paginated items and metadata

Return type

Dict[str, Any]

class shopyo.api.models.PkModel(**kwargs: Any)[source]#

Bases: shopyo.api.models.YoModel

Base model class that includes CRUD convenience methods, plus adds a ‘primary key’ column named ‘id’.

classmethod bulk_create(items: List[Dict[str, Any]]) List[shopyo.api.models.T]#

Create multiple records at once.

Parameters

items (List[Dict[str, Any]]) – List of dictionaries containing record data

Returns

List of created records

Return type

List[T]

classmethod create(**kwargs) shopyo.api.models.T#

Create a new record and save it in the database.

Returns

The created record

Return type

T

delete(commit: bool = True) Optional[shopyo.api.models.T]#

Remove the record from the database.

Parameters

commit (bool) – Whether to commit the changes

Returns

The deleted record if committed, None otherwise

Return type

Optional[T]

classmethod get_by_id(record_id: Union[int, str]) Optional[shopyo.api.models.T][source]#

Get record by ID.

Parameters

record_id (Union[int, str]) – ID of record to get

Returns

Object identified by record_id if any, None otherwise

Return type

Optional[T]

classmethod get_or_404(record_id: Union[int, str]) shopyo.api.models.T[source]#

Get record by ID or raise 404 error.

Parameters

record_id (Union[int, str]) – ID of record to get

Returns

Object identified by record_id

Return type

T

Raises

werkzeug.exceptions.NotFound – If record not found

id = Column(None, Integer(), table=None, primary_key=True, nullable=False)#
metadata = MetaData()#
query: t.ClassVar[Query]#

A SQLAlchemy query for a model. Equivalent to db.session.query(Model). Can be customized per-model by overriding query_class.

Warning

The query interface is considered legacy in SQLAlchemy. Prefer using session.execute(select()) instead.

query_class#

alias of flask_sqlalchemy.query.Query

registry = <sqlalchemy.orm.decl_api.registry object>#
save(commit: bool = True) shopyo.api.models.T#

Save the record.

Parameters

commit (bool) – Whether to commit the changes

Returns

The saved record

Return type

T

update(commit: bool = True, **kwargs) Optional[shopyo.api.models.T]#

Update specific fields of a record.

Parameters
  • commit (bool) – Whether to commit the changes

  • **kwargs – Fields to update

Returns

The updated record if committed, None otherwise

Return type

Optional[T]

class shopyo.api.models.SearchMixin[source]#

Bases: object

Mixin that adds search functionality.

classmethod search(query: str, fields: List[str]) sqlalchemy.orm.query.Query[source]#

Search records by query string in specified fields.

Parameters
  • query (str) – Search query

  • fields (List[str]) – List of field names to search in

Returns

SQLAlchemy query with search filters

Return type

Query

class shopyo.api.models.SoftDeleteMixin[source]#

Bases: object

Mixin that adds soft delete functionality.

classmethod get_active() sqlalchemy.orm.query.Query[source]#

Get all non-deleted records.

is_deleted = Column(None, Boolean(), table=None, nullable=False, default=ScalarElementColumnDefault(False))#
soft_delete(commit: bool = True) Optional[shopyo.api.models.SoftDeleteMixin][source]#

Soft delete the record by setting is_deleted to True.

class shopyo.api.models.TimestampMixin[source]#

Bases: object

Mixin that adds created_at and updated_at timestamps.

created_at = Column(None, DateTime(), table=None, nullable=False, default=CallableColumnDefault(<function TimestampMixin.<lambda>>))#
updated_at = Column(None, DateTime(), table=None, nullable=False, onupdate=CallableColumnDefault(<function TimestampMixin.<lambda>>), default=CallableColumnDefault(<function TimestampMixin.<lambda>>))#
class shopyo.api.models.ValidationMixin[source]#

Bases: object

Mixin that adds validation functionality.

is_valid() bool[source]#

Check if the model instance is valid.

validate() List[str][source]#

Validate the model instance.

Returns

List of validation errors, empty if valid

Return type

List[str]

class shopyo.api.models.YoModel(**kwargs: Any)[source]#

Bases: shopyo.api.models.CRUDMixin, sqlalchemy.orm.decl_api.Model

Base model class that includes CRUD convenience methods.

classmethod bulk_create(items: List[Dict[str, Any]]) List[shopyo.api.models.T]#

Create multiple records at once.

Parameters

items (List[Dict[str, Any]]) – List of dictionaries containing record data

Returns

List of created records

Return type

List[T]

classmethod create(**kwargs) shopyo.api.models.T#

Create a new record and save it in the database.

Returns

The created record

Return type

T

delete(commit: bool = True) Optional[shopyo.api.models.T]#

Remove the record from the database.

Parameters

commit (bool) – Whether to commit the changes

Returns

The deleted record if committed, None otherwise

Return type

Optional[T]

metadata = MetaData()#
query: t.ClassVar[Query]#

A SQLAlchemy query for a model. Equivalent to db.session.query(Model). Can be customized per-model by overriding query_class.

Warning

The query interface is considered legacy in SQLAlchemy. Prefer using session.execute(select()) instead.

query_class#

alias of flask_sqlalchemy.query.Query

registry = <sqlalchemy.orm.decl_api.registry object>#
save(commit: bool = True) shopyo.api.models.T#

Save the record.

Parameters

commit (bool) – Whether to commit the changes

Returns

The saved record

Return type

T

update(commit: bool = True, **kwargs) Optional[shopyo.api.models.T]#

Update specific fields of a record.

Parameters
  • commit (bool) – Whether to commit the changes

  • **kwargs – Fields to update

Returns

The updated record if committed, None otherwise

Return type

Optional[T]

api.module#

class shopyo.api.module.ModuleHelp(dunderfile, dundername)[source]#

Bases: object

context()[source]#
get_self_static(filename)[source]#
method(methodname)[source]#
redirect_url(url, **kwargs)[source]#
render(filename, **kwargs)[source]#

renders file.html found in module/templates/module/file.html

shopyo.api.module.iter_modules(project_root)[source]#

Yields (module_name, module_path) for every valid module in the project, transparently handling both standalone modules and 'box__' nested modules.

Yields

module_name (str) – Dot-separated python path (e.g., ‘modules.box__shop.cart’) module_path (str): Absolute file system path to the module directory.

api.perms#

Policy-based authorization system replacing is_admin checks with a Permission + PolicyEngine approach.

Usage:

from shopyo.api.perms import PolicyEngine, Permission

engine = PolicyEngine()

# Grant permissions to roles
engine.grant("admin", Permission.ADMIN_PANEL_ACCESS, Permission.USER_MANAGE)
engine.grant("editor", Permission.CONTENT_MANAGE)

# Define custom policy checks
engine.define("perm.CONTENT_PUBLISH", lambda user, resource: user.id == resource.owner_id)

# Use as a decorator on views
@engine.require(Permission.ADMIN_PANEL_ACCESS)
def dashboard():
    return "Admin dashboard"

# Programmatic check
if engine.has_permission(current_user, Permission.USER_MANAGE):
    ...
class shopyo.api.perms.Permission(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]#

Granular permissions for the Shopyo authorization system.

Members:

USER_MANAGE: Create, update, delete users. USER_READ: View user profiles and lists. ROLE_MANAGE: Create, update, delete roles. SETTINGS_MANAGE: Modify application settings. CONTENT_MANAGE: Create, update, delete content. CONTENT_PUBLISH: Publish or approve content. DASHBOARD_VIEW: Access the admin dashboard. ADMIN_PANEL_ACCESS: Enter the admin panel at all.

ADMIN_PANEL_ACCESS = 8#
CONTENT_MANAGE = 5#
CONTENT_PUBLISH = 6#
DASHBOARD_VIEW = 7#
ROLE_MANAGE = 3#
SETTINGS_MANAGE = 4#
USER_MANAGE = 1#
USER_READ = 2#
class shopyo.api.perms.PolicyEngine[source]#

Central authorization engine combining role-based and policy-based access.

Usage:

engine = PolicyEngine()
engine.grant("admin", Permission.ADMIN_PANEL_ACCESS)
engine.define("perm.CONTENT_PUBLISH", lambda u, r: u.id == r.owner_id)

# Decorator on views
@engine.require(Permission.ADMIN_PANEL_ACCESS)
def dashboard(): ...

# Programmatic check
engine.has_permission(current_user, Permission.USER_MANAGE)
define(name: str, check: Callable[[...], bool])[source]#

Register a custom policy check.

Parameters
  • name – Policy name (convention: "perm.<PERMISSION_NAME>").

  • check – Callable (user, resource=None) -> bool.

grant(role_name: str, *permissions: shopyo.api.perms.Permission)[source]#

Assign one or more permissions to a role.

Parameters
  • role_name – Name of the role (e.g. "admin", "editor").

  • permissions – One or more Permission enum members.

has_permission(user, permission: shopyo.api.perms.Permission, resource: Any = None) bool[source]#

Check whether a user holds a given permission.

Evaluation order:
  1. Admin users bypass all checks (transitional).

  2. Any role the user belongs to is checked for the permission.

  3. If a custom policy perm.<PERMISSION_NAME> exists, it is invoked with (user, resource).

Parameters
  • user – Flask-Login User instance (or proxy).

  • permission – The Permission enum member to check.

  • resource – Optional resource object for resource-aware policies.

Returns

True if the user has the permission, False otherwise.

require(permission: shopyo.api.perms.Permission, resource: Any = None)[source]#

Decorator factory that protects routes with a permission check.

Returns 401 if the user is unauthenticated, 403 if the user lacks the required permission.

Parameters
  • permission – The Permission required to access the route.

  • resource – Optional resource passed to the policy check.

Example:

@blueprint.route("/admin")
@engine.require(Permission.ADMIN_PANEL_ACCESS)
def admin_index():
    return "Admin panel"
class shopyo.api.perms.Policy(name: str, check: Callable[[...], bool])[source]

A named policy with a callable check.

name

Unique policy identifier (e.g. "perm.CONTENT_PUBLISH").

Type

str

check

Callable (user, resource=None) -> bool.

Type

Callable[[…], bool]

api.security#

shopyo.api.security.generate_csrf_token()[source]#

Generate a secure CSRF token.

Generates a secure CSRF token and stores it in the session if not present.

Returns

The generated CSRF token.

Return type

str

shopyo.api.security.get_safe_redirect(url)[source]#

Returns url for root path if url not safe

Parameters

url (String) – url

Return type

url or root page

shopyo.api.security.inject_csrf_token()[source]#

Inject CSRF token into Jinja2 template context.

Returns

Dictionary containing the CSRF token for template context.

Return type

dict

shopyo.api.security.is_safe_redirect_url(target)[source]#

Corresponds to Djangos is_safe_url

Parameters

target (String) – url

Return type

bool

shopyo.api.security.validate_csrf_token(token)[source]#

Validate the CSRF token using constant-time comparison.

Parameters

token (str) – The CSRF token to validate.

Returns

True if the token is valid, False otherwise.

Return type

bool

api.templates#

shopyo.api.templates.yo_get_macro(template_name, macro_name)[source]#

Gets a macro from a template for use in Python code.

Usage:

my_macro = yo_get_macro(“macros.html”, “my_macro”) html = my_macro(arg1, arg2)

shopyo.api.templates.yo_render(template, context_dict)[source]#

Renders template.

Usage: yo_render(“index.html”, {“x”: 1, “y”: 2}) Same as render_template(“index.html”, x=1, y=2)

Parameters
  • template (String) – template accessing

  • context_dict (Dict) – Template values

Return type

html of template

shopyo.api.templates.yo_render_string(template_string, context_dict)[source]#

Renders a template from a string.

Usage: yo_render_string(“Hello {{ name }}!”, {“name”: “World”})

shopyo.api.templates.yo_safe(html_string)[source]#

Marks a string as safe for rendering (prevents auto-escaping).

Usage: yo_safe(“<b>bold</b>”)

api.validators#

shopyo.api.validators.get_module_path_if_exists(name)[source]#
shopyo.api.validators.is_alpha_num_underscore(name)[source]#

returns whether the given name contains only alphanumeric or underscore

Parameters

name (str) – to value to check for alphanumeric or underscore

Returns

returns True if name is alphanumeric, False otherwise

Return type

bool

shopyo.api.validators.is_empty_str(string)[source]#
shopyo.api.validators.is_valid_slug(text)[source]#
shopyo.api.validators.is_valid_url(url)[source]#
shopyo.api.validators.verify_slug(form, field)[source]#

api.response#

response.py

Utilities for standardized API responses in Flask.

shopyo.api.response.error_response(message, status=400, errors=None, **kwargs)[source]#

Return a standard error JSON response.

Parameters
  • message (str) – Error message.

  • status (int) – HTTP status code.

  • errors (dict or list, optional) – Additional error details.

  • **kwargs – Additional fields to include.

Returns

JSON response.

Return type

Flask Response

shopyo.api.response.json_response(data=None, status=200, message=None, **kwargs)[source]#

Return a standard JSON response.

Parameters
  • data (dict or list, optional) – The main data payload.

  • status (int) – HTTP status code.

  • message (str, optional) – Optional message.

  • **kwargs – Additional fields to include.

Returns

JSON response.

Return type

Flask Response

shopyo.api.response.paginated_response(items, total, page, per_page, status=200, message=None, **kwargs)[source]#

Return a paginated JSON response.

Parameters
  • items (list) – List of items for the current page.

  • total (int) – Total number of items.

  • page (int) – Current page number.

  • per_page (int) – Items per page.

  • status (int) – HTTP status code.

  • message (str, optional) – Optional message.

  • **kwargs – Additional fields to include.

Returns

JSON response.

Return type

Flask Response

api.endpoint#

endpoint.py

A powerful utility for building RESTful API endpoints in Flask applications. Provides decorators and base classes for rapid API development with common patterns.

class shopyo.api.endpoint.APIEndpoint(model_class: Type[shopyo.api.endpoint.T])[source]#

Bases: object

A utility class for building RESTful API endpoints with common patterns. Provides decorators and methods for handling CRUD operations, validation, and response formatting.

format_response(data: Any) Dict[str, Any][source]#

Format response data. Override this method in subclasses.

Parameters

data (Any) – Data to format

Returns

Formatted response data

Return type

Dict[str, Any]

get_query_filters() Dict[str, Any][source]#

Get query filters from request args. Override this method in subclasses.

Returns

Query filters

Return type

Dict[str, Any]

handle_create() tuple[source]#

Handle POST request for creating a new item.

Returns

Flask response tuple

Return type

tuple

handle_delete(item_id: Union[int, str]) tuple[source]#

Handle DELETE request for removing an item.

Parameters

item_id (Union[int, str]) – Item ID

Returns

Flask response tuple

Return type

tuple

handle_get(item_id: Union[int, str]) tuple[source]#

Handle GET request for retrieving a single item.

Parameters

item_id (Union[int, str]) – Item ID

Returns

Flask response tuple

Return type

tuple

handle_list(page: int = 1, per_page: int = 20) tuple[source]#

Handle GET request for listing items with pagination.

Parameters
  • page (int) – Page number

  • per_page (int) – Items per page

Returns

Flask response tuple

Return type

tuple

handle_update(item_id: Union[int, str]) tuple[source]#

Handle PUT/PATCH request for updating an item.

Parameters

item_id (Union[int, str]) – Item ID

Returns

Flask response tuple

Return type

tuple

validate_request(data: Dict[str, Any]) List[str][source]#

Validate request data. Override this method in subclasses.

Parameters

data (Dict[str, Any]) – Request data to validate

Returns

List of validation errors, empty if valid

Return type

List[str]

shopyo.api.endpoint.api_endpoint(model_class: Type[shopyo.api.endpoint.T])[source]#

Decorator to create RESTful API endpoints for a model.

Parameters

model_class (Type[T]) – The SQLAlchemy model class to use

Returns

Decorated function that returns APIEndpoint instance

Return type

Callable