Skip to content

Commit 4fc2cca

Browse files
authored
Merge pull request #1247 from dimitri-yatsenko/master
Fix error message when deleting without delete privilege
2 parents 53e38f7 + ac141e7 commit 4fc2cca

File tree

16 files changed

+56
-53
lines changed

16 files changed

+56
-53
lines changed

datajoint/autopopulate.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ def make(self, key):
100100
101101
1. Fetch data from tables above in the dependency hierarchy, restricted by the given key.
102102
2. Compute secondary attributes based on the fetched data.
103-
3. Insert the new tuples into the current table.
103+
3. Insert the new tuple(s) into the current table.
104104
105105
The method can be implemented either as:
106106
(a) Regular method: All three steps are performed in a single database transaction.
@@ -146,7 +146,8 @@ def make(self, key):
146146
):
147147
# user must implement `make`
148148
raise NotImplementedError(
149-
"Subclasses of AutoPopulate must implement the method `make` or (`make_fetch` + `make_compute` + `make_insert`)"
149+
"Subclasses of AutoPopulate must implement the method `make` "
150+
"or (`make_fetch` + `make_compute` + `make_insert`)"
150151
)
151152

152153
# User has implemented `_fetch`, `_compute`, and `_insert` methods instead
@@ -265,9 +266,8 @@ def populate(
265266
self.connection.schemas[self.target.database].jobs if reserve_jobs else None
266267
)
267268

268-
# define and set up signal handler for SIGTERM:
269269
if reserve_jobs:
270-
270+
# Define a signal handler for SIGTERM
271271
def handler(signum, frame):
272272
logger.info("Populate terminated by SIGTERM")
273273
raise SystemExit("SIGTERM received")

datajoint/blob.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ def read_blob(self, n_bytes=None):
140140
"S": self.read_struct, # matlab struct array
141141
"C": self.read_cell_array, # matlab cell array
142142
# basic data types
143-
"\xFF": self.read_none, # None
143+
"\xff": self.read_none, # None
144144
"\x01": self.read_tuple, # a Sequence (e.g. tuple)
145145
"\x02": self.read_list, # a MutableSequence (e.g. list)
146146
"\x03": self.read_set, # a Set
@@ -401,7 +401,7 @@ def read_none(self):
401401

402402
@staticmethod
403403
def pack_none():
404-
return b"\xFF"
404+
return b"\xff"
405405

