Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/development.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8
pip install flake8 black
- name: Run syntax tests
run: flake8 datajoint --count --select=E9,F63,F7,F82 --show-source --statistics
- name: Run primary tests
Expand All @@ -47,5 +47,7 @@ jobs:
run: docker-compose -f LNX-docker-compose.yml up --build --exit-code-from app
- name: Run style tests
run: |
flake8 --ignore=E121,E123,E126,E226,E24,E704,W503,W504,E722,F401,W605 datajoint \
flake8 --ignore=E203,E722,F401,W503 datajoint \
--count --max-complexity=62 --max-line-length=127 --statistics
black datajoint --check -v
black tests --check -v
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
## Release notes

### 0.13.4 -- March, 25 2022
### 0.13.4 -- March, 28 2022
* Add - Allow reading blobs produced by legacy 32-bit compiled mYm library for matlab. PR #995
* Bugfix - Add missing `jobs` argument for multiprocessing PR #997
* Add - Test for multiprocessing PR #1008
* Bugfix - Fix external store key name doesn't allow '-' (#1005) PR #1006
* Add - Adopted black formatting into code base PR #998

### 0.13.3 -- Feb 9, 2022
* Bugfix - Fix error in listing ancestors, descendants with part tables.
Expand Down
49 changes: 37 additions & 12 deletions datajoint/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,40 @@

__author__ = "DataJoint Contributors"
__date__ = "November 7, 2020"
__all__ = ['__author__', '__version__',
'config', 'conn', 'Connection',
'Schema', 'schema', 'VirtualModule', 'create_virtual_module',
'list_schemas', 'Table', 'FreeTable',
'Manual', 'Lookup', 'Imported', 'Computed', 'Part',
'Not', 'AndList', 'U', 'Diagram', 'Di', 'ERD',
'set_password', 'kill',
'MatCell', 'MatStruct', 'AttributeAdapter',
'errors', 'DataJointError', 'key', 'key_hash']
__all__ = [
"__author__",
"__version__",
"config",
"conn",
"Connection",
"Schema",
"schema",
"VirtualModule",
"create_virtual_module",
"list_schemas",
"Table",
"FreeTable",
"Manual",
"Lookup",
"Imported",
"Computed",
"Part",
"Not",
"AndList",
"U",
"Diagram",
"Di",
"ERD",
"set_password",
"kill",
"MatCell",
"MatStruct",
"AttributeAdapter",
"errors",
"DataJointError",
"key",
"key_hash",
]

from .version import __version__
from .settings import config
Expand All @@ -44,6 +69,6 @@
from .errors import DataJointError
from .migrate import migrate_dj011_external_blob_storage_to_dj012

ERD = Di = Diagram # Aliases for Diagram
schema = Schema # Aliases for Schema
create_virtual_module = VirtualModule # Aliases for VirtualModule
ERD = Di = Diagram # Aliases for Diagram
schema = Schema # Aliases for Schema
create_virtual_module = VirtualModule # Aliases for VirtualModule
64 changes: 40 additions & 24 deletions datajoint/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,23 @@
from .utils import user_choice


def set_password(new_password=None, connection=None, update_config=None): # pragma: no cover
def set_password(
new_password=None, connection=None, update_config=None
): # pragma: no cover
connection = conn() if connection is None else connection
if new_password is None:
new_password = getpass('New password: ')
confirm_password = getpass('Confirm password: ')
new_password = getpass("New password: ")
confirm_password = getpass("Confirm password: ")
if new_password != confirm_password:
print('Failed to confirm the password! Aborting password change.')
print("Failed to confirm the password! Aborting password change.")
return
connection.query("SET PASSWORD = PASSWORD('%s')" % new_password)
print('Password updated.')
print("Password updated.")

if update_config or (update_config is None and user_choice('Update local setting?') == 'yes'):
config['database.password'] = new_password
if update_config or (
update_config is None and user_choice("Update local setting?") == "yes"
):
config["database.password"] = new_password
config.save_local(verbose=True)


Expand All @@ -40,24 +44,32 @@ def kill(restriction=None, connection=None, order_by=None): # pragma: no cover
connection = conn()

if order_by is not None and not isinstance(order_by, str):
order_by = ','.join(order_by)
order_by = ",".join(order_by)

query = 'SELECT * FROM information_schema.processlist WHERE id <> CONNECTION_ID()' + (
"" if restriction is None else ' AND (%s)' % restriction) + (
' ORDER BY %s' % (order_by or 'id'))
query = (
"SELECT * FROM information_schema.processlist WHERE id <> CONNECTION_ID()"
+ ("" if restriction is None else " AND (%s)" % restriction)
+ (" ORDER BY %s" % (order_by or "id"))
)

