datamol-io / medchem

Molecular filtering for drug discovery.
https://medchem-docs.datamol.io
Apache License 2.0
53 stars 6 forks source link

Error loading RuleFilters.list_available_rules #19

Closed ec1340 closed 9 months ago

ec1340 commented 9 months ago

Hello!

Great package and very excited to use it.

However I'm running into an issue following the tutorial Filtering with rules. These two lines raise an error.

Code to reproduce

import medchem as mc

mc.rules.RuleFilters.list_available_rules()

raises TypeError: expected str, bytes or os.PathLike object, not NoneType

Configuration:


Full error message


TypeError                                 Traceback (most recent call last)
Cell In[48], line 1
----> 1 mc.rules.RuleFilters.list_available_rules()

File ~/opt/anaconda3/envs/abenv_01/lib/python3.9/site-packages/medchem/rules/_rule_filter.py:189, in RuleFilters.list_available_rules(*query)
    185 @staticmethod
    186 @functools.lru_cache(maxsize=32)
    187 def list_available_rules(*query: str):
    188     """List all the available rules and they properties"""
--> 189     df = pd.read_csv(loader.get_data_path("medchem_rule_list.csv"))
    190     if len(query) > 0:
    191         query_str = "|".join(query)

File ~/opt/anaconda3/envs/abenv_01/lib/python3.9/site-packages/medchem/utils/loader.py:17, in get_data_path(filename, module)
     13 @functools.lru_cache(maxsize=10)
     14 def get_data_path(filename: str, module: str = "medchem.data"):
     15     """Return the filepath of an internal data file."""
---> 17     path = importlib.resources.files(module).joinpath(filename)
     18     return str(path)

File ~/opt/anaconda3/envs/abenv_01/lib/python3.9/importlib/resources.py:147, in files(package)
    143 def files(package: Package) -> resources_abc.Traversable:
    144     """
    145     Get a Traversable resource from a package
    146     """
--> 147     return _common.from_package(_get_package(package))

File ~/opt/anaconda3/envs/abenv_01/lib/python3.9/importlib/_common.py:14, in from_package(package)
      9 def from_package(package):
     10     """
     11     Return a Traversable object for the given package.
     12 
     13     """
---> 14     return fallback_resources(package.__spec__)

File ~/opt/anaconda3/envs/abenv_01/lib/python3.9/importlib/_common.py:18, in fallback_resources(spec)
     17 def fallback_resources(spec):
---> 18     package_directory = pathlib.Path(spec.origin).parent
     19     try:
     20         archive_path = spec.loader.archive

File ~/opt/anaconda3/envs/abenv_01/lib/python3.9/pathlib.py:1082, in Path.__new__(cls, *args, **kwargs)
   1080 if cls is Path:
   1081     cls = WindowsPath if os.name == 'nt' else PosixPath
-> 1082 self = cls._from_parts(args, init=False)
   1083 if not self._flavour.is_supported:
   1084     raise NotImplementedError("cannot instantiate %r on your system"
   1085                               % (cls.__name__,))

File ~/opt/anaconda3/envs/abenv_01/lib/python3.9/pathlib.py:707, in PurePath._from_parts(cls, args, init)
    702 @classmethod
    703 def _from_parts(cls, args, init=True):
    704     # We need to call _parse_args on the instance, so as to get the
    705     # right flavour.
    706     self = object.__new__(cls)
--> 707     drv, root, parts = self._parse_args(args)
    708     self._drv = drv
    709     self._root = root

File ~/opt/anaconda3/envs/abenv_01/lib/python3.9/pathlib.py:691, in PurePath._parse_args(cls, args)
    689     parts += a._parts
    690 else:
--> 691     a = os.fspath(a)
    692     if isinstance(a, str):
    693         # Force-cast str subclasses to str (issue #21127)
    694         parts.append(str(a))

TypeError: expected str, bytes or os.PathLike object, not NoneType
maclandrol commented 9 months ago

Hi @ec1340, I am unable to reproduce. It seems like the data repository is empty in your installation. Did you install using pip , conda or a local installation from sources ?

What does the content of this folder looks like ?

from medchem import data
print(str(data.__path__[0]))
os.listdir(str(data.__path__[0]))

Or in your case, maybe just:

ls ~/opt/anaconda3/envs/abenv_01/lib/python3.9/site-packages/medchem/data/
ec1340 commented 9 months ago

I used pip to install the package

running the shared python code returns

/Users/ec_lab/opt/anaconda3/envs/abenv_03/lib/python3.9/site-packages/medchem/data

`['grammar.lark',
 'nibr.csv',
 'medchem_rule_list.csv',
 'complexity',
 'graph.csv',
 'queries',
 'bredt.csv',
 'common_alerts_collection.csv',
 'smarts_bank.csv',
 'charge_assigner',
 'chemical_groups.csv']
maclandrol commented 9 months ago

Oh, that's strange the required file is there ("medchem_rule_list.csv"), so it's strange that it's returning None.

Do you know if the following code returns the file ?


from medchem.utils import loader
loader.get_data_path("medchem_rule_list.csv")

I will try to replicate with your exact version of python.

ec1340 commented 9 months ago

thank you!

same issue arises

>>> from medchem.utils import loader
>>> loader.get_data_path("medchem_rule_list.csv")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/ec_lab/opt/anaconda3/envs/abenv_03/lib/python3.9/site-packages/medchem/utils/loader.py", line 17, in get_data_path
    path = importlib.resources.files(module).joinpath(filename)
  File "/Users/ec_lab/opt/anaconda3/envs/abenv_03/lib/python3.9/importlib/resources.py", line 147, in files
    return _common.from_package(_get_package(package))
  File "/Users/ec_lab/opt/anaconda3/envs/abenv_03/lib/python3.9/importlib/_common.py", line 14, in from_package
    return fallback_resources(package.__spec__)
  File "/Users/ec_lab/opt/anaconda3/envs/abenv_03/lib/python3.9/importlib/_common.py", line 18, in fallback_resources
    package_directory = pathlib.Path(spec.origin).parent
  File "/Users/ec_lab/opt/anaconda3/envs/abenv_03/lib/python3.9/pathlib.py", line 1082, in __new__
    self = cls._from_parts(args, init=False)
  File "/Users/ec_lab/opt/anaconda3/envs/abenv_03/lib/python3.9/pathlib.py", line 707, in _from_parts
    drv, root, parts = self._parse_args(args)
  File "/Users/ec_lab/opt/anaconda3/envs/abenv_03/lib/python3.9/pathlib.py", line 691, in _parse_args
    a = os.fspath(a)
TypeError: expected str, bytes or os.PathLike object, not NoneType
ec1340 commented 9 months ago

just checked on my end and it works for me with python=3.10

maclandrol commented 9 months ago

Yes, it's importlib.resources. On python 3.9 it does not recognize module without __init__.py for data serving (which has been adopted in python since 3.3).

Using python >=3.10 should work.

I am also pushing a fix to cover that edge case.