406406
def read_tuple(self):
407407
return tuple(

datajoint/condition.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
""" methods for generating SQL WHERE clauses from datajoint restriction conditions """
1+
"""methods for generating SQL WHERE clauses from datajoint restriction conditions"""
22

33
import collections
44
import datetime

datajoint/preview.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
""" methods for generating previews of query expression results in python command line and Jupyter """
1+
"""methods for generating previews of query expression results in python command line and Jupyter"""
22

33
from .settings import config
44

datajoint/table.py

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ def alter(self, prompt=True, context=None):
137137
sql, external_stores = alter(self.definition, old_definition, context)
138138
if not sql:
139139
if prompt:
140-
logger.warn("Nothing to alter.")
140+
logger.warning("Nothing to alter.")
141141
else:
142142
sql = "ALTER TABLE {tab}\n\t".format(
143143
tab=self.full_table_name
@@ -520,7 +520,13 @@ def cascade(table):
520520
try:
521521
delete_count = table.delete_quick(get_count=True)
522522
except IntegrityError as error:
523-
match = foreign_key_error_regexp.match(error.args[0]).groupdict()
523+
match = foreign_key_error_regexp.match(error.args[0])
524+
if match is None:
525+
raise DataJointError(
526+
"Cascading deletes failed because the error message is missing foreign key information."
527+
"Make sure you have REFERENCES privilege to all dependent tables."
528+
) from None
529+
match = match.groupdict()
524530
# if schema name missing, use table
525531
if "`.`" not in match["child"]:
526532
match["child"] = "{}.{}".format(
@@ -643,7 +649,7 @@ def cascade(table):
643649
# Confirm and commit
644650
if delete_count == 0:
645651
if safemode:
646-
logger.warn("Nothing to delete.")
652+
logger.warning("Nothing to delete.")
647653
if transaction:
648654
self.connection.cancel_transaction()
649655
elif not transaction:
@@ -653,12 +659,12 @@ def cascade(table):
653659
if transaction:
654660
self.connection.commit_transaction()
655661
if safemode:
656-
logger.info("Deletes committed.")
662+
logger.info("Delete committed.")
657663
else:
658664
if transaction:
659665
self.connection.cancel_transaction()
660666
if safemode:
661-
logger.warn("Deletes cancelled")
667+
logger.warning("Delete cancelled")
662668
return delete_count
663669

664670
def drop_quick(self):
@@ -726,11 +732,6 @@ def size_on_disk(self):
726732
).fetchone()
727733
return ret["Data_length"] + ret["Index_length"]
728734

729-
def show_definition(self):
730-
raise AttributeError(
731-
"show_definition is deprecated. Use the describe method instead."
732-
)
733-
734735
def describe(self, context=None, printout=False):
735736
"""
736737
:return: the definition string for the query using DataJoint DDL.

datajoint/utils.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,3 +147,5 @@ def parse_sql(filepath):
147147
if line.endswith(delimiter):
148148
yield " ".join(statement)
149149
statement = []
150+
if statement:
151+
yield " ".join(statement)

docs/src/concepts/data-model.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ columns (often called attributes).
5454
A collection of base relations with their attributes, domain constraints, uniqueness
5555
constraints, and referential constraints is called a schema.
5656

57-
**Domain constraints:**
57+
**Domain constraints:**
5858
Each attribute (column) in a table is associated with a specific attribute domain (or
5959
datatype, a set of possible values), ensuring that the data entered is valid.
6060
Attribute domains may not include relations, which keeps the data model
@@ -68,13 +68,13 @@ columns (often called attributes).
6868
One key in a relation is designated as the primary key used for referencing its elements.
6969

7070
**Referential constraints:**
71-
Associations among data are established by means of referential constraints with the
71+
Associations among data are established by means of referential constraints with the
7272
help of foreign keys.
7373
A referential constraint on relation A referencing relation B allows only those
7474
entities in A whose foreign key attributes match the key attributes of an entity in B.
7575

7676
**Declarative queries:**
77-
Data queries are formulated through declarative, as opposed to imperative,
77+
Data queries are formulated through declarative, as opposed to imperative,
7878
specifications of sought results.
7979
This means that query expressions convey the logic for the result rather than the
8080
procedure for obtaining it.
@@ -106,7 +106,7 @@ clarity, efficiency, workflow management, and precise and flexible data
106106
queries. By enforcing entity normalization,
107107
simplifying dependency declarations, offering a rich query algebra, and visualizing
108108
relationships through schema diagrams, DataJoint makes relational database programming
109-
more intuitive and robust for complex data pipelines.
109+
more intuitive and robust for complex data pipelines.
110110

111111
The model has emerged over a decade of continuous development of complex data
112112
pipelines for neuroscience experiments ([Yatsenko et al.,
@@ -123,7 +123,7 @@ DataJoint comprises:
123123
+ a schema [definition](../design/tables/declare.md) language
124124
+ a data [manipulation](../manipulation/index.md) language
125125
+ a data [query](../query/principles.md) language
126-
+ a [diagramming](../design/diagrams.md) notation for visualizing relationships between
126+
+ a [diagramming](../design/diagrams.md) notation for visualizing relationships between
127127
modeled entities
128128

129129
The key refinement of DataJoint over other relational data models and their

docs/src/concepts/teamwork.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -60,33 +60,33 @@ division of labor among team members, leading to greater efficiency and better s
6060
### Scientists
6161

6262
Design and conduct experiments, collecting data.
63-
They interact with the data pipeline through graphical user interfaces designed by
63+
They interact with the data pipeline through graphical user interfaces designed by
6464
others.
6565
They understand what analysis is used to test their hypotheses.
6666

6767
### Data scientists
6868

69-
Have the domain expertise and select and implement the processing and analysis
69+
Have the domain expertise and select and implement the processing and analysis
7070
methods for experimental data.
71-
Data scientists are in charge of defining and managing the data pipeline using
72-
DataJoint's data model, but they may not know the details of the underlying
71+
Data scientists are in charge of defining and managing the data pipeline using
72+
DataJoint's data model, but they may not know the details of the underlying
7373
architecture.
74-
They interact with the pipeline using client programming interfaces directly from
74+
They interact with the pipeline using client programming interfaces directly from
7575
languages such as MATLAB and Python.
7676

77-
The bulk of this manual is written for working data scientists, except for System
77+
The bulk of this manual is written for working data scientists, except for System
7878
Administration.
7979

8080
### Data engineers
8181

8282
Work with the data scientists to support the data pipeline.
83-
They rely on their understanding of the DataJoint data model to configure and
84-
administer the required IT resources such as database servers, data storage
83+
They rely on their understanding of the DataJoint data model to configure and
84+
administer the required IT resources such as database servers, data storage
8585
servers, networks, cloud instances, [Globus](https://globus.org) endpoints, etc.
86-
Data engineers can provide general solutions such as web hosting, data publishing,
86+
Data engineers can provide general solutions such as web hosting, data publishing,
8787
interfaces, exports and imports.
8888

89-
The System Administration section of this tutorial contains materials helpful in
89+
The System Administration section of this tutorial contains materials helpful in
9090
accomplishing these tasks.
9191

9292
DataJoint is designed to delineate a clean boundary between **data science** and **data

docs/src/design/integrity.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Data Integrity
22

3-
The term **data integrity** describes guarantees made by the data management process
4-
that prevent errors and corruption in data due to technical failures and human errors
3+
The term **data integrity** describes guarantees made by the data management process
4+
that prevent errors and corruption in data due to technical failures and human errors
55
arising in the course of continuous use by multiple agents.
66
DataJoint pipelines respect the following forms of data integrity: **entity
77
integrity**, **referential integrity**, and **group integrity** as described in more

docs/src/design/tables/customtype.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ attribute type in a datajoint table class:
4949
import datajoint as dj
5050

5151
class GraphAdapter(dj.AttributeAdapter):
52-
52+
5353
attribute_type = 'longblob' # this is how the attribute will be declared
54-
54+
5555
def put(self, obj):
5656
# convert the nx.Graph object into an edge list
5757
assert isinstance(obj, nx.Graph)
@@ -60,7 +60,7 @@ class GraphAdapter(dj.AttributeAdapter):
6060
def get(self, value):
6161
# convert edge list back into an nx.Graph
6262
return nx.Graph(value)
63-
63+
6464

6565
# instantiate for use as a datajoint type
6666
graph = GraphAdapter()
@@ -75,6 +75,6 @@ class Connectivity(dj.Manual):
7575
definition = """
7676
conn_id : int
7777
---
78-
conn_graph = null : <graph> # a networkx.Graph object
78+
conn_graph = null : <graph> # a networkx.Graph object
7979
"""
8080
```

0 commit comments

Comments
 (0)