How to access parent/sibling module methods
Constants are looked up first in the lexically enclosing module(s) and then up the inheritance chain.
module Foo
module Bar
module Baz
class Qux
def self.qux_method
Baz.baz_method
end
end
def self.baz_method
end
end
end
end
This will work, because the constant Baz
will be first looked up in the lexically enclosing module (class) Qux
, where it isn't found. The lookup continues in the lexically enclosing module Baz
, where it also isn't found. Therefore, it will next be looked up in the lexically enclosing module Bar
, where it is found and the search stops.Note: you write in your title:
This is wrong. These modules are neither parents nor siblings. There is no inheritance here. There is, in fact, no relationship between the modules at all. There is only a relationship between the constants and the modules: constants belong to modules.Ruby, Access parent/sibling module methods
The module declarations are lexically nested, but the modules themselves aren't.
Ruby: get a sibling module
It's simpler than you thought
module ParentModule
module Foo
def self.get_bar
Bar
end
end
end
The ::
you tried with, it instructs ruby to look this name up in the top-level scope. If you omit it, ruby will first look in the current scope, then its parent, then its parent, and all the way to the top-level.So, ParentModule::Foo::Bar
will not be found, but ParentModule::Bar
will be.
Sibling package imports
Seven years after
Since I wrote the answer below, modifying sys.path
is still a quick-and-dirty trick that works well for private scripts, but there has been several improvements
- Installing the package (in a virtualenv or not) will give you what you want, though I would suggest using pip to do it rather than using setuptools directly (and using
setup.cfg
to store the metadata) - Using the
-m
flag and running as a package works too (but will turn out a bit awkward if you want to convert your working directory into an installable package). - For the tests, specifically, pytest is able to find the api package in this situation and takes care of the
sys.path
hacks for you
pip -e
is probably your best bet, even if it is not perfect yet.Old answer
As already stated elsewhere, the awful truth is that you have to do ugly hacks to allow imports from siblings modules or parents package from a __main__
module. The issue is detailed in PEP 366. PEP 3122 attempted to handle imports in a more rational way but Guido has rejected it one the account of
(here)The only use case seems to be running scripts that happen
to be living inside a module's directory, which I've always seen as an
antipattern.
Though, I use this pattern on a regular basis with
# Ugly hack to allow absolute import from the root folder
# whatever its name is. Please forgive the heresy.
if __name__ == "__main__" and __package__ is None:
from sys import path
from os.path import dirname as dir
path.append(dir(path[0]))
__package__ = "examples"
import api
Here path[0]
is your running script's parent folder and dir(path[0])
your top level folder.I have still not been able to use relative imports with this, though, but it does allow absolute imports from the top level (in your example api
's parent folder).
Import from sibling directory
You really should be using packages. Then MainDir is placed at a point in the file system on sys.path (e.g. .../site-packages), then you can say in ClassB:
from MainDir.Dir.DirA import ClassA # which is actually a module
You just have to place files named __init__.py
in each directory to make it a package hierarchy. How to import a Python module from a sibling folder?
This is happening because A
and B
are independent, unrelated, packages as far as Python is concerned.
Create a __init__.py
in the same directory as Driver.py
and everything should work as expected.
How to import python modules from sibling directory?
Since there are already many answers on SO for this*, I will focus on question (2). About what is a better code organization:
|- setup.py
|- top_pkg_name
|- __init__.py
|- pkg1
|- __init__.py
|- pkg2
|- __init__.py
The (relative) import is done as follows, from inside module_2
:from ..pkg1 import module1 as m1
Alternatively, you can use absolute imports, which refer to the top package name:from top_pkg_name.pkg1 import module1 as m1
In such an organization, when you want to run any module as a script, you have to use the -m
flag:python -m top_pkg_name.pkg1.module1
For question (3), I'm not sure but it looks like the unittest
module adds the folder to path, allowing the imports to happen directly.*Refer:
- How do I import a Python script from a sibling directory?
- Python import module from sibling folder
Xpath expression to access parent or sibling using HTML::TreeBuilder::XPath module
The error message is misleading. The problem isn't lack of support, it's that you're trying to find the parent of the boolean returned by the comparison. It doesn't have one.
You could use
//*[ td[@class="c1" and text()="Match_Text"] ]/td[@class="c2"]
//td[@class="c1" and text()="Match_Text"]/following-sibling::*
//td[@class="c1" and text()="Match_Text"]/following-sibling::td[@class="c2"]
//td[@class="c1" and text()="Match_Text"]/../td[@class="c2"]
Related Topics
Warning While Installing The Rails Plugin
Ruby on Rails: Pluralize for Other Languages
Monitor Multiple Rails Applications
What's an Example of Ruby Code That's "Too Clever"
Thor Executable - Ignore Task Name
How to Create Line Breaks in Ruby
Ruby How to Generate a Tree Structure Form Array
Ruby: Is It Acceptable to Put More Than One Class in a File
Alias_Method on Activerecord::Base Results in Nameerror
How to Flush HTML to The Wire in Sinatra
Rails Asset Pipeline and Digest Values
Static Page Routing in Sinatra (Ruby)
Starting with Redmine Locally - How Easy Is Migration to Server Later
Can't Get Paypal Encrypted Website Payments to Work in Rails
Error: Failed to Build Gem Native Extension on Windows
How Does The "#Map(&Proc)" Idiom Work When Introspecting Module Classes