Skip to content
Open
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
40 changes: 40 additions & 0 deletions .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python

name: Python package

on:
push:
branches: [ "stable" ]
pull_request:
branches: [ "stable" ]

jobs:
build:

runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
python-version: ["3.9", "3.10", "3.11"]

steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install flake8 pytest
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Test with pytest
run: |
pytest
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -129,4 +129,5 @@ dmypy.json
.pyre/
.vscode

*.json
*/×.json*
×.json*
61 changes: 15 additions & 46 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# **_FoxLin_**
simple, fast, funny column based dbms on python

![# **_FoxLin_** ](./poster.png)
[![Poetry](https://img.shields.io/endpoint?url=https://python-poetry.org/badge/v0.json)](https://python-poetry.org/)


### philosophy
Foxlin is developed to create the best User experience of DBMS interface for mini projects
Expand All @@ -20,19 +22,16 @@ also have powerfull process managers.
* query cache system # TODO in 1.2

### Quick access :
- [docs](https://GitHub.com/MisanoGo/FoxLin/blob/stable/docs)
- pypi : [todo]()
- [code](https://GitHub.com/MisanoGo/FoxLin)
- [docs](https://GitHub.com/MirS0bhan/FoxLin/blob/stable/docs)
- [pypi](https://pypi.org/project/foxlin/)
- [code](https://GitHub.com/MirS0bhan/FoxLin)


### requirements
* numpy
* pydantic
* orjson

### Table Structure
TODO

## installation

### from pypi
Expand All @@ -44,14 +43,16 @@ $ pip install foxlin
``` console
$ git clone https://github.com/MisanoGo/FoxLin && cd FoxLin
$ pytest # run tests
$ pip install -e setup.py
$ poetry install
$ poetry build
$ pip install dist/foxlin-*.whl
```

## simple usage :
```Python
from foxlin import FoxLin, Schema, column

class MyTable(schema):
class MyTable(Schema):
# define your teble schema
name: str = column(dtype=str)
age: int = column(dtype=int)
Expand All @@ -61,9 +62,9 @@ class MyTable(schema):
db = FoxLin('./db.json', MyTable) # create db

data = [
MyTable(name='brian', age=37, username='biran1999', password='123456789')
MyTable(name='brian', age=37, username='biran1999', password='123456789'),
MyTable(name='sobhan', age=20, username='misano', password='#197382645#'),
MyTable(name='Tommy', age=15, username='god_of_war', password='123QWEasdZXC')
MyTable(name='Tommy', age=15, username='god_of_war', password='123QWEasdZXC'),
MyTable(name='Ali', age=20, username='p_1969_q', password='@QWE123KFH@')
]

Expand All @@ -80,23 +81,6 @@ print(record.name, record.username, record.password)
### Note
- every crud operation on db has O(record_count * column_count) order

## FoxLin Story

Sophy was a curious girl, always looking to learn and explore new things. One day, she found herself surrounded by a dense forest, enchanted by the beauty and mystery it held.

As she walked further into the woods, she stumbled upon a Fox named Lin. Unlike other animals that would normally run away, Lin was as curious as Sophy was. Struck by their shared curiosity, they started talking.

Sophy soon realized that Lin was not just any fox but an intelligent fox with considerable knowledge in the world of data. Excited by this, Sophy began asking Lin questions, eager to learn as much as she could.

As they continued their conversation, they stumbled upon a huge database hidden in the forest that no one else had any idea about. Together, they navigated the vast expanse of knowledge within the database, reading and learning so many new things.

Sophy and Lin lost track of time, as they quenched their thirst for knowledge in this world of data.

As they walked back towards their homes, both of them were overcome with a sense of fulfillment and satisfaction. They realized that the world was full of secrets waiting to be unraveled, and it was up to them to quench their thirst for knowledge and explore all the possibilities.

From that day on, Sophy and Lin would often visit the database and other places together, learning new things and exploring the world of data. They knew that knowledge had no limit and that there was always something new to discover, and it was this knowledge that would bring them closer every day.
(generated by ai).


**my experience from this project**
* in operations with high order, when have many static if,else(no change in all of program)
Expand All @@ -105,30 +89,15 @@ From that day on, Sophy and Lin would often visit the database and other places

## TODO

##### TODO in 1.0
- [x] crud
- [x] level base operation manager
- [x] self log system
- [x] session model
- [x] transaction but by grouping commits **not ACDI**
- [x] write test
- [x] benchmarck test
- [x] add logs to .logs file
- [x] define logs in operation statment and able to setting by user
- [x] generate logs
- [x] quering
- [x] auto backup

##### TODO at 1.1
##### TODO at 1.0.0
− implement memory & storage box with rust/zig
- asynchronus
- transaction ACDI
- define Group By & HAVING
- log time duration of operation's
- migrate
- stub
- data compretion

##### TODO at 1.2
- memory cache system
- query cache system
- session privilege's
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
24 changes: 10 additions & 14 deletions foxlin/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,18 @@
StorageBox,
MemBox,
LogBox,
)

from .operation import (
DBOperation,
CRUDOperation,
DBCreate,
DBRead,
DBUpdate,
DBDelete,

DBLoad,
DBDump
DBDump,
DBLoad
)

from .column import (
Expand All @@ -25,23 +28,16 @@
column
)

from .den import (
Den,
DenManager
from .session import (
Session,
SessionManager
)

from .query import FoxQuery

from .sophy import (
from .database import (
Schema,
DBCarrier,

ID,
COLUMN,
LEVEL,

DBOperation,
Log
)

from .fox import FoxLin
21 changes: 3 additions & 18 deletions foxlin/core/box/__init__.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,5 @@
from .fox import FoxBox, BoxManager
from .memory import (
CRUDOperation,
DBCreate,
DBRead,
DBUpdate,
DBDelete,

MemBox
)

from .storage import (
StorageBox,

CreateJsonDB,
DBLoad,
DBDump
)
from .base import FoxBox, BoxManager

from .memory import MemBox
from .storage import StorageBox
from .log import LogBox
82 changes: 82 additions & 0 deletions foxlin/core/box/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
from typing import Callable, Dict, List, Optional, Set

from foxlin.core.database import LEVEL
from foxlin.core.operation import DBOperation

NONE = LEVEL('NONE')

class FoxBox:
"""
Foxbox is abs class as a operate manager for CRUD and user-self operator definated
can use in states of memory-cache and file-based db

dbom: database operation manager
"""
level: LEVEL = NONE # set level of operation

def operate(self, obj: DBOperation):
"""
we use the name has defined in operations.name for finding the function we need to use
"""
operator: Callable = getattr(self, obj.op_name.lower()+'_op')
operator(obj)

if obj.callback:
if self.level == obj.callback_level:
obj.callback(obj)

class BoxManager:
"""
Manages a collection of FoxBox instances for routing operations.

Parameters
----------
*box: FoxBox
FoxBox instances to manage.
auto_enable: bool, optional
Automatically enable added boxes (default is True).
"""

def __init__(self, *box: FoxBox, auto_enable: bool = True):
self.box_list: Dict[LEVEL, FoxBox] = {}
self.__box_list: Dict[LEVEL, FoxBox] = {}
self.add_box(*box, auto_enable=auto_enable)

def operate(self, op: DBOperation) -> None:
"""Send an operation to boxes that can handle it."""
level_list: Set[LEVEL] = set(op.levels) & self.__box_list.keys()
for level in level_list:
self.__box_list[level].operate(op)

def add_box(self, *box: FoxBox, auto_enable: bool) -> None:
"""Add one or more boxes to the manager."""
box_tray: Dict[LEVEL, FoxBox] = {}

for b in box:
if not isinstance(b, FoxBox):
raise TypeError(f"Expected instance of FoxBox, got {type(b).__name__}")
box_tray[b.level] = b

if auto_enable:
self.__box_list.update(box_tray)

self.box_list.update(box_tray)

def remove_box(self, level: LEVEL) -> Optional[FoxBox]:
"""Remove a box by its level."""
self.box_list.pop(level, None)
return self.__box_list.pop(level, None) # Return the removed box or None

def enable_box(self, level: LEVEL) -> bool:
"""Enable a box to handle operations for the specified level."""
if level in self.box_list:
self.__box_list[level] = self.box_list[level]
return True
return False

def disable_box(self, level: LEVEL) -> bool:
"""Disable a box from handling operations for the specified level."""
if level in self.__box_list:
self.__box_list.pop(level)
return True
return False
Loading