On Sun, Sep 26, 2021 at 1:10 PM Nils Bruin <
nbr...@sfu.ca> wrote:
>
> On Sunday, 26 September 2021 at 10:44:14 UTC-7 Matthias Koeppe wrote:
>>
>> 1. Replace use of "from sage.PAC.KAGE.all import ..." by more specific imports
>
>
> I'm not sure whether I'm a fan of the "all" packages (for one thing, they make proper use of "lazy_import" a lot harder, but importing lazy_import from all will cause exactly the same problem), but does it need to stand in the way of modularization? Doesn't it just mean that the "all" package needs to do a little magic to discover what its namespace should contain? Here I mean with "magic" something that perhaps needs to discover during runtime what is available within the relevant "namespace" package.
>
> One big advantage of "all" packages is that you can hide the internal module structure of a package with it a little bit, so that the structure becomes an implementation detail, not a part of the API specification. I think that has served us well in the past on some occasions. I'm not sure we want to surrender that option if we don't have to.
>
For what it's worth, we use these "all.py" files to explicitly list
everything to be exported from a directory tree mainly because I
didn't know about __init__.py, or at least how to use it properly.
With use of __init__.py the above would be "from sage.PAC.KAGE import
...". I agree with Nils in that it's not always the case that
minimizing the "scope" of an import is optimal.
>> 2. Do not import CLASS just to run an isinstance(..., CLASS); likewise, remove uses of is_CLASS functions
>>
>> Instead, create abstract base classes that can be imported without pulling in the actual implementation classes (
https://trac.sagemath.org/ticket/32414). I have done this in
https://trac.sagemath.org/ticket/32566 for real/complex floating point fields.
>
>
> Have you considered performance implications of that? It would look to me that abstract base classes require more work to determine membership than a plain MRO lookup. I think this "rule" probably needs a little more cautious formulation. I suspect there may be good reasons to do specific isinstance(...,CLASS) tests. Perhaps this is captured in your "...just to run...". I'm not sure about performance issues compared to "is_CLASS" functions, but clearly banning them should be accompanied by an assessment of why their replacement by "isinstance(...)" is not a (performance) regression.
>
>> 3. Break up Cython modules that depend on several C/C++ libraries simultaneously
>>
>> An example is sage.matrix.misc, which depends on both flint and mpfr. This is
https://trac.sagemath.org/ticket/32433 (which needs help).
The flint C library depends on mpfr, so I don't understand this. How
can you have a Cython module that depends on flint but does not depend
on mpfr, given that flint depends on mpfr? Maybe I don't understand
what "depends on" means.
> The particular file you point to looks like it deserves to be restructured, but the way your objective is structured seems definitely flawed. I just wrote a cython module that essentially depends on both the mpfr and the pari libraries (on C-level!). I don't see how that would be broken up and why it would even be bad to link a cython module against several libraries at once.
From a space point of view there isn't any drawback, since your
dynamic module (that Cython builds) just has a pointer to the mpfri
and pari shared object libraries.
> ... I think these are the kind of things that will limit the modularization of sagelib: it's just too integrated.
It might be useful to draw some dependency diagrams for all modules in
the Sage library. I remember seeing
these years ago and they were pretty huge and complicated but also
interesting. There's probably some modules that
depend on many things, but don't themselves get depended on very much
-- e.g., maybe something for visualization?
Does anybody around here do combinatorics? :-)
A chunk of fairly specialized code (e.g., the Pollack-Stevens
overconvergent modular symbols code)
could be moved from "in the sage.all" to "in a separate Python module
that depends on sage.all and is included with
Sage and built as part of Sage, but isn't in the exact same directory
tree as sage/all.py".
A non-Python example of a modular codebase is JupyterLab's own code. Look at
https://github.com/jupyterlab/jupyterlab/tree/master/packages
It's a bunch of packages that all work together to make "JupyterLab".
But by having them as separate packages (but NOT Github repos!),
there are many advantages for development. These really are real
packages, not just subdirectories of code. As an example, here's the
declaration
for the cells package:
https://github.com/jupyterlab/jupyterlab/blob/master/packages/cells/package.json
The npm page for that package is here
https://www.npmjs.com/package/@jupyterlab/cells
where one can download it, see release history, etc.
The modularization of the Sage library could have lofty longterm
goals, but start with one single package that is included
in Sage, but is also a separate Python package and is even published
to pypi and other places. It might be something at
either end of our dependency tree -- something on the top could be
used outside of Sage entirely, and something on the
bottom would only work if you're pip installing it into Sage. An
example is the preparser:
https://github.com/sagemath/sage/blob/8bae3ff7ad670e12cead6860cbd216f819e8d6d2/src/sage/repl/preparse.py
It doesn't really depend on anything. There's also a bunch of game
related code in
https://github.com/sagemath/sage/tree/develop/src/sage/games
that depends on nothing.
Some people will read this and ask "what is the advantage over what we
already have"? One advantage is that we can share our work with
more other people more easily. Somebody can find the sage preparser
or those games modules on pypi and install them
and use them. They could do the same thing with the code in the
Sage library, but it's much harder because all the random
code I mentioned above *does* have some subtle little weird dependency
on the Sage library. By factoring the code out as
separate modules, you are forced to revisit and hopefully remove these
dependencies, which provides value to the world.
There's of course been work like this already with cypari, but that's
kind of different because isn't it basically a different
project that Sage depends on. Maybe there's a massive amount of work
like this already by Matthias and others. I'm very ignorant.
William