labdata 0.1.23__tar.gz → 0.1.25__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.
- {labdata-0.1.23 → labdata-0.1.25}/PKG-INFO +1 -1
- {labdata-0.1.23 → labdata-0.1.25}/labdata/__init__.py +2 -1
- {labdata-0.1.23 → labdata-0.1.25}/labdata/accounts.py +57 -3
- {labdata-0.1.23 → labdata-0.1.25}/labdata/cli.py +619 -20
- {labdata-0.1.23 → labdata-0.1.25}/labdata/compute/__init__.py +2 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/compute/ec2.py +4 -4
- {labdata-0.1.23 → labdata-0.1.25}/labdata/compute/ephys.py +276 -131
- {labdata-0.1.23 → labdata-0.1.25}/labdata/compute/pcluster.py +8 -0
- labdata-0.1.25/labdata/compute/schedulers.py +1029 -0
- labdata-0.1.25/labdata/compute/spikeinterface.py +937 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/compute/utils.py +37 -19
- {labdata-0.1.23 → labdata-0.1.25}/labdata/copy.py +29 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/dashboard/activity.py +1 -1
- labdata-0.1.25/labdata/dashboard/ephys/__init__.py +1 -0
- {labdata-0.1.23/labdata/dashboard → labdata-0.1.25/labdata/dashboard/ephys}/drift.py +12 -16
- {labdata-0.1.23/labdata/dashboard → labdata-0.1.25/labdata/dashboard/ephys}/sorting.py +125 -56
- {labdata-0.1.23 → labdata-0.1.25}/labdata/dashboard/index.py +2 -2
- labdata-0.1.25/labdata/export/__init__.py +15 -0
- labdata-0.1.25/labdata/export/database.py +198 -0
- labdata-0.1.25/labdata/export/docker/Dockerfile.in +37 -0
- labdata-0.1.25/labdata/export/docker/entrypoint.sh +75 -0
- labdata-0.1.25/labdata/export/docker/load_database.sh +25 -0
- labdata-0.1.25/labdata/export/docker/mysql.cnf +4 -0
- labdata-0.1.25/labdata/export/docker.py +319 -0
- labdata-0.1.25/labdata/export/selection.py +1034 -0
- labdata-0.1.25/labdata/export/share.py +197 -0
- labdata-0.1.25/labdata/export/users.py +160 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/rules/ephys.py +270 -15
- {labdata-0.1.23 → labdata-0.1.25}/labdata/s3.py +89 -15
- {labdata-0.1.23 → labdata-0.1.25}/labdata/schema/ephys.py +255 -147
- {labdata-0.1.23 → labdata-0.1.25}/labdata/schema/general.py +4 -3
- {labdata-0.1.23 → labdata-0.1.25}/labdata/utils.py +69 -8
- {labdata-0.1.23 → labdata-0.1.25}/labdata/widgets.py +3 -1
- {labdata-0.1.23 → labdata-0.1.25}/labdata.egg-info/PKG-INFO +1 -1
- {labdata-0.1.23 → labdata-0.1.25}/labdata.egg-info/SOURCES.txt +16 -5
- {labdata-0.1.23 → labdata-0.1.25}/pyproject.toml +4 -1
- labdata-0.1.23/labdata/compute/schedulers.py +0 -545
- labdata-0.1.23/labdata/export.py +0 -381
- {labdata-0.1.23 → labdata-0.1.25}/LICENSE +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/README.md +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/compute/caiman.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/compute/pose.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/compute/singularity.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/compute/submission.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/compute/suite2p.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/dashboard/__init__.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/dashboard/admin.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/dashboard/ai_utils.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/dashboard/compute.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/dashboard/console.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/dashboard/decisiontask.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/dashboard/docstrings.py +0 -0
- {labdata-0.1.23/labdata/dashboard → labdata-0.1.25/labdata/dashboard/ephys}/raster.py +0 -0
- /labdata-0.1.23/labdata/dashboard/ephys.py → /labdata-0.1.25/labdata/dashboard/ephys/recordings.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/dashboard/events.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/dashboard/imaging.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/dashboard/launch.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/dashboard/local_files.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/dashboard/notes.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/dashboard/procedures.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/dashboard/reads.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/dashboard/schema_graph.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/dashboard/segmentation.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/dashboard/sync.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/dashboard/upload.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/dashboard/upload_worker.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/dashboard/video.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/dashboard/writes.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/ephys_io.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/ephys_signal.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/rules/__init__.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/rules/imaging.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/rules/utils.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/schema/__init__.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/schema/histology.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/schema/onephoton.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/schema/procedures.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/schema/tasks.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/schema/twophoton.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/schema/utils.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/schema/video.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata/stacks.py +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata.egg-info/dependency_links.txt +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata.egg-info/entry_points.txt +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata.egg-info/requires.txt +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/labdata.egg-info/top_level.txt +0 -0
- {labdata-0.1.23 → labdata-0.1.25}/setup.cfg +0 -0
|
@@ -78,13 +78,22 @@ def database_grants(name, projects, database_name='lab_data', sandbox=False):
|
|
|
78
78
|
return [g.replace('%', '%%') for g in grants]
|
|
79
79
|
|
|
80
80
|
|
|
81
|
+
def split_host(host, port=3306):
|
|
82
|
+
'''Return ``(address, port)`` of a database host written ``address`` or ``address:port``;
|
|
83
|
+
``port`` is used when the host has none.'''
|
|
84
|
+
address, _, number = str(host).strip().rpartition(':')
|
|
85
|
+
if address and number.isdigit():
|
|
86
|
+
return address, int(number)
|
|
87
|
+
return str(host).strip(), int(port)
|
|
88
|
+
|
|
89
|
+
|
|
81
90
|
def ask_database_admin(host, default_user=None):
|
|
82
91
|
'''Ask for the database admin login and return a pymysql connection.
|
|
83
92
|
|
|
84
93
|
Parameters
|
|
85
94
|
----------
|
|
86
95
|
host : str
|
|
87
|
-
Database address
|
|
96
|
+
Database address, ``address`` or ``address:port``.
|
|
88
97
|
default_user : str, optional
|
|
89
98
|
User offered as default.
|
|
90
99
|
|
|
@@ -96,7 +105,8 @@ def ask_database_admin(host, default_user=None):
|
|
|
96
105
|
print(f'Database admin login for {host} (used for this command only, not saved).')
|
|
97
106
|
user = input(f' Admin user [{default_user or ""}]: ').strip() or default_user
|
|
98
107
|
password = getpass(' Admin password: ')
|
|
99
|
-
|
|
108
|
+
address, port = split_host(host)
|
|
109
|
+
return pymysql.connect(host=address, port=port, user=user, password=password, autocommit=True)
|
|
100
110
|
|
|
101
111
|
|
|
102
112
|
def database_user_exists(conn, name):
|
|
@@ -147,6 +157,49 @@ def database_user_grants(conn, name):
|
|
|
147
157
|
return [r[0] for r in _rows(conn, f"SHOW GRANTS FOR '{name}'@'%%'", ())]
|
|
148
158
|
|
|
149
159
|
|
|
160
|
+
def _grant_pattern(schema):
|
|
161
|
+
'''Return the regular expression of a schema name of a GRANT, where ``_`` and ``%`` are
|
|
162
|
+
wildcards unless escaped with ``\\``.'''
|
|
163
|
+
out, i = '', 0
|
|
164
|
+
while i < len(schema):
|
|
165
|
+
c = schema[i]
|
|
166
|
+
if c == '\\' and i + 1 < len(schema):
|
|
167
|
+
out += re.escape(schema[i + 1])
|
|
168
|
+
i += 2
|
|
169
|
+
continue
|
|
170
|
+
out += '.*' if c == '%' else '.' if c == '_' else re.escape(c)
|
|
171
|
+
i += 1
|
|
172
|
+
return re.compile(out)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def database_access(conn, databases):
|
|
176
|
+
'''Return ``{user: [databases]}`` for the database users with privileges other than
|
|
177
|
+
REFERENCES on ``databases``; ``'*'`` stands for a grant on every database. Users whose
|
|
178
|
+
grants can not be read are left out.'''
|
|
179
|
+
access = dict()
|
|
180
|
+
for user in list_database_users(conn):
|
|
181
|
+
try:
|
|
182
|
+
grants = database_user_grants(conn, user)
|
|
183
|
+
except Exception:
|
|
184
|
+
continue
|
|
185
|
+
for grant in grants:
|
|
186
|
+
m = re.match(r'GRANT (.+?) ON (\S+?)\.\S+ TO ', grant)
|
|
187
|
+
if not m:
|
|
188
|
+
continue
|
|
189
|
+
privileges = set(p.strip().upper() for p in m.group(1).split(','))
|
|
190
|
+
if privileges <= {'USAGE', 'REFERENCES'}:
|
|
191
|
+
continue
|
|
192
|
+
schema = m.group(2).strip('`')
|
|
193
|
+
if schema == '*':
|
|
194
|
+
access.setdefault(user, set()).add('*')
|
|
195
|
+
continue
|
|
196
|
+
pattern = _grant_pattern(schema)
|
|
197
|
+
for database in databases:
|
|
198
|
+
if pattern.fullmatch(database):
|
|
199
|
+
access.setdefault(user, set()).add(database)
|
|
200
|
+
return {user: sorted(names) for user, names in sorted(access.items())}
|
|
201
|
+
|
|
202
|
+
|
|
150
203
|
def create_s3_user(session, name, groups=(), policies=(), like=None):
|
|
151
204
|
'''Create the IAM user ``name`` with one access key, and the permissions of ``groups``, ``policies`` or user ``like``.
|
|
152
205
|
|
|
@@ -836,7 +889,8 @@ def grant_database_project(conn, name, project, database_name='lab_data'):
|
|
|
836
889
|
def connect_database_admin(host, user, password):
|
|
837
890
|
'''Return a pymysql connection for ``user``, after checking it may create users and grant permissions.'''
|
|
838
891
|
import pymysql
|
|
839
|
-
|
|
892
|
+
address, port = split_host(host)
|
|
893
|
+
conn = pymysql.connect(host=address, port=port, user=user, password=password, autocommit=True)
|
|
840
894
|
grants = ' '.join(r[0] for r in _rows(conn, 'SHOW GRANTS', ())).upper()
|
|
841
895
|
if 'CREATE USER' not in grants and 'ALL PRIVILEGES ON *.*' not in grants:
|
|
842
896
|
conn.close()
|