Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: ci

on:
push:
branches: [main]
pull_request:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
lint-type-test:
name: ${{ matrix.python-version }} · lint · type · test
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: pip

- name: Install
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"

- name: Ruff
run: ruff check .

- name: Mypy
run: mypy

- name: Pytest
run: pytest -q
File renamed without changes.
71 changes: 71 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
[build-system]
requires = ["setuptools>=68", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "shiba_mysql"
version = "2.0.0"
description = "Cliente y query builder ligero para bases de datos relacionales (MySQL hoy, multi-dialecto en camino)."
readme = "README.md"
requires-python = ">=3.10"
license = { text = "MIT" }
authors = [{ name = "Rodrigo Pino", email = "ro.pinoo18@gmail.com" }]
keywords = ["mysql", "database", "sql", "query-builder", "orm"]
classifiers = [
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Topic :: Database",
"Topic :: Software Development :: Libraries",
"Topic :: Software Development :: Libraries :: Python Modules",
"Typing :: Typed",
]
dependencies = ["pymysql>=1.1"]

[project.optional-dependencies]
dev = [
"pytest>=8",
"pytest-cov>=5",
"ruff>=0.6",
"mypy>=1.10",
]

[project.urls]
Homepage = "https://github.com/ShibaRoPinoo/Shiba-Py-Mysql"
Issues = "https://github.com/ShibaRoPinoo/Shiba-Py-Mysql/issues"

[tool.setuptools.packages.find]
include = ["shiba*", "shibamysql*"]

[tool.ruff]
line-length = 100
target-version = "py310"

[tool.ruff.lint]
select = ["E", "F", "I", "B", "UP", "SIM", "RUF", "ANN", "A"]
ignore = [
"ANN401", # permitir Any explícito
"A004", # sombreamos ConnectionError a propósito (parte de la API pública)
"UP038", # `isinstance(x, X | Y)` rompe en py3.10 sin from __future__ import
]

[tool.ruff.lint.per-file-ignores]
"tests/*" = ["ANN", "D"]

[tool.mypy]
python_version = "3.10"
strict = true
warn_unreachable = true
show_error_codes = true
files = ["shiba", "shibamysql"]

[[tool.mypy.overrides]]
module = ["pymysql.*"]
ignore_missing_imports = true

[tool.pytest.ini_options]
testpaths = ["tests"]
addopts = "-ra --strict-markers"
29 changes: 0 additions & 29 deletions setup.py

This file was deleted.

110 changes: 110 additions & 0 deletions shiba/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
"""Shiba — librería ligera para hablar con bases de datos relacionales.

Punto de entrada público:

.. code-block:: python

import shiba as s

with s.ShibaConnection(host="localhost", port=3306,
user="u", password="p") as cx:
cx.create_database("my_db")
cx.use_database("my_db")
cx.create_table("users") \\
.increments("id", primary_key=True) \\
.string("name") \\
.build()

cx.table("users").insert({"name": "John"})
rows = cx.table("users").where("name", "John").get()
"""
from __future__ import annotations

from contextlib import AbstractContextManager
from typing import TYPE_CHECKING

from shiba import error_codes
from shiba.core.query_builder import QueryBuilder
from shiba.core.table_builder import TableBuilder
from shiba.dialects.mysql import Database, MySQLDialect
from shiba.errors import (
ConnectionError,
IntegrityError,
MissingDataError,
QueryError,
SchemaError,
ShibaError,
)

if TYPE_CHECKING:
from types import TracebackType


class ShibaConnection:
"""Fachada de alto nivel sobre un :class:`Database` MySQL."""

def __init__(
self,
host: str,
port: int,
user: str,
password: str,
*,
database: str | None = None,
) -> None:
self.dialect = MySQLDialect()
self.db = Database(host, port, user, password, database=database)

# ------------------------------------------------------------------
# Context manager
# ------------------------------------------------------------------

def __enter__(self) -> ShibaConnection:
return self

def __exit__(
self,
exc_type: type[BaseException] | None,
exc: BaseException | None,
tb: TracebackType | None,
) -> None:
self.close()

def close(self) -> None:
self.db.close()

# ------------------------------------------------------------------
# API pública
# ------------------------------------------------------------------

def create_database(self, database: str) -> Database:
return self.db.create_database(database)

def use_database(self, database: str) -> Database:
return self.db.use_database(database)

def create_table(self, table_name: str) -> TableBuilder:
return TableBuilder(self.db, table_name, dialect=self.dialect)

def table(self, table_name: str) -> QueryBuilder:
return QueryBuilder(self.db, table_name, dialect=self.dialect)

def transaction(self) -> AbstractContextManager[Database]:
"""Context manager transaccional. Ver :meth:`Database.transaction`."""
return self.db.transaction()


__all__ = [
"ConnectionError",
"Database",
"IntegrityError",
"MissingDataError",
"MySQLDialect",
"QueryBuilder",
"QueryError",
"SchemaError",
"ShibaConnection",
"ShibaError",
"TableBuilder",
"error_codes",
]
1 change: 1 addition & 0 deletions shiba/core/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Núcleo agnóstico de Shiba (no depende de ningún driver concreto)."""
Loading
Loading