Welcome to Cadabra Q&A, where you can ask questions and receive answers from other members of the community.
+1 vote

When I import cdb.core.component using

import cdb.core.component as comp

I get the following error:

  File "/Users/hl/Library/Preferences/cadabra_packages/cdb/core/component.py", line 17, in <module>
    from cdb.core._component import get_component
ModuleNotFoundError: No module named 'cdb.core._component'

When I go to the folder containing the file "component.py", I saw that there are 3 functions: "get_component", "remove_zero_components(ex), components_to_subrule(ex)" (this is expected as these are the 3 functions under the 'core.component' module), but the function "get_component" is grayed out (commented out). The code for this also has a strange import:

from cdb.core._component import get_component

which refers to "cdb.core._component" that cannot be found.

I recently updated Cadabra to the latest version and this is the first time I am using 'get_component' so I don't know what is wrong, but the fact that the entire 'get_component' function is grayed out is strange to me. I wish I could attach a screenshot to show this, but I can't find the option to attach an image (only the URL for the image), so I copied and pasted the code from "component.py" here:

import cadabra2
import imp
from cadabra2 import *
from cadabra2_defaults import *
__cdbkernel__ = cadabra2.__cdbkernel__
temp__all__ = dir() + ['temp__all__']

def display(ex):
   pass

from cdb.utils.node import n_children
from cdb.core.manip import get_lhs, get_rhs
from cdb.utils.indices import get_free_indices
from cdb.core._component import get_component

#def get_component(ex, components):
#   """Gets a particular component of an expression"""
#   # Work on a copy of ex
#   ex = ex.top().ex()
#
#   # Replace all free indices with the components
#   free_indices = get_free_indices(ex.top())
#   if components.top().name != r"\comma":
#       tmp = Ex(r'\comma')
#       tmp.top().append_child(components.top())
#       components = tmp
#   assert len(free_indices) == n_children(components.top()), f"Expression contains {len(free_indices)} free indices, but {n_children(components.top())} components supplied"
#   for index, component in zip(free_indices, components.top().children()):
#       node = next(ex[index.top().name], None)
#       changed = True
#       while changed:
#           for node in ex[index.top().name]:
#               if node.parent_rel == parent_rel_t.super or node.parent_rel == parent_rel_t.sub:
#                   pr = node.parent_rel
#                   node.replace(component.ex())
#                   node.parent_rel = pr
#                   break
#           else:
#               changed = False
#
#   # Replace all component nodes with the particular component we are looking for
#   for node in ex[r'\components']:
#       # Sift through \equals nodes finding the one with the right components
#       for candidate in node[r'\equals']:
#           arg = get_lhs(candidate)
#           if arg == components:
#               node = node.replace(get_rhs(candidate))
#               break
#       else:
#           node = node.replace($0$)
#
#   # The components paramater needs to have a head '\comma' node
#   # so let's quickly make sure that's true.
#   if components.head() != r'\comma':
#       bit = $@(components)$
#       components.top().name = r'\comma'
#       components.top().append_child(bit)
#
#   return ex

Thank you in advance for any help.

in Bug reports by (210 points)

Hi HL.

I'm using Version 2.4.3 (build 2899.366cb44e13 dated 2023-04-10) running on a Manjaro Linux machine, and I'm unable to reproduce your issue. Could you provide more information about the OS and cadabra version you are using?

Cheers.

PD: The function is not defined in the file you posted, but in the _component.cc.

Hi doxdrum, Thank you for your comment - I'm using MacOS Ventura (13.4.1), I'm not sure about my Cadabra version - I regularly do a "brew update/upgrade" to update all packages to the latest version, so I think my Cadabra should be 2.4.x. I run my Cadabra code in both Cadabra2-gtk and on Jupyter notebook, and I encoutered the error described in my post on both platforms. I found a way to circumvent this problem and make "import cdb.core.component" work by modifying the file "component.py": 1/Uncomment the grayed out "get_component" function, and 2/Comment the line "from cdb.core._component import get_component". After this, the code works and I can call "get_component" which yields correct results. But I don't know if this really fixes the problem.

1 Answer

+1 vote

Sorry for the wait. Just to explain the logic: this function get_component used to be implemented in Python (the commented-out bit you noticed), but was at some point rewritten in C++ for a number of reasons. Since then, the cdb.core.component Python module just imports cdb.core._component (with underscore). This is a separate C++ library, which should have been installed with the build, but either wasn't, or is not in a path where Python looks for it.

I cannot reproduce it on my macOS machine either, but will do some digging on a clean machine to see what might be the problem (Python search paths are notoriously tricky to get right across multiple platforms).

by (83.1k points)
...