while True:
print(' ID USER HOST STATE TIME INFO')
print('+--+ +----------+ +-----------+ +-----------+ +-----+')
cur = ({k.lower(): v for k, v in elem.items()}
for elem in connection.query(query, as_dict=True))
print(" ID USER HOST STATE TIME INFO")
print("+--+ +----------+ +-----------+ +-----------+ +-----+")
cur = (
{k.lower(): v for k, v in elem.items()}
for elem in connection.query(query, as_dict=True)
)
for process in cur:
try:
print('{id:>4d} {user:<12s} {host:<12s} {state:<12s} {time:>7d} {info}'.format(**process))
print(
"{id:>4d} {user:<12s} {host:<12s} {state:<12s} {time:>7d} {info}".format(
**process
)
)
except TypeError:
print(process)
response = input('process to kill or "q" to quit > ')
if response == 'q':
if response == "q":
break
if response:
try:
Expand All @@ -66,9 +78,9 @@ def kill(restriction=None, connection=None, order_by=None): # pragma: no cover
pass # ignore non-numeric input
else:
try:
connection.query('kill %d' % pid)
connection.query("kill %d" % pid)
except pymysql.err.InternalError:
print('Process not found')
print("Process not found")


def kill_quick(restriction=None, connection=None):
Expand All @@ -86,13 +98,17 @@ def kill_quick(restriction=None, connection=None):
if connection is None:
connection = conn()

query = 'SELECT * FROM information_schema.processlist WHERE id <> CONNECTION_ID()' + (
"" if restriction is None else ' AND (%s)' % restriction)
query = (
"SELECT * FROM information_schema.processlist WHERE id <> CONNECTION_ID()"
+ ("" if restriction is None else " AND (%s)" % restriction)
)

cur = ({k.lower(): v for k, v in elem.items()}
for elem in connection.query(query, as_dict=True))
cur = (
{k.lower(): v for k, v in elem.items()}
for elem in connection.query(query, as_dict=True)
)
nkill = 0
for process in cur:
connection.query('kill %d' % process['id'])
connection.query("kill %d" % process["id"])
nkill += 1
return nkill
38 changes: 26 additions & 12 deletions datajoint/attribute_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,48 +7,62 @@ class AttributeAdapter:
"""
Base class for adapter objects for user-defined attribute types.
"""

@property
def attribute_type(self):
"""
:return: a supported DataJoint attribute type to use; e.g. "longblob", "blob@store"
"""
raise NotImplementedError('Undefined attribute adapter')
raise NotImplementedError("Undefined attribute adapter")

def get(self, value):
"""
convert value retrieved from the the attribute in a table into the adapted type
:param value: value from the database
:return: object of the adapted type
"""
raise NotImplementedError('Undefined attribute adapter')
raise NotImplementedError("Undefined attribute adapter")

def put(self, obj):
"""
convert an object of the adapted type into a value that DataJoint can store in a table attribute
:param obj: an object of the adapted type
:return: value to store in the database
"""
raise NotImplementedError('Undefined attribute adapter')
raise NotImplementedError("Undefined attribute adapter")


def get_adapter(context, adapter_name):
"""
Extract the AttributeAdapter object by its name from the context and validate.
"""
if not _support_adapted_types():
raise DataJointError('Support for Adapted Attribute types is disabled.')
adapter_name = adapter_name.lstrip('<').rstrip('>')
raise DataJointError("Support for Adapted Attribute types is disabled.")
adapter_name = adapter_name.lstrip("<").rstrip(">")
try:
adapter = (context[adapter_name] if adapter_name in context
else type_plugins[adapter_name]['object'].load())
adapter = (
context[adapter_name]
if adapter_name in context
else type_plugins[adapter_name]["object"].load()
)
except KeyError:
raise DataJointError(
"Attribute adapter '{adapter_name}' is not defined.".format(adapter_name=adapter_name))
"Attribute adapter '{adapter_name}' is not defined.".format(
adapter_name=adapter_name
)
)
if not isinstance(adapter, AttributeAdapter):
raise DataJointError(
"Attribute adapter '{adapter_name}' must be an instance of datajoint.AttributeAdapter".format(
adapter_name=adapter_name))
if not isinstance(adapter.attribute_type, str) or not re.match(r'^\w', adapter.attribute_type):
raise DataJointError("Invalid attribute type {type} in attribute adapter '{adapter_name}'".format(
type=adapter.attribute_type, adapter_name=adapter_name))
adapter_name=adapter_name
)
)
if not isinstance(adapter.attribute_type, str) or not re.match(
r"^\w", adapter.attribute_type
):
raise DataJointError(
"Invalid attribute type {type} in attribute adapter '{adapter_name}'".format(
type=adapter.attribute_type, adapter_name=adapter_name
)
)
return adapter
Loading