From 1e3aab929958a8982b9d92289c05d5196d710d1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Victor=20Batista?= Date: Fri, 23 Jun 2023 20:13:19 -0300 Subject: [PATCH 1/7] Add Docker to project Co-authored by: Eduardo Maia --- Dockerfile | 25 +++++++++++++++++++++++++ requirements.txt | 1 - 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..1ffcadf --- /dev/null +++ b/Dockerfile @@ -0,0 +1,25 @@ +# Use an appropriate base image +FROM python:2.7 + +# Set the working directory inside the container +WORKDIR /app + +# Copy the project code into the container +COPY . /app + +RUN tar -xjvf data.tar.bz2 + +# Install dependencies +RUN pip install torch torchvision +RUN pip install -r requirements.txt +RUN pip install future + +# Download and extract the glove embedding +RUN bash download_glove.sh +RUN python extract_vocab.py + +# Expose any necessary ports +# EXPOSE + +# Set the command to run when the container starts +CMD ["python", "train.py"] \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 3ed1fc1..2759b7a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,7 +5,6 @@ jdcal==1.3 odfpy==1.3.5 olefile==0.44 openpyxl==2.4.9 -pkg-resources==0.0.0 pytz==2017.3 records==0.5.2 SQLAlchemy==1.1.14 From 694494a744b4d827c12facb0e94d057e53037a21 Mon Sep 17 00:00:00 2001 From: Eduardo Date: Sun, 25 Jun 2023 14:13:30 -0300 Subject: [PATCH 2/7] Config Pypi publish MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: João Victor Batista --- dist/sqlnet_predict-0.1.0-py3-none-any.whl | Bin 0 -> 3328 bytes dist/sqlnet_predict-0.1.0.tar.gz | Bin 0 -> 2884 bytes poetry.lock | 369 +++++++++++++++++++++ pyproject.toml | 28 ++ sqlnet/lib/dbengine.py | 8 +- sqlnet/model/seq2sql.py | 14 +- sqlnet/model/sqlnet.py | 14 +- sqlnet/utils.py | 8 +- sqlnet_predict.py | 4 + test.py | 62 ++-- train.py | 102 +++--- 11 files changed, 502 insertions(+), 107 deletions(-) create mode 100644 dist/sqlnet_predict-0.1.0-py3-none-any.whl create mode 100644 dist/sqlnet_predict-0.1.0.tar.gz create mode 100644 poetry.lock create mode 100644 pyproject.toml create mode 100644 sqlnet_predict.py diff --git a/dist/sqlnet_predict-0.1.0-py3-none-any.whl b/dist/sqlnet_predict-0.1.0-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..d356c07660a251fa7b71f771d45041c14ce7e2a6 GIT binary patch literal 3328 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 literal 0 HcmV?d00001 diff --git a/dist/sqlnet_predict-0.1.0.tar.gz b/dist/sqlnet_predict-0.1.0.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..6c8ecfd7cfbfdbfe98ae26901f433525b535e413 GIT binary patch literal 2884 zcmV-K3%m3miwFn+00002|8sF{Ze?^|aB^j2X=8LPFfK7JFfMdqascgGZByGw66Ujh zMVI$W*s_KEzW73FjV(ZR#`a2b2$jl_u{?khy*Sbc?4RJ3pmqX?y6erqvtkYwE9RwQ6k#7CX<-l31_^&F{R- zR{ITn;rjfb+WM{C+HbcSZMD5$->>f1m7Svf<6Hd23%IzLM||cwqN1r)RofdFJ$-2D zf9LvdH5w1C|604<-l;YkjTXKL>MdITwWikC0j*g7KfN7VeW+J@9!p{l1J~g}%oU{< z&XoL*8+w$35`+SgD&sRZRscNIMJhIp1+#meph3rD_@<52Z62Vd z4FqxzFtk~MUOnOj+9x-j>I7t=%|a*fc_1XRs0+vJA?_hQi@;}sM=tZ?HO6vc@ww z#193B6dFu4ROw=#!6iP(!HC04aZ3}P-<8#wEKC$6sH0bN51>IpEdxy4Z98T;Jc9gmnjw~tk zpgTMV{oUBqEel2_7^mZbfyz+3*&W)3Zk53p_6C!_F+45>=4YLStPRcTL;qO$J>P#uIZqvUI?(l)hp023_M+ z@2hAXErR}5AKGA@bO(d2QIhX>Vm#E*$?oAmSEMD3vTvAr&!%wJS3N`y{Tr0Q8tXlS zF7$Ug2Gcdq%b89~|6_te_)zJ0PrJt$+p8Zyf^*WFnEEOCj5t`6L(4YoiLJx&Xw)a5 z6-zhY;s?z77Ys(0L~CN{W$1V9t~87)5Gs6(*M}3!kf0euTQ|+g*fvJPU5xw;VKJ3n z7l-yGx}%{C6%iVl=cJS{kl>f$>_o?YlK_=SbqN9s5$o9-VhY+r0PT$!VW=MujAMP+ z)5)6=X*n}2eHZ7-ut>m2&7O79=0t`}bA(!bm ztakz_+^Vvp7WIEo{}=UtQU7n&|EAvUpX#bVdzSjYS*teh*Z=KCQU5-D*H`{4V zdCh55Nq^KV><%3BfJZEiOGH?KCKxFEk%dP^C=8j9cnnZm!mc=+WmTxj-9W}ffWm;Y zC_p`_PlxVQ@P(p${P-*9m6g6LJbv))ulaKHKlt(|Sz!r^LODv|{YWw0{^|vGiTSdL-V^QOb>ywnm&Zb8ZnUDa6{NU*Z6X}<53N#k;$^e0alh7ru9ioK*H=BqaA~M)Wf6sF##*c8S$lcB?kA z1I^Bti(Gd@-7k^#ujxH)ht=78@*oLZ z+J153o4mV0-3t%7dOlR6`&+ScOe1)viR;ZO@e=v4|3O)CPMVJtvHltH4MD!KbUEPW{IzoPzoQT1P=scQ9Vt*W()`tPOIe|I~P zy8qPrPt%(D`M*|EYcz5FH?>x+sQ;d$VTl$-LT=G0`L*2mRxU2Gs_)`rUH26W<|VBE z@xPBN#_(wLH-7&gS^w=ut$pwNUu)J{#rl7acFF}KDph%#F7^&!eXbCz>A+nUsH`Mp zk|luNx{?@nU_}bEo(lKTS_keiM8(XQOC|l0xdU$wh}4x| zHxOFX9mnpa%TZxw7CIdm(XYpQ<0zaXB7)8e=Lfbo2jKIoi1|JNxcb!}M`yog<5m5s z^61#phg8=w_T5+@Zj!FPdUGJzYWX!XI#t`fFSWrTQ8cBH<=3^XvKik+IZ1cRuQj#3 zMQnovOO+Z~->xxb#!{*-WxkV0$#N>8HXqWnV$d>NB+w6qD`_(=0.2.3,!=0.2.4)", "greenlet (!=0.4.17)"] +mariadb-connector = ["mariadb (>=1.0.1,!=1.1.2)"] +mssql = ["pyodbc"] +mssql-pymssql = ["pymssql"] +mssql-pyodbc = ["pyodbc"] +mypy = ["mypy (>=0.910)", "sqlalchemy2-stubs"] +mysql = ["mysqlclient (>=1.4.0)", "mysqlclient (>=1.4.0,<2)"] +mysql-connector = ["mysql-connector-python"] +oracle = ["cx-oracle (>=7)", "cx-oracle (>=7,<8)"] +postgresql = ["psycopg2 (>=2.7)"] +postgresql-asyncpg = ["asyncpg", "greenlet (!=0.4.17)"] +postgresql-pg8000 = ["pg8000 (>=1.16.6,!=1.29.0)"] +postgresql-psycopg2binary = ["psycopg2-binary"] +postgresql-psycopg2cffi = ["psycopg2cffi"] +pymysql = ["pymysql", "pymysql (<1)"] +sqlcipher = ["sqlcipher3-binary"] + +[[package]] +name = "tablib" +version = "0.12.1" +description = "Format agnostic tabular data library (XLS, JSON, YAML, CSV)" +optional = false +python-versions = "*" +files = [ + {file = "tablib-0.12.1.tar.gz", hash = "sha256:b8cf50a61d66655229993f2ee29220553fb2c80403479f8e6de77c0c24649d87"}, +] + +[package.dependencies] +odfpy = "*" +openpyxl = "*" +pyyaml = "*" +unicodecsv = "*" +xlrd = "*" +xlwt = "*" + +[package.extras] +pandas = ["pandas"] + +[[package]] +name = "unicodecsv" +version = "0.14.1" +description = "Python2's stdlib csv module is nice, but it doesn't support unicode. This module is a drop-in replacement which *does*." +optional = false +python-versions = "*" +files = [ + {file = "unicodecsv-0.14.1.tar.gz", hash = "sha256:018c08037d48649a0412063ff4eda26eaa81eff1546dbffa51fa5293276ff7fc"}, +] + +[[package]] +name = "xlrd" +version = "1.2.0" +description = "Library for developers to extract data from Microsoft Excel (tm) spreadsheet files" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +files = [ + {file = "xlrd-1.2.0-py2.py3-none-any.whl", hash = "sha256:e551fb498759fa3a5384a94ccd4c3c02eb7c00ea424426e212ac0c57be9dfbde"}, + {file = "xlrd-1.2.0.tar.gz", hash = "sha256:546eb36cee8db40c3eaa46c351e67ffee6eeb5fa2650b71bc4c758a29a1b29b2"}, +] + +[[package]] +name = "xlwt" +version = "1.3.0" +description = "Library to create spreadsheet files compatible with MS Excel 97/2000/XP/2003 XLS files, on any platform, with Python 2.6, 2.7, 3.3+" +optional = false +python-versions = "*" +files = [ + {file = "xlwt-1.3.0-py2.py3-none-any.whl", hash = "sha256:a082260524678ba48a297d922cc385f58278b8aa68741596a87de01a9c628b2e"}, + {file = "xlwt-1.3.0.tar.gz", hash = "sha256:c59912717a9b28f1a3c2a98fd60741014b06b043936dcecbc113eaaada156c88"}, +] + +[metadata] +lock-version = "2.0" +python-versions = "^3.10" +content-hash = "d9680a6b0eea53f748fa2ed0c97043e9e1119c04e94d28015e75401c11ff2a74" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..ae77afa --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,28 @@ +[tool.poetry] +name = "sqlnet-predict" +version = "0.1.0" +description = "This repo provides an implementation of SQLNet and Seq2SQL neural networks for predicting SQL queries on [WikiSQL dataset](https://github.com/salesforce/WikiSQL). The paper is available at [here](https://arxiv.org/abs/1711.04436)." +authors = ["Your Name "] +license = "BSD-3-Clause license" +readme = "README.md" + +[tool.poetry.dependencies] +python = "^3.10" +Babel = "^2.5.1" +docopt = "^0.6.2" +et-xmlfile = "^1.0.1" +jdcal = "^1.3" +odfpy = "^1.3.5" +openpyxl = "^2.4.9" +pytz = "^2017.3" +records = "^0.5.2" +SQLAlchemy = "^1.1.14" +tablib = "^0.12.1" +unicodecsv = "^0.14.1" +xlrd = "^1.1.0" +xlwt = "^1.3.0" + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" +packages = ["sqlnet_predict"] \ No newline at end of file diff --git a/sqlnet/lib/dbengine.py b/sqlnet/lib/dbengine.py index 619c8b1..5fce843 100644 --- a/sqlnet/lib/dbengine.py +++ b/sqlnet/lib/dbengine.py @@ -2,7 +2,6 @@ import re from babel.numbers import parse_decimal, NumberFormatError - schema_re = re.compile(r'\((.+)\)') num_re = re.compile(r'[-+]?\d*\.\d+|\d+') @@ -10,9 +9,7 @@ cond_ops = ['=', '>', '<', 'OP'] class DBEngine: - def __init__(self, fdb): - #fdb = 'data/test.db' self.db = records.Database('sqlite:///{}'.format(fdb)) def execute_query(self, table_id, query, *args, **kwargs): @@ -21,7 +18,7 @@ def execute_query(self, table_id, query, *args, **kwargs): def execute(self, table_id, select_index, aggregation_index, conditions, lower=True): if not table_id.startswith('table'): table_id = 'table_{}'.format(table_id.replace('-', '_')) - table_info = self.db.query('SELECT sql from sqlite_master WHERE tbl_name = :name', name=table_id).all()[0].sql.replace('\n','') + table_info = self.db.query('SELECT sql from sqlite_master WHERE tbl_name = :name', name=table_id).all()[0].sql.replace('\n', '') schema_str = schema_re.findall(table_info)[0] schema = {} for tup in schema_str.split(', '): @@ -34,7 +31,7 @@ def execute(self, table_id, select_index, aggregation_index, conditions, lower=T where_clause = [] where_map = {} for col_index, op, val in conditions: - if lower and (isinstance(val, str) or isinstance(val, unicode)): + if lower and isinstance(val, str): val = val.lower() if schema['col{}'.format(col_index)] == 'real' and not isinstance(val, (int, float)): try: @@ -47,6 +44,5 @@ def execute(self, table_id, select_index, aggregation_index, conditions, lower=T if where_clause: where_str = 'WHERE ' + ' AND '.join(where_clause) query = 'SELECT {} AS result FROM {} {}'.format(select, table_id, where_str) - #print query out = self.db.query(query, **where_map) return [o.result for o in out] diff --git a/sqlnet/model/seq2sql.py b/sqlnet/model/seq2sql.py index 651a4ea..4a1831a 100644 --- a/sqlnet/model/seq2sql.py +++ b/sqlnet/model/seq2sql.py @@ -199,9 +199,9 @@ def reinforce_backward(self, score, rewards): def check_acc(self, vis_info, pred_queries, gt_queries, pred_entry): def pretty_print(vis_data): - print 'question:', vis_data[0] - print 'headers: (%s)'%(' || '.join(vis_data[1])) - print 'query:', vis_data[2] + print ('question:', vis_data[0]) + print ('headers: (%s)'%(' || '.join(vis_data[1]))) + print ('query:', vis_data[2]) def gen_cond_str(conds, header): if len(conds) == 0: @@ -210,7 +210,7 @@ def gen_cond_str(conds, header): for cond in conds: cond_str.append( header[cond[0]] + ' ' + self.COND_OPS[cond[1]] + \ - ' ' + unicode(cond[2]).lower()) + ' ' + cond[2]).lower() return 'WHERE ' + ' AND '.join(cond_str) pred_agg, pred_sel, pred_cond = pred_entry @@ -261,8 +261,8 @@ def gen_cond_str(conds, header): if not flag: break gt_idx = tuple(x[0] for x in cond_gt).index(cond_pred[idx][0]) - if flag and unicode(cond_gt[gt_idx][2]).lower() != \ - unicode(cond_pred[idx][2]).lower(): + if flag and cond_gt[gt_idx][2].lower() != \ + cond_pred[idx][2].lower(): flag = False cond_val_err += 1 @@ -349,7 +349,7 @@ def merge_tokens(tok_list, raw_tok_str): cond_toks.append(cond_val) if verbose: - print cond_toks + print (cond_toks) if len(cond_toks) > 0: cond_toks = cond_toks[1:] st = 0 diff --git a/sqlnet/model/sqlnet.py b/sqlnet/model/sqlnet.py index 7c3ebb4..d0b09fb 100644 --- a/sqlnet/model/sqlnet.py +++ b/sqlnet/model/sqlnet.py @@ -231,17 +231,17 @@ def loss(self, score, truth_num, pred_entry, gt_where): def check_acc(self, vis_info, pred_queries, gt_queries, pred_entry): def pretty_print(vis_data): - print 'question:', vis_data[0] - print 'headers: (%s)'%(' || '.join(vis_data[1])) - print 'query:', vis_data[2] - + print ('question:', vis_data[0]) + print ('headers: (%s)'%(' || '.join(vis_data[1]))) + print ('query:', vis_data[2] +) def gen_cond_str(conds, header): if len(conds) == 0: return 'None' cond_str = [] for cond in conds: cond_str.append(header[cond[0]] + ' ' + - self.COND_OPS[cond[1]] + ' ' + unicode(cond[2]).lower()) + self.COND_OPS[cond[1]] + ' ' + cond[2]).lower() return 'WHERE ' + ' AND '.join(cond_str) pred_agg, pred_sel, pred_cond = pred_entry @@ -294,8 +294,8 @@ def gen_cond_str(conds, header): break gt_idx = tuple( x[0] for x in cond_gt).index(cond_pred[idx][0]) - if flag and unicode(cond_gt[gt_idx][2]).lower() != \ - unicode(cond_pred[idx][2]).lower(): + if flag and cond_gt[gt_idx][2].lower() != \ + cond_pred[idx][2].lower(): flag = False cond_val_err += 1 diff --git a/sqlnet/utils.py b/sqlnet/utils.py index 2311671..9605733 100644 --- a/sqlnet/utils.py +++ b/sqlnet/utils.py @@ -14,7 +14,7 @@ def load_data(sql_paths, table_paths, use_small=False): max_col_num = 0 for SQL_PATH in sql_paths: - print "Loading data from %s"%SQL_PATH + print ("Loading data from %s"%SQL_PATH) with open(SQL_PATH) as inf: for idx, line in enumerate(inf): if use_small and idx >= 1000: @@ -23,7 +23,7 @@ def load_data(sql_paths, table_paths, use_small=False): sql_data.append(sql) for TABLE_PATH in table_paths: - print "Loading data from %s"%TABLE_PATH + print ("Loading data from %s"%TABLE_PATH) with open(TABLE_PATH) as inf: for line in inf: tab = json.loads(line.strip()) @@ -36,7 +36,7 @@ def load_data(sql_paths, table_paths, use_small=False): def load_dataset(dataset_id, use_small=False): if dataset_id == 0: - print "Loading from original dataset" + print ("Loading from original dataset") sql_data, table_data = load_data('data/train_tok.jsonl', 'data/train_tok.tables.jsonl', use_small=use_small) val_sql_data, val_table_data = load_data('data/dev_tok.jsonl', @@ -47,7 +47,7 @@ def load_dataset(dataset_id, use_small=False): DEV_DB = 'data/dev.db' TEST_DB = 'data/test.db' else: - print "Loading from re-split dataset" + print ("Loading from re-split dataset") sql_data, table_data = load_data('data_resplit/train.jsonl', 'data_resplit/tables.jsonl', use_small=use_small) val_sql_data, val_table_data = load_data('data_resplit/dev.jsonl', diff --git a/sqlnet_predict.py b/sqlnet_predict.py new file mode 100644 index 0000000..da420e0 --- /dev/null +++ b/sqlnet_predict.py @@ -0,0 +1,4 @@ +import test +import train + +__version__ = "0.1.0" \ No newline at end of file diff --git a/test.py b/test.py index 52dbff3..05176f8 100644 --- a/test.py +++ b/test.py @@ -8,7 +8,7 @@ import argparse -if __name__ == '__main__': +def test(): parser = argparse.ArgumentParser() parser.add_argument('--toy', action='store_true', help='If set, use small data; used for fast debugging.') @@ -24,60 +24,60 @@ help='Use trained word embedding for SQLNet.') args = parser.parse_args() - N_word=300 - B_word=42 + N_word = 300 + B_word = 42 if args.toy: - USE_SMALL=True - GPU=True - BATCH_SIZE=15 + USE_SMALL = True + GPU = True + BATCH_SIZE = 15 else: - USE_SMALL=False - GPU=True - BATCH_SIZE=64 - TEST_ENTRY=(True, True, True) # (AGG, SEL, COND) + USE_SMALL = False + GPU = True + BATCH_SIZE = 64 + TEST_ENTRY = (True, True, True) # (AGG, SEL, COND) sql_data, table_data, val_sql_data, val_table_data, \ test_sql_data, test_table_data, \ TRAIN_DB, DEV_DB, TEST_DB = load_dataset( args.dataset, use_small=USE_SMALL) - word_emb = load_word_emb('glove/glove.%dB.%dd.txt'%(B_word,N_word), \ - load_used=True, use_small=USE_SMALL) # load_used can speed up loading + word_emb = load_word_emb('glove/glove.%dB.%dd.txt' % (B_word, N_word), \ + load_used=True, use_small=USE_SMALL) # load_used can speed up loading if args.baseline: - model = Seq2SQL(word_emb, N_word=N_word, gpu=GPU, trainable_emb = True) + model = Seq2SQL(word_emb, N_word=N_word, gpu=GPU, trainable_emb=True) else: model = SQLNet(word_emb, N_word=N_word, use_ca=args.ca, gpu=GPU, - trainable_emb = True) + trainable_emb=True) if args.train_emb: agg_m, sel_m, cond_m, agg_e, sel_e, cond_e = best_model_name(args) - print "Loading from %s"%agg_m + print("Loading from %s" % agg_m) model.agg_pred.load_state_dict(torch.load(agg_m)) - print "Loading from %s"%sel_m + print("Loading from %s" % sel_m) model.sel_pred.load_state_dict(torch.load(sel_m)) - print "Loading from %s"%cond_m + print("Loading from %s" % cond_m) model.cond_pred.load_state_dict(torch.load(cond_m)) - print "Loading from %s"%agg_e + print("Loading from %s" % agg_e) model.agg_embed_layer.load_state_dict(torch.load(agg_e)) - print "Loading from %s"%sel_e + print("Loading from %s" % sel_e) model.sel_embed_layer.load_state_dict(torch.load(sel_e)) - print "Loading from %s"%cond_e + print("Loading from %s" % cond_e) model.cond_embed_layer.load_state_dict(torch.load(cond_e)) else: agg_m, sel_m, cond_m = best_model_name(args) - print "Loading from %s"%agg_m + print("Loading from %s" % agg_m) model.agg_pred.load_state_dict(torch.load(agg_m)) - print "Loading from %s"%sel_m + print("Loading from %s" % sel_m) model.sel_pred.load_state_dict(torch.load(sel_m)) - print "Loading from %s"%cond_m + print("Loading from %s" % cond_m) model.cond_pred.load_state_dict(torch.load(cond_m)) - print "Dev acc_qm: %s;\n breakdown on (agg, sel, where): %s"%epoch_acc( - model, BATCH_SIZE, val_sql_data, val_table_data, TEST_ENTRY) - print "Dev execution acc: %s"%epoch_exec_acc( - model, BATCH_SIZE, val_sql_data, val_table_data, DEV_DB) - print "Test acc_qm: %s;\n breakdown on (agg, sel, where): %s"%epoch_acc( - model, BATCH_SIZE, test_sql_data, test_table_data, TEST_ENTRY) - print "Test execution acc: %s"%epoch_exec_acc( - model, BATCH_SIZE, test_sql_data, test_table_data, TEST_DB) + print("Dev acc_qm: %s;\n breakdown on (agg, sel, where): %s" % epoch_acc( + model, BATCH_SIZE, val_sql_data, val_table_data, TEST_ENTRY)) + print("Dev execution acc: %s" % epoch_exec_acc( + model, BATCH_SIZE, val_sql_data, val_table_data, DEV_DB)) + print("Test acc_qm: %s;\n breakdown on (agg, sel, where): %s" % epoch_acc( + model, BATCH_SIZE, test_sql_data, test_table_data, TEST_ENTRY)) + print("Test execution acc: %s" % epoch_exec_acc( + model, BATCH_SIZE, test_sql_data, test_table_data, TEST_DB)) diff --git a/train.py b/train.py index ed0cab5..982efb9 100644 --- a/train.py +++ b/train.py @@ -8,7 +8,7 @@ import argparse -if __name__ == '__main__': +def train(): parser = argparse.ArgumentParser() parser.add_argument('--toy', action='store_true', help='If set, use small data; used for fast debugging.') @@ -26,17 +26,17 @@ help='Train word embedding for SQLNet(requires pretrained model).') args = parser.parse_args() - N_word=300 - B_word=42 + N_word = 300 + B_word = 42 if args.toy: - USE_SMALL=True - GPU=True - BATCH_SIZE=15 + USE_SMALL = True + GPU = True + BATCH_SIZE = 15 else: - USE_SMALL=False - GPU=True - BATCH_SIZE=64 - TRAIN_ENTRY=(True, True, True) # (AGG, SEL, COND) + USE_SMALL = False + GPU = True + BATCH_SIZE = 64 + TRAIN_ENTRY = (True, True, True) # (AGG, SEL, COND) TRAIN_AGG, TRAIN_SEL, TRAIN_COND = TRAIN_ENTRY learning_rate = 1e-4 if args.rl else 1e-3 @@ -45,19 +45,19 @@ TRAIN_DB, DEV_DB, TEST_DB = load_dataset( args.dataset, use_small=USE_SMALL) - word_emb = load_word_emb('glove/glove.%dB.%dd.txt'%(B_word,N_word), \ + word_emb = load_word_emb('glove/glove.%dB.%dd.txt' % (B_word, N_word), \ load_used=args.train_emb, use_small=USE_SMALL) if args.baseline: model = Seq2SQL(word_emb, N_word=N_word, gpu=GPU, - trainable_emb = args.train_emb) - assert not args.train_emb, "Seq2SQL can\'t train embedding." + trainable_emb=args.train_emb) + assert not args.train_emb, "Seq2SQL can't train embedding." else: model = SQLNet(word_emb, N_word=N_word, use_ca=args.ca, - gpu=GPU, trainable_emb = args.train_emb) - assert not args.rl, "SQLNet can\'t do reinforcement learning." + gpu=GPU, trainable_emb=args.train_emb) + assert not args.rl, "SQLNet can't do reinforcement learning." optimizer = torch.optim.Adam(model.parameters(), - lr=learning_rate, weight_decay = 0) + lr=learning_rate, weight_decay=0) if args.train_emb: agg_m, sel_m, cond_m, agg_e, sel_e, cond_e = best_model_name(args) @@ -66,38 +66,37 @@ if args.rl or args.train_emb: # Load pretrained model. agg_lm, sel_lm, cond_lm = best_model_name(args, for_load=True) - print "Loading from %s"%agg_lm + print("Loading from %s" % agg_lm) model.agg_pred.load_state_dict(torch.load(agg_lm)) - print "Loading from %s"%sel_lm + print("Loading from %s" % sel_lm) model.sel_pred.load_state_dict(torch.load(sel_lm)) - print "Loading from %s"%cond_lm + print("Loading from %s" % cond_lm) model.cond_pred.load_state_dict(torch.load(cond_lm)) if args.rl: best_acc = 0.0 best_idx = -1 - print "Init dev acc_qm: %s\n breakdown on (agg, sel, where): %s"% \ - epoch_acc(model, BATCH_SIZE, val_sql_data,\ - val_table_data, TRAIN_ENTRY) - print "Init dev acc_ex: %s"%epoch_exec_acc( - model, BATCH_SIZE, val_sql_data, val_table_data, DEV_DB) + print("Init dev acc_qm: %s\n breakdown on (agg, sel, where): %s" % \ + epoch_acc(model, BATCH_SIZE, val_sql_data, val_table_data, TRAIN_ENTRY)) + print("Init dev acc_ex: %s" % epoch_exec_acc( + model, BATCH_SIZE, val_sql_data, val_table_data, DEV_DB)) torch.save(model.cond_pred.state_dict(), cond_m) for i in range(100): - print 'Epoch %d @ %s'%(i+1, datetime.datetime.now()) - print ' Avg reward = %s'%epoch_reinforce_train( - model, optimizer, BATCH_SIZE, sql_data, table_data, TRAIN_DB) - print ' dev acc_qm: %s\n breakdown result: %s'% epoch_acc( - model, BATCH_SIZE, val_sql_data, val_table_data, TRAIN_ENTRY) + print('Epoch %d @ %s' % (i + 1, datetime.datetime.now())) + print(' Avg reward = %s' % epoch_reinforce_train( + model, optimizer, BATCH_SIZE, sql_data, table_data, TRAIN_DB)) + print(' dev acc_qm: %s\n breakdown result: %s' % epoch_acc( + model, BATCH_SIZE, val_sql_data, val_table_data, TRAIN_ENTRY)) exec_acc = epoch_exec_acc( model, BATCH_SIZE, val_sql_data, val_table_data, DEV_DB) - print ' dev acc_ex: %s', exec_acc + print(' dev acc_ex: %s' % exec_acc) if exec_acc[0] > best_acc: best_acc = exec_acc[0] - best_idx = i+1 + best_idx = i + 1 torch.save(model.cond_pred.state_dict(), - 'saved_model/epoch%d.cond_model%s'%(i+1, args.suffix)) + 'saved_model/epoch%d.cond_model%s' % (i + 1, args.suffix)) torch.save(model.cond_pred.state_dict(), cond_m) - print ' Best exec acc = %s, on epoch %s'%(best_acc, best_idx) + print(' Best exec acc = %s, on epoch %s' % (best_acc, best_idx)) else: init_acc = epoch_acc(model, BATCH_SIZE, val_sql_data, val_table_data, TRAIN_ENTRY) @@ -107,8 +106,7 @@ best_sel_idx = 0 best_cond_acc = init_acc[1][2] best_cond_idx = 0 - print 'Init dev acc_qm: %s\n breakdown on (agg, sel, where): %s'%\ - init_acc + print('Init dev acc_qm: %s\n breakdown on (agg, sel, where): %s' % init_acc) if TRAIN_AGG: torch.save(model.agg_pred.state_dict(), agg_m) if args.train_emb: @@ -122,49 +120,49 @@ if args.train_emb: torch.save(model.cond_embed_layer.state_dict(), cond_e) for i in range(100): - print 'Epoch %d @ %s'%(i+1, datetime.datetime.now()) - print ' Loss = %s'%epoch_train( + print('Epoch %d @ %s' % (i + 1, datetime.datetime.now())) + print(' Loss = %s' % epoch_train( model, optimizer, BATCH_SIZE, - sql_data, table_data, TRAIN_ENTRY) - print ' Train acc_qm: %s\n breakdown result: %s'%epoch_acc( - model, BATCH_SIZE, sql_data, table_data, TRAIN_ENTRY) + sql_data, table_data, TRAIN_ENTRY)) + print(' Train acc_qm: %s\n breakdown result: %s' % epoch_acc( + model, BATCH_SIZE, sql_data, table_data, TRAIN_ENTRY)) #val_acc = epoch_token_acc(model, BATCH_SIZE, val_sql_data, val_table_data, TRAIN_ENTRY) val_acc = epoch_acc(model, BATCH_SIZE, val_sql_data, val_table_data, TRAIN_ENTRY) - print ' Dev acc_qm: %s\n breakdown result: %s'%val_acc + print(' Dev acc_qm: %s\n breakdown result: %s' % val_acc) if TRAIN_AGG: if val_acc[1][0] > best_agg_acc: best_agg_acc = val_acc[1][0] - best_agg_idx = i+1 + best_agg_idx = i + 1 torch.save(model.agg_pred.state_dict(), - 'saved_model/epoch%d.agg_model%s'%(i+1, args.suffix)) + 'saved_model/epoch%d.agg_model%s' % (i + 1, args.suffix)) torch.save(model.agg_pred.state_dict(), agg_m) if args.train_emb: torch.save(model.agg_embed_layer.state_dict(), - 'saved_model/epoch%d.agg_embed%s'%(i+1, args.suffix)) + 'saved_model/epoch%d.agg_embed%s' % (i + 1, args.suffix)) torch.save(model.agg_embed_layer.state_dict(), agg_e) if TRAIN_SEL: if val_acc[1][1] > best_sel_acc: best_sel_acc = val_acc[1][1] - best_sel_idx = i+1 + best_sel_idx = i + 1 torch.save(model.sel_pred.state_dict(), - 'saved_model/epoch%d.sel_model%s'%(i+1, args.suffix)) + 'saved_model/epoch%d.sel_model%s' % (i + 1, args.suffix)) torch.save(model.sel_pred.state_dict(), sel_m) if args.train_emb: torch.save(model.sel_embed_layer.state_dict(), - 'saved_model/epoch%d.sel_embed%s'%(i+1, args.suffix)) + 'saved_model/epoch%d.sel_embed%s' % (i + 1, args.suffix)) torch.save(model.sel_embed_layer.state_dict(), sel_e) if TRAIN_COND: if val_acc[1][2] > best_cond_acc: best_cond_acc = val_acc[1][2] - best_cond_idx = i+1 + best_cond_idx = i + 1 torch.save(model.cond_pred.state_dict(), - 'saved_model/epoch%d.cond_model%s'%(i+1, args.suffix)) + 'saved_model/epoch%d.cond_model%s' % (i + 1, args.suffix)) torch.save(model.cond_pred.state_dict(), cond_m) if args.train_emb: torch.save(model.cond_embed_layer.state_dict(), - 'saved_model/epoch%d.cond_embed%s'%(i+1, args.suffix)) + 'saved_model/epoch%d.cond_embed%s' % (i + 1, args.suffix)) torch.save(model.cond_embed_layer.state_dict(), cond_e) - print ' Best val acc = %s, on epoch %s individually'%( + print(' Best val acc = %s, on epoch %s individually' % ( (best_agg_acc, best_sel_acc, best_cond_acc), - (best_agg_idx, best_sel_idx, best_cond_idx)) + (best_agg_idx, best_sel_idx, best_cond_idx))) From bf7ee42e90425ae7db9d0bd2743ab9a005a043ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Victor=20Teixeira=20Batista?= <72669616+jvBatista@users.noreply.github.com> Date: Sun, 25 Jun 2023 15:05:51 -0300 Subject: [PATCH 3/7] Create Lint CI Co-authored-by: Eduardo Maia --- .github/workflows/pylint.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 .github/workflows/pylint.yml diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml new file mode 100644 index 0000000..2c3a7e7 --- /dev/null +++ b/.github/workflows/pylint.yml @@ -0,0 +1,20 @@ +name: Pylint + +on: [push] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v3 + with: + python-version: 3.9 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install pylint + - name: Analysing the code with pylint + run: | + pylint $(git ls-files '*.py') From d33259c7174cec5ea3f80507e838d7b63567744b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Victor=20Batista?= Date: Sun, 25 Jun 2023 15:42:02 -0300 Subject: [PATCH 4/7] Create poetry CI Co-authored-by: Eduardo Maia --- .github/workflows/poetry_ci.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .github/workflows/poetry_ci.yml diff --git a/.github/workflows/poetry_ci.yml b/.github/workflows/poetry_ci.yml new file mode 100644 index 0000000..ce1ce72 --- /dev/null +++ b/.github/workflows/poetry_ci.yml @@ -0,0 +1,27 @@ +name: Poetry CI + +on: + push: + branches: + - master + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: 3.11 + + - name: Install Poetry + run: curl -sSL https://install.python-poetry.org | python3 - + + - name: Checkout code + uses: actions/checkout@v2 + + - name: Build and Test + run: | + poetry install + poetry build From 62aa14ec6c6d2e9abfe0b93ee2560ad1058c91ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Victor=20Batista?= Date: Wed, 28 Jun 2023 23:37:01 -0300 Subject: [PATCH 5/7] Update README --- README.md | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 34a141a..66c2f1b 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,9 @@ This repo provides an implementation of SQLNet and Seq2SQL neural networks for p ``` ## Installation +Project installation can be done either locally or by running a Docker container + +## Local installation The data is in `data.tar.bz2`. Unzip the code by running ```bash tar -xjvf data.tar.bz2 @@ -28,18 +31,26 @@ The code is written using PyTorch in Python 2.7. Check [here](http://pytorch.org pip install -r requirements.txt ``` -## Downloading the glove embedding. +### Downloading the glove embedding. Download the pretrained glove embedding from [here](https://github.com/stanfordnlp/GloVe) using ```bash bash download_glove.sh ``` -## Extract the glove embedding for training. +### Extract the glove embedding for training. Run the following command to process the pretrained glove embedding for training the word embedding: ```bash python extract_vocab.py ``` +## Container Installation +Make sure you have Docker already installed in your machine + +To build the Docker image, go to the root directory of the project and run on the terminal: +```bash +docker build -t sql-net . +``` + ## Train The training script is `train.py`. To see the detailed parameters for running: ```bash From d2ae07ba48eacea819626d2af1f25a616f329222 Mon Sep 17 00:00:00 2001 From: Eduardo Date: Tue, 27 Jun 2023 14:31:00 -0300 Subject: [PATCH 6/7] =?UTF-8?q?Documentation=20using=20Sphinx=20Co-authore?= =?UTF-8?q?d-by:=20Jo=C3=A3o=20Victor=20Batista=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/Makefile | 20 + docs/build/doctrees/README.doctree | Bin 0 -> 13673 bytes docs/build/doctrees/environment.pickle | Bin 0 -> 50903 bytes docs/build/doctrees/index.doctree | Bin 0 -> 3345 bytes docs/build/doctrees/readme_link.doctree | Bin 0 -> 13146 bytes docs/build/html/.buildinfo | 4 + docs/build/html/README.html | 189 ++++ docs/build/html/_sources/README.md.txt | 93 ++ docs/build/html/_sources/index.rst.txt | 11 + docs/build/html/_sources/readme_link.rst.txt | 4 + docs/build/html/_static/alabaster.css | 701 ++++++++++++++ docs/build/html/_static/basic.css | 903 ++++++++++++++++++ docs/build/html/_static/custom.css | 1 + docs/build/html/_static/doctools.js | 156 +++ .../html/_static/documentation_options.js | 14 + docs/build/html/_static/file.png | Bin 0 -> 286 bytes .../_static/forkme_right_darkblue_121621.png | Bin 0 -> 4787 bytes docs/build/html/_static/language_data.js | 199 ++++ docs/build/html/_static/minus.png | Bin 0 -> 90 bytes docs/build/html/_static/plus.png | Bin 0 -> 90 bytes docs/build/html/_static/pygments.css | 83 ++ docs/build/html/_static/searchtools.js | 566 +++++++++++ docs/build/html/_static/sphinx_highlight.js | 144 +++ docs/build/html/genindex.html | 101 ++ docs/build/html/index.html | 109 +++ docs/build/html/objects.inv | Bin 0 -> 300 bytes docs/build/html/readme_link.html | 176 ++++ docs/build/html/search.html | 120 +++ docs/build/html/searchindex.js | 1 + docs/make.bat | 35 + docs/source/README.md | 93 ++ docs/source/conf.py | 55 ++ docs/source/index.rst | 11 + docs/source/readme_link.rst | 4 + 34 files changed, 3793 insertions(+) create mode 100644 docs/Makefile create mode 100644 docs/build/doctrees/README.doctree create mode 100644 docs/build/doctrees/environment.pickle create mode 100644 docs/build/doctrees/index.doctree create mode 100644 docs/build/doctrees/readme_link.doctree create mode 100644 docs/build/html/.buildinfo create mode 100644 docs/build/html/README.html create mode 100644 docs/build/html/_sources/README.md.txt create mode 100644 docs/build/html/_sources/index.rst.txt create mode 100644 docs/build/html/_sources/readme_link.rst.txt create mode 100644 docs/build/html/_static/alabaster.css create mode 100644 docs/build/html/_static/basic.css create mode 100644 docs/build/html/_static/custom.css create mode 100644 docs/build/html/_static/doctools.js create mode 100644 docs/build/html/_static/documentation_options.js create mode 100644 docs/build/html/_static/file.png create mode 100644 docs/build/html/_static/forkme_right_darkblue_121621.png create mode 100644 docs/build/html/_static/language_data.js create mode 100644 docs/build/html/_static/minus.png create mode 100644 docs/build/html/_static/plus.png create mode 100644 docs/build/html/_static/pygments.css create mode 100644 docs/build/html/_static/searchtools.js create mode 100644 docs/build/html/_static/sphinx_highlight.js create mode 100644 docs/build/html/genindex.html create mode 100644 docs/build/html/index.html create mode 100644 docs/build/html/objects.inv create mode 100644 docs/build/html/readme_link.html create mode 100644 docs/build/html/search.html create mode 100644 docs/build/html/searchindex.js create mode 100644 docs/make.bat create mode 100644 docs/source/README.md create mode 100644 docs/source/conf.py create mode 100644 docs/source/index.rst create mode 100644 docs/source/readme_link.rst diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..d0c3cbf --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/build/doctrees/README.doctree b/docs/build/doctrees/README.doctree new file mode 100644 index 0000000000000000000000000000000000000000..7fc6521baa2879f76a91cc9b51d8aae3f943f8d0 GIT binary patch literal 13673 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 literal 0 HcmV?d00001 diff --git a/docs/build/doctrees/index.doctree b/docs/build/doctrees/index.doctree new file mode 100644 index 0000000000000000000000000000000000000000..88876aeb6d139045338ae98c832996d0b1d6648f GIT binary patch literal 3345 zcmds3-Hsf!5)RqS@9xfK0|_9AP6q+mpv(*;909pO=!6^gFcJv@aS=71wr6auyWR26 z?#u-eTyVrnzKgjy&vf2`7lF^+J+nI#oflxG(YDLwD!b~duj=R4@9q67)t^5wB^SkF zL?|s3WhVG8Rhi3KVZ)1X@0ajXIPyJB&Wv(8W5Hj6M#hDtnib(0HV0AP3TZ}-flj9K zjq|+a|M&Epe@~cARCv!qX!Qk{qxi0!G{kXj`}|+mt>?!2qmRWEElFSncyC!WR}TgVpX!l0}?4t zL@~dgOr1@HO$=8~(uCMVGTfz~slpObzy?dSQa1U~s?2J}eoUy)EVJU2jRNmH3%uvA zeajXxNPn-#{TgDm_!#z2VgRzdRmt4m#Z zv6zzVM6+3?(_7^7kts<8Qn%F1Fn!8`^Bqg(@kHQ#ev9w;Ub+HGz^c8%-e+U3ayDkv z5lz+jaRXE{o@dOAYlw|;(v0g9V^L7H7-?gJza~Y&!g0$@k-CnFxm3j(;=IM%F|9|~ zY*}F?yR_xs`JPFDiA5OIUhbMrDBr0;ap>QDN%fDP|ND}19podt^&|d1-{E&B{NBV( z34a~YM7lba^(to>B99}_!Y#phVRRJ z|IZP>YL-}MR!S}3qHOBsa5p$3xPTO*(yFWke|u|Z%LISn2er|Q3#^X5 zy}7Y<(qE4cFo+UId}PJK`;ruMN9GLSreNi(s7e1STAk7~MGXTca1&Wz;@fDCGrSSu z5HtmS&%`3|wjU5@ReB-vR|T-OPhDQ7Yy2Uql|TS`x*#$dJg6iHZDC^WFGQtbj;a*h z0$SJEqEv>Zmrqs@$!vNmjHvN>kWyjDRK|xix9qIyf*<)kJjS3B>WT$q8ntxATmDx3 zf)n(l$W=&8v__HdU9ir2349*L;sR`nIZ!A?E^PSv`dvRLS(zdzpsoV_2shu0k}1L6 zV`ca^xV5EuG#*22M&;6SRg9FLkAuG%HLD9iGqntZ3(74vNmdTu`|xALbD(G0miZ{T zF#rC_JSvq$yq+*U63osjAE^E@x4DF~o+VS15CuOUcl~VuGEdjFxqd)e_vv$g-7GN` zEmAJ#T;f+XQx$Q)XL1Z@>2rsoHVD+K)w*7$Qe~uW3I2A*3GRc$*Tse?S0Tjd6IX)Q z;|y65eM1813Xq6m1`MoN;YQ>MUW7NaK_z_2!-~3@S4FIfiR&(09-(kgRKu`AFnoCf;fFfFBH3z1cO6Sa0L(L&B z1!!52D`1087-uAZV?$bxLlDE-Y`tj562c?}c_#|%Z!R&x`d$>+Wr-X96u3M${7w89 z{J!z~my=bU-p>S59^J!YEr~U`(yOm|SyJm^YD04KsgmpbSE{dV3D?@a4U4^%*Xq!X z4g1yD9?AUXwykCdtsRV!VR8X1Fjr(sN+cL>K+EX-tC7FJ<9`iLfPT!Qs3T062KlZX hu8Ctqyt@`xDcfzv3qWKZ$J9QJ+}6-Q?7VI|`U`)WA0+?) literal 0 HcmV?d00001 diff --git a/docs/build/doctrees/readme_link.doctree b/docs/build/doctrees/readme_link.doctree new file mode 100644 index 0000000000000000000000000000000000000000..a94966942d15e521db1ff30681926ec9d27376d3 GIT binary patch literal 13146 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 literal 0 HcmV?d00001 diff --git a/docs/build/html/.buildinfo b/docs/build/html/.buildinfo new file mode 100644 index 0000000..6cc9f03 --- /dev/null +++ b/docs/build/html/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: bb8a3b91062c0bdde59c392479c30864 +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/build/html/README.html b/docs/build/html/README.html new file mode 100644 index 0000000..76b494e --- /dev/null +++ b/docs/build/html/README.html @@ -0,0 +1,189 @@ + + + + + + + + SQLNet — SQLNet 0.1.0 documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

