Skip to content

Commit 61ee20a

Browse files
Resolve merge conflicts.
2 parents 0d06ca4 + 4d258e3 commit 61ee20a

21 files changed

+88
-81
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,5 @@ docker-compose.yml
2323
notebook
2424
.vscode
2525
__main__.py
26-
jupyter_custom.js
26+
jupyter_custom.js
27+
apk_requirements.txt

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
## Release notes
22

3+
### 0.12.7b1 -- Oct 27, 2020
4+
* Fix case sensitivity issues to adapt to MySQL 8+. PR #819
5+
* Fix pymysql regression bug (#814) PR #816
6+
* Adapted attribute types now have dtype=object in all recarray results. PR #811
7+
38
### 0.12.6b1 -- May 18, 2020
49
* Add `order_by` to `dj.kill` (#668, #779) PR #775, #783
510
* Add explicit S3 bucket and file storage location existence checks (#748) PR #781

LNX-docker-compose.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# docker-compose -f LNX-docker-compose.yml --env-file LNX.env up --build --exit-code-from app
12
version: '2.2'
23
x-net: &net
34
networks:
@@ -31,7 +32,7 @@ services:
3132
interval: 1s
3233
fakeservices.datajoint.io:
3334
<<: *net
34-
image: raphaelguzman/nginx:v0.0.6
35+
image: raphaelguzman/nginx:v0.0.10
3536
environment:
3637
- ADD_db_TYPE=DATABASE
3738
- ADD_db_ENDPOINT=db:3306

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ GID=1000
114114
* `cp local-docker-compose.yml docker-compose.yml`
115115
* `docker-compose up -d` (Note configured `JUPYTER_PASSWORD`)
116116
* Select a means of running Tests e.g. Docker Terminal, or Local Terminal (see bottom)
117+
* Add entry in `/etc/hosts` for `127.0.0.1 fakeservices.datajoint.io`
117118
* Run desired tests. Some examples are as follows:
118119

119120
| Use Case | Shell Code |
@@ -137,4 +138,4 @@ GID=1000
137138
### Launch Jupyter Notebook for Interactive Use
138139
* Navigate to `localhost:8888`
139140
* Input Jupyter password
140-
* Launch a notebook i.e. `New > Python 3`
141+
* Launch a notebook i.e. `New > Python 3`

datajoint/admin.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,11 @@ def kill(restriction=None, connection=None, order_by=None): # pragma: no cover
4949
while True:
5050
print(' ID USER HOST STATE TIME INFO')
5151
print('+--+ +----------+ +-----------+ +-----------+ +-----+')
52-
cur = connection.query(query, as_dict=True)
52+
cur = ({k.lower(): v for k, v in elem.items()}
53+
for elem in connection.query(query, as_dict=True))
5354
for process in cur:
5455
try:
55-
print('{ID:>4d} {USER:<12s} {HOST:<12s} {STATE:<12s} {TIME:>7d} {INFO}'.format(**process))
56+
print('{id:>4d} {user:<12s} {host:<12s} {state:<12s} {time:>7d} {info}'.format(**process))
5657
except TypeError:
5758
print(process)
5859
response = input('process to kill or "q" to quit > ')
@@ -88,9 +89,10 @@ def kill_quick(restriction=None, connection=None):
8889
query = 'SELECT * FROM information_schema.processlist WHERE id <> CONNECTION_ID()' + (
8990
"" if restriction is None else ' AND (%s)' % restriction)
9091

91-
cur = connection.query(query, as_dict=True)
92+
cur = ({k.lower(): v for k, v in elem.items()}
93+
for elem in connection.query(query, as_dict=True))
9294
nkill = 0
9395
for process in cur:
94-
connection.query('kill %d' % process['ID'])
96+
connection.query('kill %d' % process['id'])
9597
nkill += 1
9698
return nkill

datajoint/attribute_adapter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def get(self, value):
2525
def put(self, obj):
2626
"""
2727
convert an object of the adapted type into a value that DataJoint can store in a table attribute
28-
:param object: an object of the adapted type
28+
:param obj: an object of the adapted type
2929
:return: value to store in the database
3030
"""
3131
raise NotImplementedError('Undefined attribute adapter')

datajoint/connection.py

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313
from .dependencies import Dependencies
1414
from .plugin import connection_plugins
1515

16-
# client errors to catch
17-
client_errors = (client.err.InterfaceError, client.err.DatabaseError)
16+
logger = logging.getLogger(__name__)
17+
query_log_max_length = 300
1818

1919

2020
def get_host_hook(host_input):
@@ -48,39 +48,39 @@ def translate_query_error(client_error, query):
4848
:param query: sql query with placeholders
4949
:return: an instance of the corresponding subclass of datajoint.errors.DataJointError
5050
"""
51+
logger.debug('type: {}, args: {}'.format(type(client_error), client_error.args))
52+
53+
err, *args = client_error.args
54+
5155
# Loss of connection errors
52-
if isinstance(client_error, client.err.InterfaceError) and client_error.args[0] == "(0, '')":
53-
return errors.LostConnectionError('Server connection lost due to an interface error.', *client_error.args[1:])
54-
disconnect_codes = {
55-
2006: "Connection timed out",
56-
2013: "Server connection lost"}
57-
if isinstance(client_error, client.err.OperationalError) and client_error.args[0] in disconnect_codes:
58-
return errors.LostConnectionError(disconnect_codes[client_error.args[0]], *client_error.args[1:])
56+
if err in (0, "(0, '')"):
57+
return errors.LostConnectionError('Server connection lost due to an interface error.', *args)
58+
if err == 2006:
59+
return errors.LostConnectionError("Connection timed out", *args)
60+
if err == 2013:
61+
return errors.LostConnectionError("Server connection lost", *args)
5962
# Access errors
60-
if isinstance(client_error, client.err.OperationalError) and client_error.args[0] in (1044, 1142):
61-
return errors.AccessError('Insufficient privileges.', client_error.args[1], query)
63+
if err in (1044, 1142):
64+
return errors.AccessError('Insufficient privileges.', args[0], query)
6265
# Integrity errors
63-
if isinstance(client_error, client.err.IntegrityError) and client_error.args[0] == 1062:
64-
return errors.DuplicateError(*client_error.args[1:])
65-
if isinstance(client_error, client.err.IntegrityError) and client_error.args[0] == 1452:
66-
return errors.IntegrityError(*client_error.args[1:])
66+
if err == 1062:
67+
return errors.DuplicateError(*args)
68+
if err == 1452:
69+
return errors.IntegrityError(*args)
6770
# Syntax errors
68-
if isinstance(client_error, client.err.ProgrammingError) and client_error.args[0] == 1064:
69-
return errors.QuerySyntaxError(client_error.args[1], query)
71+
if err == 1064:
72+
return errors.QuerySyntaxError(args[0], query)
7073
# Existence errors
71-
if isinstance(client_error, client.err.ProgrammingError) and client_error.args[0] == 1146:
72-
return errors.MissingTableError(client_error.args[1], query)
73-
if isinstance(client_error, client.err.InternalError) and client_error.args[0] == 1364:
74-
return errors.MissingAttributeError(*client_error.args[1:])
75-
if isinstance(client_error, client.err.InternalError) and client_error.args[0] == 1054:
76-
return errors.UnknownAttributeError(*client_error.args[1:])
74+
if err == 1146:
75+
return errors.MissingTableError(args[0], query)
76+
if err == 1364:
77+
return errors.MissingAttributeError(*args)
78+
if err == 1054:
79+
return errors.UnknownAttributeError(*args)
7780
# all the other errors are re-raised in original form
7881
return client_error
7982

8083

81-
logger = logging.getLogger(__name__)
82-
83-
8484
def conn(host=None, user=None, password=None, *, init_fun=None, reset=False, use_tls=None):
8585
"""
8686
Returns a persistent connection object to be shared by multiple modules.
@@ -221,7 +221,7 @@ def _execute_query(cursor, query, args, cursor_class, suppress_warnings):
221221
# suppress all warnings arising from underlying SQL library
222222
warnings.simplefilter("ignore")
223223
cursor.execute(query, args)
224-
except client_errors as err:
224+
except client.err.Error as err:
225225
raise translate_query_error(err, query)
226226

227227
def query(self, query, args=(), *, as_dict=False, suppress_warnings=True, reconnect=None):
@@ -236,7 +236,7 @@ def query(self, query, args=(), *, as_dict=False, suppress_warnings=True, reconn
236236
"""
237237
if reconnect is None:
238238
reconnect = config['database.reconnect']
239-
logger.debug("Executing SQL:" + query[0:300])
239+
logger.debug("Executing SQL:" + query[:query_log_max_length])
240240
cursor_class = client.cursors.DictCursor if as_dict else client.cursors.Cursor
241241
cursor = self._conn.cursor(cursor=cursor_class)
242242
try:

datajoint/dependencies.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ class Dependencies(nx.DiGraph):
88
"""
99
The graph of dependencies (foreign keys) between loaded tables.
1010
11-
Note: the 'connnection' argument should normally be supplied;
12-
Empty use is permitted to facilliate use of networkx algorithms which
11+
Note: the 'connection' argument should normally be supplied;
12+
Empty use is permitted to facilitate use of networkx algorithms which
1313
internally create objects with the expectation of empty constructors.
1414
See also: https://github.com/datajoint/datajoint-python/pull/443
1515
"""
@@ -43,15 +43,15 @@ def load(self):
4343
self.add_node(n, primary_key=pk)
4444

4545
# load foreign keys
46-
keys = self._conn.query("""
46+
keys = ({k.lower(): v for k, v in elem.items()} for elem in self._conn.query("""
4747
SELECT constraint_name,
4848
concat('`', table_schema, '`.`', table_name, '`') as referencing_table,
4949
concat('`', referenced_table_schema, '`.`', referenced_table_name, '`') as referenced_table,
5050
column_name, referenced_column_name
5151
FROM information_schema.key_column_usage
5252
WHERE referenced_table_name NOT LIKE "~%%" AND (referenced_table_schema in ('{schemas}') OR
5353
referenced_table_schema is not NULL AND table_schema in ('{schemas}'))
54-
""".format(schemas="','".join(self._conn.schemas)), as_dict=True)
54+
""".format(schemas="','".join(self._conn.schemas)), as_dict=True))
5555
fks = defaultdict(lambda: dict(attr_map=OrderedDict()))
5656
for key in keys:
5757
d = fks[(key['constraint_name'], key['referencing_table'], key['referenced_table'])]
@@ -107,7 +107,6 @@ def descendants(self, full_table_name):
107107
"""
108108
nodes = self.subgraph(
109109
nx.algorithms.dag.descendants(self, full_table_name))
110-
111110
return [full_table_name] + list(
112111
nx.algorithms.dag.topological_sort(nodes))
113112

datajoint/external.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,11 +276,11 @@ def references(self):
276276
"""
277277
:return: generator of referencing table names and their referencing columns
278278
"""
279-
return self.connection.query("""
279+
return ({k.lower(): v for k, v in elem.items()} for elem in self.connection.query("""
280280
SELECT concat('`', table_schema, '`.`', table_name, '`') as referencing_table, column_name
281281
FROM information_schema.key_column_usage
282282
WHERE referenced_table_name="{tab}" and referenced_table_schema="{db}"
283-
""".format(tab=self.table_name, db=self.database), as_dict=True)
283+
""".format(tab=self.table_name, db=self.database), as_dict=True))
284284

285285
def fetch_external_paths(self, **fetch_kwargs):
286286
"""

datajoint/heading.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ def init_from_database(self, conn, database, table_name, context):
279279

280280
# fill out dtype. All floats and non-nullable integers are turned into specific dtypes
281281
attr['dtype'] = object
282-
if attr['numeric']:
282+
if attr['numeric'] and not attr['adapter']:
283283
is_integer = TYPE_PATTERN['INTEGER'].match(attr['type'])
284284
is_float = TYPE_PATTERN['FLOAT'].match(attr['type'])
285285
if is_integer and not attr['nullable'] or is_float:

0 commit comments

Comments
 (0)