Are indirect imports problematic?

50 views
Skip to first unread message

Joachim Durchholz

unread,
Jan 10, 2015, 5:53:00 PM1/10/15
to sy...@googlegroups.com
E.g. some modules do

from sympy import log

others do

from sympy.functions.elementary.exponential import exp


Pros of doing just direct imports
---------------------------------

01) Code review can instantly see where some symbol originates from.

02) This should eliminate some circular imports.


Cons
----

11) The import block gets longer.


Neutral aspects
---------------

21) If indirect imports are to be banned from SymPy's codebase as a
matter of code style: This can be checked using an import diagnostics
tool that's mostly done already (I'm working on it, a very old and
outdated prototype can be found in bin/diagnose_imports).

22) Contributors might not want to have to hunt down the origin of every
symbol that they want to import.
The good news is that if they import from some other module than the one
that defines the name, they'll get a message that tells them where to
import from directly.
E.g. this:
--
Error in $SYMPY/sympy/series/tests/test_limits.py line 3: Name 'log'
should be imported from module 'sympy.functions.elementary.exponential'
but is imported from module 'sympy'.
--

23) No doctest checking.
I think this could be made to work, but IMHO doctests are examples how
SymPy users should use it, and they should import from sympy instead of
from the module where the implementation of a name happens to live, so
import diagnostics on doctest code would be a bad idea anyway.


Final question
--------------

Do we want to forbid indirect imports inside the sympy/ directory, as a
matter of code style?


Why I ask this now
------------------

I'm currently testing my import diagnostics tool, and there are so many
indirect imports that they tend to drown out the interesting messages.
If indirect imports are going to go away anyway, I can cut down on them
and commit that even before I do the PR for the tool.

Aaron Meurer

unread,
Jan 11, 2015, 1:13:51 PM1/11/15
to sy...@googlegroups.com
On Sat, Jan 10, 2015 at 4:52 PM, Joachim Durchholz <j...@durchholz.org> wrote:
E.g. some modules do

from sympy import log

others do

from sympy.functions.elementary.exponential import exp


Pros of doing just direct imports
---------------------------------

01) Code review can instantly see where some symbol originates from.

02) This should eliminate some circular imports.


Cons
----

11) The import block gets longer.

The other con is that if the function is moved (say, split out into a new file), you have to change every other file that imports it.

Aaron Meurer
 


Neutral aspects
---------------

21) If indirect imports are to be banned from SymPy's codebase as a matter of code style: This can be checked using an import diagnostics tool that's mostly done already (I'm working on it, a very old and outdated prototype can be found in bin/diagnose_imports).

22) Contributors might not want to have to hunt down the origin of every symbol that they want to import.
The good news is that if they import from some other module than the one that defines the name, they'll get a message that tells them where to import from directly.
E.g. this:
--
Error in $SYMPY/sympy/series/tests/test_limits.py line 3: Name 'log' should be imported from module 'sympy.functions.elementary.exponential' but is imported from module 'sympy'.
--

23) No doctest checking.
I think this could be made to work, but IMHO doctests are examples how SymPy users should use it, and they should import from sympy instead of from the module where the implementation of a name happens to live, so import diagnostics on doctest code would be a bad idea anyway.


Final question
--------------

Do we want to forbid indirect imports inside the sympy/ directory, as a matter of code style?


Why I ask this now
------------------

I'm currently testing my import diagnostics tool, and there are so many indirect imports that they tend to drown out the interesting messages.
If indirect imports are going to go away anyway, I can cut down on them and commit that even before I do the PR for the tool.


--
You received this message because you are subscribed to the Google Groups "sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sympy+unsubscribe@googlegroups.com.
To post to this group, send email to sy...@googlegroups.com.
Visit this group at http://groups.google.com/group/sympy.
To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/54B1AD47.2030100%40durchholz.org.
For more options, visit https://groups.google.com/d/optout.

Joachim Durchholz

unread,
Jan 11, 2015, 2:47:04 PM1/11/15
to sy...@googlegroups.com
Am 11.01.2015 um 19:12 schrieb Aaron Meurer:
> The other con is that if the function is moved (say, split out into a new
> file), you have to change every other file that imports it.

I agree it's a con (and one I overlooked because I incorrectly thought
it's already covered under (22), quoted below for reference).

I do not think it's a large one. If a name's definition is moved, it's
easy to do a global search for all occurrences of the original package,
with a regular expression of
from old\.package\.name .* moved_name
(I'm usually lazy and leave the backslashes out, the false positives
that this causes don't happen in practice :-) )

The overhead is going to be partly made good by less merge conflicts in
the import statements, because imports tend to get split up (that's a
pro I forgot :-) )
Also, in those import statements that list just a few names (and there
are more if the imports get split up), you usually don't have to split
up the line further, you just fix the name of the module you import
from. That's another small reduction in overhead.

The overhead isn't going to go away of course, and in large-scale
refactoring, it can still become annoying.

Rathmann

unread,
Jan 12, 2015, 2:22:56 PM1/12/15
to sy...@googlegroups.com
To me, the relevant concept seems to be software coupling, as railed against by structured programming gurus in the 1970s and 80s.

Having imports which know exactly where a symbol is defined, increase the knowledge that one part of our code has of other parts.

Coupling is often unavoidable, but always comes with a cost.

In this case, the added coupling is pretty minor, but I would still tend to vote against a global change.

I don't use an IDE, but isn't finding definitions of symbols one of the basic features?  (Or just use an emacs tags file, if you are feeling retro.)

Joachim Durchholz

unread,
Jan 12, 2015, 5:04:00 PM1/12/15
to sy...@googlegroups.com
Am 12.01.2015 um 20:22 schrieb Rathmann:
> To me, the relevant concept seems to be software coupling, as railed
> against by structured programming gurus in the 1970s and 80s.

Coupling is logical interdependency.
An import already establishes that dependency.

> Having imports which know exactly where a symbol is defined, increase the
> knowledge that one part of our code has of other parts.

Okay... yes, there is some additional coupling, in the sense that the
caller is coupled to the callee in that it needs to know that additional
detail (implementation location).

However, internally, the SymPy code is tightly coupled anyway. E.g.
everything is connected via the assumptions system, via the Symbol
class, etc. - you can't even start to decouple anything, beyond maybe
some very basic libraries and diagnostics.

> Coupling is often unavoidable, but always comes with a cost.

I'm not seeing any noticeable cost from coupling.

Which may be because I'm overlooking something, so if coupling means
some tangible disadvantages, then by all means please describe it!

> In this case, the added coupling is pretty minor, but I would still tend to
> vote against a global change.

Well, that seems like you do not think the advantages are worth anything.
What reasons make you think so?

> I don't use an IDE, but isn't finding definitions of symbols one of the
> basic features? (Or just use an emacs tags file, if you are feeling retro.)

It is, but they depend on having enough clues about what's going on.

SymPy is being rather heroic about hiding such clues: Some classes get
their members at runtime (most notably S and C), we construct things
that are both classes and functions, and we hide some of this stuff away
in decorators just for that extra level of obfuscation.
I don't know how other IDEs fare, but PyDev (Eclipse's Python IDE) fails
horribly and misreports some 50,000 errors and warnings.

(Of course, the things SymPy does to confuse the heck out of static code
analysis does have its well-considered advantages. Most of the time,
anyway.)
Reply all
Reply to author
Forward
0 new messages