SQLNet

+

This repo provides an implementation of SQLNet and Seq2SQL neural networks for predicting SQL queries on WikiSQL dataset. The paper is available at here.

+
+

Citation

+
+

Xiaojun Xu, Chang Liu, Dawn Song. 2017. SQLNet: Generating Structured Queries from Natural Language Without Reinforcement Learning.

+
+
+
+

Bibtex

+
@article{xu2017sqlnet,
+title={SQLNet: Generating Structured Queries From Natural Language Without Reinforcement Learning},
+author={Xu, Xiaojun and Liu, Chang and Song, Dawn},
+journal={arXiv preprint arXiv:1711.04436},
+year={2017}
+}
+
+
+
+
+

Installation

+

The data is in data.tar.bz2. Unzip the code by running

+
tar -xjvf data.tar.bz2
+
+
+

The code is written using PyTorch in Python 2.7. Check here to install PyTorch. You can install other dependency by running

+
pip install -r requirements.txt
+
+
+
+
+

Downloading the glove embedding.

+

Download the pretrained glove embedding from here using

+
bash download_glove.sh
+
+
+
+
+

Extract the glove embedding for training.

+

Run the following command to process the pretrained glove embedding for training the word embedding:

+
python extract_vocab.py
+
+
+
+
+

Train

