diff --git a/CHANGELOG.md b/CHANGELOG.md index 15e4e9446..e508e1845 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ ## Release notes +### 0.14.0 -- TBA +* Bugfix - Activating a schema requires all tables to exist even if `create_tables=False` PR [#1058](https://github.com/datajoint/datajoint-python/pull/1058) + ### 0.13.8 -- Sep 21, 2022 * Add - New documentation structure based on markdown PR [#1052](https://github.com/datajoint/datajoint-python/pull/1052) * Bugfix - Fix queries with backslashes ([#999](https://github.com/datajoint/datajoint-python/issues/999)) PR [#1052](https://github.com/datajoint/datajoint-python/pull/1052) diff --git a/datajoint/schemas.py b/datajoint/schemas.py index 0e35f10ac..b167785ae 100644 --- a/datajoint/schemas.py +++ b/datajoint/schemas.py @@ -47,7 +47,7 @@ def __init__( connection=None, create_schema=True, create_tables=True, - add_objects=None + add_objects=None, ): """ Associate database schema `schema_name`. If the schema does not exist, attempt to @@ -87,7 +87,7 @@ def activate( connection=None, create_schema=None, create_tables=None, - add_objects=None + add_objects=None, ): """ Associate database schema `schema_name`. If the schema does not exist, attempt to @@ -222,9 +222,7 @@ def _decorate_table(self, table_class, context, assert_declared=False): # instantiate the class, declare the table if not already instance = table_class() is_declared = instance.is_declared - if not is_declared: - if not self.create_tables or assert_declared: - raise DataJointError("Table `%s` not declared" % instance.table_name) + if not is_declared and not assert_declared and self.create_tables: instance.declare(context) self.connection.dependencies.clear() is_declared = is_declared or instance.is_declared @@ -506,7 +504,7 @@ def __init__( create_schema=False, create_tables=False, connection=None, - add_objects=None + add_objects=None, ): """ Creates a python module with the given name from the name of a schema on the server and diff --git a/datajoint/version.py b/datajoint/version.py index 2c25e981a..697137322 100644 --- a/datajoint/version.py +++ b/datajoint/version.py @@ -1,3 +1,3 @@ -__version__ = "0.13.8" +__version__ = "0.14.0" assert len(__version__) <= 10 # The log table limits version to the 10 characters diff --git a/local-docker-compose.yml b/local-docker-compose.yml index 8bafa7cc5..f61f9e5d4 100644 --- a/local-docker-compose.yml +++ b/local-docker-compose.yml @@ -95,6 +95,7 @@ services: ## Interactive Jupyter Notebook environment jupyter notebook & ## Remote debugger + set +e while true do python -m ptvsd --host 0.0.0.0 --port 5678 --wait . diff --git a/tests/schema_privileges.py b/tests/schema_privileges.py new file mode 100644 index 000000000..8b39e4aa1 --- /dev/null +++ b/tests/schema_privileges.py @@ -0,0 +1,35 @@ +import datajoint as dj + +schema = dj.Schema() + + +@schema +class Parent(dj.Lookup): + definition = """ + id: int + """ + contents = [(1,)] + + +@schema +class Child(dj.Computed): + definition = """ + -> Parent + """ + + def make(self, key): + self.insert1(key) + + +@schema +class NoAccess(dj.Lookup): + definition = """ + string: varchar(10) + """ + + +@schema +class NoAccessAgain(dj.Manual): + definition = """ + -> NoAccess + """ diff --git a/tests/test_blob.py b/tests/test_blob.py index 91b2ce131..9cf5a30a2 100644 --- a/tests/test_blob.py +++ b/tests/test_blob.py @@ -230,7 +230,7 @@ def test_insert_longblob(): def test_datetime_serialization_speed(): # If this fails that means for some reason deserializing/serializing - # np arrays of np.datetime64 types is now slower than regular arrays of datetime64 + # np arrays of np.datetime64 types is now slower than regular arrays of datetime optimized_exe_time = timeit.timeit( setup="myarr=pack(np.array([np.datetime64('2022-10-13 03:03:13') for _ in range(0, 10000)]))", @@ -247,4 +247,4 @@ def test_datetime_serialization_speed(): ) print(f"python time {baseline_exe_time}") - assert optimized_exe_time * 1000 < baseline_exe_time + assert optimized_exe_time * 900 < baseline_exe_time diff --git a/tests/test_privileges.py b/tests/test_privileges.py index 9332a56b7..f32a1103f 100644 --- a/tests/test_privileges.py +++ b/tests/test_privileges.py @@ -1,6 +1,8 @@ -from nose.tools import assert_true, raises +import importlib import datajoint as dj -from . import schema, CONN_INFO +from . import schema, CONN_INFO_ROOT, PREFIX +from . import schema_privileges as pipeline +from nose.tools import assert_true, raises namespace = locals() @@ -10,7 +12,7 @@ class TestUnprivileged: def setup_class(cls): """A connection with only SELECT privilege to djtest schemas""" cls.connection = dj.conn( - host=CONN_INFO["host"], user="djview", password="djview", reset=True + host=CONN_INFO_ROOT["host"], user="djview", password="djview", reset=True ) @raises(dj.DataJointError) @@ -46,3 +48,62 @@ class Try(dj.Manual): """ Try().insert1((1, 1.5)) + + +class TestSubset: + USER = "djsubset" + + @classmethod + def setup_class(cls): + conn = dj.conn( + host=CONN_INFO_ROOT["host"], + user=CONN_INFO_ROOT["user"], + password=CONN_INFO_ROOT["password"], + reset=True, + ) + pipeline.schema.activate(f"{PREFIX}_pipeline") + conn.query( + f""" + CREATE USER IF NOT EXISTS '{cls.USER}'@'%%' + IDENTIFIED BY '{cls.USER}' + """ + ) + conn.query( + f""" + GRANT SELECT, INSERT, UPDATE, DELETE + ON `{PREFIX}_pipeline`.`#parent` + TO '{cls.USER}'@'%%' + """ + ) + conn.query( + f""" + GRANT SELECT, INSERT, UPDATE, DELETE + ON `{PREFIX}_pipeline`.`__child` + TO '{cls.USER}'@'%%' + """ + ) + cls.connection = dj.conn( + host=CONN_INFO_ROOT["host"], + user=cls.USER, + password=cls.USER, + reset=True, + ) + + @classmethod + def teardown_class(cls): + conn = dj.conn( + host=CONN_INFO_ROOT["host"], + user=CONN_INFO_ROOT["user"], + password=CONN_INFO_ROOT["password"], + reset=True, + ) + conn.query(f"DROP USER {cls.USER}") + conn.query(f"DROP DATABASE {PREFIX}_pipeline") + + def test_populate_activate(self): + importlib.reload(pipeline) + pipeline.schema.activate( + f"{PREFIX}_pipeline", create_schema=True, create_tables=False + ) + pipeline.Child.populate() + assert pipeline.Child.progress(display=False)[0] == 0