datajoint-python icon indicating copy to clipboard operation
datajoint-python copied to clipboard

Schema nested in class does not find datajoint elements table

Open chrisroat opened this issue 3 years ago • 3 comments
trafficstars

Bug Report

Description

When schema tables are nested within a class, datajoint cannot find an elements table. The problem seems to be related to a change in context, but even if I nest the activate call or schema assignment, it is not found.

Reproducibility

Include:

  • OS: MacOS 12.1
  • Python Version: 3.9.9
  • MySQL Version: 5.7
  • MySQL Deployment Strategy: local-docker
  • DataJoint Version: 0.3.12
  • Minimum number of steps to reliably reproduce the issue
import datajoint as dj
from element_lab import lab
from element_lab.lab import User

lab.activate('acquisition')
schema = dj.schema('acquisition')

class Foo:    
    @schema
    class Acquisition(dj.Manual):
        definition = """
        -> User
        acquisition: varchar(32)
        """

def test_elements():
    User.insert1({"user": "abc", "user_email": "[email protected]"})
    Foo.Acquisition.insert1({"user": "abc", "acquisition": "mno"})
  • Complete error stack as a result of evaluating the above steps
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> traceback >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
test_elements.py:13: in <module>
    class Foo:
test_elements.py:15: in Foo
    class Acquisition(dj.Manual):
venv/lib/python3.9/site-packages/datajoint/schemas.py:147: in __call__
    self._decorate_master(cls, context)
venv/lib/python3.9/site-packages/datajoint/schemas.py:157: in _decorate_master
    self._decorate_table(cls, context=dict(context, self=cls, **{cls.__name__: cls}))
venv/lib/python3.9/site-packages/datajoint/schemas.py:188: in _decorate_table
    instance.declare(context)
venv/lib/python3.9/site-packages/datajoint/table.py:79: in declare
    sql, external_stores = declare(self.full_table_name, self.definition, context)
venv/lib/python3.9/site-packages/datajoint/declare.py:281: in declare
    table_comment, primary_key, attribute_sql, foreign_key_sql, index_sql, external_stores = prepare_declare(
venv/lib/python3.9/site-packages/datajoint/declare.py:248: in prepare_declare
    compile_foreign_key(line, context, attributes,
venv/lib/python3.9/site-packages/datajoint/declare.py:143: in compile_foreign_key
    raise DataJointError('Foreign key reference %s could not be resolved' % result.ref_table)
E   datajoint.errors.DataJointError: Foreign key reference User could not be resolved

Expected Behavior

The schema should be created without errors.

chrisroat avatar Jan 07 '22 22:01 chrisroat

If no context is indicated, the schema object uses the local context where it's invoked to look for the table classes. This may get into some of Python's namespace handling quirks. But just as a test, could you try passing the locals() contents explicitly?

schema = dj.schema('acquisition', context=locals())

dimitri-yatsenko avatar Jan 10 '22 03:01 dimitri-yatsenko

Thanks for the suggestion. I tried that, and then also moving schema inside the class. Neither seems to work.

chrisroat avatar Jan 10 '22 05:01 chrisroat

We have never considered declaring table classes inside other classes. Here is the line where this evaluation takes place. I don't see why it would not work but Python has a few quirks about how it namespaces are handled with classes.

dimitri-yatsenko avatar Jan 10 '22 11:01 dimitri-yatsenko