+

The training script is train.py. To see the detailed parameters for running:

+
python train.py -h
+
+
+

Some typical usage are listed as below:

+

Train a SQLNet model with column attention:

+
python train.py --ca
+
+
+

Train a SQLNet model with column attention and trainable embedding (requires pretraining without training embedding, i.e., executing the command above):

+
python train.py --ca --train_emb
+
+
+

Pretrain a Seq2SQL model on the re-splitted dataset

+
python train.py --baseline --dataset 1
+
+
+

Train a Seq2SQL model with Reinforcement Learning after pretraining

+
python train.py --baseline --dataset 1 --rl
+
+
+
+
+

Test

+

The script for evaluation on the dev split and test split. The parameters for evaluation is roughly the same as the one used for training. For example, the commands for evaluating the models from above commands are:

+

Test a trained SQLNet model with column attention

+
python test.py --ca
+
+
+

Test a trained SQLNet model with column attention and trainable embedding:

+
python test.py --ca --train_emb
+
+
+

Test a trained Seq2SQL model withour RL on the re-splitted dataset

+
python test.py --baseline --dataset 1
+
+
+

Test a trained Seq2SQL model with Reinforcement learning

+
python test.py --baseline --dataset 1 --rl
+
+
+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/build/html/_sources/README.md.txt b/docs/build/html/_sources/README.md.txt new file mode 100644 index 0000000..4bf1892 --- /dev/null +++ b/docs/build/html/_sources/README.md.txt @@ -0,0 +1,93 @@ +# SQLNet + +This repo provides an implementation of SQLNet and Seq2SQL neural networks for predicting SQL queries on [WikiSQL dataset](https://github.com/salesforce/WikiSQL). The paper is available at [here](https://arxiv.org/abs/1711.04436). + +## Citation + +> Xiaojun Xu, Chang Liu, Dawn Song. 2017. SQLNet: Generating Structured Queries from Natural Language Without Reinforcement Learning. + +## Bibtex + +``` +@article{xu2017sqlnet, +title={SQLNet: Generating Structured Queries From Natural Language Without Reinforcement Learning}, +author={Xu, Xiaojun and Liu, Chang and Song, Dawn}, +journal={arXiv preprint arXiv:1711.04436}, +year={2017} +} +``` + +## Installation +The data is in `data.tar.bz2`. Unzip the code by running +```bash +tar -xjvf data.tar.bz2 +``` + +The code is written using PyTorch in Python 2.7. Check [here](http://pytorch.org/) to install PyTorch. You can install other dependency by running +```bash +pip install -r requirements.txt +``` + +## Downloading the glove embedding. +Download the pretrained glove embedding from [here](https://github.com/stanfordnlp/GloVe) using +```bash +bash download_glove.sh +``` + +## Extract the glove embedding for training. +Run the following command to process the pretrained glove embedding for training the word embedding: +```bash +python extract_vocab.py +``` + +## Train +The training script is `train.py`. To see the detailed parameters for running: +```bash +python train.py -h +``` + +Some typical usage are listed as below: + +Train a SQLNet model with column attention: +```bash +python train.py --ca +``` + +Train a SQLNet model with column attention and trainable embedding (requires pretraining without training embedding, i.e., executing the command above): +```bash +python train.py --ca --train_emb +``` + +Pretrain a [Seq2SQL model](https://arxiv.org/abs/1709.00103) on the re-splitted dataset +```bash +python train.py --baseline --dataset 1 +``` + +Train a Seq2SQL model with Reinforcement Learning after pretraining +```bash +python train.py --baseline --dataset 1 --rl +``` + +## Test +The script for evaluation on the dev split and test split. The parameters for evaluation is roughly the same as the one used for training. For example, the commands for evaluating the models from above commands are: + +Test a trained SQLNet model with column attention +```bash +python test.py --ca +``` + +Test a trained SQLNet model with column attention and trainable embedding: +```bash +python test.py --ca --train_emb +``` + +Test a trained [Seq2SQL model](https://arxiv.org/abs/1709.00103) withour RL on the re-splitted dataset +```bash +python test.py --baseline --dataset 1 +``` + +Test a trained Seq2SQL model with Reinforcement learning +```bash +python test.py --baseline --dataset 1 --rl +``` + diff --git a/docs/build/html/_sources/index.rst.txt b/docs/build/html/_sources/index.rst.txt new file mode 100644 index 0000000..d93ea22 --- /dev/null +++ b/docs/build/html/_sources/index.rst.txt @@ -0,0 +1,11 @@ +.. SQLNet documentation master file, created by + sphinx-quickstart on Tue Jun 27 13:23:58 2023. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to SQLNet's documentation! +================================== + +.. toctree:: + README + diff --git a/docs/build/html/_sources/readme_link.rst.txt b/docs/build/html/_sources/readme_link.rst.txt new file mode 100644 index 0000000..fc4804d --- /dev/null +++ b/docs/build/html/_sources/readme_link.rst.txt @@ -0,0 +1,4 @@ +About The Project +---------------------------- + +.. include:: README.md diff --git a/docs/build/html/_static/alabaster.css b/docs/build/html/_static/alabaster.css new file mode 100644 index 0000000..0eddaeb --- /dev/null +++ b/docs/build/html/_static/alabaster.css @@ -0,0 +1,701 @@ +@import url("basic.css"); + +/* -- page layout ----------------------------------------------------------- */ + +body { + font-family: Georgia, serif; + font-size: 17px; + background-color: #fff; + color: #000; + margin: 0; + padding: 0; +} + + +div.document { + width: 940px; + margin: 30px auto 0 auto; +} + +div.documentwrapper { + float: left; + width: 100%; +} + +div.bodywrapper { + margin: 0 0 0 220px; +} + +div.sphinxsidebar { + width: 220px; + font-size: 14px; + line-height: 1.5; +} + +hr { + border: 1px solid #B1B4B6; +} + +div.body { + background-color: #fff; + color: #3E4349; + padding: 0 30px 0 30px; +} + +div.body > .section { + text-align: left; +} + +div.footer { + width: 940px; + margin: 20px auto 30px auto; + font-size: 14px; + color: #888; + text-align: right; +} + +div.footer a { + color: #888; +} + +p.caption { + font-family: inherit; + font-size: inherit; +} + + +div.relations { + display: none; +} + + +div.sphinxsidebar a { + color: #444; + text-decoration: none; + border-bottom: 1px dotted #999; +} + +div.sphinxsidebar a:hover { + border-bottom: 1px solid #999; +} + +div.sphinxsidebarwrapper { + padding: 18px 10px; +} + +div.sphinxsidebarwrapper p.logo { + padding: 0; + margin: -10px 0 0 0px; + text-align: center; +} + +div.sphinxsidebarwrapper h1.logo { + margin-top: -10px; + text-align: center; + margin-bottom: 5px; + text-align: left; +} + +div.sphinxsidebarwrapper h1.logo-name { + margin-top: 0px; +} + +div.sphinxsidebarwrapper p.blurb { + margin-top: 0; + font-style: normal; +} + +div.sphinxsidebar h3, +div.sphinxsidebar h4 { + font-family: Georgia, serif; + color: #444; + font-size: 24px; + font-weight: normal; + margin: 0 0 5px 0; + padding: 0; +} + +div.sphinxsidebar h4 { + font-size: 20px; +} + +div.sphinxsidebar h3 a { + color: #444; +} + +div.sphinxsidebar p.logo a, +div.sphinxsidebar h3 a, +div.sphinxsidebar p.logo a:hover, +div.sphinxsidebar h3 a:hover { + border: none; +} + +div.sphinxsidebar p { + color: #555; + margin: 10px 0; +} + +div.sphinxsidebar ul { + margin: 10px 0; + padding: 0; + color: #000; +} + +div.sphinxsidebar ul li.toctree-l1 > a { + font-size: 120%; +} + +div.sphinxsidebar ul li.toctree-l2 > a { + font-size: 110%; +} + +div.sphinxsidebar input { + border: 1px solid #CCC; + font-family: Georgia, serif; + font-size: 1em; +} + +div.sphinxsidebar hr { + border: none; + height: 1px; + color: #AAA; + background: #AAA; + + text-align: left; + margin-left: 0; + width: 50%; +} + +div.sphinxsidebar .badge { + border-bottom: none; +} + +div.sphinxsidebar .badge:hover { + border-bottom: none; +} + +/* To address an issue with donation coming after search */ +div.sphinxsidebar h3.donation { + margin-top: 10px; +} + +/* -- body styles ----------------------------------------------------------- */ + +a { + color: #004B6B; + text-decoration: underline; +} + +a:hover { + color: #6D4100; + text-decoration: underline; +} + +div.body h1, +div.body h2, +div.body h3, +div.body h4, +div.body h5, +div.body h6 { + font-family: Georgia, serif; + font-weight: normal; + margin: 30px 0px 10px 0px; + padding: 0; +} + +div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; } +div.body h2 { font-size: 180%; } +div.body h3 { font-size: 150%; } +div.body h4 { font-size: 130%; } +div.body h5 { font-size: 100%; } +div.body h6 { font-size: 100%; } + +a.headerlink { + color: #DDD; + padding: 0 4px; + text-decoration: none; +} + +a.headerlink:hover { + color: #444; + background: #EAEAEA; +} + +div.body p, div.body dd, div.body li { + line-height: 1.4em; +} + +div.admonition { + margin: 20px 0px; + padding: 10px 30px; + background-color: #EEE; + border: 1px solid #CCC; +} + +div.admonition tt.xref, div.admonition code.xref, div.admonition a tt { + background-color: #FBFBFB; + border-bottom: 1px solid #fafafa; +} + +div.admonition p.admonition-title { + font-family: Georgia, serif; + font-weight: normal; + font-size: 24px; + margin: 0 0 10px 0; + padding: 0; + line-height: 1; +} + +div.admonition p.last { + margin-bottom: 0; +} + +div.highlight { + background-color: #fff; +} + +dt:target, .highlight { + background: #FAF3E8; +} + +div.warning { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.danger { + background-color: #FCC; + border: 1px solid #FAA; + -moz-box-shadow: 2px 2px 4px #D52C2C; + -webkit-box-shadow: 2px 2px 4px #D52C2C; + box-shadow: 2px 2px 4px #D52C2C; +} + +div.error { + background-color: #FCC; + border: 1px solid #FAA; + -moz-box-shadow: 2px 2px 4px #D52C2C; + -webkit-box-shadow: 2px 2px 4px #D52C2C; + box-shadow: 2px 2px 4px #D52C2C; +} + +div.caution { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.attention { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.important { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.note { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.tip { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.hint { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.seealso { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.topic { + background-color: #EEE; +} + +p.admonition-title { + display: inline; +} + +p.admonition-title:after { + content: ":"; +} + +pre, tt, code { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; + font-size: 0.9em; +} + +.hll { + background-color: #FFC; + margin: 0 -12px; + padding: 0 12px; + display: block; +} + +img.screenshot { +} + +tt.descname, tt.descclassname, code.descname, code.descclassname { + font-size: 0.95em; +} + +tt.descname, code.descname { + padding-right: 0.08em; +} + +img.screenshot { + -moz-box-shadow: 2px 2px 4px #EEE; + -webkit-box-shadow: 2px 2px 4px #EEE; + box-shadow: 2px 2px 4px #EEE; +} + +table.docutils { + border: 1px solid #888; + -moz-box-shadow: 2px 2px 4px #EEE; + -webkit-box-shadow: 2px 2px 4px #EEE; + box-shadow: 2px 2px 4px #EEE; +} + +table.docutils td, table.docutils th { + border: 1px solid #888; + padding: 0.25em 0.7em; +} + +table.field-list, table.footnote { + border: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} + +table.footnote { + margin: 15px 0; + width: 100%; + border: 1px solid #EEE; + background: #FDFDFD; + font-size: 0.9em; +} + +table.footnote + table.footnote { + margin-top: -15px; + border-top: none; +} + +table.field-list th { + padding: 0 0.8em 0 0; +} + +table.field-list td { + padding: 0; +} + +table.field-list p { + margin-bottom: 0.8em; +} + +/* Cloned from + * https://github.com/sphinx-doc/sphinx/commit/ef60dbfce09286b20b7385333d63a60321784e68 + */ +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +table.footnote td.label { + width: .1px; + padding: 0.3em 0 0.3em 0.5em; +} + +table.footnote td { + padding: 0.3em 0.5em; +} + +dl { + margin: 0; + padding: 0; +} + +dl dd { + margin-left: 30px; +} + +blockquote { + margin: 0 0 0 30px; + padding: 0; +} + +ul, ol { + /* Matches the 30px from the narrow-screen "li > ul" selector below */ + margin: 10px 0 10px 30px; + padding: 0; +} + +pre { + background: #EEE; + padding: 7px 30px; + margin: 15px 0px; + line-height: 1.3em; +} + +div.viewcode-block:target { + background: #ffd; +} + +dl pre, blockquote pre, li pre { + margin-left: 0; + padding-left: 30px; +} + +tt, code { + background-color: #ecf0f3; + color: #222; + /* padding: 1px 2px; */ +} + +tt.xref, code.xref, a tt { + background-color: #FBFBFB; + border-bottom: 1px solid #fff; +} + +a.reference { + text-decoration: none; + border-bottom: 1px dotted #004B6B; +} + +/* Don't put an underline on images */ +a.image-reference, a.image-reference:hover { + border-bottom: none; +} + +a.reference:hover { + border-bottom: 1px solid #6D4100; +} + +a.footnote-reference { + text-decoration: none; + font-size: 0.7em; + vertical-align: top; + border-bottom: 1px dotted #004B6B; +} + +a.footnote-reference:hover { + border-bottom: 1px solid #6D4100; +} + +a:hover tt, a:hover code { + background: #EEE; +} + + +@media screen and (max-width: 870px) { + + div.sphinxsidebar { + display: none; + } + + div.document { + width: 100%; + + } + + div.documentwrapper { + margin-left: 0; + margin-top: 0; + margin-right: 0; + margin-bottom: 0; + } + + div.bodywrapper { + margin-top: 0; + margin-right: 0; + margin-bottom: 0; + margin-left: 0; + } + + ul { + margin-left: 0; + } + + li > ul { + /* Matches the 30px from the "ul, ol" selector above */ + margin-left: 30px; + } + + .document { + width: auto; + } + + .footer { + width: auto; + } + + .bodywrapper { + margin: 0; + } + + .footer { + width: auto; + } + + .github { + display: none; + } + + + +} + + + +@media screen and (max-width: 875px) { + + body { + margin: 0; + padding: 20px 30px; + } + + div.documentwrapper { + float: none; + background: #fff; + } + + div.sphinxsidebar { + display: block; + float: none; + width: 102.5%; + margin: 50px -30px -20px -30px; + padding: 10px 20px; + background: #333; + color: #FFF; + } + + div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, + div.sphinxsidebar h3 a { + color: #fff; + } + + div.sphinxsidebar a { + color: #AAA; + } + + div.sphinxsidebar p.logo { + display: none; + } + + div.document { + width: 100%; + margin: 0; + } + + div.footer { + display: none; + } + + div.bodywrapper { + margin: 0; + } + + div.body { + min-height: 0; + padding: 0; + } + + .rtd_doc_footer { + display: none; + } + + .document { + width: auto; + } + + .footer { + width: auto; + } + + .footer { + width: auto; + } + + .github { + display: none; + } +} + + +/* misc. */ + +.revsys-inline { + display: none!important; +} + +/* Make nested-list/multi-paragraph items look better in Releases changelog + * pages. Without this, docutils' magical list fuckery causes inconsistent + * formatting between different release sub-lists. + */ +div#changelog > div.section > ul > li > p:only-child { + margin-bottom: 0; +} + +/* Hide fugly table cell borders in ..bibliography:: directive output */ +table.docutils.citation, table.docutils.citation td, table.docutils.citation th { + border: none; + /* Below needed in some edge cases; if not applied, bottom shadows appear */ + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} + + +/* relbar */ + +.related { + line-height: 30px; + width: 100%; + font-size: 0.9rem; +} + +.related.top { + border-bottom: 1px solid #EEE; + margin-bottom: 20px; +} + +.related.bottom { + border-top: 1px solid #EEE; +} + +.related ul { + padding: 0; + margin: 0; + list-style: none; +} + +.related li { + display: inline; +} + +nav#rellinks { + float: right; +} + +nav#rellinks li+li:before { + content: "|"; +} + +nav#breadcrumbs li+li:before { + content: "\00BB"; +} + +/* Hide certain items when printing */ +@media print { + div.related { + display: none; + } +} \ No newline at end of file diff --git a/docs/build/html/_static/basic.css b/docs/build/html/_static/basic.css new file mode 100644 index 0000000..7577acb --- /dev/null +++ b/docs/build/html/_static/basic.css @@ -0,0 +1,903 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: 360px; + max-width: 800px; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +nav.contents, +aside.topic, +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +nav.contents, +aside.topic, +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +nav.contents > :last-child, +aside.topic > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +nav.contents::after, +aside.topic::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +aside.footnote > span, +div.citation > span { + float: left; +} +aside.footnote > span:last-of-type, +div.citation > span:last-of-type { + padding-right: 0.5em; +} +aside.footnote > p { + margin-left: 2em; +} +div.citation > p { + margin-left: 4em; +} +aside.footnote > p:last-of-type, +div.citation > p:last-of-type { + margin-bottom: 0em; +} +aside.footnote > p:last-of-type:after, +div.citation > p:last-of-type:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; + white-space: nowrap; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/docs/build/html/_static/custom.css b/docs/build/html/_static/custom.css new file mode 100644 index 0000000..2a924f1 --- /dev/null +++ b/docs/build/html/_static/custom.css @@ -0,0 +1 @@ +/* This file intentionally left blank. */ diff --git a/docs/build/html/_static/doctools.js b/docs/build/html/_static/doctools.js new file mode 100644 index 0000000..d06a71d --- /dev/null +++ b/docs/build/html/_static/doctools.js @@ -0,0 +1,156 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Base JavaScript utilities for all Sphinx HTML documentation. + * + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ + "TEXTAREA", + "INPUT", + "SELECT", + "BUTTON", +]); + +const _ready = (callback) => { + if (document.readyState !== "loading") { + callback(); + } else { + document.addEventListener("DOMContentLoaded", callback); + } +}; + +/** + * Small JavaScript module for the documentation. + */ +const Documentation = { + init: () => { + Documentation.initDomainIndexTable(); + Documentation.initOnKeyListeners(); + }, + + /** + * i18n support + */ + TRANSLATIONS: {}, + PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), + LOCALE: "unknown", + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext: (string) => { + const translated = Documentation.TRANSLATIONS[string]; + switch (typeof translated) { + case "undefined": + return string; // no translation + case "string": + return translated; // translation exists + default: + return translated[0]; // (singular, plural) translation tuple exists + } + }, + + ngettext: (singular, plural, n) => { + const translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated !== "undefined") + return translated[Documentation.PLURAL_EXPR(n)]; + return n === 1 ? singular : plural; + }, + + addTranslations: (catalog) => { + Object.assign(Documentation.TRANSLATIONS, catalog.messages); + Documentation.PLURAL_EXPR = new Function( + "n", + `return (${catalog.plural_expr})` + ); + Documentation.LOCALE = catalog.locale; + }, + + /** + * helper function to focus on search bar + */ + focusSearchBar: () => { + document.querySelectorAll("input[name=q]")[0]?.focus(); + }, + + /** + * Initialise the domain index toggle buttons + */ + initDomainIndexTable: () => { + const toggler = (el) => { + const idNumber = el.id.substr(7); + const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); + if (el.src.substr(-9) === "minus.png") { + el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; + toggledRows.forEach((el) => (el.style.display = "none")); + } else { + el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; + toggledRows.forEach((el) => (el.style.display = "")); + } + }; + + const togglerElements = document.querySelectorAll("img.toggler"); + togglerElements.forEach((el) => + el.addEventListener("click", (event) => toggler(event.currentTarget)) + ); + togglerElements.forEach((el) => (el.style.display = "")); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); + }, + + initOnKeyListeners: () => { + // only install a listener if it is really needed + if ( + !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && + !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + ) + return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.altKey || event.ctrlKey || event.metaKey) return; + + if (!event.shiftKey) { + switch (event.key) { + case "ArrowLeft": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const prevLink = document.querySelector('link[rel="prev"]'); + if (prevLink && prevLink.href) { + window.location.href = prevLink.href; + event.preventDefault(); + } + break; + case "ArrowRight": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const nextLink = document.querySelector('link[rel="next"]'); + if (nextLink && nextLink.href) { + window.location.href = nextLink.href; + event.preventDefault(); + } + break; + } + } + + // some keyboard layouts may need Shift to get / + switch (event.key) { + case "/": + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; + Documentation.focusSearchBar(); + event.preventDefault(); + } + }); + }, +}; + +// quick alias for translations +const _ = Documentation.gettext; + +_ready(Documentation.init); diff --git a/docs/build/html/_static/documentation_options.js b/docs/build/html/_static/documentation_options.js new file mode 100644 index 0000000..e49ed18 --- /dev/null +++ b/docs/build/html/_static/documentation_options.js @@ -0,0 +1,14 @@ +var DOCUMENTATION_OPTIONS = { + URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'), + VERSION: '0.1.0', + LANGUAGE: 'en', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false, + SHOW_SEARCH_SUMMARY: true, + ENABLE_SEARCH_SHORTCUTS: true, +}; \ No newline at end of file diff --git a/docs/build/html/_static/file.png b/docs/build/html/_static/file.png new file mode 100644 index 0000000000000000000000000000000000000000..a858a410e4faa62ce324d814e4b816fff83a6fb3 GIT binary patch literal 286 zcmV+(0pb3MP)s`hMrGg#P~ix$^RISR_I47Y|r1 z_CyJOe}D1){SET-^Amu_i71Lt6eYfZjRyw@I6OQAIXXHDfiX^GbOlHe=Ae4>0m)d(f|Me07*qoM6N<$f}vM^LjV8( literal 0 HcmV?d00001 diff --git a/docs/build/html/_static/forkme_right_darkblue_121621.png b/docs/build/html/_static/forkme_right_darkblue_121621.png new file mode 100644 index 0000000000000000000000000000000000000000..91c7bd8edfa0720adbefd523d9273d945d88e140 GIT binary patch literal 4787 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 + var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 + var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 + var s_v = "^(" + C + ")?" + v; // vowel in stem + + this.stemWord = function (w) { + var stem; + var suffix; + var firstch; + var origword = w; + + if (w.length < 3) + return w; + + var re; + var re2; + var re3; + var re4; + + firstch = w.substr(0,1); + if (firstch == "y") + w = firstch.toUpperCase() + w.substr(1); + + // Step 1a + re = /^(.+?)(ss|i)es$/; + re2 = /^(.+?)([^s])s$/; + + if (re.test(w)) + w = w.replace(re,"$1$2"); + else if (re2.test(w)) + w = w.replace(re2,"$1$2"); + + // Step 1b + re = /^(.+?)eed$/; + re2 = /^(.+?)(ed|ing)$/; + if (re.test(w)) { + var fp = re.exec(w); + re = new RegExp(mgr0); + if (re.test(fp[1])) { + re = /.$/; + w = w.replace(re,""); + } + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1]; + re2 = new RegExp(s_v); + if (re2.test(stem)) { + w = stem; + re2 = /(at|bl|iz)$/; + re3 = new RegExp("([^aeiouylsz])\\1$"); + re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re2.test(w)) + w = w + "e"; + else if (re3.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + else if (re4.test(w)) + w = w + "e"; + } + } + + // Step 1c + re = /^(.+?)y$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(s_v); + if (re.test(stem)) + w = stem + "i"; + } + + // Step 2 + re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step2list[suffix]; + } + + // Step 3 + re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step3list[suffix]; + } + + // Step 4 + re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; + re2 = /^(.+?)(s|t)(ion)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + if (re.test(stem)) + w = stem; + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1] + fp[2]; + re2 = new RegExp(mgr1); + if (re2.test(stem)) + w = stem; + } + + // Step 5 + re = /^(.+?)e$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + re2 = new RegExp(meq1); + re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) + w = stem; + } + re = /ll$/; + re2 = new RegExp(mgr1); + if (re.test(w) && re2.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + + // and turn initial Y back to y + if (firstch == "y") + w = firstch.toLowerCase() + w.substr(1); + return w; + } +} + diff --git a/docs/build/html/_static/minus.png b/docs/build/html/_static/minus.png new file mode 100644 index 0000000000000000000000000000000000000000..d96755fdaf8bb2214971e0db9c1fd3077d7c419d GIT binary patch literal 90 zcmeAS@N?(olHy`uVBq!ia0vp^+#t*WBp7;*Yy1LIik>cxAr*|t7R?Mi>2?kWtu=nj kDsEF_5m^0CR;1wuP-*O&G^0G}KYk!hp00i_>zopr08q^qX#fBK literal 0 HcmV?d00001 diff --git a/docs/build/html/_static/plus.png b/docs/build/html/_static/plus.png new file mode 100644 index 0000000000000000000000000000000000000000..7107cec93a979b9a5f64843235a16651d563ce2d GIT binary patch literal 90 zcmeAS@N?(olHy`uVBq!ia0vp^+#t*WBp7;*Yy1LIik>cxAr*|t7R?Mi>2?kWtu>-2 m3q%Vub%g%s<8sJhVPMczOq}xhg9DJoz~JfX=d#Wzp$Pyb1r*Kz literal 0 HcmV?d00001 diff --git a/docs/build/html/_static/pygments.css b/docs/build/html/_static/pygments.css new file mode 100644 index 0000000..9abe04b --- /dev/null +++ b/docs/build/html/_static/pygments.css @@ -0,0 +1,83 @@ +pre { line-height: 125%; } +td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +.highlight .hll { background-color: #ffffcc } +.highlight { background: #f8f8f8; } +.highlight .c { color: #8f5902; font-style: italic } /* Comment */ +.highlight .err { color: #a40000; border: 1px solid #ef2929 } /* Error */ +.highlight .g { color: #000000 } /* Generic */ +.highlight .k { color: #004461; font-weight: bold } /* Keyword */ +.highlight .l { color: #000000 } /* Literal */ +.highlight .n { color: #000000 } /* Name */ +.highlight .o { color: #582800 } /* Operator */ +.highlight .x { color: #000000 } /* Other */ +.highlight .p { color: #000000; font-weight: bold } /* Punctuation */ +.highlight .ch { color: #8f5902; font-style: italic } /* Comment.Hashbang */ +.highlight .cm { color: #8f5902; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #8f5902 } /* Comment.Preproc */ +.highlight .cpf { color: #8f5902; font-style: italic } /* Comment.PreprocFile */ +.highlight .c1 { color: #8f5902; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #8f5902; font-style: italic } /* Comment.Special */ +.highlight .gd { color: #a40000 } /* Generic.Deleted */ +.highlight .ge { color: #000000; font-style: italic } /* Generic.Emph */ +.highlight .gr { color: #ef2929 } /* Generic.Error */ +.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight .gi { color: #00A000 } /* Generic.Inserted */ +.highlight .go { color: #888888 } /* Generic.Output */ +.highlight .gp { color: #745334 } /* Generic.Prompt */ +.highlight .gs { color: #000000; font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #a40000; font-weight: bold } /* Generic.Traceback */ +.highlight .kc { color: #004461; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #004461; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #004461; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #004461; font-weight: bold } /* Keyword.Pseudo */ +.highlight .kr { color: #004461; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #004461; font-weight: bold } /* Keyword.Type */ +.highlight .ld { color: #000000 } /* Literal.Date */ +.highlight .m { color: #990000 } /* Literal.Number */ +.highlight .s { color: #4e9a06 } /* Literal.String */ +.highlight .na { color: #c4a000 } /* Name.Attribute */ +.highlight .nb { color: #004461 } /* Name.Builtin */ +.highlight .nc { color: #000000 } /* Name.Class */ +.highlight .no { color: #000000 } /* Name.Constant */ +.highlight .nd { color: #888888 } /* Name.Decorator */ +.highlight .ni { color: #ce5c00 } /* Name.Entity */ +.highlight .ne { color: #cc0000; font-weight: bold } /* Name.Exception */ +.highlight .nf { color: #000000 } /* Name.Function */ +.highlight .nl { color: #f57900 } /* Name.Label */ +.highlight .nn { color: #000000 } /* Name.Namespace */ +.highlight .nx { color: #000000 } /* Name.Other */ +.highlight .py { color: #000000 } /* Name.Property */ +.highlight .nt { color: #004461; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #000000 } /* Name.Variable */ +.highlight .ow { color: #004461; font-weight: bold } /* Operator.Word */ +.highlight .pm { color: #000000; font-weight: bold } /* Punctuation.Marker */ +.highlight .w { color: #f8f8f8; text-decoration: underline } /* Text.Whitespace */ +.highlight .mb { color: #990000 } /* Literal.Number.Bin */ +.highlight .mf { color: #990000 } /* Literal.Number.Float */ +.highlight .mh { color: #990000 } /* Literal.Number.Hex */ +.highlight .mi { color: #990000 } /* Literal.Number.Integer */ +.highlight .mo { color: #990000 } /* Literal.Number.Oct */ +.highlight .sa { color: #4e9a06 } /* Literal.String.Affix */ +.highlight .sb { color: #4e9a06 } /* Literal.String.Backtick */ +.highlight .sc { color: #4e9a06 } /* Literal.String.Char */ +.highlight .dl { color: #4e9a06 } /* Literal.String.Delimiter */ +.highlight .sd { color: #8f5902; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #4e9a06 } /* Literal.String.Double */ +.highlight .se { color: #4e9a06 } /* Literal.String.Escape */ +.highlight .sh { color: #4e9a06 } /* Literal.String.Heredoc */ +.highlight .si { color: #4e9a06 } /* Literal.String.Interpol */ +.highlight .sx { color: #4e9a06 } /* Literal.String.Other */ +.highlight .sr { color: #4e9a06 } /* Literal.String.Regex */ +.highlight .s1 { color: #4e9a06 } /* Literal.String.Single */ +.highlight .ss { color: #4e9a06 } /* Literal.String.Symbol */ +.highlight .bp { color: #3465a4 } /* Name.Builtin.Pseudo */ +.highlight .fm { color: #000000 } /* Name.Function.Magic */ +.highlight .vc { color: #000000 } /* Name.Variable.Class */ +.highlight .vg { color: #000000 } /* Name.Variable.Global */ +.highlight .vi { color: #000000 } /* Name.Variable.Instance */ +.highlight .vm { color: #000000 } /* Name.Variable.Magic */ +.highlight .il { color: #990000 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/docs/build/html/_static/searchtools.js b/docs/build/html/_static/searchtools.js new file mode 100644 index 0000000..97d56a7 --- /dev/null +++ b/docs/build/html/_static/searchtools.js @@ -0,0 +1,566 @@ +/* + * searchtools.js + * ~~~~~~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for the full-text search. + * + * :copyright: Copyright 2007-2023 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ +"use strict"; + +/** + * Simple result scoring code. + */ +if (typeof Scorer === "undefined") { + var Scorer = { + // Implement the following function to further tweak the score for each result + // The function takes a result array [docname, title, anchor, descr, score, filename] + // and returns the new score. + /* + score: result => { + const [docname, title, anchor, descr, score, filename] = result + return score + }, + */ + + // query matches the full name of an object + objNameMatch: 11, + // or matches in the last dotted part of the object name + objPartialMatch: 6, + // Additive scores depending on the priority of the object + objPrio: { + 0: 15, // used to be importantResults + 1: 5, // used to be objectResults + 2: -5, // used to be unimportantResults + }, + // Used when the priority is not in the mapping. + objPrioDefault: 0, + + // query found in title + title: 15, + partialTitle: 7, + // query found in terms + term: 5, + partialTerm: 2, + }; +} + +const _removeChildren = (element) => { + while (element && element.lastChild) element.removeChild(element.lastChild); +}; + +/** + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping + */ +const _escapeRegExp = (string) => + string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string + +const _displayItem = (item, searchTerms) => { + const docBuilder = DOCUMENTATION_OPTIONS.BUILDER; + const docUrlRoot = DOCUMENTATION_OPTIONS.URL_ROOT; + const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX; + const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX; + const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY; + + const [docName, title, anchor, descr, score, _filename] = item; + + let listItem = document.createElement("li"); + let requestUrl; + let linkUrl; + if (docBuilder === "dirhtml") { + // dirhtml builder + let dirname = docName + "/"; + if (dirname.match(/\/index\/$/)) + dirname = dirname.substring(0, dirname.length - 6); + else if (dirname === "index/") dirname = ""; + requestUrl = docUrlRoot + dirname; + linkUrl = requestUrl; + } else { + // normal html builders + requestUrl = docUrlRoot + docName + docFileSuffix; + linkUrl = docName + docLinkSuffix; + } + let linkEl = listItem.appendChild(document.createElement("a")); + linkEl.href = linkUrl + anchor; + linkEl.dataset.score = score; + linkEl.innerHTML = title; + if (descr) + listItem.appendChild(document.createElement("span")).innerHTML = + " (" + descr + ")"; + else if (showSearchSummary) + fetch(requestUrl) + .then((responseData) => responseData.text()) + .then((data) => { + if (data) + listItem.appendChild( + Search.makeSearchSummary(data, searchTerms) + ); + }); + Search.output.appendChild(listItem); +}; +const _finishSearch = (resultCount) => { + Search.stopPulse(); + Search.title.innerText = _("Search Results"); + if (!resultCount) + Search.status.innerText = Documentation.gettext( + "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories." + ); + else + Search.status.innerText = _( + `Search finished, found ${resultCount} page(s) matching the search query.` + ); +}; +const _displayNextItem = ( + results, + resultCount, + searchTerms +) => { + // results left, load the summary and display it + // this is intended to be dynamic (don't sub resultsCount) + if (results.length) { + _displayItem(results.pop(), searchTerms); + setTimeout( + () => _displayNextItem(results, resultCount, searchTerms), + 5 + ); + } + // search finished, update title and status message + else _finishSearch(resultCount); +}; + +/** + * Default splitQuery function. Can be overridden in ``sphinx.search`` with a + * custom function per language. + * + * The regular expression works by splitting the string on consecutive characters + * that are not Unicode letters, numbers, underscores, or emoji characters. + * This is the same as ``\W+`` in Python, preserving the surrogate pair area. + */ +if (typeof splitQuery === "undefined") { + var splitQuery = (query) => query + .split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu) + .filter(term => term) // remove remaining empty strings +} + +/** + * Search Module + */ +const Search = { + _index: null, + _queued_query: null, + _pulse_status: -1, + + htmlToText: (htmlString) => { + const htmlElement = new DOMParser().parseFromString(htmlString, 'text/html'); + htmlElement.querySelectorAll(".headerlink").forEach((el) => { el.remove() }); + const docContent = htmlElement.querySelector('[role="main"]'); + if (docContent !== undefined) return docContent.textContent; + console.warn( + "Content block not found. Sphinx search tries to obtain it via '[role=main]'. Could you check your theme or template." + ); + return ""; + }, + + init: () => { + const query = new URLSearchParams(window.location.search).get("q"); + document + .querySelectorAll('input[name="q"]') + .forEach((el) => (el.value = query)); + if (query) Search.performSearch(query); + }, + + loadIndex: (url) => + (document.body.appendChild(document.createElement("script")).src = url), + + setIndex: (index) => { + Search._index = index; + if (Search._queued_query !== null) { + const query = Search._queued_query; + Search._queued_query = null; + Search.query(query); + } + }, + + hasIndex: () => Search._index !== null, + + deferQuery: (query) => (Search._queued_query = query), + + stopPulse: () => (Search._pulse_status = -1), + + startPulse: () => { + if (Search._pulse_status >= 0) return; + + const pulse = () => { + Search._pulse_status = (Search._pulse_status + 1) % 4; + Search.dots.innerText = ".".repeat(Search._pulse_status); + if (Search._pulse_status >= 0) window.setTimeout(pulse, 500); + }; + pulse(); + }, + + /** + * perform a search for something (or wait until index is loaded) + */ + performSearch: (query) => { + // create the required interface elements + const searchText = document.createElement("h2"); + searchText.textContent = _("Searching"); + const searchSummary = document.createElement("p"); + searchSummary.classList.add("search-summary"); + searchSummary.innerText = ""; + const searchList = document.createElement("ul"); + searchList.classList.add("search"); + + const out = document.getElementById("search-results"); + Search.title = out.appendChild(searchText); + Search.dots = Search.title.appendChild(document.createElement("span")); + Search.status = out.appendChild(searchSummary); + Search.output = out.appendChild(searchList); + + const searchProgress = document.getElementById("search-progress"); + // Some themes don't use the search progress node + if (searchProgress) { + searchProgress.innerText = _("Preparing search..."); + } + Search.startPulse(); + + // index already loaded, the browser was quick! + if (Search.hasIndex()) Search.query(query); + else Search.deferQuery(query); + }, + + /** + * execute search (requires search index to be loaded) + */ + query: (query) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + const allTitles = Search._index.alltitles; + const indexEntries = Search._index.indexentries; + + // stem the search terms and add them to the correct list + const stemmer = new Stemmer(); + const searchTerms = new Set(); + const excludedTerms = new Set(); + const highlightTerms = new Set(); + const objectTerms = new Set(splitQuery(query.toLowerCase().trim())); + splitQuery(query.trim()).forEach((queryTerm) => { + const queryTermLower = queryTerm.toLowerCase(); + + // maybe skip this "word" + // stopwords array is from language_data.js + if ( + stopwords.indexOf(queryTermLower) !== -1 || + queryTerm.match(/^\d+$/) + ) + return; + + // stem the word + let word = stemmer.stemWord(queryTermLower); + // select the correct list + if (word[0] === "-") excludedTerms.add(word.substr(1)); + else { + searchTerms.add(word); + highlightTerms.add(queryTermLower); + } + }); + + if (SPHINX_HIGHLIGHT_ENABLED) { // set in sphinx_highlight.js + localStorage.setItem("sphinx_highlight_terms", [...highlightTerms].join(" ")) + } + + // console.debug("SEARCH: searching for:"); + // console.info("required: ", [...searchTerms]); + // console.info("excluded: ", [...excludedTerms]); + + // array of [docname, title, anchor, descr, score, filename] + let results = []; + _removeChildren(document.getElementById("search-progress")); + + const queryLower = query.toLowerCase(); + for (const [title, foundTitles] of Object.entries(allTitles)) { + if (title.toLowerCase().includes(queryLower) && (queryLower.length >= title.length/2)) { + for (const [file, id] of foundTitles) { + let score = Math.round(100 * queryLower.length / title.length) + results.push([ + docNames[file], + titles[file] !== title ? `${titles[file]} > ${title}` : title, + id !== null ? "#" + id : "", + null, + score, + filenames[file], + ]); + } + } + } + + // search for explicit entries in index directives + for (const [entry, foundEntries] of Object.entries(indexEntries)) { + if (entry.includes(queryLower) && (queryLower.length >= entry.length/2)) { + for (const [file, id] of foundEntries) { + let score = Math.round(100 * queryLower.length / entry.length) + results.push([ + docNames[file], + titles[file], + id ? "#" + id : "", + null, + score, + filenames[file], + ]); + } + } + } + + // lookup as object + objectTerms.forEach((term) => + results.push(...Search.performObjectSearch(term, objectTerms)) + ); + + // lookup as search terms in fulltext + results.push(...Search.performTermsSearch(searchTerms, excludedTerms)); + + // let the scorer override scores with a custom scoring function + if (Scorer.score) results.forEach((item) => (item[4] = Scorer.score(item))); + + // now sort the results by score (in opposite order of appearance, since the + // display function below uses pop() to retrieve items) and then + // alphabetically + results.sort((a, b) => { + const leftScore = a[4]; + const rightScore = b[4]; + if (leftScore === rightScore) { + // same score: sort alphabetically + const leftTitle = a[1].toLowerCase(); + const rightTitle = b[1].toLowerCase(); + if (leftTitle === rightTitle) return 0; + return leftTitle > rightTitle ? -1 : 1; // inverted is intentional + } + return leftScore > rightScore ? 1 : -1; + }); + + // remove duplicate search results + // note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept + let seen = new Set(); + results = results.reverse().reduce((acc, result) => { + let resultStr = result.slice(0, 4).concat([result[5]]).map(v => String(v)).join(','); + if (!seen.has(resultStr)) { + acc.push(result); + seen.add(resultStr); + } + return acc; + }, []); + + results = results.reverse(); + + // for debugging + //Search.lastresults = results.slice(); // a copy + // console.info("search results:", Search.lastresults); + + // print the results + _displayNextItem(results, results.length, searchTerms); + }, + + /** + * search for object names + */ + performObjectSearch: (object, objectTerms) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const objects = Search._index.objects; + const objNames = Search._index.objnames; + const titles = Search._index.titles; + + const results = []; + + const objectSearchCallback = (prefix, match) => { + const name = match[4] + const fullname = (prefix ? prefix + "." : "") + name; + const fullnameLower = fullname.toLowerCase(); + if (fullnameLower.indexOf(object) < 0) return; + + let score = 0; + const parts = fullnameLower.split("."); + + // check for different match types: exact matches of full name or + // "last name" (i.e. last dotted part) + if (fullnameLower === object || parts.slice(-1)[0] === object) + score += Scorer.objNameMatch; + else if (parts.slice(-1)[0].indexOf(object) > -1) + score += Scorer.objPartialMatch; // matches in last name + + const objName = objNames[match[1]][2]; + const title = titles[match[0]]; + + // If more than one term searched for, we require other words to be + // found in the name/title/description + const otherTerms = new Set(objectTerms); + otherTerms.delete(object); + if (otherTerms.size > 0) { + const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase(); + if ( + [...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0) + ) + return; + } + + let anchor = match[3]; + if (anchor === "") anchor = fullname; + else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname; + + const descr = objName + _(", in ") + title; + + // add custom score for some objects according to scorer + if (Scorer.objPrio.hasOwnProperty(match[2])) + score += Scorer.objPrio[match[2]]; + else score += Scorer.objPrioDefault; + + results.push([ + docNames[match[0]], + fullname, + "#" + anchor, + descr, + score, + filenames[match[0]], + ]); + }; + Object.keys(objects).forEach((prefix) => + objects[prefix].forEach((array) => + objectSearchCallback(prefix, array) + ) + ); + return results; + }, + + /** + * search for full-text terms in the index + */ + performTermsSearch: (searchTerms, excludedTerms) => { + // prepare search + const terms = Search._index.terms; + const titleTerms = Search._index.titleterms; + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + + const scoreMap = new Map(); + const fileMap = new Map(); + + // perform the search on the required terms + searchTerms.forEach((word) => { + const files = []; + const arr = [ + { files: terms[word], score: Scorer.term }, + { files: titleTerms[word], score: Scorer.title }, + ]; + // add support for partial matches + if (word.length > 2) { + const escapedWord = _escapeRegExp(word); + Object.keys(terms).forEach((term) => { + if (term.match(escapedWord) && !terms[word]) + arr.push({ files: terms[term], score: Scorer.partialTerm }); + }); + Object.keys(titleTerms).forEach((term) => { + if (term.match(escapedWord) && !titleTerms[word]) + arr.push({ files: titleTerms[word], score: Scorer.partialTitle }); + }); + } + + // no match but word was a required one + if (arr.every((record) => record.files === undefined)) return; + + // found search word in contents + arr.forEach((record) => { + if (record.files === undefined) return; + + let recordFiles = record.files; + if (recordFiles.length === undefined) recordFiles = [recordFiles]; + files.push(...recordFiles); + + // set score for the word in each file + recordFiles.forEach((file) => { + if (!scoreMap.has(file)) scoreMap.set(file, {}); + scoreMap.get(file)[word] = record.score; + }); + }); + + // create the mapping + files.forEach((file) => { + if (fileMap.has(file) && fileMap.get(file).indexOf(word) === -1) + fileMap.get(file).push(word); + else fileMap.set(file, [word]); + }); + }); + + // now check if the files don't contain excluded terms + const results = []; + for (const [file, wordList] of fileMap) { + // check if all requirements are matched + + // as search terms with length < 3 are discarded + const filteredTermCount = [...searchTerms].filter( + (term) => term.length > 2 + ).length; + if ( + wordList.length !== searchTerms.size && + wordList.length !== filteredTermCount + ) + continue; + + // ensure that none of the excluded terms is in the search result + if ( + [...excludedTerms].some( + (term) => + terms[term] === file || + titleTerms[term] === file || + (terms[term] || []).includes(file) || + (titleTerms[term] || []).includes(file) + ) + ) + break; + + // select one (max) score for the file. + const score = Math.max(...wordList.map((w) => scoreMap.get(file)[w])); + // add result to the result list + results.push([ + docNames[file], + titles[file], + "", + null, + score, + filenames[file], + ]); + } + return results; + }, + + /** + * helper function to return a node containing the + * search summary for a given text. keywords is a list + * of stemmed words. + */ + makeSearchSummary: (htmlText, keywords) => { + const text = Search.htmlToText(htmlText); + if (text === "") return null; + + const textLower = text.toLowerCase(); + const actualStartPosition = [...keywords] + .map((k) => textLower.indexOf(k.toLowerCase())) + .filter((i) => i > -1) + .slice(-1)[0]; + const startWithContext = Math.max(actualStartPosition - 120, 0); + + const top = startWithContext === 0 ? "" : "..."; + const tail = startWithContext + 240 < text.length ? "..." : ""; + + let summary = document.createElement("p"); + summary.classList.add("context"); + summary.textContent = top + text.substr(startWithContext, 240).trim() + tail; + + return summary; + }, +}; + +_ready(Search.init); diff --git a/docs/build/html/_static/sphinx_highlight.js b/docs/build/html/_static/sphinx_highlight.js new file mode 100644 index 0000000..aae669d --- /dev/null +++ b/docs/build/html/_static/sphinx_highlight.js @@ -0,0 +1,144 @@ +/* Highlighting utilities for Sphinx HTML documentation. */ +"use strict"; + +const SPHINX_HIGHLIGHT_ENABLED = true + +/** + * highlight a given string on a node by wrapping it in + * span elements with the given class name. + */ +const _highlight = (node, addItems, text, className) => { + if (node.nodeType === Node.TEXT_NODE) { + const val = node.nodeValue; + const parent = node.parentNode; + const pos = val.toLowerCase().indexOf(text); + if ( + pos >= 0 && + !parent.classList.contains(className) && + !parent.classList.contains("nohighlight") + ) { + let span; + + const closestNode = parent.closest("body, svg, foreignObject"); + const isInSVG = closestNode && closestNode.matches("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.classList.add(className); + } + + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + parent.insertBefore( + span, + parent.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling + ) + ); + node.nodeValue = val.substr(0, pos); + + if (isInSVG) { + const rect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect" + ); + const bbox = parent.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute("class", className); + addItems.push({ parent: parent, target: rect }); + } + } + } else if (node.matches && !node.matches("button, select, textarea")) { + node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); + } +}; +const _highlightText = (thisNode, text, className) => { + let addItems = []; + _highlight(thisNode, addItems, text, className); + addItems.forEach((obj) => + obj.parent.insertAdjacentElement("beforebegin", obj.target) + ); +}; + +/** + * Small JavaScript module for the documentation. + */ +const SphinxHighlight = { + + /** + * highlight the search words provided in localstorage in the text + */ + highlightSearchWords: () => { + if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight + + // get and clear terms from localstorage + const url = new URL(window.location); + const highlight = + localStorage.getItem("sphinx_highlight_terms") + || url.searchParams.get("highlight") + || ""; + localStorage.removeItem("sphinx_highlight_terms") + url.searchParams.delete("highlight"); + window.history.replaceState({}, "", url); + + // get individual terms from highlight string + const terms = highlight.toLowerCase().split(/\s+/).filter(x => x); + if (terms.length === 0) return; // nothing to do + + // There should never be more than one element matching "div.body" + const divBody = document.querySelectorAll("div.body"); + const body = divBody.length ? divBody[0] : document.querySelector("body"); + window.setTimeout(() => { + terms.forEach((term) => _highlightText(body, term, "highlighted")); + }, 10); + + const searchBox = document.getElementById("searchbox"); + if (searchBox === null) return; + searchBox.appendChild( + document + .createRange() + .createContextualFragment( + '" + ) + ); + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords: () => { + document + .querySelectorAll("#searchbox .highlight-link") + .forEach((el) => el.remove()); + document + .querySelectorAll("span.highlighted") + .forEach((el) => el.classList.remove("highlighted")); + localStorage.removeItem("sphinx_highlight_terms") + }, + + initEscapeListener: () => { + // only install a listener if it is really needed + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; + if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { + SphinxHighlight.hideSearchWords(); + event.preventDefault(); + } + }); + }, +}; + +_ready(SphinxHighlight.highlightSearchWords); +_ready(SphinxHighlight.initEscapeListener); diff --git a/docs/build/html/genindex.html b/docs/build/html/genindex.html new file mode 100644 index 0000000..81ca23b --- /dev/null +++ b/docs/build/html/genindex.html @@ -0,0 +1,101 @@ + + + + + + + Index — SQLNet 0.1.0 documentation + + + + + + + + + + + + + + + + +
+
+
+ + +
+ + +

