Skip to content

Commit 5c2decb

Browse files
committed
used generators as custom functions, added condition to check if args are provided in tuple, re wrote the documentation.
1 parent 89dbc60 commit 5c2decb

6 files changed

Lines changed: 118 additions & 56 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
src/sqlsy.egginfo*
22
src/sqlsy/__pycache__/*
3+
dist/*
4+

README.md

Lines changed: 68 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
# sqlsy
2+
![badge4](https://img.shields.io/badge/MIT-License-red)
3+
![badge3](https://img.shields.io/badge/version-v1.0.0-magenta)
24
![badge1](https://img.shields.io/static/v1?label=python%203&message=SQL&color=blue)
35
![badge2](https://img.shields.io/static/v1?label=easy&message=install&color=green)
46

@@ -9,7 +11,8 @@ A simple Python Module to easy fill your sql tables with data.
911
pip install sqlsy
1012
```
1113

12-
A python module to easy filling in dummy data insde mysql databases.
14+
## Quick Usage
15+
A simple script to fill in data inside of a mysql table
1316

1417
```python
1518
from sqlsy import Engine
@@ -19,63 +22,99 @@ from sqlsy import Int, VarChar # sql datatypes to define schema
1922
config = {
2023
'user':'username',
2124
'password':'pas@word',
22-
'host':'localhost'
25+
'host':'localhost',
26+
'database':'dbName' # database to use: optional as it can be selected using a method
2327
}
2428

25-
# define the schema of the table to fill
29+
# custom function should be a generator
30+
def get_id(n1, n2):
31+
i = n1
32+
while i < n2:
33+
yield i
34+
i += 1
2635

36+
# define the schema of the table to fill
2737
# hook specifies what data to generate
2838
schema = {
29-
'id':Int(hook='sequence', args=[0,30]), # generates numbers 0 - 30 including 30
39+
'id':Int(custom_func=get_id(0,30)), # generates numbers 0 - 30 including 30
3040
'name':VarChar(hook='name'), # here generate fake names
31-
'job':VarChar(hook='job') # here generate fake jobs
41+
'ph_number':VarChar(hook='phone_number') # here generate fake jobs
3242
}
3343

3444

3545
# create engine instance
3646
engine = Engine(config)
3747

38-
# create a database to store above table, if not already created
39-
engine.create_db('employee')
40-
41-
# create the table with above schema
42-
engine.create_table('person', schema)
43-
48+
# ASSUMING that the table is already created
4449
# call the method to fill in the table
4550
# 101 rows as id can take values from 0 to 30 = 31
4651
engine.fill_table("person", schema, 31) # give it tablename, schema of table and no of rows.
4752

4853
# print the table if you want
4954
engine.print_table("table_name")
5055

51-
# delete all the data added to the table
52-
engine.clear_table("table_name")
56+
# close the connection
57+
engine.close()
58+
```
5359

54-
# drop the database if you want to
55-
engine.drop_db("employee")
60+
## API provided by Engine Class
61+
The API include following methods and attributes:
62+
Let the `engine` be an instance of `Engine` class
63+
```python
64+
engine = Engine(config)
5665
```
66+
### Attributes
67+
- `engine.config` : Stores the provided config for mysql api connection
68+
- `engine.conn` : It is what stores the connection object after connection is opened.
69+
- `engine.cursor` : It stores the cursor to execute queries on the database.
70+
71+
## Methods
72+
- `engine.fetch(table_name, [col_name1, col_name2])` : Grab the data from the specified columns directly
73+
74+
- `engine.create_db(database_name)` : Creates a database with name as provided in argument.
5775

58-
![image](https://user-images.githubusercontent.com/76217003/230254219-aafe049f-93cd-45ff-ab97-22d960785add.png)
76+
- `engine.create_table(table_name, schema)` : Creates a table with the specified Schema.
5977

78+
- `engine.drop_db(db_name)` : Drops the database if it exists
79+
80+
- `engine.drop_table(tb_name)` : Drops the table if it exists
81+
82+
- `engine.fill_table(tb_name, tb_schema, n_rows)` : Fills the table with tb_name as name and tb_schema as schema with n_rows of data. Make sure the provided hooks or custom_functions generate equal to or more than n_rows of data.
83+
84+
- `engine.print_table(tb_name)` : It prints the table in pretty format for you to see.
85+
86+
- `engine.clear_table(tb_name)` : It removes all the data from the table with provided table name
87+
88+
- `engine.close()` : It closes the connection to the database. If not called, the connection will be closed when `engine` object is destroyed.
6089

6190
# Schema Functions to specify datatypes
62-
`Int` - means "INT" of SQL.
6391

64-
`Float` - means "Float" of SQL. Doesnt support size and pricision as recommended by the Mysql docs.
92+
### How to Describe Schema
93+
> Schema can be describe by using the provided functions which are documented below:
94+
95+
1. `Int` - means "INT" of SQL.
96+
97+
2. `Float` - means "Float" of SQL. Doesnt support size and pricision as recommended by the Mysql docs.
98+
99+
3. `Char` - means "CHAR" of SQL. By default of size 255.
100+
101+
4. `VarChar` - means "VARCHAR" of SQL. By default of size 255 # does not take size like in SQL.
65102

66-
`Char` - means "CHAR" of SQL. By default of size 255.
103+
### Equivalent to SQL counterparts
104+
`Date`, `DateTime`, `Time`, `Timestamp`
67105

68-
`VarChar` - means "VARCHAR" of SQL. By default of size 255 # does not take size like in SQL.
106+
# How Data is Generated
107+
This module is designed such that the below provided hooks actually are mapped to functions which are responsible for data generation.
69108

70-
`Date` - means DATE of sql, `DateTime`, `Time` and `Timestamp`
109+
Below are the Hooks which can be used to generate data automatically, also Custom Generator functions can be provided which will then be called to generate data.
71110

72111

73-
# Hooks
74-
### Int/Float
112+
### Hooks for Int / Float type data
75113
`random_int` : generates random integers - provide range with arguments
76114
```python
115+
# schema description
77116
tb_name = {
78-
'age':Int(hook='random_int', args=[10,50])
117+
'age':Int(hook='random_int', args=(10,50))
79118
}
80119
```
81120

@@ -85,26 +124,26 @@ tb_name = {
85124

86125
```python
87126
schema = {
88-
'id':Float(hook='random_float', args=[50,200])
127+
'id':Float(hook='random_float', args=(50,200))
89128
}
90129
```
91130

92131
`sequence` : generates sequenctial numbers from the range given using `args`.
93132

94133
```python
95134
schema = {
96-
'id':Int(hook='sequence', args=[50,100])
135+
'id':Int(hook='sequence', args=(50,100))
97136
}
98137
```
99138

100139
`random_choice` : Randomly chooses values from a given list
101140
```python
102141
schema = {
103-
'stream':VarChar(hook='random_choice', args=[['bca', 'btech', 'commerce', 'mtech']])
142+
'stream':VarChar(hook='random_choice', args=(['bca', 'btech', 'commerce', 'mtech']))
104143
}
105144
```
106145

107-
### VarChar/Char
146+
### Hooks for VarChar / Char type data
108147
`name` : generates full names
109148

110149
`first_name` : generates first names
@@ -124,7 +163,7 @@ schema = {
124163
`phone_number` : generates phone numbers
125164

126165

127-
### Date/DateTime/Time/Timestamp
166+
### Hooks for Date/DateTime/Time/Timestamp type data
128167

129168
`future_datetime` : generates a future datetime
130169

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "sqlsy"
7-
version = "0.0.4"
7+
version = "1.0.0"
88
description = "Fill your database Quickly with dummy data"
99
readme = "README.md"
1010
authors = [{ name="shoaib wani", email="shoaibwani010@gmail.com"}]

src/sqlsy/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from .engine import Engine
2+
from .schema import Int, VarChar, Float, Char, Date, DateTime, Time, Timestamp

src/sqlsy/engine.py

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ class Engine:
2020
def __init__(self, config: dir):
2121
self.config = config
2222
self.conn = self.connect_db()
23-
24-
# cursor
2523
self.cursor = self.conn.cursor()
2624

2725

@@ -93,7 +91,7 @@ def create_table(self, tb_name:str, schema:dir):
9391
# drop the database
9492
def drop_db(self, db_name):
9593
try:
96-
self.cursor.execute("drop database {}".format(db_name))
94+
self.cursor.execute("drop database if exists {}".format(db_name))
9795
self.conn.commit()
9896
cprint("[+] Dropped {} database".format(db_name), 'blue')
9997
except mysql.connector.Error as err:
@@ -103,7 +101,7 @@ def drop_db(self, db_name):
103101
# drop the table
104102
def drop_table(self, tb_name):
105103
try:
106-
self.cursor.execute("drop table {}".format(tb_name))
104+
self.cursor.execute("drop table if exists {}".format(tb_name))
107105
self.conn.commit()
108106
cprint("[+] Dropped Table {}".format(tb_name), 'blue')
109107
except mysql.connector.Error as err:
@@ -160,15 +158,20 @@ def fill_table(self, table_name:str, schema:dict, n: int):
160158

161159
for i in track(range(n), description=colored(f"[+] Working on {table_name}: ", 'blue')):
162160
data.clear()
163-
164-
for col,attr in zip(schema.keys(),schema.values()):
165-
self.set_col(col)
166-
if attr['args'] == None:
167-
data.append(attr['callback']())
168-
else:
169-
# pass the arguments in
170-
data.append(attr['callback'](*attr['args']))
171-
161+
try:
162+
for col,attr in zip(schema.keys(),schema.values()):
163+
self.set_col(col)
164+
if 'custom_flag' in attr.keys():
165+
data.append(next(attr['callback']))
166+
elif attr['args'] == None:
167+
data.append(attr['callback']())
168+
else:
169+
# pass the arguments in
170+
data.append(attr['callback'](*attr['args']))
171+
except StopIteration:
172+
cprint("[x] The custom function generated less data then target rows!", "red")
173+
self.clear_table(table_name)
174+
exit(0)
172175
try:
173176
# add the data
174177
self.cursor.execute(query % tuple(data))
@@ -216,10 +219,18 @@ def print_table(self, table_name:str):
216219
# print the table
217220
console.print(table)
218221

222+
def close(self):
223+
try:
224+
self.conn.close()
225+
cprint("[+] Closed the Connection to database", "green")
226+
except mysql.connector.Error as err:
227+
cprint('[x] Couldnt close the connection : {}'.format(err), "red")
228+
219229

220230
def __del__(self):
221231
try:
222-
self.conn.close()
223-
cprint("[+] Closed the connection to mysql", "green")
232+
if self.conn.is_connected():
233+
self.conn.close()
234+
cprint("[+] Closed the connection to mysql", "green")
224235
except mysql.connector.Error as err:
225236
cprint("[x] Couldn't close connection : {}".format(err), "red")

src/sqlsy/schema.py

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,23 @@
44
####
55

66
from termcolor import cprint
7-
from .mapping import mapping
7+
from .utils.mapping import mapping
88

99

1010
# Sql datatypes
1111
def datatype(func):
12-
def sql_dtype(*, hook=None, custom_func=None, args:list = None, constraints:list=None):
12+
def sql_dtype(hook=None, custom_func=None, args:tuple = None, constraints:list=None):
1313

1414
mini_scheme = {}
1515

1616
# store the args
17-
mini_scheme['args'] = args
17+
if args and isinstance(args, tuple):
18+
mini_scheme['args'] = args
19+
elif args:
20+
cprint("[x] Provide Arugments in a Tuple", 'red')
21+
exit(1)
22+
else:
23+
mini_scheme['args'] = args
1824
mini_scheme['constraints'] = constraints
1925

2026
# check for data generator
@@ -23,6 +29,8 @@ def sql_dtype(*, hook=None, custom_func=None, args:list = None, constraints:list
2329
throw()
2430

2531
elif custom_func:
32+
# set flag for custom function
33+
mini_scheme['custom_flag'] = True
2634
mini_scheme['callback'] = custom_func
2735

2836
elif hook:
@@ -36,50 +44,50 @@ def sql_dtype(*, hook=None, custom_func=None, args:list = None, constraints:list
3644

3745

3846
@datatype
39-
def Int(*, hook=None, custom_func=None, args:list=None, this=None):
47+
def Int(hook=None, custom_func=None, args:list=None, this=None):
4048
# used in dynamic query building
4149
this['type'] = 'int'
4250
return this
4351

4452

4553
@datatype
46-
def Float(*, hook=None, custom_func=None, args:list=None, this=None):
54+
def Float(hook=None, custom_func=None, args:list=None, this=None):
4755
# store the float type
4856
this['type'] = 'float'
4957
return this
5058

5159

5260
@datatype
53-
def Char(*, hook=None, custom_func=None, args:list=None, this=None):
61+
def Char(hook=None, custom_func=None, args:list=None, this=None):
5462
this['type'] = 'char(255)'
5563
return this
5664

5765

5866
@datatype
59-
def VarChar(*, hook=None, custom_func=None, args:list = None, this=None):
67+
def VarChar(hook=None, custom_func=None, args:list = None, this=None):
6068
this['type'] = 'varchar(255)'
6169
return this
6270

6371

6472
@datatype
65-
def Date(*, hook=None, custom_func=None, args:list = None, this=None):
73+
def Date(hook=None, custom_func=None, args:list = None, this=None):
6674
this['type'] = 'date'
6775
return this
6876

6977

7078
@datatype
71-
def Time(*, hook=None, custom_func=None, args:list = None, this=None):
79+
def Time(hook=None, custom_func=None, args:list = None, this=None):
7280
this['type'] = 'time'
7381
return this
7482

7583

7684
@datatype
77-
def DateTime(*, hook=None, custom_func=None, args:list = None, this=None):
85+
def DateTime(hook=None, custom_func=None, args:list = None, this=None):
7886
this['type'] = 'datetime'
7987
return this
8088

8189

8290
@datatype
83-
def Timestamp(*, hook=None, custom_func=None, args:list = None, this=None):
91+
def Timestamp(hook=None, custom_func=None, args:list = None, this=None):
8492
this['type'] = 'timestamp'
8593
return this

0 commit comments

Comments
 (0)