How to Find All Modules and Classes Within a Module, Recursively

How do you find all modules and classes within a module, recursively?

class Module
def all_the_modules
[self] + constants.map {|const| const_get(const) }
.select {|const| const.is_a? Module }
.flat_map {|const| const.all_the_modules }
end
end

A.all_the_modules
# => [A, A::Aa, A::Aa::B]

This code will break if you do have circular namespaces, aka
A::Aa::B.const_set(:A, A).

How can I get a list of all classes within current module in Python?

Try this:

import sys
current_module = sys.modules[__name__]

In your context:

import sys, inspect
def print_classes():
for name, obj in inspect.getmembers(sys.modules[__name__]):
if inspect.isclass(obj):
print(obj)

And even better:

clsmembers = inspect.getmembers(sys.modules[__name__], inspect.isclass)

Because inspect.getmembers() takes a predicate.

How to import recursively all classes in a module?

Solved by adding this to __init__.py. May not be the best approach for most situations, but it is good enough for my use case.

from pathlib import Path

# Include all classes when 'from mypkg import *' is called.
fs = [f for f in Path('mypkg').rglob('*.py') if not f.name.startswith('_')]

for f in [str(f).replace('/', '.')[:-3] for f in fs]:
statement = f'from {f} import *'
exec(statement)

Find classes available in a Module

Classes are accessed through constants. Classes defined within a module are listed as constants in that module. So you just need to choose the constants that refer to classes.

MyModule.constants.select {|c| MyModule.const_get(c).is_a? Class}

Trying to find all classes that include a module

[Note: @engineersmnky illustrates a way to do this using flat_map eliminating the need for the matching_classes parameter. I found it more difficult to understand, but it's a perfectly sound use of flat_map and a worthy solution. The code is posted at https://repl.it/@engineersmnky/IllinformedMountainousAnkole ]

The following code uses recursion to descend the inverted tree of modules. The result (printed at the very end) is correct, and includes classes in two modules. (I've coded a minimal module and class hierarchy to use as an example.)

#!/usr/bin/env ruby

module ParentModule
module OtherModule; end
class ParentClassYes; include OtherModule; end
class ParentClassNo; end

module ChildModule
class ChildClassYes; include OtherModule; end
class ChildClassNo; end
end
end

def classes_for_module_tree(the_module, matching_classes = [])
the_module.constants.each_with_object(matching_classes) \
do |const, matching_classes|
value = the_module.const_get(const)
if value.is_a?(Class)
if value.included_modules.include?(ParentModule::OtherModule)
matching_classes << value
end
elsif value.is_a?(Module)
# Here is where we call this method recursively. We suspend collecting
# matches for this module, call the method to process the newly found
# (sub)module, then use the array returned by that invocation to resume
# processing this module.
matching_classes = classes_for_module_tree(value, matching_classes)
end
end
matching_classes
end

p classes_for_module_tree(ParentModule)
# prints: [ParentModule::ParentClassYes, ParentModule::ChildModule::ChildClassYes]

Get all classes defined in module ruby

Here is one way

module A
class Klass
end
X = 10
module B;end
end

# Just to list the class(s) defined inside A
A.constants.select { |k| A.const_get(k).instance_of? Class } # => [:Klass]

Nice post to do the same in recursively.

In Python, how do I get the list of classes defined within a particular file?

You can get both:

import importlib, inspect
for name, cls in inspect.getmembers(importlib.import_module("myfile"), inspect.isclass):

you may additionally want to check:

if cls.__module__ == 'myfile'

How can I discover classes in a specific package in python?

Scanning modules isn't good idea. If you need class registry you should look at metaclasses or use existing solutions like zope.interface.
Simple solution through metaclasses may look like that:

from functools import reduce
class DerivationRegistry(type):
def __init__(cls,name,bases,cls_dict):
type.__init__(cls,name,bases,cls_dict)
cls._subclasses = set()
for base in bases:
if isinstance(base,DerivationRegistry):
base._subclasses.add(cls)

def getSubclasses(cls):
return reduce( set.union,
( succ.getSubclasses() for succ in cls._subclasses if isinstance(succ,DerivationRegistry)),
cls._subclasses)

class Base(object):
__metaclass__ = DerivationRegistry

class Cls1(object):
pass

class Cls2(Base):
pass

class Cls3(Cls2,Cls1):
pass

class Cls4(Cls3):
pass

print(Base.getSubclasses())


Related Topics



Leave a reply



Submit