Index

+ +
+ +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/build/html/index.html b/docs/build/html/index.html new file mode 100644 index 0000000..8fa8cf1 --- /dev/null +++ b/docs/build/html/index.html @@ -0,0 +1,109 @@ + + + + + + + + Welcome to SQLNet’s documentation! — SQLNet 0.1.0 documentation + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Welcome to SQLNet’s documentation!

+
+ +
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/build/html/objects.inv b/docs/build/html/objects.inv new file mode 100644 index 0000000000000000000000000000000000000000..d32b16d6fd0166de7b94fe95ae2f3a11f3ad4e4e GIT binary patch literal 300 zcmV+{0n`2?AX9K?X>NERX>N99Zgg*Qc_4OWa&u{KZXhxWBOp+6Z)#;@bUGkYQA|!{ zbP6LNR%LQ?X>V>iAPOTORA^-&a%F8{X>Md?av*PJAarPHb0B7EY-J#6b0A}HZE$jB zb8}^6Aa!$TZf78RY-wUH3V7OukU3G~q3&r9#Q01 + + + + + + + About The Project — SQLNet 0.1.0 documentation + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

About The Project

+

# SQLNet

+

This repo provides an implementation of SQLNet and Seq2SQL neural networks for predicting SQL queries on [WikiSQL dataset](https://github.com/salesforce/WikiSQL). The paper is available at [here](https://arxiv.org/abs/1711.04436).

+

## Citation

+

> Xiaojun Xu, Chang Liu, Dawn Song. 2017. SQLNet: Generating Structured Queries from Natural Language Without Reinforcement Learning.

+

## Bibtex

+

` +@article{xu2017sqlnet, +title={SQLNet: Generating Structured Queries From Natural Language Without Reinforcement Learning}, +author={Xu, Xiaojun and Liu, Chang and Song, Dawn}, +journal={arXiv preprint arXiv:1711.04436}, +year={2017} +} +`

+

## Installation +The data is in data.tar.bz2. Unzip the code by running +`bash +tar -xjvf data.tar.bz2 +`

+

The code is written using PyTorch in Python 2.7. Check [here](http://pytorch.org/) to install PyTorch. You can install other dependency by running +`bash +pip install -r requirements.txt +`

+

## Downloading the glove embedding. +Download the pretrained glove embedding from [here](https://github.com/stanfordnlp/GloVe) using +`bash +bash download_glove.sh +`

+

## Extract the glove embedding for training. +Run the following command to process the pretrained glove embedding for training the word embedding: +`bash +python extract_vocab.py +`

+

## Train +The training script is train.py. To see the detailed parameters for running: +`bash +python train.py -h +`

+

Some typical usage are listed as below:

+

Train a SQLNet model with column attention: +`bash +python train.py --ca +`

+

Train a SQLNet model with column attention and trainable embedding (requires pretraining without training embedding, i.e., executing the command above): +`bash +python train.py --ca --train_emb +`

+

Pretrain a [Seq2SQL model](https://arxiv.org/abs/1709.00103) on the re-splitted dataset +`bash +python train.py --baseline --dataset 1 +`

+

Train a Seq2SQL model with Reinforcement Learning after pretraining +`bash +python train.py --baseline --dataset 1 --rl +`

+

## Test +The script for evaluation on the dev split and test split. The parameters for evaluation is roughly the same as the one used for training. For example, the commands for evaluating the models from above commands are:

+

Test a trained SQLNet model with column attention +`bash +python test.py --ca +`

+

Test a trained SQLNet model with column attention and trainable embedding: +`bash +python test.py --ca --train_emb +`

+

Test a trained [Seq2SQL model](https://arxiv.org/abs/1709.00103) withour RL on the re-splitted dataset +`bash +python test.py --baseline --dataset 1 +`

+

Test a trained Seq2SQL model with Reinforcement learning +`bash +python test.py --baseline --dataset 1 --rl +`

+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/build/html/search.html b/docs/build/html/search.html new file mode 100644 index 0000000..da65b95 --- /dev/null +++ b/docs/build/html/search.html @@ -0,0 +1,120 @@ + + + + + + + Search — SQLNet 0.1.0 documentation + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Search

+ + + + +

+ Searching for multiple words only shows matches that contain + all words. +

+ + +
+ + + +
+ + + +
+ +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/build/html/searchindex.js b/docs/build/html/searchindex.js new file mode 100644 index 0000000..a763f51 --- /dev/null +++ b/docs/build/html/searchindex.js @@ -0,0 +1 @@ +Search.setIndex({"docnames": ["README", "index", "readme_link"], "filenames": ["README.md", "index.rst", "readme_link.rst"], "titles": ["SQLNet", "Welcome to SQLNet\u2019s documentation!", "About The Project"], "terms": {"thi": [0, 2], "repo": [0, 2], "provid": [0, 2], "an": [0, 2], "implement": [0, 2], "seq2sql": [0, 2], "neural": [0, 2], "network": [0, 2], "predict": [0, 2], "sql": [0, 2], "queri": [0, 2], "wikisql": [0, 2], "dataset": [0, 2], "The": 0, "paper": [0, 2], "i": [0, 2], "avail": [0, 2], "here": [0, 2], "xiaojun": [0, 2], "xu": [0, 2], "chang": [0, 2], "liu": [0, 2], "dawn": [0, 2], "song": [0, 2], "2017": [0, 2], "gener": [0, 2], "structur": [0, 2], "from": [0, 2], "natur": [0, 2], "languag": [0, 2], "without": [0, 2], "reinforc": [0, 2], "learn": [0, 2], "articl": [0, 2], "xu2017sqlnet": [0, 2], "titl": [0, 2], "author": [0, 2], "journal": [0, 2], "arxiv": [0, 2], "preprint": [0, 2], "1711": [0, 2], "04436": [0, 2], "year": [0, 2], "data": [0, 2], "tar": [0, 2], "bz2": [0, 2], "unzip": [0, 2], "code": [0, 2], "run": [0, 2], "xjvf": [0, 2], "written": [0, 2], "us": [0, 2], "pytorch": [0, 2], "python": [0, 2], "2": [0, 2], "7": [0, 2], "check": [0, 2], "you": [0, 2], "can": [0, 2], "other": [0, 2], "depend": [0, 2], "pip": [0, 2], "r": [0, 2], "requir": [0, 2], "txt": [0, 2], "pretrain": [0, 2], "bash": [0, 2], "download_glov": [0, 2], "sh": [0, 2], "follow": [0, 2], "command": [0, 2], "process": [0, 2], "word": [0, 2], "extract_vocab": [0, 2], "py": [0, 2], "script": [0, 2], "To": [0, 2], "see": [0, 2], "detail": [0, 2], "paramet": [0, 2], "h": [0, 2], "some": [0, 2], "typic": [0, 2], "usag": [0, 2], "ar": [0, 2], "list": [0, 2], "below": [0, 2], "model": [0, 2], "column": [0, 2], "attent": [0, 2], "ca": [0, 2], "trainabl": [0, 2], "e": [0, 2], "execut": [0, 2], "abov": [0, 2], "train_emb": [0, 2], "re": [0, 2], "split": [0, 2], "baselin": [0, 2], "1": [0, 2], "after": [0, 2], "rl": [0, 2], "evalu": [0, 2], "dev": [0, 2], "roughli": [0, 2], "same": [0, 2], "one": [0, 2], "For": [0, 2], "exampl": [0, 2], "withour": [0, 2], "readm": 1, "sqlnet": 2, "http": 2, "github": 2, "com": 2, "salesforc": 2, "org": 2, "ab": 2, "citat": 2, "bibtex": 2, "instal": 2, "download": 2, "glove": 2, "embed": 2, "stanfordnlp": 2, "extract": 2, "train": 2, "1709": 2, "00103": 2, "test": 2}, "objects": {}, "objtypes": {}, "objnames": {}, "titleterms": {"sqlnet": [0, 1], "citat": 0, "bibtex": 0, "instal": 0, "download": 0, "glove": 0, "embed": 0, "extract": 0, "train": 0, "test": 0, "welcom": 1, "": 1, "document": 1, "about": 2, "The": 2, "project": 2}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 8, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx": 57}, "alltitles": {"SQLNet": [[0, "sqlnet"]], "Citation": [[0, "citation"]], "Bibtex": [[0, "bibtex"]], "Installation": [[0, "installation"]], "Downloading the glove embedding.": [[0, "downloading-the-glove-embedding"]], "Extract the glove embedding for training.": [[0, "extract-the-glove-embedding-for-training"]], "Train": [[0, "train"]], "Test": [[0, "test"]], "Welcome to SQLNet\u2019s documentation!": [[1, "welcome-to-sqlnet-s-documentation"]], "About The Project": [[2, "about-the-project"]]}, "indexentries": {}}) \ No newline at end of file diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..6fcf05b --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/source/README.md b/docs/source/README.md new file mode 100644 index 0000000..4bf1892 --- /dev/null +++ b/docs/source/README.md @@ -0,0 +1,93 @@ +# SQLNet + +This repo provides an implementation of SQLNet and Seq2SQL neural networks for predicting SQL queries on [WikiSQL dataset](https://github.com/salesforce/WikiSQL). The paper is available at [here](https://arxiv.org/abs/1711.04436). + +## Citation + +> Xiaojun Xu, Chang Liu, Dawn Song. 2017. SQLNet: Generating Structured Queries from Natural Language Without Reinforcement Learning. + +## Bibtex + +``` +@article{xu2017sqlnet, +title={SQLNet: Generating Structured Queries From Natural Language Without Reinforcement Learning}, +author={Xu, Xiaojun and Liu, Chang and Song, Dawn}, +journal={arXiv preprint arXiv:1711.04436}, +year={2017} +} +``` + +## Installation +The data is in `data.tar.bz2`. Unzip the code by running +```bash +tar -xjvf data.tar.bz2 +``` + +The code is written using PyTorch in Python 2.7. Check [here](http://pytorch.org/) to install PyTorch. You can install other dependency by running +```bash +pip install -r requirements.txt +``` + +## Downloading the glove embedding. +Download the pretrained glove embedding from [here](https://github.com/stanfordnlp/GloVe) using +```bash +bash download_glove.sh +``` + +## Extract the glove embedding for training. +Run the following command to process the pretrained glove embedding for training the word embedding: +```bash +python extract_vocab.py +``` + +## Train +The training script is `train.py`. To see the detailed parameters for running: +```bash +python train.py -h +``` + +Some typical usage are listed as below: + +Train a SQLNet model with column attention: +```bash +python train.py --ca +``` + +Train a SQLNet model with column attention and trainable embedding (requires pretraining without training embedding, i.e., executing the command above): +```bash +python train.py --ca --train_emb +``` + +Pretrain a [Seq2SQL model](https://arxiv.org/abs/1709.00103) on the re-splitted dataset +```bash +python train.py --baseline --dataset 1 +``` + +Train a Seq2SQL model with Reinforcement Learning after pretraining +```bash +python train.py --baseline --dataset 1 --rl +``` + +## Test +The script for evaluation on the dev split and test split. The parameters for evaluation is roughly the same as the one used for training. For example, the commands for evaluating the models from above commands are: + +Test a trained SQLNet model with column attention +```bash +python test.py --ca +``` + +Test a trained SQLNet model with column attention and trainable embedding: +```bash +python test.py --ca --train_emb +``` + +Test a trained [Seq2SQL model](https://arxiv.org/abs/1709.00103) withour RL on the re-splitted dataset +```bash +python test.py --baseline --dataset 1 +``` + +Test a trained Seq2SQL model with Reinforcement learning +```bash +python test.py --baseline --dataset 1 --rl +``` + diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 0000000..db4e067 --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,55 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +import os +import sys +sys.path.insert(0, os.path.abspath('../../sqlnet')) + + +# -- Project information ----------------------------------------------------- + +project = 'SQLNet' +copyright = '2023, xiaojunxu' +author = 'xiaojunxu' + +# The full version, including alpha/beta/rc tags +release = '0.1.0' + + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = ['myst_parser' +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = [] + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'alabaster' + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] \ No newline at end of file diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 0000000..d93ea22 --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,11 @@ +.. SQLNet documentation master file, created by + sphinx-quickstart on Tue Jun 27 13:23:58 2023. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to SQLNet's documentation! +================================== + +.. toctree:: + README + diff --git a/docs/source/readme_link.rst b/docs/source/readme_link.rst new file mode 100644 index 0000000..fc4804d --- /dev/null +++ b/docs/source/readme_link.rst @@ -0,0 +1,4 @@ +About The Project +---------------------------- + +.. include:: README.md From c605313a703be753d6fe3cc585d9c1c20434d29f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Victor=20Batista?= Date: Wed, 28 Jun 2023 23:38:01 -0300 Subject: [PATCH 7/7] Implement CD to Pypi Co-authored by: Eduardo Maia --- .github/workflows/poetry_ci.yml | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/.github/workflows/poetry_ci.yml b/.github/workflows/poetry_ci.yml index ce1ce72..6d5aaaa 100644 --- a/.github/workflows/poetry_ci.yml +++ b/.github/workflows/poetry_ci.yml @@ -21,7 +21,28 @@ jobs: - name: Checkout code uses: actions/checkout@v2 - - name: Build and Test + - name: Build run: | poetry install poetry build + + deploy: + needs: build + runs-on: ubuntu-latest + + steps: + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: 3.9 + + - name: Install Poetry + run: curl -sSL https://install.python-poetry.org | python3 - + + - name: Checkout code + uses: actions/checkout@v2 + + - name: Publish to PyPI + run: | + poetry config pypi-token.pypi ${{ secrets.PYPI_PASSWORD }} + poetry publish --username ${{ secrets.PYPI_USERNAME }} --no-interaction