sqlutilpy 0.22.0__tar.gz → 0.24.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: sqlutilpy
3
- Version: 0.22.0
3
+ Version: 0.24.0
4
4
  Summary: Database query code returning numpy arrays
5
5
  Author-email: "Sergey E. Koposov" <skoposov@ed.ac.uk>
6
6
  License: BSD
@@ -9,12 +9,13 @@ Keywords: numpy postgresql query sql sqlite array
9
9
  Classifier: Development Status :: 3 - Alpha
10
10
  Classifier: License :: OSI Approved :: BSD License
11
11
  Classifier: Topic :: Utilities
12
- Requires-Python: >=3.6
12
+ Requires-Python: >=3.8
13
13
  Description-Content-Type: text/markdown
14
14
  License-File: LICENSE.txt
15
15
  Requires-Dist: numpy
16
- Requires-Dist: psycopg2-binary
16
+ Requires-Dist: psycopg[binary]
17
17
  Requires-Dist: numpydoc
18
+ Requires-Dist: numpy
18
19
 
19
20
  [![Build Status](https://github.com/segasai/sqlutilpy/workflows/Testing/badge.svg)](https://github.com/segasai/sqlutilpy/actions)
20
21
  [![Documentation Status](https://readthedocs.org/projects/sqlutilpy/badge/?version=latest)](http://sqlutilpy.readthedocs.io/en/latest/?badge=latest)
@@ -7,10 +7,11 @@ authors = [
7
7
  ]
8
8
  dependencies = [
9
9
  "numpy",
10
- "psycopg2-binary",
10
+ "psycopg[binary]",
11
11
  "numpydoc",
12
+ "numpy\n"
12
13
  ]
13
- requires-python = ">=3.6"
14
+ requires-python = ">=3.8"
14
15
  readme = "README.md"
15
16
  license = {text = "BSD"}
16
17
  keywords = ["numpy postgresql query sql sqlite array"]
@@ -3,13 +3,11 @@
3
3
  from __future__ import print_function
4
4
  import numpy
5
5
  import numpy as np
6
- import psycopg2
6
+ import psycopg
7
7
  import threading
8
8
  import collections
9
9
  import warnings
10
10
  from numpy.core import numeric as sb
11
- from select import select
12
- from psycopg2.extensions import POLL_OK, POLL_READ, POLL_WRITE
13
11
 
14
12
  try:
15
13
  import astropy.table as atpy
@@ -22,7 +20,6 @@ except ImportError:
22
20
  # pandas is not installed
23
21
  pandas = None
24
22
 
25
- from io import BytesIO as StringIO
26
23
  import queue
27
24
 
28
25
  _WAIT_SELECT_TIMEOUT = 10
@@ -37,31 +34,6 @@ class SqlUtilException(Exception):
37
34
  pass
38
35
 
39
36
 
40
- def __wait_select_inter(conn):
41
- """ Make the queries interruptible by Ctrl-C
42
-
43
- Taken from http://initd.org/psycopg/articles/2014/07/20/cancelling-postgresql-statements-python/ # noqa
44
- """
45
- while True:
46
- try:
47
- state = conn.poll()
48
- if state == POLL_OK:
49
- break
50
- elif state == POLL_READ:
51
- select([conn.fileno()], [], [], _WAIT_SELECT_TIMEOUT)
52
- elif state == POLL_WRITE:
53
- select([], [conn.fileno()], [], _WAIT_SELECT_TIMEOUT)
54
- else:
55
- raise conn.OperationalError("bad state from poll: %s" % state)
56
- except KeyboardInterrupt:
57
- conn.cancel()
58
- # the loop will be broken by a server error
59
- continue
60
-
61
-
62
- psycopg2.extensions.set_wait_callback(__wait_select_inter)
63
-
64
-
65
37
  def getConnection(db=None,
66
38
  driver=None,
67
39
  user=None,
@@ -80,7 +52,7 @@ def getConnection(db=None,
80
52
  The name of the database (in case of PostgreSQL) or filename in
81
53
  case of sqlite db
82
54
  driver : string
83
- The db driver (either 'psycopg2' or 'sqlite3')
55
+ The db driver (either 'psycopg' or 'sqlite3')
84
56
  user : string, optional
85
57
  Username
86
58
  password: string, optional
@@ -99,6 +71,10 @@ def getConnection(db=None,
99
71
 
100
72
  """
101
73
  if driver == 'psycopg2':
74
+ warnings.warn(
75
+ 'psycopg2 driver is not supported anymore using psycopg instead')
76
+ driver = 'psycopg'
77
+ if driver == 'psycopg':
102
78
  conn_dict = dict()
103
79
  if db is not None:
104
80
  conn_dict['dbname'] = db
@@ -110,7 +86,7 @@ def getConnection(db=None,
110
86
  conn_dict['user'] = user
111
87
  if password is not None:
112
88
  conn_dict['password'] = password
113
- conn = psycopg2.connect(**conn_dict)
89
+ conn = psycopg.connect(**conn_dict)
114
90
  elif driver == 'sqlite3':
115
91
  import sqlite3
116
92
  if timeout is None:
@@ -126,6 +102,10 @@ def getCursor(conn, driver=None, preamb=None, notNamed=False):
126
102
  Retrieve the database cursor
127
103
  """
128
104
  if driver == 'psycopg2':
105
+ warnings.warn(
106
+ 'psycopg2 driver is not supported anymore using psycopg instead')
107
+ driver = 'psycopg'
108
+ if driver == 'psycopg':
129
109
  cur = conn.cursor()
130
110
  if preamb is not None:
131
111
  cur.execute(preamb)
@@ -267,7 +247,7 @@ def __getDType(row, typeCodes, strLength):
267
247
  def get(query,
268
248
  params=None,
269
249
  db="wsdb",
270
- driver="psycopg2",
250
+ driver="psycopg",
271
251
  user=None,
272
252
  password=None,
273
253
  host=None,
@@ -304,7 +284,7 @@ def get(query,
304
284
  db : string
305
285
  The name of the database
306
286
  driver : string, optional
307
- The sql driver to be used (psycopg2 or sqlite3)
287
+ The sql driver to be used (psycopg or sqlite3)
308
288
  user : string, optional
309
289
  User name for the DB connection
310
290
  password : string, optional
@@ -359,26 +339,38 @@ def get(query,
359
339
  proc = None
360
340
  colNames = []
361
341
  if driver == 'psycopg2':
342
+ warnings.warn('psycopg2 driver is not supported anymore. '
343
+ 'We using psycopg instead')
344
+ driver = 'psycopg'
345
+ if driver == 'psycopg':
362
346
  try:
363
- while (True):
347
+ while True:
364
348
  # Iterating over the cursor, retrieving batches of results
365
349
  # and then sending them for conversion
366
350
  tups = cur.fetchmany()
367
351
  desc = cur.description
368
352
 
353
+ # If the is just the start we need to launch the
354
+ # thread doing the conversion
355
+ no_results = tups == []
356
+ if nrec == 0:
357
+ typeCodes = [_tmp.type_code for _tmp in desc]
358
+ colNames = [_tmp.name for _tmp in cur.description]
359
+
369
360
  # No more data
370
- if tups == []:
361
+ if no_results:
362
+ dtype = __getDType([None] * len(typeCodes), typeCodes,
363
+ strLength)
371
364
  break
372
365
 
366
+ dtype = __getDType(tups[0], typeCodes, strLength)
367
+
373
368
  # Send the new batch for conversion
374
369
  qIn.put(tups)
375
370
 
376
371
  # If the is just the start we need to launch the
377
372
  # thread doing the conversion
378
373
  if nrec == 0:
379
- typeCodes = [_tmp.type_code for _tmp in desc]
380
- colNames = [_tmp.name for _tmp in cur.description]
381
- dtype = __getDType(tups[0], typeCodes, strLength)
382
374
  proc = threading.Thread(target=__converter,
383
375
  args=(qIn, qOut, endEvent,
384
376
  dtype, intNullVal))
@@ -473,7 +465,7 @@ def get(query,
473
465
  def execute(query,
474
466
  params=None,
475
467
  db='wsdb',
476
- driver="psycopg2",
468
+ driver="psycopg",
477
469
  user=None,
478
470
  password=None,
479
471
  host=None,
@@ -493,7 +485,7 @@ def execute(query,
493
485
  db : string
494
486
  Database name
495
487
  driver : string
496
- Driver for the DB connection ('psycopg2' or 'sqlite3')
488
+ Driver for the DB connection ('psycopg' or 'sqlite3')
497
489
  user : string, optional
498
490
  user name for the DB connection
499
491
  password : string, optional
@@ -542,7 +534,7 @@ def __create_schema(tableName, arrays, names, temp=False):
542
534
  (np.uint64, 'bigint'), (np.int16, 'smallint'),
543
535
  (np.uint8, 'smallint'), (np.int8, 'smallint'),
544
536
  (np.float32, 'real'), (np.float64, 'double precision'),
545
- (np.string_, 'varchar'), (np.str_, 'varchar'),
537
+ (np.bytes_, 'varchar'), (np.str_, 'varchar'),
546
538
  (np.bool_, 'boolean'), (np.datetime64, 'timestamp')])
547
539
  if temp:
548
540
  temp = 'temporary'
@@ -568,7 +560,7 @@ def __print_arrays(arrays, f, delimiter=' '):
568
560
  format_dict = dict([(np.int32, '%d'), (np.int64, '%d'), (np.int16, '%d'),
569
561
  (np.int8, '%d'), (np.uint8, '%d'),
570
562
  (np.float32, '%.18e'), (np.float64, '%.18e'),
571
- (np.string_, '%s'), (np.str_, '%s'),
563
+ (np.bytes_, '%s'), (np.str_, '%s'),
572
564
  (np.datetime64, '%s'), (np.bool_, '%d')])
573
565
  fmts = []
574
566
  array_mode = False
@@ -626,7 +618,7 @@ def upload(tableName,
626
618
  arrays,
627
619
  names=None,
628
620
  db="wsdb",
629
- driver="psycopg2",
621
+ driver="psycopg",
630
622
  user=None,
631
623
  password=None,
632
624
  host=None,
@@ -653,7 +645,7 @@ def upload(tableName,
653
645
  db: string
654
646
  Databas name
655
647
  driver: string
656
- Python database driver "psycopg2",
648
+ Python database driver "psycopg",
657
649
  user: string,
658
650
  password: string
659
651
  host: string
@@ -743,18 +735,17 @@ table/pandas/dictionary or provide a separate list of arrays and their names')
743
735
  cur.execute(query1)
744
736
  nsplit = 100000
745
737
  N = len(arrays[0])
738
+ names = ','.join(names)
746
739
  for i in range(0, N, nsplit):
747
- f = StringIO()
748
- __print_arrays([_[i:i + nsplit] for _ in arrays],
749
- f,
750
- delimiter=delimiter)
751
- f.seek(0)
752
740
  try:
753
- thread = psycopg2.extensions.get_wait_callback()
754
- psycopg2.extensions.set_wait_callback(None)
755
- cur.copy_from(f, tableName, sep=delimiter, columns=names)
741
+ with cur.copy(f'''copy {tableName}({names}) from stdin
742
+ with delimiter '{delimiter}' ''') as copy:
743
+ __print_arrays([_[i:i + nsplit] for _ in arrays],
744
+ copy,
745
+ delimiter=delimiter)
746
+
756
747
  finally:
757
- psycopg2.extensions.set_wait_callback(thread)
748
+ pass
758
749
  except BaseException:
759
750
  failure_cleanup(conn, connSupplied)
760
751
  raise
@@ -772,7 +763,7 @@ def local_join(query,
772
763
  arrays,
773
764
  names,
774
765
  db=None,
775
- driver="psycopg2",
766
+ driver="psycopg",
776
767
  user=None,
777
768
  password=None,
778
769
  host=None,
@@ -0,0 +1 @@
1
+ __version__ = '0.24.0'
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: sqlutilpy
3
- Version: 0.22.0
3
+ Version: 0.24.0
4
4
  Summary: Database query code returning numpy arrays
5
5
  Author-email: "Sergey E. Koposov" <skoposov@ed.ac.uk>
6
6
  License: BSD
@@ -9,12 +9,13 @@ Keywords: numpy postgresql query sql sqlite array
9
9
  Classifier: Development Status :: 3 - Alpha
10
10
  Classifier: License :: OSI Approved :: BSD License
11
11
  Classifier: Topic :: Utilities
12
- Requires-Python: >=3.6
12
+ Requires-Python: >=3.8
13
13
  Description-Content-Type: text/markdown
14
14
  License-File: LICENSE.txt
15
15
  Requires-Dist: numpy
16
- Requires-Dist: psycopg2-binary
16
+ Requires-Dist: psycopg[binary]
17
17
  Requires-Dist: numpydoc
18
+ Requires-Dist: numpy
18
19
 
19
20
  [![Build Status](https://github.com/segasai/sqlutilpy/workflows/Testing/badge.svg)](https://github.com/segasai/sqlutilpy/actions)
20
21
  [![Documentation Status](https://readthedocs.org/projects/sqlutilpy/badge/?version=latest)](http://sqlutilpy.readthedocs.io/en/latest/?badge=latest)
@@ -0,0 +1,4 @@
1
+ numpy
2
+ psycopg[binary]
3
+ numpydoc
4
+ numpy
@@ -1,7 +1,7 @@
1
1
  import pytest
2
2
  import string
3
3
  import os
4
- import psycopg2
4
+ import psycopg
5
5
  import numpy as np
6
6
  import sqlutilpy as sqlutil
7
7
  import time
@@ -16,7 +16,7 @@ PG_PASS = os.environ['SQLUTIL_TEST_PG_PASS']
16
16
  def getrand(N, float=False):
17
17
  # simple deterministic pseudo-random number generator
18
18
  a, c = 1103515245, 12345
19
- m = 2 ^ 31
19
+ m = 2**31
20
20
  arr = np.zeros(N)
21
21
  arr[0] = 1
22
22
  for i in range(1, N):
@@ -37,8 +37,8 @@ def getconn():
37
37
 
38
38
  @pytest.fixture
39
39
  def setup():
40
- conn = psycopg2.connect('dbname=%s user=%s host=%s password=%s' %
41
- (PG_DB, PG_USER, PG_HOST, PG_PASS))
40
+ conn = psycopg.connect('dbname=%s user=%s host=%s password=%s' %
41
+ (PG_DB, PG_USER, PG_HOST, PG_PASS))
42
42
  cur = conn.cursor()
43
43
  cur.execute('''
44
44
  create unlogged table sqlutil_test (sicol smallint, intcol int,
@@ -123,11 +123,14 @@ def test_nocommit(setup):
123
123
 
124
124
  def test_local_join(setup):
125
125
  kw, conn = setup
126
+ N = 1000
127
+ rands = np.random.uniform(size=N)
126
128
  R, = sqlutil.local_join(
127
129
  '''
128
- select s.sicol from sqlutil_test as s, mytab as m
129
- where s.sicol = m.id''', 'mytab', [np.arange(10)], ['id'], **kw)
130
- assert (len(R) == 1)
130
+ select xf from sqlutil_test as s, mytab as m
131
+ where s.sicol = m.id''', 'mytab', [np.arange(N), rands], ['id', 'xf'],
132
+ **kw)
133
+ assert (len(R) == 2)
131
134
 
132
135
 
133
136
  def test_big(setup):
@@ -252,6 +255,12 @@ def test_get_dict(setup):
252
255
  **kw)
253
256
  for i, k in enumerate(cols.split(',')):
254
257
  assert ((Rd[k] == R0[i]).all())
258
+ Rempty = sqlutil.get('select %s from sqlutil_test where sicol<-10000' %
259
+ (cols, ),
260
+ asDict=True,
261
+ **kw)
262
+ for i, k in enumerate(cols.split(',')):
263
+ assert k in Rempty
255
264
 
256
265
 
257
266
  def test_get_dict_rep(setup):
@@ -392,10 +401,27 @@ def test_upload(setup):
392
401
  # try the weird names
393
402
  sqlutil.upload(mytab1, (xi16, xi32, xi64, xf32, xf64, xbool),
394
403
  ('xi 16', 'xi(32)', 'xi[64]', 'xf32', 'xf64', 'xbool'),
395
- **kw)
404
+ temp=True,
405
+ conn=conn)
396
406
  yi16, yi32, yi64, yf32, yf64, ybool = sqlutil.get(
397
407
  '''select xi_16,xi_32_,xi_64_,xf32,xf64,xbool from %s''' % (mytab1),
398
- **kw)
408
+ conn=conn)
409
+
410
+
411
+ def test_upload_big(setup):
412
+ kw, conn = setup
413
+ mytab = 'sqlutil_test_tab_big'
414
+ nrows = 1_000_000
415
+ xi = np.arange(nrows, dtype=np.int32)
416
+ xf = getrand(nrows, True)
417
+ sqlutil.upload(mytab, (xi, xf), ('xi', 'xf'), **kw)
418
+ yi, yf = sqlutil.get('''select xi,xf from %s order by xi''' % (mytab),
419
+ **kw)
420
+ try:
421
+ assert ((xi == yi).all())
422
+ assert (np.allclose(xf, yf))
423
+ finally:
424
+ sqlutil.execute('drop table %s' % mytab, **kw)
399
425
 
400
426
 
401
427
  def test_upload_array(setup):
@@ -1,12 +1,7 @@
1
1
  import pytest
2
- import string
3
2
  import os
4
- import psycopg2
5
- import numpy as np
6
3
  import sqlutilpy as sqlutil
7
4
  import sqlite3
8
- import time
9
- import killer
10
5
 
11
6
 
12
7
  @pytest.fixture()
@@ -1 +0,0 @@
1
- __version__ = '0.22.0'
@@ -1,3 +0,0 @@
1
- numpy
2
- psycopg2-binary
3
- numpydoc
File without changes
File without changes
File without changes
File without changes
File without changes